LyoKICogRE9TIChNWikgbG9hZGVyCiAqCiAqIENvcHlyaWdodCAxOTk4IE92ZSBL5XZlbgogKgogKiBUaGlzIGNvZGUgaGFzbid0IGJlZW4gY29tcGxldGVseSBjbGVhbmVkIHVwIHlldC4KICovCgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDxlcnJuby5oPgojaW5jbHVkZSA8ZmNudGwuaD4KI2luY2x1ZGUgPHNpZ25hbC5oPgojaW5jbHVkZSA8dW5pc3RkLmg+CiNpbmNsdWRlIDxzeXMvdHlwZXMuaD4KI2luY2x1ZGUgPHN5cy9zdGF0Lmg+CiNpbmNsdWRlIDxzeXMvdGltZS5oPgojaW5jbHVkZSAid2luZGVmLmgiCiNpbmNsdWRlICJ3aW5lL3dpbmJhc2UxNi5oIgojaW5jbHVkZSAid2luZXJyb3IuaCIKI2luY2x1ZGUgIm1vZHVsZS5oIgojaW5jbHVkZSAicGVleGUuaCIKI2luY2x1ZGUgIm5lZXhlLmgiCiNpbmNsdWRlICJ0YXNrLmgiCiNpbmNsdWRlICJzZWxlY3RvcnMuaCIKI2luY2x1ZGUgImZpbGUuaCIKI2luY2x1ZGUgImxkdC5oIgojaW5jbHVkZSAicHJvY2Vzcy5oIgojaW5jbHVkZSAibWlzY2VtdS5oIgojaW5jbHVkZSAiZGVidWcuaCIKI2luY2x1ZGUgImRvc2V4ZS5oIgojaW5jbHVkZSAiZG9zbW9kLmgiCiNpbmNsdWRlICJvcHRpb25zLmgiCgojaWZkZWYgTVpfU1VQUE9SVEVECgojaW5jbHVkZSA8c3lzL21tYW4uaD4KCi8qIGRlZmluZSB0aGlzIHRvIHRyeSBtYXBwaW5nIHRocm91Z2ggL3Byb2MvcGlkL21lbSBpbnN0ZWFkIG9mIGEgdGVtcCBmaWxlLAogICBidXQgTGludXMgZG9lc24ndCBsaWtlIG1tYXBwaW5nIC9wcm9jL3BpZC9tZW0sIHNvIGl0IGRvZXNuJ3Qgd29yayBmb3IgbWUgKi8KI3VuZGVmIE1aX01BUFNFTEYKCiNkZWZpbmUgQklPU19EQVRBX1NFR01FTlQgMHg0MAojZGVmaW5lIFNUQVJUX09GRlNFVCAwCiNkZWZpbmUgUFNQX1NJWkUgMHgxMAoKI2RlZmluZSBTRUcxNihwdHIsc2VnKSAoKExQVk9JRCkoKEJZVEUqKXB0cisoKERXT1JEKShzZWcpPDw0KSkpCiNkZWZpbmUgU0VHUFRSMTYocHRyLHNlZ3B0cikgKChMUFZPSUQpKChCWVRFKilwdHIrKChEV09SRClTRUxFQ1RPUk9GKHNlZ3B0cik8PDQpK09GRlNFVE9GKHNlZ3B0cikpKQoKc3RhdGljIHZvaWQgTVpfSW5pdFBTUCggTFBWT0lEIGxwUFNQLCBMUENTVFIgY21kbGluZSwgV09SRCBlbnYgKQp7CiBQREIxNipwc3A9bHBQU1A7CiBjb25zdCBjaGFyKmNtZD1jbWRsaW5lP3N0cmNocihjbWRsaW5lLCcgJyk6TlVMTDsKCiBwc3AtPmludDIwPTB4MjBDRDsgLyogaW50IDIwICovCiAvKiBzb21lIHByb2dyYW1zIHVzZSB0aGlzIHRvIGNhbGN1bGF0ZSBob3cgbXVjaCBtZW1vcnkgdGhleSBuZWVkICovCiBwc3AtPm5leHRQYXJhZ3JhcGg9MHg5RkZGOwogcHNwLT5lbnZpcm9ubWVudD1lbnY7CiAvKiBjb3B5IHBhcmFtZXRlcnMgKi8KIGlmIChjbWQpIHsKI2lmIDAKICAvKiBjb21tYW5kLmNvbSBkb2Vzbid0IGRvIHRoaXMgKi8KICB3aGlsZSAoKmNtZCA9PSAnICcpIGNtZCsrOwojZW5kaWYKICBwc3AtPmNtZExpbmVbMF09c3RybGVuKGNtZCk7CiAgc3RyY3B5KHBzcC0+Y21kTGluZSsxLGNtZCk7CiAgcHNwLT5jbWRMaW5lW3BzcC0+Y21kTGluZVswXSsxXT0nXHInOwogfSBlbHNlIHBzcC0+Y21kTGluZVsxXT0nXHInOwogLyogRklYTUU6IGludGVncmF0ZSB0aGUgbWVtb3J5IHN0dWZmIGZyb20gV2luZSAobXNkb3MvZG9zbWVtLmMpICovCiAvKiBGSVhNRTogaW50ZWdyYXRlIHRoZSBQREIgc3R1ZmYgZnJvbSBXaW5lIChsb2FkZXIvdGFzay5jKSAqLwp9CgovKiBkZWZhdWx0IElOVCAwOCBoYW5kbGVyOiBpbmNyZWFzZXMgdGltZXIgdGljayBjb3VudGVyIGJ1dCBub3QgbXVjaCBtb3JlICovCnN0YXRpYyBjaGFyIGludDA4W109ewogMHhDRCwweDFDLCAgICAgICAgICAgLyogaW50ICQweDFjICovCiAweDUwLCAgICAgICAgICAgICAgICAvKiBwdXNodyAlYXggKi8KIDB4MUUsICAgICAgICAgICAgICAgIC8qIHB1c2h3ICVkcyAqLwogMHhCOCwweDQwLDB4MDAsICAgICAgLyogbW92dyAkMHg0MCwlYXggKi8KIDB4OEUsMHhEOCwgICAgICAgICAgIC8qIG1vdncgJWF4LCVkcyAqLwojaWYgMAogMHg4MywweDA2LDB4NkMsMHgwMCwweDAxLCAvKiBhZGR3ICQxLCgweDZjKSAqLwogMHg4MywweDE2LDB4NkUsMHgwMCwweDAwLCAvKiBhZGN3ICQwLCgweDZlKSAqLwojZWxzZQogMHg2NiwweEZGLDB4MDYsMHg2QywweDAwLCAvKiBpbmNsICgweDZjKSAqLwojZW5kaWYKIDB4QjAsMHgyMCwgICAgICAgICAgIC8qIG1vdmIgJDB4MjAsJWFsICovCiAweEU2LDB4MjAsICAgICAgICAgICAvKiBvdXRiICVhbCwkMHgyMCAqLwogMHgxRiwgICAgICAgICAgICAgICAgLyogcG9wdyAlYXggKi8KIDB4NTgsICAgICAgICAgICAgICAgIC8qIHBvcHcgJWF4ICovCiAweENGICAgICAgICAgICAgICAgICAvKiBpcmV0ICovCn07CgpzdGF0aWMgdm9pZCBNWl9Jbml0SGFuZGxlcnMoIExQRE9TVEFTSyBscERvc1Rhc2sgKQp7CiBXT1JEIHNlZzsKIExQQllURSBzdGFydD1ET1NNRU1fR2V0QmxvY2sobHBEb3NUYXNrLT5oTW9kdWxlLHNpemVvZihpbnQwOCksJnNlZyk7CiBtZW1jcHkoc3RhcnQsaW50MDgsc2l6ZW9mKGludDA4KSk7Ci8qIElOVCAwODogcG9pbnQgaXQgYXQgb3VyIHRpY2staW5jcmVtZW50aW5nIGhhbmRsZXIgKi8KICgoU0VHUFRSKikobHBEb3NUYXNrLT5pbWcpKVsweDA4XT1QVFJfU0VHX09GRl9UT19TRUdQVFIoc2VnLDApOwovKiBJTlQgMUM6IGp1c3QgcG9pbnQgaXQgdG8gSVJFVCwgd2UgZG9uJ3Qgd2FudCB0byBoYW5kbGUgaXQgb3Vyc2VsdmVzICovCiAoKFNFR1BUUiopKGxwRG9zVGFzay0+aW1nKSlbMHgxQ109UFRSX1NFR19PRkZfVE9fU0VHUFRSKHNlZyxzaXplb2YoaW50MDgpLTEpOwp9CgpzdGF0aWMgY2hhciBlbnRlcl94bXNbXT17Ci8qIFhNUyBob29rYWJsZSBlbnRyeSBwb2ludCAqLwogMHhFQiwweDAzLCAgICAgICAgICAgLyogam1wIGVudHJ5ICovCiAweDkwLDB4OTAsMHg5MCwgICAgICAvKiBub3A7bm9wO25vcCAqLwogICAgICAgICAgICAgICAgICAgICAgLyogZW50cnk6ICovCi8qIHJlYWwgZW50cnkgcG9pbnQgKi8KLyogZm9yIHNpbXBsaWNpdHksIHdlJ2xsIGp1c3QgdXNlIHRoZSBzYW1lIGhvb2sgYXMgRFBNSSBiZWxvdyAqLwogMHhDRCwweDMxLCAgICAgICAgICAgLyogaW50ICQweDMxICovCiAweENCICAgICAgICAgICAgICAgICAvKiBscmV0ICovCn07CgpzdGF0aWMgdm9pZCBNWl9Jbml0WE1TKCBMUERPU1RBU0sgbHBEb3NUYXNrICkKewogTFBCWVRFIHN0YXJ0PURPU01FTV9HZXRCbG9jayhscERvc1Rhc2stPmhNb2R1bGUsc2l6ZW9mKGVudGVyX3htcyksJihscERvc1Rhc2stPnhtc19zZWcpKTsKIG1lbWNweShzdGFydCxlbnRlcl94bXMsc2l6ZW9mKGVudGVyX3htcykpOwp9CgpzdGF0aWMgY2hhciBlbnRlcl9wbVtdPXsKIDB4NTAsICAgICAgICAgICAgICAgIC8qIHB1c2h3ICVheCAqLwogMHg1MiwgICAgICAgICAgICAgICAgLyogcHVzaHcgJWR4ICovCiAweDU1LCAgICAgICAgICAgICAgICAvKiBwdXNodyAlYnAgKi8KIDB4ODksMHhFNSwgICAgICAgICAgIC8qIG1vdncgJXNwLCVicCAqLwovKiBnZXQgcmV0dXJuIENTICovCiAweDhCLDB4NTYsMHgwOCwgICAgICAvKiBtb3Z3IDgoJWJwKSwlZHggKi8KLyoganVzdCBjYWxsIGludCAzMSBoZXJlIHRvIGdldCBpbnRvIHByb3RlY3RlZCBtb2RlLi4uICovCi8qIGl0J2xsIGNoZWNrIHdoZXRoZXIgaXQgd2FzIGNhbGxlZCBmcm9tIGRwbWlfc2VnLi4uICovCiAweENELDB4MzEsICAgICAgICAgICAvKiBpbnQgJDB4MzEgKi8KLyogd2UgYXJlIG5vdyBpbiB0aGUgY29udGV4dCBvZiBhIDE2LWJpdCByZWxheSBjYWxsICovCi8qIG5lZWQgdG8gZml4dXAgb3VyIHN0YWNrOwogKiAxNi1iaXQgcmVsYXkgcmV0dXJuIGFkZHJlc3Mgd2lsbCBiZSBsb3N0LCBidXQgd2Ugd29uJ3Qgd29ycnkgcXVpdGUgeWV0ICovCiAweDhFLDB4RDAsICAgICAgICAgICAvKiBtb3Z3ICVheCwlc3MgKi8KIDB4NjYsMHgwRiwweEI3LDB4RTUsIC8qIG1vdnp3bCAlYnAsJWVzcCAqLwovKiBzZXQgcmV0dXJuIENTICovCiAweDg5LDB4NTYsMHgwOCwgICAgICAvKiBtb3Z3ICVkeCw4KCVicCkgKi8KIDB4NUQsICAgICAgICAgICAgICAgIC8qIHBvcHcgJWJwICovCiAweDVBLCAgICAgICAgICAgICAgICAvKiBwb3B3ICVkeCAqLwogMHg1OCwgICAgICAgICAgICAgICAgLyogcG9wdyAlYXggKi8KIDB4Q0IgICAgICAgICAgICAgICAgIC8qIGxyZXQgKi8KfTsKCnN0YXRpYyB2b2lkIE1aX0luaXREUE1JKCBMUERPU1RBU0sgbHBEb3NUYXNrICkKewogdW5zaWduZWQgc2l6ZT1zaXplb2YoZW50ZXJfcG0pOwogTFBCWVRFIHN0YXJ0PURPU01FTV9HZXRCbG9jayhscERvc1Rhc2stPmhNb2R1bGUsc2l6ZSwmKGxwRG9zVGFzay0+ZHBtaV9zZWcpKTsKIAogbHBEb3NUYXNrLT5kcG1pX3NlbCA9IFNFTEVDVE9SX0FsbG9jQmxvY2soIHN0YXJ0LCBzaXplLCBTRUdNRU5UX0NPREUsIEZBTFNFLCBGQUxTRSApOwoKIG1lbWNweShzdGFydCxlbnRlcl9wbSxzaXplb2YoZW50ZXJfcG0pKTsKfQoKc3RhdGljIFdPUkQgTVpfSW5pdEVudmlyb25tZW50KCBMUERPU1RBU0sgbHBEb3NUYXNrLCBMUENTVFIgZW52LCBMUENTVFIgbmFtZSApCnsKIHVuc2lnbmVkIHN6PTA7CiBXT1JEIHNlZzsKIExQU1RSIGVudmJsazsKCiBpZiAoZW52KSB7CiAgLyogZ2V0IHNpemUgb2YgZW52aXJvbm1lbnQgYmxvY2sgKi8KICB3aGlsZSAoZW52W3N6KytdKSBzeis9c3RybGVuKGVuditzeikrMTsKIH0gZWxzZSBzeisrOwogLyogYWxsb2NhdGUgaXQgKi8KIGVudmJsaz1ET1NNRU1fR2V0QmxvY2sobHBEb3NUYXNrLT5oTW9kdWxlLHN6K3NpemVvZihXT1JEKStzdHJsZW4obmFtZSkrMSwmc2VnKTsKIC8qIGZpbGwgaXQgKi8KIGlmIChlbnYpIHsKICBtZW1jcHkoZW52YmxrLGVudixzeik7CiB9IGVsc2UgZW52YmxrWzBdPTA7CiAvKiBET1MgMy54OiB0aGUgYmxvY2sgY29udGFpbnMgMSBhZGRpdGlvbmFsIHN0cmluZyAqLwogKihXT1JEKikoZW52YmxrK3N6KT0xOwogLyogYmVpbmcgdGhlIHByb2dyYW0gbmFtZSBpdHNlbGYgKi8KIHN0cmNweShlbnZibGsrc3orc2l6ZW9mKFdPUkQpLG5hbWUpOwogcmV0dXJuIHNlZzsKfQoKc3RhdGljIEJPT0wgTVpfSW5pdE1lbW9yeSggTFBET1NUQVNLIGxwRG9zVGFzaywgTkVfTU9EVUxFICpwTW9kdWxlICkKewogaW50IHg7CgogaWYgKGxwRG9zVGFzay0+aW1nX29mcykgcmV0dXJuIFRSVUU7IC8qIGFscmVhZHkgYWxsb2NhdGVkICovCgogLyogYWxsb2NhdGUgMU1CKzY0SyBzaGFyZWQgbWVtb3J5ICovCiBscERvc1Rhc2stPmltZ19vZnM9U1RBUlRfT0ZGU0VUOwojaWZkZWYgTVpfTUFQU0VMRgogbHBEb3NUYXNrLT5pbWc9VmlydHVhbEFsbG9jKE5VTEwsMHgxMTAwMDAsTUVNX0NPTU1JVCxQQUdFX1JFQURXUklURSk7CiAvKiBtYWtlIHN1cmUgbW1hcCBhY2NlcHRzIGl0ICovCiAoKGNoYXIqKWxwRG9zVGFzay0+aW1nKVsweDEwRkZGRl09MDsKI2Vsc2UKIHRtcG5hbShscERvc1Rhc2stPm1tX25hbWUpOwovKiBzdHJjcHkobHBEb3NUYXNrLT5tbV9uYW1lLCIvdG1wL215ZG9zaW1hZ2UiKTsgKi8KIGxwRG9zVGFzay0+bW1fZmQ9b3BlbihscERvc1Rhc2stPm1tX25hbWUsT19SRFdSfE9fQ1JFQVQgLyogfE9fVFJVTkMgKi8sU19JUlVTUnxTX0lXVVNSKTsKIGlmIChscERvc1Rhc2stPm1tX2ZkPDApIEVSUihtb2R1bGUsImZpbGUgJXMgY291bGQgbm90IGJlIG9wZW5lZFxuIixscERvc1Rhc2stPm1tX25hbWUpOwogLyogZXhwYW5kIGZpbGUgdG8gMU1CKzY0SyAqLwogbHNlZWsobHBEb3NUYXNrLT5tbV9mZCwweDExMDAwMC0xLFNFRUtfU0VUKTsKIHg9MDsgd3JpdGUobHBEb3NUYXNrLT5tbV9mZCwmeCwxKTsKIC8qIG1hcCBpdCBpbiAqLwogbHBEb3NUYXNrLT5pbWc9bW1hcChOVUxMLDB4MTEwMDAwLVNUQVJUX09GRlNFVCxQUk9UX1JFQUR8UFJPVF9XUklURSxNQVBfU0hBUkVELGxwRG9zVGFzay0+bW1fZmQsMCk7CiNlbmRpZgogaWYgKGxwRG9zVGFzay0+aW1nPT0oTFBWT0lEKS0xKSB7CiAgRVJSKG1vZHVsZSwiY291bGQgbm90IG1hcCBzaGFyZWQgbWVtb3J5LCBlcnJvcj0lc1xuIixzdHJlcnJvcihlcnJubykpOwogIHJldHVybiBGQUxTRTsKIH0KIFRSQUNFKG1vZHVsZSwiRE9TIFZNODYgaW1hZ2UgbWFwcGVkIGF0ICUwOGx4XG4iLChEV09SRClscERvc1Rhc2stPmltZyk7CiBwTW9kdWxlLT5kb3NfaW1hZ2U9bHBEb3NUYXNrLT5pbWc7CgogLyogaW5pdGlhbGl6ZSB0aGUgbWVtb3J5ICovCiBUUkFDRShtb2R1bGUsIkluaXRpYWxpemluZyBET1MgbWVtb3J5IHN0cnVjdHVyZXNcbiIpOwogRE9TTUVNX0luaXQobHBEb3NUYXNrLT5oTW9kdWxlKTsKIE1aX0luaXRIYW5kbGVycyhscERvc1Rhc2spOwogTVpfSW5pdFhNUyhscERvc1Rhc2spOwogTVpfSW5pdERQTUkobHBEb3NUYXNrKTsKIHJldHVybiBUUlVFOwp9CgpzdGF0aWMgQk9PTCBNWl9Mb2FkSW1hZ2UoIEhGSUxFIGhGaWxlLCBPRlNUUlVDVCAqb2ZzLCBMUENTVFIgY21kbGluZSwKICAgICAgICAgICAgICAgICAgICAgICAgICBMUENTVFIgZW52LCBMUERPU1RBU0sgbHBEb3NUYXNrLCBORV9NT0RVTEUgKnBNb2R1bGUgKQp7CiBJTUFHRV9ET1NfSEVBREVSIG16X2hlYWRlcjsKIERXT1JEIGltYWdlX3N0YXJ0LGltYWdlX3NpemUsbWluX3NpemUsbWF4X3NpemUsYXZhaWw7CiBCWVRFKnBzcF9zdGFydCwqbG9hZF9zdGFydDsKIGludCB4LG9sZF9jb209MDsKIFNFR1BUUiByZWxvYzsKIFdPUkQgZW52X3NlZzsKCiBfbGxzZWVrKGhGaWxlLDAsRklMRV9CRUdJTik7CiBpZiAoKF9scmVhZChoRmlsZSwmbXpfaGVhZGVyLHNpemVvZihtel9oZWFkZXIpKSAhPSBzaXplb2YobXpfaGVhZGVyKSkgfHwKICAgICAobXpfaGVhZGVyLmVfbWFnaWMgIT0gSU1BR0VfRE9TX1NJR05BVFVSRSkpIHsKICBvbGRfY29tPTE7IC8qIGFzc3VtZSAuQ09NIGZpbGUgKi8KICBpbWFnZV9zdGFydD0wOwogIGltYWdlX3NpemU9R2V0RmlsZVNpemUoaEZpbGUsTlVMTCk7CiAgbWluX3NpemU9MHgxMDAwMDsgbWF4X3NpemU9MHgxMDAwMDA7CiAgbXpfaGVhZGVyLmVfY3JsYz0wOwogIG16X2hlYWRlci5lX3NzPTA7IG16X2hlYWRlci5lX3NwPTB4RkZGRTsKICBtel9oZWFkZXIuZV9jcz0wOyBtel9oZWFkZXIuZV9pcD0weDEwMDsKIH0gZWxzZSB7CiAgLyogY2FsY3VsYXRlIGxvYWQgc2l6ZSAqLwogIGltYWdlX3N0YXJ0PW16X2hlYWRlci5lX2NwYXJoZHI8PDQ7CiAgaW1hZ2Vfc2l6ZT1tel9oZWFkZXIuZV9jcDw8OTsgLyogcGFnZXMgYXJlIDUxMiBieXRlcyAqLwogIGlmICgobXpfaGVhZGVyLmVfY2JscCE9MCkmJihtel9oZWFkZXIuZV9jYmxwIT00KSkgaW1hZ2Vfc2l6ZS09NTEyLW16X2hlYWRlci5lX2NibHA7CiAgaW1hZ2Vfc2l6ZS09aW1hZ2Vfc3RhcnQ7CiAgbWluX3NpemU9aW1hZ2Vfc2l6ZSsoKERXT1JEKW16X2hlYWRlci5lX21pbmFsbG9jPDw0KSsoUFNQX1NJWkU8PDQpOwogIG1heF9zaXplPWltYWdlX3NpemUrKChEV09SRCltel9oZWFkZXIuZV9tYXhhbGxvYzw8NCkrKFBTUF9TSVpFPDw0KTsKIH0KCiBNWl9Jbml0TWVtb3J5KGxwRG9zVGFzayxwTW9kdWxlKTsKCiAvKiBhbGxvY2F0ZSBlbnZpcm9ubWVudCBibG9jayAqLwogZW52X3NlZz1NWl9Jbml0RW52aXJvbm1lbnQobHBEb3NUYXNrLGVudixvZnMtPnN6UGF0aE5hbWUpOwoKIC8qIGFsbG9jYXRlIG1lbW9yeSBmb3IgdGhlIGV4ZWN1dGFibGUgKi8KIFRSQUNFKG1vZHVsZSwiQWxsb2NhdGluZyBET1MgbWVtb3J5IChtaW49JWxkLCBtYXg9JWxkKVxuIixtaW5fc2l6ZSxtYXhfc2l6ZSk7CiBhdmFpbD1ET1NNRU1fQXZhaWxhYmxlKGxwRG9zVGFzay0+aE1vZHVsZSk7CiBpZiAoYXZhaWw8bWluX3NpemUpIHsKICBFUlIobW9kdWxlLCAiaW5zdWZmaWNpZW50IERPUyBtZW1vcnlcbiIpOwogIFNldExhc3RFcnJvcihFUlJPUl9OT1RfRU5PVUdIX01FTU9SWSk7CiAgcmV0dXJuIEZBTFNFOwogfQogaWYgKGF2YWlsPm1heF9zaXplKSBhdmFpbD1tYXhfc2l6ZTsKIHBzcF9zdGFydD1ET1NNRU1fR2V0QmxvY2sobHBEb3NUYXNrLT5oTW9kdWxlLGF2YWlsLCZscERvc1Rhc2stPnBzcF9zZWcpOwogaWYgKCFwc3Bfc3RhcnQpIHsKICBFUlIobW9kdWxlLCAiZXJyb3IgYWxsb2NhdGluZyBET1MgbWVtb3J5XG4iKTsKICBTZXRMYXN0RXJyb3IoRVJST1JfTk9UX0VOT1VHSF9NRU1PUlkpOwogIHJldHVybiBGQUxTRTsKIH0KIGxwRG9zVGFzay0+bG9hZF9zZWc9bHBEb3NUYXNrLT5wc3Bfc2VnKyhvbGRfY29tPzA6UFNQX1NJWkUpOwogbG9hZF9zdGFydD1wc3Bfc3RhcnQrKFBTUF9TSVpFPDw0KTsKIE1aX0luaXRQU1AocHNwX3N0YXJ0LCBjbWRsaW5lLCBlbnZfc2VnKTsKCiAvKiBsb2FkIGV4ZWN1dGFibGUgaW1hZ2UgKi8KIFRSQUNFKG1vZHVsZSwibG9hZGluZyBET1MgJXMgaW1hZ2UsICUwOGx4IGJ5dGVzXG4iLG9sZF9jb20/IkNPTSI6IkVYRSIsaW1hZ2Vfc2l6ZSk7CiBfbGxzZWVrKGhGaWxlLGltYWdlX3N0YXJ0LEZJTEVfQkVHSU4pOwogaWYgKChfbHJlYWQoaEZpbGUsbG9hZF9zdGFydCxpbWFnZV9zaXplKSkgIT0gaW1hZ2Vfc2l6ZSkgewogIFNldExhc3RFcnJvcihFUlJPUl9CQURfRk9STUFUKTsKICByZXR1cm4gRkFMU0U7CiB9CgogaWYgKG16X2hlYWRlci5lX2NybGMpIHsKICAvKiBsb2FkIHJlbG9jYXRpb24gdGFibGUgKi8KICBUUkFDRShtb2R1bGUsImxvYWRpbmcgRE9TIEVYRSByZWxvY2F0aW9uIHRhYmxlLCAlZCBlbnRyaWVzXG4iLG16X2hlYWRlci5lX2NybGMpOwogIC8qIEZJWE1FOiBpcyB0aGlzIHRvbyBzbG93IHdpdGhvdXQgcmVhZCBidWZmZXJpbmc/ICovCiAgX2xsc2VlayhoRmlsZSxtel9oZWFkZXIuZV9sZmFybGMsRklMRV9CRUdJTik7CiAgZm9yICh4PTA7IHg8bXpfaGVhZGVyLmVfY3JsYzsgeCsrKSB7CiAgIGlmIChfbHJlYWQoaEZpbGUsJnJlbG9jLHNpemVvZihyZWxvYykpICE9IHNpemVvZihyZWxvYykpIHsKICAgIFNldExhc3RFcnJvcihFUlJPUl9CQURfRk9STUFUKTsKICAgIHJldHVybiBGQUxTRTsKICAgfQogICAqKFdPUkQqKVNFR1BUUjE2KGxvYWRfc3RhcnQscmVsb2MpKz1scERvc1Rhc2stPmxvYWRfc2VnOwogIH0KIH0KCiBscERvc1Rhc2stPmluaXRfY3M9bHBEb3NUYXNrLT5sb2FkX3NlZyttel9oZWFkZXIuZV9jczsKIGxwRG9zVGFzay0+aW5pdF9pcD1tel9oZWFkZXIuZV9pcDsKIGxwRG9zVGFzay0+aW5pdF9zcz1scERvc1Rhc2stPmxvYWRfc2VnK216X2hlYWRlci5lX3NzOwogbHBEb3NUYXNrLT5pbml0X3NwPW16X2hlYWRlci5lX3NwOwoKIFRSQUNFKG1vZHVsZSwiZW50cnkgcG9pbnQ6ICUwNHg6JTA0eFxuIixscERvc1Rhc2stPmluaXRfY3MsbHBEb3NUYXNrLT5pbml0X2lwKTsKIHJldHVybiBUUlVFOwp9CgpMUERPU1RBU0sgTVpfQWxsb2NEUE1JVGFzayggSE1PRFVMRTE2IGhNb2R1bGUgKQp7CiBMUERPU1RBU0sgbHBEb3NUYXNrID0gY2FsbG9jKDEsIHNpemVvZihET1NUQVNLKSk7CiBORV9NT0RVTEUgKnBNb2R1bGU7CgogaWYgKGxwRG9zVGFzaykgewogIGxwRG9zVGFzay0+aE1vZHVsZSA9IGhNb2R1bGU7CgogIHBNb2R1bGUgPSAoTkVfTU9EVUxFICopR2xvYmFsTG9jazE2KGhNb2R1bGUpOwogIHBNb2R1bGUtPmxwRG9zVGFzayA9IGxwRG9zVGFzazsKIAogIGxwRG9zVGFzay0+aW1nPU5VTEw7IGxwRG9zVGFzay0+bW1fbmFtZVswXT0wOyBscERvc1Rhc2stPm1tX2ZkPS0xOwoKICBNWl9Jbml0TWVtb3J5KGxwRG9zVGFzaywgcE1vZHVsZSk7CgogIEdsb2JhbFVubG9jazE2KGhNb2R1bGUpOwogfQogcmV0dXJuIGxwRG9zVGFzazsKfQoKc3RhdGljIHZvaWQgTVpfSW5pdFRpbWVyKCBMUERPU1RBU0sgbHBEb3NUYXNrLCBpbnQgdmVyICkKewogaWYgKHZlcjwxKSB7CiNpZiAwCiAgLyogc3RhcnQgc2ltdWxhdGVkIHN5c3RlbSA1NUh6IHRpbWVyICovCiAgbHBEb3NUYXNrLT5zeXN0ZW1fdGltZXIgPSBDcmVhdGVTeXN0ZW1UaW1lciggNTUsIE1aX1RpY2sgKTsKICBUUkFDRShtb2R1bGUsImNyZWF0ZWQgNTVIeiB0aW1lciB0aWNrLCBoYW5kbGU9JWRcbiIsbHBEb3NUYXNrLT5zeXN0ZW1fdGltZXIpOwojZW5kaWYKIH0gZWxzZSB7CiAgaW50IGZ1bmM7CiAgc3RydWN0IHRpbWV2YWwgdGltOwoKICAvKiBzdGFydCBkb3Ntb2QgdGltZXIgYXQgNTVIeiAqLwogIGZ1bmM9RE9TTU9EX1NFVF9USU1FUjsKICB0aW0udHZfc2VjPTA7IHRpbS50dl91c2VjPTU0OTI1OwogIHdyaXRlKGxwRG9zVGFzay0+d3JpdGVfcGlwZSwmZnVuYyxzaXplb2YoZnVuYykpOwogIHdyaXRlKGxwRG9zVGFzay0+d3JpdGVfcGlwZSwmdGltLHNpemVvZih0aW0pKTsKIH0KfQoKQk9PTCBNWl9Jbml0VGFzayggTFBET1NUQVNLIGxwRG9zVGFzayApCnsKIGludCByZWFkX2ZkWzJdLHdyaXRlX2ZkWzJdOwogcGlkX3QgY2hpbGQ7CiBjaGFyICpmbmFtZSwqZmFyZyxhcmdbMTZdLGZwcm9jWzY0XSxwYXRoWzI1Nl0sKmZwYXRoOwoKIGlmICghbHBEb3NUYXNrKSByZXR1cm4gRkFMU0U7CiAvKiBjcmVhdGUgcmVhZCBwaXBlICovCiBpZiAocGlwZShyZWFkX2ZkKTwwKSByZXR1cm4gRkFMU0U7CiBpZiAocGlwZSh3cml0ZV9mZCk8MCkgewogIGNsb3NlKHJlYWRfZmRbMF0pOyBjbG9zZShyZWFkX2ZkWzFdKTsgcmV0dXJuIEZBTFNFOwogfQogbHBEb3NUYXNrLT5yZWFkX3BpcGU9cmVhZF9mZFswXTsKIGxwRG9zVGFzay0+d3JpdGVfcGlwZT13cml0ZV9mZFsxXTsKIC8qIGlmIHdlIGhhdmUgYSBtYXBwaW5nIGZpbGUsIHVzZSBpdCAqLwogZm5hbWU9bHBEb3NUYXNrLT5tbV9uYW1lOyBmYXJnPU5VTEw7CiBpZiAoIWZuYW1lWzBdKSB7CiAgLyogb3RoZXJ3aXNlLCBtYXAgb3VyIG93biBtZW1vcnkgaW1hZ2UgKi8KICBzcHJpbnRmKGZwcm9jLCIvcHJvYy8lZC9tZW0iLGdldHBpZCgpKTsKICBzcHJpbnRmKGFyZywiJWxkIiwodW5zaWduZWQgbG9uZylscERvc1Rhc2stPmltZyk7CiAgZm5hbWU9ZnByb2M7IGZhcmc9YXJnOwogfQoKIFRSQUNFKG1vZHVsZSwiTG9hZGluZyBET1MgVk0gc3VwcG9ydCBtb2R1bGUgKGhtb2R1bGU9JTA0eClcbiIsbHBEb3NUYXNrLT5oTW9kdWxlKTsKIGlmICgoY2hpbGQ9Zm9yaygpKTwwKSB7CiAgY2xvc2Uod3JpdGVfZmRbMF0pOyBjbG9zZSh3cml0ZV9mZFsxXSk7CiAgY2xvc2UocmVhZF9mZFswXSk7IGNsb3NlKHJlYWRfZmRbMV0pOyByZXR1cm4gRkFMU0U7CiB9CiBpZiAoY2hpbGQhPTApIHsKICAvKiBwYXJlbnQgcHJvY2VzcyAqLwogIGludCByZXQ7CgogIGNsb3NlKHJlYWRfZmRbMV0pOyBjbG9zZSh3cml0ZV9mZFswXSk7CiAgbHBEb3NUYXNrLT50YXNrPWNoaWxkOwogIC8qIHdhaXQgZm9yIGNoaWxkIHByb2Nlc3MgdG8gc2lnbmFsIHJlYWRpbmVzcyAqLwogIGRvIHsKICAgaWYgKHJlYWQobHBEb3NUYXNrLT5yZWFkX3BpcGUsJnJldCxzaXplb2YocmV0KSkhPXNpemVvZihyZXQpKSB7CiAgICBpZiAoKGVycm5vPT1FSU5UUil8fChlcnJubz09RUFHQUlOKSkgY29udGludWU7CiAgICAvKiBmYWlsdXJlICovCiAgICBFUlIobW9kdWxlLCJkb3Ntb2QgaGFzIGZhaWxlZCB0byBpbml0aWFsaXplXG4iKTsKICAgIGlmIChscERvc1Rhc2stPm1tX25hbWVbMF0hPTApIHVubGluayhscERvc1Rhc2stPm1tX25hbWUpOwogICAgcmV0dXJuIEZBTFNFOwogICB9CiAgfSB3aGlsZSAoMCk7CiAgLyogdGhlIGNoaWxkIGhhcyBub3cgbW1hcGVkIHRoZSB0ZW1wIGZpbGUsIGl0J3Mgbm93IHNhZmUgdG8gdW5saW5rLgogICAqIGRvIGl0IGhlcmUgdG8gYXZvaWQgbGVhdmluZyBhIG1lc3MgaW4gL3RtcCBpZi93aGVuIFdpbmUgY3Jhc2hlcy4uLiAqLwogIGlmIChscERvc1Rhc2stPm1tX25hbWVbMF0hPTApIHVubGluayhscERvc1Rhc2stPm1tX25hbWUpOwogIC8qIHN0YXJ0IHNpbXVsYXRlZCBzeXN0ZW0gdGltZXIgKi8KICBNWl9Jbml0VGltZXIobHBEb3NUYXNrLHJldCk7CiAgLyogYWxsIHN5c3RlbXMgYXJlIG5vdyBnbyAqLwogfSBlbHNlIHsKICAvKiBjaGlsZCBwcm9jZXNzICovCiAgY2xvc2UocmVhZF9mZFswXSk7IGNsb3NlKHdyaXRlX2ZkWzFdKTsKICAvKiBwdXQgb3VyIHBpcGVzIHNvbWV3aGVyZSBkb3Ntb2QgY2FuIGZpbmQgdGhlbSAqLwogIGR1cDIod3JpdGVfZmRbMF0sMCk7ICAgICAgLyogc3RkaW4gKi8KICBkdXAyKHJlYWRfZmRbMV0sMSk7ICAgICAgIC8qIHN0ZG91dCAqLwogIC8qIGVuYWJsZSBzaWduYWxzICovCiAgU0lHTkFMX01hc2tBc3luY0V2ZW50cyhGQUxTRSk7CiAgLyogbm93IGxvYWQgZG9zbW9kICovCiAgZXhlY2xwKCJkb3Ntb2QiLGZuYW1lLGZhcmcsTlVMTCk7CiAgZXhlY2woImRvc21vZCIsZm5hbWUsZmFyZyxOVUxMKTsKICAvKiBobW0sIHRoZXkgZGlkbid0IGluc3RhbGwgcHJvcGVybHkgKi8KICBleGVjbCgibG9hZGVyL2Rvcy9kb3Ntb2QiLGZuYW1lLGZhcmcsTlVMTCk7CiAgLyogbGFzdCByZXNvcnQsIHRyeSB0byBmaW5kIGl0IHRocm91Z2ggYXJndlswXSAqLwogIGZwYXRoPXN0cnJjaHIoc3RyY3B5KHBhdGgsT3B0aW9ucy5hcmd2MCksJy8nKTsKICBpZiAoZnBhdGgpIHsKICAgc3RyY3B5KGZwYXRoLCIvbG9hZGVyL2Rvcy9kb3Ntb2QiKTsKICAgZXhlY2wocGF0aCxmbmFtZSxmYXJnLE5VTEwpOwogIH0KICAvKiBpZiBmYWlsdXJlLCBleGl0ICovCiAgRVJSKG1vZHVsZSwiRmFpbGVkIHRvIHNwYXduIGRvc21vZCwgZXJyb3I9JXNcbiIsc3RyZXJyb3IoZXJybm8pKTsKICBleGl0KDEpOwogfQogcmV0dXJuIFRSVUU7Cn0KCkJPT0wgTVpfQ3JlYXRlUHJvY2VzcyggSEZJTEUgaEZpbGUsIE9GU1RSVUNUICpvZnMsIExQQ1NUUiBjbWRsaW5lLCBMUENTVFIgZW52LCAKICAgICAgICAgICAgICAgICAgICAgICBMUFNFQ1VSSVRZX0FUVFJJQlVURVMgcHNhLCBMUFNFQ1VSSVRZX0FUVFJJQlVURVMgdHNhLAogICAgICAgICAgICAgICAgICAgICAgIEJPT0wgaW5oZXJpdCwgTFBTVEFSVFVQSU5GT0Egc3RhcnR1cCwgCiAgICAgICAgICAgICAgICAgICAgICAgTFBQUk9DRVNTX0lORk9STUFUSU9OIGluZm8gKQp7CiBMUERPU1RBU0sgbHBEb3NUYXNrID0gTlVMTDsgLyoga2VlcCBnY2MgZnJvbSBjb21wbGFpbmluZyAqLwogSE1PRFVMRTE2IGhNb2R1bGU7CiBQREIgKnBkYiA9IFBST0NFU1NfQ3VycmVudCgpOwogVERCICpwVGFzayA9IChUREIqKUdsb2JhbExvY2sxNiggR2V0Q3VycmVudFRhc2soKSApOwogTkVfTU9EVUxFICpwTW9kdWxlID0gcFRhc2sgPyBORV9HZXRQdHIoIHBUYXNrLT5oTW9kdWxlICkgOiBOVUxMOwogaW50IGFsbG9jID0gIShwTW9kdWxlICYmIHBNb2R1bGUtPmRvc19pbWFnZSk7CgogaWYgKGFsbG9jICYmIChscERvc1Rhc2sgPSBjYWxsb2MoMSwgc2l6ZW9mKERPU1RBU0spKSkgPT0gTlVMTCkgewogIFNldExhc3RFcnJvcihFUlJPUl9OT1RfRU5PVUdIX01FTU9SWSk7CiAgcmV0dXJuIEZBTFNFOwogfQoKIGlmICgoIWVudikmJnBkYikgZW52ID0gcGRiLT5lbnZfZGItPmVudmlyb247CiBpZiAoYWxsb2MpIHsKICBpZiAoKGhNb2R1bGUgPSBNT0RVTEVfQ3JlYXRlRHVtbXlNb2R1bGUob2ZzLCBOVUxMKSkgPCAzMikgewogICBTZXRMYXN0RXJyb3IoaE1vZHVsZSk7CiAgIHJldHVybiBGQUxTRTsKICB9CiAgbHBEb3NUYXNrLT5oTW9kdWxlID0gaE1vZHVsZTsKCiAgcE1vZHVsZSA9IChORV9NT0RVTEUgKilHbG9iYWxMb2NrMTYoaE1vZHVsZSk7CiAgcE1vZHVsZS0+bHBEb3NUYXNrID0gbHBEb3NUYXNrOwogCiAgbHBEb3NUYXNrLT5pbWc9TlVMTDsgbHBEb3NUYXNrLT5tbV9uYW1lWzBdPTA7IGxwRG9zVGFzay0+bW1fZmQ9LTE7CiB9IGVsc2UgbHBEb3NUYXNrPXBNb2R1bGUtPmxwRG9zVGFzazsKIGlmICghTVpfTG9hZEltYWdlKCBoRmlsZSwgb2ZzLCBjbWRsaW5lLCBlbnYsIGxwRG9zVGFzaywgcE1vZHVsZSApKSB7CiAgaWYgKGFsbG9jKSB7CiAgIGlmIChscERvc1Rhc2stPm1tX25hbWVbMF0hPTApIHsKICAgIGlmIChscERvc1Rhc2stPmltZyE9TlVMTCkgbXVubWFwKGxwRG9zVGFzay0+aW1nLDB4MTEwMDAwLVNUQVJUX09GRlNFVCk7CiAgICBpZiAobHBEb3NUYXNrLT5tbV9mZD49MCkgY2xvc2UobHBEb3NUYXNrLT5tbV9mZCk7CiAgICB1bmxpbmsobHBEb3NUYXNrLT5tbV9uYW1lKTsKICAgfSBlbHNlCiAgICBpZiAobHBEb3NUYXNrLT5pbWchPU5VTEwpIFZpcnR1YWxGcmVlKGxwRG9zVGFzay0+aW1nLDB4MTEwMDAwLE1FTV9SRUxFQVNFKTsKICB9CiAgcmV0dXJuIEZBTFNFOwogfQogaWYgKGFsbG9jKSB7CiAgcE1vZHVsZS0+ZG9zX2ltYWdlID0gbHBEb3NUYXNrLT5pbWc7CiAgaWYgKCFNWl9Jbml0VGFzayggbHBEb3NUYXNrICkpIHsKICAgTVpfS2lsbE1vZHVsZSggbHBEb3NUYXNrICk7CiAgIC8qIEZJWE1FOiBjbGVhbnVwIGhNb2R1bGUgKi8KICAgU2V0TGFzdEVycm9yKEVSUk9SX0dFTl9GQUlMVVJFKTsKICAgcmV0dXJuIEZBTFNFOwogIH0KICBpZiAoIVBST0NFU1NfQ3JlYXRlKCBwTW9kdWxlLCBjbWRsaW5lLCBlbnYsIDAsIDAsIAogICAgICAgICAgICAgICAgICAgICAgIHBzYSwgdHNhLCBpbmhlcml0LCBzdGFydHVwLCBpbmZvICkpCiAgIHJldHVybiBGQUxTRTsKIH0KIHJldHVybiBUUlVFOwp9Cgp2b2lkIE1aX0tpbGxNb2R1bGUoIExQRE9TVEFTSyBscERvc1Rhc2sgKQp7CiBUUkFDRShtb2R1bGUsImtpbGxpbmcgRE9TIHRhc2tcbiIpOwojaWYgMAogU1lTVEVNX0tpbGxTeXN0ZW1UaW1lcihscERvc1Rhc2stPnN5c3RlbV90aW1lcik7CiNlbmRpZgogaWYgKGxwRG9zVGFzay0+bW1fbmFtZVswXSE9MCkgewogIG11bm1hcChscERvc1Rhc2stPmltZywweDExMDAwMC1TVEFSVF9PRkZTRVQpOwogIGNsb3NlKGxwRG9zVGFzay0+bW1fZmQpOwogfSBlbHNlIFZpcnR1YWxGcmVlKGxwRG9zVGFzay0+aW1nLDB4MTEwMDAwLE1FTV9SRUxFQVNFKTsKIGNsb3NlKGxwRG9zVGFzay0+cmVhZF9waXBlKTsKIGNsb3NlKGxwRG9zVGFzay0+d3JpdGVfcGlwZSk7CiBraWxsKGxwRG9zVGFzay0+dGFzayxTSUdURVJNKTsKI2lmIDAKIC8qIEZJWE1FOiB0aGlzIHNlZW1zIHRvIGNyYXNoICovCiBpZiAobHBEb3NUYXNrLT5kcG1pX3NlbCkKICBVbk1hcExTKFBUUl9TRUdfT0ZGX1RPX1NFR1BUUihscERvc1Rhc2stPmRwbWlfc2VsLDApKTsKI2VuZGlmCn0KCiNlbHNlIC8qICFNWl9TVVBQT1JURUQgKi8KCkJPT0wgTVpfQ3JlYXRlUHJvY2VzcyggSEZJTEUgaEZpbGUsIE9GU1RSVUNUICpvZnMsIExQQ1NUUiBjbWRsaW5lLCBMUENTVFIgZW52LCAKICAgICAgICAgICAgICAgICAgICAgICBMUFNFQ1VSSVRZX0FUVFJJQlVURVMgcHNhLCBMUFNFQ1VSSVRZX0FUVFJJQlVURVMgdHNhLAogICAgICAgICAgICAgICAgICAgICAgIEJPT0wgaW5oZXJpdCwgTFBTVEFSVFVQSU5GT0Egc3RhcnR1cCwgCiAgICAgICAgICAgICAgICAgICAgICAgTFBQUk9DRVNTX0lORk9STUFUSU9OIGluZm8gKQp7CiBXQVJOKG1vZHVsZSwiRE9TIGV4ZWN1dGFibGVzIG5vdCBzdXBwb3J0ZWQgb24gdGhpcyBhcmNoaXRlY3R1cmVcbiIpOwogU2V0TGFzdEVycm9yKEVSUk9SX0JBRF9GT1JNQVQpOwogcmV0dXJuIEZBTFNFOwp9CgojZW5kaWYK