LyogQ29weXJpZ2h0IChjKSAyMDEzLCBUaGUgTGludXggRm91bmRhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KICoKICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0CiAqIG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUKICogbWV0OgogKiAgICAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodAogKiAgICAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCiAqICAgICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUKICogICAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcKICogICAgICAgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkCiAqICAgICAgIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KICogICAgICogTmVpdGhlciB0aGUgbmFtZSBvZiBUaGUgTGludXggRm91bmRhdGlvbiBub3IgdGhlIG5hbWVzIG9mIGl0cwogKiAgICAgICBjb250cmlidXRvcnMgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQKICogICAgICAgZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLgogKgogKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQKICogV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVMgT0YKICogTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OLUlORlJJTkdFTUVOVAogKiBBUkUgRElTQ0xBSU1FRC4gIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgT1dORVIgT1IgQ09OVFJJQlVUT1JTCiAqIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IKICogQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YKICogU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SCiAqIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLAogKiBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRQogKiBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLCBFVkVOCiAqIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLgogKi8KCiNpbmNsdWRlIDxkZWJ1Zy5oPgojaW5jbHVkZSA8cmVnLmg+CiNpbmNsdWRlIDxtYWxsb2MuaD4KI2luY2x1ZGUgPHFnaWMuaD4KI2luY2x1ZGUgPHVmc19ody5oPgojaW5jbHVkZSA8dWZzX2hjaS5oPgojaW5jbHVkZSA8dWljLmg+CiNpbmNsdWRlIDxkbWUuaD4KI2luY2x1ZGUgPHBsYXRmb3JtL2lvbWFwLmg+CiNpbmNsdWRlIDxwbGF0Zm9ybS9pbnRlcnJ1cHRzLmg+CiNpbmNsdWRlIDxwbGF0Zm9ybS9jbG9jay5oPgojaW5jbHVkZSA8cGxhdGZvcm0vdGltZXIuaD4KCnN0YXRpYyBpbnQgdWljX2NoZWNrX2hjaV91Y3JkeShzdHJ1Y3QgdWZzX2RldiAqZGV2KQp7Cgl1aW50MzJfdCByZXQ7CgoJLyogQ2hlY2sgaWYgdGhlIEhDUy5VQ1JEWSBpcyBzZXQgdG8gkTGSLiAqLwoJaWYgKHVmc19yZWdfdGFyZ2V0X3ZhbF90aW1lb3V0X2xvb3AoVUZTX0hDUyhkZXYtPmJhc2UpLCBVRlNfSENTX1VDUkRZLCBIQ0lfVUlDX1RJTUVPVVQpKQoJewoJCXJldCA9IC1VSUNfRVJSX1RJTUVPVVQ7Cgl9CgoJcmV0dXJuIHJldDsKfQoKc3RhdGljIHZvaWQgdWljX2NtZF9zZXR1cF9hcmdzKHN0cnVjdCB1ZnNfZGV2ICpkZXYsIHN0cnVjdCB1aWNfY21kICpjbWQpCnsKCWlmIChjbWQtPm51bV9hcmdzICYgVUlDQ01EX09ORV9BUkdTKQoJCXdyaXRlbChjbWQtPnVpY2NtZGFyZzEsIFVGU19VSUNDTURBUkcxKGRldi0+YmFzZSkpOwoKCWlmIChjbWQtPm51bV9hcmdzICYgVUlDQ01EX1RXT19BUkdTKQoJCXdyaXRlbChjbWQtPnVpY2NtZGFyZzIsIFVGU19VSUNDTURBUkcyKGRldi0+YmFzZSkpOwoKCWlmIChjbWQtPm51bV9hcmdzICYgVUlDQ01EX1RIUkVFX0FSR1MpCgkJd3JpdGVsKGNtZC0+dWljY21kYXJnMywgVUZTX1VJQ0NNREFSRzMoZGV2LT5iYXNlKSk7Cn0KCnN0YXRpYyB2b2lkIHVpY19jbWRfc2F2ZV9yZXN1bHQoc3RydWN0IHVmc19kZXYgKmRldiwgc3RydWN0IHVpY19jbWQgKmNtZCkKewoJLyogU2F2ZSBjbWQgYXJnIDIgYW5kIDMgZm9yIHVzZSBvZiB0aGUgY29tbWFuZHMgdGhhdCByZXF1aXJlIGl0LiAqLwoJY21kLT51aWNjbWRhcmczID0gcmVhZGwoVUZTX1VJQ0NNREFSRzMoZGV2LT5iYXNlKSk7CgljbWQtPnVpY2NtZGFyZzIgPSByZWFkbChVRlNfVUlDQ01EQVJHMihkZXYtPmJhc2UpKTsKfQoKaW50IHVpY19zZW5kX2NtZChzdHJ1Y3QgdWZzX2RldiAqZGV2LCBzdHJ1Y3QgdWljX2NtZCAqY21kKQp7Cgl1aW50MzJfdCB2YWw7CglpbnQgcmV0ID0gMDsKCglyZXQgPSBtdXRleF9hY3F1aXJlKCYoZGV2LT51aWNfZGF0YS51aWNfbXV0ZXgpKTsKCWlmIChyZXQpCgl7CgkJZHByaW50ZihDUklUSUNBTCwgIk11dGV4IGFjcXVpcmUgZmFpbGVkLlxuIik7CgkJcmV0ID0gLVVGU19GQUlMVVJFOwoJCWdvdG8gdWljX3NlbmRfY21kX2VycjsKCX0KCglyZXQgPSB1aWNfY2hlY2tfaGNpX3VjcmR5KGRldik7CglpZiAocmV0KQoJewoJCWRwcmludGYoQ1JJVElDQUwsICJDaGVjayBVQ1JEWSBmYWlsZWQuXG4iKTsKCQlyZXQgPSAtVUZTX0ZBSUxVUkU7CgkJZ290byB1aWNfc2VuZF9jbWRfZXJyOwoJfQoKCS8qIFdyaXRlIGFyZ3VtZW50cywgaWYgYW55LiAqLwoJdWljX2NtZF9zZXR1cF9hcmdzKGRldiwgY21kKTsKCglldmVudF9pbml0KCYoZGV2LT51aWNfZGF0YS51aWNfZXZlbnQpLCBmYWxzZSwgMCk7CgoJLyogRXhlY3V0ZSB0aGUgY21kLiAqLwoJd3JpdGVsKGNtZC0+dWljY21kLCBVRlNfVUlDQ01EKGRldi0+YmFzZSkpOwoKCXJldCA9IGV2ZW50X3dhaXRfdGltZW91dCgmKGRldi0+dWljX2RhdGEudWljX2V2ZW50KSwgY21kLT50aW1lb3V0X21zZWNzKTsKCWlmIChyZXQpCgl7CgkJZHByaW50ZihDUklUSUNBTCwgIkV2ZW50IHdhaXQgZmFpbGVkLlxuIik7CgkJcmV0ID0gLVVGU19GQUlMVVJFOwoJCWdvdG8gdWljX3NlbmRfY21kX2VycjsKCX0KCgkvKiBTYXZlIFJlc3VsdC4gKi8KCXVpY19jbWRfc2F2ZV9yZXN1bHQoZGV2LCBjbWQpOwoKCXJldCA9IG11dGV4X3JlbGVhc2UoJihkZXYtPnVpY19kYXRhLnVpY19tdXRleCkpOwoJaWYgKHJldCkKCXsKCQlkcHJpbnRmKENSSVRJQ0FMLCAiTXV0ZXggcmVsZWFzZSBmYWlsZWQuXG4iKTsKCQlyZXQgPSAtVUZTX0ZBSUxVUkU7CgkJZ290byB1aWNfc2VuZF9jbWRfZXJyOwoJfQoKCXZhbCA9IGNtZC0+dWljY21kYXJnMjsKCS8qIFJlYWQgZ2VuZXJpYyBlcnJvciBjb2RlIGZvciB0aGUgVUlDIGNvbW1hbmQuICovCgljbWQtPmdlbl9lcnJfY29kZSA9IHZhbCAmIDB4RkY7CgoJcmV0dXJuIHJldDsKCnVpY19zZW5kX2NtZF9lcnI6CglkcHJpbnRmKENSSVRJQ0FMLCAiRmFpbGVkIHRvIHNlbmQgdGhlIFVJQyBjbWQuXG4iKTsKCXJldHVybiByZXQ7Cn0KCnN0YXRpYyBpbnQgdWljX3N0YXJ0X2xpbmsoc3RydWN0IHVmc19kZXYgKmRldikKewoJdWludDMyX3QgdHJ5X2FnYWluID0gMTA7CglpbnQgICAgICByZXQ7CgoJZG8KCXsKCQl0cnlfYWdhaW4tLTsKCgkJLyogU2VuZCBETUVfTElOS1NUQVJUVVAgY29tbWFuZCB0byBzdGFydCB0aGUgbGluayBzdGFydHVwIHByb2NlZHVyZSAqLwoJCXJldCA9IGRtZV9zZW5kX2xpbmtzdGFydHVwX3JlcShkZXYpOwoJCWlmIChyZXQpCgkJewoJCQlkcHJpbnRmKENSSVRJQ0FMLCAiRE1FIExJTktTVEFSVFVQIGZhaWxlZC5cbiIpOwoJCQlnb3RvIHVpY19zdGFydF9saW5rX2VycjsKCQl9CgoJCS8qIENoZWNrIHZhbHVlIG9mIEhDUy5EUCBhbmQgbWFrZSBzdXJlIHRoYXQgdGhlcmUgaXMgYSBkZXZpY2UgYXR0YWNoZWQgdG8gdGhlIExpbmsgKi8KCQlpZiAoIShyZWFkbChVRlNfSENTKGRldi0+YmFzZSkpICYgVUZTX0hDU19EUCkpCgkJewoJCQltZGVsYXkoMTAwMCk7CgoJCQlpZiAoIShyZWFkbChVRlNfSUUoZGV2LT5iYXNlKSkgJiBCSVQoNykpKQoJCQkJZ290byB1aWNfc3RhcnRfbGlua19lcnI7CgkJfQoJCWVsc2UKCQkJYnJlYWs7Cgl9IHdoaWxlICh0cnlfYWdhaW4pOwoJaWYgKCF0cnlfYWdhaW4pCgkJcmV0ID0gLVVGU19GQUlMVVJFOwoKdWljX3N0YXJ0X2xpbmtfZXJyOgoJcmV0dXJuIHJldDsKfQoKaW50IHVpY19pbml0KHN0cnVjdCB1ZnNfZGV2ICpkZXYpCnsKCWlmICghKHJlYWRsKFVGU19IQ0UoZGV2LT5iYXNlKSkgJiBVRlNfSENFX0VOQUJMRSkpCgl7CgkJZHByaW50ZihDUklUSUNBTCwgIlVGUyBsaW5rIGlzIG5vdCBpbml0aWFsaXplZC5cbiIpOwoJCXJldHVybiAtVUZTX0ZBSUxVUkU7Cgl9CgoNCXJldHVybiBVRlNfU1VDQ0VTUzsKfQoK