LyoKICogIEhUTUwgRW50aXR5ICYgRW5jb2Rpbmcgbm9ybWFsaXphdGlvbi4KICoKICogIENvcHlyaWdodCAoQykgMjAwNi0yMDA3IFT2cvZrIEVkdmluIDxlZHdpbkBjbGFtYXYubmV0PgogKgogKiAgVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkKICogIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lvbiAyIGFzIAogKiAgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24uCiAqCiAqICBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqICBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCiAqICBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKICogIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqICBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sCiAqICBNQSAwMjExMC0xMzAxLCBVU0EuCiAqCiAqLwojaW5jbHVkZSA8Y2xhbWF2LWNvbmZpZy5oPgoKI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKI2luY2x1ZGUgImNsdHlwZXMuaCIKI2luY2x1ZGUgImNsYW1hdi5oIgojaW5jbHVkZSAib3RoZXJzLmgiCiNpbmNsdWRlICJoYXNodGFiLmgiCgoKc3RhdGljIGNvbnN0IHNpemVfdCBwcmltZV9saXN0W10gPQp7CiAgICAgNTN1bCwgICAgICAgICA5N3VsLCAgICAgICAgIDE5M3VsLCAgICAgICAzODl1bCwgICAgICAgNzY5dWwsCiAgICAgMTU0M3VsLCAgICAgICAzMDc5dWwsICAgICAgIDYxNTF1bCwgICAgICAxMjI4OXVsLCAgICAgMjQ1OTN1bCwKICAgICA0OTE1N3VsLCAgICAgIDk4MzE3dWwsICAgICAgMTk2NjEzdWwsICAgIDM5MzI0MXVsLCAgICA3ODY0MzN1bCwKICAgICAxNTcyODY5dWwsICAgIDMxNDU3Mzl1bCwgICAgNjI5MTQ2OXVsLCAgIDEyNTgyOTE3dWwsICAyNTE2NTg0M3VsLAogICAgIDUwMzMxNjUzdWwsICAgMTAwNjYzMzE5dWwsICAyMDEzMjY2MTF1bCwgNDAyNjUzMTg5dWwsIDgwNTMwNjQ1N3VsLAogICAgIDE2MTA2MTI3NDF1bCwgMzIyMTIyNTQ3M3VsCn07CgoKc3RhdGljIGNvbnN0IHNpemVfdCBwcmltZV9uID0gc2l6ZW9mKHByaW1lX2xpc3QpL3NpemVvZihwcmltZV9saXN0WzBdKTsKCnN0YXRpYyB1bnNpZ25lZCBjaGFyIERFTEVURURfS0VZW10gPSAiIjsKCnN0YXRpYyBzaXplX3QgZ2V0X25lYXJlc3RfY2FwYWNpdHkoY29uc3Qgc2l6ZV90IGNhcGFjaXR5KQp7CglzaXplX3QgaTsKCWZvcihpPTAgO2kgPCBwcmltZV9uOyBpKyspIHsKCQlpZiAocHJpbWVfbGlzdFtpXSA+IGNhcGFjaXR5KQoJCQlyZXR1cm4gcHJpbWVfbGlzdFtpXTsKCX0KCWNsaV9lcnJtc2coIlJlcXVlc3RlZCBoYXNodGFibGUgc2l6ZSBpcyB0b28gYmlnISIpOwoJcmV0dXJuIHByaW1lX2xpc3RbcHJpbWVfbi0xXTsKfQoKI2lmZGVmIFBST0ZJTEVfSEFTSFRBQkxFCi8qIEkga25vdywgdGhpcyBpcyB1Z2x5LCBtb3N0IG9mIHRoZXNlIGZ1bmN0aW9ucyBnZXQgYSBjb25zdCBzLCB0aGF0IGdldHMgaXRzIGNvbnN0LW5lc3MgZGlzY2FyZGVkLAogKiBhbmQgdGhlbiB0aGVzZSBmdW5jdGlvbnMgbW9kaWZ5IHNvbWV0aGluZyB0aGUgY29tcGlsZXIgYXNzdW1lcyBpcyByZWFkb25seS4KICogUGxlYXNlLCBuZXZlciB1c2UgUFJPRklMRV9IQVNIVEFCTEUgaW4gcHJvZHVjdGlvbiBjb2RlLCBhbmQgaW4gcmVsZWFzZXMuIFVzZSBpdCBmb3IgZGV2ZWxvcG1lbnQgb25seSEqLwoKc3RhdGljIGlubGluZSB2b2lkIFBST0ZJTEVfSU5JVChzdHJ1Y3QgaGFzaHRhYmxlICpzKQp7CgltZW1zZXQoJnMtPlBST0ZJTEVfU1RSVUNULDAsc2l6ZW9mKHMtPlBST0ZJTEVfU1RSVUNUKSk7Cn0KCnN0YXRpYyBpbmxpbmUgdm9pZCBQUk9GSUxFX0NBTENfSEFTSChzdHJ1Y3QgaGFzaHRhYmxlICpzKQp7CglzLT5QUk9GSUxFX1NUUlVDVC5jYWxjX2hhc2grKzsKfQoKc3RhdGljIGlubGluZSB2b2lkIFBST0ZJTEVfRklORF9FTEVNRU5UKHN0cnVjdCBoYXNodGFibGUgKnMpCnsKCXMtPlBST0ZJTEVfU1RSVUNULmZpbmRfcmVxKys7Cn0KCnN0YXRpYyBpbmxpbmUgdm9pZCBQUk9GSUxFX0ZJTkRfTk9URk9VTkQoc3RydWN0IGhhc2h0YWJsZSAqcywgc2l6ZV90IHRyaWVzKQp7CglzLT5QUk9GSUxFX1NUUlVDVC5ub3RfZm91bmQrKzsKCXMtPlBST0ZJTEVfU1RSVUNULm5vdF9mb3VuZF90cmllcyArPSB0cmllczsKfQoKc3RhdGljIGlubGluZSB2b2lkIFBST0ZJTEVfRklORF9GT1VORChzdHJ1Y3QgaGFzaHRhYmxlICpzLCBzaXplX3QgdHJpZXMpCnsKCXMtPlBST0ZJTEVfU1RSVUNULmZvdW5kKys7CglzLT5QUk9GSUxFX1NUUlVDVC5mb3VuZF90cmllcyArPSB0cmllczsKfQoKc3RhdGljIGlubGluZSB2b2lkIFBST0ZJTEVfSEFTSF9FWEhBVVNURUQoc3RydWN0IGhhc2h0YWJsZSAqcykKewoJcy0+UFJPRklMRV9TVFJVQ1QuaGFzaF9leGhhdXN0ZWQrKzsKfQoKc3RhdGljIGlubGluZSB2b2lkIFBST0ZJTEVfR1JPV19TVEFSVChzdHJ1Y3QgaGFzaHRhYmxlICpzKQp7CglzLT5QUk9GSUxFX1NUUlVDVC5ncm93Kys7Cn0KCnN0YXRpYyBpbmxpbmUgdm9pZCBQUk9GSUxFX0dST1dfRk9VTkQoc3RydWN0IGhhc2h0YWJsZSAqcywgc2l6ZV90IHRyaWVzKQp7CglzLT5QUk9GSUxFX1NUUlVDVC5ncm93X2ZvdW5kKys7CglzLT5QUk9GSUxFX1NUUlVDVC5ncm93X2ZvdW5kX3RyaWVzICs9IHRyaWVzOwp9CgpzdGF0aWMgaW5saW5lIHZvaWQgUFJPRklMRV9HUk9XX0RPTkUoc3RydWN0IGhhc2h0YWJsZSAqcykKewp9CgpzdGF0aWMgaW5saW5lIHZvaWQgUFJPRklMRV9ERUxFVEVEX1JFVVNFKHN0cnVjdCBoYXNodGFibGUgKnMsIHNpemVfdCB0cmllcykKewoJcy0+UFJPRklMRV9TVFJVQ1QuZGVsZXRlZF9yZXVzZSsrOwoJcy0+UFJPRklMRV9TVFJVQ1QuZGVsZXRlZF90cmllcyArPSB0cmllczsKfQoKc3RhdGljIGlubGluZSB2b2lkIFBST0ZJTEVfSU5TRVJUKHN0cnVjdCBoYXNodGFibGUgKnMsIHNpemVfdCB0cmllcykKewoJcy0+UFJPRklMRV9TVFJVQ1QuaW5zZXJ0cysrOwoJcy0+UFJPRklMRV9TVFJVQ1QuaW5zZXJ0X3RyaWVzICs9IHRyaWVzOwp9CgpzdGF0aWMgaW5saW5lIHZvaWQgUFJPRklMRV9EQVRBX1VQREFURShzdHJ1Y3QgaGFzaHRhYmxlICpzLCBzaXplX3QgdHJpZXMpCnsKCXMtPlBST0ZJTEVfU1RSVUNULnVwZGF0ZSsrOwoJcy0+UFJPRklMRV9TVFJVQ1QudXBkYXRlX3RyaWVzICs9IHRyaWVzOwp9CgpzdGF0aWMgaW5saW5lIHZvaWQgUFJPRklMRV9IQVNIX0RFTEVURShzdHJ1Y3QgaGFzaHRhYmxlICpzKQp7CglzLT5QUk9GSUxFX1NUUlVDVC5kZWxldGVzKys7Cn0KCnN0YXRpYyBpbmxpbmUgdm9pZCBQUk9GSUxFX0hBU0hfQ0xFQVIoc3RydWN0IGhhc2h0YWJsZSAqcykKewoJcy0+UFJPRklMRV9TVFJVQ1QuY2xlYXIrKzsKfQoKc3RhdGljIGlubGluZSB2b2lkIFBST0ZJTEVfUkVQT1JUKGNvbnN0IHN0cnVjdCBoYXNodGFibGUgKnMpCnsKCXNpemVfdCBsb29rdXBzLCBxdWVyaWVzLCBpbnNlcnRfdHJpZXMsIGluc2VydHM7CgljbGlfZGJnbXNnKCItLS0tLS0tLUhhc2h0YWJsZSB1c2FnZSByZXBvcnQgZm9yICVwLS0tLS0tLS0tLS0tLS1cbiIsKGNvbnN0IHZvaWQqKXMpOwoJY2xpX2RiZ21zZygiaGFzaCBmdW5jdGlvbiBjYWxjdWxhdGlvbnM6JWxkXG4iLHMtPlBST0ZJTEVfU1RSVUNULmNhbGNfaGFzaCk7CgljbGlfZGJnbXNnKCJzdWNjZXNzZnVsbCBmaW5kcy90b3RhbCBzZWFyY2hlczogJWxkLyVsZDsgbG9va3VwczogJWxkXG4iLCBzLT5QUk9GSUxFX1NUUlVDVC5mb3VuZCwgcy0+UFJPRklMRV9TVFJVQ1QuZmluZF9yZXEsIHMtPlBST0ZJTEVfU1RSVUNULmZvdW5kX3RyaWVzKTsKCWNsaV9kYmdtc2coInVuc3VjY2Vzc2Z1bGwgZmluZHMvdG90YWwgc2VhcmNoZXM6ICVsZC8lbGQ7IGxvb2t1cHM6ICVsZFxuIiwgcy0+UFJPRklMRV9TVFJVQ1Qubm90X2ZvdW5kLCBzLT5QUk9GSUxFX1NUUlVDVC5maW5kX3JlcSAsIHMtPlBST0ZJTEVfU1RSVUNULm5vdF9mb3VuZF90cmllcyk7CgljbGlfZGJnbXNnKCJzdWNjZXNzZnVsbCBmaW5kcyBkdXJpbmcgZ3JvdzolbGQ7IGxvb2t1cHM6ICVsZFxuIixzLT5QUk9GSUxFX1NUUlVDVC5ncm93X2ZvdW5kLCBzLT5QUk9GSUxFX1NUUlVDVC5ncm93X2ZvdW5kX3RyaWVzKTsKCWxvb2t1cHMgPSBzLT5QUk9GSUxFX1NUUlVDVC5mb3VuZF90cmllcyArIHMtPlBST0ZJTEVfU1RSVUNULm5vdF9mb3VuZF90cmllcyArIHMtPlBST0ZJTEVfU1RSVUNULmdyb3dfZm91bmRfdHJpZXM7CglxdWVyaWVzID0gcy0+UFJPRklMRV9TVFJVQ1QuZmluZF9yZXEgKyBzLT5QUk9GSUxFX1NUUlVDVC5ncm93X2ZvdW5kOwoJY2xpX2RiZ21zZygiRmluZCBMb29rdXBzL3RvdGFsIHF1ZXJpZXM6ICVsZC8lbGQgPSAlM2ZcbiIsIGxvb2t1cHMsIHF1ZXJpZXMsIGxvb2t1cHMqMS4wL3F1ZXJpZXMpOwoJaW5zZXJ0X3RyaWVzID0gcy0+UFJPRklMRV9TVFJVQ1QuaW5zZXJ0X3RyaWVzICsgcy0+UFJPRklMRV9TVFJVQ1QudXBkYXRlX3RyaWVzICsgcy0+UFJPRklMRV9TVFJVQ1QuZGVsZXRlZF90cmllczsKCgljbGlfZGJnbXNnKCJuZXcgaXRlbSBpbnNlcnQgdHJpZXMvbmV3IGl0ZW1zOiAlbGQvJWxkXG4iLCBzLT5QUk9GSUxFX1NUUlVDVC5pbnNlcnRfdHJpZXMsIHMtPlBST0ZJTEVfU1RSVUNULmluc2VydHMpOwoJY2xpX2RiZ21zZygidXBkYXRlIHRyaWVzL3VwZGF0ZXM6ICVsZC8lbGRcbiIsIHMtPlBST0ZJTEVfU1RSVUNULnVwZGF0ZV90cmllcywgcy0+UFJPRklMRV9TVFJVQ1QudXBkYXRlKTsKCWNsaV9kYmdtc2coImRlbGV0ZWQgaXRlbSByZXVzZSB0cmllcy9kZWxldGVkJnJldXNlZCBpdGVtczogJWxkLyVsZFxuIiwgcy0+UFJPRklMRV9TVFJVQ1QuZGVsZXRlZF90cmllcywgcy0+UFJPRklMRV9TVFJVQ1QuZGVsZXRlZF9yZXVzZSk7CglpbnNlcnRzID0gcy0+UFJPRklMRV9TVFJVQ1QuaW5zZXJ0cyArIHMtPlBST0ZJTEVfU1RSVUNULnVwZGF0ZSArIHMtPlBST0ZJTEVfU1RSVUNULmRlbGV0ZWRfcmV1c2U7CgljbGlfZGJnbXNnKCJJbnNlcnQgdHJpZXMvdG90YWwgaW5zZXJ0czogJWxkLyVsZCA9ICUzZlxuIiwgaW5zZXJ0X3RyaWVzLCBpbnNlcnRzLCBpbnNlcnRfdHJpZXMqMS4wL2luc2VydHMpOwoKCWNsaV9kYmdtc2coIkdyb3dzOiAlbGQsIERlbGV0ZXMgOiAlbGQsIGhhc2h0YWJsZSBjbGVhcnM6ICVsZFxuIixzLT5QUk9GSUxFX1NUUlVDVC5ncm93LHMtPlBST0ZJTEVfU1RSVUNULmRlbGV0ZXMsIHMtPlBST0ZJTEVfU1RSVUNULmNsZWFyKTsKICAgICAgICBjbGlfZGJnbXNnKCItLS0tLS0tLVJlcG9ydCBlbmQtLS0tLS0tLS0tLS0tXG4iKTsJCn0KCiNlbHNlCiNkZWZpbmUgUFJPRklMRV9JTklUKHMpIAojZGVmaW5lIFBST0ZJTEVfQ0FMQ19IQVNIKHMpIAojZGVmaW5lIFBST0ZJTEVfRklORF9FTEVNRU5UKHMpIAojZGVmaW5lIFBST0ZJTEVfRklORF9OT1RGT1VORChzLCB0cmllcykgCiNkZWZpbmUgUFJPRklMRV9GSU5EX0ZPVU5EKHMsIHRyaWVzKQojZGVmaW5lIFBST0ZJTEVfSEFTSF9FWEhBVVNURUQocykKI2RlZmluZSBQUk9GSUxFX0dST1dfU1RBUlQocykKI2RlZmluZSBQUk9GSUxFX0dST1dfRk9VTkQocywgdHJpZXMpCiNkZWZpbmUgUFJPRklMRV9HUk9XX0RPTkUocykKI2RlZmluZSBQUk9GSUxFX0RFTEVURURfUkVVU0UocywgdHJpZXMpCiNkZWZpbmUgUFJPRklMRV9JTlNFUlQocywgdHJpZXMpCiNkZWZpbmUgUFJPRklMRV9EQVRBX1VQREFURShzLCB0cmllcykKI2RlZmluZSBQUk9GSUxFX0hBU0hfREVMRVRFKHMpCiNkZWZpbmUgUFJPRklMRV9IQVNIX0NMRUFSKHMpCiNkZWZpbmUgUFJPRklMRV9SRVBPUlQocykKI2VuZGlmCgppbnQgaGFzaHRhYl9pbml0KHN0cnVjdCBoYXNodGFibGUgKnMsc2l6ZV90IGNhcGFjaXR5KQp7CglpZighcykKCQlyZXR1cm4gQ0xfRU5VTExBUkc7CgoJUFJPRklMRV9JTklUKHMpOwoKCWNhcGFjaXR5ID0gZ2V0X25lYXJlc3RfY2FwYWNpdHkoY2FwYWNpdHkpOwoJcy0+aHRhYmxlID0gY2xpX2NhbGxvYyhjYXBhY2l0eSxzaXplb2YoKnMtPmh0YWJsZSkpOwoJaWYoIXMtPmh0YWJsZSkKCQlyZXR1cm4gQ0xfRU1FTTsKCXMtPmNhcGFjaXR5ID0gY2FwYWNpdHk7CglzLT51c2VkID0gMDsKCXMtPm1heGZpbGwgPSA4KmNhcGFjaXR5LzEwOwoJcmV0dXJuIDA7Cn0KCnN0YXRpYyBzaXplX3QgaGFzaChjb25zdCB1bnNpZ25lZCBjaGFyKiBrLGNvbnN0IHNpemVfdCBsZW4sY29uc3Qgc2l6ZV90IFNJWkUpCnsKCXNpemVfdCBIYXNoID0gMDsJCglzaXplX3QgaTsKCWZvcihpPWxlbjtpPjA7aS0tKQoJCUhhc2ggPSAoKEhhc2ggPDwgOCkgKyBrW2ktMV0pICUgU0laRTsKCXJldHVybiBIYXNoOwp9CgovKiBpZiByZXR1cm5lZCBlbGVtZW50IGhhcyBrZXk9PU5VTEwsIHRoZW4ga2V5IHdhcyBub3QgZm91bmQgaW4gdGFibGUgKi8Kc3RydWN0IGVsZW1lbnQqIGhhc2h0YWJfZmluZChjb25zdCBzdHJ1Y3QgaGFzaHRhYmxlICpzLGNvbnN0IHVuc2lnbmVkIGNoYXIqIGtleSxjb25zdCBzaXplX3QgbGVuKQp7CglzdHJ1Y3QgZWxlbWVudCogZWxlbWVudDsKCXNpemVfdCB0cmllcyA9IDE7IAoJc2l6ZV90IGlkeDsKCglpZighcykKCQlyZXR1cm4gTlVMTDsgCglQUk9GSUxFX0NBTENfSEFTSChzKTsKCVBST0ZJTEVfRklORF9FTEVNRU5UKHMpOwoJaWR4ID0gaGFzaChrZXksIGxlbiwgcy0+Y2FwYWNpdHkpOyAKCWVsZW1lbnQgPSAmcy0+aHRhYmxlW2lkeF07CglkbyB7CgkJaWYoIWVsZW1lbnQtPmtleSkgewoJCQlQUk9GSUxFX0ZJTkRfTk9URk9VTkQocywgdHJpZXMpOwoJCQlyZXR1cm4gTlVMTDsgLyogZWxlbWVudCBub3QgZm91bmQsIHBsYWNlIGlzIGVtcHR5Ki8KCQl9CgkJZWxzZSBpZihlbGVtZW50LT5rZXkgIT0gREVMRVRFRF9LRVkgJiYgc3RybmNtcCgoY29uc3QgY2hhciopa2V5LChjb25zdCBjaGFyKillbGVtZW50LT5rZXksbGVuKT09MCkgewoJCQlQUk9GSUxFX0ZJTkRfRk9VTkQocywgdHJpZXMpOwoJCQlyZXR1cm4gZWxlbWVudDsvKiBmb3VuZCAqLwoJCX0KCQllbHNlIHsKCQkJaWR4ID0gKGlkeCArIHRyaWVzKyspICUgcy0+Y2FwYWNpdHk7CgkJCWVsZW1lbnQgPSAmcy0+aHRhYmxlW2lkeF07CgkJfQoJfSB3aGlsZSAodHJpZXMgPD0gcy0+Y2FwYWNpdHkpOwoJUFJPRklMRV9IQVNIX0VYSEFVU1RFRChzKTsKCXJldHVybiBOVUxMOyAvKiBub3QgZm91bmQgKi8KfQoKc3RhdGljIGludCBoYXNodGFiX2dyb3coc3RydWN0IGhhc2h0YWJsZSAqcykKewoJY29uc3Qgc2l6ZV90IG5ld19jYXBhY2l0eSA9IGdldF9uZWFyZXN0X2NhcGFjaXR5KHMtPmNhcGFjaXR5KTsKCXN0cnVjdCBlbGVtZW50KiBodGFibGUgPSBjbGlfY2FsbG9jKG5ld19jYXBhY2l0eSwgc2l6ZW9mKCpzLT5odGFibGUpKTsKCXNpemVfdCBpLGlkeCwgdXNlZCA9IDA7CglpZihuZXdfY2FwYWNpdHkgPT0gcy0+Y2FwYWNpdHkgfHwgIWh0YWJsZSkKCQlyZXR1cm4gQ0xfRU1FTTsKCglQUk9GSUxFX0dST1dfU1RBUlQocyk7CgljbGlfZGJnbXNnKCJoYXNodGFiLmM6IFdhcm5pbmc6IGdyb3dpbmcgb3Blbi1hZGRyZXNzaW5nIGhhc2h0YWJsZXMgaXMgc2xvdy4gRWl0aGVyIGFsbG9jYXRlIG1vcmUgc3RvcmFnZSB3aGVuIGluaXRpYWxpemluZywgb3IgdXNlIG90aGVyIGhhc2h0YWJsZSB0eXBlcyFcbiIpOwoJZm9yKGk9MDsgaSA8IHMtPmNhcGFjaXR5O2krKykgewoJCWlmKHMtPmh0YWJsZVtpXS5rZXkgJiYgcy0+aHRhYmxlW2ldLmtleSAhPSBERUxFVEVEX0tFWSkgewoJCQlzdHJ1Y3QgZWxlbWVudCogZWxlbWVudDsKCQkJc2l6ZV90IHRyaWVzID0gMTsJCQkJCgoJCQlQUk9GSUxFX0NBTENfSEFTSChzKTsKCQkJaWR4ID0gaGFzaChzLT5odGFibGVbaV0ua2V5LCBzdHJsZW4oKGNvbnN0IGNoYXIqKXMtPmh0YWJsZVtpXS5rZXkpLCBuZXdfY2FwYWNpdHkpOwoJCQllbGVtZW50ID0gJmh0YWJsZVtpZHhdOwoKCQkJd2hpbGUoZWxlbWVudC0+a2V5ICYmIHRyaWVzIDw9IG5ld19jYXBhY2l0eSkgewoJCQkJaWR4ID0gKGlkeCArIHRyaWVzKyspICUgbmV3X2NhcGFjaXR5OwoJCQkJZWxlbWVudCA9ICZodGFibGVbaWR4XTsKCQkJfQoJCQlpZighZWxlbWVudC0+a2V5KSB7CgkJCQkvKiBjb3B5IGVsZW1lbnQgZnJvbSBvbGQgaGFzaHRhYmxlIHRvIG5ldyAqLwoJCQkJUFJPRklMRV9HUk9XX0ZPVU5EKHMsIHRyaWVzKTsKCQkJCSplbGVtZW50ID0gcy0+aHRhYmxlW2ldOwoJCQkJdXNlZCsrOwoJCQl9CgkJCWVsc2UgewoJCQkJY2xpX2Vycm1zZygiaGFzaHRhYi5jOiBJbXBvc3NpYmxlIC0gdW5hYmxlIHRvIHJlaGFzaCB0YWJsZSIpOwoJCQkJcmV0dXJuIENMX0VNRU07LyogdGhpcyBtZWFucyB3ZSBkaWRuJ3QgZmluZCBlbm91Z2ggcm9vbSBmb3IgYWxsIGVsZW1lbnRzIGluIHRoZSBuZXcgdGFibGUsIHNob3VsZCBuZXZlciBoYXBwZW4gKi8gCgkJCX0KCQl9Cgl9CglmcmVlKHMtPmh0YWJsZSk7CglzLT5odGFibGUgPSBodGFibGU7CglzLT51c2VkID0gdXNlZDsKCXMtPmNhcGFjaXR5ID0gbmV3X2NhcGFjaXR5OwoJcy0+bWF4ZmlsbCA9IG5ld19jYXBhY2l0eSo4LzEwOwoJY2xpX2RiZ21zZygiVGFibGUgJXAgc2l6ZSBhZnRlciBncm93OiVsZFxuIiwodm9pZCopcyxzLT5jYXBhY2l0eSk7CglQUk9GSUxFX0dST1dfRE9ORShzKTsKCXJldHVybiBDTF9TVUNDRVNTOwp9CgoKaW50IGhhc2h0YWJfaW5zZXJ0KHN0cnVjdCBoYXNodGFibGUgKnMsY29uc3QgdW5zaWduZWQgY2hhcioga2V5LGNvbnN0IHNpemVfdCBsZW4sY29uc3QgZWxlbWVudF9kYXRhIGRhdGEpCnsKCXN0cnVjdCBlbGVtZW50KiBlbGVtZW50OwoJc3RydWN0IGVsZW1lbnQqIGRlbGV0ZWRfZWxlbWVudCA9IE5VTEw7CglzaXplX3QgdHJpZXMgPSAxOyAKCXNpemVfdCBpZHg7CglpZighcykKCQlyZXR1cm4gQ0xfRU5VTExBUkc7IAoJZG8gewoJCVBST0ZJTEVfQ0FMQ19IQVNIKHMpOwoJCWlkeCA9IGhhc2goa2V5LCBsZW4sIHMtPmNhcGFjaXR5KTsgCgkJZWxlbWVudCA9ICZzLT5odGFibGVbaWR4XTsKCgkJZG8gewoJCQlpZighZWxlbWVudC0+a2V5KSB7CgkJCQl1bnNpZ25lZCBjaGFyKiB0aGVrZXk7CgkJCQkvKiBlbGVtZW50IG5vdCBmb3VuZCwgcGxhY2UgaXMgZW1wdHksIGluc2VydCovCgkJCQlpZihkZWxldGVkX2VsZW1lbnQpIHsKCQkJCQkvKiByZXVzZSBkZWxldGVkIGVsZW1lbnRzKi8KCQkJCQllbGVtZW50ID0gZGVsZXRlZF9lbGVtZW50OwoJCQkJCVBST0ZJTEVfREVMRVRFRF9SRVVTRShzLCB0cmllcyk7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQlQUk9GSUxFX0lOU0VSVChzLCB0cmllcyk7CgkJCQl9CgkJCQl0aGVrZXkgPSBjbGlfbWFsbG9jKGxlbisxKTsKCQkJCWlmKCF0aGVrZXkpCgkJCQkJcmV0dXJuIENMX0VNRU07CgkJCQlzdHJuY3B5KChjaGFyKil0aGVrZXksKGNvbnN0IGNoYXIqKWtleSxsZW4rMSk7CgkJCQllbGVtZW50LT5rZXkgPSB0aGVrZXk7CgkJCQllbGVtZW50LT5kYXRhID0gZGF0YTsKCQkJCXMtPnVzZWQrKzsJCQoJCQkJaWYocy0+dXNlZCA+IHMtPm1heGZpbGwpIHsKCQkJCQljbGlfZGJnbXNnKCJoYXNodGFiLmM6R3Jvd2luZyBoYXNodGFibGUgJXAsIGJlY2F1c2UgaXQgaGFzIGV4Y2VlZGVkIG1heGZpbGwsIG9sZCBzaXplOiVsZFxuIiwodm9pZCopcyxzLT5jYXBhY2l0eSk7CgkJCQkJaGFzaHRhYl9ncm93KHMpOwoJCQkJfQoJCQkJcmV0dXJuIDA7CgkJCX0KCQkJZWxzZSBpZihlbGVtZW50LT5rZXkgPT0gREVMRVRFRF9LRVkpIHsKCQkJCWRlbGV0ZWRfZWxlbWVudCA9IGVsZW1lbnQ7CgkJCX0KCQkJZWxzZSBpZihzdHJuY21wKChjb25zdCBjaGFyKilrZXksKGNvbnN0IGNoYXIqKWVsZW1lbnQtPmtleSxsZW4pPT0wKSB7CgkJCQlQUk9GSUxFX0RBVEFfVVBEQVRFKHMsIHRyaWVzKTsKCQkJCWVsZW1lbnQtPmRhdGEgPSBkYXRhOy8qIGtleSBmb3VuZCwgdXBkYXRlICovCgkJCQlyZXR1cm4gMDsJCQoJCQl9CgkJCWVsc2UgewoJCQkJaWR4ID0gKGlkeCArIHRyaWVzKyspICUgcy0+Y2FwYWNpdHk7CgkJCQllbGVtZW50ID0gJnMtPmh0YWJsZVtpZHhdOwoJCQl9CgkJfSB3aGlsZSAodHJpZXMgPD0gcy0+Y2FwYWNpdHkpOwoJCS8qIG5vIGZyZWUgcGxhY2UgZm91bmQqLwoJCVBST0ZJTEVfSEFTSF9FWEhBVVNURUQocyk7CgkJY2xpX2RiZ21zZygiaGFzaHRhYi5jOiBHcm93aW5nIGhhc2h0YWJsZSAlcCwgYmVjYXVzZSBpdHMgZnVsbCwgb2xkIHNpemU6JWxkLlxuIiwodm9pZCopcyxzLT5jYXBhY2l0eSk7Cgl9IHdoaWxlKCBoYXNodGFiX2dyb3cocykgPj0gMCApOwoJY2xpX3dhcm5tc2coImhhc2h0YWIuYzogVW5hYmxlIHRvIGdyb3cgaGFzaHRhYmxlXG4iKTsKCXJldHVybiBDTF9FTUVNOwp9Cgp2b2lkIGhhc2h0YWJfZGVsZXRlKHN0cnVjdCBoYXNodGFibGUgKnMsY29uc3QgdW5zaWduZWQgY2hhcioga2V5LGNvbnN0IHNpemVfdCBsZW4pCnsKCXN0cnVjdCBlbGVtZW50KiBlID0gaGFzaHRhYl9maW5kKHMsa2V5LGxlbik7CglpZihlICYmIGUtPmtleSkgewkKCQlQUk9GSUxFX0hBU0hfREVMRVRFKHMpOwoJCWZyZWUoZS0+a2V5KTsvKkZJWE1FOiBhbnkgd2F5IHRvIHNodXQgdXAgd2FybmluZ3MgaGVyZT8gaWYgSSBtYWtlIGtleSBjaGFyKiwgSSBnZXQgdG9ucyBvZiB3YXJuaW5ncyBpbiBlbnRpdHlsaXN0LmggKi8KCQllLT5rZXkgPSBERUxFVEVEX0tFWTsKCQlzLT51c2VkLS07Cgl9Cn0KCnZvaWQgaGFzaHRhYl9jbGVhcihzdHJ1Y3QgaGFzaHRhYmxlICpzKQp7CglzaXplX3QgaTsKCVBST0ZJTEVfSEFTSF9DTEVBUihzKTsKCWZvcihpPTA7aSA8IHMtPmNhcGFjaXR5O2krKykgewoJCWlmKHMtPmh0YWJsZVtpXS5rZXkgJiYgcy0+aHRhYmxlW2ldLmtleSAhPSBERUxFVEVEX0tFWSkKCQkJZnJlZShzLT5odGFibGVbaV0ua2V5KTsvKkZJWE1FOiBzaHV0IHVwIHdhcm5pbmdzICovCgl9CgltZW1zZXQocy0+aHRhYmxlLCAwLCBzLT5jYXBhY2l0eSk7CglzLT51c2VkID0gMDsKfQoKCmludCBoYXNodGFiX3N0b3JlKGNvbnN0IHN0cnVjdCBoYXNodGFibGUgKnMsRklMRSogb3V0KQp7CglzaXplX3QgaTsKCWZvcihpPTA7IGkgPCBzLT5jYXBhY2l0eTsgaSsrKSB7CgkJY29uc3Qgc3RydWN0IGVsZW1lbnQqIGUgPSAmcy0+aHRhYmxlW2ldOwoJCWlmKGUtPmtleSAmJiBlLT5rZXkgIT0gREVMRVRFRF9LRVkpIHsKCQkJZnByaW50ZihvdXQsIiVsZCAlc1xuIixlLT5kYXRhLGUtPmtleSk7CgkJfQoJfQoJcmV0dXJuIENMX1NVQ0NFU1M7Cn0KCmludCBoYXNodGFiX2dlbmVyYXRlX2MoY29uc3Qgc3RydWN0IGhhc2h0YWJsZSAqcyxjb25zdCBjaGFyKiBuYW1lKQp7CglzaXplX3QgaTsKCXByaW50ZigiLyogVE9ETzogaW5jbHVkZSBHUEwgaGVhZGVycyAqL1xuIik7CglwcmludGYoIiNpbmNsdWRlIDxoYXNodGFiLmg+XG4iKTsKCXByaW50Zigic3RhdGljIHN0cnVjdCBlbGVtZW50ICVzX2VsZW1lbnRzW10gPSB7XG4iLG5hbWUpOwoJZm9yKGk9MDsgaSA8IHMtPmNhcGFjaXR5OyBpKyspIHsKCQljb25zdCBzdHJ1Y3QgZWxlbWVudCogZSA9ICZzLT5odGFibGVbaV07CgkJaWYoIWUtPmtleSkKCQkJcHJpbnRmKCJcdHtOVUxMLCAwfSxcbiIpOwoJCWVsc2UgaWYoZS0+a2V5ID09IERFTEVURURfS0VZKQoJCQlwcmludGYoIlx0e0RFTEVURURfS0VZLDB9LFxuIik7CgkJZWxzZQoJCQlwcmludGYoIlx0eyhjb25zdCB1bnNpZ25lZCBjaGFyKilcIiVzXCIsICVsZH0sXG4iLCBlLT5rZXksIGUtPmRhdGEpOwoJfQoJcHJpbnRmKCJ9O1xuIik7CglwcmludGYoImNvbnN0IHN0cnVjdCBoYXNodGFibGUgJXMgPSB7XG4iLG5hbWUpOwoJcHJpbnRmKCJcdCVzX2VsZW1lbnRzLCAlbGQsICVsZCwgJWxkIiwgbmFtZSwgcy0+Y2FwYWNpdHksIHMtPnVzZWQsIHMtPm1heGZpbGwpOwoJcHJpbnRmKCJcbn07XG4iKTsKCglQUk9GSUxFX1JFUE9SVChzKTsKCXJldHVybiAwOwp9CgppbnQgaGFzaHRhYl9sb2FkKEZJTEUqIGluLCBzdHJ1Y3QgaGFzaHRhYmxlICpzKQp7CgljaGFyIGxpbmVbMTAyNF07Cgl3aGlsZSAoZmdldHMobGluZSwgc2l6ZW9mKGxpbmUpLCBpbikpIHsKCQl1bnNpZ25lZCBjaGFyIGxbMTAyNF07CgkJaW50IHZhbDsKCQlzc2NhbmYobGluZSwiJWQgJTEwMjNzIiwmdmFsLGwpOwoJCWhhc2h0YWJfaW5zZXJ0KHMsbCxzdHJsZW4oKGNvbnN0IGNoYXIqKWwpLHZhbCk7Cgl9CglyZXR1cm4gQ0xfU1VDQ0VTUzsKfQoK