Ci8qCiAqIElCTSBBU00gU2VydmljZSBQcm9jZXNzb3IgRGV2aWNlIERyaXZlcgogKgogKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQogKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieQogKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgogKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQogKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQogKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UgLSBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgMDIxMTEtMTMwNywgVVNBLgogKgogKiBDb3B5cmlnaHQgKEMpIElCTSBDb3Jwb3JhdGlvbiwgMjAwNAogKgogKiBBdXRob3I6IE1heCBBc2L2Y2sgPGFtYXhAdXMuaWJtLmNvbT4KICoKICovCgojaW5jbHVkZSAiaWJtYXNtLmgiCiNpbmNsdWRlICJsb3dsZXZlbC5oIgoKc3RhdGljIHZvaWQgZXhlY19uZXh0X2NvbW1hbmQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCk7CgpzdGF0aWMgYXRvbWljX3QgY29tbWFuZF9jb3VudCA9IEFUT01JQ19JTklUKDApOwoKc3RydWN0IGNvbW1hbmQgKmlibWFzbV9uZXdfY29tbWFuZChzdHJ1Y3Qgc2VydmljZV9wcm9jZXNzb3IgKnNwLCBzaXplX3QgYnVmZmVyX3NpemUpCnsKCXN0cnVjdCBjb21tYW5kICpjbWQ7CgoJaWYgKGJ1ZmZlcl9zaXplID4gSUJNQVNNX0NNRF9NQVhfQlVGRkVSX1NJWkUpCgkJcmV0dXJuIE5VTEw7CgoJY21kID0ga3phbGxvYyhzaXplb2Yoc3RydWN0IGNvbW1hbmQpLCBHRlBfS0VSTkVMKTsKCWlmIChjbWQgPT0gTlVMTCkKCQlyZXR1cm4gTlVMTDsKCgoJY21kLT5idWZmZXIgPSBremFsbG9jKGJ1ZmZlcl9zaXplLCBHRlBfS0VSTkVMKTsKCWlmIChjbWQtPmJ1ZmZlciA9PSBOVUxMKSB7CgkJa2ZyZWUoY21kKTsKCQlyZXR1cm4gTlVMTDsKCX0KCWNtZC0+YnVmZmVyX3NpemUgPSBidWZmZXJfc2l6ZTsKCglrcmVmX2luaXQoJmNtZC0+a3JlZik7CgljbWQtPmxvY2sgPSAmc3AtPmxvY2s7CgoJY21kLT5zdGF0dXMgPSBJQk1BU01fQ01EX1BFTkRJTkc7Cglpbml0X3dhaXRxdWV1ZV9oZWFkKCZjbWQtPndhaXQpOwoJSU5JVF9MSVNUX0hFQUQoJmNtZC0+cXVldWVfbm9kZSk7CgoJYXRvbWljX2luYygmY29tbWFuZF9jb3VudCk7CglkYmcoImNvbW1hbmQgY291bnQ6ICVkXG4iLCBhdG9taWNfcmVhZCgmY29tbWFuZF9jb3VudCkpOwoKCXJldHVybiBjbWQ7Cn0KCnZvaWQgaWJtYXNtX2ZyZWVfY29tbWFuZChzdHJ1Y3Qga3JlZiAqa3JlZikKewoJc3RydWN0IGNvbW1hbmQgKmNtZCA9IHRvX2NvbW1hbmQoa3JlZik7CgoJbGlzdF9kZWwoJmNtZC0+cXVldWVfbm9kZSk7CglhdG9taWNfZGVjKCZjb21tYW5kX2NvdW50KTsKCWRiZygiY29tbWFuZCBjb3VudDogJWRcbiIsIGF0b21pY19yZWFkKCZjb21tYW5kX2NvdW50KSk7CglrZnJlZShjbWQtPmJ1ZmZlcik7CglrZnJlZShjbWQpOwp9CgpzdGF0aWMgdm9pZCBlbnF1ZXVlX2NvbW1hbmQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCwgc3RydWN0IGNvbW1hbmQgKmNtZCkKewoJbGlzdF9hZGRfdGFpbCgmY21kLT5xdWV1ZV9ub2RlLCAmc3AtPmNvbW1hbmRfcXVldWUpOwp9CgpzdGF0aWMgc3RydWN0IGNvbW1hbmQgKmRlcXVldWVfY29tbWFuZChzdHJ1Y3Qgc2VydmljZV9wcm9jZXNzb3IgKnNwKQp7CglzdHJ1Y3QgY29tbWFuZCAqY21kOwoJc3RydWN0IGxpc3RfaGVhZCAqbmV4dDsKCglpZiAobGlzdF9lbXB0eSgmc3AtPmNvbW1hbmRfcXVldWUpKQoJCXJldHVybiBOVUxMOwoKCW5leHQgPSBzcC0+Y29tbWFuZF9xdWV1ZS5uZXh0OwoJbGlzdF9kZWxfaW5pdChuZXh0KTsKCWNtZCA9IGxpc3RfZW50cnkobmV4dCwgc3RydWN0IGNvbW1hbmQsIHF1ZXVlX25vZGUpOwoKCXJldHVybiBjbWQ7Cn0KCnN0YXRpYyBpbmxpbmUgdm9pZCBkb19leGVjX2NvbW1hbmQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCkKewoJY2hhciB0c2J1ZlszMl07CgoJZGJnKCIlczolZCBhdCAlc1xuIiwgX19GVU5DVElPTl9fLCBfX0xJTkVfXywgZ2V0X3RpbWVzdGFtcCh0c2J1ZikpOwoKCWlmIChpYm1hc21fc2VuZF9pMm9fbWVzc2FnZShzcCkpIHsKCQlzcC0+Y3VycmVudF9jb21tYW5kLT5zdGF0dXMgPSBJQk1BU01fQ01EX0ZBSUxFRDsKCQl3YWtlX3VwKCZzcC0+Y3VycmVudF9jb21tYW5kLT53YWl0KTsKCQljb21tYW5kX3B1dChzcC0+Y3VycmVudF9jb21tYW5kKTsKCQlleGVjX25leHRfY29tbWFuZChzcCk7Cgl9Cn0KCi8qKgogKiBleGVjX2NvbW1hbmQKICogc2VuZCBhIGNvbW1hbmQgdG8gYSBzZXJ2aWNlIHByb2Nlc3NvcgogKiBDb21tYW5kcyBhcmUgZXhlY3V0ZWQgc2VxdWVudGlhbGx5LiBPbmUgY29tbWFuZCAoc3AtPmN1cnJlbnRfY29tbWFuZCkKICogaXMgc2VudCB0byB0aGUgc2VydmljZSBwcm9jZXNzb3IuIE9uY2UgdGhlIGludGVycnVwdCBoYW5kbGVyIGdldHMgYQogKiBtZXNzYWdlIG9mIHR5cGUgY29tbWFuZF9yZXNwb25zZSwgdGhlIG1lc3NhZ2UgaXMgY29waWVkIGludG8KICogdGhlIGN1cnJlbnQgY29tbWFuZHMgYnVmZmVyLAogKi8Kdm9pZCBpYm1hc21fZXhlY19jb21tYW5kKHN0cnVjdCBzZXJ2aWNlX3Byb2Nlc3NvciAqc3AsIHN0cnVjdCBjb21tYW5kICpjbWQpCnsKCXVuc2lnbmVkIGxvbmcgZmxhZ3M7CgljaGFyIHRzYnVmWzMyXTsKCglkYmcoIiVzOiVkIGF0ICVzXG4iLCBfX0ZVTkNUSU9OX18sIF9fTElORV9fLCBnZXRfdGltZXN0YW1wKHRzYnVmKSk7CgoJc3Bpbl9sb2NrX2lycXNhdmUoJnNwLT5sb2NrLCBmbGFncyk7CgoJaWYgKCFzcC0+Y3VycmVudF9jb21tYW5kKSB7CgkJc3AtPmN1cnJlbnRfY29tbWFuZCA9IGNtZDsKCQljb21tYW5kX2dldChzcC0+Y3VycmVudF9jb21tYW5kKTsKCQlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZzcC0+bG9jaywgZmxhZ3MpOwoJCWRvX2V4ZWNfY29tbWFuZChzcCk7Cgl9IGVsc2UgewoJCWVucXVldWVfY29tbWFuZChzcCwgY21kKTsKCQlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZzcC0+bG9jaywgZmxhZ3MpOwoJfQp9CgpzdGF0aWMgdm9pZCBleGVjX25leHRfY29tbWFuZChzdHJ1Y3Qgc2VydmljZV9wcm9jZXNzb3IgKnNwKQp7Cgl1bnNpZ25lZCBsb25nIGZsYWdzOwoJY2hhciB0c2J1ZlszMl07CgoJZGJnKCIlczolZCBhdCAlc1xuIiwgX19GVU5DVElPTl9fLCBfX0xJTkVfXywgZ2V0X3RpbWVzdGFtcCh0c2J1ZikpOwoKCXNwaW5fbG9ja19pcnFzYXZlKCZzcC0+bG9jaywgZmxhZ3MpOwoJc3AtPmN1cnJlbnRfY29tbWFuZCA9IGRlcXVldWVfY29tbWFuZChzcCk7CglpZiAoc3AtPmN1cnJlbnRfY29tbWFuZCkgewoJCWNvbW1hbmRfZ2V0KHNwLT5jdXJyZW50X2NvbW1hbmQpOwoJCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJnNwLT5sb2NrLCBmbGFncyk7CgkJZG9fZXhlY19jb21tYW5kKHNwKTsKCX0gZWxzZSB7CgkJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmc3AtPmxvY2ssIGZsYWdzKTsKCX0KfQoKLyoqCiAqIFNsZWVwIHVudGlsIGEgY29tbWFuZCBoYXMgZmFpbGVkIG9yIGEgcmVzcG9uc2UgaGFzIGJlZW4gcmVjZWl2ZWQKICogYW5kIHRoZSBjb21tYW5kIHN0YXR1cyBiZWVuIHVwZGF0ZWQgYnkgdGhlIGludGVycnVwdCBoYW5kbGVyLgogKiAoc2VlIHJlY2VpdmVfcmVzcG9uc2UpLgogKi8Kdm9pZCBpYm1hc21fd2FpdF9mb3JfcmVzcG9uc2Uoc3RydWN0IGNvbW1hbmQgKmNtZCwgaW50IHRpbWVvdXQpCnsKCXdhaXRfZXZlbnRfaW50ZXJydXB0aWJsZV90aW1lb3V0KGNtZC0+d2FpdCwKCQkJCWNtZC0+c3RhdHVzID09IElCTUFTTV9DTURfQ09NUExFVEUgfHwKCQkJCWNtZC0+c3RhdHVzID09IElCTUFTTV9DTURfRkFJTEVELAoJCQkJdGltZW91dCAqIEhaKTsKfQoKLyoqCiAqIHJlY2VpdmVfY29tbWFuZF9yZXNwb25zZQogKiBjYWxsZWQgYnkgdGhlIGludGVycnVwdCBoYW5kbGVyIHdoZW4gYSBkb3QgY29tbWFuZCBvZiB0eXBlIGNvbW1hbmRfcmVzcG9uc2UKICogd2FzIHJlY2VpdmVkLgogKi8Kdm9pZCBpYm1hc21fcmVjZWl2ZV9jb21tYW5kX3Jlc3BvbnNlKHN0cnVjdCBzZXJ2aWNlX3Byb2Nlc3NvciAqc3AsIHZvaWQgKnJlc3BvbnNlLCBzaXplX3Qgc2l6ZSkKewoJc3RydWN0IGNvbW1hbmQgKmNtZCA9IHNwLT5jdXJyZW50X2NvbW1hbmQ7CgoJaWYgKCFzcC0+Y3VycmVudF9jb21tYW5kKQoJCXJldHVybjsKCgltZW1jcHlfZnJvbWlvKGNtZC0+YnVmZmVyLCByZXNwb25zZSwgbWluKHNpemUsIGNtZC0+YnVmZmVyX3NpemUpKTsKCWNtZC0+c3RhdHVzID0gSUJNQVNNX0NNRF9DT01QTEVURTsKCXdha2VfdXAoJnNwLT5jdXJyZW50X2NvbW1hbmQtPndhaXQpOwoJY29tbWFuZF9wdXQoc3AtPmN1cnJlbnRfY29tbWFuZCk7CglleGVjX25leHRfY29tbWFuZChzcCk7Cn0K