LyoKICogKEMpIENvcHlyaWdodCAyMDAyCiAqIERhbmllbCBFbmdzdHL2bSwgT21pY3JvbiBDZXRpIEFCLCA8ZGFuaWVsQG9taWNyb24uc2U+CiAqCiAqIFNlZSBmaWxlIENSRURJVFMgZm9yIGxpc3Qgb2YgcGVvcGxlIHdobyBjb250cmlidXRlZCB0byB0aGlzCiAqIHByb2plY3QuCiAqCiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKICogbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMKICogcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YKICogdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiAqCiAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCiAqIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlCiAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sCiAqIE1BIDAyMTExLTEzMDcgVVNBCiAqLwoKI2luY2x1ZGUgPGNvbW1vbi5oPgojaW5jbHVkZSA8cGNpLmg+CiNpbmNsdWRlIDxhc20vaW8uaD4KI2luY2x1ZGUgPGFzbS9wY2kuaD4KCiN1bmRlZiBQQ0lfUk9NX1NDQU5fVkVSQk9TRQoKaW50IHBjaV9zaGFkb3dfcm9tKHBjaV9kZXZfdCBkZXYsIHVuc2lnbmVkIGNoYXIgKmRlc3QpCnsKCXN0cnVjdCBwY2lfY29udHJvbGxlciAqaG9zZTsKCWludCByZXMgPSAtMTsKCWludCBpOwoKCXUzMiByb21fYWRkcjsKCXUzMiBhZGRyX3JlZzsKCXUzMiBzaXplOwoKCXUxNiB2ZW5kb3I7Cgl1MTYgZGV2aWNlOwoJdTMyIGNsYXNzX2NvZGU7CgoJaG9zZSA9IHBjaV9idXNfdG9faG9zZShQQ0lfQlVTKGRldikpOwojaWYgMAoJcHJpbnRmKCJwY2lfc2hhZG93X3JvbSgpIGFza2VkIHRvIHNoYWRvdyBkZXZpY2UgJXggdG8gJXhcbiIsCgkgICAgICAgZGV2LCAodTMyKWRlc3QpOwojZW5kaWYKCXBjaV9yZWFkX2NvbmZpZ193b3JkKGRldiwgUENJX1ZFTkRPUl9JRCwgJnZlbmRvcik7CglwY2lfcmVhZF9jb25maWdfd29yZChkZXYsIFBDSV9ERVZJQ0VfSUQsICZkZXZpY2UpOwoJcGNpX3JlYWRfY29uZmlnX2R3b3JkKGRldiwgUENJX0NMQVNTX1JFVklTSU9OLCAmY2xhc3NfY29kZSk7CgoJY2xhc3NfY29kZSAmPSAweGZmZmZmZjAwOwoJY2xhc3NfY29kZSA+Pj0gODsKCglkZWJ1ZygiUENJIEhlYWRlciBWZW5kb3IgJTA0eCBkZXZpY2UgJTA0eCBjbGFzcyAlMDZ4XG4iLAoJICAgICAgIHZlbmRvciwgZGV2aWNlLCBjbGFzc19jb2RlKTsKCgkvKiBFbmFibGUgdGhlIHJvbSBhZGRlc3MgZGVjb2RlciAqLwoJcGNpX3dyaXRlX2NvbmZpZ19kd29yZChkZXYsIFBDSV9ST01fQUREUkVTUywgKHUzMilQQ0lfUk9NX0FERFJFU1NfTUFTSyk7CglwY2lfcmVhZF9jb25maWdfZHdvcmQoZGV2LCBQQ0lfUk9NX0FERFJFU1MsICZhZGRyX3JlZyk7CgoJaWYgKCFhZGRyX3JlZykgewoJCS8qIHJlZ2lzdGVyIHVuaW1wbGVtZW50ZWQgKi8KCQlwcmludGYoInBjaV9jaGFkb3dfcm9tOiBkZXZpY2UgZG8gbm90IHNlZW0gdG8gaGF2ZSBhIHJvbVxuIik7CgkJcmV0dXJuIC0xOwoJfQoKCXNpemUgPSAofihhZGRyX3JlZyZQQ0lfUk9NX0FERFJFU1NfTUFTSykpKzE7CgoJZGVidWcoIlJPTSBpcyAlZCBieXRlc1xuIiwgc2l6ZSk7CgoJcm9tX2FkZHIgPSBwY2lfZ2V0X3JvbV93aW5kb3coaG9zZSwgc2l6ZSk7CgoJZGVidWcoIlJPTSBtYXBwZWQgYXQgJXhcbiIsIHJvbV9hZGRyKTsKCglwY2lfd3JpdGVfY29uZmlnX2R3b3JkKGRldiwgUENJX1JPTV9BRERSRVNTLAoJCQkgICAgICAgcGNpX3BoeXNfdG9fbWVtKGRldiwgcm9tX2FkZHIpCgkJCSAgICAgICB8UENJX1JPTV9BRERSRVNTX0VOQUJMRSk7CgoKCWZvciAoaT1yb21fYWRkcjtpPHJvbV9hZGRyK3NpemU7IGkrPTUxMikgewoKCgkJaWYgKHJlYWR3KGkpID09IDB4YWE1NSkgewoJCQl1MzIgcGNpX2RhdGE7CiNpZmRlZiBQQ0lfUk9NX1NDQU5fVkVSQk9TRQoJCQlwcmludGYoIlJPTSBzaWduYXR1cmUgZm91bmRcbiIpOwojZW5kaWYKCQkJcGNpX2RhdGEgPSByZWFkdygweDE4K2kpOwoJCQlwY2lfZGF0YSArPSBpOwoKCQkJaWYgKDA9PW1lbWNtcCgodm9pZCopcGNpX2RhdGEsICJQQ0lSIiwgNCkpIHsKI2lmZGVmIFBDSV9ST01fU0NBTl9WRVJCT1NFCgkJCQlwcmludGYoIkZvdW50IFBDSSByb20gaW1hZ2UgYXQgb2Zmc2V0ICVkXG4iLCBpLXJvbV9hZGRyKTsKCQkJCXByaW50ZigiVmVuZG9yICUwNHggZGV2aWNlICUwNHggY2xhc3MgJTA2eFxuIiwKCQkJCSAgICAgICByZWFkdyhwY2lfZGF0YSs0KSwgcmVhZHcocGNpX2RhdGErNiksCgkJCQkgICAgICAgcmVhZGwocGNpX2RhdGErMHgwZCkmMHhmZmZmZmYpOwoJCQkJcHJpbnRmKCIlc1xuIiwKCQkJCSAgICAgICAocmVhZHcocGNpX2RhdGErMHgxNSkgJjB4ODApPwoJCQkJICAgICAgICJMYXN0IGltYWdlIjoiTW9yZSBpbWFnZXMgZm9sbG93Iik7CgkJCQlzd2l0Y2gJKHJlYWRiKHBjaV9kYXRhKzB4MTQpKSB7CgkJCQljYXNlIDA6CgkJCQkJcHJpbnRmKCJYODYgY29kZVxuIik7CgkJCQkJYnJlYWs7CgkJCQljYXNlIDE6CgkJCQkJcHJpbnRmKCJPcGVuZmlybXdhcmUgY29kZVxuIik7CgkJCQkJYnJlYWs7CgkJCQljYXNlIDI6CgkJCQkJcHJpbnRmKCJQQVJJU0MgY29kZVxuIik7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCQlwcmludGYoIkltYWdlIHNpemUgJWRcbiIsIHJlYWR3KHBjaV9kYXRhKzB4MTApICogNTEyKTsKI2VuZGlmCgkJCQkvKiBGaXhNZTogSSB0aGluayB3ZSBzaG91bGQgY29tcGFyZSB0aGUgY2xhc3MgY29kZQoJCQkJICogYnl0ZXMgYXMgd2VsbCBidXQgSSBoYXZlIG5vIHJlZmVyZW5jZSBvbiB0aGUKCQkJCSAqIGV4YWN0IG9yZGVyIG9mIHRoZXNlIGJ5dGVzIGluIHRoZSBQQ0kgUk9NIGhlYWRlciAqLwoJCQkJaWYgKHJlYWR3KHBjaV9kYXRhKzQpID09IHZlbmRvciAmJgoJCQkJICAgIHJlYWR3KHBjaV9kYXRhKzYpID09IGRldmljZSAmJgoJCQkJICAgIC8qIChyZWFkbChwY2lfZGF0YSsweDBkKSYweGZmZmZmZikgPT0gY2xhc3NfY29kZSAmJiAqLwoJCQkJICAgIHJlYWRiKHBjaV9kYXRhKzB4MTQpID09IDAgLyogeDg2IGNvZGUgaW1hZ2UgKi8gKSB7CiNpZmRlZiBQQ0lfUk9NX1NDQU5fVkVSQk9TRQoJCQkJCXByaW50ZigiU3VpdGFibGUgUk9NIGltYWdlIGZvdW5kLCBjb3B5aW5nXG4iKTsKI2VuZGlmCgkJCQkJbWVtbW92ZShkZXN0LCAodm9pZCopcm9tX2FkZHIsIHJlYWR3KHBjaV9kYXRhKzB4MTApICogNTEyKTsKCQkJCQlyZXMgPSAwOwoJCQkJCWJyZWFrOwoKCQkJCX0KCQkJCWlmIChyZWFkdyhwY2lfZGF0YSsweDE1KSAmMHg4MCkgewoJCQkJCWJyZWFrOwoJCQkJfQoJCQl9CgkJfQoKCX0KCiNpZmRlZiBQQ0lfUk9NX1NDQU5fVkVSQk9TRQoJaWYgKHJlcykgewoJCXByaW50ZigiTm8gc3VpdGFibGUgaW1hZ2UgZm91bmRcbiIpOwoJfQojZW5kaWYKCS8qIGRpc2FibGUgUEFSIHJlZ2lzdGVyIGFuZCBQQ0kgZGV2aWNlIFJPTSBhZGRyZXNzIGRldm9jZXIgKi8KCXBjaV9yZW1vdmVfcm9tX3dpbmRvdyhob3NlLCByb21fYWRkcik7CgoJcGNpX3dyaXRlX2NvbmZpZ19kd29yZChkZXYsIFBDSV9ST01fQUREUkVTUywgMCk7CgoJcmV0dXJuIHJlczsKfQo=