LyoKICogIEZvcmNlIGZlZWRiYWNrIHN1cHBvcnQgZm9yIFBhbnRoZXJMb3JkL0dyZWVuQXNpYSBiYXNlZCBkZXZpY2VzCiAqCiAqICBUaGUgZGV2aWNlcyBhcmUgZGlzdHJpYnV0ZWQgdW5kZXIgdmFyaW91cyBuYW1lcyBhbmQgdGhlIHNhbWUgVVNCIGRldmljZSBJRAogKiAgY2FuIGJlIHVzZWQgaW4gYm90aCBhZGFwdGVycyBhbmQgYWN0dWFsIGdhbWUgY29udHJvbGxlcnMuCiAqCiAqICAwODEwOjAwMDEgIlR3aW4gVVNCIEpveXN0aWNrIgogKiAgIC0gdGVzdGVkIHdpdGggUGFudGhlckxvcmQgVVNCL1BTMiAyaW4xIEFkYXB0ZXIKICogICAtIGNvbnRhaW5zIHR3byByZXBvcnRzLCBvbmUgZm9yIGVhY2ggcG9ydCAoSElEX1FVSVJLX01VTFRJX0lOUFVUKQogKgogKiAgMGU4ZjowMDAzICJHcmVlbkFzaWEgSW5jLiAgICBVU0IgSm95c3RpY2sgICAgICIKICogICAtIHRlc3RlZCB3aXRoIEv2bmlnIEdhbWluZyBnYW1lcGFkCiAqCiAqICAwZThmOjAwMDMgIkdBU0lBIFVTQiBHYW1lcGFkIgogKiAgIC0gYW5vdGhlciB2ZXJzaW9uIG9mIHRoZSBL9m5pZyBnYW1lcGFkCiAqCiAqICBDb3B5cmlnaHQgKGMpIDIwMDcsIDIwMDkgQW5zc2kgSGFubnVsYSA8YW5zc2kuaGFubnVsYUBnbWFpbC5jb20+CiAqLwoKLyoKICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkKICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkKICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUKICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKICogYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKICogRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgMDIxMTEtMTMwNyBVU0EKICovCgoKLyogI2RlZmluZSBERUJVRyAqLwoKI2RlZmluZSBkZWJ1Zyhmb3JtYXQsIGFyZy4uLikgcHJfZGVidWcoImhpZC1wbGZmOiAiIGZvcm1hdCAiXG4iICwgIyMgYXJnKQoKI2luY2x1ZGUgPGxpbnV4L2lucHV0Lmg+CiNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CiNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KI2luY2x1ZGUgPGxpbnV4L3VzYi5oPgojaW5jbHVkZSA8bGludXgvaGlkLmg+CgojaW5jbHVkZSAiaGlkLWlkcy5oIgoKI2lmZGVmIENPTkZJR19QQU5USEVSTE9SRF9GRgojaW5jbHVkZSAidXNiaGlkL3VzYmhpZC5oIgoKc3RydWN0IHBsZmZfZGV2aWNlIHsKCXN0cnVjdCBoaWRfcmVwb3J0ICpyZXBvcnQ7CglzMzIgKnN0cm9uZzsKCXMzMiAqd2VhazsKfTsKCnN0YXRpYyBpbnQgaGlkX3BsZmZfcGxheShzdHJ1Y3QgaW5wdXRfZGV2ICpkZXYsIHZvaWQgKmRhdGEsCgkJCSBzdHJ1Y3QgZmZfZWZmZWN0ICplZmZlY3QpCnsKCXN0cnVjdCBoaWRfZGV2aWNlICpoaWQgPSBpbnB1dF9nZXRfZHJ2ZGF0YShkZXYpOwoJc3RydWN0IHBsZmZfZGV2aWNlICpwbGZmID0gZGF0YTsKCWludCBsZWZ0LCByaWdodDsKCglsZWZ0ID0gZWZmZWN0LT51LnJ1bWJsZS5zdHJvbmdfbWFnbml0dWRlOwoJcmlnaHQgPSBlZmZlY3QtPnUucnVtYmxlLndlYWtfbWFnbml0dWRlOwoJZGVidWcoImNhbGxlZCB3aXRoIDB4JTA0eCAweCUwNHgiLCBsZWZ0LCByaWdodCk7CgoJbGVmdCA9IGxlZnQgKiAweDdmIC8gMHhmZmZmOwoJcmlnaHQgPSByaWdodCAqIDB4N2YgLyAweGZmZmY7CgoJKnBsZmYtPnN0cm9uZyA9IGxlZnQ7CgkqcGxmZi0+d2VhayA9IHJpZ2h0OwoJZGVidWcoInJ1bm5pbmcgd2l0aCAweCUwMnggMHglMDJ4IiwgbGVmdCwgcmlnaHQpOwoJdXNiaGlkX3N1Ym1pdF9yZXBvcnQoaGlkLCBwbGZmLT5yZXBvcnQsIFVTQl9ESVJfT1VUKTsKCglyZXR1cm4gMDsKfQoKc3RhdGljIGludCBwbGZmX2luaXQoc3RydWN0IGhpZF9kZXZpY2UgKmhpZCkKewoJc3RydWN0IHBsZmZfZGV2aWNlICpwbGZmOwoJc3RydWN0IGhpZF9yZXBvcnQgKnJlcG9ydDsKCXN0cnVjdCBoaWRfaW5wdXQgKmhpZGlucHV0OwoJc3RydWN0IGxpc3RfaGVhZCAqcmVwb3J0X2xpc3QgPQoJCQkmaGlkLT5yZXBvcnRfZW51bVtISURfT1VUUFVUX1JFUE9SVF0ucmVwb3J0X2xpc3Q7CglzdHJ1Y3QgbGlzdF9oZWFkICpyZXBvcnRfcHRyID0gcmVwb3J0X2xpc3Q7CglzdHJ1Y3QgaW5wdXRfZGV2ICpkZXY7CglpbnQgZXJyb3I7CglzMzIgKnN0cm9uZzsKCXMzMiAqd2VhazsKCgkvKiBUaGUgZGV2aWNlIGNvbnRhaW5zIG9uZSBvdXRwdXQgcmVwb3J0IHBlciBwaHlzaWNhbCBkZXZpY2UsIGFsbAoJICAgY29udGFpbmluZyAxIGZpZWxkLCB3aGljaCBjb250YWlucyA0IGZmMDAuMDAwMiB1c2FnZXMgYW5kIDQgMTZiaXQKCSAgIGFic29sdXRlIHZhbHVlcy4KCgkgICBUaGUgaW5wdXQgcmVwb3J0cyBhbHNvIGNvbnRhaW4gYSBmaWVsZCB3aGljaCBjb250YWlucwoJICAgOCBmZjAwLjAwMDEgdXNhZ2VzIGFuZCA4IGJvb2xlYW4gdmFsdWVzLiBUaGVpciBtZWFuaW5nIGlzCgkgICBjdXJyZW50bHkgdW5rbm93bi4KCSAgIAoJICAgQSB2ZXJzaW9uIG9mIHRoZSAwZThmOjAwMDMgZXhpc3RzIHRoYXQgaGFzIGFsbCB0aGUgdmFsdWVzIGluCgkgICBzZXBhcmF0ZSBmaWVsZHMgYW5kIG1pc3NlcyB0aGUgZXh0cmEgaW5wdXQgZmllbGQsIHRodXMgcmVzZW1ibGluZwoJICAgWmVyb3BsdXMgKGhpZC16cGZmKSBkZXZpY2VzLgoJKi8KCglpZiAobGlzdF9lbXB0eShyZXBvcnRfbGlzdCkpIHsKCQloaWRfZXJyKGhpZCwgIm5vIG91dHB1dCByZXBvcnRzIGZvdW5kXG4iKTsKCQlyZXR1cm4gLUVOT0RFVjsKCX0KCglsaXN0X2Zvcl9lYWNoX2VudHJ5KGhpZGlucHV0LCAmaGlkLT5pbnB1dHMsIGxpc3QpIHsKCgkJcmVwb3J0X3B0ciA9IHJlcG9ydF9wdHItPm5leHQ7CgoJCWlmIChyZXBvcnRfcHRyID09IHJlcG9ydF9saXN0KSB7CgkJCWhpZF9lcnIoaGlkLCAicmVxdWlyZWQgb3V0cHV0IHJlcG9ydCBpcyBtaXNzaW5nXG4iKTsKCQkJcmV0dXJuIC1FTk9ERVY7CgkJfQoKCQlyZXBvcnQgPSBsaXN0X2VudHJ5KHJlcG9ydF9wdHIsIHN0cnVjdCBoaWRfcmVwb3J0LCBsaXN0KTsKCQlpZiAocmVwb3J0LT5tYXhmaWVsZCA8IDEpIHsKCQkJaGlkX2VycihoaWQsICJubyBmaWVsZHMgaW4gdGhlIHJlcG9ydFxuIik7CgkJCXJldHVybiAtRU5PREVWOwoJCX0KCgkJaWYgKHJlcG9ydC0+ZmllbGRbMF0tPnJlcG9ydF9jb3VudCA+PSA0KSB7CgkJCXJlcG9ydC0+ZmllbGRbMF0tPnZhbHVlWzBdID0gMHgwMDsKCQkJcmVwb3J0LT5maWVsZFswXS0+dmFsdWVbMV0gPSAweDAwOwoJCQlzdHJvbmcgPSAmcmVwb3J0LT5maWVsZFswXS0+dmFsdWVbMl07CgkJCXdlYWsgPSAmcmVwb3J0LT5maWVsZFswXS0+dmFsdWVbM107CgkJCWRlYnVnKCJkZXRlY3RlZCBzaW5nbGUtZmllbGQgZGV2aWNlIik7CgkJfSBlbHNlIGlmIChyZXBvcnQtPm1heGZpZWxkID49IDQgJiYgcmVwb3J0LT5maWVsZFswXS0+bWF4dXNhZ2UgPT0gMSAmJgoJCQkJcmVwb3J0LT5maWVsZFswXS0+dXNhZ2VbMF0uaGlkID09IChISURfVVBfTEVEIHwgMHg0MykpIHsKCQkJcmVwb3J0LT5maWVsZFswXS0+dmFsdWVbMF0gPSAweDAwOwoJCQlyZXBvcnQtPmZpZWxkWzFdLT52YWx1ZVswXSA9IDB4MDA7CgkJCXN0cm9uZyA9ICZyZXBvcnQtPmZpZWxkWzJdLT52YWx1ZVswXTsKCQkJd2VhayA9ICZyZXBvcnQtPmZpZWxkWzNdLT52YWx1ZVswXTsKCQkJZGVidWcoImRldGVjdGVkIDQtZmllbGQgZGV2aWNlIik7CgkJfSBlbHNlIHsKCQkJaGlkX2VycihoaWQsICJub3QgZW5vdWdoIGZpZWxkcyBvciB2YWx1ZXNcbiIpOwoJCQlyZXR1cm4gLUVOT0RFVjsKCQl9CgoJCXBsZmYgPSBremFsbG9jKHNpemVvZihzdHJ1Y3QgcGxmZl9kZXZpY2UpLCBHRlBfS0VSTkVMKTsKCQlpZiAoIXBsZmYpCgkJCXJldHVybiAtRU5PTUVNOwoKCQlkZXYgPSBoaWRpbnB1dC0+aW5wdXQ7CgoJCXNldF9iaXQoRkZfUlVNQkxFLCBkZXYtPmZmYml0KTsKCgkJZXJyb3IgPSBpbnB1dF9mZl9jcmVhdGVfbWVtbGVzcyhkZXYsIHBsZmYsIGhpZF9wbGZmX3BsYXkpOwoJCWlmIChlcnJvcikgewoJCQlrZnJlZShwbGZmKTsKCQkJcmV0dXJuIGVycm9yOwoJCX0KCgkJcGxmZi0+cmVwb3J0ID0gcmVwb3J0OwoJCXBsZmYtPnN0cm9uZyA9IHN0cm9uZzsKCQlwbGZmLT53ZWFrID0gd2VhazsKCgkJKnN0cm9uZyA9IDB4MDA7CgkJKndlYWsgPSAweDAwOwoJCXVzYmhpZF9zdWJtaXRfcmVwb3J0KGhpZCwgcGxmZi0+cmVwb3J0LCBVU0JfRElSX09VVCk7Cgl9CgoJaGlkX2luZm8oaGlkLCAiRm9yY2UgZmVlZGJhY2sgZm9yIFBhbnRoZXJMb3JkL0dyZWVuQXNpYSBkZXZpY2VzIGJ5IEFuc3NpIEhhbm51bGEgPGFuc3NpLmhhbm51bGFAZ21haWwuY29tPlxuIik7CgoJcmV0dXJuIDA7Cn0KI2Vsc2UKc3RhdGljIGlubGluZSBpbnQgcGxmZl9pbml0KHN0cnVjdCBoaWRfZGV2aWNlICpoaWQpCnsKCXJldHVybiAwOwp9CiNlbmRpZgoKc3RhdGljIGludCBwbF9wcm9iZShzdHJ1Y3QgaGlkX2RldmljZSAqaGRldiwgY29uc3Qgc3RydWN0IGhpZF9kZXZpY2VfaWQgKmlkKQp7CglpbnQgcmV0OwoKCWlmIChpZC0+ZHJpdmVyX2RhdGEpCgkJaGRldi0+cXVpcmtzIHw9IEhJRF9RVUlSS19NVUxUSV9JTlBVVDsKCglyZXQgPSBoaWRfcGFyc2UoaGRldik7CglpZiAocmV0KSB7CgkJaGlkX2VycihoZGV2LCAicGFyc2UgZmFpbGVkXG4iKTsKCQlnb3RvIGVycjsKCX0KCglyZXQgPSBoaWRfaHdfc3RhcnQoaGRldiwgSElEX0NPTk5FQ1RfREVGQVVMVCAmIH5ISURfQ09OTkVDVF9GRik7CglpZiAocmV0KSB7CgkJaGlkX2VycihoZGV2LCAiaHcgc3RhcnQgZmFpbGVkXG4iKTsKCQlnb3RvIGVycjsKCX0KCglwbGZmX2luaXQoaGRldik7CgoJcmV0dXJuIDA7CmVycjoKCXJldHVybiByZXQ7Cn0KCnN0YXRpYyBjb25zdCBzdHJ1Y3QgaGlkX2RldmljZV9pZCBwbF9kZXZpY2VzW10gPSB7Cgl7IEhJRF9VU0JfREVWSUNFKFVTQl9WRU5ET1JfSURfR0FNRVJPTiwgVVNCX0RFVklDRV9JRF9HQU1FUk9OX0RVQUxfUFNYX0FEQVBUT1IpLAoJCS5kcml2ZXJfZGF0YSA9IDEgfSwgLyogVHdpbiBVU0IgSm95c3RpY2sgKi8KCXsgSElEX1VTQl9ERVZJQ0UoVVNCX1ZFTkRPUl9JRF9HQU1FUk9OLCBVU0JfREVWSUNFX0lEX0dBTUVST05fRFVBTF9QQ1NfQURBUFRPUiksCgkJLmRyaXZlcl9kYXRhID0gMSB9LCAvKiBUd2luIFVTQiBKb3lzdGljayAqLwoJeyBISURfVVNCX0RFVklDRShVU0JfVkVORE9SX0lEX0dSRUVOQVNJQSwgMHgwMDAzKSwgfSwKCXsgfQp9OwpNT0RVTEVfREVWSUNFX1RBQkxFKGhpZCwgcGxfZGV2aWNlcyk7CgpzdGF0aWMgc3RydWN0IGhpZF9kcml2ZXIgcGxfZHJpdmVyID0gewoJLm5hbWUgPSAicGFudGhlcmxvcmQiLAoJLmlkX3RhYmxlID0gcGxfZGV2aWNlcywKCS5wcm9iZSA9IHBsX3Byb2JlLAp9OwoKc3RhdGljIGludCBfX2luaXQgcGxfaW5pdCh2b2lkKQp7CglyZXR1cm4gaGlkX3JlZ2lzdGVyX2RyaXZlcigmcGxfZHJpdmVyKTsKfQoKc3RhdGljIHZvaWQgX19leGl0IHBsX2V4aXQodm9pZCkKewoJaGlkX3VucmVnaXN0ZXJfZHJpdmVyKCZwbF9kcml2ZXIpOwp9Cgptb2R1bGVfaW5pdChwbF9pbml0KTsKbW9kdWxlX2V4aXQocGxfZXhpdCk7Ck1PRFVMRV9MSUNFTlNFKCJHUEwiKTsK