LyoKICogUGVyZm9ybWFuY2UgZXZlbnRzIGNhbGxjaGFpbiBjb2RlLCBleHRyYWN0ZWQgZnJvbSBjb3JlLmM6CiAqCiAqICBDb3B5cmlnaHQgKEMpIDIwMDggVGhvbWFzIEdsZWl4bmVyIDx0Z2x4QGxpbnV0cm9uaXguZGU+CiAqICBDb3B5cmlnaHQgKEMpIDIwMDgtMjAxMSBSZWQgSGF0LCBJbmMuLCBJbmdvIE1vbG5hcgogKiAgQ29weXJpZ2h0IChDKSAyMDA4LTIwMTEgUmVkIEhhdCwgSW5jLiwgUGV0ZXIgWmlqbHN0cmEKICogIENvcHlyaWdodCAgqSAgMjAwOSBQYXVsIE1hY2tlcnJhcywgSUJNIENvcnAuIDxwYXVsdXNAYXUxLmlibS5jb20+CiAqCiAqIEZvciBsaWNlbnNpbmcgZGV0YWlscyBzZWUga2VybmVsLWJhc2UvQ09QWUlORwogKi8KCiNpbmNsdWRlIDxsaW51eC9wZXJmX2V2ZW50Lmg+CiNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CiNpbmNsdWRlICJpbnRlcm5hbC5oIgoKc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMgewoJc3RydWN0IHJjdV9oZWFkCQkJcmN1X2hlYWQ7CglzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnkJKmNwdV9lbnRyaWVzWzBdOwp9OwoKaW50IHN5c2N0bF9wZXJmX2V2ZW50X21heF9zdGFjayBfX3JlYWRfbW9zdGx5ID0gUEVSRl9NQVhfU1RBQ0tfREVQVEg7CgpzdGF0aWMgaW5saW5lIHNpemVfdCBwZXJmX2NhbGxjaGFpbl9lbnRyeV9fc2l6ZW9mKHZvaWQpCnsKCXJldHVybiAoc2l6ZW9mKHN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSkgKwoJCXNpemVvZihfX3U2NCkgKiBzeXNjdGxfcGVyZl9ldmVudF9tYXhfc3RhY2spOwp9CgpzdGF0aWMgREVGSU5FX1BFUl9DUFUoaW50LCBjYWxsY2hhaW5fcmVjdXJzaW9uW1BFUkZfTlJfQ09OVEVYVFNdKTsKc3RhdGljIGF0b21pY190IG5yX2NhbGxjaGFpbl9ldmVudHM7CnN0YXRpYyBERUZJTkVfTVVURVgoY2FsbGNoYWluX211dGV4KTsKc3RhdGljIHN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzICpjYWxsY2hhaW5fY3B1c19lbnRyaWVzOwoKCl9fd2VhayB2b2lkIHBlcmZfY2FsbGNoYWluX2tlcm5lbChzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnkgKmVudHJ5LAoJCQkJICBzdHJ1Y3QgcHRfcmVncyAqcmVncykKewp9CgpfX3dlYWsgdm9pZCBwZXJmX2NhbGxjaGFpbl91c2VyKHN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSAqZW50cnksCgkJCQlzdHJ1Y3QgcHRfcmVncyAqcmVncykKewp9CgpzdGF0aWMgdm9pZCByZWxlYXNlX2NhbGxjaGFpbl9idWZmZXJzX3JjdShzdHJ1Y3QgcmN1X2hlYWQgKmhlYWQpCnsKCXN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzICplbnRyaWVzOwoJaW50IGNwdTsKCgllbnRyaWVzID0gY29udGFpbmVyX29mKGhlYWQsIHN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzLCByY3VfaGVhZCk7CgoJZm9yX2VhY2hfcG9zc2libGVfY3B1KGNwdSkKCQlrZnJlZShlbnRyaWVzLT5jcHVfZW50cmllc1tjcHVdKTsKCglrZnJlZShlbnRyaWVzKTsKfQoKc3RhdGljIHZvaWQgcmVsZWFzZV9jYWxsY2hhaW5fYnVmZmVycyh2b2lkKQp7CglzdHJ1Y3QgY2FsbGNoYWluX2NwdXNfZW50cmllcyAqZW50cmllczsKCgllbnRyaWVzID0gY2FsbGNoYWluX2NwdXNfZW50cmllczsKCVJDVV9JTklUX1BPSU5URVIoY2FsbGNoYWluX2NwdXNfZW50cmllcywgTlVMTCk7CgljYWxsX3JjdSgmZW50cmllcy0+cmN1X2hlYWQsIHJlbGVhc2VfY2FsbGNoYWluX2J1ZmZlcnNfcmN1KTsKfQoKc3RhdGljIGludCBhbGxvY19jYWxsY2hhaW5fYnVmZmVycyh2b2lkKQp7CglpbnQgY3B1OwoJaW50IHNpemU7CglzdHJ1Y3QgY2FsbGNoYWluX2NwdXNfZW50cmllcyAqZW50cmllczsKCgkvKgoJICogV2UgY2FuJ3QgdXNlIHRoZSBwZXJjcHUgYWxsb2NhdGlvbiBBUEkgZm9yIGRhdGEgdGhhdCBjYW4gYmUKCSAqIGFjY2Vzc2VkIGZyb20gTk1JLiBVc2UgYSB0ZW1wb3JhcnkgbWFudWFsIHBlciBjcHUgYWxsb2NhdGlvbgoJICogdW50aWwgdGhhdCBnZXRzIHNvcnRlZCBvdXQuCgkgKi8KCXNpemUgPSBvZmZzZXRvZihzdHJ1Y3QgY2FsbGNoYWluX2NwdXNfZW50cmllcywgY3B1X2VudHJpZXNbbnJfY3B1X2lkc10pOwoKCWVudHJpZXMgPSBremFsbG9jKHNpemUsIEdGUF9LRVJORUwpOwoJaWYgKCFlbnRyaWVzKQoJCXJldHVybiAtRU5PTUVNOwoKCXNpemUgPSBwZXJmX2NhbGxjaGFpbl9lbnRyeV9fc2l6ZW9mKCkgKiBQRVJGX05SX0NPTlRFWFRTOwoKCWZvcl9lYWNoX3Bvc3NpYmxlX2NwdShjcHUpIHsKCQllbnRyaWVzLT5jcHVfZW50cmllc1tjcHVdID0ga21hbGxvY19ub2RlKHNpemUsIEdGUF9LRVJORUwsCgkJCQkJCQkgY3B1X3RvX25vZGUoY3B1KSk7CgkJaWYgKCFlbnRyaWVzLT5jcHVfZW50cmllc1tjcHVdKQoJCQlnb3RvIGZhaWw7Cgl9CgoJcmN1X2Fzc2lnbl9wb2ludGVyKGNhbGxjaGFpbl9jcHVzX2VudHJpZXMsIGVudHJpZXMpOwoKCXJldHVybiAwOwoKZmFpbDoKCWZvcl9lYWNoX3Bvc3NpYmxlX2NwdShjcHUpCgkJa2ZyZWUoZW50cmllcy0+Y3B1X2VudHJpZXNbY3B1XSk7CglrZnJlZShlbnRyaWVzKTsKCglyZXR1cm4gLUVOT01FTTsKfQoKaW50IGdldF9jYWxsY2hhaW5fYnVmZmVycyh2b2lkKQp7CglpbnQgZXJyID0gMDsKCWludCBjb3VudDsKCgltdXRleF9sb2NrKCZjYWxsY2hhaW5fbXV0ZXgpOwoKCWNvdW50ID0gYXRvbWljX2luY19yZXR1cm4oJm5yX2NhbGxjaGFpbl9ldmVudHMpOwoJaWYgKFdBUk5fT05fT05DRShjb3VudCA8IDEpKSB7CgkJZXJyID0gLUVJTlZBTDsKCQlnb3RvIGV4aXQ7Cgl9CgoJaWYgKGNvdW50ID4gMSkgewoJCS8qIElmIHRoZSBhbGxvY2F0aW9uIGZhaWxlZCwgZ2l2ZSB1cCAqLwoJCWlmICghY2FsbGNoYWluX2NwdXNfZW50cmllcykKCQkJZXJyID0gLUVOT01FTTsKCQlnb3RvIGV4aXQ7Cgl9CgoJZXJyID0gYWxsb2NfY2FsbGNoYWluX2J1ZmZlcnMoKTsKZXhpdDoKCWlmIChlcnIpCgkJYXRvbWljX2RlYygmbnJfY2FsbGNoYWluX2V2ZW50cyk7CgoJbXV0ZXhfdW5sb2NrKCZjYWxsY2hhaW5fbXV0ZXgpOwoKCXJldHVybiBlcnI7Cn0KCnZvaWQgcHV0X2NhbGxjaGFpbl9idWZmZXJzKHZvaWQpCnsKCWlmIChhdG9taWNfZGVjX2FuZF9tdXRleF9sb2NrKCZucl9jYWxsY2hhaW5fZXZlbnRzLCAmY2FsbGNoYWluX211dGV4KSkgewoJCXJlbGVhc2VfY2FsbGNoYWluX2J1ZmZlcnMoKTsKCQltdXRleF91bmxvY2soJmNhbGxjaGFpbl9tdXRleCk7Cgl9Cn0KCnN0YXRpYyBzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnkgKmdldF9jYWxsY2hhaW5fZW50cnkoaW50ICpyY3R4KQp7CglpbnQgY3B1OwoJc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMgKmVudHJpZXM7CgoJKnJjdHggPSBnZXRfcmVjdXJzaW9uX2NvbnRleHQodGhpc19jcHVfcHRyKGNhbGxjaGFpbl9yZWN1cnNpb24pKTsKCWlmICgqcmN0eCA9PSAtMSkKCQlyZXR1cm4gTlVMTDsKCgllbnRyaWVzID0gcmN1X2RlcmVmZXJlbmNlKGNhbGxjaGFpbl9jcHVzX2VudHJpZXMpOwoJaWYgKCFlbnRyaWVzKQoJCXJldHVybiBOVUxMOwoKCWNwdSA9IHNtcF9wcm9jZXNzb3JfaWQoKTsKCglyZXR1cm4gKCgodm9pZCAqKWVudHJpZXMtPmNwdV9lbnRyaWVzW2NwdV0pICsKCQkoKnJjdHggKiBwZXJmX2NhbGxjaGFpbl9lbnRyeV9fc2l6ZW9mKCkpKTsKfQoKc3RhdGljIHZvaWQKcHV0X2NhbGxjaGFpbl9lbnRyeShpbnQgcmN0eCkKewoJcHV0X3JlY3Vyc2lvbl9jb250ZXh0KHRoaXNfY3B1X3B0cihjYWxsY2hhaW5fcmVjdXJzaW9uKSwgcmN0eCk7Cn0KCnN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSAqCnBlcmZfY2FsbGNoYWluKHN0cnVjdCBwZXJmX2V2ZW50ICpldmVudCwgc3RydWN0IHB0X3JlZ3MgKnJlZ3MpCnsKCWJvb2wga2VybmVsID0gIWV2ZW50LT5hdHRyLmV4Y2x1ZGVfY2FsbGNoYWluX2tlcm5lbDsKCWJvb2wgdXNlciAgID0gIWV2ZW50LT5hdHRyLmV4Y2x1ZGVfY2FsbGNoYWluX3VzZXI7CgkvKiBEaXNhbGxvdyBjcm9zcy10YXNrIHVzZXIgY2FsbGNoYWlucy4gKi8KCWJvb2wgY3Jvc3N0YXNrID0gZXZlbnQtPmN0eC0+dGFzayAmJiBldmVudC0+Y3R4LT50YXNrICE9IGN1cnJlbnQ7CgoJaWYgKCFrZXJuZWwgJiYgIXVzZXIpCgkJcmV0dXJuIE5VTEw7CgoJcmV0dXJuIGdldF9wZXJmX2NhbGxjaGFpbihyZWdzLCAwLCBrZXJuZWwsIHVzZXIsIGNyb3NzdGFzaywgdHJ1ZSk7Cn0KCnN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSAqCmdldF9wZXJmX2NhbGxjaGFpbihzdHJ1Y3QgcHRfcmVncyAqcmVncywgdTMyIGluaXRfbnIsIGJvb2wga2VybmVsLCBib29sIHVzZXIsCgkJICAgYm9vbCBjcm9zc3Rhc2ssIGJvb2wgYWRkX21hcmspCnsKCXN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSAqZW50cnk7CglpbnQgcmN0eDsKCgllbnRyeSA9IGdldF9jYWxsY2hhaW5fZW50cnkoJnJjdHgpOwoJaWYgKHJjdHggPT0gLTEpCgkJcmV0dXJuIE5VTEw7CgoJaWYgKCFlbnRyeSkKCQlnb3RvIGV4aXRfcHV0OwoKCWVudHJ5LT5uciA9IGluaXRfbnI7CgoJaWYgKGtlcm5lbCAmJiAhdXNlcl9tb2RlKHJlZ3MpKSB7CgkJaWYgKGFkZF9tYXJrKQoJCQlwZXJmX2NhbGxjaGFpbl9zdG9yZShlbnRyeSwgUEVSRl9DT05URVhUX0tFUk5FTCk7CgkJcGVyZl9jYWxsY2hhaW5fa2VybmVsKGVudHJ5LCByZWdzKTsKCX0KCglpZiAodXNlcikgewoJCWlmICghdXNlcl9tb2RlKHJlZ3MpKSB7CgkJCWlmICAoY3VycmVudC0+bW0pCgkJCQlyZWdzID0gdGFza19wdF9yZWdzKGN1cnJlbnQpOwoJCQllbHNlCgkJCQlyZWdzID0gTlVMTDsKCQl9CgoJCWlmIChyZWdzKSB7CgkJCWlmIChjcm9zc3Rhc2spCgkJCQlnb3RvIGV4aXRfcHV0OwoKCQkJaWYgKGFkZF9tYXJrKQoJCQkJcGVyZl9jYWxsY2hhaW5fc3RvcmUoZW50cnksIFBFUkZfQ09OVEVYVF9VU0VSKTsKCQkJcGVyZl9jYWxsY2hhaW5fdXNlcihlbnRyeSwgcmVncyk7CgkJfQoJfQoKZXhpdF9wdXQ6CglwdXRfY2FsbGNoYWluX2VudHJ5KHJjdHgpOwoKCXJldHVybiBlbnRyeTsKfQoKaW50IHBlcmZfZXZlbnRfbWF4X3N0YWNrX2hhbmRsZXIoc3RydWN0IGN0bF90YWJsZSAqdGFibGUsIGludCB3cml0ZSwKCQkJCSB2b2lkIF9fdXNlciAqYnVmZmVyLCBzaXplX3QgKmxlbnAsIGxvZmZfdCAqcHBvcykKewoJaW50IG5ld192YWx1ZSA9IHN5c2N0bF9wZXJmX2V2ZW50X21heF9zdGFjaywgcmV0OwoJc3RydWN0IGN0bF90YWJsZSBuZXdfdGFibGUgPSAqdGFibGU7CgoJbmV3X3RhYmxlLmRhdGEgPSAmbmV3X3ZhbHVlOwoJcmV0ID0gcHJvY19kb2ludHZlY19taW5tYXgoJm5ld190YWJsZSwgd3JpdGUsIGJ1ZmZlciwgbGVucCwgcHBvcyk7CglpZiAocmV0IHx8ICF3cml0ZSkKCQlyZXR1cm4gcmV0OwoKCW11dGV4X2xvY2soJmNhbGxjaGFpbl9tdXRleCk7CglpZiAoYXRvbWljX3JlYWQoJm5yX2NhbGxjaGFpbl9ldmVudHMpKQoJCXJldCA9IC1FQlVTWTsKCWVsc2UKCQlzeXNjdGxfcGVyZl9ldmVudF9tYXhfc3RhY2sgPSBuZXdfdmFsdWU7CgoJbXV0ZXhfdW5sb2NrKCZjYWxsY2hhaW5fbXV0ZXgpOwoKCXJldHVybiByZXQ7Cn0K