LyoKICogQ29weXJpZ2h0IChDKSBNaWNoZWwgRORuemVyIDxtaWNoZGFlbkBpaWljLmV0aHouY2g+CiAqCiAqIEFQVVMgUENJIHJvdXRpbmVzLgogKgogKiBDdXJyZW50bHksIG9ubHkgQi9DVmlzaW9uUFBDIGNhcmRzIChQZXJtZWRpYTIpIGFyZSBzdXBwb3J0ZWQuCiAqCiAqIFRoYW5rcyB0byBHZWVydCBVeXR0ZXJob2V2ZW4gZm9yIHRoZSBpZGVhOgogKiBSZWFkIHZhbHVlcyBmcm9tIGdpdmVuIGNvbmZpZyBzcGFjZShzKSBmb3IgdGhlIGZpcnN0IGRldmljZXMsIC0xIG90aGVyd2lzZQogKgogKi8KCiNpZmRlZiBDT05GSUdfQU1JR0EKCiNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KI2luY2x1ZGUgPGxpbnV4L3BjaS5oPgojaW5jbHVkZSA8bGludXgvZGVsYXkuaD4KI2luY2x1ZGUgPGxpbnV4L3N0cmluZy5oPgojaW5jbHVkZSA8bGludXgvaW5pdC5oPgoKI2luY2x1ZGUgPGFzbS9pby5oPgojaW5jbHVkZSA8YXNtL3BjaS1icmlkZ2UuaD4KI2luY2x1ZGUgPGFzbS9tYWNoZGVwLmg+CgojaW5jbHVkZSAiYXB1c19wY2kuaCIKCgovKiBUaGVzZSBkZWZpbml0aW9ucyBhcmUgbW9zdGx5IGFkYXB0ZWQgZnJvbSBwbTJmYi5jICovCgojdW5kZWYgQVBVU19QQ0lfTUFTVEVSX0RFQlVHCiNpZmRlZiBBUFVTX1BDSV9NQVNURVJfREVCVUcKI2RlZmluZSBEUFJJTlRLKGEsYi4uLikJcHJpbnRrKEtFUk5fREVCVUcgImFwdXNfcGNpOiAlczogIiBhLCBfX0ZVTkNUSU9OX18gLCAjIyBiKQojZWxzZQojZGVmaW5lIERQUklOVEsoYSxiLi4uKQojZW5kaWYKCi8qCiAqIFRoZSBfREVGSU5JVElWRV8gbWVtb3J5IG1hcHBpbmcvdW5tYXBwaW5nIGZ1bmN0aW9ucy4KICogVGhpcyBpcyBkdWUgdG8gdGhlIGZhY3QgdGhhdCB0aGV5J3JlIGNoYW5naW5nIHNvb29vIG9mdGVuLi4uCiAqLwojZGVmaW5lIERFRlcoKQkJd21iKCkKI2RlZmluZSBERUZSKCkJCXJtYigpCiNkZWZpbmUgREVGUlcoKQkJbWIoKQoKI2RlZmluZSBERVZOTyhkKQkoKGQpPj4zKQojZGVmaW5lIEZOTk8oZCkJCSgoZCkmNykKCgpleHRlcm4gdW5zaWduZWQgbG9uZyBwb3dlcnVwX1BDSV9wcmVzZW50OwoKc3RhdGljIHN0cnVjdCBwY2lfY29udHJvbGxlciAqYXB1c19ob3NlOwoKCnZvaWQgKnBjaV9pb19iYXNlKHVuc2lnbmVkIGludCBidXMpCnsKCXJldHVybiAwOwp9CgoKaW50CmFwdXNfcGNpYmlvc19yZWFkX2NvbmZpZyhzdHJ1Y3QgcGNpX2J1cyAqYnVzLCBpbnQgZGV2Zm4sIGludCBvZmZzZXQsCgkJCSBpbnQgbGVuLCB1MzIgKnZhbCkKewoJaW50IGZubm8gPSBGTk5PKGRldmZuKTsKCWludCBkZXZubyA9IERFVk5PKGRldmZuKTsKCXZvbGF0aWxlIHVuc2lnbmVkIGNoYXIgKmNmZ19kYXRhOwoKCWlmIChidXMtPm51bWJlciA+IDAgfHwgZGV2bm8gIT0gMSkgewoJCSp2YWwgPSB+MDsKCQlyZXR1cm4gUENJQklPU19ERVZJQ0VfTk9UX0ZPVU5EOwoJfQoJLyogYmFzZSBhZGRyZXNzICsgZnVuY3Rpb24gb2Zmc2V0ICsgb2Zmc2V0IF4gZW5kaWFubmVzcyBjb252ZXJzaW9uICovCgkvKiBYWFggdGhlIGZubm88PDUgYml0IHNlZW1zIHdhY2t5ICAtLSBwYXVsdXMgKi8KCWNmZ19kYXRhID0gYXB1c19ob3NlLT5jZmdfZGF0YSArIChmbm5vPDw1KSArIChvZmZzZXQgXiAobGVuIC0gMSkpOwoJc3dpdGNoIChsZW4pIHsKCWNhc2UgMToKCQkqdmFsID0gcmVhZGIoY2ZnX2RhdGEpOwoJCWJyZWFrOwoJY2FzZSAyOgoJCSp2YWwgPSByZWFkdyhjZmdfZGF0YSk7CgkJYnJlYWs7CglkZWZhdWx0OgoJCSp2YWwgPSByZWFkbChjZmdfZGF0YSk7CgkJYnJlYWs7Cgl9CgoJRFBSSU5USygicmVhZCBiOiAweCV4LCBkOiAweCV4LCBmOiAweCV4LCBvOiAweCV4LCBsOiAlZCwgdjogMHgleFxuIiwKCQlidXMtPm51bWJlciwgZGV2Zm4+PjMsIGRldmZuJjcsIG9mZnNldCwgbGVuLCAqdmFsKTsKCXJldHVybiBQQ0lCSU9TX1NVQ0NFU1NGVUw7Cn0KCmludAphcHVzX3BjaWJpb3Nfd3JpdGVfY29uZmlnKHN0cnVjdCBwY2lfYnVzICpidXMsIGludCBkZXZmbiwgaW50IG9mZnNldCwKCQkJICBpbnQgbGVuLCB1MzIgKnZhbCkKewoJaW50IGZubm8gPSBGTk5PKGRldmZuKTsKCWludCBkZXZubyA9IERFVk5PKGRldmZuKTsKCXZvbGF0aWxlIHVuc2lnbmVkIGNoYXIgKmNmZ19kYXRhOwoKCWlmIChidXMtPm51bWJlciA+IDAgfHwgZGV2bm8gIT0gMSkgewoJCXJldHVybiBQQ0lCSU9TX0RFVklDRV9OT1RfRk9VTkQ7Cgl9CgkvKiBiYXNlIGFkZHJlc3MgKyBmdW5jdGlvbiBvZmZzZXQgKyBvZmZzZXQgXiBlbmRpYW5uZXNzIGNvbnZlcnNpb24gKi8KCS8qIFhYWCB0aGUgZm5ubzw8NSBiaXQgc2VlbXMgd2Fja3kgIC0tIHBhdWx1cyAqLwoJY2ZnX2RhdGEgPSBhcHVzX2hvc2UtPmNmZ19kYXRhICsgKGZubm88PDUpICsgKG9mZnNldCBeIChsZW4gLSAxKSk7Cglzd2l0Y2ggKGxlbikgewoJY2FzZSAxOgoJCXdyaXRlYih2YWwsIGNmZ19kYXRhKTsgREVGVygpOwoJCWJyZWFrOwoJY2FzZSAyOgoJCXdyaXRldyh2YWwsIGNmZ19kYXRhKTsgREVGVygpOwoJCWJyZWFrOwoJZGVmYXVsdDoKCQl3cml0ZWwodmFsLCBjZmdfZGF0YSk7IERFRlcoKTsKCQlicmVhazsKCX0KCglEUFJJTlRLKCJ3cml0ZSBiOiAweCV4LCBkOiAweCV4LCBmOiAweCV4LCBvOiAweCV4LCBsOiAlZCwgdjogMHgleFxuIiwKCQlidXMtPm51bWJlciwgZGV2Zm4+PjMsIGRldmZuJjcsIG9mZnNldCwgbGVuLCB2YWwpOwoJcmV0dXJuIFBDSUJJT1NfU1VDQ0VTU0ZVTDsKfQoKc3RhdGljIHN0cnVjdCBwY2lfb3BzIGFwdXNfcGNpX29wcyA9IHsKCWFwdXNfcGNpYmlvc19yZWFkX2NvbmZpZywKCWFwdXNfcGNpYmlvc193cml0ZV9jb25maWcKfTsKCnN0YXRpYyBzdHJ1Y3QgcmVzb3VyY2UgcGNpX21lbSA9IHsgIkIvQ1Zpc2lvblBQQyBQQ0kgbWVtIiwgQ1ZQUENfRkJfQVBFUlRVUkVfT05FLCBDVlBQQ19QQ0lfQ09ORklHLCBJT1JFU09VUkNFX01FTSB9OwoKdm9pZCBfX2luaXQKYXB1c19wY2liaW9zX2ZpeHVwKHZvaWQpCnsKLyoJc3RydWN0IHBjaV9kZXYgKmRldiA9IHBjaV9maW5kX3Nsb3QoMCwgMTw8Myk7Cgl1bnNpZ25lZCBpbnQgcmVnLCB2YWwsIG9mZnNldDsqLwoKCS8qIEZJWE1FOiBpbnRlcnJ1cHQ/ICovCgkvKmRldi0+aW50ZXJydXB0ID0geHh4OyovCgogICAgICAgIHJlcXVlc3RfcmVzb3VyY2UoJmlvbWVtX3Jlc291cmNlLCAmcGNpX21lbSk7CiAgICAJcHJpbnRrKCIlczogUENJIG1lbSByZXNvdXJjZSByZXF1ZXN0ZWRcbiIsIF9fRlVOQ1RJT05fXyk7Cn0KCnN0YXRpYyB2b2lkIF9faW5pdCBhcHVzX3BjaWJpb3NfZml4dXBfYnVzKHN0cnVjdCBwY2lfYnVzICpidXMpCnsKICAgICAgICBidXMtPnJlc291cmNlWzFdID0gJnBjaV9tZW07Cn0KCgovKgogKiBUaGlzIGlzIGZyb20gcG0yZmIuYyBhZ2FpbgogKgogKiBDaGVjayBpZiBQQ0kgKEIvQ1Zpc2lvblBQQykgaXMgYXZhaWxhYmxlLCBpbml0aWFsaXplIGl0IGFuZCBzZXQgdXAKICogdGhlIHBjaWJpb3NfKiBwb2ludGVycwogKi8KCgp2b2lkIF9faW5pdAphcHVzX3NldHVwX3BjaV9wdHJzKHZvaWQpCnsKCWlmICghcG93ZXJ1cF9QQ0lfcHJlc2VudCkgewoJCURQUklOVEsoIm5vIFBDSSBicmlkZ2UgZGV0ZWN0ZWRcbiIpOwoJCXJldHVybjsKCX0KCURQUklOVEsoIlBoYXNlNSBCL0NWaXNpb25QUEMgUENJIGJyaWRnZSBkZXRlY3RlZC5cbiIpOwoKCWFwdXNfaG9zZSA9IHBjaWJpb3NfYWxsb2NfY29udHJvbGxlcigpOwoJaWYgKCFhcHVzX2hvc2UpIHsKCQlwcmludGsoImFwdXNfcGNpOiBDYW4ndCBhbGxvY2F0ZSBQQ0kgY29udHJvbGxlciBzdHJ1Y3R1cmVcbiIpOwoJCXJldHVybjsKCX0KCglpZiAoIShhcHVzX2hvc2UtPmNmZ19kYXRhID0gaW9yZW1hcChDVlBQQ19QQ0lfQ09ORklHLCAyNTYpKSkgewoJCXByaW50aygiYXB1c19wY2k6IHVuYWJsZSB0byBtYXAgUENJIGNvbmZpZyByZWdpb25cbiIpOwoJCXJldHVybjsKCX0KCglpZiAoIShhcHVzX2hvc2UtPmNmZ19hZGRyID0gaW9yZW1hcChDU1BQQ19QQ0lfQlJJREdFLCAyNTYpKSkgewoJCXByaW50aygiYXB1c19wY2k6IHVuYWJsZSB0byBtYXAgUENJIGJyaWRnZVxuIik7CgkJcmV0dXJuOwoJfQoKCXdyaXRlbChDU1BQQ0ZfQlJJREdFX0JJR19FTkRJQU4sIGFwdXNfaG9zZS0+Y2ZnX2FkZHIgKyBDU1BQQ19CUklER0VfRU5ESUFOKTsKCURFRlcoKTsKCgl3cml0ZWwoQ1ZQUENfUkVHU19SRUdJT04sICBhcHVzX2hvc2UtPmNmZ19kYXRhKyBQQ0lfQkFTRV9BRERSRVNTXzApOwoJREVGVygpOwoJd3JpdGVsKENWUFBDX0ZCX0FQRVJUVVJFX09ORSwgYXB1c19ob3NlLT5jZmdfZGF0YSArIFBDSV9CQVNFX0FERFJFU1NfMSk7CglERUZXKCk7Cgl3cml0ZWwoQ1ZQUENfRkJfQVBFUlRVUkVfVFdPLCBhcHVzX2hvc2UtPmNmZ19kYXRhICsgUENJX0JBU0VfQUREUkVTU18yKTsKCURFRlcoKTsKCXdyaXRlbChDVlBQQ19ST01fQUREUkVTUywgYXB1c19ob3NlLT5jZmdfZGF0YSArIFBDSV9ST01fQUREUkVTUyk7CglERUZXKCk7CgoJd3JpdGVsKDB4ZWYwMDAwMDAgfCBQQ0lfQ09NTUFORF9JTyB8IFBDSV9DT01NQU5EX01FTU9SWSB8CgkJUENJX0NPTU1BTkRfTUFTVEVSLCBhcHVzX2hvc2UtPmNmZ19kYXRhICsgUENJX0NPTU1BTkQpOwoJREVGVygpOwoKCWFwdXNfaG9zZS0+Zmlyc3RfYnVzbm8gPSAwOwoJYXB1c19ob3NlLT5sYXN0X2J1c25vID0gMDsKCWFwdXNfaG9zZS0+b3BzID0gJmFwdXNfcGNpX29wczsKCXBwY19tZC5wY2liaW9zX2ZpeHVwID0gYXB1c19wY2liaW9zX2ZpeHVwOwoJcHBjX21kLnBjaWJpb3NfZml4dXBfYnVzID0gYXB1c19wY2liaW9zX2ZpeHVwX2J1czsKCglyZXR1cm47Cn0KCiNlbmRpZiAvKiBDT05GSUdfQU1JR0EgKi8K