LyogQ29weXJpZ2h0IChjKSAyMDEzLCBUaGUgTGludXggRm91bmRhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KICoKICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0CiAqIG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUKICogbWV0OgogKiAgICAgKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodAogKiAgICAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCiAqICAgICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUKICogICAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcKICogICAgICAgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkCiAqICAgICAgIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KICogICAgICogTmVpdGhlciB0aGUgbmFtZSBvZiBUaGUgTGludXggRm91bmRhdGlvbiBub3IgdGhlIG5hbWVzIG9mIGl0cwogKiAgICAgICBjb250cmlidXRvcnMgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQKICogICAgICAgZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLgogKgogKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQKICogV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVMgT0YKICogTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OLUlORlJJTkdFTUVOVAogKiBBUkUgRElTQ0xBSU1FRC4gIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgT1dORVIgT1IgQ09OVFJJQlVUT1JTCiAqIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IKICogQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YKICogU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SCiAqIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLAogKiBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRQogKiBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLCBFVkVOCiAqIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLgogKi8KCiNpbmNsdWRlIDxhcmNoL29wcy5oPgojaW5jbHVkZSA8c3lzL3R5cGVzLmg+CiNpbmNsdWRlIDxrZXJuZWwvdGhyZWFkLmg+CiNpbmNsdWRlIDxkZWJ1Zy5oPgojaW5jbHVkZSA8ZXJyLmg+CiNpbmNsdWRlIDxyZWcuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8bWFsbG9jLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHVmc19ody5oPgojaW5jbHVkZSA8dXRwLmg+CiNpbmNsdWRlIDxwbGF0Zm9ybS9pb21hcC5oPgojaW5jbHVkZSA8cGxhdGZvcm0vY2xvY2suaD4KI2luY2x1ZGUgPGFyY2gvb3BzLmg+CiNpbmNsdWRlIDxlbmRpYW4uaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3lzL3R5cGVzLmg+Cgp2b2lkIHV0cF9wcm9jZXNzX3JlcV9jb21wbGV0aW9uKHN0cnVjdCB1ZnNfcmVxX2lycV90eXBlICppcnEpCnsKCXN0cnVjdCB1ZnNfcmVxX25vZGUgKnJlcTsKCXN0cnVjdCBsaXN0X25vZGUgICAgKnByZXY7Cgl1aW50MzJfdCAgICAgICAgICAgIHZhbDsKCgkvKiBNYWtlIHN1cmUgd2UgaGF2ZSBtb3JlIG5vZGVzIHRoYW4ganVzdCB0aGUgaGVhZCBpbiB0aGUgbGlzdC4gKi8KCWlmIChsaXN0X25leHQoaXJxLT5saXN0LCBpcnEtPmxpc3QpID09IE5VTEwpCgl7CgkJZHByaW50ZihDUklUSUNBTCwgIlVUUkQvIFVUTVJEIHByb2Nlc3NlZCBzaWduYWxsZWQgYW5kIHRoZSB3YWl0IHF1ZXVlIGlzIGVtcHR5XG4iKTsKCQlBU1NFUlQoMCk7Cgl9CgoJLyogUmVhZCB0aGUgZG9vciBiZWxsIHJlZ2lzdGVyLiAqLwoJdmFsID0gcmVhZGwoaXJxLT5kb29yX2JlbGxfcmVnKTsKCglsaXN0X2Zvcl9ldmVyeV9lbnRyeShpcnEtPmxpc3QsIHJlcSwgc3RydWN0IHVmc19yZXFfbm9kZSwgbGlzdF9ub2RlKQoJewoJCWlmICghKHJlcS0+ZG9vcl9iZWxsX2JpdCAmIHZhbCkpCgkJewoJCQkvKiBUcmFuc2FjdGlvbiBpcyBjb21wbGV0ZTogRWl0aGVyIHRyYW5zYWN0aW9uIGNvbXBsZXRlZCBpbiBhIG5vcm1hbCB3YXkuCgkJCSAqIERlbGV0ZSBhbmQgU2lnbmFsIGFsbCByZXF1ZXN0cyB0aGF0IGhhdmUgY29tcGxldGVkLgoJCQkgKi8KCQkJcHJldiA9IHJlcS0+bGlzdF9ub2RlLnByZXY7CgkJCS8qIFRPRE86IG1vdmUgZGVsZXRlIHRvIHRoZSBjYWxsZXIgZnVuY3Rpb24uICovCgkJCWxpc3RfZGVsZXRlKCYocmVxLT5saXN0X25vZGUpKTsKCgkJCWlmIChldmVudF9zaWduYWwocmVxLT5ldmVudCwgZmFsc2UpKQoJCQl7CgkJCQlkcHJpbnRmKENSSVRJQ0FMLCAiRXZlbnQgc2lnbmFsIGZhaWxlZC5cbiIpOwoJCQkJQVNTRVJUKDApOwoKCQkJfQoJCQlyZXEgPSBjb250YWluZXJvZihwcmV2LCBzdHJ1Y3QgdWZzX3JlcV9ub2RlLCBsaXN0X25vZGUpOwoJCX0KCX0KCglyZXR1cm47Cn0KCi8qIEFsd2F5cyBjYWxsZWQgd2l0aGluIGNyaXRpY2FsIHNlY3Rpb246IHV0cmRfYml0bWFwX211dGV4LyB1dG1yZF9iaXRtYXBfbXV0ZXguICovCnN0YXRpYyB1aW50MzJfdCB1dHBfZ2V0X2Rvb3JfYmVsbF9iaXQodWludDMyX3QgcmVnLCB1aW50MzJfdCAqcmVnX2JpdG1hcCwgdWludDMyX3QgKmJpdF9udW0pCnsKCXVpbnQzMl90IHZhbCA9IDA7Cgl1aW50MzJfdCBkb29yYmVsbF9iaXRfdmFsOwoJdWludDMyX3QgZm91bmQgPSAwOwoKCSpiaXRfbnVtID0gMDsKCgl2YWwgPSByZWFkbChyZWcpIHwgKnJlZ19iaXRtYXA7Cglkb29yYmVsbF9iaXRfdmFsID0gMTsKCgkvKiBGaW5kIGFuIGVtcHR5IHNsb3QuICovCglkbwoJewoJCSgqYml0X251bSkrKzsKCgkJaWYgKCEoZG9vcmJlbGxfYml0X3ZhbCAmIHZhbCkpCgkJewoJCQlmb3VuZCA9IDE7CgkJCSpyZWdfYml0bWFwIHw9IGRvb3JiZWxsX2JpdF92YWw7CgkJCWJyZWFrOwoJCX0KCQlkb29yYmVsbF9iaXRfdmFsIDw8PSAxOwoJfXdoaWxlIChkb29yYmVsbF9iaXRfdmFsIDw9ICh1aW50MzJfdCkgKDEgPDwgMzEpKTsKCglpZiAoIWZvdW5kKQoJewoJCS8qIFRPRE86IFRoaXMgY2FzZSBzaG91bGRkIHdhaXQgb24gYSBzZW1hcGhvcmUgaW5zdGVhZCBvZCByZXR1cm5pbmcgZXJyb3IuCgkJICogUmV0dXJuIGVycm9yIHVudGlsIExLIGFkZHMgc2VtYXBob3JlIHN1cHBvcnQuCgkJICovCgkJZG9vcmJlbGxfYml0X3ZhbCA9IDA7CgkJZHByaW50ZihDUklUSUNBTCwgIlVuYWJsZSB0byBmaW5kIGEgZnJlZSBzbG90IGZvciB0cmFuc2FjdGlvbi5cbiIpOwoJfQoKCXJldHVybiBkb29yYmVsbF9iaXRfdmFsOwp9CgpzdGF0aWMgdm9pZCB1dHBfcmluZ19kb29yX2JlbGwodWludDMyX3QgcmVnLCB1aW50MzJfdCBkb29yYmVsbF9iaXQpCnsKCXdyaXRlbChkb29yYmVsbF9iaXQsIHJlZyk7Cn0KCnN0YXRpYyBpbnQgdXRwX3V0cmRfcHJvY2Vzc190aW1lb3V0X3JlcShzdHJ1Y3QgdWZzX2RldiAqZGV2LAoJCQkJCQkJCSBzdHJ1Y3QgdXRwX3V0cmRfcmVxX2J1aWxkX3R5cGUgKnV0cmRfcmVxLAoJCQkJCQkJCSBzdHJ1Y3QgdWZzX3JlcV9ub2RlICpyZXEpCnsKCXN3aXRjaCAodXRyZF9yZXEtPnJlcV91cGl1LT50cmFuc190eXBlKQoJewoJCWNhc2UgVVBJVV9UWVBFX05PUF9PVVQ6CgkJCQkJCQkgICAgd3JpdGVsKH5yZXEtPmRvb3JfYmVsbF9iaXQsIFVGU19VVFJMQ0xSKGRldi0+YmFzZSkpOwoJCQkJCQkJCXJldHVybiAtVUZTX1JFVFJZOwoJCWRlZmF1bHQ6CgkJCQkJCQkJLyogVE9ETyA6IEFkZCB1ZnMgaGNpIHN3IHJlc2V0LiovCgkJCQkJCQkJQVNTRVJUKDApOwoJCQkJCQkJCXJldHVybiAtVUZTX0ZBSUxVUkU7Cgl9Cn0KCnN0YXRpYyBpbnQgdXRwX3JlbW92ZV9mcm9tX2JpdG1hcChzdHJ1Y3QgdXRwX2JpdG1hcF9hY2Nlc3NfdHlwZSAqcmVxKQp7CgoJaWYgKG11dGV4X2FjcXVpcmUocmVxLT5tdXR4KSkKCXsKCQlyZXR1cm4gLVVGU19GQUlMVVJFOwoJfQoKCSoocmVxLT5iaXRtYXApICY9IH5yZXEtPmRvb3JfYmVsbF9iaXQ7CgoJaWYgKG11dGV4X3JlbGVhc2UocmVxLT5tdXR4KSkKCXsKCQlyZXR1cm4gLVVGU19GQUlMVVJFOwoJfQoKCXJldHVybiBVRlNfU1VDQ0VTUzsKfQoKc3RhdGljIHZvaWQgdXRwX2VucXVldWVfdXRyZF9maWxsX2Rlc2Moc3RydWN0IHV0cF90cmFuc19yZXFfZGVzYyAqZGVzYywgc3RydWN0IHV0cF91dHJkX3JlcV9idWlsZF90eXBlICp1dHJkX3JlcSkKewoJLyogRmlsbCB0cmFuc2ZlciBkZXNjLiAqLwoJbWVtc2V0KGRlc2MsIDAsIFVQSVVfSERSX0xFTik7CglkZXNjLT5jbWRfdHlwZV9kZF9pcnEgPSBVVFBfUkVRX0JVSUxEX0NNRF9ERF9JUlFfRklFTEQodXRyZF9yZXEtPmNtZF90eXBlLCB1dHJkX3JlcS0+ZGQsIHV0cmRfcmVxLT5pcnEpOwoJZGVzYy0+b3ZlcmFsbF9jbWRfc3RhdHVzID0gdXRyZF9yZXEtPm9jczsKCS8qIEJpdHMgMCAtIDYgYXJlIHJlc2VydmVkIGluIGNtZF9kZXNjX2Jhc2VfYWRkclswXSBmaWVsZC4gKi8KCWRlc2MtPmNtZF9kZXNjX2Jhc2VfYWRkclswXSA9ICgodWludDMyX3QpIHV0cmRfcmVxLT5yZXFfdXBpdSkgJiAweEMwOwoJZGVzYy0+Y21kX2Rlc2NfYmFzZV9hZGRyWzFdID0gKCh1aW50MzJfdCkgdXRyZF9yZXEtPnJlcV91cGl1ID4+IDgpICYgMHhGRjsKCWRlc2MtPmNtZF9kZXNjX2Jhc2VfYWRkclsyXSA9ICgodWludDMyX3QpIHV0cmRfcmVxLT5yZXFfdXBpdSA+PiAxNikgJiAweEZGOwoJZGVzYy0+Y21kX2Rlc2NfYmFzZV9hZGRyWzNdID0gKCh1aW50MzJfdCkgdXRyZF9yZXEtPnJlcV91cGl1ID4+IDI0KSAmIDB4RkY7CglkZXNjLT5yZXNwX3VwaXVfb2Zmc2V0ID0gUk9VTkRVUCh1dHJkX3JlcS0+cmVxX3VwaXVfbGVuLCBVUElVX0hEUl9MRU4pIC8gNDsKCWRlc2MtPnJlc3BfdXBpdV9sZW4gPSB1dHJkX3JlcS0+cmVzcF91cGl1X2xlbjsKCglpZiAodXRyZF9yZXEtPmRkICE9IFVUUkRfTk9fREFUQV9UUkFOU0ZFUikKCXsKCQkvKiBEYXRhIHRyYW5zZmVyIGNvbW1hbmQuCgkJICogRmlsbCBpbiBQUkRUIGRhdGEuCgkJICovCgkJZGVzYy0+cHJkdF9vZmZzZXQgPSB1dHJkX3JlcS0+cHJkdF9vZmZzZXQgLyA0OwoJCWRlc2MtPnByZHRfbGVuICAgID0gdXRyZF9yZXEtPnByZHRfbGVuOwoJfQoKCS8qIEZsdXNoIFVUUkQgdG8gbWVtb3J5LiAqLwoJY2FjaGVfY2xlYW5faW52YWxpZGF0ZV91bmFsaWduZWRfc3RhcnRfYWRkcigoYWRkcl90KWRlc2MsIHNpemVvZihzdHJ1Y3QgdXRwX3RyYW5zX3JlcV9kZXNjKSk7Cn0KCnN0YXRpYyBzdHJ1Y3QgdXRwX3RyYW5zX3JlcV9kZXNjKiB1dHBfZ2V0X2Rlc2Nfc2xvdF9hZGRyKHN0cnVjdCB1ZnNfZGV2ICpkZXYsIHN0cnVjdCB1dHBfdXRyZF9yZXFfYnVpbGRfdHlwZSAqdXRyZF9yZXEsIHVpbnQzMl90ICpkb29yX2JlbGxfdmFsKQp7CglzdHJ1Y3QgdXRwX3RyYW5zX3JlcV9kZXNjICpkZXNjID0gTlVMTDsKCXVpbnQzMl90ICAgICAgICAgICAgICAgICAgZG9vcl9iZWxsX3Nsb3Q7CgoJaWYgKG11dGV4X2FjcXVpcmUoJihkZXYtPnV0cmRfZGF0YS5iaXRtYXBfbXV0ZXgpKSkKCXsKCQlnb3RvIHV0cF9nZXRfZGVzY19zbG90X2FkZHJfZXJyOwoJfQoKCSpkb29yX2JlbGxfdmFsID0gdXRwX2dldF9kb29yX2JlbGxfYml0KFVGU19VVFJMREJSKGRldi0+YmFzZSksICZkZXYtPnV0cmRfZGF0YS5iaXRtYXAsICZkb29yX2JlbGxfc2xvdCk7CglpZiAoISgqZG9vcl9iZWxsX3ZhbCkpCgl7CgkJZ290byB1dHBfZ2V0X2Rlc2Nfc2xvdF9hZGRyX2VycjsKCX0KCglpZiAobXV0ZXhfcmVsZWFzZSgmKGRldi0+dXRyZF9kYXRhLmJpdG1hcF9tdXRleCkpKQoJewoJCWdvdG8gdXRwX2dldF9kZXNjX3Nsb3RfYWRkcl9lcnI7Cgl9CgoJZGVzYyA9IChzdHJ1Y3QgdXRwX3RyYW5zX3JlcV9kZXNjICopICgoYWRkcl90KWRldi0+dXRyZF9kYXRhLmxpc3RfYmFzZV9hZGRyICsgKGRvb3JfYmVsbF9zbG90IC0gMSkgKiBzaXplb2Yoc3RydWN0IHV0cF90cmFuc19yZXFfZGVzYykpOwoKdXRwX2dldF9kZXNjX3Nsb3RfYWRkcl9lcnI6CglyZXR1cm4gZGVzYzsKfQoKc3RhdGljIGludCB1dHBfZW5xdWV1ZV91dHJkKHN0cnVjdCB1ZnNfZGV2ICpkZXYsIHN0cnVjdCB1dHBfdXRyZF9yZXFfYnVpbGRfdHlwZSAqdXRyZF9yZXEpCnsKCWludCAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldDsKCXN0cnVjdCB1dHBfdHJhbnNfcmVxX2Rlc2MgICAgICpkZXNjOwoJZXZlbnRfdCAgICAgICAgICAgICAgICAgICAgICAgdXRyZF9ldnQ7CglzdHJ1Y3QgdWZzX3JlcV9ub2RlICAgICAgICAgICByZXE7Cgl1aW50MzJfdCAgICAgICAgICAgICAgICAgICAgICBkb29yX2JlbGxfYml0X3ZhbDsKCXN0cnVjdCB1dHBfYml0bWFwX2FjY2Vzc190eXBlIGJpdG1hcF9yZXE7CgoJcmV0ID0gVUZTX1NVQ0NFU1M7CgoJZXZlbnRfaW5pdCgmdXRyZF9ldnQsIGZhbHNlLCBFVkVOVF9GTEFHX0FVVE9VTlNJR05BTCk7CgoJZGVzYyA9IHV0cF9nZXRfZGVzY19zbG90X2FkZHIoZGV2LCB1dHJkX3JlcSwgJmRvb3JfYmVsbF9iaXRfdmFsKTsKCWlmICghZGVzYykKCXsKCQlyZXQgPSBVRlNfRkFJTFVSRTsKCQlnb3RvIHV0cF9lbnF1ZXVlX3V0cmRfZXJyOwoJfQoKCS8qIENoZWNrIHJlZ2lzdGVyIFVUUkxSU1IgYW5kIG1ha2Ugc3VyZSBpdCBpcyByZWFkIJExkiBiZWZvcmUgY29udGludWluZy4gKi8KCWlmICghcmVhZGwoVUZTX1VUUkxSU1IoZGV2LT5iYXNlKSkpCgl7CgkJcmV0ID0gLVVGU19GQUlMVVJFOwoJCWdvdG8gdXRwX2VucXVldWVfdXRyZF9lcnI7Cgl9CgoJdXRwX2VucXVldWVfdXRyZF9maWxsX2Rlc2MoZGVzYywgdXRyZF9yZXEpOwoKCXJlcS5kb29yX2JlbGxfYml0ID0gZG9vcl9iZWxsX2JpdF92YWw7CglyZXEuZXZlbnQgICAgICAgICA9ICZ1dHJkX2V2dDsKCgkvKiBFbnF1ZXVlIHRoZSByZXEgaW4gdGhlIGRldmljZSB1dHJkIGxpc3QuICovCglsaXN0X2FkZF9oZWFkKCYoZGV2LT51dHJkX2RhdGEubGlzdF9oZWFkLmxpc3Rfbm9kZSksICYocmVxLmxpc3Rfbm9kZSkpOwoKCWRzYigpOwoKDQl1dHBfcmluZ19kb29yX2JlbGwoVUZTX1VUUkxEQlIoZGV2LT5iYXNlKSwgZG9vcl9iZWxsX2JpdF92YWwpOwoKCWRzYigpOwoKCS8qIFdhaXQgdGlsbCB0aGUgZGVzYyBoYXMgYmVlbiBwcm9jZXNzZWQuICovCglyZXQgPSBldmVudF93YWl0X3RpbWVvdXQoJnV0cmRfZXZ0LCB1dHJkX3JlcS0+dGltZW91dCk7CglpZiAocmV0KQoJewoJCWlmIChyZXQgPT0gRVJSX1RJTUVEX09VVCkKCQl7CgkJCS8qIFRyYW5zYWN0aW9uIG5vdCBjb21wbGV0ZWQgZXZlbiBhZnRlciB0aW1lb3V0IG1zLiAqLwoJCQlyZXQgPSB1dHBfdXRyZF9wcm9jZXNzX3RpbWVvdXRfcmVxKGRldiwgdXRyZF9yZXEsICZyZXEpOwoJCX0KCQllbHNlCgkJCXJldCA9IC1VRlNfRkFJTFVSRTsKCQlnb3RvIHV0cF9lbnF1ZXVlX3V0cmRfZXJyOwoJfQoJZWxzZQoJewoJCS8qIFJlc2V0IHJldCBiZWZvcmUgcmV0dXJuaW5nLiAqLwoJCXJldCA9IFVGU19TVUNDRVNTOwoKCQkvKiBGb3JjZSByZWFkIFVUUkQgZnJvbSBtZW1vcnkuICovCgkJZHNiKCk7CgkJY2FjaGVfY2xlYW5faW52YWxpZGF0ZV91bmFsaWduZWRfc3RhcnRfYWRkcigoYWRkcl90KSBkZXNjLCBzaXplb2Yoc3RydWN0IHVmc19yZXFfbm9kZSkpOwoKCQkvKiBDaGVjayB0aGUgcmVzcG9uc2UuICovCgkJaWYgKGRlc2MtPm92ZXJhbGxfY21kX3N0YXR1cyAhPSBVVFJEX09DU19TVUNDRVNTKQoJCXsKCQkJZHByaW50ZihDUklUSUNBTCwgIkNvbW1hbmQgZmFpbGVkLiBjb21tYW5kIHR5cGUgPSAleFxuIiwgdXRyZF9yZXEtPmNtZF90eXBlKTsKCQkJcmV0ID0gLVVGU19GQUlMVVJFOwoJCQlnb3RvIHV0cF9lbnF1ZXVlX3V0cmRfZXJyOwoJCX0KCX0KCgkvKiBTaWduYWwgc2xvdCBhcyBmcmVlLiAqLwoJYml0bWFwX3JlcS5iaXRtYXAgICAgICAgID0gJmRldi0+dXRyZF9kYXRhLmJpdG1hcDsKCWJpdG1hcF9yZXEuZG9vcl9iZWxsX2JpdCA9IHJlcS5kb29yX2JlbGxfYml0OwoJYml0bWFwX3JlcS5tdXR4ICAgICAgICAgID0gJihkZXYtPnV0cmRfZGF0YS5iaXRtYXBfbXV0ZXgpOwoKCXJldCA9IHV0cF9yZW1vdmVfZnJvbV9iaXRtYXAoJmJpdG1hcF9yZXEpOwoJaWYgKHJldCkKCQlnb3RvIHV0cF9lbnF1ZXVlX3V0cmRfZXJyOwoKdXRwX2VucXVldWVfdXRyZF9lcnI6CglyZXR1cm4gcmV0Owp9CgpzdGF0aWMgaW50IHV0cF9nZXRfcHJkdF9sZW4odWludDMyX3QgZGF0YV9sZW4sIHVpbnQzMl90ICpudW1fcHJkdCkKewoJLyogQ2FsY3VsYXRlIHRoZSBwcmR0IGVudHJpZXMgcmVxdWlyZWQuICovCgkqbnVtX3ByZHQgPSBST1VORFVQKGRhdGFfbGVuLCBVVFBfTUFYX1BSRF9EQVRBX0JZVEVfQ05UKTsKCSpudW1fcHJkdCA+Pj0gVVRQX01BWF9QUkRfREFUQV9CWVRFX0NOVF9CWVRFX1NISUZUOwoKCWlmICgqbnVtX3ByZHQgPiBVVFBfTUFYX1BSRF9UQUJMRV9FTlRSSUVTKQoJewoJCWRwcmludGYoQ1JJVElDQUwsICJEYXRhIGxlbmd0aCBleGNlZWRzIGZvciBhIHNpbmdsZSB1cGl1IHRyYW5zZmVyLlxuIik7CgkJcmV0dXJuIC1VRlNfRkFJTFVSRTsKCX0KCglyZXR1cm4gVUZTX1NVQ0NFU1M7Cn0KCnN0YXRpYyBpbnQgdXRwX2ZpbGxfcmVxX3VwaXUoc3RydWN0IHVmc19kZXYgKmRldiwgc3RydWN0IHVwaXVfcmVxX2J1aWxkX3R5cGUgKnVwaXVfZGF0YSwgc3RydWN0IHVwaXVfZ2VuX2hkciAqcmVxX3VwaXUpCnsKCW1lbXNldChyZXFfdXBpdSwgMCwgVVBJVV9IRFJfTEVOKTsKCglpZiAodXBpdV9kYXRhLT50cmFuc190eXBlID09IFVQSVVfVFlQRV9RVUVSWV9SRVEpCgl7CgkJLyogRmlsbCBpbiBxdWVyeSBzcGVjaWZpYyBmaWVsZHMuICovCgkJaWYgKHV0cF9idWlsZF9xdWVyeV9yZXFfdXBpdSgoc3RydWN0IHVwaXVfdHJhbnNfbWdtdF9xdWVyeV9oZHIgKikgcmVxX3VwaXUsIHVwaXVfZGF0YSkpCgkJewoJCQlyZXR1cm4gLVVGU19GQUlMVVJFOwoJCX0KCX0KCgkvKiBJZiBhIGRhdGEgdHJhbnNmZXIgY21kLCBjaGVjayB0aGUgYWxpZ25tZW50IGFuZCBsZW5ndGggb2YgdGhlIGJ1ZmZlci4gKi8KCWlmICh1cGl1X2RhdGEtPmV4cGVjdGVkX2RhdGFfbGVuKQoJewoJCWlmICh1cGl1X2RhdGEtPmRhdGFfYnVmZmVyX2FkZHIgJiAweDMpCgkJewoJCQlyZXR1cm4gLVVGU19GQUlMVVJFOwoJCX0KCX0KCglyZXFfdXBpdS0+YmFzaWNfaGRyLnRyYW5zX3R5cGUgICAgPSB1cGl1X2RhdGEtPnRyYW5zX3R5cGU7CglyZXFfdXBpdS0+YmFzaWNfaGRyLmZsYWdzICAgICAgICAgPSB1cGl1X2RhdGEtPmZsYWdzOwoJcmVxX3VwaXUtPmJhc2ljX2hkci5jbWRfc2V0X3R5cGUgID0gdXBpdV9kYXRhLT5jbWRfc2V0X3R5cGU7CglyZXFfdXBpdS0+YmFzaWNfaGRyLmRhdGFfc2VnX2xlbiAgPSB1cGl1X2RhdGEtPmRhdGFfc2VnX2xlbjsKCXJlcV91cGl1LT5iYXNpY19oZHIubHVuICAgICAgICAgICA9IHVwaXVfZGF0YS0+bHVuOwoJcmVxX3VwaXUtPmJhc2ljX2hkci50b3RhbF9laHNfbGVuID0gdXBpdV9kYXRhLT5laHNfbGVuOwoJcmVxX3VwaXUtPmJhc2ljX2hkci50YXNrX3RhZyAgICAgID0gYXRvbWljX2FkZCgoaW50ICopICYoZGV2LT51dHJkX2RhdGEudGFza19pZCksIDEpOwoJaWYgKHVwaXVfZGF0YS0+Y2RiKQoJCW1lbWNweSgmKHJlcV91cGl1LT50cmFuc19zcGVjaWZpY19maWVsZHNbNF0pLCAodm9pZCAqKSB1cGl1X2RhdGEtPmNkYiwgMTYpOwoJLyogSWYgY29tbWFuZCB1cGl1LCBmaWxsIGluIGRhdGEgbGVuZ3RoLiAqLwoJaWYgKHJlcV91cGl1LT5iYXNpY19oZHIudHJhbnNfdHlwZSA9PSBVUElVX1RZUEVfQ09NTUFORCkKCQkoKHN0cnVjdCB1cGl1X2NtZF9oZHIgKilyZXFfdXBpdSktPmRhdGFfZXhwZWN0ZWRfbGVuID0gQkUzMih1cGl1X2RhdGEtPmV4cGVjdGVkX2RhdGFfbGVuKTsKCglyZXR1cm4gVUZTX1NVQ0NFU1M7Cgp9CgpzdGF0aWMgdm9pZCB1dHBfZmlsbF91dHJkX3Byb3BlcnRpZXMoc3RydWN0IHVwaXVfcmVxX2J1aWxkX3R5cGUgKnVwaXVfZGF0YSwKCQkJCQkJCQkJIHN0cnVjdCB1dHBfdXRyZF9yZXFfYnVpbGRfdHlwZSAqdXRyZCwKCQkJCQkJCQkJIHN0cnVjdCB1dHJkX2NtZF9kZXNjICpjbWRfZGVzYykKewoJdXRyZC0+Y21kX3R5cGUgICAgICA9IHVwaXVfZGF0YS0+Y21kX3R5cGU7Cgl1dHJkLT5kZCAgICAgICAgICAgID0gdXBpdV9kYXRhLT5kZDsKCXV0cmQtPmlycSAgICAgICAgICAgPSBVVFJEX0lSUV9DTUQ7Cgl1dHJkLT5wcmR0X29mZnNldCAgID0gVVBJVV9IRFJfTEVOICsgY21kX2Rlc2MtPnJlc3BfdXBpdV9sZW47Cgl1dHJkLT5wcmR0X2xlbiAgICAgID0gY21kX2Rlc2MtPm51bV9wcmR0OwoJdXRyZC0+cmVxX3VwaXUgICAgICA9IChzdHJ1Y3QgdXBpdV9iYXNpY19oZHIgKikgY21kX2Rlc2MtPnJlcV91cGl1OwoJdXRyZC0+cmVxX3VwaXVfbGVuICA9IFVQSVVfSERSX0xFTjsKCXV0cmQtPnJlc3BfdXBpdV9sZW4gPSBjbWRfZGVzYy0+cmVzcF91cGl1X2xlbjsKCXV0cmQtPm9jcyAgICAgICAgICAgPSAweEY7Cgl1dHJkLT50aW1lb3V0ICAgICAgID0gdXBpdV9kYXRhLT50aW1lb3V0X21zZWNzOwp9CgpzdGF0aWMgdm9pZCB1dHBfZmlsbF9wcmR0X2VudHJpZXMoc3RydWN0IHVwaXVfcmVxX2J1aWxkX3R5cGUgKnVwaXVfZGF0YSwgc3RydWN0IHV0cF9wcmR0X2VudHJ5ICpwcmR0X2VudHJ5KQp7Cgl1aW50NjRfdCBidWY7Cgl1aW50NjRfdCBieXRlc19yZW1haW5pbmc7Cgl1aW50MzJfdCBwcmRfZGJjOwoKCWJ1ZiAgICAgICAgICAgICAgICA9IHVwaXVfZGF0YS0+ZGF0YV9idWZmZXJfYWRkcjsKCWJ5dGVzX3JlbWFpbmluZyAgICA9IHVwaXVfZGF0YS0+ZXhwZWN0ZWRfZGF0YV9sZW47CgoJd2hpbGUgKGJ5dGVzX3JlbWFpbmluZykKCXsKCQlwcmR0X2VudHJ5LT5kYXRhX2Jhc2VfYWRkciAgID0gYnVmOwoJCXByZHRfZW50cnktPmRhdGFfdXBwZXJfYWRkciAgPSBidWYgPj4gMzI7CgkJcHJkX2RiYyAgICAgICAgICAgICAgICAgICAgICA9IE1JTihVVFBfTUFYX1BSRF9EQVRBX0JZVEVfQ05ULCBieXRlc19yZW1haW5pbmcpIC0gMTsKCQlwcmR0X2VudHJ5LT5kYXRhX2J5dGVfY250ICAgID0gcHJkX2RiYzsKCQlpZiAoYnl0ZXNfcmVtYWluaW5nIDw9IFVUUF9NQVhfUFJEX0RBVEFfQllURV9DTlQpCgkJCWJyZWFrOwoJCWJ1ZiAgICAgICAgICAgICArPSBVVFBfTUFYX1BSRF9EQVRBX0JZVEVfQ05UOwoJCWJ5dGVzX3JlbWFpbmluZyAtPSBVVFBfTUFYX1BSRF9EQVRBX0JZVEVfQ05UOwoJCXByZHRfZW50cnkrKzsKCX0KCn0KCmludCB1dHBfZW5xdWV1ZV91cGl1KHN0cnVjdCB1ZnNfZGV2ICpkZXYsIHN0cnVjdCB1cGl1X3JlcV9idWlsZF90eXBlICp1cGl1X2RhdGEpCnsKCXN0cnVjdCB1cGl1X2dlbl9oZHIgICAgICAgICAgICAqcmVxX3VwaXU7CglzdHJ1Y3QgdXRwX3V0cmRfcmVxX2J1aWxkX3R5cGUgdXRyZDsKCXVpbnQzMl90ICAgICAgICAgICAgICAgICAgICAgICBudW1fcHJkdDsKCXN0cnVjdCB1dHBfcHJkdF9lbnRyeSAgICAgICAgICAqcHJkdF9lbnRyeTsKCWludCAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXQgPSBVRlNfU1VDQ0VTUzsKCXVpbnQzMl90ICAgICAgICAgICAgICAgICAgICAgICByZXNwX2xlbjsKCXVpbnQzMl90ICAgICAgICAgICAgICAgICAgICAgICBjbWRfZGVzY19sZW47CglzdHJ1Y3QgdXRyZF9jbWRfZGVzYyAgICAgICAgICAgY21kX2Rlc2M7CgoJLyogUm91bmQgdXAgcmVzcF91cGl1X2xlbiB0byBhIERXT1JEIGJvdW5kYXJ5LgoJICogQWxzbywgbWFrZSBzdXJlIGl0IGlzIG9mIG1pbiByZXF1aXJlZCBsZW5ndGguCgkgKi8KCXJlc3BfbGVuID0gUk9VTkRVUCh1cGl1X2RhdGEtPnJlc3BfZGF0YV9sZW4sIDQpICsgVVBJVV9IRFJfTEVOOwoKCWlmICh1dHBfZ2V0X3ByZHRfbGVuKHVwaXVfZGF0YS0+ZXhwZWN0ZWRfZGF0YV9sZW4sICZudW1fcHJkdCkpCgkJcmV0dXJuIC1VRlNfRkFJTFVSRTsKCgkvKiBDYWxjdWxhdGUgdGhlIGxlbmd0aC4gKi8KCWNtZF9kZXNjX2xlbiA9IFVQSVVfSERSX0xFTiArIHJlc3BfbGVuICsgbnVtX3ByZHQgKiBzaXplb2Yoc3RydWN0IHV0cF9wcmR0X2VudHJ5KTsKCgkvKiBBbGxvY2F0ZSBtZW1vcnkgZm9yIFVUUCBDb21tYW5kIERlc2NyaXB0b3IuICovCglyZXFfdXBpdSA9IChzdHJ1Y3QgdXBpdV9nZW5faGRyKikgbWVtYWxpZ24oKHNpemVfdCApIGxjbShDQUNIRV9MSU5FLCBVVFBfQ01EX0RFU0NfQkFTRV9BTElHTk1FTlRfU0laRSksIFJPVU5EVVAoY21kX2Rlc2NfbGVuLCBDQUNIRV9MSU5FKSk7CglpZiAoIXJlcV91cGl1KQoJewoJCWRwcmludGYoQ1JJVElDQUwsICJVbmFibGUgdG8gYWxsb2NhdGUgcmVxdWVzdCB1cGl1XG4iKTsKCQlyZXR1cm4gLVVGU19GQUlMVVJFOwoJfQoKCS8qIEZpbGwgcmVxIHVwaXUuICovCglyZXQgPSB1dHBfZmlsbF9yZXFfdXBpdShkZXYsIHVwaXVfZGF0YSwgcmVxX3VwaXUpOwoJaWYgKHJldCkKCXsKCQlnb3RvIHV0cF9lbnF1ZXVlX3VwaXVfZXJyOwoJfQoKCS8qIEZpbGwgVVRSRCBwcm9wZXJ0aWVzLiAqLwoJY21kX2Rlc2MubnVtX3ByZHQgICAgICA9IG51bV9wcmR0OwoJY21kX2Rlc2MucmVxX3VwaXUgICAgICA9IHJlcV91cGl1OwoJY21kX2Rlc2MucmVzcF91cGl1X2xlbiA9IHJlc3BfbGVuOwoJdXRwX2ZpbGxfdXRyZF9wcm9wZXJ0aWVzKHVwaXVfZGF0YSwgJnV0cmQsICZjbWRfZGVzYyk7CgoJcHJkdF9lbnRyeSAgICAgICAgID0gKHN0cnVjdCB1dHBfcHJkdF9lbnRyeSAqKSAoKHVpbnQzMl90KSByZXFfdXBpdSArIFVQSVVfSERSX0xFTiArIHJlc3BfbGVuKTsKCgkvKiBGaWxsIFBSRFQgZW50cmllcy4gKi8KCWlmIChudW1fcHJkdCkKCXV0cF9maWxsX3ByZHRfZW50cmllcyh1cGl1X2RhdGEsIHByZHRfZW50cnkpOwoKCS8qIEZsdXNoIHJlcV91cGl1ICovCglkc2IoKTsKCWFyY2hfY2xlYW5faW52YWxpZGF0ZV9jYWNoZV9yYW5nZSgoYWRkcl90KSByZXFfdXBpdSwgY21kX2Rlc2NfbGVuKTsKCgkvKiBDaGVjayB0aGUgcmVzcG9uc2UuICovCglyZXQgPSB1dHBfZW5xdWV1ZV91dHJkKGRldiwgJnV0cmQpOwoJaWYgKHJldCkKCXsKCQlkcHJpbnRmKENSSVRJQ0FMLCAiQ29tbWFuZCBmYWlsZWQuIGNvbW1hbmQgPSAleFxuIiwgcmVxX3VwaXUtPmJhc2ljX2hkci50cmFuc190eXBlKTsKCQlnb3RvIHV0cF9lbnF1ZXVlX3VwaXVfZXJyOwoJfQoKCS8qIFVQSVUgcHJvY2Vzc2VkLiBJbnZhbGlkYXRlIGNhY2hlIHRvIHVwZGF0ZSByZXNwLiAqLwoJYXJjaF9pbnZhbGlkYXRlX2NhY2hlX3JhbmdlKChhZGRyX3QpIHJlcV91cGl1LCBjbWRfZGVzY19sZW4pOwoKCS8qIFNhdmUgdGhlIHJlc3BvbnNlLiAqLwoJbWVtY3B5KHVwaXVfZGF0YS0+cmVzcF9wdHIsICh2b2lkICopICgodWludDMyX3QpcmVxX3VwaXUgKyBVUElVX0hEUl9MRU4pLCB1cGl1X2RhdGEtPnJlc3BfbGVuKTsKCW1lbWNweSgodm9pZCAqKSB1cGl1X2RhdGEtPnJlc3BfZGF0YV9wdHIsICh2b2lkICopICgodWludDMyX3QpcmVxX3VwaXUgKyAyICogVVBJVV9IRFJfTEVOKSwgdXBpdV9kYXRhLT5yZXNwX2RhdGFfbGVuKTsKCnV0cF9lbnF1ZXVlX3VwaXVfZXJyOgoJZnJlZShyZXFfdXBpdSk7CglyZXR1cm4gcmV0Owp9Cg==