LyoJCURpcmVjdERyYXcgLSBJRGlyZWN0UGFsZXR0ZSBiYXNlIGludGVyZmFjZQogKgogKiBDb3B5cmlnaHQgMTk5Ny0yMDAwIE1hcmN1cyBNZWlzc25lcgogKiBDb3B5cmlnaHQgMjAwMC0yMDAxIFRyYW5zR2FtaW5nIFRlY2hub2xvZ2llcyBJbmMuCiAqIENvcHlyaWdodCAyMDA2IFN0ZWZhbiBE9nNpbmdlciBmb3IgQ29kZVdlYXZlcnMKICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgMDIxMTAtMTMwMSwgVVNBCiAqLwojaW5jbHVkZSAiY29uZmlnLmgiCiNpbmNsdWRlICJ3aW5lcnJvci5oIgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgoKI2luY2x1ZGUgPGFzc2VydC5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CgojaW5jbHVkZSAid2luZWQzZF9wcml2YXRlLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChkM2QpOwoKI2RlZmluZSBTSVpFX0JJVFMgKFdJTkVERFBDQVBTXzFCSVQgfCBXSU5FRERQQ0FQU18yQklUIHwgV0lORUREUENBUFNfNEJJVCB8IFdJTkVERFBDQVBTXzhCSVQpCgpzdGF0aWMgSFJFU1VMVCAgV0lOQVBJIElXaW5lRDNEUGFsZXR0ZUltcGxfUXVlcnlJbnRlcmZhY2UoSVdpbmVEM0RQYWxldHRlICppZmFjZSwgUkVGSUlEIHJlZmlpZCwgdm9pZCAqKm9iaikgewogICAgSVdpbmVEM0RQYWxldHRlSW1wbCAqVGhpcyA9IChJV2luZUQzRFBhbGV0dGVJbXBsICopaWZhY2U7CiAgICBUUkFDRSgiKCVwKS0+KCVzLCVwKVxuIixUaGlzLGRlYnVnc3RyX2d1aWQocmVmaWlkKSxvYmopOwoKICAgIGlmIChJc0VxdWFsR1VJRChyZWZpaWQsICZJSURfSVVua25vd24pCiAgICAgICAgfHwgSXNFcXVhbEdVSUQocmVmaWlkLCAmSUlEX0lXaW5lRDNEUGFsZXR0ZSkpIHsKICAgICAgICAqb2JqID0gaWZhY2U7CiAgICAgICAgSVdpbmVEM0RQYWxldHRlX0FkZFJlZihpZmFjZSk7CiAgICAgICAgcmV0dXJuIFNfT0s7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICAqb2JqID0gTlVMTDsKICAgICAgICByZXR1cm4gRV9OT0lOVEVSRkFDRTsKICAgIH0KfQoKc3RhdGljIFVMT05HICBXSU5BUEkgSVdpbmVEM0RQYWxldHRlSW1wbF9BZGRSZWYoSVdpbmVEM0RQYWxldHRlICppZmFjZSkgewogICAgSVdpbmVEM0RQYWxldHRlSW1wbCAqVGhpcyA9IChJV2luZUQzRFBhbGV0dGVJbXBsICopaWZhY2U7CiAgICBVTE9ORyByZWYgPSBJbnRlcmxvY2tlZEluY3JlbWVudCgmVGhpcy0+cmVmKTsKCiAgICBUUkFDRSgiKCVwKS0+KCkgaW5jcmVtZW50aW5nIGZyb20gJXUuXG4iLCBUaGlzLCByZWYgLSAxKTsKCiAgICByZXR1cm4gcmVmOwp9CgpzdGF0aWMgVUxPTkcgIFdJTkFQSSBJV2luZUQzRFBhbGV0dGVJbXBsX1JlbGVhc2UoSVdpbmVEM0RQYWxldHRlICppZmFjZSkgewogICAgSVdpbmVEM0RQYWxldHRlSW1wbCAqVGhpcyA9IChJV2luZUQzRFBhbGV0dGVJbXBsICopaWZhY2U7CiAgICBVTE9ORyByZWYgPSBJbnRlcmxvY2tlZERlY3JlbWVudCgmVGhpcy0+cmVmKTsKCiAgICBUUkFDRSgiKCVwKS0+KCkgZGVjcmVtZW50aW5nIGZyb20gJXUuXG4iLCBUaGlzLCByZWYgKyAxKTsKCiAgICBpZiAoIXJlZikgewogICAgICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIFRoaXMpOwogICAgICAgIHJldHVybiAwOwogICAgfQoKICAgIHJldHVybiByZWY7Cn0KCi8qIE5vdCBjYWxsZWQgZnJvbSB0aGUgdnRhYmxlICovCkRXT1JEIElXaW5lRDNEUGFsZXR0ZUltcGxfU2l6ZShEV09SRCBkd0ZsYWdzKSB7CiAgICBzd2l0Y2ggKGR3RmxhZ3MgJiBTSVpFX0JJVFMpIHsKICAgICAgICBjYXNlIFdJTkVERFBDQVBTXzFCSVQ6IHJldHVybiAyOwogICAgICAgIGNhc2UgV0lORUREUENBUFNfMkJJVDogcmV0dXJuIDQ7CiAgICAgICAgY2FzZSBXSU5FRERQQ0FQU180QklUOiByZXR1cm4gMTY7CiAgICAgICAgY2FzZSBXSU5FRERQQ0FQU184QklUOiByZXR1cm4gMjU2OwogICAgICAgIGRlZmF1bHQ6IGFzc2VydCgwKTsgcmV0dXJuIDI1NjsKICAgIH0KfQoKc3RhdGljIEhSRVNVTFQgIFdJTkFQSSBJV2luZUQzRFBhbGV0dGVJbXBsX0dldEVudHJpZXMoSVdpbmVEM0RQYWxldHRlICppZmFjZSwgRFdPUkQgRmxhZ3MsIERXT1JEIFN0YXJ0LCBEV09SRCBDb3VudCwgUEFMRVRURUVOVFJZICpQYWxFbnQpIHsKICAgIElXaW5lRDNEUGFsZXR0ZUltcGwgKlRoaXMgPSAoSVdpbmVEM0RQYWxldHRlSW1wbCAqKWlmYWNlOwoKICAgIFRSQUNFKCIoJXApLT4oJTA4eCwlZCwlZCwlcClcbiIsVGhpcyxGbGFncyxTdGFydCxDb3VudCxQYWxFbnQpOwoKICAgIGlmIChGbGFncyAhPSAwKSByZXR1cm4gV0lORUQzREVSUl9JTlZBTElEQ0FMTDsgLyogdW5jaGVja2VkICovCiAgICBpZiAoU3RhcnQgKyBDb3VudCA+IElXaW5lRDNEUGFsZXR0ZUltcGxfU2l6ZShUaGlzLT5GbGFncykpCiAgICAgICAgcmV0dXJuIFdJTkVEM0RFUlJfSU5WQUxJRENBTEw7CgogICAgaWYgKFRoaXMtPkZsYWdzICYgV0lORUREUENBUFNfOEJJVEVOVFJJRVMpCiAgICB7CiAgICAgICAgdW5zaWduZWQgaW50IGk7CiAgICAgICAgTFBCWVRFIGVudHJ5ID0gKExQQllURSlQYWxFbnQ7CgogICAgICAgIGZvciAoaT1TdGFydDsgaSA8IENvdW50K1N0YXJ0OyBpKyspCiAgICAgICAgICAgICplbnRyeSsrID0gVGhpcy0+cGFsZW50c1tpXS5wZVJlZDsKICAgIH0KICAgIGVsc2UKICAgICAgICBtZW1jcHkoUGFsRW50LCBUaGlzLT5wYWxlbnRzK1N0YXJ0LCBDb3VudCAqIHNpemVvZihQQUxFVFRFRU5UUlkpKTsKCiAgICByZXR1cm4gV0lORUQzRF9PSzsKfQoKc3RhdGljIEhSRVNVTFQgIFdJTkFQSSBJV2luZUQzRFBhbGV0dGVJbXBsX1NldEVudHJpZXMoSVdpbmVEM0RQYWxldHRlICppZmFjZSwgRFdPUkQgRmxhZ3MsIERXT1JEIFN0YXJ0LCBEV09SRCBDb3VudCwgUEFMRVRURUVOVFJZICpQYWxFbnQpCnsKICAgIElXaW5lRDNEUGFsZXR0ZUltcGwgKlRoaXMgPSAoSVdpbmVEM0RQYWxldHRlSW1wbCAqKWlmYWNlOwogICAgUmVzb3VyY2VMaXN0ICpyZXM7CgogICAgVFJBQ0UoIiglcCktPiglMDh4LCVkLCVkLCVwKVxuIixUaGlzLEZsYWdzLFN0YXJ0LENvdW50LFBhbEVudCk7CgogICAgaWYgKFRoaXMtPkZsYWdzICYgV0lORUREUENBUFNfOEJJVEVOVFJJRVMpIHsKICAgICAgICB1bnNpZ25lZCBpbnQgaTsKICAgICAgICBjb25zdCBCWVRFKiBlbnRyeSA9IChjb25zdCBCWVRFKilQYWxFbnQ7CgogICAgICAgIGZvciAoaT1TdGFydDsgaSA8IENvdW50K1N0YXJ0OyBpKyspCiAgICAgICAgICAgIFRoaXMtPnBhbGVudHNbaV0ucGVSZWQgPSAqZW50cnkrKzsKICAgIH0KICAgIGVsc2UgewogICAgICAgIG1lbWNweShUaGlzLT5wYWxlbnRzK1N0YXJ0LCBQYWxFbnQsIENvdW50ICogc2l6ZW9mKFBBTEVUVEVFTlRSWSkpOwoKICAgICAgICBpZiAoVGhpcy0+aHBhbCkKICAgICAgICAgICAgU2V0UGFsZXR0ZUVudHJpZXMoVGhpcy0+aHBhbCwgU3RhcnQsIENvdW50LCBUaGlzLT5wYWxlbnRzK1N0YXJ0KTsKICAgIH0KCiNpZiAwCiAgICAvKiBOb3csIGlmIHdlIGFyZSBpbiAnZGVwdGggY29udmVyc2lvbiBtb2RlJywgdXBkYXRlIHRoZSBzY3JlZW4gcGFsZXR0ZSAqLwogICAgLyogRklYTUU6IHdlIG5lZWQgdG8gdXBkYXRlIHRoZSBpbWFnZSBvciB3ZSB3b24ndCBnZXQgcGFsZXR0ZSBmYWRpbmcuICovCiAgICBpZiAoVGhpcy0+ZGRyYXctPmQtPnBhbGV0dGVfY29udmVydCAhPSBOVUxMKQogICAgICAgIFRoaXMtPmRkcmF3LT5kLT5wYWxldHRlX2NvbnZlcnQocGFsZW50LFRoaXMtPnNjcmVlbl9wYWxlbnRzLHN0YXJ0LGNvdW50KTsKI2VuZGlmCgogICAgLyogSWYgdGhlIHBhbGV0dGUgaXMgYXR0YWNoZWQgdG8gdGhlIHJlbmRlciB0YXJnZXQsIHVwZGF0ZSBhbGwgcmVuZGVyIHRhcmdldHMgKi8KCiAgICBmb3IocmVzID0gVGhpcy0+d2luZUQzRERldmljZS0+cmVzb3VyY2VzOyByZXMgIT0gTlVMTDsgcmVzPXJlcy0+bmV4dCkgewogICAgICAgIGlmKElXaW5lRDNEUmVzb3VyY2VfR2V0VHlwZShyZXMtPnJlc291cmNlKSA9PSBXSU5FRDNEUlRZUEVfU1VSRkFDRSkgewogICAgICAgICAgICBJV2luZUQzRFN1cmZhY2VJbXBsICppbXBsID0gKElXaW5lRDNEU3VyZmFjZUltcGwgKikgcmVzLT5yZXNvdXJjZTsKICAgICAgICAgICAgaWYoaW1wbC0+cGFsZXR0ZSA9PSBUaGlzKQogICAgICAgICAgICAgICAgSVdpbmVEM0RTdXJmYWNlX1JlYWxpemVQYWxldHRlKCAoSVdpbmVEM0RTdXJmYWNlICopIHJlcy0+cmVzb3VyY2UpOwogICAgICAgIH0KICAgIH0KCiAgICAvKiBJZiB0aGUgcGFsZXR0ZSBpcyB0aGUgcHJpbWFyeSBwYWxldHRlLCBzZXQgdGhlIGVudHJpZXMgdG8gdGhlIGRldmljZSAqLwogICAgaWYoVGhpcy0+RmxhZ3MgJiBXSU5FRERQQ0FQU19QUklNQVJZU1VSRkFDRSkgewogICAgICAgIHVuc2lnbmVkIGludCBpOwogICAgICAgIElXaW5lRDNERGV2aWNlSW1wbCAqZGV2aWNlID0gVGhpcy0+d2luZUQzRERldmljZTsKICAgICAgICBQQUxFVFRFRU5UUlkgKmVudHJ5ID0gUGFsRW50OwoKICAgICAgICBmb3IoaSA9IFN0YXJ0OyBpIDwgU3RhcnQrQ291bnQ7IGkrKykgewogICAgICAgICAgICBkZXZpY2UtPnBhbGV0dGVzW2RldmljZS0+Y3VycmVudFBhbGV0dGVdW2ldID0gKmVudHJ5Kys7CiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiBXSU5FRDNEX09LOwp9CgpzdGF0aWMgSFJFU1VMVCAgV0lOQVBJIElXaW5lRDNEUGFsZXR0ZUltcGxfR2V0Q2FwcyhJV2luZUQzRFBhbGV0dGUgKmlmYWNlLCBEV09SRCAqQ2FwcykgewogICAgSVdpbmVEM0RQYWxldHRlSW1wbCAqVGhpcyA9IChJV2luZUQzRFBhbGV0dGVJbXBsICopaWZhY2U7CiAgICBUUkFDRSgiKCVwKS0+KCVwKVxuIiwgVGhpcywgQ2Fwcyk7CgogICAgKkNhcHMgPSBUaGlzLT5GbGFnczsKICAgIHJldHVybiBXSU5FRDNEX09LOwp9CgpzdGF0aWMgSFJFU1VMVCAgV0lOQVBJIElXaW5lRDNEUGFsZXR0ZUltcGxfR2V0UGFyZW50KElXaW5lRDNEUGFsZXR0ZSAqaWZhY2UsIElVbmtub3duICoqUGFyZW50KSB7CiAgICBJV2luZUQzRFBhbGV0dGVJbXBsICpUaGlzID0gKElXaW5lRDNEUGFsZXR0ZUltcGwgKilpZmFjZTsKICAgIFRSQUNFKCIoJXApLT4oJXApXG4iLCBUaGlzLCBQYXJlbnQpOwoKICAgICpQYXJlbnQgPSAoSVVua25vd24gKikgVGhpcy0+cGFyZW50OwogICAgSVVua25vd25fQWRkUmVmKCAoSVVua25vd24gKikgVGhpcy0+cGFyZW50KTsKICAgIHJldHVybiBXSU5FRDNEX09LOwp9Cgpjb25zdCBJV2luZUQzRFBhbGV0dGVWdGJsIElXaW5lRDNEUGFsZXR0ZV9WdGJsID0KewogICAgLyoqKiBJVW5rbm93biAqKiovCiAgICBJV2luZUQzRFBhbGV0dGVJbXBsX1F1ZXJ5SW50ZXJmYWNlLAogICAgSVdpbmVEM0RQYWxldHRlSW1wbF9BZGRSZWYsCiAgICBJV2luZUQzRFBhbGV0dGVJbXBsX1JlbGVhc2UsCiAgICAvKioqIElXaW5lRDNEUGFsZXR0ZSAqKiovCiAgICBJV2luZUQzRFBhbGV0dGVJbXBsX0dldFBhcmVudCwKICAgIElXaW5lRDNEUGFsZXR0ZUltcGxfR2V0RW50cmllcywKICAgIElXaW5lRDNEUGFsZXR0ZUltcGxfR2V0Q2FwcywKICAgIElXaW5lRDNEUGFsZXR0ZUltcGxfU2V0RW50cmllcwp9Owo=