LyoKICogZHJpdmVycy9pbnB1dC9taXNjL2FtYmFyZWxsYV9pcl9wYW5hc29uaWMuYwogKgogKiBIaXN0b3J5OgogKiAgICAgIDIwMDcvMDMvMjggLSBbRHJhZ29uIENoaWFuZ10gY3JlYXRlZCBmaWxlCiAqCTIwMDkvMDMvMTAgLSBbQW50aG9ueSBHaW5nZXJdIFBvcnQgdG8gMi42LjI4CiAqCiAqIENvcHlyaWdodCAoQykgMjAwNC0yMDA5LCBBbWJhcmVsbGEsIEluYy4KICoKICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkKICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkKICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUKICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKICogYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKICogRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgMDIxMTEtMTMwNyBVU0EKICoKICovCgojaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CiNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1cHQuaD4KCiNpbmNsdWRlIDxwbGF0L2FtYmlucHV0Lmg+CgovKioKICogUHVsc2UtV2lkdGgtQ29kZWQgU2lnbmFscyB2YXJ5IHRoZSBsZW5ndGggb2YgcHVsc2VzIHRvIGNvZGUgdGhlIGluZm9ybWF0aW9uLgogKiBJbiB0aGlzIGNhc2UgaWYgdGhlIHB1bHNlIHdpZHRoIGlzIHNob3J0IChhcHByb3hpbWF0ZWx5IDU1MHVzKSBpdAogKiBjb3JyZXNwb25kcyB0byBhIGxvZ2ljYWwgemVybyBvciBhIGxvdy4gSWYgdGhlIHB1bHNlIHdpZHRoIGlzIGxvbmcKICogKGFwcHJveGltYXRlbHkgMjIwMHVzKSBpdCBjb3JyZXNwb25kcyB0byBhIGxvZ2ljYWwgb25lIG9yIGEgaGlnaC4KICoKICogICAgICAgICArLS0rICArLS0rICArLS0tLSsgICstLS0tKwogKiAgICAgICAgIHwgIHwgIHwgIHwgIHwgICAgfCAgfCAgICB8CiAqICAgICAgLS0tKyAgKy0tKyAgKy0tKyAgICArLS0rICAgICstLS0KICogICAgICAgICAgMCAgICAgMCAgICAgIDEgICAgICAgMQogKi8KCiNkZWZpbmUgUEFOQVNPTklDX0RFRkFVTFRfRlJFUVVFTkNZCTM4MDAwCS8qIDM4S0h6ICovCgovKiBUID0gNDIwIKNncyB0byBhcHByb3ggNDI0IKNncyBpbiB0aGUgVVNBIGFuZCBDYW5hZGEgKi8KLyogVCA9IDQ1NCCjZ3MgdG8gYXBwcm94IDQ2MCCjZ3MgaW4gRXVyb3BlIGFuZCBvdGhlcnMgICovCiNkZWZpbmUgUEFOQVNPTklDX0RFRkFVTFRfU01BTExFUl9USU1FCTQ1NAkvKiBULCA0NTAgbWljcm9zZWNvbmRzLiAqLwoKLyoqIGJpdCAwCiAqICAgICAgICAgKy0tLS0rICAgICstLS0KICogICAgICAgICB8ICAgIHwgICAgfAogKiAgICAgIC0tLSsgICAgKy0tLS0rCiAqICAgICAgICAgICAyVCAgIDJUCiAqLwoKLyoqIGJpdCAxCiAqICAgICAgICAgKy0tLS0rICAgICAgICAgICAgKy0tLQogKiAgICAgICAgIHwgICAgfCAgICAgICAgICAgIHwKICogICAgICAtLS0rICAgICstLS0tLS0tLS0tLS0rCiAqICAgICAgICAgICAyVCAgICAgICA2VAogKi8KCi8qKiBzdGFydAogKiAgICAgICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsgICAgICAgICAgICAgICAgKy0tLQogKiAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgfAogKiAgICAgIC0tLSsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICstLS0tLS0tLS0tLS0tLS0tKwogKiAgICAgICAgICAgICAgICAgICAgICAgICAxNlQgICAgICAgICAgICAgICAgICAgICAgOFQKICovCgojZGVmaW5lIFBBTkFTT05JQ19MRUFERVJfSElHSF9VUEJPVU5ECTUwCiNkZWZpbmUgUEFOQVNPTklDX0xFQURFUl9ISUdIX0xPV0JPVU5ECTQyCiNkZWZpbmUgUEFOQVNPTklDX0xFQURFUl9MT1dfVVBCT1VORAkyNgojZGVmaW5lIFBBTkFTT05JQ19MRUFERVJfTE9XX0xPV0JPVU5ECTE4CgojZGVmaW5lIFBBTkFTT05JQ19EQVRBX0hJR0hfVVBCT1VORAk5CiNkZWZpbmUgUEFOQVNPTklDX0RBVEFfSElHSF9MT1dCT1VORAkxCiNkZWZpbmUgUEFOQVNPTklDX0RBVEFfMF9MT1dfVVBCT1VORAk5CiNkZWZpbmUgUEFOQVNPTklDX0RBVEFfMF9MT1dfTE9XQk9VTkQJMQojZGVmaW5lIFBBTkFTT05JQ19EQVRBXzFfTE9XX1VQQk9VTkQJMjAKI2RlZmluZSBQQU5BU09OSUNfREFUQV8xX0xPV19MT1dCT1VORAkxMgoKc3RhdGljIGludCBhbWJhcmVsbGFfaXJfcGFuYXNvbmljX3B1bHNlX2xlYWRlcl9jb2RlKHN0cnVjdCBhbWJhcmVsbGFfaXJfaW5mbyAqcGluZm8pCnsKCXUxNiB2YWwgPSBhbWJhcmVsbGFfaXJfcmVhZF9kYXRhKHBpbmZvLCBwaW5mby0+aXJfcHJlYWQpOwoKCWlmICgodmFsIDwgUEFOQVNPTklDX0xFQURFUl9ISUdIX1VQQk9VTkQpICAmJgoJICAgICh2YWwgPiBQQU5BU09OSUNfTEVBREVSX0hJR0hfTE9XQk9VTkQpKSB7Cgl9IGVsc2UgewoJCXJldHVybiAwOwoJfQoKCWlmICgocGluZm8tPmlyX3ByZWFkICsgMSkgPj0gTUFYX0lSX0JVRkZFUikgewoJCXZhbCA9IGFtYmFyZWxsYV9pcl9yZWFkX2RhdGEocGluZm8sIDApOwoJfSBlbHNlIHsKCQl2YWwgPSBhbWJhcmVsbGFfaXJfcmVhZF9kYXRhKHBpbmZvLCBwaW5mby0+aXJfcHJlYWQgKyAxKTsKCX0KCglpZiAoKHZhbCA8IFBBTkFTT05JQ19MRUFERVJfTE9XX1VQQk9VTkQpICYmCgkgICAgKHZhbCA+IFBBTkFTT05JQ19MRUFERVJfTE9XX0xPV0JPVU5EKSApCgkJcmV0dXJuIDE7CgllbHNlCgkJcmV0dXJuIDA7Cn0KCnN0YXRpYyBpbnQgYW1iYXJlbGxhX2lyX3BhbmFzb25pY19maW5kX2hlYWQoc3RydWN0IGFtYmFyZWxsYV9pcl9pbmZvICpwaW5mbykKewoJaW50IGksIHZhbCA9IDA7CgoJaSA9IGFtYmFyZWxsYV9pcl9nZXRfdGlja19zaXplKHBpbmZvKSAtIHBpbmZvLT5mcmFtZV9pbmZvLmZyYW1lX2hlYWRfc2l6ZSArIDE7CgoJd2hpbGUoaS0tKSB7CgkJaWYoYW1iYXJlbGxhX2lyX3BhbmFzb25pY19wdWxzZV9sZWFkZXJfY29kZShwaW5mbykpIHsKCQkJZGV2X2RiZygmcGluZm8tPnBpbnB1dF9kZXYtPmRldiwgImZpbmQgbGVhZGVyIGNvZGUsIGkgWyVkXVxuIiwgaSk7CgkJCXZhbCA9IDE7CgkJCWJyZWFrOwoJCX0gZWxzZSB7CgkJCWRldl9kYmcoJnBpbmZvLT5waW5wdXRfZGV2LT5kZXYsICJkaWRuJ3QgIGZpbmQgbGVhZGVyIGNvZGUsIGkgWyVkXVxuIiwgaSk7CgkJCWFtYmFyZWxsYV9pcl9tb3ZlX3JlYWRfcHRyKHBpbmZvLCAxKTsKCQl9Cgl9CgoJcmV0dXJuIHZhbCA7Cn0KCnN0YXRpYyBpbnQgYW1iYXJlbGxhX2lyX3BhbmFzb25pY19wdWxzZV9jb2RlXzAoc3RydWN0IGFtYmFyZWxsYV9pcl9pbmZvICpwaW5mbykKewoJdTE2IHZhbCA9IGFtYmFyZWxsYV9pcl9yZWFkX2RhdGEocGluZm8sIHBpbmZvLT5pcl9wcmVhZCk7CglpZiAoKHZhbCA8IFBBTkFTT05JQ19EQVRBX0hJR0hfVVBCT1VORCkgICYmCgkgICAgKHZhbCA+IFBBTkFTT05JQ19EQVRBX0hJR0hfTE9XQk9VTkQpKSB7Cgl9IGVsc2UgewoJCXJldHVybiAwOwoJfQoKCWlmICgocGluZm8tPmlyX3ByZWFkICsgMSkgPj0gTUFYX0lSX0JVRkZFUikgewoJCXZhbCA9IGFtYmFyZWxsYV9pcl9yZWFkX2RhdGEocGluZm8sIDApOwoJfSBlbHNlIHsKCQl2YWwgPSBhbWJhcmVsbGFfaXJfcmVhZF9kYXRhKHBpbmZvLCBwaW5mby0+aXJfcHJlYWQgKyAxKTsKCX0KCglpZiAoKHZhbCA8IFBBTkFTT05JQ19EQVRBXzBfTE9XX1VQQk9VTkQpICYmCgkgICAgKHZhbCA+IFBBTkFTT05JQ19EQVRBXzBfTE9XX0xPV0JPVU5EKSApCgkJcmV0dXJuIDE7CgllbHNlCgkJcmV0dXJuIDA7Cn0KCnN0YXRpYyBpbnQgYW1iYXJlbGxhX2lyX3BhbmFzb25pY19wdWxzZV9jb2RlXzEoc3RydWN0IGFtYmFyZWxsYV9pcl9pbmZvICpwaW5mbykKewoJdTE2IHZhbCA9IGFtYmFyZWxsYV9pcl9yZWFkX2RhdGEocGluZm8sIHBpbmZvLT5pcl9wcmVhZCk7CgoJaWYgKCh2YWwgPCBQQU5BU09OSUNfREFUQV9ISUdIX1VQQk9VTkQpICAmJgoJICAgICh2YWwgPiBQQU5BU09OSUNfREFUQV9ISUdIX0xPV0JPVU5EKSkgewoJfSBlbHNlIHsKCQlyZXR1cm4gMDsKCX0KCglpZiAoKHBpbmZvLT5pcl9wcmVhZCArIDEpID49IE1BWF9JUl9CVUZGRVIpIHsKCQl2YWwgPSBhbWJhcmVsbGFfaXJfcmVhZF9kYXRhKHBpbmZvLCAwKTsKCX0gZWxzZSB7CgkJdmFsID0gYW1iYXJlbGxhX2lyX3JlYWRfZGF0YShwaW5mbywgcGluZm8tPmlyX3ByZWFkICsgMSk7Cgl9CgoJaWYgKCh2YWwgPCBQQU5BU09OSUNfREFUQV8xX0xPV19VUEJPVU5EKSAmJgoJICAgICh2YWwgPiBQQU5BU09OSUNfREFUQV8xX0xPV19MT1dCT1VORCkgKQoJCXJldHVybiAxOwoJZWxzZQoJCXJldHVybiAwOwp9CgpzdGF0aWMgaW50IGFtYmFyZWxsYV9pcl9wYW5hc29uaWNfcHVsc2VfZGF0YV90cmFuc2xhdGUoc3RydWN0IGFtYmFyZWxsYV9pcl9pbmZvICpwaW5mbywgdTggKiBkYXRhKQp7CglpbnQgaTsKCgkqZGF0YSA9IDA7CgoJZm9yIChpID0gNzsgaSA+PSAwOyBpLS0pIHsKCQlpZiAoYW1iYXJlbGxhX2lyX3BhbmFzb25pY19wdWxzZV9jb2RlXzAocGluZm8pKSB7CgoJCX0gZWxzZSBpZiAoYW1iYXJlbGxhX2lyX3BhbmFzb25pY19wdWxzZV9jb2RlXzEocGluZm8pKSB7CgkJCSpkYXRhIHw9IDEgPDwgaTsKCQl9IGVsc2UgewoJCQlkZXZfZGJnKCZwaW5mby0+cGlucHV0X2Rldi0+ZGV2LCAiJWQgRVJST1IsIHRoZSB3YXZlZm9ybSBjYW4ndCBtYXRjaCIsCgkJCQkgIHBpbmZvLT5pcl9wcmVhZCk7CgkJCXJldHVybiAtMTsKCQl9CgkJYW1iYXJlbGxhX2lyX21vdmVfcmVhZF9wdHIocGluZm8sIDIpOwoJfQoKCXJldHVybiAwOwp9CgpzdGF0aWMgaW50IGFtYmFyZWxsYV9pcl9wYW5hc29uaWNfcHVsc2VfZGVjb2RlKHN0cnVjdCBhbWJhcmVsbGFfaXJfaW5mbyAqcGluZm8sIHUzMiAqdWlkKQp7Cgl1OCBhZGRyMCA9IDAsIGFkZHIxID0gMCwgZGF0YTAgPSAwLCBkYXRhMSA9IDAsIGRhdGEyID0gMCwgZGF0YTMgPSAwOwoJaW50IHJ2YWw7CgoJLyogVGhlbiBmb2xsb3dzIDIyIGJpdHMgb2YgZGF0YSwgYnJva2VuIGRvd24gaW4gNCBieXRlcyBvZiA4IGJpdHMuICovCgoJLyogVGhlIGZpcnN0IDggYml0cyBpcyB0aGUgQWRkcmVzcyAwLiAqLwoJcnZhbCA9IGFtYmFyZWxsYV9pcl9wYW5hc29uaWNfcHVsc2VfZGF0YV90cmFuc2xhdGUocGluZm8sICZhZGRyMCk7CglpZiAocnZhbCA8IDApCgkJcmV0dXJuIHJ2YWw7CgoJLyogVGhlIHNlY29uZCA4IGJpdHMgaXMgdGhlIEFkZHJlc3MgMS4gKi8KCXJ2YWwgPSBhbWJhcmVsbGFfaXJfcGFuYXNvbmljX3B1bHNlX2RhdGFfdHJhbnNsYXRlKHBpbmZvLCAmYWRkcjEpOwoJaWYgKHJ2YWwgPCAwKQoJCXJldHVybiBydmFsOwoKCS8qIFRoZSB0aGlyZCA4IGJpdHMgaXMgdGhlIGRhdGEgMC4gKi8KCXJ2YWwgPSBhbWJhcmVsbGFfaXJfcGFuYXNvbmljX3B1bHNlX2RhdGFfdHJhbnNsYXRlKHBpbmZvLCAmZGF0YTApOwoJaWYgKHJ2YWwgPCAwKQoJCXJldHVybiBydmFsOwoKCS8qIFRoZSB0aGlyZCA4IGJpdHMgaXMgdGhlIGRhdGEgMS4gKi8KCXJ2YWwgPSBhbWJhcmVsbGFfaXJfcGFuYXNvbmljX3B1bHNlX2RhdGFfdHJhbnNsYXRlKHBpbmZvLCAmZGF0YTEpOwoJaWYgKHJ2YWwgPCAwKQoJCXJldHVybiBydmFsOwoKCS8qIFRoZSB0aGlyZCA4IGJpdHMgaXMgdGhlIGRhdGEgMi4gKi8KCXJ2YWwgPSBhbWJhcmVsbGFfaXJfcGFuYXNvbmljX3B1bHNlX2RhdGFfdHJhbnNsYXRlKHBpbmZvLCAmZGF0YTIpOwoJaWYgKHJ2YWwgPCAwKQoJCXJldHVybiBydmFsOwoKCS8qIFRoZSB0aGlyZCA4IGJpdHMgaXMgdGhlIGRhdGEgMy4gKi8KCXJ2YWwgPSBhbWJhcmVsbGFfaXJfcGFuYXNvbmljX3B1bHNlX2RhdGFfdHJhbnNsYXRlKHBpbmZvLCAmZGF0YTMpOwoJaWYgKHJ2YWwgPCAwKQoJCXJldHVybiBydmFsOwoKCWRldl9kYmcoJnBpbmZvLT5waW5wdXRfZGV2LT5kZXYsICJcdGFkZHIwXHRhZGRyMVx0ZGF0YTBcdGRhdGExXHRkYXRhMlx0ZGF0YTMiKTsKCWRldl9kYmcoJnBpbmZvLT5waW5wdXRfZGV2LT5kZXYsICJcdDB4JXhcdDB4JXhcdDB4JXhcdDB4JXhcdDB4JXhcdDB4JXhcbiIsCgkJCWFkZHIwLCBhZGRyMSwgZGF0YTAsIGRhdGExLCBkYXRhMiwgZGF0YTMpOwoKCSp1aWQgPSAoZGF0YTAgPDwgMjQpIHwgKGRhdGExIDw8IDE2KSB8IChkYXRhMiA8PCA4KSB8IGRhdGEzOwoKCXJldHVybiAwOwp9CgppbnQgYW1iYXJlbGxhX2lyX3BhbmFzb25pY19wYXJzZShzdHJ1Y3QgYW1iYXJlbGxhX2lyX2luZm8gKnBpbmZvLCB1MzIgKnVpZCkKewoJaW50CQkJCXJ2YWw7CglpbnQJCQkJY3VyX3B0ciA9IHBpbmZvLT5pcl9wcmVhZDsKCglpZiAoYW1iYXJlbGxhX2lyX3BhbmFzb25pY19maW5kX2hlYWQocGluZm8pCgkJJiYgYW1iYXJlbGxhX2lyX2dldF90aWNrX3NpemUocGluZm8pID49IHBpbmZvLT5mcmFtZV9pbmZvLmZyYW1lX2RhdGFfc2l6ZQoJCSsgcGluZm8tPmZyYW1lX2luZm8uZnJhbWVfaGVhZF9zaXplKSB7CgoJCWRldl9kYmcoJnBpbmZvLT5waW5wdXRfZGV2LT5kZXYsICJnbyB0byBkZWNvZGUgc3RhdGdlXG4iKTsKCQlhbWJhcmVsbGFfaXJfbW92ZV9yZWFkX3B0cihwaW5mbywgcGluZm8tPmZyYW1lX2luZm8uZnJhbWVfaGVhZF9zaXplKTsvL21vdmUgcHRyIHRvIGRhdGEKCQlydmFsID0gYW1iYXJlbGxhX2lyX3BhbmFzb25pY19wdWxzZV9kZWNvZGUocGluZm8sIHVpZCk7Cgl9IGVsc2UgewoJCXJldHVybiAtMTsKCX0KCglpZiAocnZhbCA+PSAwKSB7CgkJZGV2X2RiZygmcGluZm8tPnBpbnB1dF9kZXYtPmRldiwgImJ1ZmZlclslZF0tLT5tb3JuYWwga2V5XG4iLCBjdXJfcHRyKTsKCQlyZXR1cm4gMDsKCX0KCglyZXR1cm4gKC0xKTsKfQoKdm9pZCBhbWJhcmVsbGFfaXJfZ2V0X3BhbmFzb25pY19pbmZvKHN0cnVjdCBhbWJhcmVsbGFfaXJfZnJhbWVfaW5mbyAqcGZyYW1lX2luZm8pCnsKCXBmcmFtZV9pbmZvLT5mcmFtZV9oZWFkX3NpemUgCT0gMjsKCXBmcmFtZV9pbmZvLT5mcmFtZV9kYXRhX3NpemUgCT0gOTY7CglwZnJhbWVfaW5mby0+ZnJhbWVfZW5kX3NpemUJPSAxOwoJcGZyYW1lX2luZm8tPmZyYW1lX3JlcGVhdF9oZWFkX3NpemUJPSAwOwp9Cgo=