LyoKICogTU1TIHByb3RvY29sIGNvbW1vbiBkZWZpbml0aW9ucy4KICogQ29weXJpZ2h0IChjKSAyMDA2LDIwMDcgUnlhbiBNYXJ0ZWxsCiAqIENvcHlyaWdodCAoYykgMjAwNyBCavZybiBBeGVsc3NvbgogKiBDb3B5cmlnaHQgKGMpIDIwMTAgWmhlbnRhbiBGZW5nIDxzcHlmZW5nIGF0IGdtYWlsIGRvdCBjb20+CiAqCiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIEZGbXBlZy4KICoKICogRkZtcGVnIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogRkZtcGVnIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIEZGbXBlZzsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BIDAyMTEwLTEzMDEgVVNBCiAqLwojaW5jbHVkZSAibW1zLmgiCiNpbmNsdWRlICJhc2YuaCIKI2luY2x1ZGUgImxpYmF2dXRpbC9pbnRyZWFkd3JpdGUuaCIKCiNpZiBGRl9BUElfTUFYX1NUUkVBTVMKI2RlZmluZSBNTVNfTUFYX1NUUkVBTVMgTUFYX1NUUkVBTVMKI2Vsc2UKI2RlZmluZSBNTVNfTUFYX1NUUkVBTVMgMjU2ICAgIC8qKjwgYXJiaXRyYXJ5IHNhbml0eSBjaGVjayB2YWx1ZSAqLwojZW5kaWYKCmludCBmZl9tbXNfcmVhZF9oZWFkZXIoTU1TQ29udGV4dCAqbW1zLCB1aW50OF90ICpidWYsIGNvbnN0IGludCBzaXplKQp7CiAgICBjaGFyICpwb3M7CiAgICBpbnQgc2l6ZV90b19jb3B5OwogICAgaW50IHJlbWFpbmluZ19zaXplID0gbW1zLT5hc2ZfaGVhZGVyX3NpemUgLSBtbXMtPmFzZl9oZWFkZXJfcmVhZF9zaXplOwogICAgc2l6ZV90b19jb3B5ID0gRkZNSU4oc2l6ZSwgcmVtYWluaW5nX3NpemUpOwogICAgcG9zID0gbW1zLT5hc2ZfaGVhZGVyICsgbW1zLT5hc2ZfaGVhZGVyX3JlYWRfc2l6ZTsKICAgIG1lbWNweShidWYsIHBvcywgc2l6ZV90b19jb3B5KTsKICAgIGlmIChtbXMtPmFzZl9oZWFkZXJfcmVhZF9zaXplID09IG1tcy0+YXNmX2hlYWRlcl9zaXplKSB7CiAgICAgICAgYXZfZnJlZXAoJm1tcy0+YXNmX2hlYWRlcik7IC8vIHdoaWNoIGNvbnRhaW5zIGFzZiBoZWFkZXIKICAgIH0KICAgIG1tcy0+YXNmX2hlYWRlcl9yZWFkX3NpemUgKz0gc2l6ZV90b19jb3B5OwogICAgcmV0dXJuIHNpemVfdG9fY29weTsKfQoKaW50IGZmX21tc19yZWFkX2RhdGEoTU1TQ29udGV4dCAqbW1zLCB1aW50OF90ICpidWYsIGNvbnN0IGludCBzaXplKQp7CiAgICBpbnQgcmVhZF9zaXplOwogICAgcmVhZF9zaXplID0gRkZNSU4oc2l6ZSwgbW1zLT5yZW1haW5pbmdfaW5fbGVuKTsKICAgIG1lbWNweShidWYsIG1tcy0+cmVhZF9pbl9wdHIsIHJlYWRfc2l6ZSk7CiAgICBtbXMtPnJlbWFpbmluZ19pbl9sZW4gLT0gcmVhZF9zaXplOwogICAgbW1zLT5yZWFkX2luX3B0ciAgICAgICs9IHJlYWRfc2l6ZTsKICAgIHJldHVybiByZWFkX3NpemU7Cn0KCmludCBmZl9tbXNfYXNmX2hlYWRlcl9wYXJzZXIoTU1TQ29udGV4dCAqbW1zKQp7CiAgICB1aW50OF90ICpwID0gbW1zLT5hc2ZfaGVhZGVyOwogICAgdWludDhfdCAqZW5kOwogICAgaW50IGZsYWdzLCBzdHJlYW1faWQ7CiAgICBtbXMtPnN0cmVhbV9udW0gPSAwOwoKICAgIGlmIChtbXMtPmFzZl9oZWFkZXJfc2l6ZSA8IHNpemVvZihmZl9hc2ZfZ3VpZCkgKiAyICsgMjIgfHwKICAgICAgICBtZW1jbXAocCwgZmZfYXNmX2hlYWRlciwgc2l6ZW9mKGZmX2FzZl9ndWlkKSkpIHsKICAgICAgICBhdl9sb2coTlVMTCwgQVZfTE9HX0VSUk9SLAogICAgICAgICAgICAgICAiQ29ycnVwdCBzdHJlYW0gKGludmFsaWQgQVNGIGhlYWRlciwgc2l6ZT0lZClcbiIsCiAgICAgICAgICAgICAgIG1tcy0+YXNmX2hlYWRlcl9zaXplKTsKICAgICAgICByZXR1cm4gQVZFUlJPUl9JTlZBTElEREFUQTsKICAgIH0KCiAgICBlbmQgPSBtbXMtPmFzZl9oZWFkZXIgKyBtbXMtPmFzZl9oZWFkZXJfc2l6ZTsKCiAgICBwICs9IHNpemVvZihmZl9hc2ZfZ3VpZCkgKyAxNDsKICAgIHdoaWxlKGVuZCAtIHAgPj0gc2l6ZW9mKGZmX2FzZl9ndWlkKSArIDgpIHsKICAgICAgICB1aW50NjRfdCBjaHVua3NpemU7CiAgICAgICAgaWYgKCFtZW1jbXAocCwgZmZfYXNmX2RhdGFfaGVhZGVyLCBzaXplb2YoZmZfYXNmX2d1aWQpKSkgewogICAgICAgICAgICBjaHVua3NpemUgPSA1MDsgLy8gc2VlIFJlZmVyZW5jZSBbMl0gc2VjdGlvbiA1LjEKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjaHVua3NpemUgPSBBVl9STDY0KHAgKyBzaXplb2YoZmZfYXNmX2d1aWQpKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFjaHVua3NpemUgfHwgY2h1bmtzaXplID4gZW5kIC0gcCkgewogICAgICAgICAgICBhdl9sb2coTlVMTCwgQVZfTE9HX0VSUk9SLAogICAgICAgICAgICAgICAgICAgIkNvcnJ1cHQgc3RyZWFtIChoZWFkZXIgY2h1bmtzaXplICUiUFJJZDY0IiBpcyBpbnZhbGlkKVxuIiwKICAgICAgICAgICAgICAgICAgIGNodW5rc2l6ZSk7CiAgICAgICAgICAgIHJldHVybiBBVkVSUk9SX0lOVkFMSUREQVRBOwogICAgICAgIH0KICAgICAgICBpZiAoIW1lbWNtcChwLCBmZl9hc2ZfZmlsZV9oZWFkZXIsIHNpemVvZihmZl9hc2ZfZ3VpZCkpKSB7CiAgICAgICAgICAgIC8qIHJlYWQgcGFja2V0IHNpemUgKi8KICAgICAgICAgICAgaWYgKGVuZCAtIHAgPiBzaXplb2YoZmZfYXNmX2d1aWQpICogMiArIDY4KSB7CiAgICAgICAgICAgICAgICBtbXMtPmFzZl9wYWNrZXRfbGVuID0gQVZfUkwzMihwICsgc2l6ZW9mKGZmX2FzZl9ndWlkKSAqIDIgKyA2NCk7CiAgICAgICAgICAgICAgICBpZiAobW1zLT5hc2ZfcGFja2V0X2xlbiA8PSAwIHx8IG1tcy0+YXNmX3BhY2tldF9sZW4gPiBzaXplb2YobW1zLT5pbl9idWZmZXIpKSB7CiAgICAgICAgICAgICAgICAgICAgYXZfbG9nKE5VTEwsIEFWX0xPR19FUlJPUiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvcnJ1cHQgc3RyZWFtICh0b28gbGFyZ2UgcGt0X2xlbiAlZClcbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1tcy0+YXNmX3BhY2tldF9sZW4pOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBBVkVSUk9SX0lOVkFMSUREQVRBOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmICghbWVtY21wKHAsIGZmX2FzZl9zdHJlYW1faGVhZGVyLCBzaXplb2YoZmZfYXNmX2d1aWQpKSkgewogICAgICAgICAgICBmbGFncyAgICAgPSBBVl9STDE2KHAgKyBzaXplb2YoZmZfYXNmX2d1aWQpKjMgKyAyNCk7CiAgICAgICAgICAgIHN0cmVhbV9pZCA9IGZsYWdzICYgMHg3RjsKICAgICAgICAgICAgLy9UaGUgc2Vjb25kIGNvbmRpdGlvbiBpcyBmb3IgY2hlY2tpbmcgQ1NfUEtUX1NUUkVBTV9JRF9SRVFVRVNUIHBhY2tldCBzaXplLAogICAgICAgICAgICAvL3dlIGNhbiBjYWxjdWF0ZSB0aGUgcGFja2V0IHNpemUgYnkgc3RyZWFtX251bS4KICAgICAgICAgICAgLy9QbGVhc2Ugc2VlIGZ1bmN0aW9uIHNlbmRfc3RyZWFtX3NlbGVjdGlvbl9yZXF1ZXN0KCkuCiAgICAgICAgICAgIGlmIChtbXMtPnN0cmVhbV9udW0gPCBNTVNfTUFYX1NUUkVBTVMgJiYKICAgICAgICAgICAgICAgICAgICA0NiArIG1tcy0+c3RyZWFtX251bSAqIDYgPCBzaXplb2YobW1zLT5vdXRfYnVmZmVyKSkgewogICAgICAgICAgICAgICAgbW1zLT5zdHJlYW1zID0gYXZfZmFzdF9yZWFsbG9jKG1tcy0+c3RyZWFtcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmbW1zLT5uYl9zdHJlYW1zX2FsbG9jYXRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobW1zLT5zdHJlYW1fbnVtICsgMSkgKiBzaXplb2YoTU1TU3RyZWFtKSk7CiAgICAgICAgICAgICAgICBtbXMtPnN0cmVhbXNbbW1zLT5zdHJlYW1fbnVtXS5pZCA9IHN0cmVhbV9pZDsKICAgICAgICAgICAgICAgIG1tcy0+c3RyZWFtX251bSsrOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgYXZfbG9nKE5VTEwsIEFWX0xPR19FUlJPUiwKICAgICAgICAgICAgICAgICAgICAgICAiQ29ycnVwdCBzdHJlYW0gKHRvbyBtYW55IEEvViBzdHJlYW1zKVxuIik7CiAgICAgICAgICAgICAgICByZXR1cm4gQVZFUlJPUl9JTlZBTElEREFUQTsKICAgICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoIW1lbWNtcChwLCBmZl9hc2ZfZXh0X3N0cmVhbV9oZWFkZXIsIHNpemVvZihmZl9hc2ZfZ3VpZCkpKSB7CiAgICAgICAgICAgIGlmIChlbmQgLSBwID49IDg4KSB7CiAgICAgICAgICAgICAgICBpbnQgc3RyZWFtX2NvdW50ID0gQVZfUkwxNihwICsgODQpLCBleHRfbGVuX2NvdW50ID0gQVZfUkwxNihwICsgODYpOwogICAgICAgICAgICAgICAgdWludDY0X3Qgc2tpcF9ieXRlcyA9IDg4OwogICAgICAgICAgICAgICAgd2hpbGUgKHN0cmVhbV9jb3VudC0tKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGVuZCAtIHAgPCBza2lwX2J5dGVzICsgNCkgewogICAgICAgICAgICAgICAgICAgICAgICBhdl9sb2coTlVMTCwgQVZfTE9HX0VSUk9SLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvcnJ1cHQgc3RyZWFtIChuZXh0IHN0cmVhbSBuYW1lIGxlbmd0aCBpcyBub3QgaW4gdGhlIGJ1ZmZlcilcbiIpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gQVZFUlJPUl9JTlZBTElEREFUQTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2tpcF9ieXRlcyArPSA0ICsgQVZfUkwxNihwICsgc2tpcF9ieXRlcyArIDIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgd2hpbGUgKGV4dF9sZW5fY291bnQtLSkgewogICAgICAgICAgICAgICAgICAgIGlmIChlbmQgLSBwIDwgc2tpcF9ieXRlcyArIDIyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGF2X2xvZyhOVUxMLCBBVl9MT0dfRVJST1IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29ycnVwdCBzdHJlYW0gKG5leHQgZXh0ZW5zaW9uIHN5c3RlbSBpbmZvIGxlbmd0aCBpcyBub3QgaW4gdGhlIGJ1ZmZlcilcbiIpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gQVZFUlJPUl9JTlZBTElEREFUQTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2tpcF9ieXRlcyArPSAyMiArIEFWX1JMMzIocCArIHNraXBfYnl0ZXMgKyAxOCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoZW5kIC0gcCA8IHNraXBfYnl0ZXMpIHsKICAgICAgICAgICAgICAgICAgICBhdl9sb2coTlVMTCwgQVZfTE9HX0VSUk9SLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29ycnVwdCBzdHJlYW0gKHRoZSBsYXN0IGV4dGVuc2lvbiBzeXN0ZW0gaW5mbyBsZW5ndGggaXMgaW52YWxpZClcbiIpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBBVkVSUk9SX0lOVkFMSUREQVRBOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGNodW5rc2l6ZSAtIHNraXBfYnl0ZXMgPiAyNCkKICAgICAgICAgICAgICAgICAgICBjaHVua3NpemUgPSBza2lwX2J5dGVzOwogICAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmICghbWVtY21wKHAsIGZmX2FzZl9oZWFkMV9ndWlkLCBzaXplb2YoZmZfYXNmX2d1aWQpKSkgewogICAgICAgICAgICBjaHVua3NpemUgPSA0NjsgLy8gc2VlIHJlZmVyZW5jZXMgWzJdIHNlY3Rpb24gMy40LiBUaGlzIHNob3VsZCBiZSBzZXQgNDYuCiAgICAgICAgfQogICAgICAgIHAgKz0gY2h1bmtzaXplOwogICAgfQoKICAgIHJldHVybiAwOwp9Cg==