LyoKICogU2NhdHRlcmxpc3QgQ3J5cHRvZ3JhcGhpYyBBUEkuCiAqCiAqIENvcHlyaWdodCAoYykgMjAwMiBKYW1lcyBNb3JyaXMgPGptb3JyaXNAaW50ZXJjb2RlLmNvbS5hdT4KICogQ29weXJpZ2h0IChjKSAyMDAyIERhdmlkIFMuIE1pbGxlciAoZGF2ZW1AcmVkaGF0LmNvbSkKICogQ29weXJpZ2h0IChjKSAyMDA1IEhlcmJlcnQgWHUgPGhlcmJlcnRAZ29uZG9yLmFwYW5hLm9yZy5hdT4KICoKICogUG9ydGlvbnMgZGVyaXZlZCBmcm9tIENyeXB0b2FwaSwgYnkgQWxleGFuZGVyIEtqZWxkYWFzIDxhc3RvckBmYXN0Lm5vPgogKiBhbmQgTmV0dGxlLCBieSBOaWVscyBN9mxsZXIuCiAqCiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0CiAqIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlCiAqIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgCiAqIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKi8KCiNpbmNsdWRlIDxsaW51eC9jb21waWxlci5oPgojaW5jbHVkZSA8bGludXgvaW5pdC5oPgojaW5jbHVkZSA8bGludXgvY3J5cHRvLmg+CiNpbmNsdWRlIDxsaW51eC9lcnJuby5oPgojaW5jbHVkZSA8bGludXgva2VybmVsLmg+CiNpbmNsdWRlIDxsaW51eC9rbW9kLmg+CiNpbmNsdWRlIDxsaW51eC9yd3NlbS5oPgojaW5jbHVkZSA8bGludXgvc2xhYi5oPgojaW5jbHVkZSA8bGludXgvc3RyaW5nLmg+CiNpbmNsdWRlICJpbnRlcm5hbC5oIgoKTElTVF9IRUFEKGNyeXB0b19hbGdfbGlzdCk7CkRFQ0xBUkVfUldTRU0oY3J5cHRvX2FsZ19zZW0pOwoKc3RhdGljIGlubGluZSBzdHJ1Y3QgY3J5cHRvX2FsZyAqY3J5cHRvX2FsZ19nZXQoc3RydWN0IGNyeXB0b19hbGcgKmFsZykKewoJYXRvbWljX2luYygmYWxnLT5jcmFfcmVmY250KTsKCXJldHVybiBhbGc7Cn0KCnN0YXRpYyBpbmxpbmUgdm9pZCBjcnlwdG9fYWxnX3B1dChzdHJ1Y3QgY3J5cHRvX2FsZyAqYWxnKQp7CglpZiAoYXRvbWljX2RlY19hbmRfdGVzdCgmYWxnLT5jcmFfcmVmY250KSAmJiBhbGctPmNyYV9kZXN0cm95KQoJCWFsZy0+Y3JhX2Rlc3Ryb3koYWxnKTsKfQoKc3RhdGljIHN0cnVjdCBjcnlwdG9fYWxnICpjcnlwdG9fbW9kX2dldChzdHJ1Y3QgY3J5cHRvX2FsZyAqYWxnKQp7CglyZXR1cm4gdHJ5X21vZHVsZV9nZXQoYWxnLT5jcmFfbW9kdWxlKSA/IGNyeXB0b19hbGdfZ2V0KGFsZykgOiBOVUxMOwp9CgpzdGF0aWMgdm9pZCBjcnlwdG9fbW9kX3B1dChzdHJ1Y3QgY3J5cHRvX2FsZyAqYWxnKQp7CgljcnlwdG9fYWxnX3B1dChhbGcpOwoJbW9kdWxlX3B1dChhbGctPmNyYV9tb2R1bGUpOwp9CgpzdGF0aWMgc3RydWN0IGNyeXB0b19hbGcgKmNyeXB0b19hbGdfbG9va3VwKGNvbnN0IGNoYXIgKm5hbWUpCnsKCXN0cnVjdCBjcnlwdG9fYWxnICpxLCAqYWxnID0gTlVMTDsKCWludCBiZXN0ID0gLTE7CgoJaWYgKCFuYW1lKQoJCXJldHVybiBOVUxMOwoJCglkb3duX3JlYWQoJmNyeXB0b19hbGdfc2VtKTsKCQoJbGlzdF9mb3JfZWFjaF9lbnRyeShxLCAmY3J5cHRvX2FsZ19saXN0LCBjcmFfbGlzdCkgewoJCWludCBleGFjdCwgZnV6enk7CgoJCWV4YWN0ID0gIXN0cmNtcChxLT5jcmFfZHJpdmVyX25hbWUsIG5hbWUpOwoJCWZ1enp5ID0gIXN0cmNtcChxLT5jcmFfbmFtZSwgbmFtZSk7CgkJaWYgKCFleGFjdCAmJiAhKGZ1enp5ICYmIHEtPmNyYV9wcmlvcml0eSA+IGJlc3QpKQoJCQljb250aW51ZTsKCgkJaWYgKHVubGlrZWx5KCFjcnlwdG9fbW9kX2dldChxKSkpCgkJCWNvbnRpbnVlOwoKCQliZXN0ID0gcS0+Y3JhX3ByaW9yaXR5OwoJCWlmIChhbGcpCgkJCWNyeXB0b19tb2RfcHV0KGFsZyk7CgkJYWxnID0gcTsKCgkJaWYgKGV4YWN0KQoJCQlicmVhazsKCX0KCQoJdXBfcmVhZCgmY3J5cHRvX2FsZ19zZW0pOwoJcmV0dXJuIGFsZzsKfQoKLyogQSBmYXIgbW9yZSBpbnRlbGxpZ2VudCB2ZXJzaW9uIG9mIHRoaXMgaXMgcGxhbm5lZC4gIEZvciBub3csIGp1c3QKICogdHJ5IGFuIGV4YWN0IG1hdGNoIG9uIHRoZSBuYW1lIG9mIHRoZSBhbGdvcml0aG0uICovCnN0YXRpYyBpbmxpbmUgc3RydWN0IGNyeXB0b19hbGcgKmNyeXB0b19hbGdfbW9kX2xvb2t1cChjb25zdCBjaGFyICpuYW1lKQp7CglyZXR1cm4gdHJ5X3RoZW5fcmVxdWVzdF9tb2R1bGUoY3J5cHRvX2FsZ19sb29rdXAobmFtZSksIG5hbWUpOwp9CgpzdGF0aWMgaW50IGNyeXB0b19pbml0X2ZsYWdzKHN0cnVjdCBjcnlwdG9fdGZtICp0Zm0sIHUzMiBmbGFncykKewoJdGZtLT5jcnRfZmxhZ3MgPSBmbGFncyAmIENSWVBUT19URk1fUkVRX01BU0s7CglmbGFncyAmPSB+Q1JZUFRPX1RGTV9SRVFfTUFTSzsKCQoJc3dpdGNoIChjcnlwdG9fdGZtX2FsZ190eXBlKHRmbSkpIHsKCWNhc2UgQ1JZUFRPX0FMR19UWVBFX0NJUEhFUjoKCQlyZXR1cm4gY3J5cHRvX2luaXRfY2lwaGVyX2ZsYWdzKHRmbSwgZmxhZ3MpOwoJCQoJY2FzZSBDUllQVE9fQUxHX1RZUEVfRElHRVNUOgoJCXJldHVybiBjcnlwdG9faW5pdF9kaWdlc3RfZmxhZ3ModGZtLCBmbGFncyk7CgkJCgljYXNlIENSWVBUT19BTEdfVFlQRV9DT01QUkVTUzoKCQlyZXR1cm4gY3J5cHRvX2luaXRfY29tcHJlc3NfZmxhZ3ModGZtLCBmbGFncyk7CgkKCWRlZmF1bHQ6CgkJYnJlYWs7Cgl9CgkKCUJVRygpOwoJcmV0dXJuIC1FSU5WQUw7Cn0KCnN0YXRpYyBpbnQgY3J5cHRvX2luaXRfb3BzKHN0cnVjdCBjcnlwdG9fdGZtICp0Zm0pCnsKCXN3aXRjaCAoY3J5cHRvX3RmbV9hbGdfdHlwZSh0Zm0pKSB7CgljYXNlIENSWVBUT19BTEdfVFlQRV9DSVBIRVI6CgkJcmV0dXJuIGNyeXB0b19pbml0X2NpcGhlcl9vcHModGZtKTsKCQkKCWNhc2UgQ1JZUFRPX0FMR19UWVBFX0RJR0VTVDoKCQlyZXR1cm4gY3J5cHRvX2luaXRfZGlnZXN0X29wcyh0Zm0pOwoJCQoJY2FzZSBDUllQVE9fQUxHX1RZUEVfQ09NUFJFU1M6CgkJcmV0dXJuIGNyeXB0b19pbml0X2NvbXByZXNzX29wcyh0Zm0pOwoJCglkZWZhdWx0OgoJCWJyZWFrOwoJfQoJCglCVUcoKTsKCXJldHVybiAtRUlOVkFMOwp9CgpzdGF0aWMgdm9pZCBjcnlwdG9fZXhpdF9vcHMoc3RydWN0IGNyeXB0b190Zm0gKnRmbSkKewoJc3dpdGNoIChjcnlwdG9fdGZtX2FsZ190eXBlKHRmbSkpIHsKCWNhc2UgQ1JZUFRPX0FMR19UWVBFX0NJUEhFUjoKCQljcnlwdG9fZXhpdF9jaXBoZXJfb3BzKHRmbSk7CgkJYnJlYWs7CgkJCgljYXNlIENSWVBUT19BTEdfVFlQRV9ESUdFU1Q6CgkJY3J5cHRvX2V4aXRfZGlnZXN0X29wcyh0Zm0pOwoJCWJyZWFrOwoJCQoJY2FzZSBDUllQVE9fQUxHX1RZUEVfQ09NUFJFU1M6CgkJY3J5cHRvX2V4aXRfY29tcHJlc3Nfb3BzKHRmbSk7CgkJYnJlYWs7CgkKCWRlZmF1bHQ6CgkJQlVHKCk7CgkJCgl9Cn0KCnN0YXRpYyB1bnNpZ25lZCBpbnQgY3J5cHRvX2N0eHNpemUoc3RydWN0IGNyeXB0b19hbGcgKmFsZywgaW50IGZsYWdzKQp7Cgl1bnNpZ25lZCBpbnQgbGVuOwoKCXN3aXRjaCAoYWxnLT5jcmFfZmxhZ3MgJiBDUllQVE9fQUxHX1RZUEVfTUFTSykgewoJZGVmYXVsdDoKCQlCVUcoKTsKCgljYXNlIENSWVBUT19BTEdfVFlQRV9DSVBIRVI6CgkJbGVuID0gY3J5cHRvX2NpcGhlcl9jdHhzaXplKGFsZywgZmxhZ3MpOwoJCWJyZWFrOwoJCQoJY2FzZSBDUllQVE9fQUxHX1RZUEVfRElHRVNUOgoJCWxlbiA9IGNyeXB0b19kaWdlc3RfY3R4c2l6ZShhbGcsIGZsYWdzKTsKCQlicmVhazsKCQkKCWNhc2UgQ1JZUFRPX0FMR19UWVBFX0NPTVBSRVNTOgoJCWxlbiA9IGNyeXB0b19jb21wcmVzc19jdHhzaXplKGFsZywgZmxhZ3MpOwoJCWJyZWFrOwoJfQoKCXJldHVybiBsZW4gKyAoYWxnLT5jcmFfYWxpZ25tYXNrICYgfihjcnlwdG9fdGZtX2N0eF9hbGlnbm1lbnQoKSAtIDEpKTsKfQoKc3RydWN0IGNyeXB0b190Zm0gKmNyeXB0b19hbGxvY190Zm0oY29uc3QgY2hhciAqbmFtZSwgdTMyIGZsYWdzKQp7CglzdHJ1Y3QgY3J5cHRvX3RmbSAqdGZtID0gTlVMTDsKCXN0cnVjdCBjcnlwdG9fYWxnICphbGc7Cgl1bnNpZ25lZCBpbnQgdGZtX3NpemU7CgoJYWxnID0gY3J5cHRvX2FsZ19tb2RfbG9va3VwKG5hbWUpOwoJaWYgKGFsZyA9PSBOVUxMKQoJCWdvdG8gb3V0OwoKCXRmbV9zaXplID0gc2l6ZW9mKCp0Zm0pICsgY3J5cHRvX2N0eHNpemUoYWxnLCBmbGFncyk7Cgl0Zm0gPSBremFsbG9jKHRmbV9zaXplLCBHRlBfS0VSTkVMKTsKCWlmICh0Zm0gPT0gTlVMTCkKCQlnb3RvIG91dF9wdXQ7CgoJdGZtLT5fX2NydF9hbGcgPSBhbGc7CgkKCWlmIChjcnlwdG9faW5pdF9mbGFncyh0Zm0sIGZsYWdzKSkKCQlnb3RvIG91dF9mcmVlX3RmbTsKCQkKCWlmIChjcnlwdG9faW5pdF9vcHModGZtKSkKCQlnb3RvIG91dF9mcmVlX3RmbTsKCglpZiAoYWxnLT5jcmFfaW5pdCAmJiBhbGctPmNyYV9pbml0KHRmbSkpCgkJZ290byBjcmFfaW5pdF9mYWlsZWQ7CgoJZ290byBvdXQ7CgpjcmFfaW5pdF9mYWlsZWQ6CgljcnlwdG9fZXhpdF9vcHModGZtKTsKb3V0X2ZyZWVfdGZtOgoJa2ZyZWUodGZtKTsKCXRmbSA9IE5VTEw7Cm91dF9wdXQ6CgljcnlwdG9fbW9kX3B1dChhbGcpOwpvdXQ6CglyZXR1cm4gdGZtOwp9Cgp2b2lkIGNyeXB0b19mcmVlX3RmbShzdHJ1Y3QgY3J5cHRvX3RmbSAqdGZtKQp7CglzdHJ1Y3QgY3J5cHRvX2FsZyAqYWxnOwoJaW50IHNpemU7CgoJaWYgKHVubGlrZWx5KCF0Zm0pKQoJCXJldHVybjsKCglhbGcgPSB0Zm0tPl9fY3J0X2FsZzsKCXNpemUgPSBzaXplb2YoKnRmbSkgKyBhbGctPmNyYV9jdHhzaXplOwoKCWlmIChhbGctPmNyYV9leGl0KQoJCWFsZy0+Y3JhX2V4aXQodGZtKTsKCWNyeXB0b19leGl0X29wcyh0Zm0pOwoJY3J5cHRvX21vZF9wdXQoYWxnKTsKCW1lbXNldCh0Zm0sIDAsIHNpemUpOwoJa2ZyZWUodGZtKTsKfQoKc3RhdGljIGlubGluZSBpbnQgY3J5cHRvX3NldF9kcml2ZXJfbmFtZShzdHJ1Y3QgY3J5cHRvX2FsZyAqYWxnKQp7CglzdGF0aWMgY29uc3QgY2hhciBzdWZmaXhbXSA9ICItZ2VuZXJpYyI7CgljaGFyICpkcml2ZXJfbmFtZSA9IGFsZy0+Y3JhX2RyaXZlcl9uYW1lOwoJaW50IGxlbjsKCglpZiAoKmRyaXZlcl9uYW1lKQoJCXJldHVybiAwOwoKCWxlbiA9IHN0cmxjcHkoZHJpdmVyX25hbWUsIGFsZy0+Y3JhX25hbWUsIENSWVBUT19NQVhfQUxHX05BTUUpOwoJaWYgKGxlbiArIHNpemVvZihzdWZmaXgpID4gQ1JZUFRPX01BWF9BTEdfTkFNRSkKCQlyZXR1cm4gLUVOQU1FVE9PTE9ORzsKCgltZW1jcHkoZHJpdmVyX25hbWUgKyBsZW4sIHN1ZmZpeCwgc2l6ZW9mKHN1ZmZpeCkpOwoJcmV0dXJuIDA7Cn0KCmludCBjcnlwdG9fcmVnaXN0ZXJfYWxnKHN0cnVjdCBjcnlwdG9fYWxnICphbGcpCnsKCWludCByZXQ7CglzdHJ1Y3QgY3J5cHRvX2FsZyAqcTsKCglpZiAoYWxnLT5jcmFfYWxpZ25tYXNrICYgKGFsZy0+Y3JhX2FsaWdubWFzayArIDEpKQoJCXJldHVybiAtRUlOVkFMOwoKCWlmIChhbGctPmNyYV9hbGlnbm1hc2sgJiBhbGctPmNyYV9ibG9ja3NpemUpCgkJcmV0dXJuIC1FSU5WQUw7CgoJaWYgKGFsZy0+Y3JhX2Jsb2Nrc2l6ZSA+IFBBR0VfU0laRSAvIDgpCgkJcmV0dXJuIC1FSU5WQUw7CgoJaWYgKGFsZy0+Y3JhX3ByaW9yaXR5IDwgMCkKCQlyZXR1cm4gLUVJTlZBTDsKCQoJcmV0ID0gY3J5cHRvX3NldF9kcml2ZXJfbmFtZShhbGcpOwoJaWYgKHVubGlrZWx5KHJldCkpCgkJcmV0dXJuIHJldDsKCglkb3duX3dyaXRlKCZjcnlwdG9fYWxnX3NlbSk7CgkKCWxpc3RfZm9yX2VhY2hfZW50cnkocSwgJmNyeXB0b19hbGdfbGlzdCwgY3JhX2xpc3QpIHsKCQlpZiAocSA9PSBhbGcpIHsKCQkJcmV0ID0gLUVFWElTVDsKCQkJZ290byBvdXQ7CgkJfQoJfQoJCglsaXN0X2FkZCgmYWxnLT5jcmFfbGlzdCwgJmNyeXB0b19hbGdfbGlzdCk7CglhdG9taWNfc2V0KCZhbGctPmNyYV9yZWZjbnQsIDEpOwpvdXQ6CQoJdXBfd3JpdGUoJmNyeXB0b19hbGdfc2VtKTsKCXJldHVybiByZXQ7Cn0KCmludCBjcnlwdG9fdW5yZWdpc3Rlcl9hbGcoc3RydWN0IGNyeXB0b19hbGcgKmFsZykKewoJaW50IHJldCA9IC1FTk9FTlQ7CglzdHJ1Y3QgY3J5cHRvX2FsZyAqcTsKCQoJZG93bl93cml0ZSgmY3J5cHRvX2FsZ19zZW0pOwoJbGlzdF9mb3JfZWFjaF9lbnRyeShxLCAmY3J5cHRvX2FsZ19saXN0LCBjcmFfbGlzdCkgewoJCWlmIChhbGcgPT0gcSkgewoJCQlsaXN0X2RlbCgmYWxnLT5jcmFfbGlzdCk7CgkJCXJldCA9IDA7CgkJCWdvdG8gb3V0OwoJCX0KCX0Kb3V0OgkKCXVwX3dyaXRlKCZjcnlwdG9fYWxnX3NlbSk7CgoJaWYgKHJldCkKCQlyZXR1cm4gcmV0OwoKCUJVR19PTihhdG9taWNfcmVhZCgmYWxnLT5jcmFfcmVmY250KSAhPSAxKTsKCWlmIChhbGctPmNyYV9kZXN0cm95KQoJCWFsZy0+Y3JhX2Rlc3Ryb3koYWxnKTsKCglyZXR1cm4gMDsKfQoKaW50IGNyeXB0b19hbGdfYXZhaWxhYmxlKGNvbnN0IGNoYXIgKm5hbWUsIHUzMiBmbGFncykKewoJaW50IHJldCA9IDA7CglzdHJ1Y3QgY3J5cHRvX2FsZyAqYWxnID0gY3J5cHRvX2FsZ19tb2RfbG9va3VwKG5hbWUpOwoJCglpZiAoYWxnKSB7CgkJY3J5cHRvX21vZF9wdXQoYWxnKTsKCQlyZXQgPSAxOwoJfQoJCglyZXR1cm4gcmV0Owp9CgpzdGF0aWMgaW50IF9faW5pdCBpbml0X2NyeXB0byh2b2lkKQp7CglwcmludGsoS0VSTl9JTkZPICJJbml0aWFsaXppbmcgQ3J5cHRvZ3JhcGhpYyBBUElcbiIpOwoJY3J5cHRvX2luaXRfcHJvYygpOwoJcmV0dXJuIDA7Cn0KCl9faW5pdGNhbGwoaW5pdF9jcnlwdG8pOwoKRVhQT1JUX1NZTUJPTF9HUEwoY3J5cHRvX3JlZ2lzdGVyX2FsZyk7CkVYUE9SVF9TWU1CT0xfR1BMKGNyeXB0b191bnJlZ2lzdGVyX2FsZyk7CkVYUE9SVF9TWU1CT0xfR1BMKGNyeXB0b19hbGxvY190Zm0pOwpFWFBPUlRfU1lNQk9MX0dQTChjcnlwdG9fZnJlZV90Zm0pOwpFWFBPUlRfU1lNQk9MX0dQTChjcnlwdG9fYWxnX2F2YWlsYWJsZSk7Cg==