LyoKICogUGVyZm9ybWFuY2UgZXZlbnRzIGNhbGxjaGFpbiBjb2RlLCBleHRyYWN0ZWQgZnJvbSBjb3JlLmM6CiAqCiAqICBDb3B5cmlnaHQgKEMpIDIwMDggVGhvbWFzIEdsZWl4bmVyIDx0Z2x4QGxpbnV0cm9uaXguZGU+CiAqICBDb3B5cmlnaHQgKEMpIDIwMDgtMjAxMSBSZWQgSGF0LCBJbmMuLCBJbmdvIE1vbG5hcgogKiAgQ29weXJpZ2h0IChDKSAyMDA4LTIwMTEgUmVkIEhhdCwgSW5jLiwgUGV0ZXIgWmlqbHN0cmEKICogIENvcHlyaWdodCAgqSAgMjAwOSBQYXVsIE1hY2tlcnJhcywgSUJNIENvcnAuIDxwYXVsdXNAYXUxLmlibS5jb20+CiAqCiAqIEZvciBsaWNlbnNpbmcgZGV0YWlscyBzZWUga2VybmVsLWJhc2UvQ09QWUlORwogKi8KCiNpbmNsdWRlIDxsaW51eC9wZXJmX2V2ZW50Lmg+CiNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CiNpbmNsdWRlIDxsaW51eC9zY2hlZC90YXNrX3N0YWNrLmg+CgojaW5jbHVkZSAiaW50ZXJuYWwuaCIKCnN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzIHsKCXN0cnVjdCByY3VfaGVhZAkJCXJjdV9oZWFkOwoJc3RydWN0IHBlcmZfY2FsbGNoYWluX2VudHJ5CSpjcHVfZW50cmllc1swXTsKfTsKCmludCBzeXNjdGxfcGVyZl9ldmVudF9tYXhfc3RhY2sgX19yZWFkX21vc3RseSA9IFBFUkZfTUFYX1NUQUNLX0RFUFRIOwppbnQgc3lzY3RsX3BlcmZfZXZlbnRfbWF4X2NvbnRleHRzX3Blcl9zdGFjayBfX3JlYWRfbW9zdGx5ID0gUEVSRl9NQVhfQ09OVEVYVFNfUEVSX1NUQUNLOwoKc3RhdGljIGlubGluZSBzaXplX3QgcGVyZl9jYWxsY2hhaW5fZW50cnlfX3NpemVvZih2b2lkKQp7CglyZXR1cm4gKHNpemVvZihzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnkpICsKCQlzaXplb2YoX191NjQpICogKHN5c2N0bF9wZXJmX2V2ZW50X21heF9zdGFjayArCgkJCQkgc3lzY3RsX3BlcmZfZXZlbnRfbWF4X2NvbnRleHRzX3Blcl9zdGFjaykpOwp9CgpzdGF0aWMgREVGSU5FX1BFUl9DUFUoaW50LCBjYWxsY2hhaW5fcmVjdXJzaW9uW1BFUkZfTlJfQ09OVEVYVFNdKTsKc3RhdGljIGF0b21pY190IG5yX2NhbGxjaGFpbl9ldmVudHM7CnN0YXRpYyBERUZJTkVfTVVURVgoY2FsbGNoYWluX211dGV4KTsKc3RhdGljIHN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzICpjYWxsY2hhaW5fY3B1c19lbnRyaWVzOwoKCl9fd2VhayB2b2lkIHBlcmZfY2FsbGNoYWluX2tlcm5lbChzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnlfY3R4ICplbnRyeSwKCQkJCSAgc3RydWN0IHB0X3JlZ3MgKnJlZ3MpCnsKfQoKX193ZWFrIHZvaWQgcGVyZl9jYWxsY2hhaW5fdXNlcihzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnlfY3R4ICplbnRyeSwKCQkJCXN0cnVjdCBwdF9yZWdzICpyZWdzKQp7Cn0KCnN0YXRpYyB2b2lkIHJlbGVhc2VfY2FsbGNoYWluX2J1ZmZlcnNfcmN1KHN0cnVjdCByY3VfaGVhZCAqaGVhZCkKewoJc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMgKmVudHJpZXM7CglpbnQgY3B1OwoKCWVudHJpZXMgPSBjb250YWluZXJfb2YoaGVhZCwgc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMsIHJjdV9oZWFkKTsKCglmb3JfZWFjaF9wb3NzaWJsZV9jcHUoY3B1KQoJCWtmcmVlKGVudHJpZXMtPmNwdV9lbnRyaWVzW2NwdV0pOwoKCWtmcmVlKGVudHJpZXMpOwp9CgpzdGF0aWMgdm9pZCByZWxlYXNlX2NhbGxjaGFpbl9idWZmZXJzKHZvaWQpCnsKCXN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzICplbnRyaWVzOwoKCWVudHJpZXMgPSBjYWxsY2hhaW5fY3B1c19lbnRyaWVzOwoJUkNVX0lOSVRfUE9JTlRFUihjYWxsY2hhaW5fY3B1c19lbnRyaWVzLCBOVUxMKTsKCWNhbGxfcmN1KCZlbnRyaWVzLT5yY3VfaGVhZCwgcmVsZWFzZV9jYWxsY2hhaW5fYnVmZmVyc19yY3UpOwp9CgpzdGF0aWMgaW50IGFsbG9jX2NhbGxjaGFpbl9idWZmZXJzKHZvaWQpCnsKCWludCBjcHU7CglpbnQgc2l6ZTsKCXN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzICplbnRyaWVzOwoKCS8qCgkgKiBXZSBjYW4ndCB1c2UgdGhlIHBlcmNwdSBhbGxvY2F0aW9uIEFQSSBmb3IgZGF0YSB0aGF0IGNhbiBiZQoJICogYWNjZXNzZWQgZnJvbSBOTUkuIFVzZSBhIHRlbXBvcmFyeSBtYW51YWwgcGVyIGNwdSBhbGxvY2F0aW9uCgkgKiB1bnRpbCB0aGF0IGdldHMgc29ydGVkIG91dC4KCSAqLwoJc2l6ZSA9IG9mZnNldG9mKHN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzLCBjcHVfZW50cmllc1tucl9jcHVfaWRzXSk7CgoJZW50cmllcyA9IGt6YWxsb2Moc2l6ZSwgR0ZQX0tFUk5FTCk7CglpZiAoIWVudHJpZXMpCgkJcmV0dXJuIC1FTk9NRU07CgoJc2l6ZSA9IHBlcmZfY2FsbGNoYWluX2VudHJ5X19zaXplb2YoKSAqIFBFUkZfTlJfQ09OVEVYVFM7CgoJZm9yX2VhY2hfcG9zc2libGVfY3B1KGNwdSkgewoJCWVudHJpZXMtPmNwdV9lbnRyaWVzW2NwdV0gPSBrbWFsbG9jX25vZGUoc2l6ZSwgR0ZQX0tFUk5FTCwKCQkJCQkJCSBjcHVfdG9fbm9kZShjcHUpKTsKCQlpZiAoIWVudHJpZXMtPmNwdV9lbnRyaWVzW2NwdV0pCgkJCWdvdG8gZmFpbDsKCX0KCglyY3VfYXNzaWduX3BvaW50ZXIoY2FsbGNoYWluX2NwdXNfZW50cmllcywgZW50cmllcyk7CgoJcmV0dXJuIDA7CgpmYWlsOgoJZm9yX2VhY2hfcG9zc2libGVfY3B1KGNwdSkKCQlrZnJlZShlbnRyaWVzLT5jcHVfZW50cmllc1tjcHVdKTsKCWtmcmVlKGVudHJpZXMpOwoKCXJldHVybiAtRU5PTUVNOwp9CgppbnQgZ2V0X2NhbGxjaGFpbl9idWZmZXJzKGludCBldmVudF9tYXhfc3RhY2spCnsKCWludCBlcnIgPSAwOwoJaW50IGNvdW50OwoKCW11dGV4X2xvY2soJmNhbGxjaGFpbl9tdXRleCk7CgoJY291bnQgPSBhdG9taWNfaW5jX3JldHVybigmbnJfY2FsbGNoYWluX2V2ZW50cyk7CglpZiAoV0FSTl9PTl9PTkNFKGNvdW50IDwgMSkpIHsKCQllcnIgPSAtRUlOVkFMOwoJCWdvdG8gZXhpdDsKCX0KCgkvKgoJICogSWYgcmVxdWVzdGluZyBwZXIgZXZlbnQgbW9yZSB0aGFuIHRoZSBnbG9iYWwgY2FwLAoJICogcmV0dXJuIGEgZGlmZmVyZW50IGVycm9yIHRvIGhlbHAgdXNlcnNwYWNlIGZpZ3VyZQoJICogdGhpcyBvdXQuCgkgKgoJICogQW5kIGFsc28gZG8gaXQgaGVyZSBzbyB0aGF0IHdlIGhhdmUgJmNhbGxjaGFpbl9tdXRleCBoZWxkLgoJICovCglpZiAoZXZlbnRfbWF4X3N0YWNrID4gc3lzY3RsX3BlcmZfZXZlbnRfbWF4X3N0YWNrKSB7CgkJZXJyID0gLUVPVkVSRkxPVzsKCQlnb3RvIGV4aXQ7Cgl9CgoJaWYgKGNvdW50ID09IDEpCgkJZXJyID0gYWxsb2NfY2FsbGNoYWluX2J1ZmZlcnMoKTsKZXhpdDoKCWlmIChlcnIpCgkJYXRvbWljX2RlYygmbnJfY2FsbGNoYWluX2V2ZW50cyk7CgoJbXV0ZXhfdW5sb2NrKCZjYWxsY2hhaW5fbXV0ZXgpOwoKCXJldHVybiBlcnI7Cn0KCnZvaWQgcHV0X2NhbGxjaGFpbl9idWZmZXJzKHZvaWQpCnsKCWlmIChhdG9taWNfZGVjX2FuZF9tdXRleF9sb2NrKCZucl9jYWxsY2hhaW5fZXZlbnRzLCAmY2FsbGNoYWluX211dGV4KSkgewoJCXJlbGVhc2VfY2FsbGNoYWluX2J1ZmZlcnMoKTsKCQltdXRleF91bmxvY2soJmNhbGxjaGFpbl9tdXRleCk7Cgl9Cn0KCnN0YXRpYyBzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnkgKmdldF9jYWxsY2hhaW5fZW50cnkoaW50ICpyY3R4KQp7CglpbnQgY3B1OwoJc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMgKmVudHJpZXM7CgoJKnJjdHggPSBnZXRfcmVjdXJzaW9uX2NvbnRleHQodGhpc19jcHVfcHRyKGNhbGxjaGFpbl9yZWN1cnNpb24pKTsKCWlmICgqcmN0eCA9PSAtMSkKCQlyZXR1cm4gTlVMTDsKCgllbnRyaWVzID0gcmN1X2RlcmVmZXJlbmNlKGNhbGxjaGFpbl9jcHVzX2VudHJpZXMpOwoJaWYgKCFlbnRyaWVzKQoJCXJldHVybiBOVUxMOwoKCWNwdSA9IHNtcF9wcm9jZXNzb3JfaWQoKTsKCglyZXR1cm4gKCgodm9pZCAqKWVudHJpZXMtPmNwdV9lbnRyaWVzW2NwdV0pICsKCQkoKnJjdHggKiBwZXJmX2NhbGxjaGFpbl9lbnRyeV9fc2l6ZW9mKCkpKTsKfQoKc3RhdGljIHZvaWQKcHV0X2NhbGxjaGFpbl9lbnRyeShpbnQgcmN0eCkKewoJcHV0X3JlY3Vyc2lvbl9jb250ZXh0KHRoaXNfY3B1X3B0cihjYWxsY2hhaW5fcmVjdXJzaW9uKSwgcmN0eCk7Cn0KCnN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSAqCnBlcmZfY2FsbGNoYWluKHN0cnVjdCBwZXJmX2V2ZW50ICpldmVudCwgc3RydWN0IHB0X3JlZ3MgKnJlZ3MpCnsKCWJvb2wga2VybmVsID0gIWV2ZW50LT5hdHRyLmV4Y2x1ZGVfY2FsbGNoYWluX2tlcm5lbDsKCWJvb2wgdXNlciAgID0gIWV2ZW50LT5hdHRyLmV4Y2x1ZGVfY2FsbGNoYWluX3VzZXI7CgkvKiBEaXNhbGxvdyBjcm9zcy10YXNrIHVzZXIgY2FsbGNoYWlucy4gKi8KCWJvb2wgY3Jvc3N0YXNrID0gZXZlbnQtPmN0eC0+dGFzayAmJiBldmVudC0+Y3R4LT50YXNrICE9IGN1cnJlbnQ7Cgljb25zdCB1MzIgbWF4X3N0YWNrID0gZXZlbnQtPmF0dHIuc2FtcGxlX21heF9zdGFjazsKCglpZiAoIWtlcm5lbCAmJiAhdXNlcikKCQlyZXR1cm4gTlVMTDsKCglyZXR1cm4gZ2V0X3BlcmZfY2FsbGNoYWluKHJlZ3MsIDAsIGtlcm5lbCwgdXNlciwgbWF4X3N0YWNrLCBjcm9zc3Rhc2ssIHRydWUpOwp9CgpzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnkgKgpnZXRfcGVyZl9jYWxsY2hhaW4oc3RydWN0IHB0X3JlZ3MgKnJlZ3MsIHUzMiBpbml0X25yLCBib29sIGtlcm5lbCwgYm9vbCB1c2VyLAoJCSAgIHUzMiBtYXhfc3RhY2ssIGJvb2wgY3Jvc3N0YXNrLCBib29sIGFkZF9tYXJrKQp7CglzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnkgKmVudHJ5OwoJc3RydWN0IHBlcmZfY2FsbGNoYWluX2VudHJ5X2N0eCBjdHg7CglpbnQgcmN0eDsKCgllbnRyeSA9IGdldF9jYWxsY2hhaW5fZW50cnkoJnJjdHgpOwoJaWYgKHJjdHggPT0gLTEpCgkJcmV0dXJuIE5VTEw7CgoJaWYgKCFlbnRyeSkKCQlnb3RvIGV4aXRfcHV0OwoKCWN0eC5lbnRyeSAgICAgPSBlbnRyeTsKCWN0eC5tYXhfc3RhY2sgPSBtYXhfc3RhY2s7CgljdHgubnIJICAgICAgPSBlbnRyeS0+bnIgPSBpbml0X25yOwoJY3R4LmNvbnRleHRzICAgICAgID0gMDsKCWN0eC5jb250ZXh0c19tYXhlZCA9IGZhbHNlOwoKCWlmIChrZXJuZWwgJiYgIXVzZXJfbW9kZShyZWdzKSkgewoJCWlmIChhZGRfbWFyaykKCQkJcGVyZl9jYWxsY2hhaW5fc3RvcmVfY29udGV4dCgmY3R4LCBQRVJGX0NPTlRFWFRfS0VSTkVMKTsKCQlwZXJmX2NhbGxjaGFpbl9rZXJuZWwoJmN0eCwgcmVncyk7Cgl9CgoJaWYgKHVzZXIpIHsKCQlpZiAoIXVzZXJfbW9kZShyZWdzKSkgewoJCQlpZiAgKGN1cnJlbnQtPm1tKQoJCQkJcmVncyA9IHRhc2tfcHRfcmVncyhjdXJyZW50KTsKCQkJZWxzZQoJCQkJcmVncyA9IE5VTEw7CgkJfQoKCQlpZiAocmVncykgewoJCQltbV9zZWdtZW50X3QgZnM7CgoJCQlpZiAoY3Jvc3N0YXNrKQoJCQkJZ290byBleGl0X3B1dDsKCgkJCWlmIChhZGRfbWFyaykKCQkJCXBlcmZfY2FsbGNoYWluX3N0b3JlX2NvbnRleHQoJmN0eCwgUEVSRl9DT05URVhUX1VTRVIpOwoKCQkJZnMgPSBnZXRfZnMoKTsKCQkJc2V0X2ZzKFVTRVJfRFMpOwoJCQlwZXJmX2NhbGxjaGFpbl91c2VyKCZjdHgsIHJlZ3MpOwoJCQlzZXRfZnMoZnMpOwoJCX0KCX0KCmV4aXRfcHV0OgoJcHV0X2NhbGxjaGFpbl9lbnRyeShyY3R4KTsKCglyZXR1cm4gZW50cnk7Cn0KCi8qCiAqIFVzZWQgZm9yIHN5c2N0bF9wZXJmX2V2ZW50X21heF9zdGFjayBhbmQKICogc3lzY3RsX3BlcmZfZXZlbnRfbWF4X2NvbnRleHRzX3Blcl9zdGFjay4KICovCmludCBwZXJmX2V2ZW50X21heF9zdGFja19oYW5kbGVyKHN0cnVjdCBjdGxfdGFibGUgKnRhYmxlLCBpbnQgd3JpdGUsCgkJCQkgdm9pZCBfX3VzZXIgKmJ1ZmZlciwgc2l6ZV90ICpsZW5wLCBsb2ZmX3QgKnBwb3MpCnsKCWludCAqdmFsdWUgPSB0YWJsZS0+ZGF0YTsKCWludCBuZXdfdmFsdWUgPSAqdmFsdWUsIHJldDsKCXN0cnVjdCBjdGxfdGFibGUgbmV3X3RhYmxlID0gKnRhYmxlOwoKCW5ld190YWJsZS5kYXRhID0gJm5ld192YWx1ZTsKCXJldCA9IHByb2NfZG9pbnR2ZWNfbWlubWF4KCZuZXdfdGFibGUsIHdyaXRlLCBidWZmZXIsIGxlbnAsIHBwb3MpOwoJaWYgKHJldCB8fCAhd3JpdGUpCgkJcmV0dXJuIHJldDsKCgltdXRleF9sb2NrKCZjYWxsY2hhaW5fbXV0ZXgpOwoJaWYgKGF0b21pY19yZWFkKCZucl9jYWxsY2hhaW5fZXZlbnRzKSkKCQlyZXQgPSAtRUJVU1k7CgllbHNlCgkJKnZhbHVlID0gbmV3X3ZhbHVlOwoKCW11dGV4X3VubG9jaygmY2FsbGNoYWluX211dGV4KTsKCglyZXR1cm4gcmV0Owp9Cg==