LyoKICogQ29weXJpZ2h0IChDKSAyMDA2LTIwMDcgU3RlZmFuIET2c2luZ2VyKEZvciBDb2RlV2VhdmVycykKICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgMDIxMTAtMTMwMSwgVVNBCiAqLwoKI2RlZmluZSBDT0JKTUFDUk9TCiNpbmNsdWRlIDxkM2Q5Lmg+CiNpbmNsdWRlIDxkeGVycjkuaD4KI2luY2x1ZGUgIndpbmUvdGVzdC5oIgoKc3RhdGljIElEaXJlY3QzRDkgKihXSU5BUEkgKnBEaXJlY3QzRENyZWF0ZTkpKFVJTlQpOwoKc3RydWN0IHF1ZXJ5SW5mbwp7CiAgICBEM0RRVUVSWVRZUEUgdHlwZTsgICAgICAvKiBRdWVyeSB0byB0ZXN0ICovCiAgICBCT09MIGZvdW5kU3VwcG9ydGVkOyAgICAvKiBJZiBhdCBsZWFzdCBvbmUgd2luZG93cyBkcml2ZXIgaGFzIGJlZW4gZm91bmQgc3VwcG9ydGluZyB0aGlzIHF1ZXJ5ICovCiAgICBCT09MIGZvdW5kVW5zdXBwb3J0ZWQ7ICAvKiBJZiBhdCBsZWFzdCBvbmUgd2luZG93cyBkcml2ZXIgaGFzIGJlZW4gZm91bmQgd2hpY2ggZG9lcyBub3Qgc3VwcG9ydCB0aGlzIHF1ZXJ5ICovCn07CgovKiBXaGVuIHJ1bm5pbmcgcnVubmluZyB0aGlzIHRlc3Qgb24gd2luZG93cyByZXZlYWxzIGFueSBkaWZmZXJlbmNlcyByZWdhcmRpbmcga25vd24gc3VwcG9ydGVkIC8gdW5zdXBwb3J0ZWQgcXVlcmllcywKICogY2hhbmdlIHRoaXMgdGFibGUuCiAqCiAqIFdoZW4gbWFya2luZyBhIHF1ZXJ5IGtub3duIHN1cHBvcnRlZCBvciBrbm93biB1bnN1cHBvcnRlZCBwbGVhc2Ugd3JpdGUgb25lIGNhcmQgd2hpY2ggc3VwcG9ydHMgLyBkb2VzIG5vdCBzdXBwb3J0CiAqIHRoZSBxdWVyeS4KICovCnN0YXRpYyBzdHJ1Y3QgcXVlcnlJbmZvIHF1ZXJpZXNbXSA9CnsKICAgIHtEM0RRVUVSWVRZUEVfVkNBQ0hFLCAgICAgICAgICAgICAgIFRSVUUgLyogZ2Vmb3JjZSA2NjAwICovLCAgICBUUlVFIC8qIGdlZm9yY2UgMiBteCAqLyB9LAogICAge0QzRFFVRVJZVFlQRV9SRVNPVVJDRU1BTkFHRVIsICAgICAgRkFMU0UsICAgICAgICAgICAgICAgICAgICAgIFRSVUUgLyogZ2Vmb3JjZSAyIG14ICovIH0sCiAgICB7RDNEUVVFUllUWVBFX1ZFUlRFWFNUQVRTLCAgICAgICAgICBGQUxTRSwgICAgICAgICAgICAgICAgICAgICAgVFJVRSAvKiBnZWZvcmNlIDIgbXggKi8gfSwKICAgIHtEM0RRVUVSWVRZUEVfRVZFTlQsICAgICAgICAgICAgICAgIFRSVUUgLyogZ2Vmb3JjZSAyIG14ICovLCAgICBUUlVFIC8qIGF0aSBtYWNoNjQgKi8gICB9LAogICAge0QzRFFVRVJZVFlQRV9PQ0NMVVNJT04sICAgICAgICAgICAgVFJVRSAvKiByYWRlb24gTTkgKi8sICAgICAgIFRSVUUgLyogZ2Vmb3JjZSAyIG14ICovIH0sCiAgICB7RDNEUVVFUllUWVBFX1RJTUVTVEFNUCwgICAgICAgICAgICBUUlVFIC8qIGdlZm9yY2UgNjYwMCAqLywgICAgVFJVRSAvKiBnZWZvcmNlIDIgbXggKi8gfSwKICAgIHtEM0RRVUVSWVRZUEVfVElNRVNUQU1QRElTSk9JTlQsICAgIFRSVUUgLyogZ2Vmb3JjZSA2NjAwICovLCAgICBUUlVFIC8qIGdlZm9yY2UgMiBteCAqLyB9LAogICAge0QzRFFVRVJZVFlQRV9USU1FU1RBTVBGUkVRLCAgICAgICAgVFJVRSAvKiBnZWZvcmNlIDY2MDAgKi8sICAgIFRSVUUgLyogZ2Vmb3JjZSAyIG14ICovIH0sCiAgICB7RDNEUVVFUllUWVBFX1BJUEVMSU5FVElNSU5HUywgICAgICBGQUxTRSwgICAgICAgICAgICAgICAgICAgICAgVFJVRSAvKiBnZWZvcmNlIDIgbXggKi8gfSwKICAgIHtEM0RRVUVSWVRZUEVfSU5URVJGQUNFVElNSU5HUywgICAgIEZBTFNFLCAgICAgICAgICAgICAgICAgICAgICBUUlVFIC8qIGdlZm9yY2UgMiBteCAqLyB9LAogICAge0QzRFFVRVJZVFlQRV9WRVJURVhUSU1JTkdTLCAgICAgICAgRkFMU0UsICAgICAgICAgICAgICAgICAgICAgIFRSVUUgLyogZ2Vmb3JjZSAyIG14ICovIH0sCiAgICB7RDNEUVVFUllUWVBFX1BJWEVMVElNSU5HUywgICAgICAgICBGQUxTRSwgICAgICAgICAgICAgICAgICAgICAgVFJVRSAvKiBnZWZvcmNlIDIgbXggKi8gfSwKICAgIHtEM0RRVUVSWVRZUEVfQkFORFdJRFRIVElNSU5HUywgICAgIEZBTFNFLCAgICAgICAgICAgICAgICAgICAgICBUUlVFIC8qIGdlZm9yY2UgMiBteCAqLyB9LAogICAge0QzRFFVRVJZVFlQRV9DQUNIRVVUSUxJWkFUSU9OLCAgICAgRkFMU0UsICAgICAgICAgICAgICAgICAgICAgIFRSVUUgLyogZ2Vmb3JjZSAyIG14ICovIH0sCn07CgpzdGF0aWMgY29uc3QgY2hhciAqcXVlcnlOYW1lKEQzRFFVRVJZVFlQRSB0eXBlKQp7CiAgICBzd2l0Y2godHlwZSkKICAgIHsKICAgICAgICBjYXNlIEQzRFFVRVJZVFlQRV9WQ0FDSEU6ICAgICAgICAgICAgICAgcmV0dXJuICJEM0RRVUVSWVRZUEVfVkNBQ0hFIjsKICAgICAgICBjYXNlIEQzRFFVRVJZVFlQRV9SRVNPVVJDRU1BTkFHRVI6ICAgICAgcmV0dXJuICJEM0RRVUVSWVRZUEVfUkVTT1VSQ0VNQU5BR0VSIjsKICAgICAgICBjYXNlIEQzRFFVRVJZVFlQRV9WRVJURVhTVEFUUzogICAgICAgICAgcmV0dXJuICJEM0RRVUVSWVRZUEVfVkVSVEVYU1RBVFMiOwogICAgICAgIGNhc2UgRDNEUVVFUllUWVBFX0VWRU5UOiAgICAgICAgICAgICAgICByZXR1cm4gIkQzRFFVRVJZVFlQRV9FVkVOVCI7CiAgICAgICAgY2FzZSBEM0RRVUVSWVRZUEVfT0NDTFVTSU9OOiAgICAgICAgICAgIHJldHVybiAiRDNEUVVFUllUWVBFX09DQ0xVU0lPTiI7CiAgICAgICAgY2FzZSBEM0RRVUVSWVRZUEVfVElNRVNUQU1QOiAgICAgICAgICAgIHJldHVybiAiRDNEUVVFUllUWVBFX1RJTUVTVEFNUCI7CiAgICAgICAgY2FzZSBEM0RRVUVSWVRZUEVfVElNRVNUQU1QRElTSk9JTlQ6ICAgIHJldHVybiAiRDNEUVVFUllUWVBFX1RJTUVTVEFNUERJU0pPSU5UIjsKICAgICAgICBjYXNlIEQzRFFVRVJZVFlQRV9USU1FU1RBTVBGUkVROiAgICAgICAgcmV0dXJuICJEM0RRVUVSWVRZUEVfVElNRVNUQU1QRlJFUSI7CiAgICAgICAgY2FzZSBEM0RRVUVSWVRZUEVfUElQRUxJTkVUSU1JTkdTOiAgICAgIHJldHVybiAiRDNEUVVFUllUWVBFX1BJUEVMSU5FVElNSU5HUyI7CiAgICAgICAgY2FzZSBEM0RRVUVSWVRZUEVfSU5URVJGQUNFVElNSU5HUzogICAgIHJldHVybiAiRDNEUVVFUllUWVBFX0lOVEVSRkFDRVRJTUlOR1MiOwogICAgICAgIGNhc2UgRDNEUVVFUllUWVBFX1ZFUlRFWFRJTUlOR1M6ICAgICAgICByZXR1cm4gIkQzRFFVRVJZVFlQRV9WRVJURVhUSU1JTkdTIjsKICAgICAgICBjYXNlIEQzRFFVRVJZVFlQRV9QSVhFTFRJTUlOR1M6ICAgICAgICAgcmV0dXJuICJEM0RRVUVSWVRZUEVfUElYRUxUSU1JTkdTIjsKICAgICAgICBjYXNlIEQzRFFVRVJZVFlQRV9CQU5EV0lEVEhUSU1JTkdTOiAgICAgcmV0dXJuICJEM0RRVUVSWVRZUEVfQkFORFdJRFRIVElNSU5HUyI7CiAgICAgICAgY2FzZSBEM0RRVUVSWVRZUEVfQ0FDSEVVVElMSVpBVElPTjogICAgIHJldHVybiAiRDNEUVVFUllUWVBFX0NBQ0hFVVRJTElaQVRJT04iOwogICAgICAgIGRlZmF1bHQ6IHJldHVybiAiVW5leHBlY3RlZCBxdWVyeSB0eXBlIjsKICAgIH0KfQoKc3RhdGljIHZvaWQgdGVzdF9xdWVyeV9zdXBwb3J0KElEaXJlY3QzRDkgKnBEM2QsIEhXTkQgaHduZCkKewoKICAgIEhSRVNVTFQgICAgICAgICAgICAgICBocjsKCiAgICBJRGlyZWN0M0REZXZpY2U5ICAgICAgKnBEZXZpY2UgPSBOVUxMOwogICAgRDNEUFJFU0VOVF9QQVJBTUVURVJTIGQzZHBwOwogICAgRDNERElTUExBWU1PREUgICAgICAgIGQzZGRtOwogICAgaW50ICAgICAgICAgICAgICAgICAgIGk7CiAgICBJRGlyZWN0M0RRdWVyeTkgICAgICAgKnBRdWVyeSA9IE5VTEw7CiAgICBCT09MIHN1cHBvcnRlZDsKCiAgICBJRGlyZWN0M0Q5X0dldEFkYXB0ZXJEaXNwbGF5TW9kZSggcEQzZCwgRDNEQURBUFRFUl9ERUZBVUxULCAmZDNkZG0gKTsKICAgIFplcm9NZW1vcnkoICZkM2RwcCwgc2l6ZW9mKGQzZHBwKSApOwogICAgZDNkcHAuV2luZG93ZWQgICAgICAgICA9IFRSVUU7CiAgICBkM2RwcC5Td2FwRWZmZWN0ICAgICAgID0gRDNEU1dBUEVGRkVDVF9ESVNDQVJEOwogICAgZDNkcHAuQmFja0J1ZmZlckZvcm1hdCA9IGQzZGRtLkZvcm1hdDsKCiAgICBociA9IElEaXJlY3QzRDlfQ3JlYXRlRGV2aWNlKCBwRDNkLCBEM0RBREFQVEVSX0RFRkFVTFQsIEQzRERFVlRZUEVfSEFMLCBod25kLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRDNEQ1JFQVRFX1NPRlRXQVJFX1ZFUlRFWFBST0NFU1NJTkcsICZkM2RwcCwgJnBEZXZpY2UgKTsKICAgIG9rKFNVQ0NFRURFRChociksICJGYWlsZWQgdG8gY3JlYXRlIElEaXJlY3QzRDlEZXZpY2UgKCVzKVxuIiwgRFhHZXRFcnJvclN0cmluZzkoaHIpKTsKICAgIGlmIChGQUlMRUQoaHIpKSBnb3RvIGNsZWFudXA7CgogICAgZm9yKGkgPSAwOyBpIDwgc2l6ZW9mKHF1ZXJpZXMpIC8gc2l6ZW9mKHF1ZXJpZXNbMF0pOyBpKyspCiAgICB7CiAgICAgICAgaHIgPSBJRGlyZWN0M0REZXZpY2U5X0NyZWF0ZVF1ZXJ5KHBEZXZpY2UsIHF1ZXJpZXNbaV0udHlwZSwgTlVMTCk7CiAgICAgICAgb2soaHIgPT0gRDNEX09LIHx8IEQzREVSUl9OT1RBVkFJTEFCTEUsCiAgICAgICAgICAgIklEaXJlY3QzRERldmljZTlfQ3JlYXRlUXVlcnkgcmV0dXJuZWQgdW5leHBlY3RlZCByZXR1cm4gdmFsdWUgJXMgZm9yIHF1ZXJ5ICVzXG4iLCBEWEdldEVycm9yU3RyaW5nOShociksIHF1ZXJ5TmFtZShxdWVyaWVzW2ldLnR5cGUpKTsKCiAgICAgICAgc3VwcG9ydGVkID0gKGhyID09IEQzRF9PSyA/IFRSVUUgOiBGQUxTRSk7CiAgICAgICAgdHJhY2UoInF1ZXJ5ICVzIGlzICVzXG4iLCBxdWVyeU5hbWUocXVlcmllc1tpXS50eXBlKSwgc3VwcG9ydGVkID8gInN1cHBvcnRlZCIgOiAibm90IHN1cHBvcnRlZCIpOwoKICAgICAgICBvayghKHN1cHBvcnRlZCA9PSBUUlVFICYmIHF1ZXJpZXNbaV0uZm91bmRTdXBwb3J0ZWQgPT0gRkFMU0UpLAogICAgICAgICAgICAiUXVlcnkgJXMgaXMgc3VwcG9ydGVkIG9uIHRoaXMgc3lzdGVtLCBidXQgd2FzIG5vdCBmb3VuZCBzdXBwb3J0ZWQgYmVmb3JlXG4iLAogICAgICAgICAgICBxdWVyeU5hbWUocXVlcmllc1tpXS50eXBlKSk7CiAgICAgICAgb2soIShzdXBwb3J0ZWQgPT0gRkFMU0UgJiYgcXVlcmllc1tpXS5mb3VuZFVuc3VwcG9ydGVkID09IEZBTFNFKSwKICAgICAgICAgICAgIlF1ZXJ5ICVzIGlzIG5vdCBzdXBwb3J0ZWQgb24gdGhpcyBzeXN0ZW0sIGJ1dCB3YXMgZm91bmQgdG8gYmUgc3VwcG9ydGVkIG9uIGFsbCBvdGhlciBzeXN0ZW1zIHRlc3RlZCBiZWZvcmVcbiIsCiAgICAgICAgICAgIHF1ZXJ5TmFtZShxdWVyaWVzW2ldLnR5cGUpKTsKCiAgICAgICAgaHIgPSBJRGlyZWN0M0REZXZpY2U5X0NyZWF0ZVF1ZXJ5KHBEZXZpY2UsIHF1ZXJpZXNbaV0udHlwZSwgJnBRdWVyeSk7CiAgICAgICAgb2soaHIgPT0gRDNEX09LIHx8IEQzREVSUl9OT1RBVkFJTEFCTEUsCiAgICAgICAgICAgIklEaXJlY3QzRERldmljZTlfQ3JlYXRlUXVlcnkgcmV0dXJuZWQgdW5leHBlY3RlZCByZXR1cm4gdmFsdWUgJXMgZm9yIHF1ZXJ5ICVzXG4iLCBEWEdldEVycm9yU3RyaW5nOShociksIHF1ZXJ5TmFtZShxdWVyaWVzW2ldLnR5cGUpKTsKICAgICAgICBvayghKHN1cHBvcnRlZCAmJiAhcFF1ZXJ5KSwgIlF1ZXJ5ICVzIHdhcyBjbGFpbWVkIHRvIGJlIHN1cHBvcnRlZCwgYnV0IGNhbid0IGJlIGNyZWF0ZWRcbiIsIHF1ZXJ5TmFtZShxdWVyaWVzW2ldLnR5cGUpKTsKICAgICAgICBvayghKCFzdXBwb3J0ZWQgJiYgcFF1ZXJ5KSwgIlF1ZXJ5ICVzIHdhcyBjbGFpbWVkIG5vdCB0byBiZSBzdXBwb3J0ZWQsIGJ1dCBjYW4gYmUgY3JlYXRlZFxuIiwgcXVlcnlOYW1lKHF1ZXJpZXNbaV0udHlwZSkpOwogICAgICAgIGlmKHBRdWVyeSkKICAgICAgICB7CiAgICAgICAgICAgIElEaXJlY3QzRFF1ZXJ5OV9SZWxlYXNlKHBRdWVyeSk7CiAgICAgICAgICAgIHBRdWVyeSA9IE5VTEw7CiAgICAgICAgfQogICAgfQoKICAgIGNsZWFudXA6CiAgICBpZihwRGV2aWNlKSBJRGlyZWN0M0REZXZpY2U5X1JlbGVhc2UocERldmljZSk7Cn0KClNUQVJUX1RFU1QocXVlcnkpCnsKICAgIEhNT0RVTEUgZDNkOV9oYW5kbGUgPSBMb2FkTGlicmFyeUEoICJkM2Q5LmRsbCIgKTsKICAgIGlmICghZDNkOV9oYW5kbGUpCiAgICB7CiAgICAgICAgc2tpcCgiQ291bGQgbm90IGxvYWQgZDNkOS5kbGxcbiIpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBwRGlyZWN0M0RDcmVhdGU5ID0gKHZvaWQgKilHZXRQcm9jQWRkcmVzcyggZDNkOV9oYW5kbGUsICJEaXJlY3QzRENyZWF0ZTkiICk7CiAgICBvayhwRGlyZWN0M0RDcmVhdGU5ICE9IE5VTEwsICJGYWlsZWQgdG8gZ2V0IGFkZHJlc3Mgb2YgRGlyZWN0M0RDcmVhdGU5XG4iKTsKICAgIGlmIChwRGlyZWN0M0RDcmVhdGU5KQogICAgewogICAgICAgIElEaXJlY3QzRDkgICAgICAgICAgICAqcEQzZCA9IE5VTEw7CiAgICAgICAgSFdORCAgICAgICAgICAgICAgICAgIGh3bmQgPSBOVUxMOwoKICAgICAgICBwRDNkID0gcERpcmVjdDNEQ3JlYXRlOSggRDNEX1NES19WRVJTSU9OICk7CiAgICAgICAgaWYoIXBEM2QpCiAgICAgICAgewogICAgICAgICAgICBza2lwKCJGYWlsZWQgdG8gY3JlYXRlIERpcmVjdDNEOSBvYmplY3QsIG5vdCBydW5uaW5nIHRlc3RzXG4iKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBod25kID0gQ3JlYXRlV2luZG93KCAic3RhdGljIiwgImQzZDlfdGVzdCIsIFdTX09WRVJMQVBQRURXSU5ET1csIDEwMCwgMTAwLCAxNjAsIDE2MCwgTlVMTCwgTlVMTCwgTlVMTCwgTlVMTCApOwogICAgICAgIGlmKCFod25kKQogICAgICAgIHsKICAgICAgICAgICAgc2tpcCgiRmFpbGVkIHRvIGNyZWF0ZSB3aW5kb3dcbiIpOwogICAgICAgICAgICBJRGlyZWN0M0Q5X1JlbGVhc2UocEQzZCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHRlc3RfcXVlcnlfc3VwcG9ydChwRDNkLCBod25kKTsKCiAgICAgICAgRGVzdHJveVdpbmRvdyhod25kKTsKICAgICAgICBJRGlyZWN0M0Q5X1JlbGVhc2UocEQzZCk7CiAgICB9Cn0K