LyoKICoKICogQ29weXJpZ2h0IChDKSAyMDAwICBSb2JlcnQgT2xzc29uLgogKiBTd2VkaXNoIFVuaXZlcnNpdHkgb2YgQWdyaWN1bHR1cmFsIFNjaWVuY2VzCiAqCiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIEdOVSBaZWJyYS4KICoKICogR05VIFplYnJhIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXQKICogdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlCiAqIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMiwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkKICogbGF0ZXIgdmVyc2lvbi4KICoKICogR05VIFplYnJhIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dAogKiBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKICogYWxvbmcgd2l0aCBHTlUgWmVicmE7IHNlZSB0aGUgZmlsZSBDT1BZSU5HLiAgSWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZQogKiBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UgLSBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEKICogMDIxMTEtMTMwNywgVVNBLiAgCiAqLwoKLyogCiAqIFRoaXMgd29yayBpbmNsdWRlcyB3b3JrIHdpdGggdGhlIGZvbGxvd2luZyBjb3B5d3JpdGU6CiAqCiAqIENvcHlyaWdodCAoQykgMTk5NywgMjAwMCBLdW5paGlybyBJc2hpZ3VybwogKgogKi8KCi8qIAogKiBUaGFua3MgdG8gSmVucyBM5eVzIGF0IFN3ZWRpc2ggVW5pdmVyc2l0eSBvZiBBZ3JpY3VsdHVyYWwgU2NpZW5jZXMKICogZm9yIHJldmlld2luZyBhbmQgdGVzdHMuCiAqLwoKCiNpbmNsdWRlIDx6ZWJyYS5oPgoKI2lmZGVmIEhBVkVfSVJEUAoKI2luY2x1ZGUgImlmLmgiCiNpbmNsdWRlICJ2dHkuaCIKI2luY2x1ZGUgInNvY2t1bmlvbi5oIgojaW5jbHVkZSAicHJlZml4LmgiCiNpbmNsdWRlICJjb21tYW5kLmgiCiNpbmNsdWRlICJtZW1vcnkuaCIKI2luY2x1ZGUgInN0cmVhbS5oIgojaW5jbHVkZSAiaW9jdGwuaCIKI2luY2x1ZGUgImNvbm5lY3RlZC5oIgojaW5jbHVkZSAibG9nLmgiCiNpbmNsdWRlICJ6Y2xpZW50LmgiCiNpbmNsdWRlICJ0aHJlYWQuaCIKI2luY2x1ZGUgInplYnJhL2ludGVyZmFjZS5oIgojaW5jbHVkZSAiemVicmEvcnRhZHYuaCIKI2luY2x1ZGUgInplYnJhL3JpYi5oIgojaW5jbHVkZSAiemVicmEvenNlcnYuaCIKI2luY2x1ZGUgInplYnJhL3JlZGlzdHJpYnV0ZS5oIgojaW5jbHVkZSAiemVicmEvaXJkcC5oIgojaW5jbHVkZSA8bmV0aW5ldC9pcF9pY21wLmg+CgojaW5jbHVkZSAiaWYuaCIKI2luY2x1ZGUgInNvY2t1bmlvbi5oIgojaW5jbHVkZSAibG9nLmgiCgovKiBHTE9CQUwgVkFSUyAqLwoKLyogTWFzdGVyIG9mIHRocmVhZHMuICovCmV4dGVybiBzdHJ1Y3QgemVicmFfdCB6ZWJyYWQ7CnN0cnVjdCB0aHJlYWQgKnRfaXJkcF9yYXc7CgovKiBUaW1lciBpbnRlcnZhbCBvZiBpcmRwLiAqLwppbnQgaXJkcF90aW1lcl9pbnRlcnZhbCA9IElSRFBfREVGQVVMVF9JTlRFUlZBTDsKCmludCBpcmRwX3JlYWRfcmF3KHN0cnVjdCB0aHJlYWQgKnIpOwppbnQgaW5fY2tzdW0gKHZvaWQgKnB0ciwgaW50IG5ieXRlcyk7CmV4dGVybiBpbnQgaXJkcF9zb2NrOwp2b2lkIHNlbmRfcGFja2V0KHN0cnVjdCBpbnRlcmZhY2UgKmlmcCwgCgkJIHN0cnVjdCBzdHJlYW0gKnMsCgkJIHVfaW50MzJfdCBkc3QsCgkJIHN0cnVjdCBwcmVmaXggKnAsCgkJIHVfaW50MzJfdCB0dGwpOwoKdm9pZCBpcmRwX2lmX2luaXQgKCk7CgpjaGFyICoKaW5ldF8yYSh1X2ludDMyX3QgYSwgY2hhciAqYikKewogIHNwcmludGYoYiwgIiV1LiV1LiV1LiV1IiwgCiAgICAgICAgICAoYSAgICApICYgMHhGRiwKICAgICAgICAgIChhPj4gOCkgJiAweEZGLCAKICAgICAgICAgIChhPj4xNikgJiAweEZGLCAKICAgICAgICAgIChhPj4yNCkgJiAweEZGKTsKICByZXR1cm4gIGI7Cn0KCmludAppcmRwX3NvY2tfaW5pdCAodm9pZCkKewogIGludCByZXQsIGk7CgogIGlyZHBfc29jayA9IHNvY2tldCAoQUZfSU5FVCwgU09DS19SQVcsIElQUFJPVE9fSUNNUCk7CiAgaWYgKGlyZHBfc29jayA8IDApIHsKICAgIHpsb2dfd2FybiAoIklSRFA6IGNhbid0IGNyZWF0ZSBpcmRwIHNvY2tldCAlcyIsIHN0cmVycm9yKGVycm5vKSk7CiAgICByZXR1cm4gaXJkcF9zb2NrOwogIH07CiAgCiAgaSA9IDE7CiAgcmV0ID0gc2V0c29ja29wdCAoaXJkcF9zb2NrLCBJUFBST1RPX0lQLCBJUF9UVEwsIAogICAgICAgICAgICAgICAgICAgICAgICAodm9pZCAqKSAmaSwgc2l6ZW9mIChpKSk7CiAgaWYgKHJldCA8IDApIHsKICAgIHpsb2dfd2FybiAoIklSRFA6IGNhbid0IGRvIGlyZHAgc29ja29wdCAlcyIsIHN0cmVycm9yKGVycm5vKSk7CiAgICByZXR1cm4gcmV0OwogIH07CiAgCiAgaSA9IDE7CiAgcmV0ID0gc2V0c29ja29wdCAoaXJkcF9zb2NrLCBJUFBST1RPX0lQLCBJUF9QS1RJTkZPLCAKICAgICAgICAgICAgICAgICAgICAgICAgKHZvaWQgKikgJmksIHNpemVvZiAoaSkpOwogIGlmIChyZXQgPCAwKSB7CiAgICB6bG9nX3dhcm4gKCJJUkRQOiBjYW4ndCBkbyBpcmRwIHNvY2tvcHQgJXMiLCBzdHJlcnJvcihlcnJubykpOwogICAgcmV0dXJuIHJldDsKICB9OwoKICB0X2lyZHBfcmF3ID0gdGhyZWFkX2FkZF9yZWFkICh6ZWJyYWQubWFzdGVyLCBpcmRwX3JlYWRfcmF3LCBOVUxMLCBpcmRwX3NvY2spOyAKCiAgcmV0dXJuIGlyZHBfc29jazsKfQoKCmludCBnZXRfcHJlZihzdHJ1Y3QgaXJkcF9pbnRlcmZhY2UgKmlyZHAsIHN0cnVjdCBwcmVmaXggKnApCnsKICBsaXN0bm9kZSBub2RlOwogIHN0cnVjdCBBZHYgKmFkdjsKCiAgLyogVXNlIGRlZmF1bHQgcHJlZmVyZW5jZSBvciB1c2UgdGhlIG92ZXJyaWRlIHByZWYgKi8KICAKICBpZiggaXJkcC0+QWR2UHJlZkxpc3QgPT0gTlVMTCApIHJldHVybiBpcmRwLT5QcmVmZXJlbmNlOwogIAogIGZvciAobm9kZSA9IGxpc3RoZWFkIChpcmRwLT5BZHZQcmVmTGlzdCk7IG5vZGU7IG5leHRub2RlIChub2RlKSkgewogICAgYWR2ID0gZ2V0ZGF0YSAobm9kZSk7CiAgICBpZiggcC0+dS5wcmVmaXg0LnNfYWRkciA9PSBhZHYtPmlwLnNfYWRkciApCiAgICAgIHJldHVybiBhZHYtPnByZWY7CiAgfQogIHJldHVybiBpcmRwLT5QcmVmZXJlbmNlOwp9CgovKiBNYWtlIElDTVAgUm91dGVyIEFkdmVydGlzZW1lbnQgTWVzc2FnZS4gKi8KaW50IG1ha2VfYWR2ZXJ0aXNlbWVudF9wYWNrZXQgKHN0cnVjdCBpbnRlcmZhY2UgKmlmcCwgCgkJCSAgICAgICBzdHJ1Y3QgcHJlZml4ICpwLAoJCQkgICAgICAgc3RydWN0IHN0cmVhbSAqcykKewogIHN0cnVjdCB6ZWJyYV9pZiAqemk9aWZwLT5pbmZvOwogIHN0cnVjdCBpcmRwX2ludGVyZmFjZSAqaXJkcD0memktPmlyZHA7CiAgaW50IHNpemU7CiAgaW50IHByZWY7CiAgdV9pbnQxNl90IGNoZWNrc3VtOwoKICBwcmVmID0gIGdldF9wcmVmKGlyZHAsIHApOwoKICBzdHJlYW1fcHV0YyAocywgSUNNUF9ST1VURVJBRFZFUlQpOyAvKiBUeXBlLiAqLwogIHN0cmVhbV9wdXRjIChzLCAwKTsJCS8qIENvZGUuICovCiAgc3RyZWFtX3B1dHcgKHMsIDApOwkJLyogQ2hlY2tzdW0uICovCiAgc3RyZWFtX3B1dGMgKHMsIDEpOwkJLyogTnVtIGFkZHJlc3MuICovCiAgc3RyZWFtX3B1dGMgKHMsIDIpOwkJLyogQWRkcmVzcyBFbnRyeSBTaXplLiAqLwoKICBpZihpcmRwLT5mbGFncyAmIElGX1NIVVRET1dOKSAgCiAgICBzdHJlYW1fcHV0dyAocywgMCk7CiAgZWxzZSAKICAgIHN0cmVhbV9wdXR3IChzLCBpcmRwLT5MaWZldGltZSk7CgogIHN0cmVhbV9wdXRsIChzLCBodG9ubChwLT51LnByZWZpeDQuc19hZGRyKSk7IC8qIFJvdXRlciBhZGRyZXNzLiAqLwogIHN0cmVhbV9wdXRsIChzLCBwcmVmKTsKCiAgLyogaW5fY2tzdW0gcmV0dXJuIG5ldHdvcmsgYnl0ZSBvcmRlciB2YWx1ZSAqLwogIHNpemUgPSAxNjsKICBjaGVja3N1bSA9IGluX2Nrc3VtIChzLT5kYXRhLCBzaXplKTsKICBzdHJlYW1fcHV0d19hdCAocywgMiwgaHRvbnMoY2hlY2tzdW0pKTsKCiAgcmV0dXJuIHNpemU7Cn0KCnZvaWQgaXJkcF9zZW5kKHN0cnVjdCBpbnRlcmZhY2UgKmlmcCwgCgkgICAgICAgc3RydWN0IHByZWZpeCAqcCwgCgkgICAgICAgc3RydWN0IHN0cmVhbSAqcykKewogIHN0cnVjdCB6ZWJyYV9pZiAqemk9aWZwLT5pbmZvOwogIHN0cnVjdCBpcmRwX2ludGVyZmFjZSAqaXJkcD0memktPmlyZHA7CiAgdV9pbnQzMl90IGRzdDsKICB1X2ludDMyX3QgdHRsPTE7CgogIGlmICghIChpZnAtPmZsYWdzICYgSUZGX1VQKSkgcmV0dXJuOyAKCiAgaWYgKGlyZHAtPmZsYWdzICYgSUZfQlJPQURDQVNUKSAKICAgIGRzdCA9SU5BRERSX0JST0FEQ0FTVCA7CiAgZWxzZSAKICAgIGRzdCA9IGh0b25sKElOQUREUl9BTExIT1NUU19HUk9VUCk7CgogIGlmKGlyZHAtPmZsYWdzICYgSUZfREVCVUdfTUVTU0FHRVMpIAogICAgemxvZ193YXJuKCJJUkRQOiBUWCBBZHZlcnQgb24gJXMgJXMvJWQgSG9sZHRpbWU9JWQgUHJlZmVyZW5jZT0lZCIsIAoJICAgICAgaWZwLT5uYW1lLAoJICAgICAgaW5ldF9udG9hKHAtPnUucHJlZml4NCksIAoJICAgICAgcC0+cHJlZml4bGVuLAoJICAgICAgaXJkcC0+ZmxhZ3MgJiBJRl9TSFVURE9XTj8gMCA6IGlyZHAtPkxpZmV0aW1lLAoJICAgICAgZ2V0X3ByZWYoaXJkcCwgcCkpOwoKICBzZW5kX3BhY2tldCAoaWZwLCBzLCBkc3QsIHAsIHR0bCk7Cn0KCnZvaWQgaXJkcF9hZHZlcnRpc2VtZW50IChzdHJ1Y3QgaW50ZXJmYWNlICppZnAsIAoJCSAgIHN0cnVjdCBwcmVmaXggKnApCnsKICBzdHJ1Y3Qgc3RyZWFtICpzOwogIHMgPSBzdHJlYW1fbmV3ICgxMjgpOwogIG1ha2VfYWR2ZXJ0aXNlbWVudF9wYWNrZXQgKGlmcCwgcCwgcyk7CiAgaXJkcF9zZW5kKGlmcCwgcCwgcyk7IAp9CgppbnQgaXJkcF9zZW5kX3RocmVhZChzdHJ1Y3QgdGhyZWFkICp0X2FkdmVydCkKewogIHVfaW50MzJfdCB0aW1lciwgdG1wOwogIHN0cnVjdCBpbnRlcmZhY2UgKmlmcCA9IFRIUkVBRF9BUkcgKHRfYWR2ZXJ0KTsKICBzdHJ1Y3QgemVicmFfaWYgKnppPWlmcC0+aW5mbzsKICBzdHJ1Y3QgaXJkcF9pbnRlcmZhY2UgKmlyZHA9JnppLT5pcmRwOwogIHN0cnVjdCBwcmVmaXggKnA7CiAgbGlzdG5vZGUgbm9kZTsKICBzdHJ1Y3QgY29ubmVjdGVkICppZmM7CgogIGlyZHAtPmZsYWdzICY9IH5JRl9TT0xJQ0lUOwoKICBpZihpZnAtPmNvbm5lY3RlZCkgCiAgICBmb3IgKG5vZGUgPSBsaXN0aGVhZCAoaWZwLT5jb25uZWN0ZWQpOyBub2RlOyBuZXh0bm9kZSAobm9kZSkpIHsKICAgICAgaWZjID0gZ2V0ZGF0YSAobm9kZSk7CgogICAgICBwID0gaWZjLT5hZGRyZXNzOwoKICAgICAgaXJkcF9hZHZlcnRpc2VtZW50KGlmcCwgcCk7CiAgICAgIGlyZHAtPmlyZHBfc2VudCsrOwoKICAgIH0KCiAgdG1wID0gaXJkcC0+TWF4QWR2ZXJ0SW50ZXJ2YWwtaXJkcC0+TWluQWR2ZXJ0SW50ZXJ2YWw7CiAgdGltZXIgPSAgKHJhbmRvbSAoKSAlIHRtcCApICsgMTsKICB0aW1lciA9IGlyZHAtPk1pbkFkdmVydEludGVydmFsICsgdGltZXI7CgogIGlmKGlyZHAtPmlyZHBfc2VudCA8ICBNQVhfSU5JVElBTF9BRFZFUlRJU0VNRU5UUyAmJgogICAgIHRpbWVyID4gTUFYX0lOSVRJQUxfQURWRVJUX0lOVEVSVkFMICkgCgkgIHRpbWVyPSBNQVhfSU5JVElBTF9BRFZFUlRfSU5URVJWQUw7CgogIGlmKGlyZHAtPmZsYWdzICYgSUZfREVCVUdfTUlTQykKICAgIHpsb2dfd2FybigiSVJEUDogTmV3IHRpbWVyIGZvciAlcyBzZXQgdG8gJXVcbiIsIGlmcC0+bmFtZSwgdGltZXIpOwoKICBpcmRwLT50X2FkdmVydGlzZSA9IHRocmVhZF9hZGRfdGltZXIoemVicmFkLm1hc3RlciwgaXJkcF9zZW5kX3RocmVhZCwgaWZwLCB0aW1lcik7CiAgcmV0dXJuIDA7Cn0KCnZvaWQgaXJkcF9hZHZlcnRfb2ZmKHN0cnVjdCBpbnRlcmZhY2UgKmlmcCkKewogIHN0cnVjdCB6ZWJyYV9pZiAqemk9aWZwLT5pbmZvOwogIHN0cnVjdCBpcmRwX2ludGVyZmFjZSAqaXJkcD0memktPmlyZHA7CiAgbGlzdG5vZGUgbm9kZTsKICBpbnQgaTsKICBzdHJ1Y3QgY29ubmVjdGVkICppZmM7CiAgc3RydWN0IHByZWZpeCAqcDsKCiAgaWYoaXJkcC0+dF9hZHZlcnRpc2UpICB0aHJlYWRfY2FuY2VsKGlyZHAtPnRfYWR2ZXJ0aXNlKTsKICBpcmRwLT50X2FkdmVydGlzZSA9IE5VTEw7CiAgCiAgaWYoaWZwLT5jb25uZWN0ZWQpIAogICAgZm9yIChub2RlID0gbGlzdGhlYWQgKGlmcC0+Y29ubmVjdGVkKTsgbm9kZTsgbmV4dG5vZGUgKG5vZGUpKSB7CiAgICAgIGlmYyA9IGdldGRhdGEgKG5vZGUpOwoKICAgICAgcCA9IGlmYy0+YWRkcmVzczsKCiAgICAgIC8qIE91dHB1dCBzb21lIHBhY2tldHMgd2l0aCBMaWZldGltZSAwIAoJIHdlIHNob3VsZCBhZGQgYSB3YWl0Li4uCiAgICAgICovCgogICAgICBmb3IoaT0wOyBpPCBJUkRQX0xBU1RfQURWRVJUX01FU1NBR0VTOyBpKyspIHsKCglpcmRwLT5pcmRwX3NlbnQrKzsKCWlyZHBfYWR2ZXJ0aXNlbWVudChpZnAsIHApOwogICAgICB9CiAgICB9Cn0KCgp2b2lkIHByb2Nlc3Nfc29saWNpdCAoc3RydWN0IGludGVyZmFjZSAqaWZwKQp7CiAgc3RydWN0IHplYnJhX2lmICp6aT1pZnAtPmluZm87CiAgc3RydWN0IGlyZHBfaW50ZXJmYWNlICppcmRwPSZ6aS0+aXJkcDsKICB1X2ludDMyX3QgdGltZXI7CgogIC8qIFdoZW4gU09MSUNJVCBpcyBhY3RpdmUgd2UgcmVqZWN0IGZ1cnRoZXIgaW5jb21pbmcgc29saWNpdHMgCiAgICAgdGhpcyBrZWVwcyBkb3duIHRoZSBhbnN3ZXJpbmcgcmF0ZSBzbyB3ZSBkb24ndCBoYXZlIHRoaW5rCiAgICAgYWJvdXQgRG9TIGF0dGFja3MgaGVyZS4gKi8KCiAgaWYoIGlyZHAtPmZsYWdzICYgSUZfU09MSUNJVCkgcmV0dXJuOwoKICBpcmRwLT5mbGFncyB8PSBJRl9TT0xJQ0lUOwogIGlmKGlyZHAtPnRfYWR2ZXJ0aXNlKSAgdGhyZWFkX2NhbmNlbChpcmRwLT50X2FkdmVydGlzZSk7CiAgaXJkcC0+dF9hZHZlcnRpc2UgPSBOVUxMOwoKICB0aW1lciA9ICAocmFuZG9tICgpICUgTUFYX1JFU1BPTlNFX0RFTEFZKSArIDE7CgogIGlyZHAtPnRfYWR2ZXJ0aXNlID0gdGhyZWFkX2FkZF90aW1lcih6ZWJyYWQubWFzdGVyLCAKCQkJCSAgICAgICBpcmRwX3NlbmRfdGhyZWFkLCAKCQkJCSAgICAgICBpZnAsIAoJCQkJICAgICAgIHRpbWVyKTsKfQoKdm9pZCBpcmRwX2ZpbmlzaCgpCnsKCiAgbGlzdG5vZGUgbm9kZTsKICBzdHJ1Y3QgaW50ZXJmYWNlICppZnA7CiAgc3RydWN0IHplYnJhX2lmICp6aTsKICBzdHJ1Y3QgaXJkcF9pbnRlcmZhY2UgKmlyZHA7CgogIHpsb2dfd2FybigiSVJEUDogUmVjZWl2ZWQgc2h1dGRvd24gbm90aWZpY2F0aW9uLiIpOwogIAogIGZvciAobm9kZSA9IGxpc3RoZWFkIChpZmxpc3QpOyBub2RlOyBub2RlID0gbmV4dG5vZGUgKG5vZGUpKQogICAgewogICAgICBpZnAgPSBnZXRkYXRhKG5vZGUpOwogICAgICB6aT0gaWZwLT5pbmZvOwogICAgICBpZighIHppKSBjb250aW51ZTsKICAgICAgaXJkcCA9ICZ6aS0+aXJkcDsKICAgICAgaWYoIWlyZHApIGNvbnRpbnVlOwoKICAgICAgaWYoaXJkcC0+ZmxhZ3MgJiBJRl9BQ1RJVkUgKSB7CglpcmRwLT5mbGFncyB8PSBJRl9TSFVURE9XTjsKCWlyZHBfYWR2ZXJ0X29mZihpZnApOwogICAgICB9CiAgICB9Cn0KCnZvaWQgaXJkcF9pbml0KCkKewogIGlyZHBfc29ja19pbml0KCk7CiAgaXJkcF9pZl9pbml0ICgpOwp9CgoKCiNlbmRpZiAvKiBIQVZFX0lSRFAgKi8KCgoKCg==