Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8KLy8gIExpdHRsZSBDb2xvciBNYW5hZ2VtZW50IFN5c3RlbQovLyAgQ29weXJpZ2h0IChjKSAxOTk4LTIwMTQgTWFydGkgTWFyaWEgU2FndWVyCi8vCi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZwovLyBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCi8vIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24KLy8gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsCi8vIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZQovLyBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgovLwovLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpbgovLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS4KLy8KLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsCi8vIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTwovLyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORAovLyBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFCi8vIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04KLy8gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OCi8vIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgovLwovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovLwoKI2luY2x1ZGUgImxjbXMyX2ludGVybmFsLmgiCgovLyBWaXJ0dWFsIChidWlsdC1pbikgcHJvZmlsZXMKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCnN0YXRpYwpjbXNCb29sIFNldFRleHRUYWdzKGNtc0hQUk9GSUxFIGhQcm9maWxlLCBjb25zdCB3Y2hhcl90KiBEZXNjcmlwdGlvbikKewogICAgY21zTUxVICpEZXNjcmlwdGlvbk1MVSwgKkNvcHlyaWdodE1MVTsKICAgIGNtc0Jvb2wgIHJjID0gRkFMU0U7CiAgICBjbXNDb250ZXh0IENvbnRleHRJRCA9IGNtc0dldFByb2ZpbGVDb250ZXh0SUQoaFByb2ZpbGUpOwoKICAgIERlc2NyaXB0aW9uTUxVICA9IGNtc01MVWFsbG9jKENvbnRleHRJRCwgMSk7CiAgICBDb3B5cmlnaHRNTFUgICAgPSBjbXNNTFVhbGxvYyhDb250ZXh0SUQsIDEpOwoKICAgIGlmIChEZXNjcmlwdGlvbk1MVSA9PSBOVUxMIHx8IENvcHlyaWdodE1MVSA9PSBOVUxMKSBnb3RvIEVycm9yOwoKICAgIGlmICghY21zTUxVc2V0V2lkZShEZXNjcmlwdGlvbk1MVSwgICJlbiIsICJVUyIsIERlc2NyaXB0aW9uKSkgZ290byBFcnJvcjsKICAgIGlmICghY21zTUxVc2V0V2lkZShDb3B5cmlnaHRNTFUsICAgICJlbiIsICJVUyIsIEwiTm8gY29weXJpZ2h0LCB1c2UgZnJlZWx5IikpIGdvdG8gRXJyb3I7CgogICAgaWYgKCFjbXNXcml0ZVRhZyhoUHJvZmlsZSwgY21zU2lnUHJvZmlsZURlc2NyaXB0aW9uVGFnLCAgRGVzY3JpcHRpb25NTFUpKSBnb3RvIEVycm9yOwogICAgaWYgKCFjbXNXcml0ZVRhZyhoUHJvZmlsZSwgY21zU2lnQ29weXJpZ2h0VGFnLCAgICAgICAgICAgQ29weXJpZ2h0TUxVKSkgZ290byBFcnJvcjsKCiAgICByYyA9IFRSVUU7CgpFcnJvcjoKCiAgICBpZiAoRGVzY3JpcHRpb25NTFUpCiAgICAgICAgY21zTUxVZnJlZShEZXNjcmlwdGlvbk1MVSk7CiAgICBpZiAoQ29weXJpZ2h0TUxVKQogICAgICAgIGNtc01MVWZyZWUoQ29weXJpZ2h0TUxVKTsKICAgIHJldHVybiByYzsKfQoKCnN0YXRpYwpjbXNCb29sICBTZXRTZXFEZXNjVGFnKGNtc0hQUk9GSUxFIGhQcm9maWxlLCBjb25zdCBjaGFyKiBNb2RlbCkKewogICAgY21zQm9vbCAgcmMgPSBGQUxTRTsKICAgIGNtc0NvbnRleHQgQ29udGV4dElEID0gY21zR2V0UHJvZmlsZUNvbnRleHRJRChoUHJvZmlsZSk7CiAgICBjbXNTRVEqIFNlcSA9IGNtc0FsbG9jUHJvZmlsZVNlcXVlbmNlRGVzY3JpcHRpb24oQ29udGV4dElELCAxKTsKCiAgICBpZiAoU2VxID09IE5VTEwpIHJldHVybiBGQUxTRTsKCiAgICBTZXEtPnNlcVswXS5kZXZpY2VNZmcgPSAoY21zU2lnbmF0dXJlKSAwOwogICAgU2VxLT5zZXFbMF0uZGV2aWNlTW9kZWwgPSAoY21zU2lnbmF0dXJlKSAwOwoKI2lmZGVmIENNU19ET05UX1VTRV9JTlQ2NAogICAgU2VxLT5zZXFbMF0uYXR0cmlidXRlc1swXSA9IDA7CiAgICBTZXEtPnNlcVswXS5hdHRyaWJ1dGVzWzFdID0gMDsKI2Vsc2UKICAgIFNlcS0+c2VxWzBdLmF0dHJpYnV0ZXMgPSAwOwojZW5kaWYKCiAgICBTZXEtPnNlcVswXS50ZWNobm9sb2d5ID0gKGNtc1RlY2hub2xvZ3lTaWduYXR1cmUpIDA7CgogICAgY21zTUxVc2V0QVNDSUkoIFNlcS0+c2VxWzBdLk1hbnVmYWN0dXJlciwgY21zTm9MYW5ndWFnZSwgY21zTm9Db3VudHJ5LCAiTGl0dGxlIENNUyIpOwogICAgY21zTUxVc2V0QVNDSUkoIFNlcS0+c2VxWzBdLk1vZGVsLCAgICAgICAgY21zTm9MYW5ndWFnZSwgY21zTm9Db3VudHJ5LCBNb2RlbCk7CgogICAgaWYgKCFfY21zV3JpdGVQcm9maWxlU2VxdWVuY2UoaFByb2ZpbGUsIFNlcSkpIGdvdG8gRXJyb3I7CgogICAgcmMgPSBUUlVFOwoKRXJyb3I6CiAgICBpZiAoU2VxKQogICAgICAgIGNtc0ZyZWVQcm9maWxlU2VxdWVuY2VEZXNjcmlwdGlvbihTZXEpOwoKICAgIHJldHVybiByYzsKfQoKCgovLyBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgYSBwcm9maWxlIGJhc2VkIG9uIFdoaXRlIHBvaW50LCBwcmltYXJpZXMgYW5kCi8vIHRyYW5zZmVyIGZ1bmN0aW9ucy4KY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZVJHQlByb2ZpbGVUSFIoY21zQ29udGV4dCBDb250ZXh0SUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNtc0NJRXh5WSogV2hpdGVQb2ludCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY21zQ0lFeHlZVFJJUExFKiBQcmltYXJpZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc1RvbmVDdXJ2ZSogY29uc3QgVHJhbnNmZXJGdW5jdGlvblszXSkKewogICAgY21zSFBST0ZJTEUgaElDQzsKICAgIGNtc01BVDMgTUNvbG9yYW50czsKICAgIGNtc0NJRVhZWlRSSVBMRSBDb2xvcmFudHM7CiAgICBjbXNDSUV4eVkgTWF4V2hpdGU7CiAgICBjbXNNQVQzIENIQUQ7CiAgICBjbXNDSUVYWVogV2hpdGVQb2ludFhZWjsKCiAgICBoSUNDID0gY21zQ3JlYXRlUHJvZmlsZVBsYWNlaG9sZGVyKENvbnRleHRJRCk7CiAgICBpZiAoIWhJQ0MpICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjYW4ndCBhbGxvY2F0ZQogICAgICAgIHJldHVybiBOVUxMOwoKICAgIGNtc1NldFByb2ZpbGVWZXJzaW9uKGhJQ0MsIDQuMyk7CgogICAgY21zU2V0RGV2aWNlQ2xhc3MoaElDQywgICAgICBjbXNTaWdEaXNwbGF5Q2xhc3MpOwogICAgY21zU2V0Q29sb3JTcGFjZShoSUNDLCAgICAgICBjbXNTaWdSZ2JEYXRhKTsKICAgIGNtc1NldFBDUyhoSUNDLCAgICAgICAgICAgICAgY21zU2lnWFlaRGF0YSk7CgogICAgY21zU2V0SGVhZGVyUmVuZGVyaW5nSW50ZW50KGhJQ0MsICBJTlRFTlRfUEVSQ0VQVFVBTCk7CgoKICAgIC8vIEltcGxlbWVudCBwcm9maWxlIHVzaW5nIGZvbGxvd2luZyB0YWdzOgogICAgLy8KICAgIC8vICAxIGNtc1NpZ1Byb2ZpbGVEZXNjcmlwdGlvblRhZwogICAgLy8gIDIgY21zU2lnTWVkaWFXaGl0ZVBvaW50VGFnCiAgICAvLyAgMyBjbXNTaWdSZWRDb2xvcmFudFRhZwogICAgLy8gIDQgY21zU2lnR3JlZW5Db2xvcmFudFRhZwogICAgLy8gIDUgY21zU2lnQmx1ZUNvbG9yYW50VGFnCiAgICAvLyAgNiBjbXNTaWdSZWRUUkNUYWcKICAgIC8vICA3IGNtc1NpZ0dyZWVuVFJDVGFnCiAgICAvLyAgOCBjbXNTaWdCbHVlVFJDVGFnCiAgICAvLyAgOSBDaHJvbWF0aWMgYWRhcHRhdGlvbiBUYWcKICAgIC8vIFRoaXMgY29uZm9ybXMgYSBzdGFuZGFyZCBSR0IgRGlzcGxheVByb2ZpbGUgYXMgc2F5cyBJQ0MsIGFuZCB0aGVuIEkgYWRkIChBcyBwZXIgYWRkZW5kdW0gSUkpCiAgICAvLyAxMCBjbXNTaWdDaHJvbWF0aWNpdHlUYWcKCgogICAgaWYgKCFTZXRUZXh0VGFncyhoSUNDLCBMIlJHQiBidWlsdC1pbiIpKSBnb3RvIEVycm9yOwoKICAgIGlmIChXaGl0ZVBvaW50KSB7CgogICAgICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnTWVkaWFXaGl0ZVBvaW50VGFnLCBjbXNENTBfWFlaKCkpKSBnb3RvIEVycm9yOwoKICAgICAgICBjbXN4eVkyWFlaKCZXaGl0ZVBvaW50WFlaLCBXaGl0ZVBvaW50KTsKICAgICAgICBfY21zQWRhcHRhdGlvbk1hdHJpeCgmQ0hBRCwgTlVMTCwgJldoaXRlUG9pbnRYWVosIGNtc0Q1MF9YWVooKSk7CgogICAgICAgIC8vIFRoaXMgaXMgYSBWNCB0YWcsIGJ1dCBtYW55IENNTSBkb2VzIHJlYWQgYW5kIHVuZGVyc3RhbmQgaXQgbm8gbWF0dGVyIHdoaWNoIHZlcnNpb24KICAgICAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ0Nocm9tYXRpY0FkYXB0YXRpb25UYWcsICh2b2lkKikgJkNIQUQpKSBnb3RvIEVycm9yOwogICAgfQoKICAgIGlmIChXaGl0ZVBvaW50ICYmIFByaW1hcmllcykgewoKICAgICAgICBNYXhXaGl0ZS54ID0gIFdoaXRlUG9pbnQgLT4geDsKICAgICAgICBNYXhXaGl0ZS55ID0gIFdoaXRlUG9pbnQgLT4geTsKICAgICAgICBNYXhXaGl0ZS5ZID0gIDEuMDsKCiAgICAgICAgaWYgKCFfY21zQnVpbGRSR0IyWFladHJhbnNmZXJNYXRyaXgoJk1Db2xvcmFudHMsICZNYXhXaGl0ZSwgUHJpbWFyaWVzKSkgZ290byBFcnJvcjsKCiAgICAgICAgQ29sb3JhbnRzLlJlZC5YICAgPSBNQ29sb3JhbnRzLnZbMF0ublswXTsKICAgICAgICBDb2xvcmFudHMuUmVkLlkgICA9IE1Db2xvcmFudHMudlsxXS5uWzBdOwogICAgICAgIENvbG9yYW50cy5SZWQuWiAgID0gTUNvbG9yYW50cy52WzJdLm5bMF07CgogICAgICAgIENvbG9yYW50cy5HcmVlbi5YID0gTUNvbG9yYW50cy52WzBdLm5bMV07CiAgICAgICAgQ29sb3JhbnRzLkdyZWVuLlkgPSBNQ29sb3JhbnRzLnZbMV0ublsxXTsKICAgICAgICBDb2xvcmFudHMuR3JlZW4uWiA9IE1Db2xvcmFudHMudlsyXS5uWzFdOwoKICAgICAgICBDb2xvcmFudHMuQmx1ZS5YICA9IE1Db2xvcmFudHMudlswXS5uWzJdOwogICAgICAgIENvbG9yYW50cy5CbHVlLlkgID0gTUNvbG9yYW50cy52WzFdLm5bMl07CiAgICAgICAgQ29sb3JhbnRzLkJsdWUuWiAgPSBNQ29sb3JhbnRzLnZbMl0ublsyXTsKCiAgICAgICAgaWYgKCFjbXNXcml0ZVRhZyhoSUNDLCBjbXNTaWdSZWRDb2xvcmFudFRhZywgICAodm9pZCopICZDb2xvcmFudHMuUmVkKSkgZ290byBFcnJvcjsKICAgICAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ0JsdWVDb2xvcmFudFRhZywgICh2b2lkKikgJkNvbG9yYW50cy5CbHVlKSkgZ290byBFcnJvcjsKICAgICAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ0dyZWVuQ29sb3JhbnRUYWcsICh2b2lkKikgJkNvbG9yYW50cy5HcmVlbikpIGdvdG8gRXJyb3I7CiAgICB9CgoKICAgIGlmIChUcmFuc2ZlckZ1bmN0aW9uKSB7CgogICAgICAgIC8vIFRyaWVzIHRvIG1pbmltaXplIHNwYWNlLiBUaGFua3MgdG8gUmljaGFyZCBIdWdoZXMgZm9yIHRoaXMgbmljZSBpZGVhICAgICAgICAgCiAgICAgICAgaWYgKCFjbXNXcml0ZVRhZyhoSUNDLCBjbXNTaWdSZWRUUkNUYWcsICAgKHZvaWQqKSBUcmFuc2ZlckZ1bmN0aW9uWzBdKSkgZ290byBFcnJvcjsKCiAgICAgICAgaWYgKFRyYW5zZmVyRnVuY3Rpb25bMV0gPT0gVHJhbnNmZXJGdW5jdGlvblswXSkgewoKICAgICAgICAgICAgaWYgKCFjbXNMaW5rVGFnIChoSUNDLCBjbXNTaWdHcmVlblRSQ1RhZywgY21zU2lnUmVkVFJDVGFnKSkgZ290byBFcnJvcjsKCiAgICAgICAgfSBlbHNlIHsKCiAgICAgICAgICAgIGlmICghY21zV3JpdGVUYWcoaElDQywgY21zU2lnR3JlZW5UUkNUYWcsICh2b2lkKikgVHJhbnNmZXJGdW5jdGlvblsxXSkpIGdvdG8gRXJyb3I7CiAgICAgICAgfQoKICAgICAgICBpZiAoVHJhbnNmZXJGdW5jdGlvblsyXSA9PSBUcmFuc2ZlckZ1bmN0aW9uWzBdKSB7CgogICAgICAgICAgICBpZiAoIWNtc0xpbmtUYWcgKGhJQ0MsIGNtc1NpZ0JsdWVUUkNUYWcsIGNtc1NpZ1JlZFRSQ1RhZykpIGdvdG8gRXJyb3I7CgogICAgICAgIH0gZWxzZSB7CgogICAgICAgICAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ0JsdWVUUkNUYWcsICh2b2lkKikgVHJhbnNmZXJGdW5jdGlvblsyXSkpIGdvdG8gRXJyb3I7CiAgICAgICAgfQogICAgfQoKICAgIGlmIChQcmltYXJpZXMpIHsKICAgICAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ0Nocm9tYXRpY2l0eVRhZywgKHZvaWQqKSBQcmltYXJpZXMpKSBnb3RvIEVycm9yOwogICAgfQoKCiAgICByZXR1cm4gaElDQzsKCkVycm9yOgogICAgaWYgKGhJQ0MpCiAgICAgICAgY21zQ2xvc2VQcm9maWxlKGhJQ0MpOwogICAgcmV0dXJuIE5VTEw7Cn0KCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVSR0JQcm9maWxlKGNvbnN0IGNtc0NJRXh5WSogV2hpdGVQb2ludCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY21zQ0lFeHlZVFJJUExFKiBQcmltYXJpZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc1RvbmVDdXJ2ZSogY29uc3QgVHJhbnNmZXJGdW5jdGlvblszXSkKewogICAgcmV0dXJuIGNtc0NyZWF0ZVJHQlByb2ZpbGVUSFIoTlVMTCwgV2hpdGVQb2ludCwgUHJpbWFyaWVzLCBUcmFuc2ZlckZ1bmN0aW9uKTsKfQoKCgovLyBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgYSBwcm9maWxlIGJhc2VkIG9uIFdoaXRlIHBvaW50IGFuZCB0cmFuc2ZlciBmdW5jdGlvbi4KY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZUdyYXlQcm9maWxlVEhSKGNtc0NvbnRleHQgQ29udGV4dElELAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY21zQ0lFeHlZKiBXaGl0ZVBvaW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY21zVG9uZUN1cnZlKiBUcmFuc2ZlckZ1bmN0aW9uKQp7CiAgICBjbXNIUFJPRklMRSBoSUNDOwogICAgY21zQ0lFWFlaIHRtcDsKCiAgICBoSUNDID0gY21zQ3JlYXRlUHJvZmlsZVBsYWNlaG9sZGVyKENvbnRleHRJRCk7CiAgICBpZiAoIWhJQ0MpICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjYW4ndCBhbGxvY2F0ZQogICAgICAgIHJldHVybiBOVUxMOwoKICAgIGNtc1NldFByb2ZpbGVWZXJzaW9uKGhJQ0MsIDQuMyk7CgogICAgY21zU2V0RGV2aWNlQ2xhc3MoaElDQywgICAgICBjbXNTaWdEaXNwbGF5Q2xhc3MpOwogICAgY21zU2V0Q29sb3JTcGFjZShoSUNDLCAgICAgICBjbXNTaWdHcmF5RGF0YSk7CiAgICBjbXNTZXRQQ1MoaElDQywgICAgICAgICAgICAgIGNtc1NpZ1hZWkRhdGEpOwogICAgY21zU2V0SGVhZGVyUmVuZGVyaW5nSW50ZW50KGhJQ0MsICBJTlRFTlRfUEVSQ0VQVFVBTCk7CgoKICAgIC8vIEltcGxlbWVudCBwcm9maWxlIHVzaW5nIGZvbGxvd2luZyB0YWdzOgogICAgLy8KICAgIC8vICAxIGNtc1NpZ1Byb2ZpbGVEZXNjcmlwdGlvblRhZwogICAgLy8gIDIgY21zU2lnTWVkaWFXaGl0ZVBvaW50VGFnCiAgICAvLyAgMyBjbXNTaWdHcmF5VFJDVGFnCgogICAgLy8gVGhpcyBjb25mb3JtcyBhIHN0YW5kYXJkIEdyYXkgRGlzcGxheVByb2ZpbGUKCiAgICAvLyBGaWxsLWluIHRoZSB0YWdzCgogICAgaWYgKCFTZXRUZXh0VGFncyhoSUNDLCBMImdyYXkgYnVpbHQtaW4iKSkgZ290byBFcnJvcjsKCgogICAgaWYgKFdoaXRlUG9pbnQpIHsKCiAgICAgICAgY21zeHlZMlhZWigmdG1wLCBXaGl0ZVBvaW50KTsKICAgICAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ01lZGlhV2hpdGVQb2ludFRhZywgKHZvaWQqKSAmdG1wKSkgZ290byBFcnJvcjsKICAgIH0KCiAgICBpZiAoVHJhbnNmZXJGdW5jdGlvbikgewoKICAgICAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ0dyYXlUUkNUYWcsICh2b2lkKikgVHJhbnNmZXJGdW5jdGlvbikpIGdvdG8gRXJyb3I7CiAgICB9CgogICAgcmV0dXJuIGhJQ0M7CgpFcnJvcjoKICAgIGlmIChoSUNDKQogICAgICAgIGNtc0Nsb3NlUHJvZmlsZShoSUNDKTsKICAgIHJldHVybiBOVUxMOwp9CgoKCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVHcmF5UHJvZmlsZShjb25zdCBjbXNDSUV4eVkqIFdoaXRlUG9pbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjbXNUb25lQ3VydmUqIFRyYW5zZmVyRnVuY3Rpb24pCnsKICAgIHJldHVybiBjbXNDcmVhdGVHcmF5UHJvZmlsZVRIUihOVUxMLCBXaGl0ZVBvaW50LCBUcmFuc2ZlckZ1bmN0aW9uKTsKfQoKLy8gVGhpcyBpcyBhIGRldmljZWxpbmsgb3BlcmF0aW5nIGluIHRoZSB0YXJnZXQgY29sb3JzcGFjZSB3aXRoIGFzIG1hbnkgdHJhbnNmZXIgZnVuY3Rpb25zIGFzIGNvbXBvbmVudHMKCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVMaW5lYXJpemF0aW9uRGV2aWNlTGlua1RIUihjbXNDb250ZXh0IENvbnRleHRJRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc0NvbG9yU3BhY2VTaWduYXR1cmUgQ29sb3JTcGFjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc1RvbmVDdXJ2ZSogY29uc3QgVHJhbnNmZXJGdW5jdGlvbnNbXSkKewogICAgY21zSFBST0ZJTEUgaElDQzsKICAgIGNtc1BpcGVsaW5lKiBQaXBlbGluZTsKICAgIGludCBuQ2hhbm5lbHM7CgogICAgaElDQyA9IGNtc0NyZWF0ZVByb2ZpbGVQbGFjZWhvbGRlcihDb250ZXh0SUQpOwogICAgaWYgKCFoSUNDKQogICAgICAgIHJldHVybiBOVUxMOwoKICAgIGNtc1NldFByb2ZpbGVWZXJzaW9uKGhJQ0MsIDQuMyk7CgogICAgY21zU2V0RGV2aWNlQ2xhc3MoaElDQywgICAgICBjbXNTaWdMaW5rQ2xhc3MpOwogICAgY21zU2V0Q29sb3JTcGFjZShoSUNDLCAgICAgICBDb2xvclNwYWNlKTsKICAgIGNtc1NldFBDUyhoSUNDLCAgICAgICAgICAgICAgQ29sb3JTcGFjZSk7CgogICAgY21zU2V0SGVhZGVyUmVuZGVyaW5nSW50ZW50KGhJQ0MsICBJTlRFTlRfUEVSQ0VQVFVBTCk7CgogICAgLy8gU2V0IHVwIGNoYW5uZWxzCiAgICBuQ2hhbm5lbHMgPSBjbXNDaGFubmVsc09mKENvbG9yU3BhY2UpOwoKICAgIC8vIENyZWF0ZXMgYSBQaXBlbGluZSB3aXRoIHByZWxpbmVhcml6YXRpb24gc3RlcCBvbmx5CiAgICBQaXBlbGluZSA9IGNtc1BpcGVsaW5lQWxsb2MoQ29udGV4dElELCBuQ2hhbm5lbHMsIG5DaGFubmVscyk7CiAgICBpZiAoUGlwZWxpbmUgPT0gTlVMTCkgZ290byBFcnJvcjsKCgogICAgLy8gQ29weSB0YWJsZXMgdG8gUGlwZWxpbmUKICAgIGlmICghY21zUGlwZWxpbmVJbnNlcnRTdGFnZShQaXBlbGluZSwgY21zQVRfQkVHSU4sIGNtc1N0YWdlQWxsb2NUb25lQ3VydmVzKENvbnRleHRJRCwgbkNoYW5uZWxzLCBUcmFuc2ZlckZ1bmN0aW9ucykpKQogICAgICAgIGdvdG8gRXJyb3I7CgogICAgLy8gQ3JlYXRlIHRhZ3MKICAgIGlmICghU2V0VGV4dFRhZ3MoaElDQywgTCJMaW5lYXJpemF0aW9uIGJ1aWx0LWluIikpIGdvdG8gRXJyb3I7CiAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ0FUb0IwVGFnLCAodm9pZCopIFBpcGVsaW5lKSkgZ290byBFcnJvcjsKICAgIGlmICghU2V0U2VxRGVzY1RhZyhoSUNDLCAiTGluZWFyaXphdGlvbiBidWlsdC1pbiIpKSBnb3RvIEVycm9yOwoKICAgIC8vIFBpcGVsaW5lIGlzIGFscmVhZHkgb24gdmlydHVhbCBwcm9maWxlCiAgICBjbXNQaXBlbGluZUZyZWUoUGlwZWxpbmUpOwoKICAgIC8vIE9rLCBkb25lCiAgICByZXR1cm4gaElDQzsKCkVycm9yOgogICAgY21zUGlwZWxpbmVGcmVlKFBpcGVsaW5lKTsKICAgIGlmIChoSUNDKQogICAgICAgIGNtc0Nsb3NlUHJvZmlsZShoSUNDKTsKCgogICAgcmV0dXJuIE5VTEw7Cn0KCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVMaW5lYXJpemF0aW9uRGV2aWNlTGluayhjbXNDb2xvclNwYWNlU2lnbmF0dXJlIENvbG9yU3BhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zVG9uZUN1cnZlKiBjb25zdCBUcmFuc2ZlckZ1bmN0aW9uc1tdKQp7CiAgICByZXR1cm4gY21zQ3JlYXRlTGluZWFyaXphdGlvbkRldmljZUxpbmtUSFIoTlVMTCwgQ29sb3JTcGFjZSwgVHJhbnNmZXJGdW5jdGlvbnMpOwp9CgovLyBJbmstbGltaXRpbmcgYWxnb3JpdGhtCi8vCi8vICBTdW0gPSBDICsgTSArIFkgKyBLCi8vICBJZiBTdW0gPiBJbmtMaW1pdAovLyAgICAgICAgUmF0aW89IDEgLSAoU3VtIC0gSW5rTGltaXQpIC8gKEMgKyBNICsgWSkKLy8gICAgICAgIGlmIFJhdGlvIDwwCi8vICAgICAgICAgICAgICBSYXRpbz0wCi8vICAgICAgICBlbmRpZgovLyAgICAgRWxzZQovLyAgICAgICAgIFJhdGlvPTEKLy8gICAgIGVuZGlmCi8vCi8vICAgICBDID0gUmF0aW8gKiBDCi8vICAgICBNID0gUmF0aW8gKiBNCi8vICAgICBZID0gUmF0aW8gKiBZCi8vICAgICBLOiBEb2VzIG5vdCBjaGFuZ2UKCnN0YXRpYwppbnQgSW5rTGltaXRpbmdTYW1wbGVyKHJlZ2lzdGVyIGNvbnN0IGNtc1VJbnQxNk51bWJlciBJbltdLCByZWdpc3RlciBjbXNVSW50MTZOdW1iZXIgT3V0W10sIHJlZ2lzdGVyIHZvaWQqIENhcmdvKQp7CiAgICBjbXNGbG9hdDY0TnVtYmVyIElua0xpbWl0ID0gKihjbXNGbG9hdDY0TnVtYmVyICopIENhcmdvOwogICAgY21zRmxvYXQ2NE51bWJlciBTdW1DTVksIFN1bUNNWUssIFJhdGlvOwoKICAgIElua0xpbWl0ID0gKElua0xpbWl0ICogNjU1LjM1KTsKCiAgICBTdW1DTVkgICA9IEluWzBdICArIEluWzFdICsgSW5bMl07CiAgICBTdW1DTVlLICA9IFN1bUNNWSArIEluWzNdOwoKICAgIGlmIChTdW1DTVlLID4gSW5rTGltaXQpIHsKCiAgICAgICAgUmF0aW8gPSAxIC0gKChTdW1DTVlLIC0gSW5rTGltaXQpIC8gU3VtQ01ZKTsKICAgICAgICBpZiAoUmF0aW8gPCAwKQogICAgICAgICAgICBSYXRpbyA9IDA7CiAgICB9CiAgICBlbHNlIFJhdGlvID0gMTsKCiAgICBPdXRbMF0gPSBfY21zUXVpY2tTYXR1cmF0ZVdvcmQoSW5bMF0gKiBSYXRpbyk7ICAgICAvLyBDCiAgICBPdXRbMV0gPSBfY21zUXVpY2tTYXR1cmF0ZVdvcmQoSW5bMV0gKiBSYXRpbyk7ICAgICAvLyBNCiAgICBPdXRbMl0gPSBfY21zUXVpY2tTYXR1cmF0ZVdvcmQoSW5bMl0gKiBSYXRpbyk7ICAgICAvLyBZCgogICAgT3V0WzNdID0gSW5bM107ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSyAodW50b3VjaGVkKQoKICAgIHJldHVybiBUUlVFOwp9CgovLyBUaGlzIGlzIGEgZGV2aWNlbGluayBvcGVyYXRpbmcgaW4gQ01ZSyBmb3IgaW5rLWxpbWl0aW5nCgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlSW5rTGltaXRpbmdEZXZpY2VMaW5rVEhSKGNtc0NvbnRleHQgQ29udGV4dElELAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc0NvbG9yU3BhY2VTaWduYXR1cmUgQ29sb3JTcGFjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbXNGbG9hdDY0TnVtYmVyIExpbWl0KQp7CiAgICBjbXNIUFJPRklMRSBoSUNDOwogICAgY21zUGlwZWxpbmUqIExVVDsKICAgIGNtc1N0YWdlKiBDTFVUOwogICAgaW50IG5DaGFubmVsczsKCiAgICBpZiAoQ29sb3JTcGFjZSAhPSBjbXNTaWdDbXlrRGF0YSkgewogICAgICAgIGNtc1NpZ25hbEVycm9yKENvbnRleHRJRCwgY21zRVJST1JfQ09MT1JTUEFDRV9DSEVDSywgIklua0xpbWl0aW5nOiBPbmx5IENNWUsgY3VycmVudGx5IHN1cHBvcnRlZCIpOwogICAgICAgIHJldHVybiBOVUxMOwogICAgfQoKICAgIGlmIChMaW1pdCA8IDAuMCB8fCBMaW1pdCA+IDQwMCkgewoKICAgICAgICBjbXNTaWduYWxFcnJvcihDb250ZXh0SUQsIGNtc0VSUk9SX1JBTkdFLCAiSW5rTGltaXRpbmc6IExpbWl0IHNob3VsZCBiZSBiZXR3ZWVuIDAuLjQwMCIpOwogICAgICAgIGlmIChMaW1pdCA8IDApIExpbWl0ID0gMDsKICAgICAgICBpZiAoTGltaXQgPiA0MDApIExpbWl0ID0gNDAwOwoKICAgIH0KCiAgICBoSUNDID0gY21zQ3JlYXRlUHJvZmlsZVBsYWNlaG9sZGVyKENvbnRleHRJRCk7CiAgICBpZiAoIWhJQ0MpICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjYW4ndCBhbGxvY2F0ZQogICAgICAgIHJldHVybiBOVUxMOwoKICAgIGNtc1NldFByb2ZpbGVWZXJzaW9uKGhJQ0MsIDQuMyk7CgogICAgY21zU2V0RGV2aWNlQ2xhc3MoaElDQywgICAgICBjbXNTaWdMaW5rQ2xhc3MpOwogICAgY21zU2V0Q29sb3JTcGFjZShoSUNDLCAgICAgICBDb2xvclNwYWNlKTsKICAgIGNtc1NldFBDUyhoSUNDLCAgICAgICAgICAgICAgQ29sb3JTcGFjZSk7CgogICAgY21zU2V0SGVhZGVyUmVuZGVyaW5nSW50ZW50KGhJQ0MsICBJTlRFTlRfUEVSQ0VQVFVBTCk7CgoKICAgIC8vIENyZWF0ZXMgYSBQaXBlbGluZSB3aXRoIDNEIGdyaWQgb25seQogICAgTFVUID0gY21zUGlwZWxpbmVBbGxvYyhDb250ZXh0SUQsIDQsIDQpOwogICAgaWYgKExVVCA9PSBOVUxMKSBnb3RvIEVycm9yOwoKCiAgICBuQ2hhbm5lbHMgPSBjbXNDaGFubmVsc09mKENvbG9yU3BhY2UpOwoKICAgIENMVVQgPSBjbXNTdGFnZUFsbG9jQ0x1dDE2Yml0KENvbnRleHRJRCwgMTcsIG5DaGFubmVscywgbkNoYW5uZWxzLCBOVUxMKTsKICAgIGlmIChDTFVUID09IE5VTEwpIGdvdG8gRXJyb3I7CgogICAgaWYgKCFjbXNTdGFnZVNhbXBsZUNMdXQxNmJpdChDTFVULCBJbmtMaW1pdGluZ1NhbXBsZXIsICh2b2lkKikgJkxpbWl0LCAwKSkgZ290byBFcnJvcjsKCiAgICBpZiAoIWNtc1BpcGVsaW5lSW5zZXJ0U3RhZ2UoTFVULCBjbXNBVF9CRUdJTiwgX2Ntc1N0YWdlQWxsb2NJZGVudGl0eUN1cnZlcyhDb250ZXh0SUQsIG5DaGFubmVscykpIHx8CiAgICAgICAgIWNtc1BpcGVsaW5lSW5zZXJ0U3RhZ2UoTFVULCBjbXNBVF9FTkQsIENMVVQpIHx8CiAgICAgICAgIWNtc1BpcGVsaW5lSW5zZXJ0U3RhZ2UoTFVULCBjbXNBVF9FTkQsIF9jbXNTdGFnZUFsbG9jSWRlbnRpdHlDdXJ2ZXMoQ29udGV4dElELCBuQ2hhbm5lbHMpKSkKICAgICAgICBnb3RvIEVycm9yOwoKICAgIC8vIENyZWF0ZSB0YWdzCiAgICBpZiAoIVNldFRleHRUYWdzKGhJQ0MsIEwiaW5rLWxpbWl0aW5nIGJ1aWx0LWluIikpIGdvdG8gRXJyb3I7CgogICAgaWYgKCFjbXNXcml0ZVRhZyhoSUNDLCBjbXNTaWdBVG9CMFRhZywgKHZvaWQqKSBMVVQpKSAgZ290byBFcnJvcjsKICAgIGlmICghU2V0U2VxRGVzY1RhZyhoSUNDLCAiaW5rLWxpbWl0aW5nIGJ1aWx0LWluIikpIGdvdG8gRXJyb3I7CgogICAgLy8gY21zUGlwZWxpbmUgaXMgYWxyZWFkeSBvbiB2aXJ0dWFsIHByb2ZpbGUKICAgIGNtc1BpcGVsaW5lRnJlZShMVVQpOwoKICAgIC8vIE9rLCBkb25lCiAgICByZXR1cm4gaElDQzsKCkVycm9yOgogICAgaWYgKExVVCAhPSBOVUxMKQogICAgICAgIGNtc1BpcGVsaW5lRnJlZShMVVQpOwoKICAgIGlmIChoSUNDICE9IE5VTEwpCiAgICAgICAgY21zQ2xvc2VQcm9maWxlKGhJQ0MpOwoKICAgIHJldHVybiBOVUxMOwp9CgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlSW5rTGltaXRpbmdEZXZpY2VMaW5rKGNtc0NvbG9yU3BhY2VTaWduYXR1cmUgQ29sb3JTcGFjZSwgY21zRmxvYXQ2NE51bWJlciBMaW1pdCkKewogICAgcmV0dXJuIGNtc0NyZWF0ZUlua0xpbWl0aW5nRGV2aWNlTGlua1RIUihOVUxMLCBDb2xvclNwYWNlLCBMaW1pdCk7Cn0KCgovLyBDcmVhdGVzIGEgZmFrZSBMYWIgaWRlbnRpdHkuCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVMYWIyUHJvZmlsZVRIUihjbXNDb250ZXh0IENvbnRleHRJRCwgY29uc3QgY21zQ0lFeHlZKiBXaGl0ZVBvaW50KQp7CiAgICBjbXNIUFJPRklMRSBoUHJvZmlsZTsKICAgIGNtc1BpcGVsaW5lKiBMVVQgPSBOVUxMOwoKICAgIGhQcm9maWxlID0gY21zQ3JlYXRlUkdCUHJvZmlsZVRIUihDb250ZXh0SUQsIFdoaXRlUG9pbnQgPT0gTlVMTCA/IGNtc0Q1MF94eVkoKSA6IFdoaXRlUG9pbnQsIE5VTEwsIE5VTEwpOwogICAgaWYgKGhQcm9maWxlID09IE5VTEwpIHJldHVybiBOVUxMOwoKICAgIGNtc1NldFByb2ZpbGVWZXJzaW9uKGhQcm9maWxlLCAyLjEpOwoKICAgIGNtc1NldERldmljZUNsYXNzKGhQcm9maWxlLCBjbXNTaWdBYnN0cmFjdENsYXNzKTsKICAgIGNtc1NldENvbG9yU3BhY2UoaFByb2ZpbGUsICBjbXNTaWdMYWJEYXRhKTsKICAgIGNtc1NldFBDUyhoUHJvZmlsZSwgICAgICAgICBjbXNTaWdMYWJEYXRhKTsKCiAgICBpZiAoIVNldFRleHRUYWdzKGhQcm9maWxlLCBMIkxhYiBpZGVudGl0eSBidWlsdC1pbiIpKSByZXR1cm4gTlVMTDsKCiAgICAvLyBBbiBpZGVudGl0eSBMVVQgaXMgYWxsIHdlIG5lZWQKICAgIExVVCA9IGNtc1BpcGVsaW5lQWxsb2MoQ29udGV4dElELCAzLCAzKTsKICAgIGlmIChMVVQgPT0gTlVMTCkgZ290byBFcnJvcjsKCiAgICBpZiAoIWNtc1BpcGVsaW5lSW5zZXJ0U3RhZ2UoTFVULCBjbXNBVF9CRUdJTiwgX2Ntc1N0YWdlQWxsb2NJZGVudGl0eUNMdXQoQ29udGV4dElELCAzKSkpCiAgICAgICAgZ290byBFcnJvcjsKCiAgICBpZiAoIWNtc1dyaXRlVGFnKGhQcm9maWxlLCBjbXNTaWdBVG9CMFRhZywgTFVUKSkgZ290byBFcnJvcjsKICAgIGNtc1BpcGVsaW5lRnJlZShMVVQpOwoKICAgIHJldHVybiBoUHJvZmlsZTsKCkVycm9yOgoKICAgIGlmIChMVVQgIT0gTlVMTCkKICAgICAgICBjbXNQaXBlbGluZUZyZWUoTFVUKTsKCiAgICBpZiAoaFByb2ZpbGUgIT0gTlVMTCkKICAgICAgICBjbXNDbG9zZVByb2ZpbGUoaFByb2ZpbGUpOwoKICAgIHJldHVybiBOVUxMOwp9CgoKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZUxhYjJQcm9maWxlKGNvbnN0IGNtc0NJRXh5WSogV2hpdGVQb2ludCkKewogICAgcmV0dXJuIGNtc0NyZWF0ZUxhYjJQcm9maWxlVEhSKE5VTEwsIFdoaXRlUG9pbnQpOwp9CgoKLy8gQ3JlYXRlcyBhIGZha2UgTGFiIFY0IGlkZW50aXR5LgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlTGFiNFByb2ZpbGVUSFIoY21zQ29udGV4dCBDb250ZXh0SUQsIGNvbnN0IGNtc0NJRXh5WSogV2hpdGVQb2ludCkKewogICAgY21zSFBST0ZJTEUgaFByb2ZpbGU7CiAgICBjbXNQaXBlbGluZSogTFVUID0gTlVMTDsKCiAgICBoUHJvZmlsZSA9IGNtc0NyZWF0ZVJHQlByb2ZpbGVUSFIoQ29udGV4dElELCBXaGl0ZVBvaW50ID09IE5VTEwgPyBjbXNENTBfeHlZKCkgOiBXaGl0ZVBvaW50LCBOVUxMLCBOVUxMKTsKICAgIGlmIChoUHJvZmlsZSA9PSBOVUxMKSByZXR1cm4gTlVMTDsKCiAgICBjbXNTZXRQcm9maWxlVmVyc2lvbihoUHJvZmlsZSwgNC4zKTsKCiAgICBjbXNTZXREZXZpY2VDbGFzcyhoUHJvZmlsZSwgY21zU2lnQWJzdHJhY3RDbGFzcyk7CiAgICBjbXNTZXRDb2xvclNwYWNlKGhQcm9maWxlLCAgY21zU2lnTGFiRGF0YSk7CiAgICBjbXNTZXRQQ1MoaFByb2ZpbGUsICAgICAgICAgY21zU2lnTGFiRGF0YSk7CgogICAgaWYgKCFTZXRUZXh0VGFncyhoUHJvZmlsZSwgTCJMYWIgaWRlbnRpdHkgYnVpbHQtaW4iKSkgZ290byBFcnJvcjsKCiAgICAvLyBBbiBlbXB0eSBMVVRzIGlzIGFsbCB3ZSBuZWVkCiAgICBMVVQgPSBjbXNQaXBlbGluZUFsbG9jKENvbnRleHRJRCwgMywgMyk7CiAgICBpZiAoTFVUID09IE5VTEwpIGdvdG8gRXJyb3I7CgogICAgaWYgKCFjbXNQaXBlbGluZUluc2VydFN0YWdlKExVVCwgY21zQVRfQkVHSU4sIF9jbXNTdGFnZUFsbG9jSWRlbnRpdHlDdXJ2ZXMoQ29udGV4dElELCAzKSkpCiAgICAgICAgZ290byBFcnJvcjsKCiAgICBpZiAoIWNtc1dyaXRlVGFnKGhQcm9maWxlLCBjbXNTaWdBVG9CMFRhZywgTFVUKSkgZ290byBFcnJvcjsKICAgIGNtc1BpcGVsaW5lRnJlZShMVVQpOwoKICAgIHJldHVybiBoUHJvZmlsZTsKCkVycm9yOgoKICAgIGlmIChMVVQgIT0gTlVMTCkKICAgICAgICBjbXNQaXBlbGluZUZyZWUoTFVUKTsKCiAgICBpZiAoaFByb2ZpbGUgIT0gTlVMTCkKICAgICAgICBjbXNDbG9zZVByb2ZpbGUoaFByb2ZpbGUpOwoKICAgIHJldHVybiBOVUxMOwp9CgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlTGFiNFByb2ZpbGUoY29uc3QgY21zQ0lFeHlZKiBXaGl0ZVBvaW50KQp7CiAgICByZXR1cm4gY21zQ3JlYXRlTGFiNFByb2ZpbGVUSFIoTlVMTCwgV2hpdGVQb2ludCk7Cn0KCgovLyBDcmVhdGVzIGEgZmFrZSBYWVogaWRlbnRpdHkKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZVhZWlByb2ZpbGVUSFIoY21zQ29udGV4dCBDb250ZXh0SUQpCnsKICAgIGNtc0hQUk9GSUxFIGhQcm9maWxlOwogICAgY21zUGlwZWxpbmUqIExVVCA9IE5VTEw7CgogICAgaFByb2ZpbGUgPSBjbXNDcmVhdGVSR0JQcm9maWxlVEhSKENvbnRleHRJRCwgY21zRDUwX3h5WSgpLCBOVUxMLCBOVUxMKTsKICAgIGlmIChoUHJvZmlsZSA9PSBOVUxMKSByZXR1cm4gTlVMTDsKCiAgICBjbXNTZXRQcm9maWxlVmVyc2lvbihoUHJvZmlsZSwgNC4zKTsKCiAgICBjbXNTZXREZXZpY2VDbGFzcyhoUHJvZmlsZSwgY21zU2lnQWJzdHJhY3RDbGFzcyk7CiAgICBjbXNTZXRDb2xvclNwYWNlKGhQcm9maWxlLCAgY21zU2lnWFlaRGF0YSk7CiAgICBjbXNTZXRQQ1MoaFByb2ZpbGUsICAgICAgICAgY21zU2lnWFlaRGF0YSk7CgogICAgaWYgKCFTZXRUZXh0VGFncyhoUHJvZmlsZSwgTCJYWVogaWRlbnRpdHkgYnVpbHQtaW4iKSkgZ290byBFcnJvcjsKCiAgICAvLyBBbiBpZGVudGl0eSBMVVQgaXMgYWxsIHdlIG5lZWQKICAgIExVVCA9IGNtc1BpcGVsaW5lQWxsb2MoQ29udGV4dElELCAzLCAzKTsKICAgIGlmIChMVVQgPT0gTlVMTCkgZ290byBFcnJvcjsKCiAgICBpZiAoIWNtc1BpcGVsaW5lSW5zZXJ0U3RhZ2UoTFVULCBjbXNBVF9CRUdJTiwgX2Ntc1N0YWdlQWxsb2NJZGVudGl0eUN1cnZlcyhDb250ZXh0SUQsIDMpKSkKICAgICAgICBnb3RvIEVycm9yOwoKICAgIGlmICghY21zV3JpdGVUYWcoaFByb2ZpbGUsIGNtc1NpZ0FUb0IwVGFnLCBMVVQpKSBnb3RvIEVycm9yOwogICAgY21zUGlwZWxpbmVGcmVlKExVVCk7CgogICAgcmV0dXJuIGhQcm9maWxlOwoKRXJyb3I6CgogICAgaWYgKExVVCAhPSBOVUxMKQogICAgICAgIGNtc1BpcGVsaW5lRnJlZShMVVQpOwoKICAgIGlmIChoUHJvZmlsZSAhPSBOVUxMKQogICAgICAgIGNtc0Nsb3NlUHJvZmlsZShoUHJvZmlsZSk7CgogICAgcmV0dXJuIE5VTEw7Cn0KCgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlWFlaUHJvZmlsZSh2b2lkKQp7CiAgICByZXR1cm4gY21zQ3JlYXRlWFlaUHJvZmlsZVRIUihOVUxMKTsKfQoKCi8vc1JHQiBDdXJ2ZXMgYXJlIGRlZmluZWQgYnk6Ci8vCi8vSWYgIFKSc1JHQixHknNSR0IsIEKSc1JHQiA8IDAuMDQwNDUKLy8KLy8gICAgUiA9ICBSknNSR0IgLyAxMi45MgovLyAgICBHID0gIEeSc1JHQiAvIDEyLjkyCi8vICAgIEIgPSAgQpJzUkdCIC8gMTIuOTIKLy8KLy8KLy9lbHNlIGlmICBSknNSR0IsR5JzUkdCLCBCknNSR0IgPj0gMC4wNDA0NQovLwovLyAgICBSID0gKChSknNSR0IgKyAwLjA1NSkgLyAxLjA1NSleMi40Ci8vICAgIEcgPSAoKEeSc1JHQiArIDAuMDU1KSAvIDEuMDU1KV4yLjQKLy8gICAgQiA9ICgoQpJzUkdCICsgMC4wNTUpIC8gMS4wNTUpXjIuNAoKc3RhdGljCmNtc1RvbmVDdXJ2ZSogQnVpbGRfc1JHQkdhbW1hKGNtc0NvbnRleHQgQ29udGV4dElEKQp7CiAgICBjbXNGbG9hdDY0TnVtYmVyIFBhcmFtZXRlcnNbNV07CgogICAgUGFyYW1ldGVyc1swXSA9IDIuNDsKICAgIFBhcmFtZXRlcnNbMV0gPSAxLiAvIDEuMDU1OwogICAgUGFyYW1ldGVyc1syXSA9IDAuMDU1IC8gMS4wNTU7CiAgICBQYXJhbWV0ZXJzWzNdID0gMS4gLyAxMi45MjsKICAgIFBhcmFtZXRlcnNbNF0gPSAwLjA0MDQ1OwoKICAgIHJldHVybiBjbXNCdWlsZFBhcmFtZXRyaWNUb25lQ3VydmUoQ29udGV4dElELCA0LCBQYXJhbWV0ZXJzKTsKfQoKLy8gQ3JlYXRlIHRoZSBJQ0MgdmlydHVhbCBwcm9maWxlIGZvciBzUkdCIHNwYWNlCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVfc1JHQlByb2ZpbGVUSFIoY21zQ29udGV4dCBDb250ZXh0SUQpCnsKICAgICAgIGNtc0NJRXh5WSAgICAgICBENjU7CiAgICAgICBjbXNDSUV4eVlUUklQTEUgUmVjNzA5UHJpbWFyaWVzID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHswLjY0MDAsIDAuMzMwMCwgMS4wfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7MC4zMDAwLCAwLjYwMDAsIDEuMH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgezAuMTUwMCwgMC4wNjAwLCAxLjB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgIGNtc1RvbmVDdXJ2ZSogR2FtbWEyMlszXTsKICAgICAgIGNtc0hQUk9GSUxFICBoc1JHQjsKCiAgICAgICBjbXNXaGl0ZVBvaW50RnJvbVRlbXAoJkQ2NSwgNjUwNCk7CiAgICAgICBHYW1tYTIyWzBdID0gR2FtbWEyMlsxXSA9IEdhbW1hMjJbMl0gPSBCdWlsZF9zUkdCR2FtbWEoQ29udGV4dElEKTsKICAgICAgIGlmIChHYW1tYTIyWzBdID09IE5VTEwpIHJldHVybiBOVUxMOwoKICAgICAgIGhzUkdCID0gY21zQ3JlYXRlUkdCUHJvZmlsZVRIUihDb250ZXh0SUQsICZENjUsICZSZWM3MDlQcmltYXJpZXMsIEdhbW1hMjIpOwogICAgICAgY21zRnJlZVRvbmVDdXJ2ZShHYW1tYTIyWzBdKTsKICAgICAgIGlmIChoc1JHQiA9PSBOVUxMKSByZXR1cm4gTlVMTDsKCiAgICAgICBpZiAoIVNldFRleHRUYWdzKGhzUkdCLCBMInNSR0IgYnVpbHQtaW4iKSkgewogICAgICAgICAgIGNtc0Nsb3NlUHJvZmlsZShoc1JHQik7CiAgICAgICAgICAgcmV0dXJuIE5VTEw7CiAgICAgICB9CgogICAgICAgcmV0dXJuIGhzUkdCOwp9CgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlX3NSR0JQcm9maWxlKHZvaWQpCnsKICAgIHJldHVybiBjbXNDcmVhdGVfc1JHQlByb2ZpbGVUSFIoTlVMTCk7Cn0KCgoKdHlwZWRlZiBzdHJ1Y3QgewogICAgICAgICAgICAgICAgY21zRmxvYXQ2NE51bWJlciBCcmlnaHRuZXNzOwogICAgICAgICAgICAgICAgY21zRmxvYXQ2NE51bWJlciBDb250cmFzdDsKICAgICAgICAgICAgICAgIGNtc0Zsb2F0NjROdW1iZXIgSHVlOwogICAgICAgICAgICAgICAgY21zRmxvYXQ2NE51bWJlciBTYXR1cmF0aW9uOwogICAgICAgICAgICAgICAgY21zQ0lFWFlaIFdQc3JjLCBXUGRlc3Q7Cgp9IEJDSFNXQURKVVNUUywgKkxQQkNIU1dBREpVU1RTOwoKCnN0YXRpYwppbnQgYmNoc3dTYW1wbGVyKHJlZ2lzdGVyIGNvbnN0IGNtc1VJbnQxNk51bWJlciBJbltdLCByZWdpc3RlciBjbXNVSW50MTZOdW1iZXIgT3V0W10sIHJlZ2lzdGVyIHZvaWQqIENhcmdvKQp7CiAgICBjbXNDSUVMYWIgTGFiSW4sIExhYk91dDsKICAgIGNtc0NJRUxDaCBMQ2hJbiwgTENoT3V0OwogICAgY21zQ0lFWFlaIFhZWjsKICAgIExQQkNIU1dBREpVU1RTIGJjaHN3ID0gKExQQkNIU1dBREpVU1RTKSBDYXJnbzsKCgogICAgY21zTGFiRW5jb2RlZDJGbG9hdCgmTGFiSW4sIEluKTsKCgogICAgY21zTGFiMkxDaCgmTENoSW4sICZMYWJJbik7CgogICAgLy8gRG8gc29tZSBhZGp1c3RzIG9uIExDaAoKICAgIExDaE91dC5MID0gTENoSW4uTCAqIGJjaHN3IC0+Q29udHJhc3QgKyBiY2hzdyAtPkJyaWdodG5lc3M7CiAgICBMQ2hPdXQuQyA9IExDaEluLkMgKyBiY2hzdyAtPiBTYXR1cmF0aW9uOwogICAgTENoT3V0LmggPSBMQ2hJbi5oICsgYmNoc3cgLT4gSHVlOwoKCiAgICBjbXNMQ2gyTGFiKCZMYWJPdXQsICZMQ2hPdXQpOwoKICAgIC8vIE1vdmUgd2hpdGUgcG9pbnQgaW4gTGFiCgogICAgY21zTGFiMlhZWigmYmNoc3cgLT5XUHNyYywgICZYWVosICZMYWJPdXQpOwogICAgY21zWFlaMkxhYigmYmNoc3cgLT5XUGRlc3QsICZMYWJPdXQsICZYWVopOwoKICAgIC8vIEJhY2sgdG8gZW5jb2RlZAoKICAgIGNtc0Zsb2F0MkxhYkVuY29kZWQoT3V0LCAmTGFiT3V0KTsKCiAgICByZXR1cm4gVFJVRTsKfQoKCi8vIENyZWF0ZXMgYW4gYWJzdHJhY3QgcHJvZmlsZSBvcGVyYXRpbmcgaW4gTGFiIHNwYWNlIGZvciBCcmlnaHRuZXNzLAovLyBjb250cmFzdCwgU2F0dXJhdGlvbiBhbmQgd2hpdGUgcG9pbnQgZGlzcGxhY2VtZW50CgpjbXNIUFJPRklMRSBDTVNFWFBPUlQgY21zQ3JlYXRlQkNIU1dhYnN0cmFjdFByb2ZpbGVUSFIoY21zQ29udGV4dCBDb250ZXh0SUQsCiAgICBpbnQgbkxVVFBvaW50cywKICAgIGNtc0Zsb2F0NjROdW1iZXIgQnJpZ2h0LAogICAgY21zRmxvYXQ2NE51bWJlciBDb250cmFzdCwKICAgIGNtc0Zsb2F0NjROdW1iZXIgSHVlLAogICAgY21zRmxvYXQ2NE51bWJlciBTYXR1cmF0aW9uLAogICAgaW50IFRlbXBTcmMsCiAgICBpbnQgVGVtcERlc3QpCnsKICAgIGNtc0hQUk9GSUxFIGhJQ0M7CiAgICBjbXNQaXBlbGluZSogUGlwZWxpbmU7CiAgICBCQ0hTV0FESlVTVFMgYmNoc3c7CiAgICBjbXNDSUV4eVkgV2hpdGVQbnQ7CiAgICBjbXNTdGFnZSogQ0xVVDsKICAgIGNtc1VJbnQzMk51bWJlciBEaW1lbnNpb25zW01BWF9JTlBVVF9ESU1FTlNJT05TXTsKICAgIGludCBpOwoKICAgIGJjaHN3LkJyaWdodG5lc3MgPSBCcmlnaHQ7CiAgICBiY2hzdy5Db250cmFzdCAgID0gQ29udHJhc3Q7CiAgICBiY2hzdy5IdWUgICAgICAgID0gSHVlOwogICAgYmNoc3cuU2F0dXJhdGlvbiA9IFNhdHVyYXRpb247CgogICAgY21zV2hpdGVQb2ludEZyb21UZW1wKCZXaGl0ZVBudCwgVGVtcFNyYyApOwogICAgY21zeHlZMlhZWigmYmNoc3cuV1BzcmMsICZXaGl0ZVBudCk7CgogICAgY21zV2hpdGVQb2ludEZyb21UZW1wKCZXaGl0ZVBudCwgVGVtcERlc3QpOwogICAgY21zeHlZMlhZWigmYmNoc3cuV1BkZXN0LCAmV2hpdGVQbnQpOwoKICAgIGhJQ0MgPSBjbXNDcmVhdGVQcm9maWxlUGxhY2Vob2xkZXIoQ29udGV4dElEKTsKICAgIGlmICghaElDQykgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbid0IGFsbG9jYXRlCiAgICAgICAgcmV0dXJuIE5VTEw7CgoKICAgIGNtc1NldERldmljZUNsYXNzKGhJQ0MsICAgICAgY21zU2lnQWJzdHJhY3RDbGFzcyk7CiAgICBjbXNTZXRDb2xvclNwYWNlKGhJQ0MsICAgICAgIGNtc1NpZ0xhYkRhdGEpOwogICAgY21zU2V0UENTKGhJQ0MsICAgICAgICAgICAgICBjbXNTaWdMYWJEYXRhKTsKCiAgICBjbXNTZXRIZWFkZXJSZW5kZXJpbmdJbnRlbnQoaElDQywgIElOVEVOVF9QRVJDRVBUVUFMKTsKCiAgICAvLyBDcmVhdGVzIGEgUGlwZWxpbmUgd2l0aCAzRCBncmlkIG9ubHkKICAgIFBpcGVsaW5lID0gY21zUGlwZWxpbmVBbGxvYyhDb250ZXh0SUQsIDMsIDMpOwogICAgaWYgKFBpcGVsaW5lID09IE5VTEwpIHsKICAgICAgICBjbXNDbG9zZVByb2ZpbGUoaElDQyk7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CgogICAgZm9yIChpPTA7IGkgPCBNQVhfSU5QVVRfRElNRU5TSU9OUzsgaSsrKSBEaW1lbnNpb25zW2ldID0gbkxVVFBvaW50czsKICAgIENMVVQgPSBjbXNTdGFnZUFsbG9jQ0x1dDE2Yml0R3JhbnVsYXIoQ29udGV4dElELCBEaW1lbnNpb25zLCAzLCAzLCBOVUxMKTsKICAgIGlmIChDTFVUID09IE5VTEwpIHJldHVybiBOVUxMOwoKCiAgICBpZiAoIWNtc1N0YWdlU2FtcGxlQ0x1dDE2Yml0KENMVVQsIGJjaHN3U2FtcGxlciwgKHZvaWQqKSAmYmNoc3csIDApKSB7CgogICAgICAgIC8vIFNob3VsZG4ndCByZWFjaCBoZXJlCiAgICAgICAgZ290byBFcnJvcjsKICAgIH0KCiAgICBpZiAoIWNtc1BpcGVsaW5lSW5zZXJ0U3RhZ2UoUGlwZWxpbmUsIGNtc0FUX0VORCwgQ0xVVCkpIHsKICAgICAgICBnb3RvIEVycm9yOwogICAgfQoKICAgIC8vIENyZWF0ZSB0YWdzCiAgICBpZiAoIVNldFRleHRUYWdzKGhJQ0MsIEwiQkNIUyBidWlsdC1pbiIpKSByZXR1cm4gTlVMTDsKCiAgICBjbXNXcml0ZVRhZyhoSUNDLCBjbXNTaWdNZWRpYVdoaXRlUG9pbnRUYWcsICh2b2lkKikgY21zRDUwX1hZWigpKTsKCiAgICBjbXNXcml0ZVRhZyhoSUNDLCBjbXNTaWdBVG9CMFRhZywgKHZvaWQqKSBQaXBlbGluZSk7CgogICAgLy8gUGlwZWxpbmUgaXMgYWxyZWFkeSBvbiB2aXJ0dWFsIHByb2ZpbGUKICAgIGNtc1BpcGVsaW5lRnJlZShQaXBlbGluZSk7CgogICAgLy8gT2ssIGRvbmUKICAgIHJldHVybiBoSUNDOwoKRXJyb3I6CiAgICBjbXNQaXBlbGluZUZyZWUoUGlwZWxpbmUpOwogICAgY21zQ2xvc2VQcm9maWxlKGhJQ0MpOwogICAgcmV0dXJuIE5VTEw7Cn0KCgpDTVNBUEkgY21zSFBST0ZJTEUgICBDTVNFWFBPUlQgY21zQ3JlYXRlQkNIU1dhYnN0cmFjdFByb2ZpbGUoaW50IG5MVVRQb2ludHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbXNGbG9hdDY0TnVtYmVyIEJyaWdodCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc0Zsb2F0NjROdW1iZXIgQ29udHJhc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbXNGbG9hdDY0TnVtYmVyIEh1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc0Zsb2F0NjROdW1iZXIgU2F0dXJhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludCBUZW1wU3JjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IFRlbXBEZXN0KQp7CiAgICByZXR1cm4gY21zQ3JlYXRlQkNIU1dhYnN0cmFjdFByb2ZpbGVUSFIoTlVMTCwgbkxVVFBvaW50cywgQnJpZ2h0LCBDb250cmFzdCwgSHVlLCBTYXR1cmF0aW9uLCBUZW1wU3JjLCBUZW1wRGVzdCk7Cn0KCgovLyBDcmVhdGVzIGEgZmFrZSBOVUxMIHByb2ZpbGUuIFRoaXMgcHJvZmlsZSByZXR1cm4gMSBjaGFubmVsIGFzIGFsd2F5cyAwLgovLyBJcyB1c2VmdWwgb25seSBmb3IgZ2FtdXQgY2hlY2tpbmcgdHJpY2tzCmNtc0hQUk9GSUxFIENNU0VYUE9SVCBjbXNDcmVhdGVOVUxMUHJvZmlsZVRIUihjbXNDb250ZXh0IENvbnRleHRJRCkKewogICAgY21zSFBST0ZJTEUgaFByb2ZpbGU7CiAgICBjbXNQaXBlbGluZSogTFVUID0gTlVMTDsKICAgIGNtc1N0YWdlKiBQb3N0TGluOwogICAgY21zVG9uZUN1cnZlKiBFbXB0eVRhYjsKICAgIGNtc1VJbnQxNk51bWJlciBaZXJvWzJdID0geyAwLCAwIH07CgogICAgaFByb2ZpbGUgPSBjbXNDcmVhdGVQcm9maWxlUGxhY2Vob2xkZXIoQ29udGV4dElEKTsKICAgIGlmICghaFByb2ZpbGUpICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjYW4ndCBhbGxvY2F0ZQogICAgICAgIHJldHVybiBOVUxMOwoKICAgIGNtc1NldFByb2ZpbGVWZXJzaW9uKGhQcm9maWxlLCA0LjMpOwoKICAgIGlmICghU2V0VGV4dFRhZ3MoaFByb2ZpbGUsIEwiTlVMTCBwcm9maWxlIGJ1aWx0LWluIikpIGdvdG8gRXJyb3I7CgoKCiAgICBjbXNTZXREZXZpY2VDbGFzcyhoUHJvZmlsZSwgY21zU2lnT3V0cHV0Q2xhc3MpOwogICAgY21zU2V0Q29sb3JTcGFjZShoUHJvZmlsZSwgIGNtc1NpZ0dyYXlEYXRhKTsKICAgIGNtc1NldFBDUyhoUHJvZmlsZSwgICAgICAgICBjbXNTaWdMYWJEYXRhKTsKCiAgICAvLyBBbiBlbXB0eSBMVVRzIGlzIGFsbCB3ZSBuZWVkCiAgICBMVVQgPSBjbXNQaXBlbGluZUFsbG9jKENvbnRleHRJRCwgMSwgMSk7CiAgICBpZiAoTFVUID09IE5VTEwpIGdvdG8gRXJyb3I7CgogICAgRW1wdHlUYWIgPSBjbXNCdWlsZFRhYnVsYXRlZFRvbmVDdXJ2ZTE2KENvbnRleHRJRCwgMiwgWmVybyk7CiAgICBQb3N0TGluID0gY21zU3RhZ2VBbGxvY1RvbmVDdXJ2ZXMoQ29udGV4dElELCAxLCAmRW1wdHlUYWIpOwogICAgY21zRnJlZVRvbmVDdXJ2ZShFbXB0eVRhYik7CgogICAgaWYgKCFjbXNQaXBlbGluZUluc2VydFN0YWdlKExVVCwgY21zQVRfRU5ELCBQb3N0TGluKSkKICAgICAgICBnb3RvIEVycm9yOwoKICAgIGlmICghY21zV3JpdGVUYWcoaFByb2ZpbGUsIGNtc1NpZ0JUb0EwVGFnLCAodm9pZCopIExVVCkpIGdvdG8gRXJyb3I7CiAgICBpZiAoIWNtc1dyaXRlVGFnKGhQcm9maWxlLCBjbXNTaWdNZWRpYVdoaXRlUG9pbnRUYWcsIGNtc0Q1MF9YWVooKSkpIGdvdG8gRXJyb3I7CgogICAgY21zUGlwZWxpbmVGcmVlKExVVCk7CiAgICByZXR1cm4gaFByb2ZpbGU7CgpFcnJvcjoKCiAgICBpZiAoTFVUICE9IE5VTEwpCiAgICAgICAgY21zUGlwZWxpbmVGcmVlKExVVCk7CgogICAgaWYgKGhQcm9maWxlICE9IE5VTEwpCiAgICAgICAgY21zQ2xvc2VQcm9maWxlKGhQcm9maWxlKTsKCiAgICByZXR1cm4gTlVMTDsKfQoKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc0NyZWF0ZU5VTExQcm9maWxlKHZvaWQpCnsKICAgIHJldHVybiBjbXNDcmVhdGVOVUxMUHJvZmlsZVRIUihOVUxMKTsKfQoKCnN0YXRpYwppbnQgSXNQQ1MoY21zQ29sb3JTcGFjZVNpZ25hdHVyZSBDb2xvclNwYWNlKQp7CiAgICByZXR1cm4gKENvbG9yU3BhY2UgPT0gY21zU2lnWFlaRGF0YSB8fAogICAgICAgICAgICBDb2xvclNwYWNlID09IGNtc1NpZ0xhYkRhdGEpOwp9CgoKc3RhdGljCnZvaWQgRml4Q29sb3JTcGFjZXMoY21zSFBST0ZJTEUgaFByb2ZpbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc0NvbG9yU3BhY2VTaWduYXR1cmUgQ29sb3JTcGFjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY21zQ29sb3JTcGFjZVNpZ25hdHVyZSBQQ1MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtc1VJbnQzMk51bWJlciBkd0ZsYWdzKQp7CiAgICBpZiAoZHdGbGFncyAmIGNtc0ZMQUdTX0dVRVNTREVWSUNFQ0xBU1MpIHsKCiAgICAgICAgICAgIGlmIChJc1BDUyhDb2xvclNwYWNlKSAmJiBJc1BDUyhQQ1MpKSB7CgogICAgICAgICAgICAgICAgICAgIGNtc1NldERldmljZUNsYXNzKGhQcm9maWxlLCAgICAgIGNtc1NpZ0Fic3RyYWN0Q2xhc3MpOwogICAgICAgICAgICAgICAgICAgIGNtc1NldENvbG9yU3BhY2UoaFByb2ZpbGUsICAgICAgIENvbG9yU3BhY2UpOwogICAgICAgICAgICAgICAgICAgIGNtc1NldFBDUyhoUHJvZmlsZSwgICAgICAgICAgICAgIFBDUyk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoSXNQQ1MoQ29sb3JTcGFjZSkgJiYgIUlzUENTKFBDUykpIHsKCiAgICAgICAgICAgICAgICAgICAgY21zU2V0RGV2aWNlQ2xhc3MoaFByb2ZpbGUsIGNtc1NpZ091dHB1dENsYXNzKTsKICAgICAgICAgICAgICAgICAgICBjbXNTZXRQQ1MoaFByb2ZpbGUsICAgICAgICAgQ29sb3JTcGFjZSk7CiAgICAgICAgICAgICAgICAgICAgY21zU2V0Q29sb3JTcGFjZShoUHJvZmlsZSwgIFBDUyk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoSXNQQ1MoUENTKSAmJiAhSXNQQ1MoQ29sb3JTcGFjZSkpIHsKCiAgICAgICAgICAgICAgICAgICBjbXNTZXREZXZpY2VDbGFzcyhoUHJvZmlsZSwgIGNtc1NpZ0lucHV0Q2xhc3MpOwogICAgICAgICAgICAgICAgICAgY21zU2V0Q29sb3JTcGFjZShoUHJvZmlsZSwgICBDb2xvclNwYWNlKTsKICAgICAgICAgICAgICAgICAgIGNtc1NldFBDUyhoUHJvZmlsZSwgICAgICAgICAgUENTKTsKICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgfQoKICAgIGNtc1NldERldmljZUNsYXNzKGhQcm9maWxlLCAgICAgIGNtc1NpZ0xpbmtDbGFzcyk7CiAgICBjbXNTZXRDb2xvclNwYWNlKGhQcm9maWxlLCAgICAgICBDb2xvclNwYWNlKTsKICAgIGNtc1NldFBDUyhoUHJvZmlsZSwgICAgICAgICAgICAgIFBDUyk7Cn0KCgoKLy8gVGhpcyBmdW5jdGlvbiBjcmVhdGVzIGEgbmFtZWQgY29sb3IgcHJvZmlsZSBkdW1waW5nIGFsbCB0aGUgY29udGVudHMgb2YgdHJhbnNmb3JtIHRvIGEgc2luZ2xlIHByb2ZpbGUKLy8gSW4gdGhpcyB3YXksIExpdHRsZUNNUyBtYXkgYmUgdXNlZCB0byAiZ3JvdXAiIHNldmVyYWwgbmFtZWQgY29sb3IgZGF0YWJhc2VzIGludG8gYSBzaW5nbGUgcHJvZmlsZS4KLy8gSXQgaGFzLCBob3dldmVyLCBzZXZlcmFsIG1pbm9yIGxpbWl0YXRpb25zLiBQQ1MgaXMgYWx3YXlzIExhYiwgd2hpY2ggaXMgbm90IHZlcnkgY3JpdGljIHNpbmNlIHRoaXMKLy8gaXMgdGhlIG5vcm1hbCBQQ1MgZm9yIG5hbWVkIGNvbG9yIHByb2ZpbGVzLgpzdGF0aWMKY21zSFBST0ZJTEUgQ3JlYXRlTmFtZWRDb2xvckRldmljZWxpbmsoY21zSFRSQU5TRk9STSB4Zm9ybSkKewogICAgX2Ntc1RSQU5TRk9STSogdiA9IChfY21zVFJBTlNGT1JNKikgeGZvcm07CiAgICBjbXNIUFJPRklMRSBoSUNDID0gTlVMTDsKICAgIGludCBpLCBuQ29sb3JzOwogICAgY21zTkFNRURDT0xPUkxJU1QgKm5jMiA9IE5VTEwsICpPcmlnaW5hbCA9IE5VTEw7CgogICAgLy8gQ3JlYXRlIGFuIGVtcHR5IHBsYWNlaG9sZGVyCiAgICBoSUNDID0gY21zQ3JlYXRlUHJvZmlsZVBsYWNlaG9sZGVyKHYtPkNvbnRleHRJRCk7CiAgICBpZiAoaElDQyA9PSBOVUxMKSByZXR1cm4gTlVMTDsKCiAgICAvLyBDcml0aWNhbCBpbmZvcm1hdGlvbgogICAgY21zU2V0RGV2aWNlQ2xhc3MoaElDQywgY21zU2lnTmFtZWRDb2xvckNsYXNzKTsKICAgIGNtc1NldENvbG9yU3BhY2UoaElDQywgdiAtPkV4aXRDb2xvclNwYWNlKTsKICAgIGNtc1NldFBDUyhoSUNDLCBjbXNTaWdMYWJEYXRhKTsKCiAgICAvLyBUYWcgcHJvZmlsZSB3aXRoIGluZm9ybWF0aW9uCiAgICBpZiAoIVNldFRleHRUYWdzKGhJQ0MsIEwiTmFtZWQgY29sb3IgZGV2aWNlbGluayIpKSBnb3RvIEVycm9yOwoKICAgIE9yaWdpbmFsID0gY21zR2V0TmFtZWRDb2xvckxpc3QoeGZvcm0pOwogICAgaWYgKE9yaWdpbmFsID09IE5VTEwpIGdvdG8gRXJyb3I7CgogICAgbkNvbG9ycyA9IGNtc05hbWVkQ29sb3JDb3VudChPcmlnaW5hbCk7CiAgICBuYzIgICAgID0gY21zRHVwTmFtZWRDb2xvckxpc3QoT3JpZ2luYWwpOwogICAgaWYgKG5jMiA9PSBOVUxMKSBnb3RvIEVycm9yOwoKICAgIC8vIENvbG9yYW50IGNvdW50IG5vdyBkZXBlbmRzIG9uIHRoZSBvdXRwdXQgc3BhY2UKICAgIG5jMiAtPkNvbG9yYW50Q291bnQgPSBjbXNQaXBlbGluZU91dHB1dENoYW5uZWxzKHYgLT5MdXQpOwoKICAgIC8vIE1ha2Ugc3VyZSB3ZSBoYXZlIHByb3BlciBmb3JtYXR0ZXJzCiAgICBjbXNDaGFuZ2VCdWZmZXJzRm9ybWF0KHhmb3JtLCBUWVBFX05BTUVEX0NPTE9SX0lOREVYLAogICAgICAgIEZMT0FUX1NIKDApIHwgQ09MT1JTUEFDRV9TSChfY21zTENNU2NvbG9yU3BhY2UodiAtPkV4aXRDb2xvclNwYWNlKSkKICAgICAgICB8IEJZVEVTX1NIKDIpIHwgQ0hBTk5FTFNfU0goY21zQ2hhbm5lbHNPZih2IC0+RXhpdENvbG9yU3BhY2UpKSk7CgogICAgLy8gQXBwbHkgdGhlIHRyYW5zZm9yIHRvIGNvbG9yYW50cy4KICAgIGZvciAoaT0wOyBpIDwgbkNvbG9yczsgaSsrKSB7CiAgICAgICAgY21zRG9UcmFuc2Zvcm0oeGZvcm0sICZpLCBuYzIgLT5MaXN0W2ldLkRldmljZUNvbG9yYW50LCAxKTsKICAgIH0KCiAgICBpZiAoIWNtc1dyaXRlVGFnKGhJQ0MsIGNtc1NpZ05hbWVkQ29sb3IyVGFnLCAodm9pZCopIG5jMikpIGdvdG8gRXJyb3I7CiAgICBjbXNGcmVlTmFtZWRDb2xvckxpc3QobmMyKTsKCiAgICByZXR1cm4gaElDQzsKCkVycm9yOgogICAgaWYgKGhJQ0MgIT0gTlVMTCkgY21zQ2xvc2VQcm9maWxlKGhJQ0MpOwogICAgcmV0dXJuIE5VTEw7Cn0KCgovLyBUaGlzIHN0cnVjdHVyZSBob2xkcyBpbmZvcm1hdGlvbiBhYm91dCB3aGljaCBNUFUgY2FuIGJlIHN0b3JlZCBvbiBhIHByb2ZpbGUgYmFzZWQgb24gdGhlIHZlcnNpb24KCnR5cGVkZWYgc3RydWN0IHsKICAgIGNtc0Jvb2wgICAgICAgICAgICAgIElzVjQ7ICAgICAgICAgICAgIC8vIElzIGEgVjQgdGFnPwogICAgY21zVGFnU2lnbmF0dXJlICAgICAgUmVxdWlyZWRUYWc7ICAgICAgLy8gU2V0IHRvIDAgZm9yIGJvdGggdHlwZXMKICAgIGNtc1RhZ1R5cGVTaWduYXR1cmUgIEx1dFR5cGU7ICAgICAgICAgIC8vIFRoZSBMVVQgdHlwZQogICAgaW50ICAgICAgICAgICAgICAgICAgblR5cGVzOyAgICAgICAgICAgLy8gTnVtYmVyIG9mIHR5cGVzICh1cCB0byA1KQogICAgY21zU3RhZ2VTaWduYXR1cmUgICAgTXBlVHlwZXNbNV07ICAgICAgLy8gNSBpcyB0aGUgbWF4aW11bSBudW1iZXIKCn0gY21zQWxsb3dlZExVVDsKCnN0YXRpYyBjb25zdCBjbXNBbGxvd2VkTFVUIEFsbG93ZWRMVVRUeXBlc1tdID0gewoKICAgIHsgRkFMU0UsIDAsICAgICAgICAgICAgICBjbXNTaWdMdXQxNlR5cGUsICAgIDQsICB7IGNtc1NpZ01hdHJpeEVsZW1UeXBlLCAgIGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUsIGNtc1NpZ0NMdXRFbGVtVHlwZSwgY21zU2lnQ3VydmVTZXRFbGVtVHlwZX19LAogICAgeyBGQUxTRSwgMCwgICAgICAgICAgICAgIGNtc1NpZ0x1dDE2VHlwZSwgICAgMywgIHsgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSwgY21zU2lnQ0x1dEVsZW1UeXBlLCBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlfX0sCiAgICB7IEZBTFNFLCAwLCAgICAgICAgICAgICAgY21zU2lnTHV0MTZUeXBlLCAgICAyLCAgeyBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlLCBjbXNTaWdDTHV0RWxlbVR5cGV9fSwKICAgIHsgVFJVRSAsIDAsICAgICAgICAgICAgICBjbXNTaWdMdXRBdG9CVHlwZSwgIDEsICB7IGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUgfX0sCiAgICB7IFRSVUUgLCBjbXNTaWdBVG9CMFRhZywgY21zU2lnTHV0QXRvQlR5cGUsICAzLCAgeyBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlLCBjbXNTaWdNYXRyaXhFbGVtVHlwZSwgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSB9IH0sCiAgICB7IFRSVUUgLCBjbXNTaWdBVG9CMFRhZywgY21zU2lnTHV0QXRvQlR5cGUsICAzLCAgeyBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlLCBjbXNTaWdDTHV0RWxlbVR5cGUsIGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUgICB9IH0sCiAgICB7IFRSVUUgLCBjbXNTaWdBVG9CMFRhZywgY21zU2lnTHV0QXRvQlR5cGUsICA1LCAgeyBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlLCBjbXNTaWdDTHV0RWxlbVR5cGUsIGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUsIGNtc1NpZ01hdHJpeEVsZW1UeXBlLCBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlIH19LAogICAgeyBUUlVFICwgY21zU2lnQlRvQTBUYWcsIGNtc1NpZ0x1dEJ0b0FUeXBlLCAgMSwgIHsgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSB9fSwKICAgIHsgVFJVRSAsIGNtc1NpZ0JUb0EwVGFnLCBjbXNTaWdMdXRCdG9BVHlwZSwgIDMsICB7IGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUsIGNtc1NpZ01hdHJpeEVsZW1UeXBlLCBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlIH19LAogICAgeyBUUlVFICwgY21zU2lnQlRvQTBUYWcsIGNtc1NpZ0x1dEJ0b0FUeXBlLCAgMywgIHsgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSwgY21zU2lnQ0x1dEVsZW1UeXBlLCBjbXNTaWdDdXJ2ZVNldEVsZW1UeXBlIH19LAogICAgeyBUUlVFICwgY21zU2lnQlRvQTBUYWcsIGNtc1NpZ0x1dEJ0b0FUeXBlLCAgNSwgIHsgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSwgY21zU2lnTWF0cml4RWxlbVR5cGUsIGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUsIGNtc1NpZ0NMdXRFbGVtVHlwZSwgY21zU2lnQ3VydmVTZXRFbGVtVHlwZSB9fQp9OwoKI2RlZmluZSBTSVpFX09GX0FMTE9XRURfTFVUIChzaXplb2YoQWxsb3dlZExVVFR5cGVzKS9zaXplb2YoY21zQWxsb3dlZExVVCkpCgovLyBDaGVjayBhIHNpbmdsZSBlbnRyeQpzdGF0aWMKY21zQm9vbCBDaGVja09uZShjb25zdCBjbXNBbGxvd2VkTFVUKiBUYWIsIGNvbnN0IGNtc1BpcGVsaW5lKiBMdXQpCnsKICAgIGNtc1N0YWdlKiBtcGU7CiAgICBpbnQgbjsKCiAgICBmb3IgKG49MCwgbXBlID0gTHV0IC0+RWxlbWVudHM7IG1wZSAhPSBOVUxMOyBtcGUgPSBtcGUgLT5OZXh0LCBuKyspIHsKCiAgICAgICAgaWYgKG4gPiBUYWIgLT5uVHlwZXMpIHJldHVybiBGQUxTRTsKICAgICAgICBpZiAoY21zU3RhZ2VUeXBlKG1wZSkgIT0gVGFiIC0+TXBlVHlwZXNbbl0pIHJldHVybiBGQUxTRTsKICAgIH0KCiAgICByZXR1cm4gKG4gPT0gVGFiIC0+blR5cGVzKTsKfQoKCnN0YXRpYwpjb25zdCBjbXNBbGxvd2VkTFVUKiBGaW5kQ29tYmluYXRpb24oY29uc3QgY21zUGlwZWxpbmUqIEx1dCwgY21zQm9vbCBJc1Y0LCBjbXNUYWdTaWduYXR1cmUgRGVzdGluYXRpb25UYWcpCnsKICAgIGNtc1VJbnQzMk51bWJlciBuOwoKICAgIGZvciAobj0wOyBuIDwgU0laRV9PRl9BTExPV0VEX0xVVDsgbisrKSB7CgogICAgICAgIGNvbnN0IGNtc0FsbG93ZWRMVVQqIFRhYiA9IEFsbG93ZWRMVVRUeXBlcyArIG47CgogICAgICAgIGlmIChJc1Y0IF4gVGFiIC0+IElzVjQpIGNvbnRpbnVlOwogICAgICAgIGlmICgoVGFiIC0+UmVxdWlyZWRUYWcgIT0gMCkgJiYgKFRhYiAtPlJlcXVpcmVkVGFnICE9IERlc3RpbmF0aW9uVGFnKSkgY29udGludWU7CgogICAgICAgIGlmIChDaGVja09uZShUYWIsIEx1dCkpIHJldHVybiBUYWI7CiAgICB9CgogICAgcmV0dXJuIE5VTEw7Cn0KCgovLyBEb2VzIGNvbnZlcnQgYSB0cmFuc2Zvcm0gaW50byBhIGRldmljZSBsaW5rIHByb2ZpbGUKY21zSFBST0ZJTEUgQ01TRVhQT1JUIGNtc1RyYW5zZm9ybTJEZXZpY2VMaW5rKGNtc0hUUkFOU0ZPUk0gaFRyYW5zZm9ybSwgY21zRmxvYXQ2NE51bWJlciBWZXJzaW9uLCBjbXNVSW50MzJOdW1iZXIgZHdGbGFncykKewogICAgY21zSFBST0ZJTEUgaFByb2ZpbGUgPSBOVUxMOwogICAgY21zVUludDMyTnVtYmVyIEZybUluLCBGcm1PdXQsIENoYW5zSW4sIENoYW5zT3V0OwogICAgY21zVUludDMyTnVtYmVyIENvbG9yU3BhY2VCaXRzSW4sIENvbG9yU3BhY2VCaXRzT3V0OwogICAgX2Ntc1RSQU5TRk9STSogeGZvcm0gPSAoX2Ntc1RSQU5TRk9STSopIGhUcmFuc2Zvcm07CiAgICBjbXNQaXBlbGluZSogTFVUID0gTlVMTDsKICAgIGNtc1N0YWdlKiBtcGU7CiAgICBjbXNDb250ZXh0IENvbnRleHRJRCA9IGNtc0dldFRyYW5zZm9ybUNvbnRleHRJRChoVHJhbnNmb3JtKTsKICAgIGNvbnN0IGNtc0FsbG93ZWRMVVQqIEFsbG93ZWRMVVQ7CiAgICBjbXNUYWdTaWduYXR1cmUgRGVzdGluYXRpb25UYWc7CiAgICBjbXNQcm9maWxlQ2xhc3NTaWduYXR1cmUgZGV2aWNlQ2xhc3M7IAoKICAgIF9jbXNBc3NlcnQoaFRyYW5zZm9ybSAhPSBOVUxMKTsKCiAgICAvLyBHZXQgdGhlIGZpcnN0IG1wZSB0byBjaGVjayBmb3IgbmFtZWQgY29sb3IKICAgIG1wZSA9IGNtc1BpcGVsaW5lR2V0UHRyVG9GaXJzdFN0YWdlKHhmb3JtIC0+THV0KTsKCiAgICAvLyBDaGVjayBpZiBpcyBhIG5hbWVkIGNvbG9yIHRyYW5zZm9ybQogICAgaWYgKG1wZSAhPSBOVUxMKSB7CgogICAgICAgIGlmIChjbXNTdGFnZVR5cGUobXBlKSA9PSBjbXNTaWdOYW1lZENvbG9yRWxlbVR5cGUpIHsKICAgICAgICAgICAgcmV0dXJuIENyZWF0ZU5hbWVkQ29sb3JEZXZpY2VsaW5rKGhUcmFuc2Zvcm0pOwogICAgICAgIH0KICAgIH0KCiAgICAvLyBGaXJzdCB0aGluZyB0byBkbyBpcyB0byBnZXQgYSBjb3B5IG9mIHRoZSB0cmFuc2Zvcm1hdGlvbgogICAgTFVUID0gY21zUGlwZWxpbmVEdXAoeGZvcm0gLT5MdXQpOwogICAgaWYgKExVVCA9PSBOVUxMKSByZXR1cm4gTlVMTDsKCiAgICAvLyBUaW1lIHRvIGZpeCB0aGUgTGFiMi9MYWI0IGlzc3VlLgogICAgaWYgKCh4Zm9ybSAtPkVudHJ5Q29sb3JTcGFjZSA9PSBjbXNTaWdMYWJEYXRhKSAmJiAoVmVyc2lvbiA8IDQuMCkpIHsKCiAgICAgICAgaWYgKCFjbXNQaXBlbGluZUluc2VydFN0YWdlKExVVCwgY21zQVRfQkVHSU4sIF9jbXNTdGFnZUFsbG9jTGFiVjJUb1Y0Y3VydmVzKENvbnRleHRJRCkpKQogICAgICAgICAgICBnb3RvIEVycm9yOwogICAgfQoKICAgIC8vIE9uIHRoZSBvdXRwdXQgc2lkZSB0b28KICAgIGlmICgoeGZvcm0gLT5FeGl0Q29sb3JTcGFjZSkgPT0gY21zU2lnTGFiRGF0YSAmJiAoVmVyc2lvbiA8IDQuMCkpIHsKCiAgICAgICAgaWYgKCFjbXNQaXBlbGluZUluc2VydFN0YWdlKExVVCwgY21zQVRfRU5ELCBfY21zU3RhZ2VBbGxvY0xhYlY0VG9WMihDb250ZXh0SUQpKSkKICAgICAgICAgICAgZ290byBFcnJvcjsKICAgIH0KCgogICAgaFByb2ZpbGUgPSBjbXNDcmVhdGVQcm9maWxlUGxhY2Vob2xkZXIoQ29udGV4dElEKTsKICAgIGlmICghaFByb2ZpbGUpIGdvdG8gRXJyb3I7ICAgICAgICAgICAgICAgICAgICAvLyBjYW4ndCBhbGxvY2F0ZQoKICAgIGNtc1NldFByb2ZpbGVWZXJzaW9uKGhQcm9maWxlLCBWZXJzaW9uKTsKCiAgICBGaXhDb2xvclNwYWNlcyhoUHJvZmlsZSwgeGZvcm0gLT4gRW50cnlDb2xvclNwYWNlLCB4Zm9ybSAtPiBFeGl0Q29sb3JTcGFjZSwgZHdGbGFncyk7CgogICAgLy8gT3B0aW1pemUgdGhlIExVVCBhbmQgcHJlY2FsY3VsYXRlIGEgZGV2aWNlbGluawoKICAgIENoYW5zSW4gID0gY21zQ2hhbm5lbHNPZih4Zm9ybSAtPiBFbnRyeUNvbG9yU3BhY2UpOwogICAgQ2hhbnNPdXQgPSBjbXNDaGFubmVsc09mKHhmb3JtIC0+IEV4aXRDb2xvclNwYWNlKTsKCiAgICBDb2xvclNwYWNlQml0c0luICA9IF9jbXNMQ01TY29sb3JTcGFjZSh4Zm9ybSAtPiBFbnRyeUNvbG9yU3BhY2UpOwogICAgQ29sb3JTcGFjZUJpdHNPdXQgPSBfY21zTENNU2NvbG9yU3BhY2UoeGZvcm0gLT4gRXhpdENvbG9yU3BhY2UpOwoKICAgIEZybUluICA9IENPTE9SU1BBQ0VfU0goQ29sb3JTcGFjZUJpdHNJbikgfCBDSEFOTkVMU19TSChDaGFuc0luKXxCWVRFU19TSCgyKTsKICAgIEZybU91dCA9IENPTE9SU1BBQ0VfU0goQ29sb3JTcGFjZUJpdHNPdXQpIHwgQ0hBTk5FTFNfU0goQ2hhbnNPdXQpfEJZVEVTX1NIKDIpOwoKICAgIGRldmljZUNsYXNzID0gY21zR2V0RGV2aWNlQ2xhc3MoaFByb2ZpbGUpOwoKICAgICBpZiAoZGV2aWNlQ2xhc3MgPT0gY21zU2lnT3V0cHV0Q2xhc3MpCiAgICAgICAgIERlc3RpbmF0aW9uVGFnID0gY21zU2lnQlRvQTBUYWc7CiAgICAgZWxzZQogICAgICAgICBEZXN0aW5hdGlvblRhZyA9IGNtc1NpZ0FUb0IwVGFnOwoKICAgIC8vIENoZWNrIGlmIHRoZSBwcm9maWxlL3ZlcnNpb24gY2FuIHN0b3JlIHRoZSByZXN1bHQKICAgIGlmIChkd0ZsYWdzICYgY21zRkxBR1NfRk9SQ0VfQ0xVVCkKICAgICAgICBBbGxvd2VkTFVUID0gTlVMTDsKICAgIGVsc2UKICAgICAgICBBbGxvd2VkTFVUID0gRmluZENvbWJpbmF0aW9uKExVVCwgVmVyc2lvbiA+PSA0LjAsIERlc3RpbmF0aW9uVGFnKTsKCiAgICBpZiAoQWxsb3dlZExVVCA9PSBOVUxMKSB7CgogICAgICAgIC8vIFRyeSB0byBvcHRpbWl6ZQogICAgICAgIF9jbXNPcHRpbWl6ZVBpcGVsaW5lKENvbnRleHRJRCwgJkxVVCwgeGZvcm0gLT5SZW5kZXJpbmdJbnRlbnQsICZGcm1JbiwgJkZybU91dCwgJmR3RmxhZ3MpOwogICAgICAgIEFsbG93ZWRMVVQgPSBGaW5kQ29tYmluYXRpb24oTFVULCBWZXJzaW9uID49IDQuMCwgRGVzdGluYXRpb25UYWcpOwoKICAgIH0KCiAgICAvLyBJZiBubyB3YXksIHRoZW4gZm9yY2UgQ0xVVCB0aGF0IGZvciBzdXJlIGNhbiBiZSB3cml0dGVuCiAgICBpZiAoQWxsb3dlZExVVCA9PSBOVUxMKSB7CgogICAgICAgIGR3RmxhZ3MgfD0gY21zRkxBR1NfRk9SQ0VfQ0xVVDsKICAgICAgICBfY21zT3B0aW1pemVQaXBlbGluZShDb250ZXh0SUQsICZMVVQsIHhmb3JtIC0+UmVuZGVyaW5nSW50ZW50LCAmRnJtSW4sICZGcm1PdXQsICZkd0ZsYWdzKTsKCiAgICAgICAgLy8gUHV0IGlkZW50aXR5IGN1cnZlcyBpZiBuZWVkZWQKICAgICAgICBpZiAoY21zUGlwZWxpbmVHZXRQdHJUb0ZpcnN0U3RhZ2UoTFVUKSAtPlR5cGUgIT0gY21zU2lnQ3VydmVTZXRFbGVtVHlwZSkKICAgICAgICAgICAgIGlmICghY21zUGlwZWxpbmVJbnNlcnRTdGFnZShMVVQsIGNtc0FUX0JFR0lOLCBfY21zU3RhZ2VBbGxvY0lkZW50aXR5Q3VydmVzKENvbnRleHRJRCwgQ2hhbnNJbikpKQogICAgICAgICAgICAgICAgIGdvdG8gRXJyb3I7CgogICAgICAgIGlmIChjbXNQaXBlbGluZUdldFB0clRvTGFzdFN0YWdlKExVVCkgLT5UeXBlICE9IGNtc1NpZ0N1cnZlU2V0RWxlbVR5cGUpCiAgICAgICAgICAgICBpZiAoIWNtc1BpcGVsaW5lSW5zZXJ0U3RhZ2UoTFVULCBjbXNBVF9FTkQsICAgX2Ntc1N0YWdlQWxsb2NJZGVudGl0eUN1cnZlcyhDb250ZXh0SUQsIENoYW5zT3V0KSkpCiAgICAgICAgICAgICAgICAgZ290byBFcnJvcjsKCiAgICAgICAgQWxsb3dlZExVVCA9IEZpbmRDb21iaW5hdGlvbihMVVQsIFZlcnNpb24gPj0gNC4wLCBEZXN0aW5hdGlvblRhZyk7CiAgICB9CgogICAgLy8gU29tZXRoaW5ncyBpcyB3cm9uZy4uLgogICAgaWYgKEFsbG93ZWRMVVQgPT0gTlVMTCkgewogICAgICAgIGdvdG8gRXJyb3I7CiAgICB9CgoKICAgIGlmIChkd0ZsYWdzICYgY21zRkxBR1NfOEJJVFNfREVWSUNFTElOSykKICAgICAgICAgICAgICAgICAgICAgY21zUGlwZWxpbmVTZXRTYXZlQXM4Yml0c0ZsYWcoTFVULCBUUlVFKTsKCiAgICAvLyBUYWcgcHJvZmlsZSB3aXRoIGluZm9ybWF0aW9uCiAgICBpZiAoIVNldFRleHRUYWdzKGhQcm9maWxlLCBMImRldmljZWxpbmsiKSkgZ290byBFcnJvcjsKCiAgICAvLyBTdG9yZSByZXN1bHQKICAgIGlmICghY21zV3JpdGVUYWcoaFByb2ZpbGUsIERlc3RpbmF0aW9uVGFnLCBMVVQpKSBnb3RvIEVycm9yOwoKCiAgICBpZiAoeGZvcm0gLT4gSW5wdXRDb2xvcmFudCAhPSBOVUxMKSB7CiAgICAgICAgICAgaWYgKCFjbXNXcml0ZVRhZyhoUHJvZmlsZSwgY21zU2lnQ29sb3JhbnRUYWJsZVRhZywgeGZvcm0tPklucHV0Q29sb3JhbnQpKSBnb3RvIEVycm9yOwogICAgfQoKICAgIGlmICh4Zm9ybSAtPiBPdXRwdXRDb2xvcmFudCAhPSBOVUxMKSB7CiAgICAgICAgICAgaWYgKCFjbXNXcml0ZVRhZyhoUHJvZmlsZSwgY21zU2lnQ29sb3JhbnRUYWJsZU91dFRhZywgeGZvcm0tPk91dHB1dENvbG9yYW50KSkgZ290byBFcnJvcjsKICAgIH0KCiAgICBpZiAoKGRldmljZUNsYXNzID09IGNtc1NpZ0xpbmtDbGFzcykgJiYgKHhmb3JtIC0+U2VxdWVuY2UgIT0gTlVMTCkpIHsKICAgICAgICBpZiAoIV9jbXNXcml0ZVByb2ZpbGVTZXF1ZW5jZShoUHJvZmlsZSwgeGZvcm0gLT5TZXF1ZW5jZSkpIGdvdG8gRXJyb3I7CiAgICB9CgogICAgLy8gU2V0IHRoZSB3aGl0ZSBwb2ludAogICAgaWYgKGRldmljZUNsYXNzID09IGNtc1NpZ0lucHV0Q2xhc3MpIHsKICAgICAgICBpZiAoIWNtc1dyaXRlVGFnKGhQcm9maWxlLCBjbXNTaWdNZWRpYVdoaXRlUG9pbnRUYWcsICZ4Zm9ybSAtPkVudHJ5V2hpdGVQb2ludCkpIGdvdG8gRXJyb3I7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICAgaWYgKCFjbXNXcml0ZVRhZyhoUHJvZmlsZSwgY21zU2lnTWVkaWFXaGl0ZVBvaW50VGFnLCAmeGZvcm0gLT5FeGl0V2hpdGVQb2ludCkpIGdvdG8gRXJyb3I7CiAgICB9CgogIAogICAgLy8gUGVyIDcuMi4xNSBpbiBzcGVjIDQuMwogICAgY21zU2V0SGVhZGVyUmVuZGVyaW5nSW50ZW50KGhQcm9maWxlLCB4Zm9ybSAtPlJlbmRlcmluZ0ludGVudCk7CgogICAgY21zUGlwZWxpbmVGcmVlKExVVCk7CiAgICByZXR1cm4gaFByb2ZpbGU7CgpFcnJvcjoKICAgIGlmIChMVVQgIT0gTlVMTCkgY21zUGlwZWxpbmVGcmVlKExVVCk7CiAgICBjbXNDbG9zZVByb2ZpbGUoaFByb2ZpbGUpOwogICAgcmV0dXJuIE5VTEw7Cn0K