LyoKICogRE9TIGRldmljZXMKICoKICogQ29weXJpZ2h0IDE5OTkgT3ZlIEvldmVuCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKICogbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIKICogdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiAqCiAqIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVQogKiBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKICogRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgIDAyMTExLTEzMDcgIFVTQQogKi8KCiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSAid2luZS93aW5iYXNlMTYuaCIKI2luY2x1ZGUgImRvc2V4ZS5oIgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgoKI2luY2x1ZGUgInBzaHBhY2sxLmgiCgovKiBXYXJuaW5nOiBuZWVkIHRvIHJldHVybiBMT0wgcHRyIHcvIG9mZnNldCAwICgmcHRyX2ZpcnN0X0RQQikgdG8gcHJvZ3JhbXMgISAqLwp0eXBlZGVmIHN0cnVjdCBfRE9TX0xJU1RPRkxJU1RTCnsKICAgIFdPUkQgIENYX0ludDIxXzVlMDE7ICAgICAgICAvKiAtMjRkIGNvbnRlbnRzIG9mIENYIGZyb20gSU5UIDIxL0FYPTVFMDFoICovCiAgICBXT1JEICBMUlVfY291bnRfRkNCX2NhY2hlOyAgLyogLTIyZCAqLwogICAgV09SRCAgTFJVX2NvdW50X0ZDQl9vcGVuOyAgIC8qIC0yMGQgKi8KICAgIERXT1JEIE9FTV9mdW5jX2hhbmRsZXI7ICAgICAvKiAtMThkIE9FTSBmdW5jdGlvbiBvZiBJTlQgMjEvQUg9RjhoICovCiAgICBXT1JEICBJTlQyMV9vZmZzZXQ7ICAgICAgICAgLyogLTE0ZCBvZmZzZXQgaW4gRE9TIENTIG9mIGNvZGUgdG8gcmV0dXJuIGZyb20gSU5UIDIxIGNhbGwgKi8KICAgIFdPUkQgIHNoYXJpbmdfcmV0cnlfY291bnQ7ICAvKiAtMTJkICovCiAgICBXT1JEICBzaGFyaW5nX3JldHJ5X2RlbGF5OyAgLyogLTEwZCAqLwogICAgRFdPUkQgcHRyX2Rpc2tfYnVmOyAgICAgICAgIC8qIC04ZCBwdHIgdG8gY3VycmVudCBkaXNrIGJ1ZiAqLwogICAgV09SRCAgb2Zmc191bnJlYWRfQ09OOyAgICAgIC8qIC00ZCBwb2ludGVyIGluIERPUyBkYXRhIHNlZ21lbnQgb2YgdW5yZWFkIENPTiBpbnB1dCAqLwogICAgV09SRCAgc2VnX2ZpcnN0X01DQjsgICAgICAgIC8qIC0yZCAqLwogICAgRFdPUkQgcHRyX2ZpcnN0X0RQQjsgICAgICAgIC8qIDAwICovCiAgICBEV09SRCBwdHJfZmlyc3RfU3lzRmlsZVRhYmxlOyAvKiAwNCAqLwogICAgRFdPUkQgcHRyX2Nsb2NrX2Rldl9oZHI7ICAgIC8qIDA4ICovCiAgICBEV09SRCBwdHJfQ09OX2Rldl9oZHI7ICAgICAgLyogMEMgKi8KICAgIFdPUkQgIG1heF9ieXRlX3Blcl9zZWM7ICAgICAvKiAxMCBtYXhpbXVtIGJ5dGVzIHBlciBzZWN0b3Igb2YgYW55IGJsb2NrIGRldmljZSAqLwogICAgRFdPUkQgcHRyX2Rpc2tfYnVmX2luZm87ICAgIC8qIDEyICovCiAgICBEV09SRCBwdHJfYXJyYXlfQ0RTOyAgICAgICAgLyogMTYgY3VycmVudCBkaXJlY3Rvcnkgc3RydWN0dXJlICovCiAgICBEV09SRCBwdHJfc3lzX0ZDQjsgICAgICAgICAgLyogMUEgKi8KICAgIFdPUkQgIG5yX3Byb3RlY3RfRkNCOyAgICAgICAvKiAxRSAqLwogICAgQllURSAgbnJfYmxvY2tfZGV2OyAgICAgICAgIC8qIDIwICovCiAgICBCWVRFICBucl9hdmFpbF9kcml2ZV9sZXR0ZXJzOyAvKiAyMSAqLwogICAgRE9TX0RFVklDRV9IRUFERVIgTlVMX2RldjsgIC8qIDIyICovCiAgICBCWVRFICBucl9kcml2ZXNfSk9JTmVkOyAgICAgLyogMzQgKi8KICAgIFdPUkQgIHB0cl9zcGVjX3ByZ19uYW1lczsgICAvKiAzNSAqLwogICAgRFdPUkQgcHRyX1NFVFZFUl9wcmdfbGlzdDsgIC8qIDM3ICovCiAgICBXT1JEIERPU19ISUdIX0EyMF9mdW5jX29mZnM7LyogM0IgKi8KICAgIFdPUkQgUFNQX2xhc3RfZXhlYzsgICAgICAgICAvKiAzRCBpZiBET1MgaW4gSE1BOiBQU1Agb2YgcHJvZ3JhbSBleGVjdXRlZCBsYXN0OyBpZiBET1MgbG93OiAwMDAwaCAqLwogICAgV09SRCBCVUZGRVJTX3ZhbDsgICAgICAgICAgIC8qIDNGICovCiAgICBXT1JEIEJVRkZFUlNfbnJfbG9va2FoZWFkOyAgLyogNDEgKi8KICAgIEJZVEUgYm9vdF9kcml2ZTsgICAgICAgICAgICAvKiA0MyAqLwogICAgQllURSBmbGFnX0RXT1JEX21vdmVzOyAgICAgIC8qIDQ0IDAxaCBmb3IgMzg2KywgMDBoIG90aGVyd2lzZSAqLwogICAgV09SRCBzaXplX2V4dGVuZGVkX21lbTsgICAgIC8qIDQ1IHNpemUgb2YgZXh0ZW5kZWQgbWVtIGluIEtCICovCiAgICBTRUdQVFIgd2luZV9ybV9sb2w7ICAgICAgICAgLyogLS0gd2luZTogUmVhbCBtb2RlIHBvaW50ZXIgdG8gTE9MICovCiAgICBTRUdQVFIgd2luZV9wbV9sb2w7ICAgICAgICAgLyogLS0gd2luZTogUHJvdGVjdGVkIG1vZGUgcG9pbnRlciB0byBMT0wgKi8KfSBET1NfTElTVE9GTElTVFM7CgojaW5jbHVkZSAicG9wcGFjay5oIgoKI2RlZmluZSBDT05fQlVGRkVSIDEyOAoKZW51bSBzdHJhdGVneSB7IFNZU1RFTV9TVFJBVEVHWV9OVUwsIFNZU1RFTV9TVFJBVEVHWV9DT04sIE5CX1NZU1RFTV9TVFJBVEVHSUVTIH07CgpzdGF0aWMgdm9pZCAqc3RyYXRlZ3lfZGF0YVtOQl9TWVNURU1fU1RSQVRFR0lFU107CgojZGVmaW5lIExKTVAgMHhlYQoKCi8qIHByb3RvdHlwZXMgKi8Kc3RhdGljIHZvaWQgV0lOQVBJIG51bF9zdHJhdGVneShDT05URVhUODYqY3R4KTsKc3RhdGljIHZvaWQgV0lOQVBJIG51bF9pbnRlcnJ1cHQoQ09OVEVYVDg2KmN0eCk7CnN0YXRpYyB2b2lkIFdJTkFQSSBjb25fc3RyYXRlZ3koQ09OVEVYVDg2KmN0eCk7CnN0YXRpYyB2b2lkIFdJTkFQSSBjb25faW50ZXJydXB0KENPTlRFWFQ4NipjdHgpOwoKLyogZGV2aWNlcyAqLwpzdGF0aWMgV0lORURFViBkZXZzW10gPQp7CiAgeyAiTlVMICAgICAiLAogICAgQVRUUl9DSEFSfEFUVFJfTlVMfEFUVFJfREVWSUNFLAogICAgbnVsX3N0cmF0ZWd5LCBudWxfaW50ZXJydXB0IH0sCgogIHsgIkNPTiAgICAgIiwKICAgIEFUVFJfQ0hBUnxBVFRSX1NURElOfEFUVFJfU1RET1VUfEFUVFJfRkFTVENPTnxBVFRSX05PVEVPRnxBVFRSX0RFVklDRSwKICAgIGNvbl9zdHJhdGVneSwgY29uX2ludGVycnVwdCB9Cn07CgojZGVmaW5lIE5SX0RFVlMgKHNpemVvZihkZXZzKS9zaXplb2YoV0lORURFVikpCgovKiBET1MgZGF0YSBzZWdtZW50ICovCnR5cGVkZWYgc3RydWN0CnsKICAgIERPU19MSVNUT0ZMSVNUUyAgICBsb2w7CiAgICBET1NfREVWSUNFX0hFQURFUiAgZGV2W05SX0RFVlMtMV07CiAgICBET1NfREVWSUNFX0hFQURFUiAqbGFzdF9kZXY7IC8qIHB0ciB0byBsYXN0IHJlZ2lzdGVyZWQgZGV2aWNlIGRyaXZlciAqLwogICAgV0lORURFVl9USFVOSyAgICAgIHRodW5rW05SX0RFVlNdOwogICAgUkVRX0lPICAgICAgICAgICAgIHJlcTsKICAgIEJZVEUgICAgICAgICAgICAgICBidWZmZXJbQ09OX0JVRkZFUl07Cgp9IERPU19EQVRBU0VHOwoKI2RlZmluZSBET1NfREFUQVNFR19PRkYoeHh4KSBGSUVMRF9PRkZTRVQoRE9TX0RBVEFTRUcsIHh4eCkKCkRXT1JEIERPU19MT0xTZWc7CgpzdGF0aWMgc3RydWN0IF9ET1NfTElTVE9GTElTVFMgKiBET1NNRU1fTE9MKHZvaWQpCnsKICAgIHJldHVybiBQVFJfUkVBTF9UT19MSU4oSElXT1JEKERPU19MT0xTZWcpLDApOwp9CgoKLyogdGhlIGRldmljZSBpbXBsZW1lbnRhdGlvbnMgKi8Kc3RhdGljIHZvaWQgZG9fbHJldChDT05URVhUODYqY3R4KQp7CiAgV09SRCAqc3RhY2sgPSBDVFhfU0VHX09GRl9UT19MSU4oY3R4LCBjdHgtPlNlZ1NzLCBjdHgtPkVzcCk7CgogIGN0eC0+RWlwICAgPSAqKHN0YWNrKyspOwogIGN0eC0+U2VnQ3MgPSAqKHN0YWNrKyspOwogIGN0eC0+RXNwICArPSAyKnNpemVvZihXT1JEKTsKfQoKc3RhdGljIHZvaWQgZG9fc3RyYXRlZ3koQ09OVEVYVDg2KmN0eCwgaW50IGlkLCBpbnQgZXh0cmEpCnsKICBSRVFVRVNUX0hFQURFUiAqaGRyID0gQ1RYX1NFR19PRkZfVE9fTElOKGN0eCwgY3R4LT5TZWdFcywgY3R4LT5FYngpOwogIHZvaWQgKipoZHJfcHRyID0gc3RyYXRlZ3lfZGF0YVtpZF07CgogIGlmICghaGRyX3B0cikgewogICAgaGRyX3B0ciA9IGNhbGxvYygxLHNpemVvZih2b2lkICopK2V4dHJhKTsKICAgIHN0cmF0ZWd5X2RhdGFbaWRdID0gaGRyX3B0cjsKICB9CiAgKmhkcl9wdHIgPSBoZHI7CiAgZG9fbHJldChjdHgpOwp9CgpzdGF0aWMgUkVRVUVTVF9IRUFERVIgKiBnZXRfaGRyKGludCBpZCwgdm9pZCoqZXh0cmEpCnsKICB2b2lkICoqaGRyX3B0ciA9IHN0cmF0ZWd5X2RhdGFbaWRdOwogIGlmIChleHRyYSkKICAgICpleHRyYSA9IGhkcl9wdHIgPyAodm9pZCopKGhkcl9wdHIrMSkgOiAodm9pZCAqKU5VTEw7CiAgcmV0dXJuIGhkcl9wdHIgPyAqaGRyX3B0ciA6ICh2b2lkICopTlVMTDsKfQoKc3RhdGljIHZvaWQgV0lOQVBJIG51bF9zdHJhdGVneShDT05URVhUODYqY3R4KQp7CiAgZG9fc3RyYXRlZ3koY3R4LCBTWVNURU1fU1RSQVRFR1lfTlVMLCAwKTsKfQoKc3RhdGljIHZvaWQgV0lOQVBJIG51bF9pbnRlcnJ1cHQoQ09OVEVYVDg2KmN0eCkKewogIFJFUVVFU1RfSEVBREVSICpoZHIgPSBnZXRfaGRyKFNZU1RFTV9TVFJBVEVHWV9OVUwsIE5VTEwpOwogIC8qIGVhdCBldmVyeXRoaW5nIGFuZCByZWN5Y2xlIG5vdGhpbmcgKi8KICBzd2l0Y2ggKGhkci0+Y29tbWFuZCkgewogIGNhc2UgQ01EX0lOUFVUOgogICAgKChSRVFfSU8qKWhkciktPmNvdW50ID0gMDsKICAgIGhkci0+c3RhdHVzID0gU1RBVF9ET05FOwogICAgYnJlYWs7CiAgY2FzZSBDTURfU0FGRUlOUFVUOgogICAgaGRyLT5zdGF0dXMgPSBTVEFUX0RPTkV8U1RBVF9CVVNZOwogICAgYnJlYWs7CiAgZGVmYXVsdDoKICAgIGhkci0+c3RhdHVzID0gU1RBVF9ET05FOwogIH0KICBkb19scmV0KGN0eCk7Cn0KCnN0YXRpYyB2b2lkIFdJTkFQSSBjb25fc3RyYXRlZ3koQ09OVEVYVDg2KmN0eCkKewogIGRvX3N0cmF0ZWd5KGN0eCwgU1lTVEVNX1NUUkFURUdZX0NPTiwgc2l6ZW9mKGludCkpOwp9CgpzdGF0aWMgdm9pZCBXSU5BUEkgY29uX2ludGVycnVwdChDT05URVhUODYqY3R4KQp7CiAgaW50ICpzY2FuOwogIFJFUVVFU1RfSEVBREVSICpoZHIgPSBnZXRfaGRyKFNZU1RFTV9TVFJBVEVHWV9DT04sKHZvaWQgKiopJnNjYW4pOwogIEJJT1NEQVRBICpiaW9zID0gRE9TVk1fQmlvc0RhdGEoKTsKICBXT1JEIEN1ck9mcyA9IGJpb3MtPk5leHRLYmRDaGFyUHRyOwogIERPU19MSVNUT0ZMSVNUUyAqbG9sID0gRE9TTUVNX0xPTCgpOwogIERPU19EQVRBU0VHICpkYXRhc2VnID0gKERPU19EQVRBU0VHICopbG9sOwogIEJZVEUgKmxpbmVidWZmZXIgPSBkYXRhc2VnLT5idWZmZXI7CiAgQllURSAqY3VyYnVmZmVyID0gKGxvbC0+b2Zmc191bnJlYWRfQ09OKSA/CiAgICAoKChCWVRFKilkYXRhc2VnKSArIGxvbC0+b2Zmc191bnJlYWRfQ09OKSA6IChCWVRFKilOVUxMOwogIERPU19ERVZJQ0VfSEVBREVSICpjb24gPSBkYXRhc2VnLT5kZXY7CiAgRFdPUkQgdzsKCiAgc3dpdGNoIChoZHItPmNvbW1hbmQpIHsKICBjYXNlIENNRF9JTlBVVDoKICAgIHsKICAgICAgUkVRX0lPICppbyA9IChSRVFfSU8gKiloZHI7CiAgICAgIFdPUkQgY291bnQgPSBpby0+Y291bnQsIGxlbiA9IDA7CiAgICAgIEJZVEUgKmJ1ZmZlciA9IENUWF9TRUdfT0ZGX1RPX0xJTihjdHgsCgkJCQkJU0VMRUNUT1JPRihpby0+YnVmZmVyKSwKCQkJCQkoRFdPUkQpT0ZGU0VUT0YoaW8tPmJ1ZmZlcikpOwoKICAgICAgaGRyLT5zdGF0dXMgPSBTVEFUX0JVU1k7CiAgICAgIC8qIGZpcnN0LCBjaGVjayB3aGV0aGVyIHdlIGFscmVhZHkgaGF2ZSBkYXRhIGluIGxpbmUgYnVmZmVyICovCiAgICAgIGlmIChjdXJidWZmZXIpIHsKCS8qIHllcCwgY29weSBhcyBtdWNoIGFzIHdlIGNhbiAqLwoJQllURSBkYXRhID0gMDsKCXdoaWxlICgobGVuPGNvdW50KSAmJiAoZGF0YSAhPSAnXHInKSkgewoJICBkYXRhID0gKmN1cmJ1ZmZlcisrOwoJICBidWZmZXJbbGVuKytdID0gZGF0YTsKCX0KCWlmIChkYXRhID09ICdccicpIHsKCSAgLyogbGluZSBidWZmZXIgZW1wdGllZCAqLwoJICBsb2wtPm9mZnNfdW5yZWFkX0NPTiA9IDA7CgkgIGN1cmJ1ZmZlciA9IE5VTEw7CgkgIC8qIGlmIHdlJ3JlIG5vdCBpbiByYXcgbW9kZSwgY2FsbCBpdCBhIGRheSAqLwoJICBpZiAoIShjb24tPmF0dHIgJiBBVFRSX1JBVykpIHsKCSAgICBoZHItPnN0YXR1cyA9IFNUQVRfRE9ORTsKCSAgICBpby0+Y291bnQgPSBsZW47CgkgICAgYnJlYWs7CgkgIH0KCX0gZWxzZSB7CgkgIC8qIHN0aWxsIHNvbWUgZGF0YSBsZWZ0ICovCgkgIGxvbC0+b2Zmc191bnJlYWRfQ09OID0gY3VyYnVmZmVyIC0gKEJZVEUqKWxvbDsKCSAgLyogYnV0IGJ1ZmZlciB3YXMgZmlsbGVkLCB3ZSdyZSBkb25lICovCgkgIGhkci0+c3RhdHVzID0gU1RBVF9ET05FOwoJICBpby0+Y291bnQgPSBsZW47CgkgIGJyZWFrOwoJfQogICAgICB9CgogICAgICAvKiBpZiB3ZSdyZSBpbiByYXcgbW9kZSwgd2UganVzdCBuZWVkIHRvIGZpbGwgdGhlIGJ1ZmZlciAqLwogICAgICBpZiAoY29uLT5hdHRyICYgQVRUUl9SQVcpIHsKCXdoaWxlIChsZW48Y291bnQpIHsKCSAgV09SRCBkYXRhOwoKCSAgLyogZG8gd2UgaGF2ZSBhIHdhaXRpbmcgc2NhbmNvZGU/ICovCgkgIGlmICgqc2NhbikgewoJICAgIC8qIHllcywgc3RvcmUgc2NhbmNvZGUgaW4gYnVmZmVyICovCgkgICAgYnVmZmVyW2xlbisrXSA9ICpzY2FuOwoJICAgICpzY2FuID0gMDsKCSAgICBpZiAobGVuPT1jb3VudCkgYnJlYWs7CgkgIH0KCgkgIC8qIGNoZWNrIGZvciBuZXcga2V5Ym9hcmQgaW5wdXQgKi8KCSAgd2hpbGUgKEN1ck9mcyA9PSBiaW9zLT5GaXJzdEtiZENoYXJQdHIpIHsKCSAgICAvKiBubyBpbnB1dCBhdmFpbGFibGUgeWV0LCBzbyB3YWl0Li4uICovCgkgICAgRE9TVk1fV2FpdCggY3R4ICk7CgkgIH0KCSAgLyogcmVhZCBmcm9tIGtleWJvYXJkIHF1ZXVlIChjYWxsIGludDE2PykgKi8KCSAgZGF0YSA9ICgoV09SRCopYmlvcylbQ3VyT2ZzXTsKCSAgQ3VyT2ZzICs9IDI7CgkgIGlmIChDdXJPZnMgPj0gYmlvcy0+S2JkQnVmZmVyRW5kKSBDdXJPZnMgPSBiaW9zLT5LYmRCdWZmZXJTdGFydDsKCSAgYmlvcy0+TmV4dEtiZENoYXJQdHIgPSBDdXJPZnM7CgkgIC8qIGlmIGl0J3MgYW4gZXh0ZW5kZWQga2V5LCBzYXZlIHNjYW5jb2RlICovCgkgIGlmIChMT0JZVEUoZGF0YSkgPT0gMCkgKnNjYW4gPSBISUJZVEUoZGF0YSk7CgkgIC8qIHN0b3JlIEFTQ0lJIGNoYXIgaW4gYnVmZmVyICovCgkgIGJ1ZmZlcltsZW4rK10gPSBMT0JZVEUoZGF0YSk7Cgl9CiAgICAgIH0gZWxzZSB7CgkvKiB3ZSdyZSBub3QgaW4gcmF3IG1vZGUsIHNvIHdlIG5lZWQgdG8gZG8gbGluZSBpbnB1dC4uLiAqLwoJd2hpbGUgKFRSVUUpIHsKCSAgV09SRCBkYXRhOwoJICAvKiBjaGVjayBmb3IgbmV3IGtleWJvYXJkIGlucHV0ICovCgkgIHdoaWxlIChDdXJPZnMgPT0gYmlvcy0+Rmlyc3RLYmRDaGFyUHRyKSB7CgkgICAgLyogbm8gaW5wdXQgYXZhaWxhYmxlIHlldCwgc28gd2FpdC4uLiAqLwoJICAgIERPU1ZNX1dhaXQoIGN0eCApOwoJICB9CgkgIC8qIHJlYWQgZnJvbSBrZXlib2FyZCBxdWV1ZSAoY2FsbCBpbnQxNj8pICovCgkgIGRhdGEgPSAoKFdPUkQqKWJpb3MpW0N1ck9mc107CgkgIEN1ck9mcyArPSAyOwoJICBpZiAoQ3VyT2ZzID49IGJpb3MtPktiZEJ1ZmZlckVuZCkgQ3VyT2ZzID0gYmlvcy0+S2JkQnVmZmVyU3RhcnQ7CgkgIGJpb3MtPk5leHRLYmRDaGFyUHRyID0gQ3VyT2ZzOwoKCSAgaWYgKExPQllURShkYXRhKSA9PSAnXHInKSB7CgkgICAgLyogaXQncyB0aGUgcmV0dXJuIGtleSwgd2UncmUgZG9uZSAqLwoJICAgIGxpbmVidWZmZXJbbGVuKytdID0gTE9CWVRFKGRhdGEpOwoJICAgIGJyZWFrOwoJICB9CgkgIGVsc2UgaWYgKExPQllURShkYXRhKSA+PSAnICcpIHsKCSAgICAvKiBhIGNoYXJhY3RlciAqLwoJICAgIGlmICgobGVuKzEpPENPTl9CVUZGRVIpIHsKCSAgICAgIGxpbmVidWZmZXJbbGVuXSA9IExPQllURShkYXRhKTsKCSAgICAgIFdyaXRlRmlsZShHZXRTdGRIYW5kbGUoU1REX09VVFBVVF9IQU5ETEUpLCAmbGluZWJ1ZmZlcltsZW4rK10sIDEsICZ3LCBOVUxMKTsKCSAgICB9CgkgICAgLyogZWxzZSBiZWVwLCBidXQgSSBkb24ndCBsaWtlIG5vaXNlICovCgkgIH0KCSAgZWxzZSBzd2l0Y2ggKExPQllURShkYXRhKSkgewoJICBjYXNlICdcYic6CgkgICAgaWYgKGxlbj4wKSB7CgkgICAgICBsZW4tLTsKCSAgICAgIFdyaXRlRmlsZShHZXRTdGRIYW5kbGUoU1REX09VVFBVVF9IQU5ETEUpLCAiXGIgXGIiLCAzLCAmdywgTlVMTCk7CgkgICAgfQoJICAgIGJyZWFrOwoJICB9Cgl9CglpZiAobGVuID4gY291bnQpIHsKCSAgLyogc2F2ZSByZXN0IG9mIGxpbmUgZm9yIGxhdGVyICovCgkgIGxvbC0+b2Zmc191bnJlYWRfQ09OID0gbGluZWJ1ZmZlciAtIChCWVRFKilsb2wgKyBjb3VudDsKCSAgbGVuID0gY291bnQ7Cgl9CgltZW1jcHkoYnVmZmVyLCBsaW5lYnVmZmVyLCBsZW4pOwogICAgICB9CiAgICAgIGhkci0+c3RhdHVzID0gU1RBVF9ET05FOwogICAgICBpby0+Y291bnQgPSBsZW47CiAgICB9CiAgICBicmVhazsKICBjYXNlIENNRF9TQUZFSU5QVVQ6CiAgICBpZiAoY3VyYnVmZmVyKSB7CiAgICAgIC8qIHNvbWUgbGluZSBpbnB1dCB3YWl0aW5nICovCiAgICAgIGhkci0+c3RhdHVzID0gU1RBVF9ET05FOwogICAgICAoKFJFUV9TQUZFSU5QVVQqKWhkciktPmRhdGEgPSAqY3VyYnVmZmVyOwogICAgfQogICAgZWxzZSBpZiAoY29uLT5hdHRyICYgQVRUUl9SQVcpIHsKICAgICAgaWYgKEN1ck9mcyA9PSBiaW9zLT5GaXJzdEtiZENoYXJQdHIpIHsKCS8qIG5vIGlucHV0ICovCgloZHItPnN0YXR1cyA9IFNUQVRfRE9ORXxTVEFUX0JVU1k7CiAgICAgIH0gZWxzZSB7CgkvKiBzb21lIGtleWJvYXJkIGlucHV0IHdhaXRpbmcgKi8KCWhkci0+c3RhdHVzID0gU1RBVF9ET05FOwoJKChSRVFfU0FGRUlOUFVUKiloZHIpLT5kYXRhID0gKChCWVRFKiliaW9zKVtDdXJPZnNdOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICAvKiBubyBsaW5lIGlucHV0ICovCiAgICAgIGhkci0+c3RhdHVzID0gU1RBVF9ET05FfFNUQVRfQlVTWTsKICAgIH0KICAgIGJyZWFrOwogIGNhc2UgQ01EX0lOU1RBVFVTOgogICAgaWYgKGN1cmJ1ZmZlcikgewogICAgICAvKiB3ZSBoYXZlIGRhdGEgKi8KICAgICAgaGRyLT5zdGF0dXMgPSBTVEFUX0RPTkU7CiAgICB9CiAgICBlbHNlIGlmIChjb24tPmF0dHIgJiBBVFRSX1JBVykgewogICAgICBpZiAoQ3VyT2ZzID09IGJpb3MtPkZpcnN0S2JkQ2hhclB0cikgewoJLyogbm8gaW5wdXQgKi8KCWhkci0+c3RhdHVzID0gU1RBVF9ET05FfFNUQVRfQlVTWTsKICAgICAgfSBlbHNlIHsKCS8qIHNvbWUga2V5Ym9hcmQgaW5wdXQgd2FpdGluZyAqLwoJaGRyLT5zdGF0dXMgPSBTVEFUX0RPTkU7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIC8qIG5vIGxpbmUgaW5wdXQgKi8KICAgICAgaGRyLT5zdGF0dXMgPSBTVEFUX0RPTkV8U1RBVF9CVVNZOwogICAgfQoKICAgIGJyZWFrOwogIGNhc2UgQ01EX0lORkxVU0g6CiAgICAvKiBmbHVzaCBsaW5lIGFuZCBrZXlib2FyZCBxdWV1ZSAqLwogICAgbG9sLT5vZmZzX3VucmVhZF9DT04gPSAwOwogICAgYmlvcy0+TmV4dEtiZENoYXJQdHIgPSBiaW9zLT5GaXJzdEtiZENoYXJQdHI7CiAgICBicmVhazsKICBjYXNlIENNRF9PVVRQVVQ6CiAgY2FzZSBDTURfU0FGRU9VVFBVVDoKICAgIHsKICAgICAgUkVRX0lPICppbyA9IChSRVFfSU8gKiloZHI7CiAgICAgIEJZVEUgKmJ1ZmZlciA9IENUWF9TRUdfT0ZGX1RPX0xJTihjdHgsCgkJCQkJU0VMRUNUT1JPRihpby0+YnVmZmVyKSwKCQkJCQkoRFdPUkQpT0ZGU0VUT0YoaW8tPmJ1ZmZlcikpOwogICAgICBEV09SRCByZXN1bHQgPSAwOwogICAgICBXcml0ZUZpbGUoR2V0U3RkSGFuZGxlKFNURF9PVVRQVVRfSEFORExFKSwgYnVmZmVyLCBpby0+Y291bnQsICZyZXN1bHQsIE5VTEwpOwogICAgICBpby0+Y291bnQgPSByZXN1bHQ7CiAgICAgIGhkci0+c3RhdHVzID0gU1RBVF9ET05FOwogICAgfQogICAgYnJlYWs7CiAgZGVmYXVsdDoKICAgIGhkci0+c3RhdHVzID0gU1RBVF9ET05FOwogIH0KICBkb19scmV0KGN0eCk7Cn0KCnN0YXRpYyB2b2lkIEluaXRMaXN0T2ZMaXN0cyhET1NfTElTVE9GTElTVFMgKkRPU19MT0wpCnsKLyoKT3V0cHV0IG9mIERPUyA2LjIyOgoKMDEzMzowMDIwICAgICAgICAgICAgICAgICAgICA2QSAxMy0zMyAwMSBDQyAwMCAzMyAwMSA1OSAwMCAgICAgICAgIGouMy4uLjMuWS4KMDEzMzowMDMwICA3MCAwMCAwMCAwMCA3MiAwMiAwMCAwMi02RCAwMCAzMyAwMSAwMCAwMCAyRSAwNSAgIHAuLi5yLi4ubS4zLi4uLi4KMDEzMzowMDQwICAwMCAwMCBGQyAwNCAwMCAwMCAwMyAwOC05MiAyMSAxMSBFMCAwNCA4MCBDNiAwRCAgIC4uLi4uLi4uLiEuLi4uLi4KMDEzMzowMDUwICBDQyAwRCA0RSA1NSA0QyAyMCAyMCAyMC0yMCAyMCAwMCAwMCAwMCAwMCAwMCAwMCAgIC4uTlVMICAgICAuLi4uLi4KMDEzMzowMDYwICAwMCA0QiBCQSBDMSAwNiAxNCAwMCAwMC0wMCAwMyAwMSAwMCAwNCA3MCBDRSBGRiAgIC5LLi4uLi4uLi4uLi5wLi4KMDEzMzowMDcwICBGRiAwMCAwMCAwMCAwMCAwMCAwMCAwMC0wMCAwMSAwMCAwMCAwRCAwNSAwMCAwMCAgIC4uLi4uLi4uLi4uLi4uLi4KMDEzMzowMDgwICAwMCBGRiBGRiAwMCAwMCAwMCAwMCBGRS0wMCAwMCBGOCAwMyBGRiA5RiA3MCAwMiAgIC4uLi4uLi4uLi4uLi4ucC4KMDEzMzowMDkwICBEMCA0NCBDOCBGRCBENCA0NCBDOCBGRC1ENCA0NCBDOCBGRCBEMCA0NCBDOCBGRCAgIC5ELi4uRC4uLkQuLi5ELi4KMDEzMzowMEEwICBEMCA0NCBDOCBGRCBEMCA0NCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5ELi4uRAoqLwogIERPU19MT0wtPkNYX0ludDIxXzVlMDEJCT0gMHgwOwogIERPU19MT0wtPkxSVV9jb3VudF9GQ0JfY2FjaGUJPSAweDA7CiAgRE9TX0xPTC0+TFJVX2NvdW50X0ZDQl9vcGVuCQk9IDB4MDsKICBET1NfTE9MLT5PRU1fZnVuY19oYW5kbGVyCQk9IC0xOyAvKiBub3QgYXZhaWxhYmxlICovCiAgRE9TX0xPTC0+SU5UMjFfb2Zmc2V0CQk9IDB4MDsKICBET1NfTE9MLT5zaGFyaW5nX3JldHJ5X2NvdW50CT0gMzsKICBET1NfTE9MLT5zaGFyaW5nX3JldHJ5X2RlbGF5CT0gMTsKICBET1NfTE9MLT5wdHJfZGlza19idWYJCT0gMHgwOwogIERPU19MT0wtPm9mZnNfdW5yZWFkX0NPTgkJPSAweDA7CiAgRE9TX0xPTC0+c2VnX2ZpcnN0X01DQgkJPSAweDA7CiAgRE9TX0xPTC0+cHRyX2ZpcnN0X0RQQgkJPSAweDA7CiAgRE9TX0xPTC0+cHRyX2ZpcnN0X1N5c0ZpbGVUYWJsZQk9IDB4MDsKICBET1NfTE9MLT5wdHJfY2xvY2tfZGV2X2hkcgkJPSAweDA7CiAgRE9TX0xPTC0+cHRyX0NPTl9kZXZfaGRyCQk9IDB4MDsKICBET1NfTE9MLT5tYXhfYnl0ZV9wZXJfc2VjCQk9IDUxMjsKICBET1NfTE9MLT5wdHJfZGlza19idWZfaW5mbwkJPSAweDA7CiAgRE9TX0xPTC0+cHRyX2FycmF5X0NEUwkJPSAweDA7CiAgRE9TX0xPTC0+cHRyX3N5c19GQ0IJCT0gMHgwOwogIERPU19MT0wtPm5yX3Byb3RlY3RfRkNCCQk9IDB4MDsKICBET1NfTE9MLT5ucl9ibG9ja19kZXYJCT0gMHgwOwogIERPU19MT0wtPm5yX2F2YWlsX2RyaXZlX2xldHRlcnMJPSAyNjsgLyogQSAtIFogKi8KICBET1NfTE9MLT5ucl9kcml2ZXNfSk9JTmVkCQk9IDB4MDsKICBET1NfTE9MLT5wdHJfc3BlY19wcmdfbmFtZXMJCT0gMHgwOwogIERPU19MT0wtPnB0cl9TRVRWRVJfcHJnX2xpc3QJPSAweDA7IC8qIG5vIFNFVFZFUiBsaXN0ICovCiAgRE9TX0xPTC0+RE9TX0hJR0hfQTIwX2Z1bmNfb2Zmcwk9IDB4MDsKICBET1NfTE9MLT5QU1BfbGFzdF9leGVjCQk9IDB4MDsKICBET1NfTE9MLT5CVUZGRVJTX3ZhbAkJPSA5OTsgLyogbWF4aW11bTogOTkgKi8KICBET1NfTE9MLT5CVUZGRVJTX25yX2xvb2thaGVhZAk9IDg7IC8qIG1heGltdW06IDggKi8KICBET1NfTE9MLT5ib290X2RyaXZlCQkJPSAzOyAvKiBDOiAqLwogIERPU19MT0wtPmZsYWdfRFdPUkRfbW92ZXMJCT0gMHgwMTsgLyogaTM4NisgKi8KICBET1NfTE9MLT5zaXplX2V4dGVuZGVkX21lbQkJPSAweGYwMDA7IC8qIHZlcnkgaGlnaCB2YWx1ZSAqLwp9Cgp2b2lkIERPU0RFVl9TZXR1cERldmljZShjb25zdCBXSU5FREVWICogZGV2aW5mbywKCQkJV09SRCBzZWcsIFdPUkQgb2ZmX2RldiwgV09SRCBvZmZfdGh1bmspCnsKICBET1NfREVWSUNFX0hFQURFUiAqZGV2ID0gUFRSX1JFQUxfVE9fTElOKHNlZywgb2ZmX2Rldik7CiAgV0lORURFVl9USFVOSyAqdGh1bmsgPSBQVFJfUkVBTF9UT19MSU4oc2VnLCBvZmZfdGh1bmspOwogIERPU19EQVRBU0VHICpkYXRhc2VnID0gKERPU19EQVRBU0VHKilET1NNRU1fTE9MKCk7CgogIGRldi0+YXR0ciA9IGRldmluZm8tPmF0dHI7CiAgZGV2LT5zdHJhdGVneSAgPSBvZmZfdGh1bmsgKyBGSUVMRF9PRkZTRVQoV0lORURFVl9USFVOSywgbGptcDEpOwogIGRldi0+aW50ZXJydXB0ID0gb2ZmX3RodW5rICsgRklFTERfT0ZGU0VUKFdJTkVERVZfVEhVTkssIGxqbXAyKTsKICBtZW1jcHkoZGV2LT5uYW1lLCBkZXZpbmZvLT5uYW1lLCA4KTsKCiAgdGh1bmstPmxqbXAxICAgICA9IExKTVA7CiAgdGh1bmstPnN0cmF0ZWd5ICA9IERQTUlfQWxsb2NJbnRlcm5hbFJNQ0IoZGV2aW5mby0+c3RyYXRlZ3kpOwogIHRodW5rLT5sam1wMiAgICAgPSBMSk1QOwogIHRodW5rLT5pbnRlcnJ1cHQgPSBEUE1JX0FsbG9jSW50ZXJuYWxSTUNCKGRldmluZm8tPmludGVycnVwdCk7CgogIGRldi0+bmV4dF9kZXYgPSBOT05FWFQ7CiAgaWYgKGRhdGFzZWctPmxhc3RfZGV2KQogICAgICBkYXRhc2VnLT5sYXN0X2Rldi0+bmV4dF9kZXYgPSBNQUtFU0VHUFRSKHNlZywgb2ZmX2Rldik7CiAgZGF0YXNlZy0+bGFzdF9kZXYgPSBkZXY7Cn0KCnZvaWQgRE9TREVWX0luc3RhbGxET1NEZXZpY2VzKHZvaWQpCnsKICBET1NfREFUQVNFRyAqZGF0YXNlZzsKICBXT1JEIHNlZzsKICBXT1JEIHNlbGVjdG9yOwogIHVuc2lnbmVkIGludCBuOwoKICAvKiBhbGxvY2F0ZSBET1MgZGF0YSBzZWdtZW50IG9yIHNvbWV0aGluZyAqLwogIGRhdGFzZWcgPSBET1NWTV9BbGxvY0RhdGFVTUIoIHNpemVvZihET1NfREFUQVNFRyksICZzZWcsICZzZWxlY3RvciApOwoKICBET1NfTE9MU2VnID0gTUFLRVNFR1BUUiggc2VnLCAwICk7CiAgRE9TTUVNX0xPTCgpLT53aW5lX3JtX2xvbCA9IAogICAgICBNQUtFU0VHUFRSKCBzZWcsIEZJRUxEX09GRlNFVChET1NfTElTVE9GTElTVFMsIHB0cl9maXJzdF9EUEIpICk7CiAgRE9TTUVNX0xPTCgpLT53aW5lX3BtX2xvbCA9IAogICAgICBNQUtFU0VHUFRSKCBzZWxlY3RvciwgRklFTERfT0ZGU0VUKERPU19MSVNUT0ZMSVNUUywgcHRyX2ZpcnN0X0RQQikgKTsKCiAgLyogaW5pdGlhbGl6ZSB0aGUgbWFnbmlmaWNlbnQgTGlzdCBPZiBMaXN0cyAqLwogIEluaXRMaXN0T2ZMaXN0cygmZGF0YXNlZy0+bG9sKTsKCiAgLyogU2V0IHVwIGZpcnN0IGRldmljZSAoTlVMKSAqLwogIGRhdGFzZWctPmxhc3RfZGV2ID0gTlVMTDsKICBET1NERVZfU2V0dXBEZXZpY2UoICZkZXZzWzBdLAoJCSAgICAgIHNlZywKCQkgICAgICBET1NfREFUQVNFR19PRkYobG9sLk5VTF9kZXYpLAoJCSAgICAgIERPU19EQVRBU0VHX09GRih0aHVua1swXSkgKTsKCiAgLyogU2V0IHVwIHRoZSByZW1haW5pbmcgZGV2aWNlcyAqLwogIGZvciAobiA9IDE7IG4gPCBOUl9ERVZTOyBuKyspCiAgICBET1NERVZfU2V0dXBEZXZpY2UoICZkZXZzW25dLAoJCQlzZWcsCgkJCURPU19EQVRBU0VHX09GRihkZXZbbi0xXSksCgkJCURPU19EQVRBU0VHX09GRih0aHVua1tuXSkgKTsKCiAgLyogQ09OIGlzIGRldmljZSAxICovCiAgZGF0YXNlZy0+bG9sLnB0cl9DT05fZGV2X2hkciA9IE1BS0VTRUdQVFIoc2VnLCBET1NfREFUQVNFR19PRkYoZGV2WzBdKSk7Cn0KCkRXT1JEIERPU0RFVl9Db25zb2xlKHZvaWQpCnsKICByZXR1cm4gRE9TTUVNX0xPTCgpLT5wdHJfQ09OX2Rldl9oZHI7Cn0KCkRXT1JEIERPU0RFVl9GaW5kQ2hhckRldmljZShjaGFyKm5hbWUpCnsKICBTRUdQVFIgY3VyX3B0ciA9IE1BS0VTRUdQVFIoSElXT1JEKERPU19MT0xTZWcpLCBGSUVMRF9PRkZTRVQoRE9TX0xJU1RPRkxJU1RTLE5VTF9kZXYpKTsKICBET1NfREVWSUNFX0hFQURFUiAqY3VyID0gUFRSX1JFQUxfVE9fTElOKFNFTEVDVE9ST0YoY3VyX3B0ciksT0ZGU0VUT0YoY3VyX3B0cikpOwogIGNoYXIgZG5hbWVbOF07CiAgaW50IGNudDsKCiAgLyogZ2V0IGZpcnN0IDggY2hhcmFjdGVycyAqLwogIC8qIGlmIGxlc3MgdGhhbiA4IGNoYXJhY3RlcnMsIHBhZCB3aXRoIHNwYWNlcyAqLwogIGZvciAoY250PTA7IG5hbWVbY250XSAmJiBjbnQ8ODsgY250KyspCiAgICBkbmFtZVtjbnRdPW5hbWVbY250XTsKCiAgd2hpbGUoY250PDgpIGRuYW1lW2NudCsrXSA9ICcgJzsKCiAgLyogc2VhcmNoIGZvciBjaGFyIGRldmljZXMgd2l0aCB0aGUgcmlnaHQgbmFtZSAqLwogIHdoaWxlIChjdXIgJiYKCSAoKCEoY3VyLT5hdHRyICYgQVRUUl9DSEFSKSkgfHwKCSAgbWVtY21wKGN1ci0+bmFtZSxkbmFtZSw4KSkpIHsKICAgIGN1cl9wdHIgPSBjdXItPm5leHRfZGV2OwogICAgaWYgKGN1cl9wdHIgPT0gTk9ORVhUKSBjdXI9TlVMTDsKICAgIGVsc2UgY3VyID0gUFRSX1JFQUxfVE9fTElOKFNFTEVDVE9ST0YoY3VyX3B0ciksT0ZGU0VUT0YoY3VyX3B0cikpOwogIH0KICByZXR1cm4gY3VyX3B0cjsKfQoKc3RhdGljIHZvaWQgRE9TREVWX0RvUmVxKHZvaWQqcmVxLCBEV09SRCBkZXYpCnsKICBSRVFVRVNUX0hFQURFUiAqaGRyID0gKFJFUVVFU1RfSEVBREVSICopcmVxOwogIERPU19ERVZJQ0VfSEVBREVSICpkaGRyOwogIENPTlRFWFQ4NiBjdHg7CiAgY2hhciAqcGhkcjsKCiAgZGhkciA9IFBUUl9SRUFMX1RPX0xJTihTRUxFQ1RPUk9GKGRldiksT0ZGU0VUT0YoZGV2KSk7CiAgcGhkciA9ICgoY2hhciopRE9TTUVNX0xPTCgpKSArIERPU19EQVRBU0VHX09GRihyZXEpOwoKICAvKiBjb3B5IHJlcXVlc3QgdG8gcmVxdWVzdCBzY3JhdGNoIGFyZWEgKi8KICBtZW1jcHkocGhkciwgcmVxLCBoZHItPnNpemUpOwoKICAvKiBwcmVwYXJlIHRvIGNhbGwgZGV2aWNlIGRyaXZlciAqLwogIG1lbXNldCgmY3R4LCAwLCBzaXplb2YoY3R4KSk7CiAgY3R4LkVGbGFncyB8PSBWODZfRkxBRzsKCiAgLyogRVM6QlggcG9pbnRzIHRvIHJlcXVlc3QgZm9yIHN0cmF0ZWd5IHJvdXRpbmUgKi8KICBjdHguU2VnRXMgPSBISVdPUkQoRE9TX0xPTFNlZyk7CiAgY3R4LkVieCAgID0gRE9TX0RBVEFTRUdfT0ZGKHJlcSk7CgogIC8qIGNhbGwgc3RyYXRlZ3kgcm91dGluZSAqLwogIGN0eC5TZWdDcyA9IFNFTEVDVE9ST0YoZGV2KTsKICBjdHguRWlwICAgPSBkaGRyLT5zdHJhdGVneTsKICBEUE1JX0NhbGxSTVByb2MoJmN0eCwgMCwgMCwgMCk7CgogIC8qIGNhbGwgaW50ZXJydXB0IHJvdXRpbmUgKi8KICBjdHguU2VnQ3MgPSBTRUxFQ1RPUk9GKGRldik7CiAgY3R4LkVpcCAgID0gZGhkci0+aW50ZXJydXB0OwogIERQTUlfQ2FsbFJNUHJvYygmY3R4LCAwLCAwLCAwKTsKCiAgLyogY29tcGxldGVkLCBjb3B5IHJlcXVlc3QgYmFjayAqLwogIG1lbWNweShyZXEsIHBoZHIsIGhkci0+c2l6ZSk7CgogIGlmIChoZHItPnN0YXR1cyAmIFNUQVRfRVJST1IpIHsKICAgIHN3aXRjaCAoaGRyLT5zdGF0dXMgJiBTVEFUX01BU0spIHsKICAgIGNhc2UgMHgwRjogLyogaW52YWxpZCBkaXNrIGNoYW5nZSAqLwogICAgICAvKiB0aGlzIGVycm9yIHNlZW1zIHRvIGZpdCB0aGUgYmlsbCAqLwogICAgICBTZXRMYXN0RXJyb3IoRVJST1JfTk9UX1NBTUVfREVWSUNFKTsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICBTZXRMYXN0RXJyb3IoKGhkci0+c3RhdHVzICYgU1RBVF9NQVNLKSArIDB4MTMpOwogICAgICBicmVhazsKICAgIH0KICB9Cn0KCnN0YXRpYyBpbnQgRE9TREVWX0lPKHVuc2lnbmVkIGNtZCwgRFdPUkQgZGV2LCBEV09SRCBidWYsIGludCBidWZsZW4pCnsKICBSRVFfSU8gcmVxOwoKICByZXEuaGRyLnNpemU9c2l6ZW9mKHJlcSk7CiAgcmVxLmhkci51bml0PTA7IC8qIG5vdCBkZWFsaW5nIHdpdGggYmxvY2sgZGV2aWNlcyB5ZXQgKi8KICByZXEuaGRyLmNvbW1hbmQ9Y21kOwogIHJlcS5oZHIuc3RhdHVzPVNUQVRfQlVTWTsKICByZXEubWVkaWE9MDsgLyogbm90IGRlYWxpbmcgd2l0aCBibG9jayBkZXZpY2VzIHlldCAqLwogIHJlcS5idWZmZXI9YnVmOwogIHJlcS5jb3VudD1idWZsZW47CiAgcmVxLnNlY3Rvcj0wOyAvKiBibG9jayBkZXZpY2VzICovCiAgcmVxLnZvbHVtZT0wOyAvKiBibG9jayBkZXZpY2VzICovCgogIERPU0RFVl9Eb1JlcSgmcmVxLCBkZXYpOwoKICByZXR1cm4gcmVxLmNvdW50Owp9CgppbnQgRE9TREVWX1BlZWsoRFdPUkQgZGV2LCBCWVRFKmRhdGEpCnsKICBSRVFfU0FGRUlOUFVUIHJlcTsKCiAgcmVxLmhkci5zaXplPXNpemVvZihyZXEpOwogIHJlcS5oZHIudW5pdD0wOyAvKiBub3QgZGVhbGluZyB3aXRoIGJsb2NrIGRldmljZXMgeWV0ICovCiAgcmVxLmhkci5jb21tYW5kPUNNRF9TQUZFSU5QVVQ7CiAgcmVxLmhkci5zdGF0dXM9U1RBVF9CVVNZOwogIHJlcS5kYXRhPTA7CgogIERPU0RFVl9Eb1JlcSgmcmVxLCBkZXYpOwoKICBpZiAocmVxLmhkci5zdGF0dXMgJiBTVEFUX0JVU1kpIHJldHVybiAwOwoKICAqZGF0YSA9IHJlcS5kYXRhOwogIHJldHVybiAxOwp9CgppbnQgRE9TREVWX1JlYWQoRFdPUkQgZGV2LCBEV09SRCBidWYsIGludCBidWZsZW4pCnsKICByZXR1cm4gRE9TREVWX0lPKENNRF9JTlBVVCwgZGV2LCBidWYsIGJ1Zmxlbik7Cn0KCmludCBET1NERVZfV3JpdGUoRFdPUkQgZGV2LCBEV09SRCBidWYsIGludCBidWZsZW4sIGludCB2ZXJpZnkpCnsKICByZXR1cm4gRE9TREVWX0lPKHZlcmlmeT9DTURfU0FGRU9VVFBVVDpDTURfT1VUUFVULCBkZXYsIGJ1ZiwgYnVmbGVuKTsKfQoKaW50IERPU0RFVl9Jb2N0bFJlYWQoRFdPUkQgZGV2LCBEV09SRCBidWYsIGludCBidWZsZW4pCnsKICByZXR1cm4gRE9TREVWX0lPKENNRF9JTklPQ1RMLCBkZXYsIGJ1ZiwgYnVmbGVuKTsKfQoKaW50IERPU0RFVl9Jb2N0bFdyaXRlKERXT1JEIGRldiwgRFdPUkQgYnVmLCBpbnQgYnVmbGVuKQp7CiAgcmV0dXJuIERPU0RFVl9JTyhDTURfT1VUSU9DVEwsIGRldiwgYnVmLCBidWZsZW4pOwp9Cgp2b2lkIERPU0RFVl9TZXRTaGFyaW5nUmV0cnkoV09SRCBkZWxheSwgV09SRCBjb3VudCkKewogICAgRE9TTUVNX0xPTCgpLT5zaGFyaW5nX3JldHJ5X2RlbGF5ID0gZGVsYXk7CiAgICBpZiAoY291bnQpIERPU01FTV9MT0woKS0+c2hhcmluZ19yZXRyeV9jb3VudCA9IGNvdW50Owp9CgpTRUdQVFIgRE9TREVWX0dldExPTChCT09MIHY4NikKewogICAgaWYgKHY4NikgcmV0dXJuIERPU01FTV9MT0woKS0+d2luZV9ybV9sb2w7CiAgICBlbHNlIHJldHVybiBET1NNRU1fTE9MKCktPndpbmVfcG1fbG9sOwp9Cg==