LyoKICogUGVyZm9ybWFuY2UgZXZlbnRzIGNhbGxjaGFpbiBjb2RlLCBleHRyYWN0ZWQgZnJvbSBjb3JlLmM6CiAqCiAqICBDb3B5cmlnaHQgKEMpIDIwMDggVGhvbWFzIEdsZWl4bmVyIDx0Z2x4QGxpbnV0cm9uaXguZGU+CiAqICBDb3B5cmlnaHQgKEMpIDIwMDgtMjAxMSBSZWQgSGF0LCBJbmMuLCBJbmdvIE1vbG5hcgogKiAgQ29weXJpZ2h0IChDKSAyMDA4LTIwMTEgUmVkIEhhdCwgSW5jLiwgUGV0ZXIgWmlqbHN0cmEgPHB6aWpsc3RyQHJlZGhhdC5jb20+CiAqICBDb3B5cmlnaHQgIKkgIDIwMDkgUGF1bCBNYWNrZXJyYXMsIElCTSBDb3JwLiA8cGF1bHVzQGF1MS5pYm0uY29tPgogKgogKiBGb3IgbGljZW5zaW5nIGRldGFpbHMgc2VlIGtlcm5lbC1iYXNlL0NPUFlJTkcKICovCgojaW5jbHVkZSA8bGludXgvcGVyZl9ldmVudC5oPgojaW5jbHVkZSA8bGludXgvc2xhYi5oPgojaW5jbHVkZSAiaW50ZXJuYWwuaCIKCnN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzIHsKCXN0cnVjdCByY3VfaGVhZAkJCXJjdV9oZWFkOwoJc3RydWN0IHBlcmZfY2FsbGNoYWluX2VudHJ5CSpjcHVfZW50cmllc1swXTsKfTsKCnN0YXRpYyBERUZJTkVfUEVSX0NQVShpbnQsIGNhbGxjaGFpbl9yZWN1cnNpb25bUEVSRl9OUl9DT05URVhUU10pOwpzdGF0aWMgYXRvbWljX3QgbnJfY2FsbGNoYWluX2V2ZW50czsKc3RhdGljIERFRklORV9NVVRFWChjYWxsY2hhaW5fbXV0ZXgpOwpzdGF0aWMgc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMgKmNhbGxjaGFpbl9jcHVzX2VudHJpZXM7CgoKX193ZWFrIHZvaWQgcGVyZl9jYWxsY2hhaW5fa2VybmVsKHN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSAqZW50cnksCgkJCQkgIHN0cnVjdCBwdF9yZWdzICpyZWdzKQp7Cn0KCl9fd2VhayB2b2lkIHBlcmZfY2FsbGNoYWluX3VzZXIoc3RydWN0IHBlcmZfY2FsbGNoYWluX2VudHJ5ICplbnRyeSwKCQkJCXN0cnVjdCBwdF9yZWdzICpyZWdzKQp7Cn0KCnN0YXRpYyB2b2lkIHJlbGVhc2VfY2FsbGNoYWluX2J1ZmZlcnNfcmN1KHN0cnVjdCByY3VfaGVhZCAqaGVhZCkKewoJc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMgKmVudHJpZXM7CglpbnQgY3B1OwoKCWVudHJpZXMgPSBjb250YWluZXJfb2YoaGVhZCwgc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMsIHJjdV9oZWFkKTsKCglmb3JfZWFjaF9wb3NzaWJsZV9jcHUoY3B1KQoJCWtmcmVlKGVudHJpZXMtPmNwdV9lbnRyaWVzW2NwdV0pOwoKCWtmcmVlKGVudHJpZXMpOwp9CgpzdGF0aWMgdm9pZCByZWxlYXNlX2NhbGxjaGFpbl9idWZmZXJzKHZvaWQpCnsKCXN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzICplbnRyaWVzOwoKCWVudHJpZXMgPSBjYWxsY2hhaW5fY3B1c19lbnRyaWVzOwoJUkNVX0lOSVRfUE9JTlRFUihjYWxsY2hhaW5fY3B1c19lbnRyaWVzLCBOVUxMKTsKCWNhbGxfcmN1KCZlbnRyaWVzLT5yY3VfaGVhZCwgcmVsZWFzZV9jYWxsY2hhaW5fYnVmZmVyc19yY3UpOwp9CgpzdGF0aWMgaW50IGFsbG9jX2NhbGxjaGFpbl9idWZmZXJzKHZvaWQpCnsKCWludCBjcHU7CglpbnQgc2l6ZTsKCXN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzICplbnRyaWVzOwoKCS8qCgkgKiBXZSBjYW4ndCB1c2UgdGhlIHBlcmNwdSBhbGxvY2F0aW9uIEFQSSBmb3IgZGF0YSB0aGF0IGNhbiBiZQoJICogYWNjZXNzZWQgZnJvbSBOTUkuIFVzZSBhIHRlbXBvcmFyeSBtYW51YWwgcGVyIGNwdSBhbGxvY2F0aW9uCgkgKiB1bnRpbCB0aGF0IGdldHMgc29ydGVkIG91dC4KCSAqLwoJc2l6ZSA9IG9mZnNldG9mKHN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzLCBjcHVfZW50cmllc1tucl9jcHVfaWRzXSk7CgoJZW50cmllcyA9IGt6YWxsb2Moc2l6ZSwgR0ZQX0tFUk5FTCk7CglpZiAoIWVudHJpZXMpCgkJcmV0dXJuIC1FTk9NRU07CgoJc2l6ZSA9IHNpemVvZihzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnkpICogUEVSRl9OUl9DT05URVhUUzsKCglmb3JfZWFjaF9wb3NzaWJsZV9jcHUoY3B1KSB7CgkJZW50cmllcy0+Y3B1X2VudHJpZXNbY3B1XSA9IGttYWxsb2Nfbm9kZShzaXplLCBHRlBfS0VSTkVMLAoJCQkJCQkJIGNwdV90b19ub2RlKGNwdSkpOwoJCWlmICghZW50cmllcy0+Y3B1X2VudHJpZXNbY3B1XSkKCQkJZ290byBmYWlsOwoJfQoKCXJjdV9hc3NpZ25fcG9pbnRlcihjYWxsY2hhaW5fY3B1c19lbnRyaWVzLCBlbnRyaWVzKTsKCglyZXR1cm4gMDsKCmZhaWw6Cglmb3JfZWFjaF9wb3NzaWJsZV9jcHUoY3B1KQoJCWtmcmVlKGVudHJpZXMtPmNwdV9lbnRyaWVzW2NwdV0pOwoJa2ZyZWUoZW50cmllcyk7CgoJcmV0dXJuIC1FTk9NRU07Cn0KCmludCBnZXRfY2FsbGNoYWluX2J1ZmZlcnModm9pZCkKewoJaW50IGVyciA9IDA7CglpbnQgY291bnQ7CgoJbXV0ZXhfbG9jaygmY2FsbGNoYWluX211dGV4KTsKCgljb3VudCA9IGF0b21pY19pbmNfcmV0dXJuKCZucl9jYWxsY2hhaW5fZXZlbnRzKTsKCWlmIChXQVJOX09OX09OQ0UoY291bnQgPCAxKSkgewoJCWVyciA9IC1FSU5WQUw7CgkJZ290byBleGl0OwoJfQoKCWlmIChjb3VudCA+IDEpIHsKCQkvKiBJZiB0aGUgYWxsb2NhdGlvbiBmYWlsZWQsIGdpdmUgdXAgKi8KCQlpZiAoIWNhbGxjaGFpbl9jcHVzX2VudHJpZXMpCgkJCWVyciA9IC1FTk9NRU07CgkJZ290byBleGl0OwoJfQoKCWVyciA9IGFsbG9jX2NhbGxjaGFpbl9idWZmZXJzKCk7CmV4aXQ6CglpZiAoZXJyKQoJCWF0b21pY19kZWMoJm5yX2NhbGxjaGFpbl9ldmVudHMpOwoKCW11dGV4X3VubG9jaygmY2FsbGNoYWluX211dGV4KTsKCglyZXR1cm4gZXJyOwp9Cgp2b2lkIHB1dF9jYWxsY2hhaW5fYnVmZmVycyh2b2lkKQp7CglpZiAoYXRvbWljX2RlY19hbmRfbXV0ZXhfbG9jaygmbnJfY2FsbGNoYWluX2V2ZW50cywgJmNhbGxjaGFpbl9tdXRleCkpIHsKCQlyZWxlYXNlX2NhbGxjaGFpbl9idWZmZXJzKCk7CgkJbXV0ZXhfdW5sb2NrKCZjYWxsY2hhaW5fbXV0ZXgpOwoJfQp9CgpzdGF0aWMgc3RydWN0IHBlcmZfY2FsbGNoYWluX2VudHJ5ICpnZXRfY2FsbGNoYWluX2VudHJ5KGludCAqcmN0eCkKewoJaW50IGNwdTsKCXN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzICplbnRyaWVzOwoKCSpyY3R4ID0gZ2V0X3JlY3Vyc2lvbl9jb250ZXh0KHRoaXNfY3B1X3B0cihjYWxsY2hhaW5fcmVjdXJzaW9uKSk7CglpZiAoKnJjdHggPT0gLTEpCgkJcmV0dXJuIE5VTEw7CgoJZW50cmllcyA9IHJjdV9kZXJlZmVyZW5jZShjYWxsY2hhaW5fY3B1c19lbnRyaWVzKTsKCWlmICghZW50cmllcykKCQlyZXR1cm4gTlVMTDsKCgljcHUgPSBzbXBfcHJvY2Vzc29yX2lkKCk7CgoJcmV0dXJuICZlbnRyaWVzLT5jcHVfZW50cmllc1tjcHVdWypyY3R4XTsKfQoKc3RhdGljIHZvaWQKcHV0X2NhbGxjaGFpbl9lbnRyeShpbnQgcmN0eCkKewoJcHV0X3JlY3Vyc2lvbl9jb250ZXh0KHRoaXNfY3B1X3B0cihjYWxsY2hhaW5fcmVjdXJzaW9uKSwgcmN0eCk7Cn0KCnN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSAqCnBlcmZfY2FsbGNoYWluKHN0cnVjdCBwZXJmX2V2ZW50ICpldmVudCwgc3RydWN0IHB0X3JlZ3MgKnJlZ3MpCnsKCWludCByY3R4OwoJc3RydWN0IHBlcmZfY2FsbGNoYWluX2VudHJ5ICplbnRyeTsKCglpbnQga2VybmVsID0gIWV2ZW50LT5hdHRyLmV4Y2x1ZGVfY2FsbGNoYWluX2tlcm5lbDsKCWludCB1c2VyICAgPSAhZXZlbnQtPmF0dHIuZXhjbHVkZV9jYWxsY2hhaW5fdXNlcjsKCglpZiAoIWtlcm5lbCAmJiAhdXNlcikKCQlyZXR1cm4gTlVMTDsKCgllbnRyeSA9IGdldF9jYWxsY2hhaW5fZW50cnkoJnJjdHgpOwoJaWYgKHJjdHggPT0gLTEpCgkJcmV0dXJuIE5VTEw7CgoJaWYgKCFlbnRyeSkKCQlnb3RvIGV4aXRfcHV0OwoKCWVudHJ5LT5uciA9IDA7CgoJaWYgKGtlcm5lbCAmJiAhdXNlcl9tb2RlKHJlZ3MpKSB7CgkJcGVyZl9jYWxsY2hhaW5fc3RvcmUoZW50cnksIFBFUkZfQ09OVEVYVF9LRVJORUwpOwoJCXBlcmZfY2FsbGNoYWluX2tlcm5lbChlbnRyeSwgcmVncyk7Cgl9CgoJaWYgKHVzZXIpIHsKCQlpZiAoIXVzZXJfbW9kZShyZWdzKSkgewoJCQlpZiAgKGN1cnJlbnQtPm1tKQoJCQkJcmVncyA9IHRhc2tfcHRfcmVncyhjdXJyZW50KTsKCQkJZWxzZQoJCQkJcmVncyA9IE5VTEw7CgkJfQoKCQlpZiAocmVncykgewoJCQkvKgoJCQkgKiBEaXNhbGxvdyBjcm9zcy10YXNrIHVzZXIgY2FsbGNoYWlucy4KCQkJICovCgkJCWlmIChldmVudC0+Y3R4LT50YXNrICYmIGV2ZW50LT5jdHgtPnRhc2sgIT0gY3VycmVudCkKCQkJCWdvdG8gZXhpdF9wdXQ7CgoJCQlwZXJmX2NhbGxjaGFpbl9zdG9yZShlbnRyeSwgUEVSRl9DT05URVhUX1VTRVIpOwoJCQlwZXJmX2NhbGxjaGFpbl91c2VyKGVudHJ5LCByZWdzKTsKCQl9Cgl9CgpleGl0X3B1dDoKCXB1dF9jYWxsY2hhaW5fZW50cnkocmN0eCk7CgoJcmV0dXJuIGVudHJ5Owp9Cg==