LyoKICoKICogQ29weXJpZ2h0IChDKSAyMDAwICBSb2JlcnQgT2xzc29uLgogKiBTd2VkaXNoIFVuaXZlcnNpdHkgb2YgQWdyaWN1bHR1cmFsIFNjaWVuY2VzCiAqCiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIEdOVSBaZWJyYS4KICoKICogR05VIFplYnJhIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXQKICogdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlCiAqIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMiwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkKICogbGF0ZXIgdmVyc2lvbi4KICoKICogR05VIFplYnJhIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dAogKiBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKICogYWxvbmcgd2l0aCBHTlUgWmVicmE7IHNlZSB0aGUgZmlsZSBDT1BZSU5HLiAgSWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZQogKiBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UgLSBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEKICogMDIxMTEtMTMwNywgVVNBLiAgCiAqLwoKLyogCiAqIFRoaXMgd29yayBpbmNsdWRlcyB3b3JrIHdpdGggdGhlIGZvbGxvd2luZyBjb3B5d3JpdGU6CiAqCiAqIENvcHlyaWdodCAoQykgMTk5NywgMjAwMCBLdW5paGlybyBJc2hpZ3VybwogKgogKi8KCi8qIAogKiBUaGFua3MgdG8gSmVucyBM5eVzIGF0IFN3ZWRpc2ggVW5pdmVyc2l0eSBvZiBBZ3JpY3VsdHVyYWwgU2NpZW5jZXMKICogZm9yIHJldmlld2luZyBhbmQgdGVzdHMuCiAqLwoKCiNpbmNsdWRlIDx6ZWJyYS5oPgoKI2lmZGVmIEhBVkVfSVJEUAoKI2luY2x1ZGUgImlmLmgiCiNpbmNsdWRlICJ2dHkuaCIKI2luY2x1ZGUgInNvY2t1bmlvbi5oIgojaW5jbHVkZSAic29ja29wdC5oIgojaW5jbHVkZSAicHJlZml4LmgiCiNpbmNsdWRlICJjb21tYW5kLmgiCiNpbmNsdWRlICJtZW1vcnkuaCIKI2luY2x1ZGUgInN0cmVhbS5oIgojaW5jbHVkZSAiaW9jdGwuaCIKI2luY2x1ZGUgImNvbm5lY3RlZC5oIgojaW5jbHVkZSAibG9nLmgiCiNpbmNsdWRlICJ6Y2xpZW50LmgiCiNpbmNsdWRlICJ0aHJlYWQuaCIKI2luY2x1ZGUgInByaXZzLmgiCiNpbmNsdWRlICJ6ZWJyYS9pbnRlcmZhY2UuaCIKI2luY2x1ZGUgInplYnJhL3J0YWR2LmgiCiNpbmNsdWRlICJ6ZWJyYS9yaWIuaCIKI2luY2x1ZGUgInplYnJhL3pzZXJ2LmgiCiNpbmNsdWRlICJ6ZWJyYS9yZWRpc3RyaWJ1dGUuaCIKI2luY2x1ZGUgInplYnJhL2lyZHAuaCIKI2luY2x1ZGUgPG5ldGluZXQvaXBfaWNtcC5oPgoKI2luY2x1ZGUgImNoZWNrc3VtLmgiCiNpbmNsdWRlICJpZi5oIgojaW5jbHVkZSAic29ja3VuaW9uLmgiCiNpbmNsdWRlICJsb2cuaCIKCi8qIEdMT0JBTCBWQVJTICovCgpleHRlcm4gc3RydWN0IHplYnJhX3ByaXZzX3QgenNlcnZfcHJpdnM7CgovKiBNYXN0ZXIgb2YgdGhyZWFkcy4gKi8KZXh0ZXJuIHN0cnVjdCB6ZWJyYV90IHplYnJhZDsKc3RydWN0IHRocmVhZCAqdF9pcmRwX3JhdzsKCi8qIFRpbWVyIGludGVydmFsIG9mIGlyZHAuICovCmludCBpcmRwX3RpbWVyX2ludGVydmFsID0gSVJEUF9ERUZBVUxUX0lOVEVSVkFMOwoKaW50CmlyZHBfc29ja19pbml0ICh2b2lkKQp7CiAgaW50IHJldCwgaTsKICBpbnQgc2F2ZV9lcnJubzsKICBpbnQgc29jazsKCiAgaWYgKCB6c2Vydl9wcml2cy5jaGFuZ2UgKFpQUklWU19SQUlTRSkgKQogICAgICAgemxvZ19lcnIgKCJpcmRwX3NvY2tfaW5pdDogY291bGQgbm90IHJhaXNlIHByaXZzLCAlcyIsCiAgICAgICAgICAgICAgICAgIHNhZmVfc3RyZXJyb3IgKGVycm5vKSApOwoKICBzb2NrID0gc29ja2V0IChBRl9JTkVULCBTT0NLX1JBVywgSVBQUk9UT19JQ01QKTsKICBzYXZlX2Vycm5vID0gZXJybm87CgogIGlmICggenNlcnZfcHJpdnMuY2hhbmdlIChaUFJJVlNfTE9XRVIpICkKICAgICAgIHpsb2dfZXJyICgiaXJkcF9zb2NrX2luaXQ6IGNvdWxkIG5vdCBsb3dlciBwcml2cywgJXMiLAogICAgICAgICAgICAgc2FmZV9zdHJlcnJvciAoZXJybm8pICk7CgogIGlmIChzb2NrIDwgMCkgewogICAgemxvZ193YXJuICgiSVJEUDogY2FuJ3QgY3JlYXRlIGlyZHAgc29ja2V0ICVzIiwgc2FmZV9zdHJlcnJvcihzYXZlX2Vycm5vKSk7CiAgICByZXR1cm4gc29jazsKICB9OwogIAogIGkgPSAxOwogIHJldCA9IHNldHNvY2tvcHQgKHNvY2ssIElQUFJPVE9fSVAsIElQX1RUTCwgCiAgICAgICAgICAgICAgICAgICAgICAgICh2b2lkICopICZpLCBzaXplb2YgKGkpKTsKICBpZiAocmV0IDwgMCkgewogICAgemxvZ193YXJuICgiSVJEUDogY2FuJ3QgZG8gaXJkcCBzb2Nrb3B0ICVzIiwgc2FmZV9zdHJlcnJvcihlcnJubykpOwogICAgY2xvc2Uoc29jayk7CiAgICByZXR1cm4gcmV0OwogIH07CiAgCiAgcmV0ID0gc2V0c29ja29wdF9pZmluZGV4IChBRl9JTkVULCBzb2NrLCAxKTsKICBpZiAocmV0IDwgMCkgewogICAgemxvZ193YXJuICgiSVJEUDogY2FuJ3QgZG8gaXJkcCBzb2Nrb3B0ICVzIiwgc2FmZV9zdHJlcnJvcihlcnJubykpOwogICAgY2xvc2Uoc29jayk7CiAgICByZXR1cm4gcmV0OwogIH07CgogIHRfaXJkcF9yYXcgPSB0aHJlYWRfYWRkX3JlYWQgKHplYnJhZC5tYXN0ZXIsIGlyZHBfcmVhZF9yYXcsIE5VTEwsIHNvY2spOyAKCiAgcmV0dXJuIHNvY2s7Cn0KCgpzdGF0aWMgaW50CmdldF9wcmVmKHN0cnVjdCBpcmRwX2ludGVyZmFjZSAqaXJkcCwgc3RydWN0IHByZWZpeCAqcCkKewogIHN0cnVjdCBsaXN0bm9kZSAqbm9kZTsKICBzdHJ1Y3QgQWR2ICphZHY7CgogIC8qIFVzZSBkZWZhdWx0IHByZWZlcmVuY2Ugb3IgdXNlIHRoZSBvdmVycmlkZSBwcmVmICovCiAgCiAgaWYoIGlyZHAtPkFkdlByZWZMaXN0ID09IE5VTEwgKQogICAgcmV0dXJuIGlyZHAtPlByZWZlcmVuY2U7CiAgCiAgZm9yIChBTExfTElTVF9FTEVNRU5UU19STyAoaXJkcC0+QWR2UHJlZkxpc3QsIG5vZGUsIGFkdikpCiAgICBpZiggcC0+dS5wcmVmaXg0LnNfYWRkciA9PSBhZHYtPmlwLnNfYWRkciApCiAgICAgIHJldHVybiBhZHYtPnByZWY7CgogIHJldHVybiBpcmRwLT5QcmVmZXJlbmNlOwp9CgovKiBNYWtlIElDTVAgUm91dGVyIEFkdmVydGlzZW1lbnQgTWVzc2FnZS4gKi8Kc3RhdGljIGludAptYWtlX2FkdmVydGlzZW1lbnRfcGFja2V0IChzdHJ1Y3QgaW50ZXJmYWNlICppZnAsIAoJCQkgICBzdHJ1Y3QgcHJlZml4ICpwLAoJCQkgICBzdHJ1Y3Qgc3RyZWFtICpzKQp7CiAgc3RydWN0IHplYnJhX2lmICp6aT1pZnAtPmluZm87CiAgc3RydWN0IGlyZHBfaW50ZXJmYWNlICppcmRwPSZ6aS0+aXJkcDsKICBpbnQgc2l6ZTsKICBpbnQgcHJlZjsKICB1X2ludDE2X3QgY2hlY2tzdW07CgogIHByZWYgPSAgZ2V0X3ByZWYoaXJkcCwgcCk7CgogIHN0cmVhbV9wdXRjIChzLCBJQ01QX1JPVVRFUkFEVkVSVCk7IC8qIFR5cGUuICovCiAgc3RyZWFtX3B1dGMgKHMsIDApOwkJLyogQ29kZS4gKi8KICBzdHJlYW1fcHV0dyAocywgMCk7CQkvKiBDaGVja3N1bS4gKi8KICBzdHJlYW1fcHV0YyAocywgMSk7CQkvKiBOdW0gYWRkcmVzcy4gKi8KICBzdHJlYW1fcHV0YyAocywgMik7CQkvKiBBZGRyZXNzIEVudHJ5IFNpemUuICovCgogIGlmKGlyZHAtPmZsYWdzICYgSUZfU0hVVERPV04pICAKICAgIHN0cmVhbV9wdXR3IChzLCAwKTsKICBlbHNlIAogICAgc3RyZWFtX3B1dHcgKHMsIGlyZHAtPkxpZmV0aW1lKTsKCiAgc3RyZWFtX3B1dGwgKHMsIGh0b25sKHAtPnUucHJlZml4NC5zX2FkZHIpKTsgLyogUm91dGVyIGFkZHJlc3MuICovCiAgc3RyZWFtX3B1dGwgKHMsIHByZWYpOwoKICAvKiBpbl9ja3N1bSByZXR1cm4gbmV0d29yayBieXRlIG9yZGVyIHZhbHVlICovCiAgc2l6ZSA9IDE2OwogIGNoZWNrc3VtID0gaW5fY2tzdW0gKHMtPmRhdGEsIHNpemUpOwogIHN0cmVhbV9wdXR3X2F0IChzLCAyLCBodG9ucyhjaGVja3N1bSkpOwoKICByZXR1cm4gc2l6ZTsKfQoKc3RhdGljIHZvaWQKaXJkcF9zZW5kKHN0cnVjdCBpbnRlcmZhY2UgKmlmcCwgc3RydWN0IHByZWZpeCAqcCwgc3RydWN0IHN0cmVhbSAqcykKewogIHN0cnVjdCB6ZWJyYV9pZiAqemk9aWZwLT5pbmZvOwogIHN0cnVjdCBpcmRwX2ludGVyZmFjZSAqaXJkcD0memktPmlyZHA7CiAgdV9pbnQzMl90IGRzdDsKICB1X2ludDMyX3QgdHRsPTE7CgogIGlmICghIChpZnAtPmZsYWdzICYgSUZGX1VQKSkgcmV0dXJuOyAKCiAgaWYgKGlyZHAtPmZsYWdzICYgSUZfQlJPQURDQVNUKSAKICAgIGRzdCA9SU5BRERSX0JST0FEQ0FTVCA7CiAgZWxzZSAKICAgIGRzdCA9IGh0b25sKElOQUREUl9BTExIT1NUU19HUk9VUCk7CgogIGlmKGlyZHAtPmZsYWdzICYgSUZfREVCVUdfTUVTU0FHRVMpIAogICAgemxvZ19kZWJ1ZygiSVJEUDogVFggQWR2ZXJ0IG9uICVzICVzLyVkIEhvbGR0aW1lPSVkIFByZWZlcmVuY2U9JWQiLCAKCSAgICAgIGlmcC0+bmFtZSwKCSAgICAgIGluZXRfbnRvYShwLT51LnByZWZpeDQpLCAKCSAgICAgIHAtPnByZWZpeGxlbiwKCSAgICAgIGlyZHAtPmZsYWdzICYgSUZfU0hVVERPV04/IDAgOiBpcmRwLT5MaWZldGltZSwKCSAgICAgIGdldF9wcmVmKGlyZHAsIHApKTsKCiAgc2VuZF9wYWNrZXQgKGlmcCwgcywgZHN0LCBwLCB0dGwpOwp9CgpzdGF0aWMgdm9pZCBpcmRwX2FkdmVydGlzZW1lbnQgKHN0cnVjdCBpbnRlcmZhY2UgKmlmcCwgc3RydWN0IHByZWZpeCAqcCkKewogIHN0cnVjdCBzdHJlYW0gKnM7CiAgcyA9IHN0cmVhbV9uZXcgKDEyOCk7CiAgbWFrZV9hZHZlcnRpc2VtZW50X3BhY2tldCAoaWZwLCBwLCBzKTsKICBpcmRwX3NlbmQoaWZwLCBwLCBzKTsKICBzdHJlYW1fZnJlZSAocyk7Cn0KCmludCBpcmRwX3NlbmRfdGhyZWFkKHN0cnVjdCB0aHJlYWQgKnRfYWR2ZXJ0KQp7CiAgdV9pbnQzMl90IHRpbWVyLCB0bXA7CiAgc3RydWN0IGludGVyZmFjZSAqaWZwID0gVEhSRUFEX0FSRyAodF9hZHZlcnQpOwogIHN0cnVjdCB6ZWJyYV9pZiAqemk9aWZwLT5pbmZvOwogIHN0cnVjdCBpcmRwX2ludGVyZmFjZSAqaXJkcD0memktPmlyZHA7CiAgc3RydWN0IHByZWZpeCAqcDsKICBzdHJ1Y3QgbGlzdG5vZGUgKm5vZGUsICpubm9kZTsKICBzdHJ1Y3QgY29ubmVjdGVkICppZmM7CgogIGlyZHAtPmZsYWdzICY9IH5JRl9TT0xJQ0lUOwoKICBpZihpZnAtPmNvbm5lY3RlZCkgCiAgICBmb3IgKEFMTF9MSVNUX0VMRU1FTlRTIChpZnAtPmNvbm5lY3RlZCwgbm9kZSwgbm5vZGUsIGlmYykpCiAgICAgIHsKICAgICAgICBwID0gaWZjLT5hZGRyZXNzOwogICAgICAgIAogICAgICAgIGlmIChwLT5mYW1pbHkgIT0gQUZfSU5FVCkKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIAogICAgICAgIGlyZHBfYWR2ZXJ0aXNlbWVudChpZnAsIHApOwogICAgICAgIGlyZHAtPmlyZHBfc2VudCsrOwogICAgICB9CgogIHRtcCA9IGlyZHAtPk1heEFkdmVydEludGVydmFsLWlyZHAtPk1pbkFkdmVydEludGVydmFsOwogIHRpbWVyID0gIChyYW5kb20gKCkgJSB0bXAgKSArIDE7CiAgdGltZXIgPSBpcmRwLT5NaW5BZHZlcnRJbnRlcnZhbCArIHRpbWVyOwoKICBpZihpcmRwLT5pcmRwX3NlbnQgPCAgTUFYX0lOSVRJQUxfQURWRVJUSVNFTUVOVFMgJiYKICAgICB0aW1lciA+IE1BWF9JTklUSUFMX0FEVkVSVF9JTlRFUlZBTCApIAoJICB0aW1lcj0gTUFYX0lOSVRJQUxfQURWRVJUX0lOVEVSVkFMOwoKICBpZihpcmRwLT5mbGFncyAmIElGX0RFQlVHX01JU0MpCiAgICB6bG9nX2RlYnVnKCJJUkRQOiBOZXcgdGltZXIgZm9yICVzIHNldCB0byAldVxuIiwgaWZwLT5uYW1lLCB0aW1lcik7CgogIGlyZHAtPnRfYWR2ZXJ0aXNlID0gdGhyZWFkX2FkZF90aW1lcih6ZWJyYWQubWFzdGVyLCBpcmRwX3NlbmRfdGhyZWFkLCBpZnAsIHRpbWVyKTsKICByZXR1cm4gMDsKfQoKdm9pZCBpcmRwX2FkdmVydF9vZmYoc3RydWN0IGludGVyZmFjZSAqaWZwKQp7CiAgc3RydWN0IHplYnJhX2lmICp6aT1pZnAtPmluZm87CiAgc3RydWN0IGlyZHBfaW50ZXJmYWNlICppcmRwPSZ6aS0+aXJkcDsKICBzdHJ1Y3QgbGlzdG5vZGUgKm5vZGUsICpubm9kZTsKICBpbnQgaTsKICBzdHJ1Y3QgY29ubmVjdGVkICppZmM7CiAgc3RydWN0IHByZWZpeCAqcDsKCiAgaWYoaXJkcC0+dF9hZHZlcnRpc2UpICB0aHJlYWRfY2FuY2VsKGlyZHAtPnRfYWR2ZXJ0aXNlKTsKICBpcmRwLT50X2FkdmVydGlzZSA9IE5VTEw7CiAgCiAgaWYoaWZwLT5jb25uZWN0ZWQpIAogICAgZm9yIChBTExfTElTVF9FTEVNRU5UUyAoaWZwLT5jb25uZWN0ZWQsIG5vZGUsIG5ub2RlLCBpZmMpKQogICAgICB7CiAgICAgICAgcCA9IGlmYy0+YWRkcmVzczsKCiAgICAgICAgLyogT3V0cHV0IHNvbWUgcGFja2V0cyB3aXRoIExpZmV0aW1lIDAgCiAgICAgICAgICAgd2Ugc2hvdWxkIGFkZCBhIHdhaXQuLi4KICAgICAgICAqLwoKICAgICAgICBmb3IoaT0wOyBpPCBJUkRQX0xBU1RfQURWRVJUX01FU1NBR0VTOyBpKyspIAogICAgICAgICAgewogICAgICAgICAgICBpcmRwLT5pcmRwX3NlbnQrKzsKICAgICAgICAgICAgaXJkcF9hZHZlcnRpc2VtZW50KGlmcCwgcCk7CiAgICAgICAgICB9CiAgICAgIH0KfQoKCnZvaWQgcHJvY2Vzc19zb2xpY2l0IChzdHJ1Y3QgaW50ZXJmYWNlICppZnApCnsKICBzdHJ1Y3QgemVicmFfaWYgKnppPWlmcC0+aW5mbzsKICBzdHJ1Y3QgaXJkcF9pbnRlcmZhY2UgKmlyZHA9JnppLT5pcmRwOwogIHVfaW50MzJfdCB0aW1lcjsKCiAgLyogV2hlbiBTT0xJQ0lUIGlzIGFjdGl2ZSB3ZSByZWplY3QgZnVydGhlciBpbmNvbWluZyBzb2xpY2l0cyAKICAgICB0aGlzIGtlZXBzIGRvd24gdGhlIGFuc3dlcmluZyByYXRlIHNvIHdlIGRvbid0IGhhdmUgdGhpbmsKICAgICBhYm91dCBEb1MgYXR0YWNrcyBoZXJlLiAqLwoKICBpZiggaXJkcC0+ZmxhZ3MgJiBJRl9TT0xJQ0lUKSByZXR1cm47CgogIGlyZHAtPmZsYWdzIHw9IElGX1NPTElDSVQ7CiAgaWYoaXJkcC0+dF9hZHZlcnRpc2UpICB0aHJlYWRfY2FuY2VsKGlyZHAtPnRfYWR2ZXJ0aXNlKTsKICBpcmRwLT50X2FkdmVydGlzZSA9IE5VTEw7CgogIHRpbWVyID0gIChyYW5kb20gKCkgJSBNQVhfUkVTUE9OU0VfREVMQVkpICsgMTsKCiAgaXJkcC0+dF9hZHZlcnRpc2UgPSB0aHJlYWRfYWRkX3RpbWVyKHplYnJhZC5tYXN0ZXIsIAoJCQkJICAgICAgIGlyZHBfc2VuZF90aHJlYWQsIAoJCQkJICAgICAgIGlmcCwgCgkJCQkgICAgICAgdGltZXIpOwp9Cgp2b2lkIGlyZHBfZmluaXNoKCkKewoKICBzdHJ1Y3QgbGlzdG5vZGUgKm5vZGUsICpubm9kZTsKICBzdHJ1Y3QgaW50ZXJmYWNlICppZnA7CiAgc3RydWN0IHplYnJhX2lmICp6aTsKICBzdHJ1Y3QgaXJkcF9pbnRlcmZhY2UgKmlyZHA7CgogIHpsb2dfaW5mbygiSVJEUDogUmVjZWl2ZWQgc2h1dGRvd24gbm90aWZpY2F0aW9uLiIpOwogIAogIGZvciAoQUxMX0xJU1RfRUxFTUVOVFMgKGlmbGlzdCwgbm9kZSwgbm5vZGUsIGlmcCkpCiAgICB7CiAgICAgIHppID0gaWZwLT5pbmZvOwogICAgICAKICAgICAgaWYgKCF6aSkgCiAgICAgICAgY29udGludWU7CiAgICAgIGlyZHAgPSAmemktPmlyZHA7CiAgICAgIGlmICghaXJkcCkgCiAgICAgICAgY29udGludWU7CgogICAgICBpZiAoaXJkcC0+ZmxhZ3MgJiBJRl9BQ1RJVkUgKSAKICAgICAgICB7CgkgIGlyZHAtPmZsYWdzIHw9IElGX1NIVVRET1dOOwoJICBpcmRwX2FkdmVydF9vZmYoaWZwKTsKICAgICAgICB9CiAgICB9Cn0KCiNlbmRpZiAvKiBIQVZFX0lSRFAgKi8K