LyoJCURpcmVjdERyYXcgLSBJRGlyZWN0UGFsZXR0ZSBiYXNlIGludGVyZmFjZQogKgogKiBDb3B5cmlnaHQgMTk5Ny0yMDAwIE1hcmN1cyBNZWlzc25lcgogKiBDb3B5cmlnaHQgMjAwMC0yMDAxIFRyYW5zR2FtaW5nIFRlY2hub2xvZ2llcyBJbmMuCiAqIENvcHlyaWdodCAyMDA2IFN0ZWZhbiBE9nNpbmdlciBmb3IgQ29kZVdlYXZlcnMKICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgMDIxMTAtMTMwMSwgVVNBCiAqLwojaW5jbHVkZSAiY29uZmlnLmgiCiNpbmNsdWRlICJ3aW5lcnJvci5oIgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgoKI2luY2x1ZGUgPGFzc2VydC5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CgojaW5jbHVkZSAid2luZWQzZF9wcml2YXRlLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChkM2QpOwoKI2RlZmluZSBTSVpFX0JJVFMgKFdJTkVERFBDQVBTXzFCSVQgfCBXSU5FRERQQ0FQU18yQklUIHwgV0lORUREUENBUFNfNEJJVCB8IFdJTkVERFBDQVBTXzhCSVQpCgpzdGF0aWMgSFJFU1VMVCAgV0lOQVBJIElXaW5lRDNEUGFsZXR0ZUltcGxfUXVlcnlJbnRlcmZhY2UoSVdpbmVEM0RQYWxldHRlICppZmFjZSwgUkVGSUlEIHJlZmlpZCwgdm9pZCAqKm9iaikgewogICAgSVdpbmVEM0RQYWxldHRlSW1wbCAqVGhpcyA9IChJV2luZUQzRFBhbGV0dGVJbXBsICopaWZhY2U7CiAgICBUUkFDRSgiKCVwKS0+KCVzLCVwKVxuIixUaGlzLGRlYnVnc3RyX2d1aWQocmVmaWlkKSxvYmopOwoKICAgIGlmIChJc0VxdWFsR1VJRChyZWZpaWQsICZJSURfSVVua25vd24pCiAgICAgICAgfHwgSXNFcXVhbEdVSUQocmVmaWlkLCAmSUlEX0lXaW5lRDNEUGFsZXR0ZSkpIHsKICAgICAgICAqb2JqID0gaWZhY2U7CiAgICAgICAgSVdpbmVEM0RQYWxldHRlX0FkZFJlZihpZmFjZSk7CiAgICAgICAgcmV0dXJuIFNfT0s7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICAqb2JqID0gTlVMTDsKICAgICAgICByZXR1cm4gRV9OT0lOVEVSRkFDRTsKICAgIH0KfQoKc3RhdGljIFVMT05HICBXSU5BUEkgSVdpbmVEM0RQYWxldHRlSW1wbF9BZGRSZWYoSVdpbmVEM0RQYWxldHRlICppZmFjZSkgewogICAgSVdpbmVEM0RQYWxldHRlSW1wbCAqVGhpcyA9IChJV2luZUQzRFBhbGV0dGVJbXBsICopaWZhY2U7CiAgICBVTE9ORyByZWYgPSBJbnRlcmxvY2tlZEluY3JlbWVudCgmVGhpcy0+cmVmKTsKCiAgICBUUkFDRSgiKCVwKS0+KCkgaW5jcmVtZW50aW5nIGZyb20gJXUuXG4iLCBUaGlzLCByZWYgLSAxKTsKCiAgICByZXR1cm4gcmVmOwp9CgpzdGF0aWMgVUxPTkcgIFdJTkFQSSBJV2luZUQzRFBhbGV0dGVJbXBsX1JlbGVhc2UoSVdpbmVEM0RQYWxldHRlICppZmFjZSkgewogICAgSVdpbmVEM0RQYWxldHRlSW1wbCAqVGhpcyA9IChJV2luZUQzRFBhbGV0dGVJbXBsICopaWZhY2U7CiAgICBVTE9ORyByZWYgPSBJbnRlcmxvY2tlZERlY3JlbWVudCgmVGhpcy0+cmVmKTsKCiAgICBUUkFDRSgiKCVwKS0+KCkgZGVjcmVtZW50aW5nIGZyb20gJXUuXG4iLCBUaGlzLCByZWYgKyAxKTsKCiAgICBpZiAoIXJlZikgewogICAgICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIFRoaXMpOwogICAgICAgIHJldHVybiAwOwogICAgfQoKICAgIHJldHVybiByZWY7Cn0KCi8qIE5vdCBjYWxsZWQgZnJvbSB0aGUgdnRhYmxlICovCkRXT1JEIElXaW5lRDNEUGFsZXR0ZUltcGxfU2l6ZShEV09SRCBkd0ZsYWdzKSB7CiAgICBzd2l0Y2ggKGR3RmxhZ3MgJiBTSVpFX0JJVFMpIHsKICAgICAgICBjYXNlIFdJTkVERFBDQVBTXzFCSVQ6IHJldHVybiAyOwogICAgICAgIGNhc2UgV0lORUREUENBUFNfMkJJVDogcmV0dXJuIDQ7CiAgICAgICAgY2FzZSBXSU5FRERQQ0FQU180QklUOiByZXR1cm4gMTY7CiAgICAgICAgY2FzZSBXSU5FRERQQ0FQU184QklUOiByZXR1cm4gMjU2OwogICAgICAgIGRlZmF1bHQ6IGFzc2VydCgwKTsgcmV0dXJuIDI1NjsKICAgIH0KfQoKc3RhdGljIEhSRVNVTFQgIFdJTkFQSSBJV2luZUQzRFBhbGV0dGVJbXBsX0dldEVudHJpZXMoSVdpbmVEM0RQYWxldHRlICppZmFjZSwgRFdPUkQgRmxhZ3MsIERXT1JEIFN0YXJ0LCBEV09SRCBDb3VudCwgUEFMRVRURUVOVFJZICpQYWxFbnQpIHsKICAgIElXaW5lRDNEUGFsZXR0ZUltcGwgKlRoaXMgPSAoSVdpbmVEM0RQYWxldHRlSW1wbCAqKWlmYWNlOwoKICAgIFRSQUNFKCIoJXApLT4oJTA4eCwlZCwlZCwlcClcbiIsVGhpcyxGbGFncyxTdGFydCxDb3VudCxQYWxFbnQpOwoKICAgIGlmIChGbGFncyAhPSAwKSByZXR1cm4gV0lORUQzREVSUl9JTlZBTElEQ0FMTDsgLyogdW5jaGVja2VkICovCiAgICBpZiAoU3RhcnQgKyBDb3VudCA+IElXaW5lRDNEUGFsZXR0ZUltcGxfU2l6ZShUaGlzLT5GbGFncykpCiAgICAgICAgcmV0dXJuIFdJTkVEM0RFUlJfSU5WQUxJRENBTEw7CgogICAgaWYgKFRoaXMtPkZsYWdzICYgV0lORUREUENBUFNfOEJJVEVOVFJJRVMpCiAgICB7CiAgICAgICAgdW5zaWduZWQgaW50IGk7CiAgICAgICAgTFBCWVRFIGVudHJ5ID0gKExQQllURSlQYWxFbnQ7CgogICAgICAgIGZvciAoaT1TdGFydDsgaSA8IENvdW50K1N0YXJ0OyBpKyspCiAgICAgICAgICAgICplbnRyeSsrID0gVGhpcy0+cGFsZW50c1tpXS5wZVJlZDsKICAgIH0KICAgIGVsc2UKICAgICAgICBtZW1jcHkoUGFsRW50LCBUaGlzLT5wYWxlbnRzK1N0YXJ0LCBDb3VudCAqIHNpemVvZihQQUxFVFRFRU5UUlkpKTsKCiAgICByZXR1cm4gV0lORUQzRF9PSzsKfQoKc3RhdGljIEhSRVNVTFQgIFdJTkFQSSBJV2luZUQzRFBhbGV0dGVJbXBsX1NldEVudHJpZXMoSVdpbmVEM0RQYWxldHRlICppZmFjZSwgRFdPUkQgRmxhZ3MsIERXT1JEIFN0YXJ0LCBEV09SRCBDb3VudCwgUEFMRVRURUVOVFJZICpQYWxFbnQpCnsKICAgIElXaW5lRDNEUGFsZXR0ZUltcGwgKlRoaXMgPSAoSVdpbmVEM0RQYWxldHRlSW1wbCAqKWlmYWNlOwogICAgSVdpbmVEM0RSZXNvdXJjZUltcGwgKnJlczsKCiAgICBUUkFDRSgiKCVwKS0+KCUwOHgsJWQsJWQsJXApXG4iLFRoaXMsRmxhZ3MsU3RhcnQsQ291bnQsUGFsRW50KTsKCiAgICBpZiAoVGhpcy0+RmxhZ3MgJiBXSU5FRERQQ0FQU184QklURU5UUklFUykgewogICAgICAgIHVuc2lnbmVkIGludCBpOwogICAgICAgIGNvbnN0IEJZVEUqIGVudHJ5ID0gKGNvbnN0IEJZVEUqKVBhbEVudDsKCiAgICAgICAgZm9yIChpPVN0YXJ0OyBpIDwgQ291bnQrU3RhcnQ7IGkrKykKICAgICAgICAgICAgVGhpcy0+cGFsZW50c1tpXS5wZVJlZCA9ICplbnRyeSsrOwogICAgfQogICAgZWxzZSB7CiAgICAgICAgbWVtY3B5KFRoaXMtPnBhbGVudHMrU3RhcnQsIFBhbEVudCwgQ291bnQgKiBzaXplb2YoUEFMRVRURUVOVFJZKSk7CgogICAgICAgIGlmIChUaGlzLT5ocGFsKQogICAgICAgICAgICBTZXRQYWxldHRlRW50cmllcyhUaGlzLT5ocGFsLCBTdGFydCwgQ291bnQsIFRoaXMtPnBhbGVudHMrU3RhcnQpOwogICAgfQoKI2lmIDAKICAgIC8qIE5vdywgaWYgd2UgYXJlIGluICdkZXB0aCBjb252ZXJzaW9uIG1vZGUnLCB1cGRhdGUgdGhlIHNjcmVlbiBwYWxldHRlICovCiAgICAvKiBGSVhNRTogd2UgbmVlZCB0byB1cGRhdGUgdGhlIGltYWdlIG9yIHdlIHdvbid0IGdldCBwYWxldHRlIGZhZGluZy4gKi8KICAgIGlmIChUaGlzLT5kZHJhdy0+ZC0+cGFsZXR0ZV9jb252ZXJ0ICE9IE5VTEwpCiAgICAgICAgVGhpcy0+ZGRyYXctPmQtPnBhbGV0dGVfY29udmVydChwYWxlbnQsVGhpcy0+c2NyZWVuX3BhbGVudHMsc3RhcnQsY291bnQpOwojZW5kaWYKCiAgICAvKiBJZiB0aGUgcGFsZXR0ZSBpcyBhdHRhY2hlZCB0byB0aGUgcmVuZGVyIHRhcmdldCwgdXBkYXRlIGFsbCByZW5kZXIgdGFyZ2V0cyAqLwoKICAgIExJU1RfRk9SX0VBQ0hfRU5UUlkocmVzLCAmVGhpcy0+d2luZUQzRERldmljZS0+cmVzb3VyY2VzLCBJV2luZUQzRFJlc291cmNlSW1wbCwgcmVzb3VyY2UucmVzb3VyY2VfbGlzdF9lbnRyeSkgewogICAgICAgIGlmKElXaW5lRDNEUmVzb3VyY2VfR2V0VHlwZSgoSVdpbmVEM0RSZXNvdXJjZSAqKSByZXMpID09IFdJTkVEM0RSVFlQRV9TVVJGQUNFKSB7CiAgICAgICAgICAgIElXaW5lRDNEU3VyZmFjZUltcGwgKmltcGwgPSAoSVdpbmVEM0RTdXJmYWNlSW1wbCAqKSByZXM7CiAgICAgICAgICAgIGlmKGltcGwtPnBhbGV0dGUgPT0gVGhpcykKICAgICAgICAgICAgICAgIElXaW5lRDNEU3VyZmFjZV9SZWFsaXplUGFsZXR0ZSgoSVdpbmVEM0RTdXJmYWNlICopIHJlcyk7CiAgICAgICAgfQogICAgfQoKICAgIC8qIElmIHRoZSBwYWxldHRlIGlzIHRoZSBwcmltYXJ5IHBhbGV0dGUsIHNldCB0aGUgZW50cmllcyB0byB0aGUgZGV2aWNlICovCiAgICBpZihUaGlzLT5GbGFncyAmIFdJTkVERFBDQVBTX1BSSU1BUllTVVJGQUNFKSB7CiAgICAgICAgdW5zaWduZWQgaW50IGk7CiAgICAgICAgSVdpbmVEM0REZXZpY2VJbXBsICpkZXZpY2UgPSBUaGlzLT53aW5lRDNERGV2aWNlOwogICAgICAgIFBBTEVUVEVFTlRSWSAqZW50cnkgPSBQYWxFbnQ7CgogICAgICAgIGZvcihpID0gU3RhcnQ7IGkgPCBTdGFydCtDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGRldmljZS0+cGFsZXR0ZXNbZGV2aWNlLT5jdXJyZW50UGFsZXR0ZV1baV0gPSAqZW50cnkrKzsKICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIFdJTkVEM0RfT0s7Cn0KCnN0YXRpYyBIUkVTVUxUICBXSU5BUEkgSVdpbmVEM0RQYWxldHRlSW1wbF9HZXRDYXBzKElXaW5lRDNEUGFsZXR0ZSAqaWZhY2UsIERXT1JEICpDYXBzKSB7CiAgICBJV2luZUQzRFBhbGV0dGVJbXBsICpUaGlzID0gKElXaW5lRDNEUGFsZXR0ZUltcGwgKilpZmFjZTsKICAgIFRSQUNFKCIoJXApLT4oJXApXG4iLCBUaGlzLCBDYXBzKTsKCiAgICAqQ2FwcyA9IFRoaXMtPkZsYWdzOwogICAgcmV0dXJuIFdJTkVEM0RfT0s7Cn0KCnN0YXRpYyBIUkVTVUxUICBXSU5BUEkgSVdpbmVEM0RQYWxldHRlSW1wbF9HZXRQYXJlbnQoSVdpbmVEM0RQYWxldHRlICppZmFjZSwgSVVua25vd24gKipQYXJlbnQpIHsKICAgIElXaW5lRDNEUGFsZXR0ZUltcGwgKlRoaXMgPSAoSVdpbmVEM0RQYWxldHRlSW1wbCAqKWlmYWNlOwogICAgVFJBQ0UoIiglcCktPiglcClcbiIsIFRoaXMsIFBhcmVudCk7CgogICAgKlBhcmVudCA9IChJVW5rbm93biAqKSBUaGlzLT5wYXJlbnQ7CiAgICBJVW5rbm93bl9BZGRSZWYoIChJVW5rbm93biAqKSBUaGlzLT5wYXJlbnQpOwogICAgcmV0dXJuIFdJTkVEM0RfT0s7Cn0KCmNvbnN0IElXaW5lRDNEUGFsZXR0ZVZ0YmwgSVdpbmVEM0RQYWxldHRlX1Z0YmwgPQp7CiAgICAvKioqIElVbmtub3duICoqKi8KICAgIElXaW5lRDNEUGFsZXR0ZUltcGxfUXVlcnlJbnRlcmZhY2UsCiAgICBJV2luZUQzRFBhbGV0dGVJbXBsX0FkZFJlZiwKICAgIElXaW5lRDNEUGFsZXR0ZUltcGxfUmVsZWFzZSwKICAgIC8qKiogSVdpbmVEM0RQYWxldHRlICoqKi8KICAgIElXaW5lRDNEUGFsZXR0ZUltcGxfR2V0UGFyZW50LAogICAgSVdpbmVEM0RQYWxldHRlSW1wbF9HZXRFbnRyaWVzLAogICAgSVdpbmVEM0RQYWxldHRlSW1wbF9HZXRDYXBzLAogICAgSVdpbmVEM0RQYWxldHRlSW1wbF9TZXRFbnRyaWVzCn07Cg==