LyoKICogU2NhdHRlcmxpc3QgQ3J5cHRvZ3JhcGhpYyBBUEkuCiAqCiAqIENvcHlyaWdodCAoYykgMjAwMiBKYW1lcyBNb3JyaXMgPGptb3JyaXNAaW50ZXJjb2RlLmNvbS5hdT4KICogQ29weXJpZ2h0IChjKSAyMDAyIERhdmlkIFMuIE1pbGxlciAoZGF2ZW1AcmVkaGF0LmNvbSkKICogQ29weXJpZ2h0IChjKSAyMDA1IEhlcmJlcnQgWHUgPGhlcmJlcnRAZ29uZG9yLmFwYW5hLm9yZy5hdT4KICoKICogUG9ydGlvbnMgZGVyaXZlZCBmcm9tIENyeXB0b2FwaSwgYnkgQWxleGFuZGVyIEtqZWxkYWFzIDxhc3RvckBmYXN0Lm5vPgogKiBhbmQgTmV0dGxlLCBieSBOaWVscyBN9mxsZXIuCiAqCiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0CiAqIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlCiAqIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgCiAqIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKi8KCiNpbmNsdWRlIDxsaW51eC9jb21waWxlci5oPgojaW5jbHVkZSA8bGludXgvaW5pdC5oPgojaW5jbHVkZSA8bGludXgvY3J5cHRvLmg+CiNpbmNsdWRlIDxsaW51eC9lcnJuby5oPgojaW5jbHVkZSA8bGludXgva2VybmVsLmg+CiNpbmNsdWRlIDxsaW51eC9rbW9kLmg+CiNpbmNsdWRlIDxsaW51eC9yd3NlbS5oPgojaW5jbHVkZSA8bGludXgvc2xhYi5oPgojaW5jbHVkZSA8bGludXgvc3RyaW5nLmg+CiNpbmNsdWRlICJpbnRlcm5hbC5oIgoKTElTVF9IRUFEKGNyeXB0b19hbGdfbGlzdCk7CkRFQ0xBUkVfUldTRU0oY3J5cHRvX2FsZ19zZW0pOwoKc3RhdGljIGlubGluZSBpbnQgY3J5cHRvX2FsZ19nZXQoc3RydWN0IGNyeXB0b19hbGcgKmFsZykKewoJcmV0dXJuIHRyeV9tb2R1bGVfZ2V0KGFsZy0+Y3JhX21vZHVsZSk7Cn0KCnN0YXRpYyBpbmxpbmUgdm9pZCBjcnlwdG9fYWxnX3B1dChzdHJ1Y3QgY3J5cHRvX2FsZyAqYWxnKQp7Cgltb2R1bGVfcHV0KGFsZy0+Y3JhX21vZHVsZSk7Cn0KCnN0YXRpYyBzdHJ1Y3QgY3J5cHRvX2FsZyAqY3J5cHRvX2FsZ19sb29rdXAoY29uc3QgY2hhciAqbmFtZSkKewoJc3RydWN0IGNyeXB0b19hbGcgKnEsICphbGcgPSBOVUxMOwoJaW50IGJlc3QgPSAtMTsKCglpZiAoIW5hbWUpCgkJcmV0dXJuIE5VTEw7CgkKCWRvd25fcmVhZCgmY3J5cHRvX2FsZ19zZW0pOwoJCglsaXN0X2Zvcl9lYWNoX2VudHJ5KHEsICZjcnlwdG9fYWxnX2xpc3QsIGNyYV9saXN0KSB7CgkJaW50IGV4YWN0LCBmdXp6eTsKCgkJZXhhY3QgPSAhc3RyY21wKHEtPmNyYV9kcml2ZXJfbmFtZSwgbmFtZSk7CgkJZnV6enkgPSAhc3RyY21wKHEtPmNyYV9uYW1lLCBuYW1lKTsKCQlpZiAoIWV4YWN0ICYmICEoZnV6enkgJiYgcS0+Y3JhX3ByaW9yaXR5ID4gYmVzdCkpCgkJCWNvbnRpbnVlOwoKCQlpZiAodW5saWtlbHkoIWNyeXB0b19hbGdfZ2V0KHEpKSkKCQkJY29udGludWU7CgoJCWJlc3QgPSBxLT5jcmFfcHJpb3JpdHk7CgkJaWYgKGFsZykKCQkJY3J5cHRvX2FsZ19wdXQoYWxnKTsKCQlhbGcgPSBxOwoKCQlpZiAoZXhhY3QpCgkJCWJyZWFrOwoJfQoJCgl1cF9yZWFkKCZjcnlwdG9fYWxnX3NlbSk7CglyZXR1cm4gYWxnOwp9CgovKiBBIGZhciBtb3JlIGludGVsbGlnZW50IHZlcnNpb24gb2YgdGhpcyBpcyBwbGFubmVkLiAgRm9yIG5vdywganVzdAogKiB0cnkgYW4gZXhhY3QgbWF0Y2ggb24gdGhlIG5hbWUgb2YgdGhlIGFsZ29yaXRobS4gKi8Kc3RhdGljIGlubGluZSBzdHJ1Y3QgY3J5cHRvX2FsZyAqY3J5cHRvX2FsZ19tb2RfbG9va3VwKGNvbnN0IGNoYXIgKm5hbWUpCnsKCXJldHVybiB0cnlfdGhlbl9yZXF1ZXN0X21vZHVsZShjcnlwdG9fYWxnX2xvb2t1cChuYW1lKSwgbmFtZSk7Cn0KCnN0YXRpYyBpbnQgY3J5cHRvX2luaXRfZmxhZ3Moc3RydWN0IGNyeXB0b190Zm0gKnRmbSwgdTMyIGZsYWdzKQp7Cgl0Zm0tPmNydF9mbGFncyA9IGZsYWdzICYgQ1JZUFRPX1RGTV9SRVFfTUFTSzsKCWZsYWdzICY9IH5DUllQVE9fVEZNX1JFUV9NQVNLOwoJCglzd2l0Y2ggKGNyeXB0b190Zm1fYWxnX3R5cGUodGZtKSkgewoJY2FzZSBDUllQVE9fQUxHX1RZUEVfQ0lQSEVSOgoJCXJldHVybiBjcnlwdG9faW5pdF9jaXBoZXJfZmxhZ3ModGZtLCBmbGFncyk7CgkJCgljYXNlIENSWVBUT19BTEdfVFlQRV9ESUdFU1Q6CgkJcmV0dXJuIGNyeXB0b19pbml0X2RpZ2VzdF9mbGFncyh0Zm0sIGZsYWdzKTsKCQkKCWNhc2UgQ1JZUFRPX0FMR19UWVBFX0NPTVBSRVNTOgoJCXJldHVybiBjcnlwdG9faW5pdF9jb21wcmVzc19mbGFncyh0Zm0sIGZsYWdzKTsKCQoJZGVmYXVsdDoKCQlicmVhazsKCX0KCQoJQlVHKCk7CglyZXR1cm4gLUVJTlZBTDsKfQoKc3RhdGljIGludCBjcnlwdG9faW5pdF9vcHMoc3RydWN0IGNyeXB0b190Zm0gKnRmbSkKewoJc3dpdGNoIChjcnlwdG9fdGZtX2FsZ190eXBlKHRmbSkpIHsKCWNhc2UgQ1JZUFRPX0FMR19UWVBFX0NJUEhFUjoKCQlyZXR1cm4gY3J5cHRvX2luaXRfY2lwaGVyX29wcyh0Zm0pOwoJCQoJY2FzZSBDUllQVE9fQUxHX1RZUEVfRElHRVNUOgoJCXJldHVybiBjcnlwdG9faW5pdF9kaWdlc3Rfb3BzKHRmbSk7CgkJCgljYXNlIENSWVBUT19BTEdfVFlQRV9DT01QUkVTUzoKCQlyZXR1cm4gY3J5cHRvX2luaXRfY29tcHJlc3Nfb3BzKHRmbSk7CgkKCWRlZmF1bHQ6CgkJYnJlYWs7Cgl9CgkKCUJVRygpOwoJcmV0dXJuIC1FSU5WQUw7Cn0KCnN0YXRpYyB2b2lkIGNyeXB0b19leGl0X29wcyhzdHJ1Y3QgY3J5cHRvX3RmbSAqdGZtKQp7Cglzd2l0Y2ggKGNyeXB0b190Zm1fYWxnX3R5cGUodGZtKSkgewoJY2FzZSBDUllQVE9fQUxHX1RZUEVfQ0lQSEVSOgoJCWNyeXB0b19leGl0X2NpcGhlcl9vcHModGZtKTsKCQlicmVhazsKCQkKCWNhc2UgQ1JZUFRPX0FMR19UWVBFX0RJR0VTVDoKCQljcnlwdG9fZXhpdF9kaWdlc3Rfb3BzKHRmbSk7CgkJYnJlYWs7CgkJCgljYXNlIENSWVBUT19BTEdfVFlQRV9DT01QUkVTUzoKCQljcnlwdG9fZXhpdF9jb21wcmVzc19vcHModGZtKTsKCQlicmVhazsKCQoJZGVmYXVsdDoKCQlCVUcoKTsKCQkKCX0KfQoKc3RhdGljIHVuc2lnbmVkIGludCBjcnlwdG9fY3R4c2l6ZShzdHJ1Y3QgY3J5cHRvX2FsZyAqYWxnLCBpbnQgZmxhZ3MpCnsKCXVuc2lnbmVkIGludCBsZW47CgoJc3dpdGNoIChhbGctPmNyYV9mbGFncyAmIENSWVBUT19BTEdfVFlQRV9NQVNLKSB7CglkZWZhdWx0OgoJCUJVRygpOwoKCWNhc2UgQ1JZUFRPX0FMR19UWVBFX0NJUEhFUjoKCQlsZW4gPSBjcnlwdG9fY2lwaGVyX2N0eHNpemUoYWxnLCBmbGFncyk7CgkJYnJlYWs7CgkJCgljYXNlIENSWVBUT19BTEdfVFlQRV9ESUdFU1Q6CgkJbGVuID0gY3J5cHRvX2RpZ2VzdF9jdHhzaXplKGFsZywgZmxhZ3MpOwoJCWJyZWFrOwoJCQoJY2FzZSBDUllQVE9fQUxHX1RZUEVfQ09NUFJFU1M6CgkJbGVuID0gY3J5cHRvX2NvbXByZXNzX2N0eHNpemUoYWxnLCBmbGFncyk7CgkJYnJlYWs7Cgl9CgoJcmV0dXJuIGxlbiArIGFsZy0+Y3JhX2FsaWdubWFzazsKfQoKc3RydWN0IGNyeXB0b190Zm0gKmNyeXB0b19hbGxvY190Zm0oY29uc3QgY2hhciAqbmFtZSwgdTMyIGZsYWdzKQp7CglzdHJ1Y3QgY3J5cHRvX3RmbSAqdGZtID0gTlVMTDsKCXN0cnVjdCBjcnlwdG9fYWxnICphbGc7Cgl1bnNpZ25lZCBpbnQgdGZtX3NpemU7CgoJYWxnID0gY3J5cHRvX2FsZ19tb2RfbG9va3VwKG5hbWUpOwoJaWYgKGFsZyA9PSBOVUxMKQoJCWdvdG8gb3V0OwoKCXRmbV9zaXplID0gc2l6ZW9mKCp0Zm0pICsgY3J5cHRvX2N0eHNpemUoYWxnLCBmbGFncyk7Cgl0Zm0gPSBrbWFsbG9jKHRmbV9zaXplLCBHRlBfS0VSTkVMKTsKCWlmICh0Zm0gPT0gTlVMTCkKCQlnb3RvIG91dF9wdXQ7CgoJbWVtc2V0KHRmbSwgMCwgdGZtX3NpemUpOwoJCgl0Zm0tPl9fY3J0X2FsZyA9IGFsZzsKCQoJaWYgKGNyeXB0b19pbml0X2ZsYWdzKHRmbSwgZmxhZ3MpKQoJCWdvdG8gb3V0X2ZyZWVfdGZtOwoJCQoJaWYgKGNyeXB0b19pbml0X29wcyh0Zm0pKSB7CgkJY3J5cHRvX2V4aXRfb3BzKHRmbSk7CgkJZ290byBvdXRfZnJlZV90Zm07Cgl9CgoJZ290byBvdXQ7CgpvdXRfZnJlZV90Zm06CglrZnJlZSh0Zm0pOwoJdGZtID0gTlVMTDsKb3V0X3B1dDoKCWNyeXB0b19hbGdfcHV0KGFsZyk7Cm91dDoKCXJldHVybiB0Zm07Cn0KCnZvaWQgY3J5cHRvX2ZyZWVfdGZtKHN0cnVjdCBjcnlwdG9fdGZtICp0Zm0pCnsKCXN0cnVjdCBjcnlwdG9fYWxnICphbGc7CglpbnQgc2l6ZTsKCglpZiAodW5saWtlbHkoIXRmbSkpCgkJcmV0dXJuOwoKCWFsZyA9IHRmbS0+X19jcnRfYWxnOwoJc2l6ZSA9IHNpemVvZigqdGZtKSArIGFsZy0+Y3JhX2N0eHNpemU7CgoJY3J5cHRvX2V4aXRfb3BzKHRmbSk7CgljcnlwdG9fYWxnX3B1dChhbGcpOwoJbWVtc2V0KHRmbSwgMCwgc2l6ZSk7CglrZnJlZSh0Zm0pOwp9CgpzdGF0aWMgaW5saW5lIGludCBjcnlwdG9fc2V0X2RyaXZlcl9uYW1lKHN0cnVjdCBjcnlwdG9fYWxnICphbGcpCnsKCXN0YXRpYyBjb25zdCBjaGFyIHN1ZmZpeFtdID0gIi1nZW5lcmljIjsKCWNoYXIgKmRyaXZlcl9uYW1lID0gKGNoYXIgKilhbGctPmNyYV9kcml2ZXJfbmFtZTsKCWludCBsZW47CgoJaWYgKCpkcml2ZXJfbmFtZSkKCQlyZXR1cm4gMDsKCglsZW4gPSBzdHJsY3B5KGRyaXZlcl9uYW1lLCBhbGctPmNyYV9uYW1lLCBDUllQVE9fTUFYX0FMR19OQU1FKTsKCWlmIChsZW4gKyBzaXplb2Yoc3VmZml4KSA+IENSWVBUT19NQVhfQUxHX05BTUUpCgkJcmV0dXJuIC1FTkFNRVRPT0xPTkc7CgoJbWVtY3B5KGRyaXZlcl9uYW1lICsgbGVuLCBzdWZmaXgsIHNpemVvZihzdWZmaXgpKTsKCXJldHVybiAwOwp9CgppbnQgY3J5cHRvX3JlZ2lzdGVyX2FsZyhzdHJ1Y3QgY3J5cHRvX2FsZyAqYWxnKQp7CglpbnQgcmV0OwoJc3RydWN0IGNyeXB0b19hbGcgKnE7CgoJaWYgKGFsZy0+Y3JhX2FsaWdubWFzayAmIChhbGctPmNyYV9hbGlnbm1hc2sgKyAxKSkKCQlyZXR1cm4gLUVJTlZBTDsKCglpZiAoYWxnLT5jcmFfYWxpZ25tYXNrICYgYWxnLT5jcmFfYmxvY2tzaXplKQoJCXJldHVybiAtRUlOVkFMOwoKCWlmIChhbGctPmNyYV9ibG9ja3NpemUgPiBQQUdFX1NJWkUgLyA4KQoJCXJldHVybiAtRUlOVkFMOwoKCWlmIChhbGctPmNyYV9wcmlvcml0eSA8IDApCgkJcmV0dXJuIC1FSU5WQUw7CgkKCXJldCA9IGNyeXB0b19zZXRfZHJpdmVyX25hbWUoYWxnKTsKCWlmICh1bmxpa2VseShyZXQpKQoJCXJldHVybiByZXQ7CgoJZG93bl93cml0ZSgmY3J5cHRvX2FsZ19zZW0pOwoJCglsaXN0X2Zvcl9lYWNoX2VudHJ5KHEsICZjcnlwdG9fYWxnX2xpc3QsIGNyYV9saXN0KSB7CgkJaWYgKCFzdHJjbXAocS0+Y3JhX2RyaXZlcl9uYW1lLCBhbGctPmNyYV9kcml2ZXJfbmFtZSkpIHsKCQkJcmV0ID0gLUVFWElTVDsKCQkJZ290byBvdXQ7CgkJfQoJfQoJCglsaXN0X2FkZF90YWlsKCZhbGctPmNyYV9saXN0LCAmY3J5cHRvX2FsZ19saXN0KTsKb3V0OgkKCXVwX3dyaXRlKCZjcnlwdG9fYWxnX3NlbSk7CglyZXR1cm4gcmV0Owp9CgppbnQgY3J5cHRvX3VucmVnaXN0ZXJfYWxnKHN0cnVjdCBjcnlwdG9fYWxnICphbGcpCnsKCWludCByZXQgPSAtRU5PRU5UOwoJc3RydWN0IGNyeXB0b19hbGcgKnE7CgkKCUJVR19PTighYWxnLT5jcmFfbW9kdWxlKTsKCQoJZG93bl93cml0ZSgmY3J5cHRvX2FsZ19zZW0pOwoJbGlzdF9mb3JfZWFjaF9lbnRyeShxLCAmY3J5cHRvX2FsZ19saXN0LCBjcmFfbGlzdCkgewoJCWlmIChhbGcgPT0gcSkgewoJCQlsaXN0X2RlbCgmYWxnLT5jcmFfbGlzdCk7CgkJCXJldCA9IDA7CgkJCWdvdG8gb3V0OwoJCX0KCX0Kb3V0OgkKCXVwX3dyaXRlKCZjcnlwdG9fYWxnX3NlbSk7CglyZXR1cm4gcmV0Owp9CgppbnQgY3J5cHRvX2FsZ19hdmFpbGFibGUoY29uc3QgY2hhciAqbmFtZSwgdTMyIGZsYWdzKQp7CglpbnQgcmV0ID0gMDsKCXN0cnVjdCBjcnlwdG9fYWxnICphbGcgPSBjcnlwdG9fYWxnX21vZF9sb29rdXAobmFtZSk7CgkKCWlmIChhbGcpIHsKCQljcnlwdG9fYWxnX3B1dChhbGcpOwoJCXJldCA9IDE7Cgl9CgkKCXJldHVybiByZXQ7Cn0KCnN0YXRpYyBpbnQgX19pbml0IGluaXRfY3J5cHRvKHZvaWQpCnsKCXByaW50ayhLRVJOX0lORk8gIkluaXRpYWxpemluZyBDcnlwdG9ncmFwaGljIEFQSVxuIik7CgljcnlwdG9faW5pdF9wcm9jKCk7CglyZXR1cm4gMDsKfQoKX19pbml0Y2FsbChpbml0X2NyeXB0byk7CgpFWFBPUlRfU1lNQk9MX0dQTChjcnlwdG9fcmVnaXN0ZXJfYWxnKTsKRVhQT1JUX1NZTUJPTF9HUEwoY3J5cHRvX3VucmVnaXN0ZXJfYWxnKTsKRVhQT1JUX1NZTUJPTF9HUEwoY3J5cHRvX2FsbG9jX3RmbSk7CkVYUE9SVF9TWU1CT0xfR1BMKGNyeXB0b19mcmVlX3RmbSk7CkVYUE9SVF9TWU1CT0xfR1BMKGNyeXB0b19hbGdfYXZhaWxhYmxlKTsK