LyoKICogUGVyZm9ybWFuY2UgZXZlbnRzIGNhbGxjaGFpbiBjb2RlLCBleHRyYWN0ZWQgZnJvbSBjb3JlLmM6CiAqCiAqICBDb3B5cmlnaHQgKEMpIDIwMDggVGhvbWFzIEdsZWl4bmVyIDx0Z2x4QGxpbnV0cm9uaXguZGU+CiAqICBDb3B5cmlnaHQgKEMpIDIwMDgtMjAxMSBSZWQgSGF0LCBJbmMuLCBJbmdvIE1vbG5hcgogKiAgQ29weXJpZ2h0IChDKSAyMDA4LTIwMTEgUmVkIEhhdCwgSW5jLiwgUGV0ZXIgWmlqbHN0cmEKICogIENvcHlyaWdodCAgqSAgMjAwOSBQYXVsIE1hY2tlcnJhcywgSUJNIENvcnAuIDxwYXVsdXNAYXUxLmlibS5jb20+CiAqCiAqIEZvciBsaWNlbnNpbmcgZGV0YWlscyBzZWUga2VybmVsLWJhc2UvQ09QWUlORwogKi8KCiNpbmNsdWRlIDxsaW51eC9wZXJmX2V2ZW50Lmg+CiNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CiNpbmNsdWRlICJpbnRlcm5hbC5oIgoKc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMgewoJc3RydWN0IHJjdV9oZWFkCQkJcmN1X2hlYWQ7CglzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnkJKmNwdV9lbnRyaWVzWzBdOwp9OwoKaW50IHN5c2N0bF9wZXJmX2V2ZW50X21heF9zdGFjayBfX3JlYWRfbW9zdGx5ID0gUEVSRl9NQVhfU1RBQ0tfREVQVEg7CmludCBzeXNjdGxfcGVyZl9ldmVudF9tYXhfY29udGV4dHNfcGVyX3N0YWNrIF9fcmVhZF9tb3N0bHkgPSBQRVJGX01BWF9DT05URVhUU19QRVJfU1RBQ0s7CgpzdGF0aWMgaW5saW5lIHNpemVfdCBwZXJmX2NhbGxjaGFpbl9lbnRyeV9fc2l6ZW9mKHZvaWQpCnsKCXJldHVybiAoc2l6ZW9mKHN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSkgKwoJCXNpemVvZihfX3U2NCkgKiAoc3lzY3RsX3BlcmZfZXZlbnRfbWF4X3N0YWNrICsKCQkJCSBzeXNjdGxfcGVyZl9ldmVudF9tYXhfY29udGV4dHNfcGVyX3N0YWNrKSk7Cn0KCnN0YXRpYyBERUZJTkVfUEVSX0NQVShpbnQsIGNhbGxjaGFpbl9yZWN1cnNpb25bUEVSRl9OUl9DT05URVhUU10pOwpzdGF0aWMgYXRvbWljX3QgbnJfY2FsbGNoYWluX2V2ZW50czsKc3RhdGljIERFRklORV9NVVRFWChjYWxsY2hhaW5fbXV0ZXgpOwpzdGF0aWMgc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMgKmNhbGxjaGFpbl9jcHVzX2VudHJpZXM7CgoKX193ZWFrIHZvaWQgcGVyZl9jYWxsY2hhaW5fa2VybmVsKHN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeV9jdHggKmVudHJ5LAoJCQkJICBzdHJ1Y3QgcHRfcmVncyAqcmVncykKewp9CgpfX3dlYWsgdm9pZCBwZXJmX2NhbGxjaGFpbl91c2VyKHN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeV9jdHggKmVudHJ5LAoJCQkJc3RydWN0IHB0X3JlZ3MgKnJlZ3MpCnsKfQoKc3RhdGljIHZvaWQgcmVsZWFzZV9jYWxsY2hhaW5fYnVmZmVyc19yY3Uoc3RydWN0IHJjdV9oZWFkICpoZWFkKQp7CglzdHJ1Y3QgY2FsbGNoYWluX2NwdXNfZW50cmllcyAqZW50cmllczsKCWludCBjcHU7CgoJZW50cmllcyA9IGNvbnRhaW5lcl9vZihoZWFkLCBzdHJ1Y3QgY2FsbGNoYWluX2NwdXNfZW50cmllcywgcmN1X2hlYWQpOwoKCWZvcl9lYWNoX3Bvc3NpYmxlX2NwdShjcHUpCgkJa2ZyZWUoZW50cmllcy0+Y3B1X2VudHJpZXNbY3B1XSk7CgoJa2ZyZWUoZW50cmllcyk7Cn0KCnN0YXRpYyB2b2lkIHJlbGVhc2VfY2FsbGNoYWluX2J1ZmZlcnModm9pZCkKewoJc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMgKmVudHJpZXM7CgoJZW50cmllcyA9IGNhbGxjaGFpbl9jcHVzX2VudHJpZXM7CglSQ1VfSU5JVF9QT0lOVEVSKGNhbGxjaGFpbl9jcHVzX2VudHJpZXMsIE5VTEwpOwoJY2FsbF9yY3UoJmVudHJpZXMtPnJjdV9oZWFkLCByZWxlYXNlX2NhbGxjaGFpbl9idWZmZXJzX3JjdSk7Cn0KCnN0YXRpYyBpbnQgYWxsb2NfY2FsbGNoYWluX2J1ZmZlcnModm9pZCkKewoJaW50IGNwdTsKCWludCBzaXplOwoJc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMgKmVudHJpZXM7CgoJLyoKCSAqIFdlIGNhbid0IHVzZSB0aGUgcGVyY3B1IGFsbG9jYXRpb24gQVBJIGZvciBkYXRhIHRoYXQgY2FuIGJlCgkgKiBhY2Nlc3NlZCBmcm9tIE5NSS4gVXNlIGEgdGVtcG9yYXJ5IG1hbnVhbCBwZXIgY3B1IGFsbG9jYXRpb24KCSAqIHVudGlsIHRoYXQgZ2V0cyBzb3J0ZWQgb3V0LgoJICovCglzaXplID0gb2Zmc2V0b2Yoc3RydWN0IGNhbGxjaGFpbl9jcHVzX2VudHJpZXMsIGNwdV9lbnRyaWVzW25yX2NwdV9pZHNdKTsKCgllbnRyaWVzID0ga3phbGxvYyhzaXplLCBHRlBfS0VSTkVMKTsKCWlmICghZW50cmllcykKCQlyZXR1cm4gLUVOT01FTTsKCglzaXplID0gcGVyZl9jYWxsY2hhaW5fZW50cnlfX3NpemVvZigpICogUEVSRl9OUl9DT05URVhUUzsKCglmb3JfZWFjaF9wb3NzaWJsZV9jcHUoY3B1KSB7CgkJZW50cmllcy0+Y3B1X2VudHJpZXNbY3B1XSA9IGttYWxsb2Nfbm9kZShzaXplLCBHRlBfS0VSTkVMLAoJCQkJCQkJIGNwdV90b19ub2RlKGNwdSkpOwoJCWlmICghZW50cmllcy0+Y3B1X2VudHJpZXNbY3B1XSkKCQkJZ290byBmYWlsOwoJfQoKCXJjdV9hc3NpZ25fcG9pbnRlcihjYWxsY2hhaW5fY3B1c19lbnRyaWVzLCBlbnRyaWVzKTsKCglyZXR1cm4gMDsKCmZhaWw6Cglmb3JfZWFjaF9wb3NzaWJsZV9jcHUoY3B1KQoJCWtmcmVlKGVudHJpZXMtPmNwdV9lbnRyaWVzW2NwdV0pOwoJa2ZyZWUoZW50cmllcyk7CgoJcmV0dXJuIC1FTk9NRU07Cn0KCmludCBnZXRfY2FsbGNoYWluX2J1ZmZlcnModm9pZCkKewoJaW50IGVyciA9IDA7CglpbnQgY291bnQ7CgoJbXV0ZXhfbG9jaygmY2FsbGNoYWluX211dGV4KTsKCgljb3VudCA9IGF0b21pY19pbmNfcmV0dXJuKCZucl9jYWxsY2hhaW5fZXZlbnRzKTsKCWlmIChXQVJOX09OX09OQ0UoY291bnQgPCAxKSkgewoJCWVyciA9IC1FSU5WQUw7CgkJZ290byBleGl0OwoJfQoKCWlmIChjb3VudCA+IDEpIHsKCQkvKiBJZiB0aGUgYWxsb2NhdGlvbiBmYWlsZWQsIGdpdmUgdXAgKi8KCQlpZiAoIWNhbGxjaGFpbl9jcHVzX2VudHJpZXMpCgkJCWVyciA9IC1FTk9NRU07CgkJZ290byBleGl0OwoJfQoKCWVyciA9IGFsbG9jX2NhbGxjaGFpbl9idWZmZXJzKCk7CmV4aXQ6CglpZiAoZXJyKQoJCWF0b21pY19kZWMoJm5yX2NhbGxjaGFpbl9ldmVudHMpOwoKCW11dGV4X3VubG9jaygmY2FsbGNoYWluX211dGV4KTsKCglyZXR1cm4gZXJyOwp9Cgp2b2lkIHB1dF9jYWxsY2hhaW5fYnVmZmVycyh2b2lkKQp7CglpZiAoYXRvbWljX2RlY19hbmRfbXV0ZXhfbG9jaygmbnJfY2FsbGNoYWluX2V2ZW50cywgJmNhbGxjaGFpbl9tdXRleCkpIHsKCQlyZWxlYXNlX2NhbGxjaGFpbl9idWZmZXJzKCk7CgkJbXV0ZXhfdW5sb2NrKCZjYWxsY2hhaW5fbXV0ZXgpOwoJfQp9CgpzdGF0aWMgc3RydWN0IHBlcmZfY2FsbGNoYWluX2VudHJ5ICpnZXRfY2FsbGNoYWluX2VudHJ5KGludCAqcmN0eCkKewoJaW50IGNwdTsKCXN0cnVjdCBjYWxsY2hhaW5fY3B1c19lbnRyaWVzICplbnRyaWVzOwoKCSpyY3R4ID0gZ2V0X3JlY3Vyc2lvbl9jb250ZXh0KHRoaXNfY3B1X3B0cihjYWxsY2hhaW5fcmVjdXJzaW9uKSk7CglpZiAoKnJjdHggPT0gLTEpCgkJcmV0dXJuIE5VTEw7CgoJZW50cmllcyA9IHJjdV9kZXJlZmVyZW5jZShjYWxsY2hhaW5fY3B1c19lbnRyaWVzKTsKCWlmICghZW50cmllcykKCQlyZXR1cm4gTlVMTDsKCgljcHUgPSBzbXBfcHJvY2Vzc29yX2lkKCk7CgoJcmV0dXJuICgoKHZvaWQgKillbnRyaWVzLT5jcHVfZW50cmllc1tjcHVdKSArCgkJKCpyY3R4ICogcGVyZl9jYWxsY2hhaW5fZW50cnlfX3NpemVvZigpKSk7Cn0KCnN0YXRpYyB2b2lkCnB1dF9jYWxsY2hhaW5fZW50cnkoaW50IHJjdHgpCnsKCXB1dF9yZWN1cnNpb25fY29udGV4dCh0aGlzX2NwdV9wdHIoY2FsbGNoYWluX3JlY3Vyc2lvbiksIHJjdHgpOwp9CgpzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnkgKgpwZXJmX2NhbGxjaGFpbihzdHJ1Y3QgcGVyZl9ldmVudCAqZXZlbnQsIHN0cnVjdCBwdF9yZWdzICpyZWdzKQp7Cglib29sIGtlcm5lbCA9ICFldmVudC0+YXR0ci5leGNsdWRlX2NhbGxjaGFpbl9rZXJuZWw7Cglib29sIHVzZXIgICA9ICFldmVudC0+YXR0ci5leGNsdWRlX2NhbGxjaGFpbl91c2VyOwoJLyogRGlzYWxsb3cgY3Jvc3MtdGFzayB1c2VyIGNhbGxjaGFpbnMuICovCglib29sIGNyb3NzdGFzayA9IGV2ZW50LT5jdHgtPnRhc2sgJiYgZXZlbnQtPmN0eC0+dGFzayAhPSBjdXJyZW50OwoKCWlmICgha2VybmVsICYmICF1c2VyKQoJCXJldHVybiBOVUxMOwoKCXJldHVybiBnZXRfcGVyZl9jYWxsY2hhaW4ocmVncywgMCwga2VybmVsLCB1c2VyLCBzeXNjdGxfcGVyZl9ldmVudF9tYXhfc3RhY2ssIGNyb3NzdGFzaywgdHJ1ZSk7Cn0KCnN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSAqCmdldF9wZXJmX2NhbGxjaGFpbihzdHJ1Y3QgcHRfcmVncyAqcmVncywgdTMyIGluaXRfbnIsIGJvb2wga2VybmVsLCBib29sIHVzZXIsCgkJICAgdTMyIG1heF9zdGFjaywgYm9vbCBjcm9zc3Rhc2ssIGJvb2wgYWRkX21hcmspCnsKCXN0cnVjdCBwZXJmX2NhbGxjaGFpbl9lbnRyeSAqZW50cnk7CglzdHJ1Y3QgcGVyZl9jYWxsY2hhaW5fZW50cnlfY3R4IGN0eDsKCWludCByY3R4OwoKCWVudHJ5ID0gZ2V0X2NhbGxjaGFpbl9lbnRyeSgmcmN0eCk7CglpZiAocmN0eCA9PSAtMSkKCQlyZXR1cm4gTlVMTDsKCglpZiAoIWVudHJ5KQoJCWdvdG8gZXhpdF9wdXQ7CgoJY3R4LmVudHJ5ICAgICA9IGVudHJ5OwoJY3R4Lm1heF9zdGFjayA9IG1heF9zdGFjazsKCWN0eC5ucgkgICAgICA9IGVudHJ5LT5uciA9IGluaXRfbnI7CgljdHguY29udGV4dHMgICAgICAgPSAwOwoJY3R4LmNvbnRleHRzX21heGVkID0gZmFsc2U7CgoJaWYgKGtlcm5lbCAmJiAhdXNlcl9tb2RlKHJlZ3MpKSB7CgkJaWYgKGFkZF9tYXJrKQoJCQlwZXJmX2NhbGxjaGFpbl9zdG9yZV9jb250ZXh0KCZjdHgsIFBFUkZfQ09OVEVYVF9LRVJORUwpOwoJCXBlcmZfY2FsbGNoYWluX2tlcm5lbCgmY3R4LCByZWdzKTsKCX0KCglpZiAodXNlcikgewoJCWlmICghdXNlcl9tb2RlKHJlZ3MpKSB7CgkJCWlmICAoY3VycmVudC0+bW0pCgkJCQlyZWdzID0gdGFza19wdF9yZWdzKGN1cnJlbnQpOwoJCQllbHNlCgkJCQlyZWdzID0gTlVMTDsKCQl9CgoJCWlmIChyZWdzKSB7CgkJCWlmIChjcm9zc3Rhc2spCgkJCQlnb3RvIGV4aXRfcHV0OwoKCQkJaWYgKGFkZF9tYXJrKQoJCQkJcGVyZl9jYWxsY2hhaW5fc3RvcmVfY29udGV4dCgmY3R4LCBQRVJGX0NPTlRFWFRfVVNFUik7CgkJCXBlcmZfY2FsbGNoYWluX3VzZXIoJmN0eCwgcmVncyk7CgkJfQoJfQoKZXhpdF9wdXQ6CglwdXRfY2FsbGNoYWluX2VudHJ5KHJjdHgpOwoKCXJldHVybiBlbnRyeTsKfQoKLyoKICogVXNlZCBmb3Igc3lzY3RsX3BlcmZfZXZlbnRfbWF4X3N0YWNrIGFuZAogKiBzeXNjdGxfcGVyZl9ldmVudF9tYXhfY29udGV4dHNfcGVyX3N0YWNrLgogKi8KaW50IHBlcmZfZXZlbnRfbWF4X3N0YWNrX2hhbmRsZXIoc3RydWN0IGN0bF90YWJsZSAqdGFibGUsIGludCB3cml0ZSwKCQkJCSB2b2lkIF9fdXNlciAqYnVmZmVyLCBzaXplX3QgKmxlbnAsIGxvZmZfdCAqcHBvcykKewoJaW50ICp2YWx1ZSA9IHRhYmxlLT5kYXRhOwoJaW50IG5ld192YWx1ZSA9ICp2YWx1ZSwgcmV0OwoJc3RydWN0IGN0bF90YWJsZSBuZXdfdGFibGUgPSAqdGFibGU7CgoJbmV3X3RhYmxlLmRhdGEgPSAmbmV3X3ZhbHVlOwoJcmV0ID0gcHJvY19kb2ludHZlY19taW5tYXgoJm5ld190YWJsZSwgd3JpdGUsIGJ1ZmZlciwgbGVucCwgcHBvcyk7CglpZiAocmV0IHx8ICF3cml0ZSkKCQlyZXR1cm4gcmV0OwoKCW11dGV4X2xvY2soJmNhbGxjaGFpbl9tdXRleCk7CglpZiAoYXRvbWljX3JlYWQoJm5yX2NhbGxjaGFpbl9ldmVudHMpKQoJCXJldCA9IC1FQlVTWTsKCWVsc2UKCQkqdmFsdWUgPSBuZXdfdmFsdWU7CgoJbXV0ZXhfdW5sb2NrKCZjYWxsY2hhaW5fbXV0ZXgpOwoKCXJldHVybiByZXQ7Cn0K