LyogQ29weXJpZ2h0IChjKSAyMDEzLCBUaGUgTGludXggRm91bmRhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KICoKICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0CiAqIG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUKICogbWV0OgogKiAgICAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodAogKiAgICAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCiAqICAgICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUKICogICAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcKICogICAgICAgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkCiAqICAgICAgIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KICogICAgICogTmVpdGhlciB0aGUgbmFtZSBvZiBUaGUgTGludXggRm91bmRhdGlvbiBub3IgdGhlIG5hbWVzIG9mIGl0cwogKiAgICAgICBjb250cmlidXRvcnMgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQKICogICAgICAgZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLgogKgogKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQKICogV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVMgT0YKICogTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OLUlORlJJTkdFTUVOVAogKiBBUkUgRElTQ0xBSU1FRC4gIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgT1dORVIgT1IgQ09OVFJJQlVUT1JTCiAqIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IKICogQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YKICogU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SCiAqIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLAogKiBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRQogKiBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLCBFVkVOCiAqIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLgogKi8KCiNpbmNsdWRlIDxkZWJ1Zy5oPgojaW5jbHVkZSA8cmVnLmg+CiNpbmNsdWRlIDxtYWxsb2MuaD4KI2luY2x1ZGUgPHFnaWMuaD4KI2luY2x1ZGUgPHVmc19ody5oPgojaW5jbHVkZSA8dWZzX2hjaS5oPgojaW5jbHVkZSA8dWljLmg+CiNpbmNsdWRlIDxkbWUuaD4KI2luY2x1ZGUgPHBsYXRmb3JtL2lvbWFwLmg+CiNpbmNsdWRlIDxwbGF0Zm9ybS9pbnRlcnJ1cHRzLmg+CiNpbmNsdWRlIDxwbGF0Zm9ybS9jbG9jay5oPgojaW5jbHVkZSA8cGxhdGZvcm0vdGltZXIuaD4KCnN0YXRpYyBpbnQgdWljX2NoZWNrX2hjaV91Y3JkeShzdHJ1Y3QgdWZzX2RldiAqZGV2KQp7Cgl1aW50MzJfdCByZXQgPSAwOwoKCS8qIENoZWNrIGlmIHRoZSBIQ1MuVUNSRFkgaXMgc2V0IHRvIJExki4gKi8KCWlmICh1ZnNfcmVnX3RhcmdldF92YWxfdGltZW91dF9sb29wKFVGU19IQ1MoZGV2LT5iYXNlKSwgVUZTX0hDU19VQ1JEWSwgSENJX1VJQ19USU1FT1VUKSkKCXsKCQlyZXQgPSAtVUlDX0VSUl9USU1FT1VUOwoJfQoKCXJldHVybiByZXQ7Cn0KCnN0YXRpYyB2b2lkIHVpY19jbWRfc2V0dXBfYXJncyhzdHJ1Y3QgdWZzX2RldiAqZGV2LCBzdHJ1Y3QgdWljX2NtZCAqY21kKQp7CglpZiAoY21kLT5udW1fYXJncyAmIFVJQ0NNRF9PTkVfQVJHUykKCQl3cml0ZWwoY21kLT51aWNjbWRhcmcxLCBVRlNfVUlDQ01EQVJHMShkZXYtPmJhc2UpKTsKCglpZiAoY21kLT5udW1fYXJncyAmIFVJQ0NNRF9UV09fQVJHUykKCQl3cml0ZWwoY21kLT51aWNjbWRhcmcyLCBVRlNfVUlDQ01EQVJHMihkZXYtPmJhc2UpKTsKCglpZiAoY21kLT5udW1fYXJncyAmIFVJQ0NNRF9USFJFRV9BUkdTKQoJCXdyaXRlbChjbWQtPnVpY2NtZGFyZzMsIFVGU19VSUNDTURBUkczKGRldi0+YmFzZSkpOwp9CgpzdGF0aWMgdm9pZCB1aWNfY21kX3NhdmVfcmVzdWx0KHN0cnVjdCB1ZnNfZGV2ICpkZXYsIHN0cnVjdCB1aWNfY21kICpjbWQpCnsKCS8qIFNhdmUgY21kIGFyZyAyIGFuZCAzIGZvciB1c2Ugb2YgdGhlIGNvbW1hbmRzIHRoYXQgcmVxdWlyZSBpdC4gKi8KCWNtZC0+dWljY21kYXJnMyA9IHJlYWRsKFVGU19VSUNDTURBUkczKGRldi0+YmFzZSkpOwoJY21kLT51aWNjbWRhcmcyID0gcmVhZGwoVUZTX1VJQ0NNREFSRzIoZGV2LT5iYXNlKSk7Cn0KCmludCB1aWNfc2VuZF9jbWQoc3RydWN0IHVmc19kZXYgKmRldiwgc3RydWN0IHVpY19jbWQgKmNtZCkKewoJdWludDMyX3QgdmFsOwoJaW50IHJldCA9IDA7CgoJcmV0ID0gbXV0ZXhfYWNxdWlyZSgmKGRldi0+dWljX2RhdGEudWljX211dGV4KSk7CglpZiAocmV0KQoJewoJCWRwcmludGYoQ1JJVElDQUwsICJNdXRleCBhY3F1aXJlIGZhaWxlZC5cbiIpOwoJCXJldCA9IC1VRlNfRkFJTFVSRTsKCQlnb3RvIHVpY19zZW5kX2NtZF9lcnI7Cgl9CgoJcmV0ID0gdWljX2NoZWNrX2hjaV91Y3JkeShkZXYpOwoJaWYgKHJldCkKCXsKCQlkcHJpbnRmKENSSVRJQ0FMLCAiQ2hlY2sgVUNSRFkgZmFpbGVkLlxuIik7CgkJcmV0ID0gLVVGU19GQUlMVVJFOwoJCWdvdG8gdWljX3NlbmRfY21kX2VycjsKCX0KCgkvKiBXcml0ZSBhcmd1bWVudHMsIGlmIGFueS4gKi8KCXVpY19jbWRfc2V0dXBfYXJncyhkZXYsIGNtZCk7CgoJZXZlbnRfaW5pdCgmKGRldi0+dWljX2RhdGEudWljX2V2ZW50KSwgZmFsc2UsIDApOwoKCS8qIEV4ZWN1dGUgdGhlIGNtZC4gKi8KCXdyaXRlbChjbWQtPnVpY2NtZCwgVUZTX1VJQ0NNRChkZXYtPmJhc2UpKTsKCglyZXQgPSBldmVudF93YWl0X3RpbWVvdXQoJihkZXYtPnVpY19kYXRhLnVpY19ldmVudCksIGNtZC0+dGltZW91dF9tc2Vjcyk7CglpZiAocmV0KQoJewoJCWRwcmludGYoQ1JJVElDQUwsICJFdmVudCB3YWl0IGZhaWxlZC5cbiIpOwoJCXJldCA9IC1VRlNfRkFJTFVSRTsKCQlnb3RvIHVpY19zZW5kX2NtZF9lcnI7Cgl9CgoJLyogU2F2ZSBSZXN1bHQuICovCgl1aWNfY21kX3NhdmVfcmVzdWx0KGRldiwgY21kKTsKCglyZXQgPSBtdXRleF9yZWxlYXNlKCYoZGV2LT51aWNfZGF0YS51aWNfbXV0ZXgpKTsKCWlmIChyZXQpCgl7CgkJZHByaW50ZihDUklUSUNBTCwgIk11dGV4IHJlbGVhc2UgZmFpbGVkLlxuIik7CgkJcmV0ID0gLVVGU19GQUlMVVJFOwoJCWdvdG8gdWljX3NlbmRfY21kX2VycjsKCX0KCgl2YWwgPSBjbWQtPnVpY2NtZGFyZzI7CgkvKiBSZWFkIGdlbmVyaWMgZXJyb3IgY29kZSBmb3IgdGhlIFVJQyBjb21tYW5kLiAqLwoJY21kLT5nZW5fZXJyX2NvZGUgPSB2YWwgJiAweEZGOwoKCXJldHVybiByZXQ7Cgp1aWNfc2VuZF9jbWRfZXJyOgoJZHByaW50ZihDUklUSUNBTCwgIkZhaWxlZCB0byBzZW5kIHRoZSBVSUMgY21kLlxuIik7CglyZXR1cm4gcmV0Owp9CgpzdGF0aWMgaW50IHVpY19zdGFydF9saW5rKHN0cnVjdCB1ZnNfZGV2ICpkZXYpCnsKCXVpbnQzMl90IHRyeV9hZ2FpbiA9IDEwOwoJaW50ICAgICAgcmV0OwoKCWRvCgl7CgkJdHJ5X2FnYWluLS07CgoJCS8qIFNlbmQgRE1FX0xJTktTVEFSVFVQIGNvbW1hbmQgdG8gc3RhcnQgdGhlIGxpbmsgc3RhcnR1cCBwcm9jZWR1cmUgKi8KCQlyZXQgPSBkbWVfc2VuZF9saW5rc3RhcnR1cF9yZXEoZGV2KTsKCQlpZiAocmV0KQoJCXsKCQkJZHByaW50ZihDUklUSUNBTCwgIkRNRSBMSU5LU1RBUlRVUCBmYWlsZWQuXG4iKTsKCQkJZ290byB1aWNfc3RhcnRfbGlua19lcnI7CgkJfQoKCQkvKiBDaGVjayB2YWx1ZSBvZiBIQ1MuRFAgYW5kIG1ha2Ugc3VyZSB0aGF0IHRoZXJlIGlzIGEgZGV2aWNlIGF0dGFjaGVkIHRvIHRoZSBMaW5rICovCgkJaWYgKCEocmVhZGwoVUZTX0hDUyhkZXYtPmJhc2UpKSAmIFVGU19IQ1NfRFApKQoJCXsKCQkJbWRlbGF5KDEwMDApOwoKCQkJaWYgKCEocmVhZGwoVUZTX0lFKGRldi0+YmFzZSkpICYgQklUKDcpKSkKCQkJCWdvdG8gdWljX3N0YXJ0X2xpbmtfZXJyOwoJCX0KCQllbHNlCgkJCWJyZWFrOwoJfSB3aGlsZSAodHJ5X2FnYWluKTsKCWlmICghdHJ5X2FnYWluKQoJCXJldCA9IC1VRlNfRkFJTFVSRTsKCnVpY19zdGFydF9saW5rX2VycjoKCXJldHVybiByZXQ7Cn0KCmludCB1aWNfaW5pdChzdHJ1Y3QgdWZzX2RldiAqZGV2KQp7CglpZiAoIShyZWFkbChVRlNfSENFKGRldi0+YmFzZSkpICYgVUZTX0hDRV9FTkFCTEUpKQoJewoJCWRwcmludGYoQ1JJVElDQUwsICJVRlMgbGluayBpcyBub3QgaW5pdGlhbGl6ZWQuXG4iKTsKCQlyZXR1cm4gLVVGU19GQUlMVVJFOwoJfQoKDQlyZXR1cm4gVUZTX1NVQ0NFU1M7Cn0KCg==