Ci8qCiAqIElCTSBBU00gU2VydmljZSBQcm9jZXNzb3IgRGV2aWNlIERyaXZlcgogKgogKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQogKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieQogKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgogKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQogKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQogKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UgLSBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgMDIxMTEtMTMwNywgVVNBLgogKgogKiBDb3B5cmlnaHQgKEMpIElCTSBDb3Jwb3JhdGlvbiwgMjAwNAogKgogKiBBdXRob3I6IE1heCBBc2L2Y2sgPGFtYXhAdXMuaWJtLmNvbT4gCiAqCiAqLwoKI2luY2x1ZGUgImlibWFzbS5oIgoKLyoKICogQVNNIHNlcnZpY2UgcHJvY2Vzc29yIGV2ZW50IGhhbmRsaW5nIHJvdXRpbmVzLgogKgogKiBFdmVudHMgYXJlIHNpZ25hbGxlZCB0byB0aGUgZGV2aWNlIGRyaXZlcnMgdGhyb3VnaCBpbnRlcnJ1cHRzLgogKiBUaGV5IGhhdmUgdGhlIGZvcm1hdCBvZiBkb3QgY29tbWFuZHMsIHdpdGggdGhlIHR5cGUgZmllbGQgc2V0IHRvCiAqIHNwX2V2ZW50LgogKiBUaGUgZHJpdmVyIGRvZXMgbm90IGludGVycHJldCB0aGUgZXZlbnRzLCBpdCBzaW1wbHkgc3RvcmVzIHRoZW0gaW4gYQogKiBjaXJjdWxhciBidWZmZXIuCiAqLwoKCnN0YXRpYyB2b2lkIHdha2VfdXBfZXZlbnRfcmVhZGVycyhzdHJ1Y3Qgc2VydmljZV9wcm9jZXNzb3IgKnNwKQp7CglzdHJ1Y3QgZXZlbnRfcmVhZGVyICpyZWFkZXI7CgoJbGlzdF9mb3JfZWFjaF9lbnRyeShyZWFkZXIsICZzcC0+ZXZlbnRfYnVmZmVyLT5yZWFkZXJzLCBub2RlKQogICAgICAgICAgICAgICAgd2FrZV91cF9pbnRlcnJ1cHRpYmxlKCZyZWFkZXItPndhaXQpOwp9CgovKioKICogcmVjZWl2ZV9ldmVudAogKiBDYWxsZWQgYnkgdGhlIGludGVycnVwdCBoYW5kbGVyIHdoZW4gYSBkb3QgY29tbWFuZCBvZiB0eXBlIHNwX2V2ZW50IGlzCiAqIHJlY2VpdmVkLgogKiBTdG9yZSB0aGUgZXZlbnQgaW4gdGhlIGNpcmN1bGFyIGV2ZW50IGJ1ZmZlciwgd2FrZSB1cCBhbnkgc2xlZXBpbmcKICogZXZlbnQgcmVhZGVycy4KICogVGhlcmUgaXMgbm8gcmVhZGVyIG1hcmtlciBpbiB0aGUgYnVmZmVyLCB0aGVyZWZvcmUgcmVhZGVycyBhcmUKICogcmVzcG9uc2libGUgZm9yIGtlZXBpbmcgdXAgd2l0aCB0aGUgd3JpdGVyLCBvciB0aGV5IHdpbGwgbG9vc2UgZXZlbnRzLgogKi8gCnZvaWQgaWJtYXNtX3JlY2VpdmVfZXZlbnQoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCwgdm9pZCAqZGF0YSwgdW5zaWduZWQgaW50IGRhdGFfc2l6ZSkKewoJc3RydWN0IGV2ZW50X2J1ZmZlciAqYnVmZmVyID0gc3AtPmV2ZW50X2J1ZmZlcjsKCXN0cnVjdCBpYm1hc21fZXZlbnQgKmV2ZW50OwoJdW5zaWduZWQgbG9uZyBmbGFnczsKCglkYXRhX3NpemUgPSBtaW4oZGF0YV9zaXplLCBJQk1BU01fRVZFTlRfTUFYX1NJWkUpOwoKCXNwaW5fbG9ja19pcnFzYXZlKCZzcC0+bG9jaywgZmxhZ3MpOwoJLyogY29weSB0aGUgZXZlbnQgaW50byB0aGUgbmV4dCBzbG90IGluIHRoZSBjaXJjdWxhciBidWZmZXIgKi8KCWV2ZW50ID0gJmJ1ZmZlci0+ZXZlbnRzW2J1ZmZlci0+bmV4dF9pbmRleF07CgltZW1jcHkoZXZlbnQtPmRhdGEsIGRhdGEsIGRhdGFfc2l6ZSk7CglldmVudC0+ZGF0YV9zaXplID0gZGF0YV9zaXplOwoJZXZlbnQtPnNlcmlhbF9udW1iZXIgPSBidWZmZXItPm5leHRfc2VyaWFsX251bWJlcjsKCgkvKiBhZHZhbmNlIGluZGljZXMgaW4gdGhlIGJ1ZmZlciAqLwoJYnVmZmVyLT5uZXh0X2luZGV4ID0gKGJ1ZmZlci0+bmV4dF9pbmRleCArIDEpICUgSUJNQVNNX05VTV9FVkVOVFM7CglidWZmZXItPm5leHRfc2VyaWFsX251bWJlcisrOwoJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmc3AtPmxvY2ssIGZsYWdzKTsKCgl3YWtlX3VwX2V2ZW50X3JlYWRlcnMoc3ApOwp9CgpzdGF0aWMgaW5saW5lIGludCBldmVudF9hdmFpbGFibGUoc3RydWN0IGV2ZW50X2J1ZmZlciAqYiwgc3RydWN0IGV2ZW50X3JlYWRlciAqcikKewoJcmV0dXJuIAkoci0+bmV4dF9zZXJpYWxfbnVtYmVyIDwgYi0+bmV4dF9zZXJpYWxfbnVtYmVyKTsKfQoKLyoqCiAqIGdldF9uZXh0X2V2ZW50CiAqIENhbGxlZCBieSBldmVudCByZWFkZXJzIChpbml0aWF0ZWQgZnJvbSB1c2VyIHNwYWNlIHRocm91Z2ggdGhlIGZpbGUKICogc3lzdGVtKS4gCiAqIFNsZWVwcyB1bnRpbCBhIG5ldyBldmVudCBpcyBhdmFpbGFibGUuCiAqLwppbnQgaWJtYXNtX2dldF9uZXh0X2V2ZW50KHN0cnVjdCBzZXJ2aWNlX3Byb2Nlc3NvciAqc3AsIHN0cnVjdCBldmVudF9yZWFkZXIgKnJlYWRlcikKewoJc3RydWN0IGV2ZW50X2J1ZmZlciAqYnVmZmVyID0gc3AtPmV2ZW50X2J1ZmZlcjsKCXN0cnVjdCBpYm1hc21fZXZlbnQgKmV2ZW50OwoJdW5zaWduZWQgaW50IGluZGV4OwoJdW5zaWduZWQgbG9uZyBmbGFnczsKCglpZiAod2FpdF9ldmVudF9pbnRlcnJ1cHRpYmxlKHJlYWRlci0+d2FpdCwgZXZlbnRfYXZhaWxhYmxlKGJ1ZmZlciwgcmVhZGVyKSkpCgkJcmV0dXJuIC1FUkVTVEFSVFNZUzsKCglpZiAoIWV2ZW50X2F2YWlsYWJsZShidWZmZXIsIHJlYWRlcikpCgkJcmV0dXJuIDA7CgoJc3Bpbl9sb2NrX2lycXNhdmUoJnNwLT5sb2NrLCBmbGFncyk7CgoJaW5kZXggPSBidWZmZXItPm5leHRfaW5kZXg7CglldmVudCA9ICZidWZmZXItPmV2ZW50c1tpbmRleF07Cgl3aGlsZSAoZXZlbnQtPnNlcmlhbF9udW1iZXIgPCByZWFkZXItPm5leHRfc2VyaWFsX251bWJlcikgewoJCWluZGV4ID0gKGluZGV4ICsgMSkgJSBJQk1BU01fTlVNX0VWRU5UUzsKCQlldmVudCA9ICZidWZmZXItPmV2ZW50c1tpbmRleF07Cgl9CgltZW1jcHkocmVhZGVyLT5kYXRhLCBldmVudC0+ZGF0YSwgZXZlbnQtPmRhdGFfc2l6ZSk7CglyZWFkZXItPmRhdGFfc2l6ZSA9IGV2ZW50LT5kYXRhX3NpemU7CglyZWFkZXItPm5leHRfc2VyaWFsX251bWJlciA9IGV2ZW50LT5zZXJpYWxfbnVtYmVyICsgMTsKCglzcGluX3VubG9ja19pcnFyZXN0b3JlKCZzcC0+bG9jaywgZmxhZ3MpOwoKCXJldHVybiBldmVudC0+ZGF0YV9zaXplOwp9Cgp2b2lkIGlibWFzbV9ldmVudF9yZWFkZXJfcmVnaXN0ZXIoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCwgc3RydWN0IGV2ZW50X3JlYWRlciAqcmVhZGVyKQp7Cgl1bnNpZ25lZCBsb25nIGZsYWdzOwoKCXJlYWRlci0+bmV4dF9zZXJpYWxfbnVtYmVyID0gc3AtPmV2ZW50X2J1ZmZlci0+bmV4dF9zZXJpYWxfbnVtYmVyOwoJaW5pdF93YWl0cXVldWVfaGVhZCgmcmVhZGVyLT53YWl0KTsKCXNwaW5fbG9ja19pcnFzYXZlKCZzcC0+bG9jaywgZmxhZ3MpOwoJbGlzdF9hZGQoJnJlYWRlci0+bm9kZSwgJnNwLT5ldmVudF9idWZmZXItPnJlYWRlcnMpOwoJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmc3AtPmxvY2ssIGZsYWdzKTsKfQoKdm9pZCBpYm1hc21fZXZlbnRfcmVhZGVyX3VucmVnaXN0ZXIoc3RydWN0IHNlcnZpY2VfcHJvY2Vzc29yICpzcCwgc3RydWN0IGV2ZW50X3JlYWRlciAqcmVhZGVyKQp7Cgl1bnNpZ25lZCBsb25nIGZsYWdzOwoKCXdha2VfdXBfaW50ZXJydXB0aWJsZSgmcmVhZGVyLT53YWl0KTsKCglzcGluX2xvY2tfaXJxc2F2ZSgmc3AtPmxvY2ssIGZsYWdzKTsKCWxpc3RfZGVsKCZyZWFkZXItPm5vZGUpOwoJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmc3AtPmxvY2ssIGZsYWdzKTsKfQoKaW50IGlibWFzbV9ldmVudF9idWZmZXJfaW5pdChzdHJ1Y3Qgc2VydmljZV9wcm9jZXNzb3IgKnNwKQp7CglzdHJ1Y3QgZXZlbnRfYnVmZmVyICpidWZmZXI7CglzdHJ1Y3QgaWJtYXNtX2V2ZW50ICpldmVudDsKCWludCBpOwoKCWJ1ZmZlciA9IGttYWxsb2Moc2l6ZW9mKHN0cnVjdCBldmVudF9idWZmZXIpLCBHRlBfS0VSTkVMKTsKCWlmICghYnVmZmVyKQoJCXJldHVybiAxOwoKCWJ1ZmZlci0+bmV4dF9pbmRleCA9IDA7CglidWZmZXItPm5leHRfc2VyaWFsX251bWJlciA9IDE7CgoJZXZlbnQgPSBidWZmZXItPmV2ZW50czsKCWZvciAoaT0wOyBpPElCTUFTTV9OVU1fRVZFTlRTOyBpKyssIGV2ZW50KyspCgkJZXZlbnQtPnNlcmlhbF9udW1iZXIgPSAwOwoKCUlOSVRfTElTVF9IRUFEKCZidWZmZXItPnJlYWRlcnMpOwoKCXNwLT5ldmVudF9idWZmZXIgPSBidWZmZXI7CgoJcmV0dXJuIDA7Cn0KCnZvaWQgaWJtYXNtX2V2ZW50X2J1ZmZlcl9leGl0KHN0cnVjdCBzZXJ2aWNlX3Byb2Nlc3NvciAqc3ApCnsKCXdha2VfdXBfZXZlbnRfcmVhZGVycyhzcCk7CglrZnJlZShzcC0+ZXZlbnRfYnVmZmVyKTsKfQo=