LyogCiAqIEVtYWdpYyBFTUkgMnw2IHVzYiBhdWRpbyBpbnRlcmZhY2UgZmlybXdhcmUgbG9hZGVyLgogKiBDb3B5cmlnaHQgKEMpIDIwMDIKICogCVRhcGlvIExheHN0cvZtICh0YXBpby5sYXhzdHJvbUBpcHRpbWUuZmkpCiAqCiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5CiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UsIGFzIHB1Ymxpc2hlZCBieQogKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCB2ZXJzaW9uIDIuCiAqIAogKiBlbWkyNi5jLHYgMS4xMyAyMDAyLzAzLzA4IDEzOjEwOjI2IHRhcGlvIEV4cAogKi8KI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgojaW5jbHVkZSA8bGludXgvZXJybm8uaD4KI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgojaW5jbHVkZSA8bGludXgvaW5pdC5oPgojaW5jbHVkZSA8bGludXgvdXNiLmg+CiNpbmNsdWRlIDxsaW51eC9kZWxheS5oPgoKI2RlZmluZSBNQVhfSU5URUxfSEVYX1JFQ09SRF9MRU5HVEggMTYKdHlwZWRlZiBzdHJ1Y3QgX0lOVEVMX0hFWF9SRUNPUkQKewoJX191MzIJbGVuZ3RoOwoJX191MzIJYWRkcmVzczsKCV9fdTMyCXR5cGU7CglfX3U4CWRhdGFbTUFYX0lOVEVMX0hFWF9SRUNPUkRfTEVOR1RIXTsKfSBJTlRFTF9IRVhfUkVDT1JELCAqUElOVEVMX0hFWF9SRUNPUkQ7CgovKiBpbmNsdWRlIGZpcm13YXJlICh2YXJpYWJsZXMpICovCiNpbmNsdWRlICJlbWkyNl9mdy5oIgoKI2RlZmluZSBFTUkyNl9WRU5ET1JfSUQgCQkweDA4NmEgIC8qIEVtYWdpYyBTb2Z0LXVuZCBIYXJkd2FyZSBHbUJIICovCiNkZWZpbmUgRU1JMjZfUFJPRFVDVF9JRAkJMHgwMTAwCS8qIEVNSSAyfDYgd2l0aG91dCBmaXJtd2FyZSAqLwojZGVmaW5lIEVNSTI2Ql9QUk9EVUNUX0lECQkweDAxMDIJLyogRU1JIDJ8NiB3aXRob3V0IGZpcm13YXJlICovCgojZGVmaW5lIEFOQ0hPUl9MT0FEX0lOVEVSTkFMCTB4QTAJLyogVmVuZG9yIHNwZWNpZmljIHJlcXVlc3QgY29kZSBmb3IgQW5jaG9yIFVwbG9hZC9Eb3dubG9hZCAoVGhpcyBvbmUgaXMgaW1wbGVtZW50ZWQgaW4gdGhlIGNvcmUpICovCiNkZWZpbmUgQU5DSE9SX0xPQURfRVhURVJOQUwJMHhBMwkvKiBUaGlzIGNvbW1hbmQgaXMgbm90IGltcGxlbWVudGVkIGluIHRoZSBjb3JlLiBSZXF1aXJlcyBmaXJtd2FyZSAqLwojZGVmaW5lIEFOQ0hPUl9MT0FEX0ZQR0EJMHhBNQkvKiBUaGlzIGNvbW1hbmQgaXMgbm90IGltcGxlbWVudGVkIGluIHRoZSBjb3JlLiBSZXF1aXJlcyBmaXJtd2FyZS4gRW1hZ2ljIGV4dGVuc2lvbiAqLwojZGVmaW5lIE1BWF9JTlRFUk5BTF9BRERSRVNTCTB4MUIzRgkvKiBUaGlzIGlzIHRoZSBoaWdoZXN0IGludGVybmFsIFJBTSBhZGRyZXNzIGZvciB0aGUgQU4yMTMxUSAqLwojZGVmaW5lIENQVUNTX1JFRwkJMHg3RjkyICAvKiBFWi1VU0IgQ29udHJvbCBhbmQgU3RhdHVzIFJlZ2lzdGVyLiAgQml0IDAgY29udHJvbHMgODA1MSByZXNldCAqLyAKI2RlZmluZSBJTlRFUk5BTF9SQU0oYWRkcmVzcykgICAoYWRkcmVzcyA8PSBNQVhfSU5URVJOQUxfQUREUkVTUykKCnN0YXRpYyBpbnQgZW1pMjZfd3JpdGVtZW1vcnkoIHN0cnVjdCB1c2JfZGV2aWNlICpkZXYsIGludCBhZGRyZXNzLCB1bnNpZ25lZCBjaGFyICpkYXRhLCBpbnQgbGVuZ3RoLCBfX3U4IGJSZXF1ZXN0KTsKc3RhdGljIGludCBlbWkyNl9zZXRfcmVzZXQoc3RydWN0IHVzYl9kZXZpY2UgKmRldiwgdW5zaWduZWQgY2hhciByZXNldF9iaXQpOwpzdGF0aWMgaW50IGVtaTI2X2xvYWRfZmlybXdhcmUgKHN0cnVjdCB1c2JfZGV2aWNlICpkZXYpOwpzdGF0aWMgaW50IGVtaTI2X3Byb2JlKHN0cnVjdCB1c2JfaW50ZXJmYWNlICppbnRmLCBjb25zdCBzdHJ1Y3QgdXNiX2RldmljZV9pZCAqaWQpOwpzdGF0aWMgdm9pZCBlbWkyNl9kaXNjb25uZWN0KHN0cnVjdCB1c2JfaW50ZXJmYWNlICppbnRmKTsKc3RhdGljIGludCBfX2luaXQgZW1pMjZfaW5pdCAodm9pZCk7CnN0YXRpYyB2b2lkIF9fZXhpdCBlbWkyNl9leGl0ICh2b2lkKTsKCgovKiB0aGFua3MgdG8gZHJpdmVycy91c2Ivc2VyaWFsL2tleXNwYW5fcGRhLmMgY29kZSAqLwpzdGF0aWMgaW50IGVtaTI2X3dyaXRlbWVtb3J5IChzdHJ1Y3QgdXNiX2RldmljZSAqZGV2LCBpbnQgYWRkcmVzcywgdW5zaWduZWQgY2hhciAqZGF0YSwgaW50IGxlbmd0aCwgX191OCByZXF1ZXN0KQp7CglpbnQgcmVzdWx0OwoJdW5zaWduZWQgY2hhciAqYnVmZmVyID0gIGttZW1kdXAoZGF0YSwgbGVuZ3RoLCBHRlBfS0VSTkVMKTsKCglpZiAoIWJ1ZmZlcikgewoJCWVycigiZW1pMjY6IGttYWxsb2MoJWQpIGZhaWxlZC4iLCBsZW5ndGgpOwoJCXJldHVybiAtRU5PTUVNOwoJfQoJLyogTm90ZTogdXNiX2NvbnRyb2xfbXNnIHJldHVybnMgbmVnYXRpdmUgdmFsdWUgb24gZXJyb3Igb3IgbGVuZ3RoIG9mIHRoZQoJICogCQkgZGF0YSB0aGF0IHdhcyB3cml0dGVuISAqLwoJcmVzdWx0ID0gdXNiX2NvbnRyb2xfbXNnIChkZXYsIHVzYl9zbmRjdHJscGlwZShkZXYsIDApLCByZXF1ZXN0LCAweDQwLCBhZGRyZXNzLCAwLCBidWZmZXIsIGxlbmd0aCwgMzAwKTsKCWtmcmVlIChidWZmZXIpOwoJcmV0dXJuIHJlc3VsdDsKfQoKLyogdGhhbmtzIHRvIGRyaXZlcnMvdXNiL3NlcmlhbC9rZXlzcGFuX3BkYS5jIGNvZGUgKi8Kc3RhdGljIGludCBlbWkyNl9zZXRfcmVzZXQgKHN0cnVjdCB1c2JfZGV2aWNlICpkZXYsIHVuc2lnbmVkIGNoYXIgcmVzZXRfYml0KQp7CglpbnQgcmVzcG9uc2U7CglpbmZvKCIlcyAtICVkIiwgX19GVU5DVElPTl9fLCByZXNldF9iaXQpOwoJLyogcHJpbnRrKEtFUk5fREVCVUcgIiVzIC0gJWQiLCBfX0ZVTkNUSU9OX18sIHJlc2V0X2JpdCk7ICovCglyZXNwb25zZSA9IGVtaTI2X3dyaXRlbWVtb3J5IChkZXYsIENQVUNTX1JFRywgJnJlc2V0X2JpdCwgMSwgMHhhMCk7CglpZiAocmVzcG9uc2UgPCAwKSB7CgkJZXJyKCJlbWkyNjogc2V0X3Jlc2V0ICglZCkgZmFpbGVkIiwgcmVzZXRfYml0KTsKCX0KCXJldHVybiByZXNwb25zZTsKfQoKI2RlZmluZSBGV19MT0FEX1NJWkUJCTEwMjMKCnN0YXRpYyBpbnQgZW1pMjZfbG9hZF9maXJtd2FyZSAoc3RydWN0IHVzYl9kZXZpY2UgKmRldikKewoJaW50IGVycjsKCWludCBpOwoJaW50IHBvcyA9IDA7CS8qIFBvc2l0aW9uIGluIGhleCByZWNvcmQgKi8KCV9fdTMyIGFkZHI7CS8qIEFkZHJlc3MgdG8gd3JpdGUgKi8KCV9fdTggKmJ1ZjsKCglidWYgPSBrbWFsbG9jKEZXX0xPQURfU0laRSwgR0ZQX0tFUk5FTCk7CglpZiAoIWJ1ZikgewoJCWVyciggIiVzIC0gZXJyb3IgbG9hZGluZyBmaXJtd2FyZTogZXJyb3IgPSAlZCIsIF9fRlVOQ1RJT05fXywgLUVOT01FTSk7CgkJZXJyID0gLUVOT01FTTsKCQlnb3RvIHdyYXBlcnI7Cgl9CgoJLyogQXNzZXJ0IHJlc2V0IChzdG9wIHRoZSBDUFUgaW4gdGhlIEVNSSkgKi8KCWVyciA9IGVtaTI2X3NldF9yZXNldChkZXYsMSk7CglpZiAoZXJyIDwgMCkgewoJCWVyciggIiVzIC0gZXJyb3IgbG9hZGluZyBmaXJtd2FyZTogZXJyb3IgPSAlZCIsIF9fRlVOQ1RJT05fXywgZXJyKTsKCQlnb3RvIHdyYXBlcnI7Cgl9CgoJLyogMS4gV2UgbmVlZCB0byBwdXQgdGhlIGxvYWRlciBmb3IgdGhlIEZQR0EgaW50byB0aGUgRVotVVNCICovCglmb3IgKGk9MDsgZ19Mb2FkZXJbaV0udHlwZSA9PSAwOyBpKyspIHsKCQllcnIgPSBlbWkyNl93cml0ZW1lbW9yeShkZXYsIGdfTG9hZGVyW2ldLmFkZHJlc3MsIGdfTG9hZGVyW2ldLmRhdGEsIGdfTG9hZGVyW2ldLmxlbmd0aCwgQU5DSE9SX0xPQURfSU5URVJOQUwpOwoJCWlmIChlcnIgPCAwKSB7CgkJCWVycigiJXMgLSBlcnJvciBsb2FkaW5nIGZpcm13YXJlOiBlcnJvciA9ICVkIiwgX19GVU5DVElPTl9fLCBlcnIpOwoJCQlnb3RvIHdyYXBlcnI7CgkJfQoJfQoKCS8qIERlLWFzc2VydCByZXNldCAobGV0IHRoZSBDUFUgcnVuKSAqLwoJZXJyID0gZW1pMjZfc2V0X3Jlc2V0KGRldiwwKTsKCW1zbGVlcCgyNTApOwkvKiBsZXQgZGV2aWNlIHNldHRsZSAqLwoKCS8qIDIuIFdlIHVwbG9hZCB0aGUgRlBHQSBmaXJtd2FyZSBpbnRvIHRoZSBFTUkKCSAqIE5vdGU6IGNvbGxlY3QgdXAgdG8gMTAyMyAoeWVzISkgYnl0ZXMgYW5kIHNlbmQgdGhlbSB3aXRoCgkgKiBhIHNpbmdsZSByZXF1ZXN0LiBUaGlzIGlzIF9tdWNoXyBmYXN0ZXIhICovCglkbyB7CgkJaSA9IDA7CgkJYWRkciA9IGdfYml0c3RyZWFtW3Bvc10uYWRkcmVzczsKCgkJLyogaW50ZWwgaGV4IHJlY29yZHMgYXJlIHRlcm1pbmF0ZWQgd2l0aCB0eXBlIDAgZWxlbWVudCAqLwoJCXdoaWxlICgoZ19iaXRzdHJlYW1bcG9zXS50eXBlID09IDApICYmIChpICsgZ19iaXRzdHJlYW1bcG9zXS5sZW5ndGggPCBGV19MT0FEX1NJWkUpKSB7CgkJCW1lbWNweShidWYgKyBpLCBnX2JpdHN0cmVhbVtwb3NdLmRhdGEsIGdfYml0c3RyZWFtW3Bvc10ubGVuZ3RoKTsKCQkJaSArPSBnX2JpdHN0cmVhbVtwb3NdLmxlbmd0aDsKCQkJcG9zKys7CgkJfQoJCWVyciA9IGVtaTI2X3dyaXRlbWVtb3J5KGRldiwgYWRkciwgYnVmLCBpLCBBTkNIT1JfTE9BRF9GUEdBKTsKCQlpZiAoZXJyIDwgMCkgewoJCQllcnIoIiVzIC0gZXJyb3IgbG9hZGluZyBmaXJtd2FyZTogZXJyb3IgPSAlZCIsIF9fRlVOQ1RJT05fXywgZXJyKTsKCQkJZ290byB3cmFwZXJyOwoJCX0KCX0gd2hpbGUgKGkgPiAwKTsKCgkvKiBBc3NlcnQgcmVzZXQgKHN0b3AgdGhlIENQVSBpbiB0aGUgRU1JKSAqLwoJZXJyID0gZW1pMjZfc2V0X3Jlc2V0KGRldiwxKTsKCWlmIChlcnIgPCAwKSB7CgkJZXJyKCIlcyAtIGVycm9yIGxvYWRpbmcgZmlybXdhcmU6IGVycm9yID0gJWQiLCBfX0ZVTkNUSU9OX18sIGVycik7CgkJZ290byB3cmFwZXJyOwoJfQoKCS8qIDMuIFdlIG5lZWQgdG8gcHV0IHRoZSBsb2FkZXIgZm9yIHRoZSBmaXJtd2FyZSBpbnRvIHRoZSBFWi1VU0IgKGFnYWluLi4uKSAqLwoJZm9yIChpPTA7IGdfTG9hZGVyW2ldLnR5cGUgPT0gMDsgaSsrKSB7CgkJZXJyID0gZW1pMjZfd3JpdGVtZW1vcnkoZGV2LCBnX0xvYWRlcltpXS5hZGRyZXNzLCBnX0xvYWRlcltpXS5kYXRhLCBnX0xvYWRlcltpXS5sZW5ndGgsIEFOQ0hPUl9MT0FEX0lOVEVSTkFMKTsKCQlpZiAoZXJyIDwgMCkgewoJCQllcnIoIiVzIC0gZXJyb3IgbG9hZGluZyBmaXJtd2FyZTogZXJyb3IgPSAlZCIsIF9fRlVOQ1RJT05fXywgZXJyKTsKCQkJZ290byB3cmFwZXJyOwoJCX0KCX0KCW1zbGVlcCgyNTApOwkvKiBsZXQgZGV2aWNlIHNldHRsZSAqLwoKCS8qIERlLWFzc2VydCByZXNldCAobGV0IHRoZSBDUFUgcnVuKSAqLwoJZXJyID0gZW1pMjZfc2V0X3Jlc2V0KGRldiwwKTsKCWlmIChlcnIgPCAwKSB7CgkJZXJyKCIlcyAtIGVycm9yIGxvYWRpbmcgZmlybXdhcmU6IGVycm9yID0gJWQiLCBfX0ZVTkNUSU9OX18sIGVycik7CgkJZ290byB3cmFwZXJyOwoJfQoKCS8qIDQuIFdlIHB1dCB0aGUgcGFydCBvZiB0aGUgZmlybXdhcmUgdGhhdCBsaWVzIGluIHRoZSBleHRlcm5hbCBSQU0gaW50byB0aGUgRVotVVNCICovCglmb3IgKGk9MDsgZ19GaXJtd2FyZVtpXS50eXBlID09IDA7IGkrKykgewoJCWlmICghSU5URVJOQUxfUkFNKGdfRmlybXdhcmVbaV0uYWRkcmVzcykpIHsKCQkJZXJyID0gZW1pMjZfd3JpdGVtZW1vcnkoZGV2LCBnX0Zpcm13YXJlW2ldLmFkZHJlc3MsIGdfRmlybXdhcmVbaV0uZGF0YSwgZ19GaXJtd2FyZVtpXS5sZW5ndGgsIEFOQ0hPUl9MT0FEX0VYVEVSTkFMKTsKCQkJaWYgKGVyciA8IDApIHsKCQkJCWVycigiJXMgLSBlcnJvciBsb2FkaW5nIGZpcm13YXJlOiBlcnJvciA9ICVkIiwgX19GVU5DVElPTl9fLCBlcnIpOwoJCQkJZ290byB3cmFwZXJyOwoJCQl9CgkJfQoJfQoJCgkvKiBBc3NlcnQgcmVzZXQgKHN0b3AgdGhlIENQVSBpbiB0aGUgRU1JKSAqLwoJZXJyID0gZW1pMjZfc2V0X3Jlc2V0KGRldiwxKTsKCWlmIChlcnIgPCAwKSB7CgkJZXJyKCIlcyAtIGVycm9yIGxvYWRpbmcgZmlybXdhcmU6IGVycm9yID0gJWQiLCBfX0ZVTkNUSU9OX18sIGVycik7CgkJZ290byB3cmFwZXJyOwoJfQoKCWZvciAoaT0wOyBnX0Zpcm13YXJlW2ldLnR5cGUgPT0gMDsgaSsrKSB7CgkJaWYgKElOVEVSTkFMX1JBTShnX0Zpcm13YXJlW2ldLmFkZHJlc3MpKSB7CgkJCWVyciA9IGVtaTI2X3dyaXRlbWVtb3J5KGRldiwgZ19GaXJtd2FyZVtpXS5hZGRyZXNzLCBnX0Zpcm13YXJlW2ldLmRhdGEsIGdfRmlybXdhcmVbaV0ubGVuZ3RoLCBBTkNIT1JfTE9BRF9JTlRFUk5BTCk7CgkJCWlmIChlcnIgPCAwKSB7CgkJCQllcnIoIiVzIC0gZXJyb3IgbG9hZGluZyBmaXJtd2FyZTogZXJyb3IgPSAlZCIsIF9fRlVOQ1RJT05fXywgZXJyKTsKCQkJCWdvdG8gd3JhcGVycjsKCQkJfQoJCX0KCX0KCgkvKiBEZS1hc3NlcnQgcmVzZXQgKGxldCB0aGUgQ1BVIHJ1bikgKi8KCWVyciA9IGVtaTI2X3NldF9yZXNldChkZXYsMCk7CglpZiAoZXJyIDwgMCkgewoJCWVycigiJXMgLSBlcnJvciBsb2FkaW5nIGZpcm13YXJlOiBlcnJvciA9ICVkIiwgX19GVU5DVElPTl9fLCBlcnIpOwoJCWdvdG8gd3JhcGVycjsKCX0KCW1zbGVlcCgyNTApOwkvKiBsZXQgZGV2aWNlIHNldHRsZSAqLwoKCS8qIHJldHVybiAxIHRvIGZhaWwgdGhlIGRyaXZlciBpbmlhbGl6YXRpb24KCSAqIGFuZCBnaXZlIHJlYWwgZHJpdmVyIGNoYW5nZSB0byBsb2FkICovCgllcnIgPSAxOwoKd3JhcGVycjoKCWtmcmVlKGJ1Zik7CglyZXR1cm4gZXJyOwp9CgpzdGF0aWMgc3RydWN0IHVzYl9kZXZpY2VfaWQgaWRfdGFibGUgW10gPSB7Cgl7IFVTQl9ERVZJQ0UoRU1JMjZfVkVORE9SX0lELCBFTUkyNl9QUk9EVUNUX0lEKSB9LAoJeyBVU0JfREVWSUNFKEVNSTI2X1ZFTkRPUl9JRCwgRU1JMjZCX1BST0RVQ1RfSUQpIH0sCgl7IH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvKiBUZXJtaW5hdGluZyBlbnRyeSAqLwp9OwoKTU9EVUxFX0RFVklDRV9UQUJMRSAodXNiLCBpZF90YWJsZSk7CgpzdGF0aWMgaW50IGVtaTI2X3Byb2JlKHN0cnVjdCB1c2JfaW50ZXJmYWNlICppbnRmLCBjb25zdCBzdHJ1Y3QgdXNiX2RldmljZV9pZCAqaWQpCnsKCXN0cnVjdCB1c2JfZGV2aWNlICpkZXYgPSBpbnRlcmZhY2VfdG9fdXNiZGV2KGludGYpOwoKCWluZm8oIiVzIHN0YXJ0IiwgX19GVU5DVElPTl9fKTsgCgoJZW1pMjZfbG9hZF9maXJtd2FyZShkZXYpOwoKCS8qIGRvIG5vdCByZXR1cm4gdGhlIGRyaXZlciBjb250ZXh0LCBsZXQgcmVhbCBhdWRpbyBkcml2ZXIgZG8gdGhhdCAqLwoJcmV0dXJuIC1FSU87Cn0KCnN0YXRpYyB2b2lkIGVtaTI2X2Rpc2Nvbm5lY3Qoc3RydWN0IHVzYl9pbnRlcmZhY2UgKmludGYpCnsKfQoKc3RhdGljIHN0cnVjdCB1c2JfZHJpdmVyIGVtaTI2X2RyaXZlciA9IHsKCS5uYW1lCQk9ICJlbWkyNiAtIGZpcm13YXJlIGxvYWRlciIsCgkucHJvYmUJCT0gZW1pMjZfcHJvYmUsCgkuZGlzY29ubmVjdAk9IGVtaTI2X2Rpc2Nvbm5lY3QsCgkuaWRfdGFibGUJPSBpZF90YWJsZSwKfTsKCnN0YXRpYyBpbnQgX19pbml0IGVtaTI2X2luaXQgKHZvaWQpCnsKCXJldHVybiB1c2JfcmVnaXN0ZXIoJmVtaTI2X2RyaXZlcik7Cn0KCnN0YXRpYyB2b2lkIF9fZXhpdCBlbWkyNl9leGl0ICh2b2lkKQp7Cgl1c2JfZGVyZWdpc3RlciAoJmVtaTI2X2RyaXZlcik7Cn0KCm1vZHVsZV9pbml0KGVtaTI2X2luaXQpOwptb2R1bGVfZXhpdChlbWkyNl9leGl0KTsKCk1PRFVMRV9BVVRIT1IoInRhcGlvIGxheHN0cvZtIik7Ck1PRFVMRV9ERVNDUklQVElPTigiRW1hZ2ljIEVNSSAyfDYgZmlybXdhcmUgbG9hZGVyLiIpOwpNT0RVTEVfTElDRU5TRSgiR1BMIik7CgovKiB2aTphaTpzeW50YXg9Yzpzdz04OnRzPTg6dHc9ODAKICovCg==