All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <20161101185611.GA1999@localhost.localdomain>

diff --git a/a/1.txt b/N1/1.txt
index 628fa52..5fc2140 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1,1998 +1,4417 @@
-SGkgUmFmYWVsLCBTY290dCwKCgpGaXJzdCBvZmYsIGNvbmdyYXRzIG9uIHRoZSBzZXQhIEl0IGxv
-b2tzIGdvb2Qgc28gZmFyLgoKSnVzdCBzb21lIHNtYWxsIG5pdHMgYmVsb3cgc2luY2UgeW91IGhh
-dmUgdG8gcmVzcGluIGl0IGFueXdheXMgOikKCk9uIE1vbiwgT2N0IDMxLCAyMDE2IGF0IDAzOjU4
-OjE1UE0gLTA2MDAsIFNjb3R0IEJhdWVyIHdyb3RlOgo+IFRoaXMgcGF0Y2ggaW1wbGVtZW50cyB0
-aGUgbmVjZXNzYXJ5IGxvZ2ljIHRvIGJyaW5nIGFuIE9wYWwKPiBlbmFibGVkIGRyaXZlIG91dCBv
-ZiBhIGZhY3RvcnktZW5hYmxlZCBpbnRvIGEgd29ya2luZwo+IE9wYWwgc3RhdGUuCj4gCj4gVGhp
-cyBwYXRjaCBzZXQgYWxzbyBlbmFibGVzIGxvZ2ljIHRvIHNhdmUgYSBwYXNzd29yZCB0bwo+IGJl
-IHJlcGxheWVkIGR1cmluZyBhIHJlc3VtZSBmcm9tIHN1c3BlbmQuIFRoZSBrZXkgY2FuIGJlCj4g
-c2F2ZWQgaW4gdGhlIGRyaXZlciBvciBpbiB0aGUgS2VybmVsJ3MgS2V5IG1hbmFnbWVudC4KPiAK
-PiBTaWduZWQtb2ZmLWJ5OiBTY290dCBCYXVlciA8c2NvdHQuYmF1ZXJAaW50ZWwuY29tPgo+IFNp
-Z25lZC1vZmYtYnk6IFJhZmFlbCBBbnRvZ25vbGxpIDxSYWZhZWwuQW50b2dub2xsaUBpbnRlbC5j
-b20+Cj4gLS0tCj4gIGxpYi9zZWQtb3BhbC5jICAgICAgICAgIHwgMzMzNyArKysrKysrKysrKysr
-KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwo+ICBsaWIvc2VkLW9wYWxfaW50ZXJu
-YWwuaCB8ICA1ODYgKysrKysrKysrCj4gIGxpYi9zZWQtb3BhbF9rZXkuYyAgICAgIHwgICA0NiAr
-Cj4gIGxpYi9zZWQuYyAgICAgICAgICAgICAgIHwgIDMwMyArKysrKwo+ICA0IGZpbGVzIGNoYW5n
-ZWQsIDQyNzIgaW5zZXJ0aW9ucygrKQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL3NlZC1vcGFs
-LmMKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGxpYi9zZWQtb3BhbF9pbnRlcm5hbC5oCj4gIGNyZWF0
-ZSBtb2RlIDEwMDY0NCBsaWIvc2VkLW9wYWxfa2V5LmMKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGxp
-Yi9zZWQuYwo+IAo+IGRpZmYgLS1naXQgYS9saWIvc2VkLW9wYWwuYyBiL2xpYi9zZWQtb3BhbC5j
-Cj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwLi4xMGIzMzQ4Cj4gLS0tIC9k
-ZXYvbnVsbAo+ICsrKyBiL2xpYi9zZWQtb3BhbC5jCj4gQEAgLTAsMCArMSwzMzM3IEBACj4gKy8q
-Cj4gKyAqIENvcHlyaWdodCDCqSAyMDE2IEludGVsIENvcnBvcmF0aW9uCj4gKyAqCj4gKyAqIFBl
-cm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29u
-IG9idGFpbmluZyBhCj4gKyAqIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBk
-b2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCj4gKyAqIHRvIGRlYWwgaW4gdGhl
-IFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRp
-b24KPiArICogdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gs
-IGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsCj4gKyAqIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUg
-U29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZQo+ICsgKiBTb2Z0d2Fy
-ZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRp
-b25zOgo+ICsgKgo+ICsgKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJt
-aXNzaW9uIG5vdGljZSAoaW5jbHVkaW5nIHRoZSBuZXh0Cj4gKyAqIHBhcmFncmFwaCkgc2hhbGwg
-YmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUK
-PiArICogU29mdHdhcmUuCj4gKyAqCj4gKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMg
-SVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCj4gKyAqIElNUExJ
-RUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hB
-TlRBQklMSVRZLAo+ICsgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9O
-SU5GUklOR0VNRU5ULiAgSU4gTk8gRVZFTlQgU0hBTEwKPiArICogVEhFIEFVVEhPUlMgT1IgQ09Q
-WVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIK
-PiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBP
-UiBPVEhFUldJU0UsIEFSSVNJTkcKPiArICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04g
-V0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUwo+ICsgKiBJTiBU
-SEUgU09GVFdBUkUuCj4gKyAqCj4gKyAqIEF1dGhvcnM6Cj4gKyAqICAgIFJhZmFlbCBBbnRvZ25v
-bGxpIDxyYWZhZWwuYW50b2dub2xsaUBpbnRlbC5jb20+Cj4gKyAqICAgIFNjb3R0ICBCYXVlciAg
-ICAgIDxzY290dC5iYXVlckBpbnRlbC5jb20+Cj4gKyAqLwo+ICsKPiArI2RlZmluZSBwcl9mbXQo
-Zm10KSBLQlVJTERfTU9ETkFNRSAiOk9QQUw6ICIgZm10Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgv
-ZGVsYXkuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2RldmljZS5oPgo+ICsjaW5jbHVkZSA8bGludXgv
-a2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9saXN0Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9n
-ZW5oZC5oPgo+ICsjaW5jbHVkZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvdWFj
-Y2Vzcy5oPgo+ICsjaW5jbHVkZSA8dWFwaS9saW51eC9zZWQtb3BhbC5oPgo+ICsjaW5jbHVkZSA8
-bGludXgvc2VkLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zZWQtb3BhbC5oPgo+ICsjaW5jbHVkZSA8
-bGludXgvc3RyaW5nLmg+Cj4gKwo+ICsjaW5jbHVkZSAic2VkLW9wYWxfaW50ZXJuYWwuaCIKPiAr
-Cj4gKyNkZWZpbmUgSU9fQlVGRkVSX0xFTkdUSCAyMDQ4Cj4gKwo+ICsjZGVmaW5lIE1BWF9UT0tT
-IDY0Cj4gKwo+ICtzdHJ1Y3Qgb3BhbF9jbWQgewo+ICsJc3RydWN0IGJsb2NrX2RldmljZSAqYmRl
-djsKPiArCXNlY19jYiAqY2I7Cj4gKwl2b2lkICpjYl9kYXRhOwo+ICsKPiArCXNpemVfdCBwb3M7
-Cj4gKwl1OCBjbWRfYnVmW0lPX0JVRkZFUl9MRU5HVEggKiAyXTsKPiArCXU4IHJlc3BfYnVmW0lP
-X0JVRkZFUl9MRU5HVEggKiAyXTsKPiArCXU4ICpjbWQ7Cj4gKwl1OCAqcmVzcDsKPiArfTsKPiAr
-Cj4gKy8qCj4gKyAqIE9uIHRoZSBwYXJzZWQgcmVzcG9uc2UsIHdlIGRvbid0IHN0b3JlIGFnYWlu
-IHRoZSB0b2tzIHRoYXQgYXJlIGFscmVhZHkKPiArICogc3RvcmVkIGluIHRoZSByZXNwb25zZSBi
-dWZmZXIuIEluc3RlYWQsIGZvciBlYWNoIHRva2VuLCB3ZSBqdXN0IHN0b3JlIGEKPiArICogcG9p
-bnRlciB0byB0aGUgcG9zaXRpb24gaW4gdGhlIGJ1ZmZlciB3aGVyZSB0aGUgdG9rZW4gc3RhcnRz
-LCBhbmQgdGhlIHNpemUKPiArICogb2YgdGhlIHRva2VuIGluIGJ5dGVzLgo+ICsgKi8KPiArc3Ry
-dWN0IG9wYWxfcmVzcF90b2sgewo+ICsJY29uc3QgdTggKnBvczsKPiArCXNpemVfdCBsZW47Cj4g
-KwllbnVtIE9QQUxfUkVTUE9OU0VfVE9LRU4gdHlwZTsKPiArCWVudW0gT1BBTF9BVE9NX1dJRFRI
-IHdpZHRoOwo+ICsJdW5pb24gewo+ICsJCXU2NCB1Owo+ICsJCXM2NCBzOwo+ICsJfSBzdG9yZWQ7
-Cj4gK307Cj4gKwo+ICsvKgo+ICsgKiBGcm9tIHRoZSByZXNwb25zZSBoZWFkZXIgaXQncyBub3Qg
-cG9zc2libGUgdG8ga25vdyBob3cgbWFueSB0b2tlbnMgdGhlcmUgYXJlCj4gKyAqIG9uIHRoZSBw
-YXlsb2FkLiBTbyB3ZSBoYXJkY29kZSB0aGF0IHRoZSBtYXhpbXVtIHdpbGwgYmUgTUFYX1RPS1Ms
-IGFuZCBsYXRlcgo+ICsgKiBpZiB3ZSBzdGFydCBkZWFsaW5nIHdpdGggbWVzc2FnZXMgdGhhdCBo
-YXZlIG1vcmUgdGhhbiB0aGF0LCB3ZSBjYW4gaW5jcmVhc2UKPiArICogdGhpcyBudW1iZXIuIFRo
-aXMgaXMgZG9uZSB0byBhdm9pZCBoYXZpbmcgdG8gbWFrZSB0d28gcGFzc2VzIHRocm91Z2ggdGhl
-Cj4gKyAqIHJlc3BvbnNlLCB0aGUgZmlyc3Qgb25lIGNvdW50aW5nIGhvdyBtYW55IHRva2VucyB3
-ZSBoYXZlIGFuZCB0aGUgc2Vjb25kIG9uZQo+ICsgKiBhY3R1YWxseSBzdG9yaW5nIHRoZSBwb3Np
-dGlvbnMuCj4gKyAqLwo+ICtzdHJ1Y3QgcGFyc2VkX3Jlc3Agewo+ICsJaW50IG51bTsKPiArCXN0
-cnVjdCBvcGFsX3Jlc3BfdG9rIHRva3NbTUFYX1RPS1NdOwo+ICt9Owo+ICsKPiArc3RydWN0IG9w
-YWxfZGV2Owo+ICsKPiArdHlwZWRlZiB2b2lkICgqb3BhbF9jYikoaW50IGVycm9yLCBzdHJ1Y3Qg
-b3BhbF9kZXYgKmRldik7Cj4gKwo+ICt0eXBlZGVmIGludCAoKm9wYWxfc3RlcCkoc3RydWN0IG9w
-YWxfZGV2ICpkZXYpOwo+ICsKPiArc3RydWN0IG9wYWxfY29tcGxldGlvbiB7Cj4gKwlzdHJ1Y3Qg
-Y29tcGxldGlvbiBjbWRfY29tcGxldGlvbjsKPiArCWludCBjb21wbGV0aW9uX3N0YXR1czsKPiAr
-fTsKPiArCj4gK3N0cnVjdCBvcGFsX2RldiB7Cj4gKwlzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2
-Owo+ICsJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCXN0cnVjdCBvcGFs
-X2xvY2tfdW5sb2NrIGxrdWw7Cj4gKwljb25zdCBvcGFsX3N0ZXAgKmZ1bmNzOwo+ICsJdm9pZCAq
-KmZ1bmNfZGF0YTsKPiArCWJvb2wgcmVzdW1lX2Zyb21fc3VzcGVuZDsKPiArCXN0cnVjdCBvcGFs
-X3N1c3BlbmRfdW5sayAqcmVzdW1lX2RhdGE7Cj4gKwlzaXplX3QgbnVtX2Z1bmNfZGF0YTsKPiAr
-CWF0b21pY190IGluX3VzZTsKPiArCXNlY3Rvcl90IHN0YXJ0Owo+ICsJc2VjdG9yX3QgbGVuZ3Ro
-Owo+ICsJdTggbHI7Cj4gKwl1OCBrZXlfdHlwZTsKPiArCXU4IGtleV9uYW1lW09QQUxfS0VZX01B
-WF07Cj4gKwlzaXplX3Qga2V5X25hbWVfbGVuOwo+ICsJdTgga2V5W09QQUxfS0VZX01BWF07Cj4g
-KwlzaXplX3Qga2V5X2xlbjsKPiArCXUxNiBjb21JRDsKPiArCXUzMiBIU047Cj4gKwl1MzIgVFNO
-Owo+ICsJdTY0IGFsaWduOwo+ICsJdTY0IGxvd2VzdF9sYmE7Cj4gKwlzdHJ1Y3QgbGlzdF9oZWFk
-IG5vZGU7Cj4gKwljaGFyIGRpc2tfbmFtZVtESVNLX05BTUVfTEVOXTsKPiArCWludCBzdGF0ZTsK
-PiArCj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgY21kOwo+ICsJc3RydWN0IHBhcnNlZF9yZXNwIHBhcnNl
-ZDsKPiArCj4gKwlzaXplX3QgcHJldl9kX2xlbjsKPiArCXZvaWQgKnByZXZfZGF0YTsKPiArCj4g
-KwlzZWNfY2IgKmZpbmFsX2NiOwo+ICsJdm9pZCAqZmluYWxfY2JfZGF0YTsKPiArCW9wYWxfc3Rl
-cCBlcnJvcl9jYjsKPiArCXZvaWQgKmVycm9yX2NiX2RhdGE7Cj4gKwlvcGFsX2NiIG9wZXJfY2I7
-Cj4gK307Cj4gKwo+ICtMSVNUX0hFQUQob3BhbF9saXN0KTsKPiArREVGSU5FX1NQSU5MT0NLKGxp
-c3Rfc3BpbmxvY2spOwo+ICsKPiArc3RhdGljIHZvaWQgcHJpbnRfYnVmZmVyKGNvbnN0IHU4ICpw
-dHIsIHUzMiBsZW5ndGgpCj4gK3sKPiArI2lmZGVmIERFQlVHCj4gKwlwcmludF9oZXhfZHVtcF9i
-eXRlcygiT1BBTDogIiwgRFVNUF9QUkVGSVhfT0ZGU0VULCBwdHIsIGxlbmd0aCk7Cj4gKwlwcl9k
-ZWJ1ZygiXG4iKTsKPiArI2VuZGlmCj4gK30KPiArCj4gKyNkZWZpbmUgVFBFUl9TWU5DX1NVUFBP
-UlRFRCBCSVQoMCkKPiArCj4gK3N0YXRpYyBib29sIGNoZWNrX3RwZXIoY29uc3Qgdm9pZCAqZGF0
-YSkKPiArewo+ICsJY29uc3Qgc3RydWN0IGQwX3RwZXJfZmVhdHVyZXMgKnRwZXIgPSBkYXRhOwo+
-ICsJdTggZmxhZ3MgPSB0cGVyLT5zdXBwb3J0ZWRfZmVhdHVyZXM7Cj4gKwo+ICsJaWYgKCEoZmxh
-Z3MgJiBUUEVSX1NZTkNfU1VQUE9SVEVEKSkgewo+ICsJCXByX2VycigiVFBlciBzeW5jIG5vdCBz
-dXBwb3J0ZWQuIGZsYWdzID0gJWRcbiIsCj4gKwkJICAgICAgIHRwZXItPnN1cHBvcnRlZF9mZWF0
-dXJlcyk7Cj4gKwkJcmV0dXJuIGZhbHNlOwo+ICsJfQo+ICsKPiArCXJldHVybiB0cnVlOwo+ICt9
-Cj4gKwo+ICtzdGF0aWMgYm9vbCBjaGVja19TVU0oY29uc3Qgdm9pZCAqZGF0YSkKPiArewo+ICsJ
-Y29uc3Qgc3RydWN0IGQwX3NpbmdsZV91c2VyX21vZGUgKnN1bSA9IGRhdGE7Cj4gKwl1MzIgbmxv
-ID0gYmUzMl90b19jcHUoc3VtLT5udW1fbG9ja2luZ19vYmplY3RzKTsKPiArCj4gKwlpZiAobmxv
-ID09IDApIHsKPiArCQlwcl9lcnIoIk5lZWQgYXQgbGVhc3Qgb25lIGxvY2tpbmcgb2JqZWN0Llxu
-Iik7Cj4gKwkJcmV0dXJuIGZhbHNlOwo+ICsJfQo+ICsKPiArCXByX2RlYnVnKCJOdW1iZXIgb2Yg
-bG9ja2luZyBvYmplY3RzOiAlZFxuIiwgbmxvKTsKPiArCj4gKwlyZXR1cm4gdHJ1ZTsKPiArfQo+
-ICsKPiArc3RhdGljIHUxNiBnZXRfY29tSURfdjEwMChjb25zdCB2b2lkICpkYXRhKQo+ICt7Cj4g
-Kwljb25zdCBzdHJ1Y3QgZDBfb3BhbF92MTAwICp2MTAwID0gZGF0YTsKPiArCj4gKwlyZXR1cm4g
-YmUxNl90b19jcHUodjEwMC0+YmFzZUNvbUlEKTsKPiArfQo+ICsKPiArc3RhdGljIHUxNiBnZXRf
-Y29tSURfdjIwMChjb25zdCB2b2lkICpkYXRhKQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3QgZDBfb3Bh
-bF92MjAwICp2MjAwID0gZGF0YTsKPiArCj4gKwlyZXR1cm4gYmUxNl90b19jcHUodjIwMC0+YmFz
-ZUNvbUlEKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBfX29wYWxfc2VuZF9jbWQoc3RydWN0IG9w
-YWxfc3VzcGVuZF91bmxrICpkYXRhLCB1MTYgY29tSUQsCj4gKwkJCSAgIHZvaWQgKmJ1ZmZlciwg
-c2l6ZV90IGJ1Zmxlbiwgc2VjX2NiICpjYiwKPiArCQkJICAgdm9pZCAqY2JfZGF0YSkKPiArewo+
-ICsJcmV0dXJuIGRhdGEtPm9wcy5zZW5kKGRhdGEtPmRhdGEsIGNvbUlELCBUQ0dfU0VDUF8wMSwg
-YnVmZmVyLCBidWZsZW4sCj4gKwkJCSAgICAgY2IsIGNiX2RhdGEpOwo+ICt9Cj4gK3N0YXRpYyBp
-bnQgX29wYWxfc2VuZF9jbWQoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgdTE2IGNvbUlELAo+
-ICsJCQkgIHZvaWQgKmJ1ZmZlciwgc2l6ZV90IGJ1ZmxlbiwKPiArCQkJICBzZWNfY2IgKmNiLCB2
-b2lkICpjYl9kYXRhKQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3Qgc2VjX29wcyAqb3BzID0gYmRldi0+
-YmRfZGlzay0+Zm9wcy0+c2VjX29wczsKPiArCj4gKwlyZXR1cm4gb3BzLT5zZW5kKGJkZXYtPmJk
-X2Rpc2stPnByaXZhdGVfZGF0YSwgY29tSUQsCj4gKwkJCSBUQ0dfU0VDUF8wMSwgYnVmZmVyLCBi
-dWZsZW4sCj4gKwkJCSBjYiwgY2JfZGF0YSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgX19vcGFs
-X3JlY3ZfY21kKHN0cnVjdCBvcGFsX3N1c3BlbmRfdW5sayAqZGF0YSwgdTE2IGNvbUlELAo+ICsJ
-CQkgICB2b2lkICpidWZmZXIsIHNpemVfdCBidWZsZW4sIHNlY19jYiAqY2IsCj4gKwkJCSAgIHZv
-aWQgKmNiX2RhdGEpCj4gK3sKPiArCXJldHVybiBkYXRhLT5vcHMucmVjdihkYXRhLT5kYXRhLCBj
-b21JRCwgVENHX1NFQ1BfMDEsIGJ1ZmZlciwgYnVmbGVuLAo+ICsJCQkgICAgIGNiLCBjYl9kYXRh
-KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBfb3BhbF9yZWN2X2NtZChzdHJ1Y3QgYmxvY2tfZGV2
-aWNlICpiZGV2LCB1MTYgY29tSUQsCj4gKwkJCSAgdm9pZCAqYnVmZmVyLCBzaXplX3QgYnVmbGVu
-LAo+ICsJCQkgIHNlY19jYiAqY2IsIHZvaWQgKmNiX2RhdGEpCj4gK3sKPiArCWNvbnN0IHN0cnVj
-dCBzZWNfb3BzICpvcHMgPSBiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzOwo+ICsKPiArCXJl
-dHVybiBvcHMtPnJlY3YoYmRldi0+YmRfZGlzay0+cHJpdmF0ZV9kYXRhLCBjb21JRCwKPiArCQkJ
-IFRDR19TRUNQXzAxLCBidWZmZXIsIGJ1ZmxlbiwKPiArCQkJIGNiLCBjYl9kYXRhKTsKPiArfQo+
-ICsKPiArc3RhdGljIHZvaWQgb3BhbF9zZW5kX2NiX2NvbnQoaW50IGVycm9yLCB2b2lkICpkYXRh
-KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7Cj4gKwlzaXplX3QgYnVmbGVu
-ID0gSU9fQlVGRkVSX0xFTkdUSDsKPiArCXZvaWQgKmJ1ZmZlciA9IGRldi0+Y21kLnJlc3A7Cj4g
-KwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9IGJ1ZmZlcjsKPiArCj4gKwlwcl9kZWJ1ZygiJXM6
-IFNlbnQgT1BBTCBjb21tYW5kOiBlcnJvcj0lZCwgb3V0c3RhbmRpbmc9JWQsIG1pblRyYW5zZmVy
-PSVkXG4iLAo+ICsJICAgICAgIGRldi0+ZGlza19uYW1lLCBlcnJvciwgaGRyLT5jcC5vdXRzdGFu
-ZGluZ0RhdGEsCj4gKwkgICAgICAgaGRyLT5jcC5taW5UcmFuc2Zlcik7Cj4gKwo+ICsJaWYgKGVy
-cm9yIHx8IGhkci0+Y3Aub3V0c3RhbmRpbmdEYXRhID09IDAgfHwKPiArCSAgICBoZHItPmNwLm1p
-blRyYW5zZmVyICE9IDApIHsKPiArCQlpZiAoZGV2LT5jbWQuY2IpCj4gKwkJCWRldi0+Y21kLmNi
-KGVycm9yLCBkZXYtPmNtZC5jYl9kYXRhKTsKPiArCQlyZXR1cm47Cj4gKwl9Cj4gKwo+ICsJbWVt
-c2V0KGJ1ZmZlciwgMCwgYnVmbGVuKTsKPiArCWlmIChkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQp
-Cj4gKwkJX19vcGFsX3JlY3ZfY21kKGRldi0+cmVzdW1lX2RhdGEsIGRldi0+Y29tSUQsCj4gKwkJ
-CQlidWZmZXIsIGJ1Zmxlbiwgb3BhbF9zZW5kX2NiX2NvbnQsIGRldik7Cj4gKwllbHNlCj4gKwkJ
-X29wYWxfcmVjdl9jbWQoZGV2LT5iZGV2LCBkZXYtPmNvbUlELCBidWZmZXIsIGJ1ZmxlbiwKPiAr
-CQkJICAgICAgIG9wYWxfc2VuZF9jYl9jb250LCBkZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9p
-ZCBvcGFsX3NlbmRfY2IoaW50IGVycm9yLCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3Qgb3Bh
-bF9kZXYgKmRldiA9IGRhdGE7Cj4gKwlzaXplX3QgYnVmbGVuID0gSU9fQlVGRkVSX0xFTkdUSDsK
-PiArCXZvaWQgKmJ1ZmZlciA9IGRldi0+Y21kLnJlc3A7Cj4gKwo+ICsJaWYgKGVycm9yKSB7Cj4g
-KwkJaWYgKGRldi0+Y21kLmNiKQo+ICsJCQlkZXYtPmNtZC5jYihlcnJvciwgZGV2LT5jbWQuY2Jf
-ZGF0YSk7Cj4gKwkJcmV0dXJuOwo+ICsJfQo+ICsKPiArCW1lbXNldChidWZmZXIsIDAsIGJ1Zmxl
-bik7Cj4gKwlpZiAoZGV2LT5yZXN1bWVfZnJvbV9zdXNwZW5kKQo+ICsJCV9fb3BhbF9yZWN2X2Nt
-ZChkZXYtPnJlc3VtZV9kYXRhLCBkZXYtPmNvbUlELAo+ICsJCQkJYnVmZmVyLCBidWZsZW4sIG9w
-YWxfc2VuZF9jYl9jb250LCBkZXYpOwo+ICsJZWxzZQo+ICsJCV9vcGFsX3JlY3ZfY21kKGRldi0+
-YmRldiwgZGV2LT5jb21JRCwgYnVmZmVyLCBidWZsZW4sCj4gKwkJCSAgICAgICBvcGFsX3NlbmRf
-Y2JfY29udCwgZGV2KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBvcGFsX3NlbmRfcmVjdihzdHJ1
-Y3Qgb3BhbF9kZXYgKmRldiwgc2VjX2NiICpjYiwgdm9pZCAqY2JfZGF0YSkKPiArewo+ICsJc2l6
-ZV90IGJ1ZmxlbiA9IElPX0JVRkZFUl9MRU5HVEg7Cj4gKwl2b2lkICpidWZmZXIgPSBkZXYtPmNt
-ZC5jbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWRldi0+Y21kLmNiID0gY2I7Cj4gKwlkZXYtPmNt
-ZC5jYl9kYXRhID0gY2JfZGF0YTsKPiArCWlmIChkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQpCj4g
-KwkJcmV0ID0gX19vcGFsX3NlbmRfY21kKGRldi0+cmVzdW1lX2RhdGEsIGRldi0+Y29tSUQsIGJ1
-ZmZlciwKPiArCQkJCSAgICAgIGJ1Zmxlbiwgb3BhbF9zZW5kX2NiLCBkZXYpOwo+ICsJZWxzZQo+
-ICsJCXJldCA9IF9vcGFsX3NlbmRfY21kKGRldi0+YmRldiwgZGV2LT5jb21JRCwgYnVmZmVyLCBi
-dWZsZW4sCj4gKwkJCQkgICAgIG9wYWxfc2VuZF9jYiwgZGV2KTsKPiArCj4gKwlyZXR1cm4gcmV0
-Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjaGVja19nZW9tZXRyeShzdHJ1Y3Qgb3BhbF9kZXYg
-KmRldiwgY29uc3Qgdm9pZCAqZGF0YSkKPiArewo+ICsJY29uc3Qgc3RydWN0IGQwX2dlb21ldHJ5
-X2ZlYXR1cmVzICpnZW8gPSBkYXRhOwo+ICsKPiArCWRldi0+YWxpZ24gPSBnZW8tPmFsaWdubWVu
-dF9ncmFudWxhcml0eTsKPiArCWRldi0+bG93ZXN0X2xiYSA9IGdlby0+bG93ZXN0X2FsaWduZWRf
-bGJhOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBvcGFsX2Rpc2NvdmVyeTBfZW5kKGludCBlcnJv
-ciwgdm9pZCAqZGF0YSkKPiArewo+ICsJYm9vbCBmb3VuZENvbUlEID0gZmFsc2UsIHN1cHBvcnRl
-ZCA9IHRydWUsIHNpbmdsZV91c2VyID0gZmFsc2U7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9
-IGRhdGE7Cj4gKwljb25zdCBzdHJ1Y3QgZDBfaGVhZGVyICpoZHI7Cj4gKwljb25zdCB1OCAqZXBv
-cywgKmNwb3M7Cj4gKwl1MTYgY29tSUQgPSAwOwo+ICsKPiArCWlmIChlcnJvcikgewo+ICsJCXBy
-X2VycigiJXM6IFNlbmRpbmcgZGlzY292ZXJ5MCBmYWlsZWRcbiIsIGRldi0+ZGlza19uYW1lKTsK
-PiArCQlnb3RvIGVycl9jYWxsYmFjazsKPiArCX0KPiArCj4gKwllcG9zID0gZGV2LT5jbWQucmVz
-cDsKPiArCWNwb3MgPSBkZXYtPmNtZC5yZXNwOwo+ICsJaGRyID0gKHN0cnVjdCBkMF9oZWFkZXIg
-KilkZXYtPmNtZC5yZXNwOwo+ICsKPiArCXByaW50X2J1ZmZlcihkZXYtPmNtZC5yZXNwLCBiZTMy
-X3RvX2NwdShoZHItPmxlbmd0aCkpOwo+ICsKPiArCWVwb3MgKz0gYmUzMl90b19jcHUoaGRyLT5s
-ZW5ndGgpOyAvKiBlbmQgb2YgYnVmZmVyICovCj4gKwljcG9zICs9IHNpemVvZigqaGRyKTsgLyog
-Y3VycmVudCBwb3NpdGlvbiBvbiBidWZmZXIgKi8KPiArCj4gKwl3aGlsZSAoY3BvcyA8IGVwb3Mg
-JiYgc3VwcG9ydGVkKSB7Cj4gKwkJY29uc3Qgc3RydWN0IGQwX2ZlYXR1cmVzICpib2R5ID0KPiAr
-CQkJKGNvbnN0IHN0cnVjdCBkMF9mZWF0dXJlcyAqKWNwb3M7Cj4gKwo+ICsJCXN3aXRjaCAoYmUx
-Nl90b19jcHUoYm9keS0+Y29kZSkpIHsKPiArCQljYXNlIEZDX1RQRVI6Cj4gKwkJCXN1cHBvcnRl
-ZCA9IGNoZWNrX3RwZXIoYm9keS0+ZmVhdHVyZXMpOwo+ICsJCQlicmVhazsKPiArCQljYXNlIEZD
-X1NJTkdMRVVTRVI6Cj4gKwkJCXNpbmdsZV91c2VyID0gY2hlY2tfU1VNKGJvZHktPmZlYXR1cmVz
-KTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBGQ19HRU9NRVRSWToKPiArCQkJY2hlY2tfZ2VvbWV0
-cnkoZGV2LCBib2R5KTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBGQ19MT0NLSU5HOgo+ICsJCWNh
-c2UgRkNfRU5URVJQUklTRToKPiArCQljYXNlIEZDX0RBVEFTVE9SRToKPiArCQkJLyogc29tZSBp
-Z25vcmVkIHByb3BlcnRpZXMgKi8KPiArCQkJcHJfZGVidWcoIiVzOiBGb3VuZCBPUEFMIGZlYXR1
-cmUgZGVzY3JpcHRpb246ICVkXG4iLAo+ICsJCQkJIGRldi0+ZGlza19uYW1lLCBiZTE2X3RvX2Nw
-dShib2R5LT5jb2RlKSk7Cj4gKwkJCWJyZWFrOwo+ICsJCWNhc2UgRkNfT1BBTFYxMDA6Cj4gKwkJ
-CWNvbUlEID0gZ2V0X2NvbUlEX3YxMDAoYm9keS0+ZmVhdHVyZXMpOwo+ICsJCQlmb3VuZENvbUlE
-ID0gdHJ1ZTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBGQ19PUEFMVjIwMDoKPiArCQkJY29tSUQg
-PSBnZXRfY29tSURfdjIwMChib2R5LT5mZWF0dXJlcyk7Cj4gKwkJCWZvdW5kQ29tSUQgPSB0cnVl
-Owo+ICsJCQlicmVhazsKPiArCQlkZWZhdWx0Ogo+ICsJCQlpZiAoYmUxNl90b19jcHUoYm9keS0+
-Y29kZSkgPiAweGJmZmYpIHsKPiArCQkJCS8qIHZlbmRvciBzcGVjaWZpYywganVzdCBpZ25vcmUg
-Ki8KPiArCQkJfSBlbHNlIHsKPiArCQkJCXByX3dhcm4oIiVzOiBPUEFMIFVua25vd24gZmVhdHVy
-ZTogJWRcbiIsCj4gKwkJCQkJZGV2LT5kaXNrX25hbWUsIGJlMTZfdG9fY3B1KGJvZHktPmNvZGUp
-KTsKPiArCQkJfQpTbWFsbCBuaXQsIGhvdyBhYm91dDoKCmNhc2UgMHhiZmZmIC4uLiAweGZmZmY6
-CgkvKiB2ZW5kb3Igc3BlY2lmaWMsIGp1c3QgaWdub3JlICovCglicmVhazsKZGVmYXVsdDoKCXBy
-X3dhcm4oLi4uCgoKCj4gKwkJfQo+ICsJCWNwb3MgKz0gYm9keS0+bGVuZ3RoICsgNDsKPiArCX0K
-PiArCj4gKwlpZiAoIXN1cHBvcnRlZCkgewo+ICsJCXByX2VycigiJXM6IERldmljZSBub3Qgc3Vw
-cG9ydGVkXG4iLCBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJZ290byBlcnJfY2FsbGJhY2s7Cj4gKwl9
-Cj4gKwo+ICsJaWYgKCFzaW5nbGVfdXNlcikKPiArCQlwcl93YXJuKCIlczogRGV2aWNlIGRvZXNu
-J3Qgc3VwcG9ydCBzaW5nbGUgdXNlciBtb2RlXG4iLAo+ICsJCQlkZXYtPmRpc2tfbmFtZSk7Cj4g
-Kwo+ICsJaWYgKCFmb3VuZENvbUlEKSB7Cj4gKwkJcHJfd2FybigiJXM6IENvdWxkIG5vdCBmaW5k
-IE9QQUwgY29tSUQgZm9yIGRldmljZS4gT1BBTCBrZXJuZWwgdW5sb2NraW5nIHdpbGwgYmUgZGlz
-YWJsZWRcbiIsCj4gKwkJCWRldi0+ZGlza19uYW1lKTsKPiArCQlnb3RvIGVycl9jYWxsYmFjazsK
-PiArCX0KPiArCj4gKwlkZXYtPmNvbUlEID0gY29tSUQ7Cj4gKwo+ICtlcnJfY2FsbGJhY2s6Cj4g
-KwlpZiAoZGV2LT5vcGVyX2NiKQo+ICsJCWRldi0+b3Blcl9jYihlcnJvciwgZGV2KTsKPiArfQo+
-ICsKPiArc3RhdGljIGludCBvcGFsX2Rpc2NvdmVyeTAoc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4g
-K3sKPiArCW1lbXNldChkZXYtPmNtZC5yZXNwLCAwLCBJT19CVUZGRVJfTEVOR1RIKTsKPiArCj4g
-KwlpZiAoZGV2LT5yZXN1bWVfZnJvbV9zdXNwZW5kKQo+ICsJCXJldHVybiBfX29wYWxfcmVjdl9j
-bWQoZGV2LT5yZXN1bWVfZGF0YSwgMHgwMDAxLAo+ICsJCQkJICAgICAgIGRldi0+Y21kLnJlc3As
-IElPX0JVRkZFUl9MRU5HVEgsCj4gKwkJCQkgICAgICAgb3BhbF9kaXNjb3ZlcnkwX2VuZCwgZGV2
-KTsKPiArCj4gKwlyZXR1cm4gX29wYWxfcmVjdl9jbWQoZGV2LT5iZGV2LCAweDAwMDEsIGRldi0+
-Y21kLnJlc3AsCj4gKwkJCSAgICAgIElPX0JVRkZFUl9MRU5HVEgsIG9wYWxfZGlzY292ZXJ5MF9l
-bmQsCj4gKwkJCSAgICAgIGRldik7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGFkZF90b2tlbl91
-OChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTggdG9rKQo+ICt7Cj4gKwljbWQtPmNtZFtjbWQtPnBv
-cysrXSA9IHRvazsKPiArfQo+ICsKPiArc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRkX3Rva2Vu
-X3U4KHN0cnVjdCBvcGFsX2NtZCAqY21kLCB1OCB0b2spCj4gK3sKPiArCUJVSUxEX0JVR19PTihJ
-T19CVUZGRVJfTEVOR1RIID49IFNJWkVfTUFYKTsKPiArCj4gKwlpZiAoY21kLT5wb3MgPj0gSU9f
-QlVGRkVSX0xFTkdUSCAtIDEpIHsKPiArCQlwcl9lcnIoIkVycm9yIGFkZGluZyB1ODogZW5kIG9m
-IGJ1ZmZlci5cbiIpOwo+ICsJCXJldHVybiAtRVJBTkdFOwo+ICsJfQo+ICsKPiArCWFkZF90b2tl
-bl91OChjbWQsIHRvayk7Cj4gKwo+ICsJcmV0dXJuIDE7Cj4gK30KPiArCj4gKyNkZWZpbmUgVElO
-WV9BVE9NX0RBVEFfTUFTSyBHRU5NQVNLKDUsIDApCj4gKyNkZWZpbmUgVElOWV9BVE9NX1NJR05F
-RCBCSVQoNikKPiArCj4gKyNkZWZpbmUgU0hPUlRfQVRPTV9JRCBCSVQoNykKPiArI2RlZmluZSBT
-SE9SVF9BVE9NX0JZVEVTVFJJTkcgQklUKDUpCj4gKyNkZWZpbmUgU0hPUlRfQVRPTV9TSUdORUQg
-QklUKDQpCj4gKyNkZWZpbmUgU0hPUlRfQVRPTV9MRU5fTUFTSyBHRU5NQVNLKDMsIDApCj4gKwo+
-ICtzdGF0aWMgdm9pZCBhZGRfc2hvcnRfYXRvbV9oZWFkZXIoc3RydWN0IG9wYWxfY21kICpjbWQs
-IGJvb2wgYnl0ZXN0cmluZywKPiArCQkJCSAgYm9vbCBoYXNfc2lnbiwgaW50IGxlbikKPiArewo+
-ICsJdTggYXRvbTsKPiArCj4gKwlhdG9tID0gU0hPUlRfQVRPTV9JRDsKPiArCWF0b20gfD0gYnl0
-ZXN0cmluZyA/IFNIT1JUX0FUT01fQllURVNUUklORyA6IDA7Cj4gKwlhdG9tIHw9IGhhc19zaWdu
-ID8gU0hPUlRfQVRPTV9TSUdORUQgOiAwOwo+ICsJYXRvbSB8PSBsZW4gJiBTSE9SVF9BVE9NX0xF
-Tl9NQVNLOwo+ICsKPiArCWFkZF90b2tlbl91OChjbWQsIGF0b20pOwo+ICt9Cj4gKwo+ICsjZGVm
-aW5lIE1FRElVTV9BVE9NX0lEIChCSVQoNykgfCBCSVQoNikpCj4gKyNkZWZpbmUgTUVESVVNX0FU
-T01fQllURVNUUklORyBCSVQoNCkKPiArI2RlZmluZSBNRURJVU1fQVRPTV9TSUdORUQgQklUKDMp
-Cj4gKyNkZWZpbmUgTUVESVVNX0FUT01fTEVOX01BU0sgR0VOTUFTSygyLCAwKQo+ICsKPiArc3Rh
-dGljIHZvaWQgYWRkX21lZGl1bV9hdG9tX2hlYWRlcihzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgYm9v
-bCBieXRlc3RyaW5nLAo+ICsJCQkJICAgYm9vbCBoYXNfc2lnbiwgaW50IGxlbikKPiArewo+ICsJ
-dTggaGVhZGVyMDsKPiArCj4gKwloZWFkZXIwID0gTUVESVVNX0FUT01fSUQ7Cj4gKwloZWFkZXIw
-IHw9IGJ5dGVzdHJpbmcgPyBNRURJVU1fQVRPTV9CWVRFU1RSSU5HIDogMDsKPiArCWhlYWRlcjAg
-fD0gaGFzX3NpZ24gPyBNRURJVU1fQVRPTV9TSUdORUQgOiAwOwo+ICsJaGVhZGVyMCB8PSAobGVu
-ID4+IDgpICYgTUVESVVNX0FUT01fTEVOX01BU0s7Cj4gKwljbWQtPmNtZFtjbWQtPnBvcysrXSA9
-IGhlYWRlcjA7Cj4gKwljbWQtPmNtZFtjbWQtPnBvcysrXSA9IGxlbjsKPiArfQo+ICsKPiArc3Rh
-dGljIHZvaWQgYWRkX3Rva2VuX3U2NChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTY0IG51bWJlciwg
-c2l6ZV90IGxlbikKPiArewo+ICsJYWRkX3Nob3J0X2F0b21faGVhZGVyKGNtZCwgZmFsc2UsIGZh
-bHNlLCBsZW4pOwo+ICsKPiArCXdoaWxlIChsZW4tLSkgewo+ICsJCXU4IG4gPSBudW1iZXIgPj4g
-KGxlbiAqIDgpOwo+ICsKPiArCQlhZGRfdG9rZW5fdTgoY21kLCBuKTsKPiArCX0KPiArfQo+ICsK
-PiArc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRkX3Rva2VuX3U2NChzdHJ1Y3Qgb3BhbF9jbWQg
-KmNtZCwgdTY0IG51bWJlcikKPiArewo+ICsJaW50IGxlbjsKPiArCWludCBtc2I7Cj4gKwo+ICsJ
-aWYgKCEobnVtYmVyICYgflRJTllfQVRPTV9EQVRBX01BU0spKQo+ICsJCXJldHVybiB0ZXN0X2Fu
-ZF9hZGRfdG9rZW5fdTgoY21kLCBudW1iZXIpOwo+ICsKPiArCW1zYiA9IGZscyhudW1iZXIpOwo+
-ICsJbGVuID0gRElWX1JPVU5EX1VQKG1zYiwgNCk7Cj4gKwo+ICsJaWYgKGNtZC0+cG9zID49IElP
-X0JVRkZFUl9MRU5HVEggLSBsZW4gLSAxKSB7Cj4gKwkJcHJfZXJyKCJFcnJvciBhZGRpbmcgdTY0
-OiBlbmQgb2YgYnVmZmVyLlxuIik7Cj4gKwkJcmV0dXJuIC1FUkFOR0U7Cj4gKwl9Cj4gKwo+ICsJ
-YWRkX3Rva2VuX3U2NChjbWQsIG51bWJlciwgbGVuKTsKPiArCj4gKwkvKiByZXR1cm4gbGVuZ3Ro
-IG9mIHRva2VuIHBsdXMgYXRvbSAqLwo+ICsJcmV0dXJuIGxlbiArIDE7Cj4gK30KPiArCj4gK3N0
-YXRpYyB2b2lkIGFkZF90b2tlbl9ieXRlc3RyaW5nKHN0cnVjdCBvcGFsX2NtZCAqY21kLAo+ICsJ
-CQkJIGNvbnN0IHU4ICpieXRlc3RyaW5nLCBzaXplX3QgbGVuKQo+ICt7Cj4gKwltZW1jcHkoJmNt
-ZC0+Y21kW2NtZC0+cG9zXSwgYnl0ZXN0cmluZywgbGVuKTsKPiArCWNtZC0+cG9zICs9IGxlbjsK
-PiArfQo+ICsKPiArc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRkX3Rva2VuX2J5dGVzdHJpbmco
-c3RydWN0IG9wYWxfY21kICpjbWQsCj4gKwkJCQkJICAgICBjb25zdCB1OCAqYnl0ZXN0cmluZywg
-c2l6ZV90IGxlbikKPiArewo+ICsJc2l6ZV90IGhlYWRlcl9sZW4gPSAxOwo+ICsJYm9vbCBpc19z
-aG9ydF9hdG9tID0gdHJ1ZTsKPiArCj4gKwlpZiAobGVuICYgflNIT1JUX0FUT01fTEVOX01BU0sp
-IHsKPiArCQloZWFkZXJfbGVuID0gMjsKPiArCQlpc19zaG9ydF9hdG9tID0gZmFsc2U7Cj4gKwl9
-Cj4gKwo+ICsJaWYgKGNtZC0+cG9zID49IElPX0JVRkZFUl9MRU5HVEggLSBsZW4gLSBoZWFkZXJf
-bGVuKSB7Cj4gKwkJcHJfZXJyKCJFcnJvciBhZGRpbmcgYnl0ZXN0cmluZzogZW5kIG9mIGJ1ZmZl
-ci5cbiIpOwo+ICsJCXJldHVybiAtRVJBTkdFOwo+ICsJfQo+ICsKPiArCWlmIChpc19zaG9ydF9h
-dG9tKQo+ICsJCWFkZF9zaG9ydF9hdG9tX2hlYWRlcihjbWQsIHRydWUsIGZhbHNlLCBsZW4pOwo+
-ICsJZWxzZQo+ICsJCWFkZF9tZWRpdW1fYXRvbV9oZWFkZXIoY21kLCB0cnVlLCBmYWxzZSwgbGVu
-KTsKPiArCj4gKwlhZGRfdG9rZW5fYnl0ZXN0cmluZyhjbWQsIGJ5dGVzdHJpbmcsIGxlbik7Cj4g
-Kwo+ICsJcmV0dXJuIGhlYWRlcl9sZW4gKyBsZW47Cj4gK30KPiArCj4gKyNkZWZpbmUgTE9DS0lO
-R19SQU5HRV9OT05fR0xPQkFMIDB4MDMKPiArCj4gK3N0YXRpYyBpbnQgYnVpbGRfbG9ja2luZ19y
-YW5nZSh1OCAqYnVmZmVyLCBzaXplX3QgbGVuZ3RoLCB1OCBscikKPiArewo+ICsJaWYgKGxlbmd0
-aCA8IE9QQUxfVUlEX0xFTkdUSCkKPiArCQlyZXR1cm4gLUVSQU5HRTsKPiArCj4gKwltZW1jcHko
-YnVmZmVyLCBPUEFMVUlEW09QQUxfTE9DS0lOR1JBTkdFX0dMT0JBTF0sIE9QQUxfVUlEX0xFTkdU
-SCk7Cj4gKwo+ICsJaWYgKGxyID09IDApCj4gKwkJcmV0dXJuIDA7Cj4gKwlidWZmZXJbNV0gPSBM
-T0NLSU5HX1JBTkdFX05PTl9HTE9CQUw7Cj4gKwlidWZmZXJbN10gPSBscjsKPiArCj4gKwlyZXR1
-cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBidWlsZF9sb2NraW5nX3VzZXIodTggKmJ1ZmZl
-ciwgc2l6ZV90IGxlbmd0aCwgdTggbHIpCj4gK3sKPiArCWlmIChsZW5ndGggPCBPUEFMX1VJRF9M
-RU5HVEgpCj4gKwkJcmV0dXJuIC1FUkFOR0U7Cj4gKwo+ICsJbWVtY3B5KGJ1ZmZlciwgT1BBTFVJ
-RFtPUEFMX1VTRVIxX1VJRF0sIE9QQUxfVUlEX0xFTkdUSCk7Cj4gKwo+ICsJYnVmZmVyWzddID0g
-bHIgKyAxOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBOID0gbnVtYmVy
-IG9mIGZvcm1hdCBzcGVjaWZpZXJzICgxLTk5OSkgdG8gYmUgcmVwbGljYXRlZAo+ICsgKiBjID0g
-dTgKPiArICogdSA9IHU2NAo+ICsgKiBzID0gYnl0ZXN0cmluZywgbGVuZ3RoCj4gKyAqCj4gKyAq
-IHJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjIiwKPiArICoJCQkgICAgICAgdThf
-dmFsMSk7Cj4gKyAqCj4gKyAqIHJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICIyYzJ1
-IiwKPiArICoJCQkgICAgICAgdThfdmFsMSwgdThfdmFsMiwgdTY0X3ZhbDEsIHU2NF92YWwyKTsK
-PiArICoKPiArICogcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgIjNzIiwKPiArICoJ
-CQkgICAgICAgYnl0ZXN0cmluZzEsIGxlbmd0aDEsCj4gKyAqCQkJICAgICAgIGJ5dGVzdHJpbmcy
-LCBsZW5ndGgyLAo+ICsgKgkJCSAgICAgICBieXRlc3RyaW5nMywgbGVuZ3RoMyk7Cj4gKyAqLwo+
-ICtzdGF0aWMgaW50IHRlc3RfYW5kX2FkZF90b2tlbl92YShzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwK
-PiArCQkJCSBjb25zdCBjaGFyICpmbXQsIC4uLikKPiArewo+ICsJY29uc3QgdTggKml0ID0gZm10
-LCAqdG1wOwo+ICsJaW50IHJldCwgbnVtID0gMSwgc3VtID0gMDsKPiArCXZhX2xpc3QgYXA7Cj4g
-Kwo+ICsJdmFfc3RhcnQoYXAsIGZtdCk7Cj4gKwo+ICsJd2hpbGUgKCppdCAhPSAnXDAnKSB7Cj4g
-KwkJdTY0IHRvazY0ID0gMDsKPiArCQl1OCB0b2ssICpic3RyOwo+ICsJCXNpemVfdCBsZW47Cj4g
-Kwo+ICsJCXJldCA9IDA7Cj4gKwo+ICsJCXN3aXRjaCAoKml0KSB7Cj4gKwkJY2FzZSAnMScgLi4u
-ICc5JzoKPiArCQkJdG1wID0gaXQ7Cj4gKwkJCW51bSA9IDA7Cj4gKwkJCXdoaWxlICgqdG1wID49
-ICcwJyAmJiAqdG1wIDw9ICc5JykKPiArCQkJCW51bSA9IG51bSAqIDEwICsgKCp0bXArKyAtICcw
-Jyk7Cj4gKwkJCWl0ID0gdG1wOwo+ICsJCQljb250aW51ZTsKPiArCQljYXNlICdjJzoKPiArCQkJ
-d2hpbGUgKG51bS0tKSB7Cj4gKwkJCQl0b2sgPSB2YV9hcmcoYXAsIHVuc2lnbmVkIGludCk7Cj4g
-KwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdTgoY21kLCB0b2spOwo+ICsJCQkJaWYgKHJl
-dCA8IDApCj4gKwkJCQkJZ290byBlcnI7Cj4gKwkJCX0KPiArCQkJbnVtID0gMTsKPiArCQkJYnJl
-YWs7Cj4gKwkJY2FzZSAndSc6Cj4gKwkJCXdoaWxlIChudW0tLSkgewo+ICsJCQkJdG9rNjQgPSB2
-YV9hcmcoYXAsIHU2NCk7Cj4gKwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdTY0KGNtZCwg
-dG9rNjQpOwo+ICsJCQkJaWYgKHJldCA8IDApCj4gKwkJCQkJZ290byBlcnI7Cj4gKwkJCX0KPiAr
-CQkJbnVtID0gMTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSAncyc6Cj4gKwkJCXdoaWxlIChudW0t
-LSkgewo+ICsJCQkJYnN0ciA9IHZhX2FyZyhhcCwgdTggKik7Cj4gKwkJCQlsZW4gPSB2YV9hcmco
-YXAsIHNpemVfdCk7Cj4gKwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fYnl0ZXN0cmluZyhj
-bWQsIGJzdHIsCj4gKwkJCQkJCQkJICAgIGxlbik7Cj4gKwkJCQlpZiAocmV0IDwgMCkKPiArCQkJ
-CQlnb3RvIGVycjsKPiArCQkJfQo+ICsJCQludW0gPSAxOwo+ICsJCQlicmVhazsKPiArCQljYXNl
-ICcgJzoKPiArCQljYXNlICdcdCc6Cj4gKwkJCS8qIGlnbm9yZWQgKi8KPiArCQkJYnJlYWs7Cj4g
-KwkJZGVmYXVsdDoKPiArCQkJcHJfd2FybigiVW5yZWNvZ25pemVkIHR5cGUuXG4iKTsKPiArCQl9
-Cj4gKwo+ICsJCWl0Kys7Cj4gKwkJc3VtICs9IHJldDsKPiArCX0KPiArCj4gKwl2YV9lbmQoYXAp
-Owo+ICsKPiArCXJldHVybiBzdW07Cj4gKwo+ICsgZXJyOgo+ICsJcHJfZXJyKCJUb2tlbiBmYWls
-ZWQgdG8gYmUgYWRkZWQuXG4iKTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyB2
-b2lkIHNldF9jb21JRChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTE2IGNvbUlEKQo+ICt7Cj4gKwlz
-dHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9IChzdHJ1Y3Qgb3BhbF9oZWFkZXIgKiljbWQtPmNtZDsK
-PiArCj4gKwloZHItPmNwLmV4dGVuZGVkQ29tSURbMF0gPSBjb21JRCA+PiA4Owo+ICsJaGRyLT5j
-cC5leHRlbmRlZENvbUlEWzFdID0gY29tSUQ7Cj4gKwloZHItPmNwLmV4dGVuZGVkQ29tSURbMl0g
-PSAwOwo+ICsJaGRyLT5jcC5leHRlbmRlZENvbUlEWzNdID0gMDsKPiArfQo+ICsKPiArc3RhdGlj
-IGludCBjbWRfZmluYWxpemUoc3RydWN0IG9wYWxfY21kICpjbWQsIHUzMiBoc24sIHUzMiB0c24p
-Cj4gK3sKPiArCXN0cnVjdCBvcGFsX2hlYWRlciAqaGRyOwo+ICsJaW50IHJldDsKPiArCj4gKwly
-ZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiNmMiLAo+ICsJCQkJICAgIE9QQUxfRU5E
-T0ZEQVRBLCBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICAwLCAwLCAwLCBPUEFMX0VORExJU1Qp
-Owo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCJFcnJvciBmaW5hbGl6aW5nIGNv
-bW1hbmQuXG4iKTsKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCX0KPiArCj4gKwloZHIgPSAoc3Ry
-dWN0IG9wYWxfaGVhZGVyICopIGNtZC0+Y21kOwo+ICsKPiArCWhkci0+cGt0LlRTTiA9IGNwdV90
-b19iZTMyKHRzbik7Cj4gKwloZHItPnBrdC5IU04gPSBjcHVfdG9fYmUzMihoc24pOwo+ICsKPiAr
-CWhkci0+c3VicGt0Lmxlbmd0aCA9IGNwdV90b19iZTMyKGNtZC0+cG9zIC0gc2l6ZW9mKCpoZHIp
-KTsKPiArCXdoaWxlIChjbWQtPnBvcyAlIDQpIHsKPiArCQlpZiAoY21kLT5wb3MgPj0gSU9fQlVG
-RkVSX0xFTkdUSCkgewo+ICsJCQlwcl9lcnIoIkVycm9yOiBCdWZmZXIgb3ZlcnJ1blxuIik7Cj4g
-KwkJCXJldHVybiAtRVJBTkdFOwo+ICsJCX0KPiArCQljbWQtPmNtZFtjbWQtPnBvcysrXSA9IDA7
-Cj4gKwl9Cj4gKwloZHItPnBrdC5sZW5ndGggPSBjcHVfdG9fYmUzMihjbWQtPnBvcyAtIHNpemVv
-ZihoZHItPmNwKSAtCj4gKwkJCQkgICAgICBzaXplb2YoaGRyLT5wa3QpKTsKPiArCWhkci0+Y3Au
-bGVuZ3RoID0gY3B1X3RvX2JlMzIoY21kLT5wb3MgLSBzaXplb2YoaGRyLT5jcCkpOwo+ICsKPiAr
-CXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZW51bSBPUEFMX1JFU1BPTlNFX1RPS0VOIHRv
-a2VuX3R5cGUoY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLAo+ICsJCQkJCSAgIGludCBu
-KQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rOwo+ICsKPiArCWlmIChu
-ID49IHJlc3AtPm51bSkgewo+ICsJCXByX2VycigiVG9rZW4gbnVtYmVyIGRvZXNuJ3QgZXhpc3Q6
-ICVkLCByZXNwOiAlZFxuIiwKPiArCQkgICAgICAgbiwgcmVzcC0+bnVtKTsKPiArCQlyZXR1cm4g
-T1BBTF9EVEFfVE9LRU5JRF9JTlZBTElEOwo+ICsJfQo+ICsKPiArCXRvayA9ICZyZXNwLT50b2tz
-W25dOwo+ICsJaWYgKHRvay0+bGVuID09IDApIHsKPiArCQlwcl9lcnIoIlRva2VuIGxlbmd0aCBt
-dXN0IGJlIG5vbi16ZXJvXG4iKTsKPiArCQlyZXR1cm4gT1BBTF9EVEFfVE9LRU5JRF9JTlZBTElE
-Owo+ICsJfQo+ICsKPiArCXJldHVybiB0b2stPnR5cGU7Cj4gK30KPiArCj4gKy8qCj4gKyAqIFRo
-aXMgZnVuY3Rpb24gcmV0dXJucyAwIGluIGNhc2Ugb2YgaW52YWxpZCB0b2tlbi4gT25lIHNob3Vs
-ZCBjYWxsCj4gKyAqIHRva2VuX3R5cGUoKSBmaXJzdCB0byBmaW5kIG91dCBpZiB0aGUgdG9rZW4g
-aXMgdmFsaWQgb3Igbm90Lgo+ICsgKi8KPiArc3RhdGljIGVudW0gT1BBTF9UT0tFTiByZXNwb25z
-ZV9nZXRfdG9rZW4oY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLAo+ICsJCQkJCSAgaW50
-IG4pCj4gK3sKPiArCWNvbnN0IHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2s7Cj4gKwo+ICsJaWYg
-KG4gPj0gcmVzcC0+bnVtKSB7Cj4gKwkJcHJfZXJyKCJUb2tlbiBudW1iZXIgZG9lc24ndCBleGlz
-dDogJWQsIHJlc3A6ICVkXG4iLAo+ICsJCSAgICAgICBuLCByZXNwLT5udW0pOwo+ICsJCXJldHVy
-biAwOwo+ICsJfQo+ICsKPiArCXRvayA9ICZyZXNwLT50b2tzW25dOwo+ICsJaWYgKHRvay0+bGVu
-ID09IDApIHsKPiArCQlwcl9lcnIoIlRva2VuIGxlbmd0aCBtdXN0IGJlIG5vbi16ZXJvXG4iKTsK
-PiArCQlyZXR1cm4gMDsKPiArCX0KPiArCj4gKwlyZXR1cm4gdG9rLT5wb3NbMF07Cj4gK30KPiAr
-Cj4gK3N0YXRpYyBzaXplX3QgcmVzcG9uc2VfcGFyc2VfdGlueShzdHJ1Y3Qgb3BhbF9yZXNwX3Rv
-ayAqdG9rLAo+ICsJCQkJICBjb25zdCB1OCAqcG9zKQo+ICt7Cj4gKwl0b2stPnBvcyA9IHBvczsK
-PiArCXRvay0+bGVuID0gMTsKPiArCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX1RJTlk7Cj4gKwo+
-ICsJaWYgKHBvc1swXSAmIFRJTllfQVRPTV9TSUdORUQpIHsKPiArCQl0b2stPnR5cGUgPSBPUEFM
-X0RUQV9UT0tFTklEX1NJTlQ7Cj4gKwl9IGVsc2Ugewo+ICsJCXRvay0+dHlwZSA9IE9QQUxfRFRB
-X1RPS0VOSURfVUlOVDsKPiArCQl0b2stPnN0b3JlZC51ID0gcG9zWzBdICYgMHgzZjsKPiArCX0K
-PiArCj4gKwlyZXR1cm4gdG9rLT5sZW47Cj4gK30KPiArCj4gK3N0YXRpYyBzaXplX3QgcmVzcG9u
-c2VfcGFyc2Vfc2hvcnQoc3RydWN0IG9wYWxfcmVzcF90b2sgKnRvaywKPiArCQkJCSAgIGNvbnN0
-IHU4ICpwb3MpCj4gK3sKPiArCXRvay0+cG9zID0gcG9zOwo+ICsJdG9rLT5sZW4gPSAocG9zWzBd
-ICYgU0hPUlRfQVRPTV9MRU5fTUFTSykgKyAxOwo+ICsJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhf
-U0hPUlQ7Cj4gKwo+ICsJaWYgKHBvc1swXSAmIFNIT1JUX0FUT01fQllURVNUUklORykgewo+ICsJ
-CXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfQllURVNUUklORzsKPiArCX0gZWxzZSBpZiAo
-cG9zWzBdICYgU0hPUlRfQVRPTV9TSUdORUQpIHsKPiArCQl0b2stPnR5cGUgPSBPUEFMX0RUQV9U
-T0tFTklEX1NJTlQ7Cj4gKwl9IGVsc2Ugewo+ICsJCXU2NCB1X2ludGVnZXIgPSAwOwo+ICsJCWlu
-dCBpLCBiID0gMDsKPiArCj4gKwkJdG9rLT50eXBlID0gT1BBTF9EVEFfVE9LRU5JRF9VSU5UOwo+
-ICsJCWlmICh0b2stPmxlbiA+IDkpClNob3VsZCB0aGlzIGJlIGxlbiA+IDggb3IgbGVuID49IDkg
-PwoKPiArCQkJcHJfd2FybigidWludDY0IHdpdGggbW9yZSB0aGFuIDggYnl0ZXNcbiIpOwo+ICsJ
-CWZvciAoaSA9IHRvay0+bGVuIC0gMTsgaSA+IDA7IGktLSkgewo+ICsJCQl1X2ludGVnZXIgfD0g
-KCh1NjQpcG9zW2ldIDw8ICg4ICogYikpOwo+ICsJCQliKys7Cj4gKwkJfQpJdCBkb2Vzbid0IGxv
-b2sgcGFydGljdWxhcmx5IHNhZmUgdG8ga2VlcCB1c2luZyB0aGlzIGRyaXZlciBvbiBhIGRyaXZl
-CmlmIGl0IHJldHVybnMgYSBsZW4gPiA4LiBCdXQgdGhlIHNwZWNzIGRvIGFsbG93IDE2LWJ5dGUg
-ZGF0YSBpbiBhIHNob3J0CmF0b20sIHNvIG1heWJlIHdlIHNob3VsZCBiYWlsIG9uIGFsbG93aW5n
-IHRoZSBkcml2ZXIgdG8gbWFuYWdlIHRoZQpkcml2ZSwgb3IgY2hhbmdlIHRoZSB0eXBlcyB0byBz
-b21lIDE2LWJ5dGUgdHlwZT8KCj4gKwkJdG9rLT5zdG9yZWQudSA9IHVfaW50ZWdlcjsKPiArCX0K
-PiArCj4gKwlyZXR1cm4gdG9rLT5sZW47Cj4gK30KPiArCj4gK3N0YXRpYyBzaXplX3QgcmVzcG9u
-c2VfcGFyc2VfbWVkaXVtKHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2ssCj4gKwkJCQkgICAgY29u
-c3QgdTggKnBvcykKPiArewo+ICsJdG9rLT5wb3MgPSBwb3M7Cj4gKwl0b2stPmxlbiA9ICgoKHBv
-c1swXSAmIE1FRElVTV9BVE9NX0xFTl9NQVNLKSA8PCA4KSB8IHBvc1sxXSkgKyAyOwo+ICsJdG9r
-LT53aWR0aCA9IE9QQUxfV0lEVEhfTUVESVVNOwo+ICsKPiArCWlmIChwb3NbMF0gJiBNRURJVU1f
-QVRPTV9CWVRFU1RSSU5HKQo+ICsJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfQllURVNU
-UklORzsKPiArCWVsc2UgaWYgKHBvc1swXSAmIE1FRElVTV9BVE9NX1NJR05FRCkKPiArCQl0b2st
-PnR5cGUgPSBPUEFMX0RUQV9UT0tFTklEX1NJTlQ7Cj4gKwllbHNlCj4gKwkJdG9rLT50eXBlID0g
-T1BBTF9EVEFfVE9LRU5JRF9VSU5UOwo+ICsKPiArCXJldHVybiB0b2stPmxlbjsKPiArfQo+ICsK
-PiArI2RlZmluZSBMT05HX0FUT01fSUQgKEJJVCg3KSB8IEJJVCg2KSB8IEJJVCg1KSkKPiArI2Rl
-ZmluZSBMT05HX0FUT01fQllURVNUUklORyBCSVQoMSkKPiArI2RlZmluZSBMT05HX0FUT01fU0lH
-TkVEIEJJVCgwKQo+ICtzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX3BhcnNlX2xvbmcoc3RydWN0IG9w
-YWxfcmVzcF90b2sgKnRvaywKPiArCQkJCSAgY29uc3QgdTggKnBvcykKPiArewo+ICsJdG9rLT5w
-b3MgPSBwb3M7Cj4gKwl0b2stPmxlbiA9ICgocG9zWzFdIDw8IDE2KSB8IChwb3NbMl0gPDwgOCkg
-fCBwb3NbM10pICsgNDsKPiArCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX0xPTkc7Cj4gKwo+ICsJ
-aWYgKHBvc1swXSAmIExPTkdfQVRPTV9CWVRFU1RSSU5HKQo+ICsJCXRvay0+dHlwZSA9IE9QQUxf
-RFRBX1RPS0VOSURfQllURVNUUklORzsKPiArCWVsc2UgaWYgKHBvc1swXSAmIExPTkdfQVRPTV9T
-SUdORUQpCj4gKwkJdG9rLT50eXBlID0gT1BBTF9EVEFfVE9LRU5JRF9TSU5UOwo+ICsJZWxzZQo+
-ICsJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKPiArCj4gKwlyZXR1cm4gdG9r
-LT5sZW47Cj4gK30KPiArCj4gK3N0YXRpYyBzaXplX3QgcmVzcG9uc2VfcGFyc2VfdG9rZW4oc3Ry
-dWN0IG9wYWxfcmVzcF90b2sgKnRvaywKPiArCQkJCSAgIGNvbnN0IHU4ICpwb3MpCj4gK3sKPiAr
-CXRvay0+cG9zID0gcG9zOwo+ICsJdG9rLT5sZW4gPSAxOwo+ICsJdG9rLT50eXBlID0gT1BBTF9E
-VEFfVE9LRU5JRF9UT0tFTjsKPiArCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX1RPS0VOOwo+ICsK
-PiArCXJldHVybiB0b2stPmxlbjsKPiArfQo+ICsKPiArc3RhdGljIGludCByZXNwb25zZV9wYXJz
-ZShjb25zdCB1OCAqYnVmLCBzaXplX3QgbGVuZ3RoLAo+ICsJCQkgIHN0cnVjdCBwYXJzZWRfcmVz
-cCAqcmVzcCkKPiArewo+ICsJY29uc3Qgc3RydWN0IG9wYWxfaGVhZGVyICpoZHI7Cj4gKwlzdHJ1
-Y3Qgb3BhbF9yZXNwX3RvayAqaXRlcjsKPiArCWludCByZXQsIG51bV9lbnRyaWVzID0gMDsKPiAr
-CXUzMiBjcG9zID0gMCwgdG90YWw7Cj4gKwlzaXplX3QgdG9rZW5fbGVuZ3RoOwo+ICsJY29uc3Qg
-dTggKnBvczsKPiArCj4gKwlpZiAoIWJ1ZikKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlp
-ZiAoIXJlc3ApCj4gKwkJcmV0dXJuIC1FRkFVTFQ7Cj4gKwo+ICsJaGRyID0gKHN0cnVjdCBvcGFs
-X2hlYWRlciAqKWJ1ZjsKPiArCXBvcyA9IGJ1ZjsKPiArCXBvcyArPSBzaXplb2YoKmhkcik7Cj4g
-Kwo+ICsJcHJfZGVidWcoIlJlc3BvbnNlIHNpemU6IGNwOiAlZCwgcGt0OiAlZCwgc3VicGt0OiAl
-ZFxuIiwKPiArCQkgYmUzMl90b19jcHUoaGRyLT5jcC5sZW5ndGgpLAo+ICsJCSBiZTMyX3RvX2Nw
-dShoZHItPnBrdC5sZW5ndGgpLAo+ICsJCSBiZTMyX3RvX2NwdShoZHItPnN1YnBrdC5sZW5ndGgp
-KTsKPiArCj4gKwlpZiAoKGhkci0+Y3AubGVuZ3RoID09IDApCj4gKwkgICAgfHwgKGhkci0+cGt0
-Lmxlbmd0aCA9PSAwKQo+ICsJICAgIHx8IChoZHItPnN1YnBrdC5sZW5ndGggPT0gMCkpIHsKPiAr
-CQlwcl9lcnIoIkJhZCBoZWFkZXIgbGVuZ3RoLiBjcDogJWQsIHBrdDogJWQsIHN1YnBrdDogJWRc
-biIsCj4gKwkJICAgICAgIGJlMzJfdG9fY3B1KGhkci0+Y3AubGVuZ3RoKSwKPiArCQkgICAgICAg
-YmUzMl90b19jcHUoaGRyLT5wa3QubGVuZ3RoKSwKPiArCQkgICAgICAgYmUzMl90b19jcHUoaGRy
-LT5zdWJwa3QubGVuZ3RoKSk7Cj4gKwkJcHJpbnRfYnVmZmVyKHBvcywgc2l6ZW9mKCpoZHIpKTsK
-PiArCQlyZXQgPSAtRUlOVkFMOwo+ICsJCWdvdG8gZXJyOwo+ICsJfQo+ICsKPiArCWlmIChwb3Mg
-PiBidWYgKyBsZW5ndGgpIHsKPiArCQlyZXQgPSAtRUZBVUxUOwo+ICsJCWdvdG8gZXJyOwo+ICsJ
-fQo+ICsKPiArCWl0ZXIgPSByZXNwLT50b2tzOwo+ICsJdG90YWwgPSBiZTMyX3RvX2NwdShoZHIt
-PnN1YnBrdC5sZW5ndGgpOwo+ICsJcHJpbnRfYnVmZmVyKHBvcywgdG90YWwpOwo+ICsJd2hpbGUg
-KGNwb3MgPCB0b3RhbCkgewo+ICsJCWlmICghKHBvc1swXSAmIDB4ODApKSAvKiB0aW55IGF0b20g
-Ki8KPiArCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfdGlueShpdGVyLCBwb3MpOwo+
-ICsJCWVsc2UgaWYgKCEocG9zWzBdICYgMHg0MCkpIC8qIHNob3J0IGF0b20gKi8KPiArCQkJdG9r
-ZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2Vfc2hvcnQoaXRlciwgcG9zKTsKPiArCQllbHNlIGlm
-ICghKHBvc1swXSAmIDB4MjApKSAvKiBtZWRpdW0gYXRvbSAqLwo+ICsJCQl0b2tlbl9sZW5ndGgg
-PSByZXNwb25zZV9wYXJzZV9tZWRpdW0oaXRlciwgcG9zKTsKPiArCQllbHNlIGlmICghKHBvc1sw
-XSAmIDB4MTApKSAvKiBsb25nIGF0b20gKi8KPiArCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2Vf
-cGFyc2VfbG9uZyhpdGVyLCBwb3MpOwo+ICsJCWVsc2UgLyogVE9LRU4gKi8KPiArCQkJdG9rZW5f
-bGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfdG9rZW4oaXRlciwgcG9zKTsKPiArCj4gKwkJcG9zICs9
-IHRva2VuX2xlbmd0aDsKPiArCQljcG9zICs9IHRva2VuX2xlbmd0aDsKPiArCQlpdGVyKys7Cj4g
-KwkJbnVtX2VudHJpZXMrKzsKPiArCX0KPiArCj4gKwlpZiAobnVtX2VudHJpZXMgPT0gMCkgewo+
-ICsJCXByX2VycigiQ291bGRuJ3QgcGFyc2UgcmVzcG9uc2UuXG4iKTsKPiArCQlyZXQgPSAtRUlO
-VkFMOwo+ICsJCWdvdG8gZXJyOwo+ICsJfQo+ICsJcmVzcC0+bnVtID0gbnVtX2VudHJpZXM7Cj4g
-Kwo+ICsJcmV0dXJuIDA7Cj4gK2VycjoKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRp
-YyBzaXplX3QgcmVzcG9uc2VfZ2V0X3N0cmluZyhjb25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJl
-c3AsIGludCBuLAo+ICsJCQkJICBjb25zdCBjaGFyICoqc3RvcmUpCj4gK3sKPiArCSpzdG9yZSA9
-IE5VTEw7Cj4gKwlpZiAoIXJlc3ApIHsKPiArCQlwcl9lcnIoIlJlc3BvbnNlIGlzIE5VTExcbiIp
-Owo+ICsJCXJldHVybiAwOwo+ICsJfQo+ICsKPiArCWlmIChuID4gcmVzcC0+bnVtKSB7Cj4gKwkJ
-cHJfZXJyKCJSZXNwb25zZSBoYXMgJWQgdG9rZW5zLiBDYW4ndCBhY2Nlc3MgJWRcbiIsCj4gKwkJ
-ICAgICAgIHJlc3AtPm51bSwgbik7Cj4gKwkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ICsJaWYgKHJl
-c3AtPnRva3Nbbl0udHlwZSAhPSBPUEFMX0RUQV9UT0tFTklEX0JZVEVTVFJJTkcpIHsKPiArCQlw
-cl9lcnIoIlRva2VuIGlzIG5vdCBhIGJ5dGUgc3RyaW5nIVxuIik7Cj4gKwkJcmV0dXJuIDA7Cj4g
-Kwl9Cj4gKwo+ICsJKnN0b3JlID0gcmVzcC0+dG9rc1tuXS5wb3MgKyAxOwo+ICsJcmV0dXJuIHJl
-c3AtPnRva3Nbbl0ubGVuIC0gMTsKPiArfQo+ICsKPiArc3RhdGljIHU2NCByZXNwb25zZV9nZXRf
-dTY0KGNvbnN0IHN0cnVjdCBwYXJzZWRfcmVzcCAqcmVzcCwgaW50IG4pCj4gK3sKPiArCWlmICgh
-cmVzcCkgewo+ICsJCXByX2VycigiUmVzcG9uc2UgaXMgTlVMTFxuIik7Cj4gKwkJcmV0dXJuIDA7
-Cj4gKwl9Cj4gKwo+ICsJaWYgKG4gPiByZXNwLT5udW0pIHsKPiArCQlwcl9lcnIoIlJlc3BvbnNl
-IGhhcyAlZCB0b2tlbnMuIENhbid0IGFjY2VzcyAlZFxuIiwKPiArCQkgICAgICAgcmVzcC0+bnVt
-LCBuKTsKPiArCQlyZXR1cm4gMDsKPiArCX0KPiArCj4gKwlpZiAocmVzcC0+dG9rc1tuXS50eXBl
-ICE9IE9QQUxfRFRBX1RPS0VOSURfVUlOVCkgewo+ICsJCXByX2VycigiVG9rZW4gaXMgbm90IHVu
-c2lnbmVkIGl0OiAlZFxuIiwKPiArCQkgICAgICAgcmVzcC0+dG9rc1tuXS50eXBlKTsKPiArCQly
-ZXR1cm4gMDsKPiArCX0KPiArCj4gKwlpZiAoISgocmVzcC0+dG9rc1tuXS53aWR0aCA9PSBPUEFM
-X1dJRFRIX1RJTlkpIHx8Cj4gKwkgICAgICAocmVzcC0+dG9rc1tuXS53aWR0aCA9PSBPUEFMX1dJ
-RFRIX1NIT1JUKSkpIHsKPiArCQlwcl9lcnIoIkF0b20gaXMgbm90IHNob3J0IG9yIHRpbnk6ICVk
-XG4iLAo+ICsJCSAgICAgICByZXNwLT50b2tzW25dLndpZHRoKTsKPiArCQlyZXR1cm4gMDsKPiAr
-CX0KPiArCj4gKwlyZXR1cm4gcmVzcC0+dG9rc1tuXS5zdG9yZWQudTsKPiArfQo+ICsKPiArc3Rh
-dGljIHU4IHJlc3BvbnNlX3N0YXR1cyhjb25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJlc3ApCj4g
-K3sKPiArCWlmICgodG9rZW5fdHlwZShyZXNwLCAwKSA9PSBPUEFMX0RUQV9UT0tFTklEX1RPS0VO
-KQo+ICsJICAgICYmIChyZXNwb25zZV9nZXRfdG9rZW4ocmVzcCwgMCkgPT0gT1BBTF9FTkRPRlNF
-U1NJT04pKSB7Cj4gKwkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ICsJaWYgKHJlc3AtPm51bSA8IDUp
-Cj4gKwkJcmV0dXJuIERUQUVSUk9SX05PX01FVEhPRF9TVEFUVVM7Cj4gKwo+ICsJaWYgKCh0b2tl
-bl90eXBlKHJlc3AsIHJlc3AtPm51bSAtIDEpICE9IE9QQUxfRFRBX1RPS0VOSURfVE9LRU4pIHx8
-Cj4gKwkgICAgKHRva2VuX3R5cGUocmVzcCwgcmVzcC0+bnVtIC0gNSkgIT0gT1BBTF9EVEFfVE9L
-RU5JRF9UT0tFTikgfHwKPiArCSAgICAocmVzcG9uc2VfZ2V0X3Rva2VuKHJlc3AsIHJlc3AtPm51
-bSAtIDEpICE9IE9QQUxfRU5ETElTVCkgfHwKPiArCSAgICAocmVzcG9uc2VfZ2V0X3Rva2VuKHJl
-c3AsIHJlc3AtPm51bSAtIDUpICE9IE9QQUxfU1RBUlRMSVNUKSkKPiArCQlyZXR1cm4gRFRBRVJS
-T1JfTk9fTUVUSE9EX1NUQVRVUzsKPiArCj4gKwlyZXR1cm4gcmVzcG9uc2VfZ2V0X3U2NChyZXNw
-LCByZXNwLT5udW0gLSA0KTsKPiArfQo+ICsKPiArLyogUGFyc2VzIGFuZCBjaGVja3MgZm9yIGVy
-cm9ycyAqLwo+ICtzdGF0aWMgaW50IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoc3RydWN0IG9wYWxf
-ZGV2ICpkZXYpCj4gK3sKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJaW50IGVycm9yOwo+
-ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsKPiArCXByaW50X2J1ZmZlcihjbWQtPmNtZCwgY21kLT5w
-b3MpOwo+ICsKPiArCWVycm9yID0gcmVzcG9uc2VfcGFyc2UoY21kLT5yZXNwLCBJT19CVUZGRVJf
-TEVOR1RILCAmZGV2LT5wYXJzZWQpOwo+ICsJaWYgKGVycm9yKSB7Cj4gKwkJcHJfZXJyKCIlczog
-Q291bGRuJ3QgcGFyc2UgcmVzcG9uc2UuXG4iLCBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJZ290byBl
-cnJfcmV0dXJuOwo+ICsJfQo+ICsKPiArCWVycm9yID0gcmVzcG9uc2Vfc3RhdHVzKCZkZXYtPnBh
-cnNlZCk7Cj4gKwlpZiAoZXJyb3IpCj4gKwkJcHJfZXJyKCIlczogUmVzcG9uc2UgU3RhdHVzOiAl
-ZFxuIiwgZGV2LT5kaXNrX25hbWUsCj4gKwkJICAgICAgIGVycm9yKTsKPiArCj4gKyBlcnJfcmV0
-dXJuOgo+ICsJcmV0dXJuIGVycm9yOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjbGVhcl9vcGFs
-X2NtZChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCkKPiArewo+ICsJY21kLT5wb3MgPSBzaXplb2Yoc3Ry
-dWN0IG9wYWxfaGVhZGVyKTsKPiArCW1lbXNldChjbWQtPmNtZCwgMCwgSU9fQlVGRkVSX0xFTkdU
-SCk7Cj4gKwljbWQtPmNiID0gTlVMTDsKPiArCWNtZC0+Y2JfZGF0YSA9IE5VTEw7Cj4gK30KPiAr
-Cj4gK3N0YXRpYyB2b2lkIHN0YXJ0X29wYWxfc2Vzc2lvbl9jb250KGludCBlcnJvciwgdm9pZCAq
-ZGF0YSkKPiArewo+ICsJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwo+ICsJdTMyIEhTTiwg
-VFNOOwo+ICsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4gKwo+ICsJZXJy
-b3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7Cj4gKwlpZiAoZXJyb3IpCj4gKwkJZ290
-byBlcnJfcmV0dXJuOwo+ICsKPiArCUhTTiA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2Vk
-LCA0KTsKPiArCVRTTiA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2VkLCA1KTsKPiArCj4g
-KwlpZiAoSFNOID09IDAgJiYgVFNOID09IDApIHsKPiArCQlwcl9lcnIoIiVzOiBDb3VsZG4ndCBh
-dXRoZW50aWNhdGUgc2Vzc2lvblxuIiwgZGV2LT5kaXNrX25hbWUpOwo+ICsJCWVycm9yID0gLUVQ
-RVJNOwo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCX0KPiArCj4gKwlkZXYtPkhTTiA9IEhTTjsK
-PiArCWRldi0+VFNOID0gVFNOOwo+ICsKPiArZXJyX3JldHVybjoKPiArCWlmIChkZXYtPm9wZXJf
-Y2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50
-IGdldF9vcGFsX2tleShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJc3RydWN0IGtleSAq
-dWtleSA9IE5VTEw7Cj4gKwljb25zdCB1OCAqdG1wa2V5ID0gTlVMTDsKPiArCXNpemVfdCB0bXBs
-ZW47Cj4gKwlpbnQgcmV0ID0gMDsKPiArCj4gKwlpZiAoZGV2LT5rZXlfdHlwZSA9PSBPUEFMX0tF
-WV9QTEFJTikgewo+ICsJCXRtcGtleSA9IGRldi0+a2V5X25hbWU7Cj4gKwkJdG1wbGVuID0gZGV2
-LT5rZXlfbmFtZV9sZW47Cj4gKwl9IGVsc2UgaWYgKGRldi0+a2V5X3R5cGUgPT0gT1BBTF9LRVlf
-S0VZUklORykgewo+ICsJCXVrZXkgPSByZXF1ZXN0X3VzZXJfa2V5KGRldi0+a2V5X25hbWUsICZ0
-bXBrZXksICZ0bXBsZW4pOwo+ICsJCWlmIChJU19FUlIodWtleSkpIHsKPiArCQkJcHJfZXJyKCIl
-czogQ2FuJ3QgcmV0cmlldmUga2V5OiAlbGRcbiIsIGRldi0+ZGlza19uYW1lLAo+ICsJCQkgICAg
-ICAgUFRSX0VSUih1a2V5KSk7Cj4gKwkJCXJldHVybiBQVFJfRVJSKHVrZXkpOwo+ICsJCX0KPiAr
-CX0gZWxzZSB7Cj4gKwkJcHJfZXJyKCJSZXF1ZXN0ZWQgaW52YWxpZCBrZXkgdHlwZTogJWRcbiIs
-IGRldi0+a2V5X3R5cGUpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWlmICh0
-bXBsZW4gPiBPUEFMX0tFWV9NQVgpIHsKPiArCQlwcl9lcnIoIlJlcXVlc3RlZCBrZXkgd2l0aCBp
-bnZhbGlkIHNpemU6ICV6ZFxuIiwgdG1wbGVuKTsKPiArCQlyZXQgPSAtRUlOVkFMOwo+ICsJCWdv
-dG8gZXJyX2V4aXQ7Cj4gKwl9Cj4gKwo+ICsJZGV2LT5rZXlfbGVuID0gdG1wbGVuOwo+ICsJaWYg
-KCFtZW1jcHkoZGV2LT5rZXksIHRtcGtleSwgdG1wbGVuKSkgewo+ICsJCXByX2VycigiRXJyb3Ig
-d2hlbiBjb3B5aW5nIGtleSIpOwo+ICsJCXJldCA9IC1FRkFVTFQ7Cj4gKwkJZ290byBlcnJfZXhp
-dDsKPiArCX0KPiArCj4gK2Vycl9leGl0Ogo+ICsJa2V5X3B1dCh1a2V5KTsKPiArCj4gKwlyZXR1
-cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgY2xlYW5fb3BhbF9rZXkoc3RydWN0IG9wYWxf
-ZGV2ICpkZXYpCj4gK3sKPiArCW1lbXNldChkZXYtPmtleSwgMCwgT1BBTF9LRVlfTUFYKTsKPiAr
-CWRldi0+a2V5X2xlbiA9IDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgdm9pZCBjbGVhbl9m
-dW5jdGlvbl9kYXRhKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwkJZGV2LT5mdW5jX2Rh
-dGEgPSBOVUxMOwo+ICsJCWRldi0+bnVtX2Z1bmNfZGF0YSA9IDA7Cj4gK30KPiArCj4gKy8qIFRo
-aXMgaXMgYSBnZW5lcmljIGNvbnRpbnVlIGZuLgo+ICsgKiBXZSB1c2UgdGhpcyB3aGVuIHdlIGRv
-bid0IGNhcmUgYWJvdXQgdGhlIHJlc3BvbnNlIGRhdGEKPiArICogYW5kIHNpbXBseSB3YW50IHRv
-IGNoZWNrIHRoZSBzdGF0dXMgYW5kIGNvbnRpbnVlLgo+ICsgKi8KPiArc3RhdGljIHZvaWQgZ2Vu
-ZXJpY19jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKPiArewo+ICsJc3RydWN0IG9wYWxfZGV2
-ICpkZXYgPSBkYXRhOwo+ICsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4g
-Kwo+ICsJZXJyb3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7Cj4gKwo+ICsgZXJyX3Jl
-dHVybjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYp
-Owo+ICt9CgpIb3cgYWJvdXQ6CgpzdGF0aWMgdm9pZCBnZW5lcmljX2NvbnQoaW50IGVycm9yLCB2
-b2lkICpkYXRhKQp7CglzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CgoJaWYgKCFlcnJvcikK
-CQllcnJvciA9IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoZGV2KTsKCglpZiAoZGV2LT5vcGVyX2Ni
-KQoJCWRldi0+b3Blcl9jYihlcnJvciwgZGV2KTsKfQoKPiArCj4gK3N0YXRpYyB2b2lkIGVuZF9z
-ZXNzaW9uX2NvbnQoaW50IGVycm9yLCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9k
-ZXYgKmRldiA9IGRhdGE7Cj4gKwo+ICsJZGV2LT5IU04gPSAwOwo+ICsJZGV2LT5UU04gPSAwOwo+
-ICsJZ2VuZXJpY19jb250KGVycm9yLCBkYXRhKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBmaW5h
-bGl6ZV9hbmRfc2VuZChzdHJ1Y3Qgb3BhbF9kZXYgKmRldiwgc3RydWN0IG9wYWxfY21kICpjbWQs
-Cj4gKwkJCSAgICAgc2VjX2NiIGNvbnQpCj4gK3sKPiArCWludCByZXQ7Cj4gKwo+ICsJcmV0ID0g
-Y21kX2ZpbmFsaXplKGNtZCwgZGV2LT5IU04sIGRldi0+VFNOKTsKPiArCWlmIChyZXQpIHsKPiAr
-CQlwcl9lcnIoIiVzOiBFcnJvciBmaW5hbGl6aW5nIGNvbW1hbmQgYnVmZmVyOiAlZFxuIiwKPiAr
-CQkgICAgICAgZGV2LT5kaXNrX25hbWUsIHJldCk7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiAr
-Cj4gKwlwcmludF9idWZmZXIoY21kLT5jbWQsIGNtZC0+cG9zKTsKPiArCj4gKwlyZXQgPSBvcGFs
-X3NlbmRfcmVjdihkZXYsIGNvbnQsIGRldik7Cj4gKwlpZiAocmV0KQo+ICsJCXByX2VycigiJXM6
-IEVycm9yIHJ1bm5pbmcgY29tbWFuZDogJWRcbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1l
-LCByZXQpOwo+ICsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgd2FpdF9m
-b3JfY21kX2NvbXBsZXRpb24oc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbikKPiAr
-ewo+ICsJd2FpdF9mb3JfY29tcGxldGlvbl9pbnRlcnJ1cHRpYmxlKCZjb21wbGV0aW9uLT5jbWRf
-Y29tcGxldGlvbik7Cj4gKwlyZXR1cm4gY29tcGxldGlvbi0+Y29tcGxldGlvbl9zdGF0dXM7Cj4g
-K30KPiArCj4gK3N0YXRpYyBpbnQgZ2VuX2tleShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+
-ICsJY29uc3QgdTggKm1ldGhvZDsKPiArCXU4IHVpZFtPUEFMX1VJRF9MRU5HVEhdOwo+ICsJc3Ry
-dWN0IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsK
-PiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsK
-PiArCj4gKwltZW1jcHkodWlkLCBkZXYtPnByZXZfZGF0YSwgbWluKHNpemVvZih1aWQpLCBkZXYt
-PnByZXZfZF9sZW4pKTsKPiArCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRU5LRVldOwo+ICsJ
-a2ZyZWUoZGV2LT5wcmV2X2RhdGEpOwo+ICsJZGV2LT5wcmV2X2RhdGEgPSBOVUxMOwo+ICsKPiAr
-CXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgMmMiLAo+ICsJCQkJICAgIE9Q
-QUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRo
-b2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4g
-KwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIl
-czogRXJyb3IgYnVpbGRpbmcgZ2VuIGtleSBjb21tYW5kXG4iLAo+ICsJCSAgICAgICBkZXYtPmRp
-c2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVf
-YW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29udCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lk
-IGdldF9hY3RpdmVfa2V5X2NvbnQoaW50IGVycm9yLCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1
-Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7Cj4gKwljb25zdCBjaGFyICphY3RpdmVrZXk7Cj4gKwlz
-aXplX3Qga2V5bGVuOwo+ICsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4g
-Kwo+ICsJZXJyb3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7Cj4gKwlpZiAoZXJyb3Ip
-Cj4gKwkJZ290byBlcnJfcmV0dXJuOwo+ICsJa2V5bGVuID0gcmVzcG9uc2VfZ2V0X3N0cmluZygm
-ZGV2LT5wYXJzZWQsIDQsICZhY3RpdmVrZXkpOwo+ICsJaWYgKCFhY3RpdmVrZXkpIHsKPiArCQlw
-cl9lcnIoIiVzOiBDb3VsZG4ndCBleHRyYWN0IHRoZSBBY3RpdmVrZXkgZnJvbSB0aGUgcmVzcG9u
-c2VcbiIsCj4gKwkJICAgICAgIF9fZnVuY19fKTsKPiArCQllcnJvciA9IDB4MEE7Cj4gKwkJZ290
-byBlcnJfcmV0dXJuOwo+ICsJfQo+ICsJZGV2LT5wcmV2X2RhdGEgPSBrbWVtZHVwKGFjdGl2ZWtl
-eSwga2V5bGVuLCBHRlBfS0VSTkVMKTsKPiArCj4gKwlpZiAoIWRldi0+cHJldl9kYXRhKQo+ICsJ
-CWVycm9yID0gLUVOT01FTTsKPiArCj4gKwlkZXYtPnByZXZfZF9sZW4gPSBrZXlsZW47Cj4gKwo+
-ICtlcnJfcmV0dXJuOgo+ICsJaWYgKGRldi0+b3Blcl9jYikKPiArCQlkZXYtPm9wZXJfY2IoZXJy
-b3IsIGRldik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZ2V0X2FjdGl2ZV9rZXkoc3RydWN0IG9w
-YWxfZGV2ICpkZXYpCj4gK3sKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwl1OCB1aWRbT1BBTF9V
-SURfTEVOR1RIXTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJaW50IHJldDsKPiArCj4g
-KwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsJc2V0X2NvbUlE
-KGNtZCwgZGV2LT5jb21JRCk7Cj4gKwo+ICsJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0dFVF07
-Cj4gKwo+ICsJcmV0ID0gYnVpbGRfbG9ja2luZ19yYW5nZSh1aWQsIHNpemVvZih1aWQpLCBkZXYt
-PmxyKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9j
-a2luZyByYW5nZVxuIiwgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJ
-fQo+ICsKPiArCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgNmMgNGMgMmMi
-LAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwK
-PiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BB
-TF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9T
-VEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIHN0YXJ0Q2xvdW1uICov
-Cj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMTAsIC8qIEFjdGl2ZUtleSAqLwo+ICsJCQkJICAg
-IE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAg
-T1BBTF9USU5ZX1VJTlRfMDQsIC8qIGVuZENvbHVtbiAqLwo+ICsJCQkJICAgIE9QQUxfVElOWV9V
-SU5UXzEwLCAvKiBBY3RpdmVLZXkgKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJ
-CQkJICAgIE9QQUxfRU5ETElTVCwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsJaWYgKHJl
-dCA8IDApIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBnZXQgYWN0aXZlIGtleSBj
-b21tYW5kXG4iLAo+ICsJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsK
-PiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdldF9hY3Rp
-dmVfa2V5X2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNldHVwX2xvY2tpbmdfcmFuZ2Uo
-c3RydWN0IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwl1OCB1
-aWRbT1BBTF9VSURfTEVOR1RIXTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJc3RydWN0
-IG9wYWxfdXNlcl9scl9zZXR1cCAqc2V0dXA7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZk
-ZXYtPmNtZDsKPiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwlzZXRfY29tSUQoY21kLCBkZXYt
-PmNvbUlEKTsKPiArCj4gKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU0VUXTsKPiArCXJldCA9
-IGJ1aWxkX2xvY2tpbmdfcmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5scik7Cj4gKwlpZiAo
-cmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIs
-IGRldi0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCXNldHVwID0g
-ZGV2LT5mdW5jX2RhdGFbZGV2LT5zdGF0ZSAtIDFdOwo+ICsKPiArCXJldCA9IHRlc3RfYW5kX2Fk
-ZF90b2tlbl92YShjbWQsICJjMnMgIDRjIDJjdWMgMmN1YyAyY3VjIDJjdSA0YyIsCj4gKwkJCQkg
-ICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIHVpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAg
-IG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElT
-VCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywKPiAr
-CQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4g
-KwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIFJhbmdlIFN0YXJ0ICovCj4gKwkJCQkgICAg
-c2V0dXAtPnJhbmdlX3N0YXJ0LAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkg
-ICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDQsIC8qIFJhbmdl
-IExlbmd0aCAqLwo+ICsJCQkJICAgIHNldHVwLT5yYW5nZV9sZW5ndGgsCj4gKwkJCQkgICAgT1BB
-TF9FTkROQU1FLAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFM
-X1RJTllfVUlOVF8wNSwgLyogUmVhZExvY2tFbmFibGVkICovCj4gKwkJCQkgICAgISFzZXR1cC0+
-UkxFLAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5B
-TUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIFdyaXRlTG9ja0VuYWJsZWQgKi8K
-PiArCQkJCSAgICAhIXNldHVwLT5XTEUsCj4gKwo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiAr
-CQkJCSAgICBPUEFMX0VORExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+ICsJCQkJICAg
-IE9QQUxfRU5ETElTVCk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9y
-IGJ1aWxkaW5nIFNldHVwIExvY2tpbmcgcmFuZ2UgY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRl
-di0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCX0KPiArCj4gKwlyZXR1cm4g
-ZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29udCk7Cj4gK30KPiArCj4gK3N0
-YXRpYyBpbnQgc3RhcnRfYWRtaW5zcF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYs
-Cj4gKwkJCQkgICAgICBlbnVtIE9QQUxfVUlEIGF1dGgsCj4gKwkJCQkgICAgICBjb25zdCBjaGFy
-ICprZXksCj4gKwkJCQkgICAgICB1OCBrZXlfbGVuKQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9k
-LCAqc211aWQsICphZG1pbl9zcCwgKmhzYTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJ
-dTMyIEhTTjsKPiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKGtleSA9PSBOVUxMICYmIGF1dGggIT0g
-T1BBTF9BTllCT0RZX1VJRCkgewo+ICsJCXByX2VycigiJXM6IEF0dGVtcHRlZCB0byBvcGVuIEFE
-TUlOX1NQIFNlc3Npb24gd2l0aG91dCBhIEhvc3QiIFwKPiArCQkgICAgICAgIkNoYWxsZW5nZSwg
-YW5kIG5vdCBhcyB0aGUgQW55Ym9keSBVSURcbiIsIF9fZnVuY19fKTsKPiArCQlyZXR1cm4gMTsK
-PiArCX0KPiArCj4gKwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+
-ICsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsJSFNOID0gMHg0MTsKPiArCj4g
-KwlzbXVpZCA9IE9QQUxVSURbT1BBTF9TTVVJRF9VSURdOwo+ICsJbWV0aG9kID0gT1BBTE1FVEhP
-RFtPUEFMX1NUQVJUU0VTU0lPTl07Cj4gKwlhZG1pbl9zcCA9IE9QQUxVSURbT1BBTF9BRE1JTlNQ
-X1VJRF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyBjdXNj
-IiwKPiArCQkJCSAgICBPUEFMX0NBTEwsCj4gKwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdU
-SCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCQkJCSAgICBPUEFM
-X1NUQVJUTElTVCwKPiArCQkJCSAgICBIU04sCj4gKwkJCQkgICAgYWRtaW5fc3AsIE9QQUxfVUlE
-X0xFTkdUSCwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSk7Cj4gKwlpZiAocmV0IDwgMCkg
-ewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIHN0YXJ0IGFkbWluc3Agc2Vzc2lvbiBj
-b21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7
-Cj4gKwl9Cj4gKwo+ICsJc3dpdGNoIChhdXRoKSB7Cj4gKwljYXNlIE9QQUxfQU5ZQk9EWV9VSUQ6
-Cj4gKwkJLyogbm90aGluZyBsZWZ0IHRvIGRvIGZvciBhbnlib2R5LCBqdXN0IGVuZCBhbmQgZmlu
-YWxpemUgKi8KPiArCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYyIsCj4gKwkJ
-CQkJICAgIE9QQUxfRU5ETElTVCk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIE9QQUxfU0lEX1VJRDoK
-PiArCQloc2EgPSBPUEFMVUlEW09QQUxfU0lEX1VJRF07Cj4gKwkJcmV0ID0gdGVzdF9hbmRfYWRk
-X3Rva2VuX3ZhKGNtZCwgIjJjIHMgM2MgcyAyYyIsCj4gKwkJCQkJICAgIE9QQUxfU1RBUlROQU1F
-LAo+ICsJCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMCwgLyogSG9zdENoYWxsZW5nZSAqLwo+ICsJ
-CQkJCSAgICBrZXksIGtleV9sZW4sCj4gKwkJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJCQkg
-ICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAvKiBIb3N0
-U2lnbkF1dGggKi8KPiArCQkJCQkgICAgaHNhLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkJICAg
-IE9QQUxfRU5ETkFNRSwKPiArCQkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCQlicmVhazsKPiAr
-CWRlZmF1bHQ6Cj4gKwkJcHJfZXJyKCJDYW5ub3Qgc3RhcnQgQWRtaW4gU1Agc2Vzc2lvbiB3aXRo
-IGF1dGggJWRcbiIsIGF1dGgpOwo+ICsJCXJldHVybiAxOwo+ICsJfQo+ICsKPiArCWlmIChyZXQg
-PCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgc3RhcnQgYWRtaW5zcCBzZXNz
-aW9uIGNvbW1hbmQuXG4iLAo+ICsJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJu
-IHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0
-YXJ0X29wYWxfc2Vzc2lvbl9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzdGFydF9hbnli
-b2R5QVNQX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJcmV0dXJu
-IHN0YXJ0X2FkbWluc3Bfb3BhbF9zZXNzaW9uKGRldiwgT1BBTF9BTllCT0RZX1VJRCwgTlVMTCwg
-MCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgc3RhcnRfU0lEQVNQX29wYWxfc2Vzc2lvbihzdHJ1
-Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJaW50IHJldDsKPiArCWNvbnN0IHU4ICprZXkgPSBk
-ZXYtPnByZXZfZGF0YTsKPiArCj4gKwlpZiAoIWtleSkKPiArCQlyZXQgPSBzdGFydF9hZG1pbnNw
-X29wYWxfc2Vzc2lvbihkZXYsIE9QQUxfU0lEX1VJRCwgZGV2LT5rZXksCj4gKwkJCQkJCSBkZXYt
-PmtleV9sZW4pOwo+ICsJZWxzZSB7Cj4gKwkJcmV0ID0gc3RhcnRfYWRtaW5zcF9vcGFsX3Nlc3Np
-b24oZGV2LCBPUEFMX1NJRF9VSUQsIGtleSwKPiArCQkJCQkJIGRldi0+cHJldl9kX2xlbik7Cj4g
-KwkJa2ZyZWUoa2V5KTsKPiArCQlkZXYtPnByZXZfZGF0YSA9IE5VTEw7Cj4gKwl9Cj4gKwlyZXR1
-cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHN0YXJ0X2xvY2tpbmdzcF9vcGFsX3Nlc3Np
-b24oc3RydWN0IG9wYWxfZGV2ICpkZXYsCj4gKwkJCQkJZW51bSBPUEFMX1VJRCBhdXRoLCBjb25z
-dCB1OCAqa2V5LAo+ICsJCQkJCXU4IGtleV9sZW4pCj4gK3sKPiArCj4gKwljb25zdCB1OCAqbWV0
-aG9kLCAqc211aWQsICpsb2NraW5nX3NwLCAqaHNhOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7
-Cj4gKwlzaXplX3Qga2xlbiA9IGtleV9sZW47Cj4gKwl1MzIgSFNOOwo+ICsJaW50IHJldDsKPiAr
-Cj4gKwlpZiAoa2V5ID09IE5VTEwpIHsKPiArCQlwcl9lcnIoIkNhbm5vdCBzdGFydCBMb2NraW5n
-IFNQIHNlc3Npb24gd2l0aG91dCBhIGtleVxuIik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9
-Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCj4g
-KwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKPiArCUhTTiA9IDB4NDE7Cj4gKwo+ICsJc211
-aWQgPSBPUEFMVUlEW09QQUxfU01VSURfVUlEXTsKPiArCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BB
-TF9TVEFSVFNFU1NJT05dOwo+ICsJbG9ja2luZ19zcCA9IE9QQUxVSURbT1BBTF9MT0NLSU5HU1Bf
-VUlEXTsKPiArCWhzYSA9IE9QQUxVSURbYXV0aF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk
-X3Rva2VuX3ZhKGNtZCwgImMycyBjdXNjIDJjc2MgMmNzYyBjIiwKPiArCQkJCSAgICBPUEFMX0NB
-TEwsCj4gKwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2Qs
-IE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJ
-CQkgICAgSFNOLAo+ICsJCQkJICAgIGxvY2tpbmdfc3AsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJ
-CSAgICBPUEFMX1RJTllfVUlOVF8wMSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4g
-KwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDAsIC8qIEhvc3RDaGFsbGVuZ2UgKi8KPiArCQkJCSAg
-ICBrZXksIGtsZW4sCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+ICsKPiArCQkJCSAgICBPUEFM
-X1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogSG9zdCBTaWduIEF1
-dGhvcml0eSAqLwo+ICsJCQkJICAgIGhzYSwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9Q
-QUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlpZiAocmV0
-IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIHN0YXJ0IGFkbWluc3Agc2Vz
-c2lvbiBjb21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVy
-biByZXQ7Cj4gKwl9Cj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0YXJ0
-X29wYWxfc2Vzc2lvbl9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBpbnQgc3RhcnRf
-YWRtaW4xTFNQX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJcmV0
-dXJuIHN0YXJ0X2xvY2tpbmdzcF9vcGFsX3Nlc3Npb24oZGV2LCBPUEFMX0FETUlOMV9VSUQsCj4g
-KwkJCQkJICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4pOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50
-IHN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwlj
-b25zdCB1OCAqbWV0aG9kLCAqc211aWQsICpsb2NraW5nX3NwOwo+ICsJdTggbGtfdWxfdXNlcltP
-UEFMX1VJRF9MRU5HVEhdOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwl1MzIgSFNOOwo+
-ICsJaW50IHJldDsKPiArCXN0cnVjdCBvcGFsX3VzZXJfaW5mbyAqdWluZm87Cj4gKwo+ICsJY21k
-ID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCj4gKwlzZXRfY29tSUQo
-Y21kLCBkZXYtPmNvbUlEKTsKPiArCj4gKwlIU04gPSAweDQxOwpDYW4gd2UgI2RlZmluZSB0aGlz
-OyBpdCdzIHVzZWQgYSBmZXcgb3RoZXIgcGxhY2VzIGFuZCBpcyBtYWdpY2t5Cgo+ICsKPiArCXVp
-bmZvID0gZGV2LT5mdW5jX2RhdGFbZGV2LT5zdGF0ZSAtIDFdOwo+ICsKPiArCXNtdWlkID0gT1BB
-TFVJRFtPUEFMX1NNVUlEX1VJRF07Cj4gKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU1RBUlRT
-RVNTSU9OXTsKPiArCWxvY2tpbmdfc3AgPSBPUEFMVUlEW09QQUxfTE9DS0lOR1NQX1VJRF07Cj4g
-Kwo+ICsJaWYgKHVpbmZvLT5TVU0pIHsKPiArCQlyZXQgPSBidWlsZF9sb2NraW5nX3VzZXIobGtf
-dWxfdXNlciwgc2l6ZW9mKGxrX3VsX3VzZXIpLAo+ICsJCQkJCSBkZXYtPmxyKTsKPiArCQlpZiAo
-cmV0IDwgMCkgewo+ICsJCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHVzZXJcbiIs
-Cj4gKwkJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJCXJldHVybiByZXQ7Cj4gKwkJfQo+
-ICsJfSBlbHNlIGlmICh1aW5mby0+d2hvICE9IE9QQUxfQURNSU4xICYmICF1aW5mby0+U1VNKSB7
-Cj4gKwkJcmV0ID0gYnVpbGRfbG9ja2luZ191c2VyKGxrX3VsX3VzZXIsIHNpemVvZihsa191bF91
-c2VyKSwKPiArCQkJCQkgdWluZm8tPndobyAtIDEpOwo+ICsJCWlmIChyZXQgPCAwKSB7Cj4gKwkJ
-CXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgdXNlclxuIiwKPiArCQkJICAgICAgIGRl
-di0+ZGlza19uYW1lKTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwl9IGVsc2UKPiArCQlt
-ZW1jcHkobGtfdWxfdXNlciwgT1BBTFVJRFtPUEFMX0FETUlOMV9VSURdLCBPUEFMX1VJRF9MRU5H
-VEgpOwo+ICsKPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIGN1
-czNjczNjIHMgMmMiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICBzbXVpZCwgT1BB
-TF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsK
-PiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBIU04sCj4gKwkJCQkgICAgbG9j
-a2luZ19zcCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLAo+
-ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAwLAo+
-ICsJCQkJICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4sCj4gKwkJCQkgICAgT1BBTF9FTkROQU1F
-LAo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAz
-LAo+ICsKPiArCQkJCSAgICBsa191bF91c2VyLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwo+ICsJCQkJ
-ICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsKPiArCWlmIChy
-ZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgU1RBUlRTRVNTSU9OIGNv
-bW1hbmQuXG4iLAo+ICsJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsK
-PiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0YXJ0X29w
-YWxfc2Vzc2lvbl9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCByZXZlcnRfdHBlcihzdHJ1
-Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJY29uc3QgdTggKm1ldGhvZCwgKnNtdWlkOwo+ICsJ
-c3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZkZXYtPmNt
-ZDsKPiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5j
-b21JRCk7Cj4gKwo+ICsJc211aWQgPSBPUEFMVUlEW09QQUxfQURNSU5TUF9VSURdOwo+ICsJbWV0
-aG9kID0gT1BBTE1FVEhPRFtPUEFMX1JFVkVSVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk
-X3Rva2VuX3ZhKGNtZCwgImMycyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAg
-IHNtdWlkLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9M
-RU5HVEgsCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNU
-KTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgUkVW
-RVJUIFRQRVIgY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKPiArCQly
-ZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNt
-ZCwgZ2VuZXJpY19jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBpbnRlcm5hbF9hY3RpdmF0
-ZV91c2VyKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9kOwo+
-ICsJdTggdWlkW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiAr
-CWludCByZXQ7Cj4gKwlzdHJ1Y3Qgb3BhbF9hY3RpdmF0ZV91c2VyICphY3Q7Cj4gKwo+ICsJY21k
-ID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQs
-IGRldi0+Y29tSUQpOwo+ICsKPiArCWFjdCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAx
-XTsKPiArCj4gKwltZW1jcHkodWlkLCBPUEFMVUlEW09QQUxfVVNFUjFfVUlEXSwgT1BBTF9VSURf
-TEVOR1RIKTsKPiArCXVpZFs3XSA9IGFjdC0+d2hvLndobzsKPiArCj4gKwltZXRob2QgPSBPUEFM
-TUVUSE9EW09QQUxfU0VUXTsKPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21k
-LCAiYzJzIDNjIGMgNGMgM2MiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQs
-IE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwK
-PiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUs
-Cj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDEsIC8qIFZhbHVlcyAqLwo+ICsKPiArCQkJCSAg
-ICBPUEFMX1NUQVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkg
-ICAgT1BBTF9USU5ZX1VJTlRfMDUsIC8qIEVuYWJsZWQgKi8KPiArCQkJCSAgICBPUEFMX1RJTllf
-VUlOVF8wMSwgLyogVHJ1ZSAqLwo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkg
-ICAgT1BBTF9FTkRMSVNULAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJCSAgICBPUEFM
-X0VORExJU1QpOwo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3Ig
-YnVpbGRpbmcgQWN0aXZhdGUgVXNlck4gY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlz
-a19uYW1lKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9h
-bmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBl
-cmFzZV9sb2NraW5nX3JhbmdlKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1
-OCAqbWV0aG9kOwo+ICsJdTggdWlkW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9j
-bWQgKmNtZDsKPiArCWludCByZXQ7Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJf
-b3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1l
-dGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9FUkFTRV07Cj4gKwo+ICsJaWYgKGJ1aWxkX2xvY2tpbmdf
-cmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5scikgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczog
-Q2FuJ3QgYnVpbGQgbG9ja2luZyByYW5nZVxuIiwgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVy
-biAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQs
-ICJjMnMgMmMiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlE
-X0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJ
-CQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlp
-ZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEVyYXNlIExvY2tp
-bmcgUmFuZ2UgQ21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJl
-dHVybiByZXQ7Cj4gKwl9Cj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdl
-bmVyaWNfY29udCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgc2V0X21icl9kb25lKHN0cnVjdCBv
-cGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9kLCAqdWlkOwo+ICsJc3RydWN0
-IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXU4IG1icl9kb25lX3RmID0gKih1
-OCAqKWRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKPiArCj4gKwljbWQgPSAmZGV2LT5j
-bWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21J
-RCk7Cj4gKwo+ICsJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07Cj4gKwl1aWQgPSBPUEFM
-VUlEW09QQUxfTUJSQ09OVFJPTF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3Zh
-KGNtZCwgImMycyAzYyA2YyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIHVp
-ZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RI
-LAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFN
-RSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1Qs
-Cj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDIs
-IC8qIERvbmUgKi8KPiArCQkJCSAgICBtYnJfZG9uZV90ZiwgICAgICAgLyogRG9uZSBUIG9yIEYg
-Ki8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsK
-PiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCWlm
-IChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgc2V0IE1CUiBEb250
-L05vdCBkb25lIGNvbW1hbmRcbiIsCnMvRG9udC9Eb25lLyA/CgoKPiArCQkgICAgICAgZGV2LT5k
-aXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXpl
-X2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50
-IHNldF9tYnJfZW5hYmxlX2Rpc2FibGUoc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCWNv
-bnN0IHU4ICptZXRob2QsICp1aWQ7Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWludCBy
-ZXQ7Cj4gKwo+ICsJdTggbWJyX2VuX2RpcyA9ICoodTggKilkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0
-YXRlIC0gMV07Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21k
-KTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9QQUxN
-RVRIT0RbT1BBTF9TRVRdOwo+ICsJdWlkID0gT1BBTFVJRFtPUEFMX01CUkNPTlRST0xdOwo+ICsK
-PiArCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgM2MgNmMgMmMiLAo+ICsJ
-CQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJ
-CSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFS
-VExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9WQUxVRVMs
-Cj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1F
-LAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLCAvKiBFbmFibGUgKi8KPiArCQkJCSAgICBt
-YnJfZW5fZGlzLCAgICAgICAgLyogRW5hYmxlIG9yIERpc2FibGUgKi8KPiArCQkJCSAgICBPUEFM
-X0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsKPiArCQkJCSAgICBPUEFMX0VO
-RE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJ
-cHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgc2V0IE1CUiBEb250L05vdCBkb25lIGNvbW1hbmRc
-biIsCnMvRG9udC9Eb25lLyA/CgoKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJl
-dHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21k
-LCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNldF9uZXdfcHcoc3RydWN0
-IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwl1OCBjcGluX3Vp
-ZFtPUEFMX1VJRF9MRU5HVEhdOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0
-Owo+ICsJc3RydWN0IG9wYWxfbmV3X3B3ICpwdzsKPiArCXNpemVfdCBrZXlfbGVuOwo+ICsJdTgg
-KmtleTsKPiArCj4gKwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+
-ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7Cj4gKwo+ICsJcHcgPSBkZXYtPmZ1bmNfZGF0
-YVtkZXYtPnN0YXRlIC0gMV07Cj4gKwlrZXkgPSBwdy0+bmV3X3Bpbi5rZXk7Cj4gKwlrZXlfbGVu
-ID0gcHctPm5ld19waW4ua2V5X2xlbjsKPiArCW1lbWNweShjcGluX3VpZCwgT1BBTFVJRFtPUEFM
-X0NfUElOX0FETUlOMV0sIE9QQUxfVUlEX0xFTkdUSCk7Cj4gKwo+ICsJaWYgKHB3LT51c2VyX2Zv
-cl9wdyAhPSBPUEFMX0FETUlOMSkgewo+ICsJCWNwaW5fdWlkWzVdID0gMHgwMzsKPiArCQlpZiAo
-cHctPndoby5TVU0pCj4gKwkJCWNwaW5fdWlkWzddID0gcHctPm5ld19waW4ubHIgKyAxOwo+ICsJ
-CWVsc2UKPiArCQkJY3Bpbl91aWRbN10gPSBwdy0+dXNlcl9mb3JfcHc7Cj4gKwl9Cj4gKwo+ICsJ
-bWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk
-X3Rva2VuX3ZhKGNtZCwgImMycyAzYyAzY3MyYyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+
-ICsJCQkJICAgIGNwaW5fdWlkLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkgICAgbWV0aG9kLCBP
-UEFMX01FVEhPRF9MRU5HVEgsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsJCQkJ
-ICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLCAvKiBWYWx1
-ZXMgKi8KPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFS
-VE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIFBJTiAqLwo+ICsJCQkJICAg
-IGtleSwga2V5X2xlbiwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9F
-TkRMSVNULAo+ICsKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRM
-SVNUKTsKPiArCj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxk
-aW5nIFNFVCBBTUlOMSBQSU4gY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1l
-KTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2Vu
-ZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzZXRfc2lk
-X2NwaW5fcGluKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9k
-LCAqY3Bpbl91aWQ7Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWludCByZXQ7Cj4gKwo+
-ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21J
-RChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCWNwaW5fdWlkID0gT1BBTFVJRFtPUEFMX0NfUElO
-X1NJRF07Cj4gKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU0VUXTsKPiArCj4gKwlyZXQgPSB0
-ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDJjIDRjczJjIDJjIiwKPiArCQkJCSAgICBP
-UEFMX0NBTEwsCj4gKwkJCQkgICAgY3Bpbl91aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAg
-ICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJ
-U1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfVElOWV9V
-SU5UXzAxLCAvKiBWYWx1ZXMgKi8KPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAg
-ICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElOICov
-Cj4gKwkJCQkgICAgZGV2LT5rZXksIGRldi0+a2V5X2xlbiwKPiArCQkJCSAgICBPUEFMX0VORE5B
-TUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsKPiArCQkJCSAgICBPUEFMX0VORE5BTUUs
-Cj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXBy
-X2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIFNFVCBDUElOIFBJTiBjb21tYW5kLlxuIiwKPiArCQkg
-ICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0
-dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+
-ICtzdGF0aWMgdm9pZCBxdWVyeV9sb2NraW5nX3JhbmdlX2NvbnQoaW50IGVycm9yLCB2b2lkICpk
-YXRhKQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7Cj4gKwo+ICsJaWYgKGVy
-cm9yKQo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCj4gKwllcnJvciA9IHBhcnNlX2FuZF9jaGVj
-a19zdGF0dXMoZGV2KTsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4gKwo+
-ICsJZGV2LT5zdGFydCA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2VkLCA0KTsKPiArCWRl
-di0+bGVuZ3RoID0gcmVzcG9uc2VfZ2V0X3U2NCgmZGV2LT5wYXJzZWQsIDgpOwo+ICsKPiArZXJy
-X3JldHVybjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBk
-ZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHF1ZXJ5X2xvY2tpbmdfcmFuZ2Uoc3RydWN0IG9w
-YWxfZGV2ICpkZXYpCj4gK3sKPiArCXU4IGxyX2J1ZmZlcltPUEFMX1VJRF9MRU5HVEhdOwo+ICsJ
-c3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwljb25zdCB1OCAqbWV0aG9kOwo+ICsJaW50IHJldDsK
-PiArCj4gKwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsKPiAr
-CW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRVRdOwo+ICsKPiArCWlmIChidWlsZF9sb2NraW5n
-X3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1ZmZlciksIGRldi0+bHIpIDwgMCkgewo+ICsJ
-CXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIsIGRldi0+ZGlza19uYW1l
-KTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlzZXRfY29tSUQoY21kLCBkZXYt
-PmNvbUlEKTsKPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDEy
-YyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURf
-TEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsKPiArCQkJ
-CSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAg
-ICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1NUQVJUQ09MVU1OLAo+ICsJCQkJICAg
-IE9QQUxfUkFOR0VTVEFSVCwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BB
-TF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRDT0xVTU4sCj4gKwkJCQkgICAgT1BBTF9S
-QU5HRUxFTkdUSCwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRM
-SVNULAo+ICsJCQkJICAgIE9QQUxfRU5ETElTVCk7Cj4gKwo+ICsJaWYgKHJldCA8IDApIHsKPiAr
-CQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBHRVQgTG9ja2luZyBSYW5nZSBjb21tYW5kLlxu
-IiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4g
-Kwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBxdWVyeV9sb2NraW5nX3Jh
-bmdlX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkZF91c2VyX3RvX2xyKHN0cnVjdCBv
-cGFsX2RldiAqZGV2KQo+ICt7Cj4gKwl1OCBscl9idWZmZXJbT1BBTF9VSURfTEVOR1RIXTsKPiAr
-CXU4IHVzZXJfdWlkW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsK
-PiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayAqbGt1bDsK
-PiArCWludCByZXQ7Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQo
-Y21kKTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9Q
-QUxNRVRIT0RbT1BBTF9TRVRdOwo+ICsKPiArCWxrdWwgPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0
-YXRlIC0gMV07Cj4gKwo+ICsJbWVtY3B5KGxyX2J1ZmZlciwgT1BBTFVJRFtPUEFMX0xPQ0tJTkdS
-QU5HRV9BQ0VfUkRMT0NLRURdLAo+ICsJICAgICAgIE9QQUxfVUlEX0xFTkdUSCk7Cj4gKwo+ICsJ
-aWYgKGxrdWwtPmxfc3RhdGUgPT0gT1BBTF9SVykKPiArCQltZW1jcHkobHJfYnVmZmVyLCBPUEFM
-VUlEW09QQUxfTE9DS0lOR1JBTkdFX0FDRV9XUkxPQ0tFRF0sCj4gKwkJICAgICAgIE9QQUxfVUlE
-X0xFTkdUSCk7Cj4gKwo+ICsJbHJfYnVmZmVyWzddID0gZGV2LT5scjsKPiArCj4gKwltZW1jcHko
-dXNlcl91aWQsIE9QQUxVSURbT1BBTF9VU0VSMV9VSURdLCBPUEFMX1VJRF9MRU5HVEgpOwo+ICsJ
-dXNlcl91aWRbN10gPSBsa3VsLT5hdXRob3JpdHkud2hvOwo+ICsKPiArCXJldCA9IHRlc3RfYW5k
-X2FkZF90b2tlbl92YShjbWQsICJjMnMgM2MgM2MgMmMgMnNjIGMyc2MgY3MyYyA1YyIsCj4gKwkJ
-CQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVOR1RILAo+
-ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsKPiArCQkJCSAgICBPUEFM
-X1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1RJ
-TllfVUlOVF8wMSwgLyogVmFsdWVzICovCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+
-ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAv
-KiBCb29sZWFuRXhwciAqLwo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAg
-ICBPUEFMX1NUQVJUTkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTFVJRFtPUEFMX0hBTEZfVUlEX0FV
-VEhPUklUWV9PQkpfUkVGXSwKPiArCQkJCSAgICBPUEFMX1VJRF9MRU5HVEhfSEFMRiwKPiArCQkJ
-CSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwK
-PiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTFVJRFtPUEFMX0hB
-TEZfVUlEX0FVVEhPUklUWV9PQkpfUkVGXSwKPiArCQkJCSAgICBPUEFMX1VJRF9MRU5HVEhfSEFM
-RiwKPiArCQkJCSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxf
-RU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTFVJ
-RFtPUEFMX0hBTEZfVUlEX0JPT0xFQU5fQUNFXSwKPiArCQkJCSAgICBPUEFMX1VJRF9MRU5HVEhf
-SEFMRiwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSwKPiArCQkJCSAgICBPUEFMX0VORE5B
-TUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfRU5ETElTVCwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUs
-Cj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJ
-CSAgICBPUEFMX0VORExJU1QpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlwcl9lcnIoIiVzOiBF
-cnJvciBidWlsZGluZyBhZGQgdXNlciB0byBsb2NraW5nIHJhbmdlIGNvbW1hbmQuXG4iLAo+ICsJ
-CSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwly
-ZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29udCk7Cj4gK30KPiAr
-Cj4gK3N0YXRpYyBpbnQgbG9ja191bmxvY2tfbG9ja2luZ19yYW5nZShzdHJ1Y3Qgb3BhbF9kZXYg
-KmRldikKPiArewo+ICsJdTggbHJfYnVmZmVyW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qg
-b3BhbF9jbWQgKmNtZDsKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2Nr
-X3VubG9jayAqbGt1bDsKPiArCWludCByZXQ7Cj4gKwl1OCByZWFkX2xvY2tlZCA9IDEsIHdyaXRl
-X2xvY2tlZCA9IDE7Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQo
-Y21kKTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9Q
-QUxNRVRIT0RbT1BBTF9TRVRdOwo+ICsJbGt1bCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUg
-LSAxXTsKPiArCWlmIChidWlsZF9sb2NraW5nX3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1
-ZmZlciksIGRldi0+bHIpIDwgMCkgewo+ICsJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tp
-bmcgcmFuZ2VcbiIsIGRldi0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0K
-PiArCj4gKwlzd2l0Y2ggKGxrdWwtPmxfc3RhdGUpIHsKPiArCWNhc2UgT1BBTF9STzoKPiArCQly
-ZWFkX2xvY2tlZCA9IDA7Cj4gKwkJd3JpdGVfbG9ja2VkID0gMTsKPiArCQlicmVhazsKPiArCWNh
-c2UgT1BBTF9SVzoKPiArCQlyZWFkX2xvY2tlZCA9IDA7Cj4gKwkJd3JpdGVfbG9ja2VkID0gMDsK
-PiArCQlicmVhazsKPiArCWNhc2UgT1BBTF9MSzoKPiArCQkvKiB2YXJzIGFyZSBpbml0YWxpemVk
-IHRvIGxvY2tlZCAqLwo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoKPiArCQlwcl9lcnIoIlRyaWVk
-IHRvIHNldCBhbiBpbnZhbGlkIGxvY2tpbmcgc3RhdGUuLi4gcmV0dXJuaW5nIHRvIHVsYW5kXG4i
-KTsKPiArCQlyZXR1cm4gMTsKPiArCX0KPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5f
-dmEoY21kLCAiYzJzYyAzYyA0YyA0YyAzYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJ
-ICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9N
-RVRIT0RfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsKPiArCQkJCSAgICBP
-UEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywKPiArCQkJCSAgICBPUEFMX1NU
-QVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9S
-RUFETE9DS0VELAo+ICsJCQkJICAgIHJlYWRfbG9ja2VkLAo+ICsJCQkJICAgIE9QQUxfRU5ETkFN
-RSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9XUklURUxP
-Q0tFRCwKPiArCQkJCSAgICB3cml0ZV9sb2NrZWQsCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+
-ICsKPiArCQkJCSAgICBPUEFMX0VORExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+ICsJ
-CQkJICAgIE9QQUxfRU5ETElTVCk7Cj4gKwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlwcl9lcnIo
-IiVzOiBFcnJvciBidWlsZGluZyBTRVQgY29tbWFuZC5cbiIsIGRldi0+ZGlza19uYW1lKTsKPiAr
-CQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21k
-LCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICsKPiArc3RhdGljIGludCBsb2NrX3VubG9ja19s
-b2NraW5nX3JhbmdlX1NVTShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJdTggbHJfYnVm
-ZmVyW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWNvbnN0
-IHU4ICptZXRob2Q7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayAqbGt1bDsKPiArCWludCBy
-ZXQ7Cj4gKwl1OCByZWFkX2xvY2tlZCA9IDEsIHdyaXRlX2xvY2tlZCA9IDE7Cj4gKwo+ICsJY21k
-ID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQs
-IGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOwo+ICsJ
-bGt1bCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKPiArCWlmIChidWlsZF9sb2Nr
-aW5nX3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1ZmZlciksIGRldi0+bHIpIDwgMCkgewo+
-ICsJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIsIGRldi0+ZGlza19u
-YW1lKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlzd2l0Y2ggKGxrdWwtPmxf
-c3RhdGUpIHsKPiArCWNhc2UgT1BBTF9STzoKPiArCQlyZWFkX2xvY2tlZCA9IDA7Cj4gKwkJd3Jp
-dGVfbG9ja2VkID0gMTsKPiArCQlicmVhazsKPiArCWNhc2UgT1BBTF9SVzoKPiArCQlyZWFkX2xv
-Y2tlZCA9IDA7Cj4gKwkJd3JpdGVfbG9ja2VkID0gMDsKPiArCQlicmVhazsKPiArCWNhc2UgT1BB
-TF9MSzoKPiArCQkvKiB2YXJzIGFyZSBpbml0YWxpemVkIHRvIGxvY2tlZCAqLwo+ICsJCWJyZWFr
-Owo+ICsJZGVmYXVsdDoKPiArCQlwcl9lcnIoIlRyaWVkIHRvIHNldCBhbiBpbnZhbGlkIGxvY2tp
-bmcgc3RhdGUuXG4iKTsKPiArCQlyZXR1cm4gMTsKPiArCX0KPiArCj4gKwlyZXQgPSB0ZXN0X2Fu
-ZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzYyAzYyA0YyA0YyA0YyA0YyAzYyIsCj4gKwkJCQkgICAg
-T1BBTF9DQUxMLAo+ICsJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJ
-ICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNU
-LAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywK
-PiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUs
-Cj4gKwkJCQkgICAgT1BBTF9SRUFETE9DS0VOQUJMRUQsCj4gKwkJCQkgICAgT1BBTF9UUlVFLAo+
-ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4g
-KwkJCQkgICAgT1BBTF9XUklURUxPQ0tFTkFCTEVELAo+ICsJCQkJICAgIE9QQUxfVFJVRSwKPiAr
-CQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJ
-CQkJICAgIE9QQUxfUkVBRExPQ0tFRCwKPiArCQkJCSAgICByZWFkX2xvY2tlZCwKPiArCQkJCSAg
-ICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAg
-IE9QQUxfV1JJVEVMT0NLRUQsCj4gKwkJCQkgICAgd3JpdGVfbG9ja2VkLAo+ICsJCQkJICAgIE9Q
-QUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsJCQkJICAgIE9QQUxf
-RU5ETkFNRSwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsJaWYgKHJldCA8IDApIHsKPiAr
-CQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBTRVQgY29tbWFuZC5cbiIsIGRldi0+ZGlza19u
-YW1lKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5k
-KGRldiwgY21kLCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtpbnQgYWN0aXZhdGVfbHNwKHN0
-cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwl1OCB1c2VyX2xyW09QQUxfVUlEX0xFTkdUSF07
-Cj4gKwljb25zdCB1OCAqbWV0aG9kLCAqdWlkOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4g
-KwlpbnQgcmV0Owo+ICsJc2l6ZV90IHVpbnRfMyA9IDB4ODM7Cj4gKwo+ICsJY21kID0gJmRldi0+
-Y21kOwo+ICsKPiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwlzZXRfY29tSUQoY21kLCBkZXYt
-PmNvbUlEKTsKPiArCj4gKwl1aWQgPSBPUEFMVUlEW09QQUxfTE9DS0lOR1NQX1VJRF07Cj4gKwlt
-ZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfQUNUSVZBVEVdOwo+ICsKPiArCXJldCA9IHRlc3RfYW5k
-X2FkZF90b2tlbl92YShjbWQsICJjMnMiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAg
-ICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xF
-TkdUSCk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5n
-IEFjdGl2YXRlIExvY2tpbmdTUCBjb21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25h
-bWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwkvKiBBY3RpdmF0aW5nIGFzIFNVTSAqLwo+
-ICsJaWYgKGRldi0+bHIgPiAwKSB7Cj4gKwkJcmV0ID0gYnVpbGRfbG9ja2luZ19yYW5nZSh1c2Vy
-X2xyLCBzaXplb2YodXNlcl9sciksIGRldi0+bHIpOwo+ICsJCWlmIChyZXQgPCAwKSB7Cj4gKwkJ
-CXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgdXNlclxuIiwKPiArCQkJICAgICAgIGRl
-di0+ZGlza19uYW1lKTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwkJdGVzdF9hbmRfYWRk
-X3Rva2VuX3ZhKGNtZCwgIjJjIDRjIGNzYyAyYyIsCj4gKwkJCQkgICAgICBPUEFMX1NUQVJUTElT
-VCwKPiArCQkJCSAgICAgIE9QQUxfU1RBUlROQU1FLAo+ICsKPiArCQkJCSAgICAgIHVpbnRfMywK
-PiArCQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzA2LAo+ICsJCQkJICAgICAgT1BBTF9USU5ZX1VJ
-TlRfMDAsCj4gKwkJCQkgICAgICBPUEFMX1RJTllfVUlOVF8wMCwKPiArCj4gKwkJCQkgICAgICBP
-UEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICAgIHVzZXJfbHIsIE9QQUxfVUlEX0xFTkdUSCwKPiAr
-CQkJCSAgICAgIE9QQUxfRU5ETElTVCwKPiArCj4gKwkJCQkgICAgICBPUEFMX0VORE5BTUUsCj4g
-KwkJCQkgICAgICBPUEFMX0VORExJU1QpOwo+ICsJfSBlbHNlIC8qIEFjdGlhdmUgTm9ybWFsIE1v
-ZGUgKi8KPiArCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiMmMiLAo+ICsJCQkJ
-CSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlp
-ZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEFjdGl2YXRlIExv
-Y2tpbmdTUCBjb21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJl
-dHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21k
-LCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBnZXRfbHNwX2xpZmVjeWNs
-ZV9jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKPiArewo+ICsKPiArCXN0cnVjdCBvcGFsX2Rl
-diAqZGV2ID0gZGF0YTsKPiArCXU4IGxjX3N0YXR1czsKPiArCj4gKwlpZiAoZXJyb3IpCj4gKwkJ
-Z290byBlcnJfcmV0dXJuOwo+ICsKPiArCWVycm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhk
-ZXYpOwo+ICsJaWYgKGVycm9yKQo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCj4gKwlsY19zdGF0
-dXMgPSByZXNwb25zZV9nZXRfdTY0KCZkZXYtPnBhcnNlZCwgNCk7Cj4gKwkvKiAweDA4IGlzIE1h
-bnVmYWN1cmVkIEluYWN0aXZlICovCj4gKwkvKiAweDA5IGlzIE1hbnVmYWN0dXJlZCAqLwo+ICsJ
-aWYgKGxjX3N0YXR1cyAhPSAweDA4KSB7Cj4gKwkJcHJfZXJyKCIlczogQ291bGRuJ3QgZGV0ZXJt
-aW5lIHRoZSBzdGF0dXMgb2YgdGhlIExpZmN5Y2xlIHN0YXRlXG4iLAo+ICsJCSAgICAgICBkZXYt
-PmRpc2tfbmFtZSk7Cj4gKwkJZXJyb3IgPSAtRU5PREVWOwo+ICsJfQo+ICsKPiArZXJyX3JldHVy
-bjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYpOwo+
-ICt9Cj4gKwo+ICsvKiBEZXRlcm1pbmUgaWYgd2UncmUgaW4gdGhlIE1hbnVmYWN0dXJlZCBJbmFj
-dGl2ZSBvciBBY3RpdmUgc3RhdGUgKi8KPiAraW50IGdldF9sc3BfbGlmZWN5Y2xlKHN0cnVjdCBv
-cGFsX2RldiAqZGV2KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWNvbnN0IHU4
-ICptZXRob2QsICp1aWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsKPiAr
-Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7
-Cj4gKwo+ICsJdWlkID0gT1BBTFVJRFtPUEFMX0xPQ0tJTkdTUF9VSURdOwo+ICsJbWV0aG9kID0g
-T1BBTE1FVEhPRFtPUEFMX0dFVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3Zh
-KGNtZCwgImMycyAyYyA0YyA0YyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAg
-IHVpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVO
-R1RILAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJU
-TElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5Z
-X1VJTlRfMDMsIC8qIFN0YXJ0IENvbHVtbiAqLwo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzA2
-LCAvKiBMaWZjeWNsZSBDb2x1bW4gKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJ
-CQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzA0LCAvKiBF
-bmQgQ29sdW1uICovCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIExpZmVjeWNsZSBD
-b2x1bW4gKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfRU5E
-TElTVCwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4g
-KwkJcHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgR0VUIExpZmVjeWNsZSBTdGF0dXMgY29tbWFu
-ZFxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9
-Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZXRfbHNwX2xpZmVj
-eWNsZV9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgZ2V0X21zaWRfY3Bpbl9waW5fY29u
-dChpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCj4gK3sKPiArCWNvbnN0IGNoYXIgKm1zaWRfcGluOwo+
-ICsJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwo+ICsJc2l6ZV90IHN0cmxlbjsKPiArCj4g
-KwlpZiAoZXJyb3IpCj4gKwkJZ290byBlcnJfcmV0dXJuOwo+ICsKPiArCWVycm9yID0gcGFyc2Vf
-YW5kX2NoZWNrX3N0YXR1cyhkZXYpOwo+ICsJaWYgKGVycm9yKQo+ICsJCWdvdG8gZXJyX3JldHVy
-bjsKPiArCj4gKwlzdHJsZW4gPSByZXNwb25zZV9nZXRfc3RyaW5nKCZkZXYtPnBhcnNlZCwgNCwg
-Jm1zaWRfcGluKTsKPiArCWlmICghbXNpZF9waW4pIHsKPiArCQlwcl9lcnIoIiVzOiBDb3VsZG4n
-dCBleHRyYWN0IFBJTiBmcm9tIHJlc3BvbnNlXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJZXJyb3IgPSAx
-Owo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCX0KPiArCj4gKwlkZXYtPnByZXZfZGF0YSA9IGtt
-ZW1kdXAobXNpZF9waW4sIHN0cmxlbiwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWRldi0+cHJldl9k
-YXRhKQo+ICsJCWVycm9yID0gLUVOT01FTTsKPiArCj4gKwlkZXYtPnByZXZfZF9sZW4gPSBzdHJs
-ZW47Cj4gKwo+ICsgZXJyX3JldHVybjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5v
-cGVyX2NiKGVycm9yLCBkZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGdldF9tc2lkX2NwaW5f
-cGluKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9kLCAqc211
-aWQ7Cj4gKwlpbnQgcmV0Owo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwo+ICsJY21kID0g
-JmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQsIGRl
-di0+Y29tSUQpOwo+ICsKPiArCXNtdWlkID0gT1BBTFVJRFtPUEFMX0NfUElOX01TSURdOwo+ICsJ
-bWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0dFVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk
-X3Rva2VuX3ZhKGNtZCwgImMgMnMgMTJjIiwKPiArCQkJCSAgICBPUEFMX0NBTEwsCj4gKwo+ICsJ
-CQkJICAgIHNtdWlkLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkgICAgbWV0aG9kLCBPUEFMX01F
-VEhPRF9MRU5HVEgsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsJCQkJICAgIE9Q
-QUxfU1RBUlRMSVNULAo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxf
-VElOWV9VSU5UXzAzLCAvKiBTYXJ0IENvbHVtbiAqLwo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5U
-XzAzLCAvKiBQSU4gKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9T
-VEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDQsIC8qIEVuZCBDb2x1bW4gKi8K
-PiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElOICovCj4gKwkJCQkgICAgT1BBTF9F
-TkROQU1FLAo+ICsJCQkJICAgIE9QQUxfRU5ETElTVCwKPiArCQkJCSAgICBPUEFMX0VORExJU1Qp
-Owo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcg
-R2V0IE1TSUQgQ1BJTiBQSU4gY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1l
-KTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2Vu
-ZChkZXYsIGNtZCwgZ2V0X21zaWRfY3Bpbl9waW5fY29udCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2
-b2lkIHVubG9ja19zdXNwZW5kX2ZpbmFsKGludCBlcnJvciwgdm9pZCAqZGF0YSkKPiArewo+ICsJ
-c3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwo+ICsKPiArCWRldi0+cmVzdW1lX2Zyb21fc3Vz
-cGVuZCA9IGZhbHNlOwo+ICsJZGV2LT5yZXN1bWVfZGF0YSA9IE5VTEw7Cj4gKwlkZXYtPmZ1bmNf
-ZGF0YSA9IE5VTEw7Cj4gKwlkZXYtPmJkZXYgPSBOVUxMOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50
-IGJ1aWxkX2VuZF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCXN0
-cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsKPiArCWNsZWFyX29w
-YWxfY21kKGNtZCk7Cj4gKwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7Cj4gKwlyZXR1
-cm4gdGVzdF9hbmRfYWRkX3Rva2VuX3U4KGNtZCwgT1BBTF9FTkRPRlNFU1NJT04pOwo+ICt9Cj4g
-Kwo+ICtzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4g
-K3sKPiArCWlmIChidWlsZF9lbmRfb3BhbF9zZXNzaW9uKGRldikgPCAwKQo+ICsJCXJldHVybiAt
-MTsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsICZkZXYtPmNtZCwgZW5kX3Nlc3Np
-b25fY29udCk7Cj4gK30KQW55IHJlYXNvbiB3ZSBjYW50OgoKaW50IHJldCA9IGJ1aWxkXy4uLgpp
-ZiAocmV0IDwgMCkKCXJldHVybiByZXQ7CgoKPiArCj4gK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9kZXYg
-KmZpbmRfb3BhbF9kZXYoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgdTggbHIpCj4gK3sKPiAr
-CXN0cnVjdCBvcGFsX2RldiAqaXRlciwgKm9wYWxfZGV2ID0gTlVMTDsKPiArCj4gKwlsaXN0X2Zv
-cl9lYWNoX2VudHJ5KGl0ZXIsICZvcGFsX2xpc3QsIG5vZGUpIHsKPiArCQlpZiAoc3RybmNtcChp
-dGVyLT5kaXNrX25hbWUsIGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZSwKPiArCQkJICAgIERJU0tf
-TkFNRV9MRU4pKQo+ICsJCQljb250aW51ZTsKPiArCQlpZiAoaXRlci0+bHIgPT0gbHIpIHsKPiAr
-CQkJb3BhbF9kZXYgPSBpdGVyOwo+ICsJCQlicmVhazsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJcmV0
-dXJuIG9wYWxfZGV2Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHVwZGF0ZV9vcGFsX2RldihzdHJ1
-Y3Qgb3BhbF9kZXYgKm9sZF9kZXYsIHN0cnVjdCBvcGFsX2RldiAqbmV3X2RldikKPiArewo+ICsJ
-aWYgKCFhdG9taWNfYWRkX3VubGVzcygmb2xkX2Rldi0+aW5fdXNlLCAxLCAxKSkgewo+ICsJCXBy
-X2VycigiJXM6IGRldiB3YXMgaW4gdXNlXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJcmV0dXJuIC1FQlVT
-WTsKPiArCX0KPiArCj4gKwlvbGRfZGV2LT5rZXlfbmFtZV9sZW4gPSBuZXdfZGV2LT5rZXlfbmFt
-ZV9sZW47Cj4gKwlpZiAoIW1lbWNweShvbGRfZGV2LT5rZXlfbmFtZSwgbmV3X2Rldi0+a2V5X25h
-bWUsIG9sZF9kZXYtPmtleV9uYW1lX2xlbikpIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJvciB1cGRh
-dGluZyBkZXZpY2U6XG4iLCBvbGRfZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiAtRUZBVUxU
-Owo+ICsJfQo+ICsKPiArCWlmICghc3RybmNweShvbGRfZGV2LT5kaXNrX25hbWUsIG5ld19kZXYt
-PmRpc2tfbmFtZSwgRElTS19OQU1FX0xFTikpIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJvciByZWdp
-c3RlcmluZyBkZXZpY2U6IGNvcHlpbmcgZGlzayBuYW1lXG4iLAo+ICsJCSAgICAgICBvbGRfZGV2
-LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsJfQo+ICsKPiArCW9sZF9kZXYt
-PmNvbUlEID0gbmV3X2Rldi0+Y29tSUQ7Cj4gKwlvbGRfZGV2LT5zdGFydCA9IG5ld19kZXYtPnN0
-YXJ0Owo+ICsJb2xkX2Rldi0+bGVuZ3RoID0gbmV3X2Rldi0+bGVuZ3RoOwo+ICsJb2xkX2Rldi0+
-YWxpZ24gPSBuZXdfZGV2LT5hbGlnbjsKPiArCW9sZF9kZXYtPmxvd2VzdF9sYmEgPSBuZXdfZGV2
-LT5sb3dlc3RfbGJhOwo+ICsJb2xkX2Rldi0+YmRldiA9IE5VTEw7Cj4gKwlvbGRfZGV2LT5maW5h
-bF9jYiA9IG5ld19kZXYtPmZpbmFsX2NiOwo+ICsJb2xkX2Rldi0+ZmluYWxfY2JfZGF0YSA9IG5l
-d19kZXYtPmZpbmFsX2NiX2RhdGE7Cj4gKwlvbGRfZGV2LT5vcGVyX2NiID0gbmV3X2Rldi0+b3Bl
-cl9jYjsKPiArCW9sZF9kZXYtPnN0YXRlID0gbmV3X2Rldi0+c3RhdGU7Cj4gKwlvbGRfZGV2LT5m
-dW5jcyA9IG5ld19kZXYtPmZ1bmNzOwo+ICsKPiArCWtmcmVlKG9sZF9kZXYtPmNvbXBsZXRpb24p
-Owo+ICsJY2xlYW5fZnVuY3Rpb25fZGF0YShvbGRfZGV2KTsKPiArCj4gKwlvbGRfZGV2LT5jb21w
-bGV0aW9uID0gbmV3X2Rldi0+Y29tcGxldGlvbjsKPiArCj4gKwkvKgo+ICsJICogV29uJ3QgYmUg
-YWJsZSB0byBhdXRvIHVubG9jayB0aGlzIGxvY2tpbmcgcmFuZ2UgYmFzZWQgb24gYmxvY2sKPiAr
-CSAqIHJlcXVlc3Rlcy4KPiArCSAqLwo+ICsJaWYgKG9sZF9kZXYtPmxlbmd0aCA9PSAwKQo+ICsJ
-CXByX3dhcm4oIiVzOiBNaXNzaW5nIGJsb2NrIGluZm9ybWF0aW9uIGZvciBsb2NraW5nIHJhbmdl
-ICVkXG4iLAo+ICsJCQlvbGRfZGV2LT5kaXNrX25hbWUsIG9sZF9kZXYtPmxyKTsKPiArCj4gKwly
-ZXR1cm4gMDsKPiArfQo+ICsKPiAraW50IG9wYWxfcmVnaXN0ZXJfY29udChzdHJ1Y3Qgb3BhbF9k
-ZXYgKm5ld19kZXYpCj4gK3sKPiArCXN0cnVjdCBvcGFsX2RldiAqb2xkX2RldjsKPiArCXVuc2ln
-bmVkIGxvbmcgZmxhZ3M7Cj4gKwlpbnQgZXJyb3IgPSAwOwo+ICsKPiArCXNwaW5fbG9ja19pcnFz
-YXZlKCZsaXN0X3NwaW5sb2NrLCBmbGFncyk7Cj4gKwo+ICsJb2xkX2RldiA9IGZpbmRfb3BhbF9k
-ZXYobmV3X2Rldi0+YmRldiwgbmV3X2Rldi0+bHIpOwo+ICsJaWYgKCFvbGRfZGV2KSB7Cj4gKwkJ
-bGlzdF9hZGRfdGFpbCgmbmV3X2Rldi0+bm9kZSwgJm9wYWxfbGlzdCk7Cj4gKwkJb2xkX2RldiA9
-IG5ld19kZXY7Cj4gKwl9IGVsc2Ugewo+ICsJCWlmIChvbGRfZGV2ID09IG5ld19kZXYpCj4gKwkJ
-CWVycm9yID0gMDsKPiArCQllbHNlIHsKPiArCQkJZXJyb3IgPSB1cGRhdGVfb3BhbF9kZXYob2xk
-X2RldiwgbmV3X2Rldik7Cj4gKwkJCWNsZWFuX29wYWxfa2V5KG5ld19kZXYpOwo+ICsJCQlrZnJl
-ZShuZXdfZGV2KTsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJaWYgKGVycm9yKQo+ICsJCWxpc3RfZGVs
-KCZvbGRfZGV2LT5ub2RlKTsKPiArCj4gKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZsaXN0X3Nw
-aW5sb2NrLCBmbGFncyk7Cj4gKwo+ICsJaWYgKCFlcnJvcikKPiArCQlwcl9pbmZvKCIlczogUmVn
-aXN0ZXJlZCBrZXkgZm9yIGxvY2tpbmcgcmFuZ2U6ICVkXG4iLAo+ICsJCQlvbGRfZGV2LT5kaXNr
-X25hbWUsIG9sZF9kZXYtPmxyKTsKPiArCj4gKwlpZiAob2xkX2Rldi0+b3Blcl9jYikKPiArCQlv
-bGRfZGV2LT5vcGVyX2NiKGVycm9yLCBvbGRfZGV2KTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+
-ICsKPiArc3RhdGljIHZvaWQgbmV4dChpbnQgZXJyb3IsIHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+
-ICt7Cj4gKwlvcGFsX3N0ZXAgZnVuYyA9IGRldi0+ZnVuY3NbZGV2LT5zdGF0ZV07Cj4gKwl2b2lk
-ICpjYl9kYXRhID0gZGV2LT5maW5hbF9jYl9kYXRhOwo+ICsJc2VjX2NiICpjYiA9IGRldi0+Zmlu
-YWxfY2I7Cj4gKwlib29sIGRvbmUgPSBmYWxzZTsKPiArCj4gKwo+ICsJaWYgKGVycm9yIHx8ICFm
-dW5jKSB7Cj4gKwkJZG9uZSA9IHRydWU7Cj4gKwkJZ290byBuZXh0X2V4aXQ7Cj4gKwl9Cj4gKwlk
-ZXYtPnN0YXRlKys7Cj4gKwlkZXYtPm9wZXJfY2IgPSBuZXh0Owo+ICsJZXJyb3IgPSBmdW5jKGRl
-dik7Cj4gKyBuZXh0X2V4aXQ6Cj4gKwlpZiAoZXJyb3IpIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJv
-ciBvbiBzdGVwIGZ1bmN0aW9uOiAlZCB3aXRoIGVycm9yICVkOiAlc1xuIiwKPiArCQkgICAgICAg
-ZGV2LT5kaXNrX25hbWUsIGRldi0+c3RhdGUsIGVycm9yLAo+ICsJCSAgICAgICBvcGFsX2Vycm9y
-X3RvX2h1bWFuKGVycm9yKSk7Cj4gKwo+ICsKPiArCQlhdG9taWNfZGVjKCZkZXYtPmluX3VzZSk7
-Cj4gKwkJaWYgKGRldi0+ZXJyb3JfY2IpIHsKPiArCQkJZGV2LT5lcnJvcl9jYihkZXYtPmVycm9y
-X2NiX2RhdGEpOwo+ICsJCQlyZXR1cm47Cj4gKwkJfQo+ICsJCWlmIChjYikKPiArCQkJY2IoZXJy
-b3IsIGNiX2RhdGEpOwo+ICsKPiArCQlkZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVz
-ID0gZXJyb3I7Cj4gKwkJY29tcGxldGUoJmRldi0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24p
-Owo+ICsJfSBlbHNlIGlmICghZXJyb3IgJiYgZG9uZSkgewo+ICsJCWF0b21pY19kZWMoJmRldi0+
-aW5fdXNlKTsKPiArCQlpZiAoY2IpCj4gKwkJCWNiKGVycm9yLCBjYl9kYXRhKTsKPiArCQlkZXYt
-PmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVzID0gZXJyb3I7Cj4gKwkJY29tcGxldGUoJmRl
-di0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24pOwo+ICsJfQo+ICt9Cj4gKwo+ICtjb25zdCBv
-cGFsX3N0ZXAgZXJyb3JfZW5kX3Nlc3Npb25bXSA9IHsKPiArCWVuZF9vcGFsX3Nlc3Npb24sCj4g
-KwlOVUxMLAo+ICt9Owo+ICtzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb25fZXJyb3Ioc3RydWN0
-IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCj4gKwlkZXYtPmZ1bmNzID0gZXJyb3JfZW5kX3Nlc3Np
-b247Cj4gKwlkZXYtPnN0YXRlID0gMDsKPiArCWRldi0+ZXJyb3JfY2IgPSBOVUxMOwo+ICsJbmV4
-dCgwLCBkZXYpOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9k
-ZXYgKmFsbG9jX29wYWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHU4IGxyKQo+ICt7
-Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKm9wYWxfZGV2Owo+ICsJc3RydWN0IHJlcXVlc3RfcXVldWUg
-KnE7Cj4gKwl1bnNpZ25lZCBsb25nIGRtYV9hbGlnbjsKPiArCWNvbnN0IGNoYXIgKmRpc2tfbmFt
-ZTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJaW50IHJldDsKPiArCj4gKwlvcGFsX2Rl
-diA9IGt6YWxsb2Moc2l6ZW9mKCpvcGFsX2RldiksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCFvcGFs
-X2RldikKPiArCQlyZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKPiArCj4gKwlvcGFsX2Rldi0+YmRl
-diA9IGJkZXY7Cj4gKwlvcGFsX2Rldi0+bHIgPSBscjsKPiArCWNtZCA9ICZvcGFsX2Rldi0+Y21k
-Owo+ICsJY21kLT5jbWQgPSBjbWQtPmNtZF9idWY7Cj4gKwljbWQtPnJlc3AgPSBjbWQtPnJlc3Bf
-YnVmOwo+ICsKPiArCWRpc2tfbmFtZSA9IGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZTsKPiArCWlm
-ICghc3RybmNweShvcGFsX2Rldi0+ZGlza19uYW1lLCBkaXNrX25hbWUsIERJU0tfTkFNRV9MRU4p
-KSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgcmVnaXN0ZXJpbmcgZGV2aWNlOiBjb3B5aW5nIGRp
-c2sgbmFtZVxuIiwKPiArCQkgICAgICAgZGlza19uYW1lKTsKPiArCQlyZXQgPSAtRUZBVUxUOwo+
-ICsJCWdvdG8gZXJyX2ZyZWVfZGV2Owo+ICsJfQo+ICsKPiArCXEgPSBiZGV2LT5iZF9xdWV1ZTsK
-PiArCWRtYV9hbGlnbiA9IChxdWV1ZV9kbWFfYWxpZ25tZW50KHEpIHwgcS0+ZG1hX3BhZF9tYXNr
-KSArIDE7Cj4gKwljbWQtPmNtZCA9ICh1OCAqKXJvdW5kX3VwKCh1aW50cHRyX3QpY21kLT5jbWQs
-IGRtYV9hbGlnbik7Cj4gKwljbWQtPnJlc3AgPSAodTggKilyb3VuZF91cCgodWludHB0cl90KWNt
-ZC0+cmVzcCwgZG1hX2FsaWduKTsKPiArCj4gKwlJTklUX0xJU1RfSEVBRCgmb3BhbF9kZXYtPm5v
-ZGUpOwo+ICsJYXRvbWljX3NldCgmb3BhbF9kZXYtPmluX3VzZSwgMSk7Cj4gKwo+ICsJb3BhbF9k
-ZXYtPmNvbXBsZXRpb24gPSBremFsbG9jKHNpemVvZigqb3BhbF9kZXYtPmNvbXBsZXRpb24pLAo+
-ICsJCQkJICAgICAgIEdGUF9LRVJORUwpOwo+ICsKPiArCWlmICghb3BhbF9kZXYtPmNvbXBsZXRp
-b24pCj4gKwkJZ290byBlcnJfZnJlZV9kZXY7Cj4gKwo+ICsJaW5pdF9jb21wbGV0aW9uKCZvcGFs
-X2Rldi0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24pOwo+ICsJb3BhbF9kZXYtPmNvbXBsZXRp
-b24tPmNvbXBsZXRpb25fc3RhdHVzID0gMDsKPiArCW9wYWxfZGV2LT5zdGF0ZSA9IDA7Cj4gKwo+
-ICsJcmV0dXJuIG9wYWxfZGV2Owo+ICsKPiArZXJyX2ZyZWVfZGV2Ogo+ICsJa2ZyZWUob3BhbF9k
-ZXYpOwo+ICsJcmV0dXJuIEVSUl9QVFIocmV0KTsKPiArfQo+ICsKPiAraW50IG9wYWxfcmVnaXN0
-ZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IG9wYWxfa2V5ICprZXlfY21kLAo+
-ICsJCSAgY29uc3Qgb3BhbF9zdGVwICpmdW5jcykKPiArewo+ICsJc3RydWN0IG9wYWxfZGV2ICpu
-ZXdfZGV2ID0gTlVMTDsKPiArCXU4IGtleV9sZW4gPSBrZXlfY21kLT5rZXlfbGVuOwo+ICsJdTgg
-bHIgPSBrZXlfY21kLT5scjsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247
-Cj4gKwlpbnQgcmV0Owo+ICsKPiArCW5ld19kZXYgPSBhbGxvY19vcGFsX2RldihiZGV2LCBscik7
-Cj4gKwlpZiAoSVNfRVJSKG5ld19kZXYpKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgcmVnaXN0
-ZXJpbmcgZGV2aWNlOiBhbGxvY2F0aW9uXG4iLAo+ICsJCSAgICAgICBiZGV2LT5iZF9kaXNrLT5k
-aXNrX25hbWUpOwo+ICsJCXJldHVybiBQVFJfRVJSKG5ld19kZXYpOwo+ICsJfQo+ICsKPiArCWlm
-ICghbWVtY3B5KG5ld19kZXYtPmtleV9uYW1lLCBrZXlfY21kLT5rZXksIGtleV9sZW4pKSB7Cj4g
-KwkJcHJfZXJyKCIlczogRXJyb3IgcmVnaXN0ZXJpbmcga2V5OiBjb3VsZG4ndCBjb3B5IGtleVxu
-IiwKPiArCQkgICAgICAgbmV3X2Rldi0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gLUVGQVVMVDsK
-PiArCX0KPiArCj4gKwluZXdfZGV2LT5rZXlfbmFtZV9sZW4gPSBrZXlfbGVuOwo+ICsJbmV3X2Rl
-di0+a2V5X3R5cGUgPSBrZXlfY21kLT5rZXlfdHlwZTsKPiArCXJldCA9IGdldF9vcGFsX2tleShu
-ZXdfZGV2KTsKPiArCWlmIChyZXQpIHsKPiArCQlwcl9lcnIoIiVzOiBDb3VsZG4ndCBnZXQga2V5
-OiAlZFxuIiwgbmV3X2Rldi0+ZGlza19uYW1lLCByZXQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9
-Cj4gKwo+ICsJbmV3X2Rldi0+ZnVuY3MgPSBmdW5jczsKPiArCj4gKwluZXdfZGV2LT5zdGF0ZSA9
-IDA7Cj4gKwljb21wbGV0aW9uID0gbmV3X2Rldi0+Y29tcGxldGlvbjsKPiArCW5leHQoMCwgbmV3
-X2Rldik7Cj4gKwo+ICsJcmV0dXJuIHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24p
-Owo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IG9wYWxfZGV2ICpnZXRfcmVnaXN0ZXJlZF9vcGFs
-X2RldihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LAo+ICsJCQkJCQl1OCBscikKPiArewo+ICsJ
-Y29uc3QgY2hhciAqZGlza25hbWUgPSBiZGV2LT5iZF9kaXNrLT5kaXNrX25hbWU7Cj4gKwlzdHJ1
-Y3Qgb3BhbF9kZXYgKml0ZXIsICpkZXYgPSBOVUxMOwo+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsK
-PiArCWJvb2wgaW5fdXNlID0gZmFsc2U7Cj4gKwo+ICsJc3Bpbl9sb2NrX2lycXNhdmUoJmxpc3Rf
-c3BpbmxvY2ssIGZsYWdzKTsKPiArCWxpc3RfZm9yX2VhY2hfZW50cnkoaXRlciwgJm9wYWxfbGlz
-dCwgbm9kZSkgewo+ICsJCWlmIChzdHJuY21wKGl0ZXItPmRpc2tfbmFtZSwgZGlza25hbWUsIERJ
-U0tfTkFNRV9MRU4pKQo+ICsJCQljb250aW51ZTsKPiArCQlpZiAoaXRlci0+bHIgPT0gbHIpIHsK
-PiArCQkJZGV2ID0gaXRlcjsKPiArCQkJaWYgKCFhdG9taWNfYWRkX3VubGVzcygmaXRlci0+aW5f
-dXNlLCAxLCAxKSkgewo+ICsJCQkJZGV2ID0gTlVMTDsKPiArCQkJCWluX3VzZSA9IHRydWU7Cj4g
-KwkJCX0KPiArCQkJYnJlYWs7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCXNwaW5fdW5sb2NrX2lycXJl
-c3RvcmUoJmxpc3Rfc3BpbmxvY2ssIGZsYWdzKTsKPiArCj4gKwlpZiAoIWRldikKPiArCQlyZXR1
-cm4gTlVMTDsKPiArCj4gKwlkZXYtPmJkZXYgPSBiZGV2Owo+ICsJcmV0dXJuIGRldjsKPiArfQo+
-ICsKPiArLyogRnJlZSB1cCB0aGUgT3BhbCBkZXYgYW5kIGl0cyBrZXlzIGR1cmluZyB0d28gc2Nl
-bmFyaW9zOgo+ICsgKgo+ICsgKiAxKSBXaGVuIGEgY29tbWFuZCBpcyBjb21wbGV0ZSB0aGF0IG5v
-IGxvbmdlciByZXF1aXJlcwo+ICsgKiAgICB0aGUgb3BhbCBkZXYgdG8gYmUgYXJvdW5kLgo+ICsg
-KiAyKSBXaGVuIGEgY29tbWFuZCwgaW5jbHVkaW5nIE9wYWwgU2F2ZSBmYWlscyB3ZSBjbGVhbgo+
-ICsgKiAgICBhbmQgZnJlZSB0aGUgb3BhbCBkZXYuCj4gKyAqCj4gKyAqICAgIElmIHdlIGZpbmQg
-dGhlIG9wYWwgZGV2IHN0cnVjdHVyZSBpbiB0aGUgbGlzdCBvZgo+ICsgKiAgICBzYXZlZCBwYXNz
-d29yZHMgd2Ugd2lsbCAqbm90KiByZW1vdmUgaXQuCj4gKyAqLwo+ICtzdGF0aWMgdm9pZCByZW1v
-dmVfYW5kX2NsZWFuX29wYWxfZGV2KHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwlzdHJ1
-Y3Qgb3BhbF9kZXYgKml0ZXI7Cj4gKwlib29sIGZvdW5kID0gZmFsc2U7Cj4gKwo+ICsJc3Bpbl9s
-b2NrKCZsaXN0X3NwaW5sb2NrKTsKPiArCWxpc3RfZm9yX2VhY2hfZW50cnkoaXRlciwgJm9wYWxf
-bGlzdCwgbm9kZSkgewo+ICsJCWlmIChpdGVyID09IGRldikgewo+ICsJCQlmb3VuZCA9IHRydWU7
-Cj4gKwkJCWJyZWFrOwo+ICsJCX0KPiArCX0KPiArCj4gKwlzcGluX3VubG9jaygmbGlzdF9zcGlu
-bG9jayk7Cj4gKwlpZiAoIWZvdW5kKSB7Cj4gKwkJY2xlYW5fb3BhbF9rZXkoZGV2KTsKPiArCQlj
-bGVhbl9mdW5jdGlvbl9kYXRhKGRldik7Cj4gKwkJa2ZyZWUoZGV2KTsKPiArCX0KPiArfQo+ICsK
-PiArc3RhdGljIHN0cnVjdCBvcGFsX2RldiAqZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihzdHJ1Y3Qg
-YmxvY2tfZGV2aWNlICpiZGV2LAo+ICsJCQkJCSAgICAgICB1OCBsciwgYm9vbCB1c2VfbmV3KQo+
-ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKPiArCj4gKwlpZiAodXNlX25ldykKPiArCQly
-ZXR1cm4gYWxsb2Nfb3BhbF9kZXYoYmRldiwgbHIpOwo+ICsKPiArCWRldiA9IGdldF9yZWdpc3Rl
-cmVkX29wYWxfZGV2KGJkZXYsIGxyKTsKPiArCWlmICghZGV2KSB7Cj4gKwkJZGV2ID0gYWxsb2Nf
-b3BhbF9kZXYoYmRldiwgbHIpOwo+ICsJCWlmICghZGV2KQo+ICsJCQlyZXR1cm4gTlVMTDsKTm8g
-bmVlZCBmb3IgdGhpcyBjaGVjayB3aGVuIHlvdSBhbHJlYWR5IHJldHVybiBkZXYKCgo+ICsJfQo+
-ICsJcmV0dXJuIGRldjsKPiArfQpJbnN0ZWFkLCBob3cgYWJvdXQ6CnN0YXRpYyBzdHJ1Y3Qgb3Bh
-bF9kZXYgKmdldF9vcl9jcmVhdGVfb3BhbF9kZXYoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwK
-CQkJCQkgICAgICAgdTggbHIsIGJvb2wgdXNlX25ldykKewoJc3RydWN0IG9wYWxfZGV2ICpkZXYg
-PSBOVUxMOwoKCWlmICghdXNlX25ldykKCQlkZXYgPSBnZXRfcmVnaXN0ZXJlZF9vcGFsX2Rldihi
-ZGV2LCBscik7CgoJaWYgKCFkZXYpCgkJZGV2ID0gYWxsb2Nfb3BhbF9kZXYoYmRldiwgbHIpOwoK
-CXJldHVybiBkZXY7Cn0KCgo+ICsKPiArc3RhdGljIHN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKnNl
-dHVwX29wYWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQkJICAgICAgc3Ry
-dWN0IG9wYWxfZGV2ICpkZXYsCj4gKwkJCQkJICAgICAgY29uc3Qgb3BhbF9zdGVwICpmdW5jcywK
-PiArCQkJCQkgICAgICBzdHJ1Y3Qgb3BhbF9rZXkgKmtleSkKPiArewo+ICsJaW50IHJldDsKPiAr
-Cj4gKwlkZXYtPmJkZXYgPSBiZGV2Owo+ICsJZGV2LT5zdGF0ZSA9IDA7Cj4gKwlkZXYtPmZ1bmNz
-ID0gZnVuY3M7Cj4gKwlkZXYtPlRTTiA9IDA7Cj4gKwlkZXYtPkhTTiA9IDA7Cj4gKwlkZXYtPmZp
-bmFsX2NiID0gTlVMTDsKPiArCWRldi0+ZmluYWxfY2JfZGF0YSA9IE5VTEw7Cj4gKwlkZXYtPmxy
-ID0ga2V5LT5scjsKPiArCWRldi0+ZXJyb3JfY2IgPSBlbmRfb3BhbF9zZXNzaW9uX2Vycm9yOwo+
-ICsJZGV2LT5lcnJvcl9jYl9kYXRhID0gZGV2Owo+ICsKPiArCWlmIChrZXkpIHsKPiArCQltZW1j
-cHkoZGV2LT5rZXlfbmFtZSwga2V5LT5rZXksIGtleS0+a2V5X2xlbik7Cj4gKwkJZGV2LT5rZXlf
-bmFtZV9sZW4gPSBrZXktPmtleV9sZW47Cj4gKwkJZGV2LT5rZXlfdHlwZSA9IGtleS0+a2V5X3R5
-cGU7Cj4gKwo+ICsJCXJldCA9IGdldF9vcGFsX2tleShkZXYpOwo+ICsJCWlmIChyZXQpIHsKPiAr
-CQkJa2ZyZWUoZGV2LT5jb21wbGV0aW9uKTsKPiArCQkJcHJfZXJyKCIlczogQ291bGRuJ3QgZ2V0
-IGtleTogJWRcbiIsCj4gKwkJCSAgICAgICBkZXYtPmRpc2tfbmFtZSwgcmV0KTsKPiArCQkJcmV0
-dXJuIEVSUl9QVFIocmV0KTsKPiArCQl9Cj4gKwl9Cj4gKwlkZXYtPmZ1bmNfZGF0YSA9IE5VTEw7
-Cj4gKwlkZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVzID0gMDsKPiArCj4gKwlyZXR1
-cm4gZGV2LT5jb21wbGV0aW9uOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGludGVybmFsX3NldHVw
-X2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCSAgICAgc3RydWN0IG9wYWxfdXNl
-cl9scl9zZXR1cCAqc2V0dXApCj4gK3sKPiArCXN0cnVjdCBvcGFsX2RldiAqZGV2Owo+ICsJc3Ry
-dWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCXZvaWQgKmRhdGFbM10gPSB7IE5V
-TEwgfTsKPiArCWNvbnN0IG9wYWxfc3RlcCBscl9mdW5jc1tdID0gewo+ICsJCW9wYWxfZGlzY292
-ZXJ5MCwKPiArCQlzdGFydF9hdXRoX29wYWxfc2Vzc2lvbiwKPiArCQlzZXR1cF9sb2NraW5nX3Jh
-bmdlLAo+ICsJCWdldF9hY3RpdmVfa2V5LAo+ICsJCWdlbl9rZXksCj4gKwkJZW5kX29wYWxfc2Vz
-c2lvbiwKPiArCQlOVUxMLAo+ICsJfTsKPiArCWludCByZXQ7Cj4gKwo+ICsJZGV2ID0gZ2V0X29y
-X2NyZWF0ZV9vcGFsX2RldihiZGV2LCBzZXR1cC0+a2V5LmxyLCB0cnVlKTsKPiArCWlmICghZGV2
-KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2Rl
-dihiZGV2LCBkZXYsIGxyX2Z1bmNzLCAmc2V0dXAtPmtleSk7Cj4gKwlpZiAoSVNfRVJSKGNvbXBs
-ZXRpb24pKSB7Cj4gKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKPiArCQlnb3RvIGVycm9y
-X3JldHVybjsKPiArCX0KPiArCj4gKwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7Cj4gKwlkZXYtPm51
-bV9mdW5jX2RhdGEgPSAzOwo+ICsJZGV2LT5mdW5jX2RhdGFbMV0gPSAmc2V0dXAtPndobzsKPiAr
-CWRldi0+ZnVuY19kYXRhWzJdID0gc2V0dXA7Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0
-ID0gd2FpdF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0
-dXJuOgo+ICsJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsK
-PiArfQo+ICsKPiAraW50IG9wYWxfcmV2ZXJ0KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0
-cnVjdCBvcGFsX2tleSAqa2V5KQo+ICt7Cj4gKwljb25zdCBvcGFsX3N0ZXAgcmV2ZXJ0X2Z1bmNz
-W10gPSB7Cj4gKwkJb3BhbF9kaXNjb3ZlcnkwLAo+ICsJCXN0YXJ0X1NJREFTUF9vcGFsX3Nlc3Np
-b24sCj4gKwkJcmV2ZXJ0X3RwZXIsIC8qIGNvbnRyb2xsZXIgd2lsbCB0ZXJtaW5hdGUgc2Vzc2lv
-biAqLwo+ICsJCU5VTEwsCj4gKwl9Owo+ICsKPiArCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYs
-IGtleSwgcmV2ZXJ0X2Z1bmNzKTsKPiArfQo+ICsKPiAraW50IGFjdGl2YXRlX3VzZXIoc3RydWN0
-IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IG9wYWxfYWN0aXZhdGVfdXNlciAqYWN0KQo+ICt7
-Cj4gKwljb25zdCBvcGFsX3N0ZXAgYWN0X2Z1bmNzW10gPSB7Cj4gKwkJb3BhbF9kaXNjb3Zlcnkw
-LAo+ICsJCXN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24sCj4gKwkJaW50ZXJuYWxfYWN0aXZh
-dGVfdXNlciwKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCU5VTEwKPiArCX07Cj4gKwlzdHJ1
-Y3Qgb3BhbF9kZXYgKmRldjsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247
-Cj4gKwl2b2lkICpkYXRhWzNdID0geyBOVUxMIH07Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWRldiA9
-IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgYWN0LT5rZXkubHIsIHRydWUpOwo+ICsJaWYg
-KCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJY29tcGxldGlvbiA9IHNldHVwX29w
-YWxfZGV2KGJkZXYsIGRldiwgYWN0X2Z1bmNzLCAmYWN0LT5rZXkpOwo+ICsJaWYgKElTX0VSUihj
-b21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBl
-cnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKPiArCWRl
-di0+ZnVuY19kYXRhID0gZGF0YTsKPiArCWRldi0+ZnVuY19kYXRhWzFdID0gYWN0Owo+ICsJZGV2
-LT5mdW5jX2RhdGFbMl0gPSBhY3Q7Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0ID0gd2Fp
-dF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0dXJuOgo+
-ICsJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+
-ICsKPiAraW50IG9wYWxfc2V0X3B3KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBv
-cGFsX25ld19wdyAqcHcpCj4gKwo+ICt7Cj4gKwljb25zdCBvcGFsX3N0ZXAgcHdfZnVuY3NbXSA9
-IHsKPiArCQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCj4g
-KwkJc2V0X25ld19wdywKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCU5VTEwKPiArCX07Cj4g
-KwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBs
-ZXRpb247Cj4gKwl2b2lkICpkYXRhWzNdID0geyBOVUxMIH07Cj4gKwlpbnQgcmV0Owo+ICsKPiAr
-CWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgcHctPmN1cnJlbnRfcGluLmxyLCB0
-cnVlKTsKPiArCWlmICghZGV2KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWNvbXBsZXRp
-b24gPSBzZXR1cF9vcGFsX2RldihiZGV2LCBkZXYsIHB3X2Z1bmNzLCAmcHctPmN1cnJlbnRfcGlu
-KTsKPiArCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsKPiArCQlyZXQgPSBQVFJfRVJSKGNvbXBs
-ZXRpb24pOwo+ICsJCWdvdG8gZXJyb3JfcmV0dXJuOwo+ICsJfQo+ICsKPiArCWRldi0+bnVtX2Z1
-bmNfZGF0YSA9IDM7Cj4gKwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7Cj4gKwlkZXYtPmZ1bmNfZGF0
-YVsxXSA9ICh2b2lkICopICZwdy0+d2hvOwo+ICsJZGV2LT5mdW5jX2RhdGFbMl0gPSAodm9pZCAq
-KSBwdzsKPiArCj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxl
-dGlvbihjb21wbGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVfYW5kX2Ns
-ZWFuX29wYWxfZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtpbnQgb3BhbF9h
-Y3RfbHNwX2ludChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgb3BhbF9rZXkgKmtl
-eSwKPiArCQkgICAgIGNvbnN0IG9wYWxfc3RlcCAqZnVuY3MpCj4gK3sKPiArCXN0cnVjdCBvcGFs
-X2RldiAqZGV2Owo+ICsJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCWlu
-dCByZXQ7Cj4gKwo+ICsJZGV2ID0gZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihiZGV2LCBrZXktPmxy
-LCB0cnVlKTsKPiArCWlmICghZGV2KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsJY29tcGxldGlv
-biA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwgZnVuY3MsIGtleSk7Cj4gKwlpZiAoSVNfRVJS
-KGNvbXBsZXRpb24pKSB7Cj4gKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKPiArCQlnb3Rv
-IGVycm9yX3JldHVybjsKPiArCX0KPiArCj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0
-X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4g
-KwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4g
-Kwo+ICsKPiArc3RhdGljIGludCBvcGFsX3NhdmVfaW50ZXJuYWwoc3RydWN0IGJsb2NrX2Rldmlj
-ZSAqYmRldiwKPiArCQkJICAgICAgc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrKQo+ICt7Cj4g
-Kwl2b2lkICpmdW5jX2RhdGFbM10gPSB7IE5VTEwgfTsKPiArCXN0cnVjdCBvcGFsX2RldiAqZGV2
-Owo+ICsJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCWNvbnN0IG9wYWxf
-c3RlcCBfYXV0aF9mdW5jc1tdID0gewo+ICsJCW9wYWxfZGlzY292ZXJ5MCwKPiArCQlzdGFydF9h
-dXRoX29wYWxfc2Vzc2lvbiwKPiArCQlxdWVyeV9sb2NraW5nX3JhbmdlLAo+ICsJCWVuZF9vcGFs
-X3Nlc3Npb24sCj4gKwkJb3BhbF9yZWdpc3Rlcl9jb250LAo+ICsJCU5VTEwKPiArCX07Cj4gKwlp
-bnQgcmV0Owo+ICsKPiArCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgbGstPmtl
-eS5sciwgZmFsc2UpOwo+ICsJaWYgKCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwljb21w
-bGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBfYXV0aF9mdW5jcywgJmxrLT5rZXkp
-Owo+ICsJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBUUl9FUlIoY29tcGxl
-dGlvbik7Cj4gKwkJZ290byBlcnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZGV2LT5udW1fZnVu
-Y19kYXRhID0gMzsKPiArCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOwo+ICsJZGV2LT5mdW5j
-X2RhdGFbMV0gPSAmbGstPmF1dGhvcml0eTsKPiArCWRldi0+bGt1bCA9ICpsazsKPiArCj4gKwlu
-ZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9u
-KTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRl
-dik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkZF91c2VyX2xyX2lu
-dGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQlzdHJ1Y3Qgb3BhbF9sb2Nr
-X3VubG9jayAqbGspCj4gK3sKPiArCXZvaWQgKmZ1bmNfZGF0YVszXSA9IHsgTlVMTCB9Owo+ICsJ
-c3RydWN0IG9wYWxfZGV2ICpkZXY7Cj4gKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpjb21wbGV0
-aW9uOwo+ICsJY29uc3Qgb3BhbF9zdGVwIGZ1bmNzW10gPSB7Cj4gKwkJb3BhbF9kaXNjb3Zlcnkw
-LAo+ICsJCXN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24sCj4gKwkJYWRkX3VzZXJfdG9fbHIs
-Cj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlOVUxMCj4gKwl9Owo+ICsJaW50IHJldDsKPiAr
-Cj4gKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJkZXYsIGxrLT5rZXkubHIsIHRydWUp
-Owo+ICsJaWYgKCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwljb21wbGV0aW9uID0gc2V0
-dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBmdW5jcywgJmxrLT5rZXkpOwo+ICsJaWYgKElTX0VSUihj
-b21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBl
-cnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKPiArCWRl
-di0+ZnVuY19kYXRhID0gZnVuY19kYXRhOwo+ICsJZGV2LT5mdW5jX2RhdGFbMl0gPSBsazsKPiAr
-Cj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21w
-bGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxf
-ZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGxvY2tfdW5s
-b2NrX2ludGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQlzdHJ1Y3Qgb3Bh
-bF9sb2NrX3VubG9jayAqbGspCj4gK3sKPiArCXZvaWQgKmZ1bmNfZGF0YVszXSA9IHsgTlVMTCB9
-Owo+ICsJc3RydWN0IG9wYWxfZGV2ICpkZXY7Cj4gKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpj
-b21wbGV0aW9uOwo+ICsKPiArCWNvbnN0IG9wYWxfc3RlcCB1bGtfZnVuY3NfU1VNW10gPSB7Cj4g
-KwkJb3BhbF9kaXNjb3ZlcnkwLAo+ICsJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAo+ICsJCWxv
-Y2tfdW5sb2NrX2xvY2tpbmdfcmFuZ2VfU1VNLAo+ICsJCWVuZF9vcGFsX3Nlc3Npb24sCj4gKwkJ
-TlVMTAo+ICsJfTsKPiArCWNvbnN0IG9wYWxfc3RlcCBfdW5sb2NrX2Z1bmNzW10gPSB7Cj4gKwkJ
-b3BhbF9kaXNjb3ZlcnkwLAo+ICsJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAo+ICsJCWxvY2tf
-dW5sb2NrX2xvY2tpbmdfcmFuZ2UsCj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlOVUxMCj4g
-Kwl9Owo+ICsJaW50IHJldDsKPiArCj4gKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJk
-ZXYsIGxrLT5rZXkubHIsIHRydWUpOwo+ICsJaWYgKCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07
-Cj4gKwo+ICsJaWYgKGxrLT5hdXRob3JpdHkuU1VNKQo+ICsJCWNvbXBsZXRpb24gPSBzZXR1cF9v
-cGFsX2RldihiZGV2LCBkZXYsIHVsa19mdW5jc19TVU0sICZsay0+a2V5KTsKPiArCWVsc2UKPiAr
-CQljb21wbGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBfdW5sb2NrX2Z1bmNzLCAm
-bGstPmtleSk7Cj4gKwo+ICsJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBU
-Ul9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBlcnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJ
-ZGV2LT5udW1fZnVuY19kYXRhID0gMzsKPiArCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOwo+
-ICsJZGV2LT5mdW5jX2RhdGFbMV0gPSAmbGstPmF1dGhvcml0eTsKPiArCWRldi0+ZnVuY19kYXRh
-WzJdID0gbGs7Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0ID0gd2FpdF9mb3JfY21kX2Nv
-bXBsZXRpb24oY29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0dXJuOgo+ICsJcmVtb3ZlX2Fu
-ZF9jbGVhbl9vcGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiAraW50IG9w
-YWxfZXJhc2VfbG9ja2luZ19yYW5nZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qg
-c2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKPiArCXN0cnVjdCBv
-cGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247Cj4gKwlzdHJ1Y3Qgb3BhbF9rZXkgazsKPiArCWlu
-dCByZXQ7Cj4gKwljb25zdCBvcGFsX3N0ZXAgZXJhc2VfZnVuY3NbXSA9IHsKPiArCQlvcGFsX2Rp
-c2NvdmVyeTAsCj4gKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxfc2Vzc2lvbiwKPiArCQllcmFzZV9s
-b2NraW5nX3JhbmdlLAo+ICsJCWVuZF9vcGFsX3Nlc3Npb24sCj4gKwkJTlVMTCwKPiArCX07Cj4g
-Kwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBz
-YXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlO
-VkFMOwo+ICsJfQo+ICsKPiArCWlmIChjb3B5X2Zyb21fdXNlcigmaywga2V5LT5vcGFsLCBzaXpl
-b2YoKmtleS0+b3BhbCkpKQo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsKPiArCWRldiA9IGdldF9v
-cl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgay5sciwgdHJ1ZSk7Cj4gKwlpZiAoIWRldikKPiArCQly
-ZXR1cm4gLUVOT01FTTsKPiArCj4gKwljb21wbGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwg
-ZGV2LCBlcmFzZV9mdW5jcywgJmspOwo+ICsJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgewo+ICsJ
-CXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBlcnJvcl9yZXR1cm47Cj4gKwl9
-Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0ID0gd2FpdF9mb3JfY21kX2NvbXBsZXRpb24o
-Y29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0dXJuOgo+ICsJcmVtb3ZlX2FuZF9jbGVhbl9v
-cGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICtFWFBPUlRfU1lNQk9MKG9wYWxf
-ZXJhc2VfbG9ja2luZ19yYW5nZSk7Cj4gKwo+ICtpbnQgb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFk
-b3dfbWJyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQkgICBzdHJ1Y3Qgc2VkX2tl
-eSAqa2V5KQo+ICt7Cj4gKwl2b2lkICpmdW5jX2RhdGFbNl0gPSB7IE5VTEwgfTsKPiArCXN0cnVj
-dCBvcGFsX21icl9kYXRhIG1icjsKPiArCXN0cnVjdCBvcGFsX2RldiAqZGV2Owo+ICsJc3RydWN0
-IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCWNvbnN0IG9wYWxfc3RlcCBtYnJfZnVu
-Y3NbXSA9IHsKPiArCQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxf
-c2Vzc2lvbiwKPiArCQlzZXRfbWJyX2RvbmUsCj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlz
-dGFydF9hZG1pbjFMU1Bfb3BhbF9zZXNzaW9uLAo+ICsJCXNldF9tYnJfZW5hYmxlX2Rpc2FibGUs
-Cj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlOVUxMLAo+ICsJfTsKPiArCWludCByZXQ7Cj4g
-Kwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBz
-YXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlO
-VkFMOwo+ICsJfQo+ICsKPiArCWlmIChjb3B5X2Zyb21fdXNlcigmbWJyLCBrZXktPm9wYWxfbWJy
-LCBzaXplb2YoKmtleS0+b3BhbF9tYnIpKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlp
-ZiAobWJyLmVuYWJsZV9kaXNhYmxlICE9IE9QQUxfTUJSX0VOQUJMRSAmJgo+ICsJICAgIG1ici5l
-bmFibGVfZGlzYWJsZSAhPSBPUEFMX01CUl9ESVNBQkxFKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+
-ICsKPiArCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgbWJyLmtleS5sciwgdHJ1
-ZSk7Cj4gKwlpZiAoIWRldikKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwljb21wbGV0aW9u
-ID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBtYnJfZnVuY3MsICZtYnIua2V5KTsKPiArCWlm
-IChJU19FUlIoY29tcGxldGlvbikpIHsKPiArCQlyZXQgPSBQVFJfRVJSKGNvbXBsZXRpb24pOwo+
-ICsJCWdvdG8gZXJyb3JfcmV0dXJuOwo+ICsJfQo+ICsKPiArCWRldi0+bnVtX2Z1bmNfZGF0YSA9
-IDY7Cj4gKwlkZXYtPmZ1bmNfZGF0YSA9IGZ1bmNfZGF0YTsKPiArCWRldi0+ZnVuY19kYXRhWzJd
-ID0gJm1ici5lbmFibGVfZGlzYWJsZTsKPiArCWRldi0+ZnVuY19kYXRhWzVdID0gJm1ici5lbmFi
-bGVfZGlzYWJsZTsKPiArCj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRf
-Y29tcGxldGlvbihjb21wbGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVf
-YW5kX2NsZWFuX29wYWxfZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICsKPiArfQo+ICtFWFBP
-UlRfU1lNQk9MKG9wYWxfZW5hYmxlX2Rpc2FibGVfc2hhZG93X21icik7Cj4gKwo+ICtpbnQgb3Bh
-bF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4g
-K3sKPiArCXN0cnVjdCBvcGFsX2xvY2tfdW5sb2NrIGxrdWw7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8
-ICFiZGV2LT5iZF9kaXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBzYXZlIHBhc3N3b3JkIGZvciBO
-VUxMIGJsb2NrIGRldmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiAr
-CWlmIChjb3B5X2Zyb21fdXNlcigmbGt1bCwga2V5LT5vcGFsX2xrX3VubGssIHNpemVvZigqa2V5
-LT5vcGFsKSkpCj4gKwkJcmV0dXJuIC1FRkFVTFQ7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfc2F2ZV9p
-bnRlcm5hbChiZGV2LCAmbGt1bCk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX3NhdmUpOwo+
-ICsKPiAraW50IG9wYWxfYWRkX3VzZXJfdG9fbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg
-c3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgbGt1
-bDsKPiArCj4gKwlpZiAoY29weV9mcm9tX3VzZXIoJmxrdWwsIGtleS0+b3BhbF9sa191bmxrLCBz
-aXplb2YobGt1bCkpKQo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsKPiArCWlmICghYmRldiB8fCAh
-YmRldi0+YmRfZGlzaykgewo+ICsJCXByX2VycigiQ2FuJ3QgYXNzaWduIHVzZXIgdG8gTFIgd2l0
-aG91dCBiYWNraW5nIGRpc2tcbiIpOwo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsJfQo+ICsJaWYg
-KGxrdWwubF9zdGF0ZSAhPSBPUEFMX1JPICYmIGxrdWwubF9zdGF0ZSAhPSBPUEFMX1JXKSB7Cj4g
-KwkJcHJfZXJyKCJMb2NraW5nIHN0YXRlIHdhcyBub3QgUk8gb3IgUldcbiIpOwo+ICsJCXJldHVy
-biAtRUlOVkFMOwo+ICsJfQo+ICsJaWYgKGxrdWwuYXV0aG9yaXR5LndobyA8IE9QQUxfVVNFUjEg
-JiYKPiArCSAgICBsa3VsLmF1dGhvcml0eS53aG8gPiBPUEFMX1VTRVI5KSB7Cj4gKwkJcHJfZXJy
-KCJBdXRob3JpdHkgd2FzIG5vdCB3aXRoaW4gdGhlIHJhbmdlIG9mIHVzZXJzOiAlZFxuIiwKPiAr
-CQkgICAgICAgbGt1bC5hdXRob3JpdHkud2hvKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0K
-PiArCWlmIChsa3VsLmF1dGhvcml0eS5TVU0pIHsKPiArCQlwcl9lcnIoIiVzIG5vdCBzdXBwb3J0
-ZWQgaW4gU1VNLiBVc2Ugc2V0dXAgbG9ja2luZyByYW5nZVxuIiwKPiArCQkgICAgICAgX19mdW5j
-X18pOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXJldHVybiBhZGRfdXNlcl9s
-cl9pbnRlcm5hbChiZGV2LCAmbGt1bCk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX2FkZF91
-c2VyX3RvX2xyKTsKPiArCj4gK2ludCBvcGFsX3JldmVydHRwZXIoc3RydWN0IGJsb2NrX2Rldmlj
-ZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsJc3RydWN0IG9wYWxfa2V5IGs7
-Cj4gKwo+ICsJaWYgKGNvcHlfZnJvbV91c2VyKCZrLCBrZXktPm9wYWwsIHNpemVvZigqa2V5LT5v
-cGFsKSkpCj4gKwkJcmV0dXJuIC1FRkFVTFQ7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfcmV2ZXJ0KGJk
-ZXYsICZrKTsKPiArfQo+ICtFWFBPUlRfU1lNQk9MKG9wYWxfcmV2ZXJ0dHBlcik7Cj4gKwo+ICtp
-bnQgb3BhbF9sb2NrX3VubG9jayhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk
-X2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayBrOwo+ICsKPiArCWlm
-IChjb3B5X2Zyb21fdXNlcigmaywga2V5LT5vcGFsX2xrX3VubGssIHNpemVvZigqa2V5LT5vcGFs
-X2xrX3VubGspKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlpZiAoay5hdXRob3JpdHku
-d2hvIDwgT1BBTF9BRE1JTjEgfHwgay5hdXRob3JpdHkud2hvID49IE9QQUxfVVNFUjkpClNob3Vs
-ZCB0aGlzIGJlID4gT1BBTF9VU0VSOSA/CgoKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwly
-ZXR1cm4gbG9ja191bmxvY2tfaW50ZXJuYWwoYmRldiwgJmspOwo+ICt9Cj4gK0VYUE9SVF9TWU1C
-T0wob3BhbF9sb2NrX3VubG9jayk7Cj4gKwo+ICtpbnQgb3BhbF90YWtlX293bmVyc2hpcChzdHJ1
-Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1
-Y3Qgb3BhbF9rZXkgazsKPiArCWNvbnN0IG9wYWxfc3RlcCBvd25lcl9mdW5jc1tdID0gewo+ICsJ
-CW9wYWxfZGlzY292ZXJ5MCwKPiArCQlzdGFydF9hbnlib2R5QVNQX29wYWxfc2Vzc2lvbiwKPiAr
-CQlnZXRfbXNpZF9jcGluX3BpbiwKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCXN0YXJ0X1NJ
-REFTUF9vcGFsX3Nlc3Npb24sCj4gKwkJc2V0X3NpZF9jcGluX3BpbiwKPiArCQllbmRfb3BhbF9z
-ZXNzaW9uLAo+ICsJCU5VTEwKPiArCX07Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9k
-aXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBzYXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRl
-dmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWlmIChjb3B5X2Zy
-b21fdXNlcigmaywga2V5LT5vcGFsLCBzaXplb2YoKmtleS0+b3BhbCkpKQo+ICsJCXJldHVybiAt
-RUZBVUxUOwo+ICsKPiArCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYsICZrLCBvd25lcl9mdW5j
-cyk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX3Rha2Vfb3duZXJzaGlwKTsKPiArCj4gK2lu
-dCBvcGFsX2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk
-X2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9rZXkgazsKPiArCWNvbnN0IG9wYWxfc3Rl
-cCBhY3RpdmVfZnVuY3NbXSA9IHsKPiArCQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfU0lE
-QVNQX29wYWxfc2Vzc2lvbiwgLyogT3BlbiBzZXNzaW9uIGFzIFNJRCBhdXRoICovCj4gKwkJZ2V0
-X2xzcF9saWZlY3ljbGUsCj4gKwkJYWN0aXZhdGVfbHNwLAo+ICsJCWVuZF9vcGFsX3Nlc3Npb24s
-Cj4gKwkJTlVMTAo+ICsJfTsKPiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2spIHsK
-PiArCQlwcl9lcnIoIkNhbid0IHNhdmUgcGFzc3dvcmQgZm9yIE5VTEwgYmxvY2sgZGV2aWNlLlxu
-Iik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJaWYgKGNvcHlfZnJvbV91c2Vy
-KCZrLCBrZXktPm9wYWwsIHNpemVvZigqa2V5LT5vcGFsKSkpCj4gKwkJcmV0dXJuIC1FRkFVTFQ7
-Cj4gKwo+ICsJcmV0dXJuIG9wYWxfYWN0X2xzcF9pbnQoYmRldiwgJmssIGFjdGl2ZV9mdW5jcyk7
-Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX2FjdGl2YXRlX2xzcCk7Cj4gKwo+ICtpbnQgb3Bh
-bF9zZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBz
-ZWRfa2V5ICpwdykKPiArewo+ICsJc3RydWN0IG9wYWxfdXNlcl9scl9zZXR1cCBrOwo+ICsKPiAr
-CWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzaykgewo+ICsJCXByX2VycigiQ2FuJ3Qgc2F2ZSBw
-YXNzd29yZCBmb3IgTlVMTCBibG9jayBkZXZpY2UuXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsK
-PiArCX0KPiArCj4gKwlpZiAoY29weV9mcm9tX3VzZXIoJmssIHB3LT5vcGFsX2xycywgc2l6ZW9m
-KCpwdy0+b3BhbF9scnMpKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlyZXR1cm4gaW50
-ZXJuYWxfc2V0dXBfbHIoYmRldiwgJmspOwo+ICt9Cj4gKwo+ICtpbnQgb3BhbF9zZXRfbmV3X3B3
-KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICpwdykKPiArewo+ICsJ
-c3RydWN0IG9wYWxfbmV3X3B3IGs7Cj4gKwo+ICsJaWYgKHB3LT5zZWRfdHlwZSAhPSBPUEFMX1BX
-KQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWlmIChjb3B5X2Zyb21fdXNlcigmaywgcHct
-Pm9wYWxfcHcsIHNpemVvZigqcHctPm9wYWxfcHcpKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiAr
-Cj4gKwlpZiAoay53aG8ud2hvIDwgT1BBTF9BRE1JTjEgfHwgay53aG8ud2hvID4gT1BBTF9VU0VS
-OSkKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlyZXR1cm4gb3BhbF9zZXRfcHcoYmRldiwg
-JmspOwo+ICt9Cj4gK0VYUE9SVF9TWU1CT0wob3BhbF9zZXRfbmV3X3B3KTsKPiArCj4gK2ludCBv
-cGFsX2FjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9r
-ZXkgKnB3KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9hY3RpdmF0ZV91c2VyIGs7Cj4gKwo+ICsJaWYg
-KHB3LT5zZWRfdHlwZSAhPSBPUEFMX0FDVF9VU1IpIHsKPiArCQlwcl9lcnIoIlNlZCB0eXBlIHdh
-cyBub3QgYWN0IHVzZXJcbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWlm
-IChjb3B5X2Zyb21fdXNlcigmaywgcHctPm9wYWxfYWN0LCBzaXplb2YoKnB3LT5vcGFsX2FjdCkp
-KSB7Cj4gKwkJcHJfZXJyKCJjb3B5IGZyb20gdXNlciBlcnJvclxuIik7Cj4gKwkJcmV0dXJuIC1F
-RkFVTFQ7Cj4gKwl9Cj4gKwo+ICsJLyogV2UgY2FuJ3QgYWN0aXZhdGUgQWRtaW4xIGl0J3MgYWN0
-aXZlIGFzIG1hbnVmYWN0dXJlZCAqLwo+ICsJaWYgKGsud2hvLndobyA8IE9QQUxfVVNFUjEgJiYg
-ay53aG8ud2hvID4gT1BBTF9VU0VSOSkgewo+ICsJCXByX2VycigiV2hvIHdhcyBub3QgYSB2YWxp
-ZCB1c2VyOiAlZCBcbiIsIGsud2hvLndobyk7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4g
-Kwo+ICsJcmV0dXJuIGFjdGl2YXRlX3VzZXIoYmRldiwgJmspOwo+ICsKPiArfQo+ICtFWFBPUlRf
-U1lNQk9MKG9wYWxfYWN0aXZhdGVfdXNlcik7Cj4gKwo+ICtpbnQgb3BhbF91bmxvY2tfZnJvbV9z
-dXNwZW5kKHN0cnVjdCBvcGFsX3N1c3BlbmRfdW5sayAqZGF0YSkKPiArewo+ICsJY29uc3QgY2hh
-ciAqZGlza25hbWUgPSBkYXRhLT5uYW1lOwo+ICsJc3RydWN0IG9wYWxfZGV2ICppdGVyLCAqZGV2
-ID0gTlVMTDsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247Cj4gKwl2b2lk
-ICpmdW5jX2RhdGFbM10gPSB7IE5VTEwgfTsKPiArCWNvbnN0IG9wYWxfc3RlcCBfdW5sb2NrX2Z1
-bmNzX1NVTVtdID0gewo+ICsJCW9wYWxfZGlzY292ZXJ5MCwKPiArCQlzdGFydF9hdXRoX29wYWxf
-c2Vzc2lvbiwKPiArCQlsb2NrX3VubG9ja19sb2NraW5nX3JhbmdlLApEaWQgeW91IG1lYW4gdG8g
-dXNlIGxvY2tfdW5sb2NrX2xvY2tpbmdfcmFuZ2VfU1VNID8KQ2FuIHdlIHB1bGwgdGhlc2UgdHdv
-IGFycmF5cyBvdXQgc2luY2UgdGhleSBhcmUgcmVxdWlyZWQgZm9yIGJvdGggdGhpcwpmdW5jdGlv
-biBhbmQgbG9ja191bmxvY2tfaW50ZXJuYWwgPwoKCj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiAr
-CQlOVUxMCj4gKwl9Owo+ICsJY29uc3Qgb3BhbF9zdGVwIF91bmxvY2tfZnVuY3NbXSA9IHsKPiAr
-CQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCj4gKwkJbG9j
-a191bmxvY2tfbG9ja2luZ19yYW5nZSwKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCU5VTEwK
-PiArCX07Cj4gKwo+ICsKPiArCXNwaW5fbG9jaygmbGlzdF9zcGlubG9jayk7Cj4gKwlsaXN0X2Zv
-cl9lYWNoX2VudHJ5KGl0ZXIsICZvcGFsX2xpc3QsIG5vZGUpIHsKPiArCQlpZiAoc3RybmNtcChp
-dGVyLT5kaXNrX25hbWUsIGRpc2tuYW1lLCBESVNLX05BTUVfTEVOKSkgewo+ICsJCQlwcl9lcnIo
-Iml0ZXJkaXNrIHdhcyAlcyBhbmQgZGlza25hbWUgaXMgJXNcbiIsCj4gKwkJCSAgICAgICBpdGVy
-LT5kaXNrX25hbWUsIGRpc2tuYW1lKTsKPiArCQkJY29udGludWU7Cj4gKwkJfQo+ICsJCWlmIChh
-dG9taWNfYWRkX3VubGVzcygmaXRlci0+aW5fdXNlLCAxLCAxKSkgewo+ICsJCQlkZXYgPSBpdGVy
-Owo+ICsJCQlkZXYtPmZ1bmNfZGF0YSA9IGZ1bmNfZGF0YTsKPiArCQkJZGV2LT5yZXN1bWVfZnJv
-bV9zdXNwZW5kID0gdHJ1ZTsKPiArCQkJZGV2LT5yZXN1bWVfZGF0YSA9IGRhdGE7Cj4gKwkJCWRl
-di0+ZmluYWxfY2IgPSB1bmxvY2tfc3VzcGVuZF9maW5hbDsKPiArCQkJZGV2LT5maW5hbF9jYl9k
-YXRhID0gZGV2Owo+ICsJCQlkZXYtPmVycm9yX2NiID0gZW5kX29wYWxfc2Vzc2lvbl9lcnJvcjsK
-PiArCQkJZGV2LT5lcnJvcl9jYl9kYXRhID0gZGV2Owo+ICsJCQlkZXYtPnN0YXRlID0gMDsKPiAr
-CQkJaWYgKGRldi0+bGt1bC5hdXRob3JpdHkuU1VNKQo+ICsJCQkJZGV2LT5mdW5jcyA9IF91bmxv
-Y2tfZnVuY3NfU1VNOwo+ICsJCQllbHNlCj4gKwkJCQlkZXYtPmZ1bmNzID0gX3VubG9ja19mdW5j
-czsKPiArCQkJZGV2LT5UU04gPSAwOwo+ICsJCQlkZXYtPkhTTiA9IDA7Cj4gKwkJCWRldi0+ZnVu
-Y19kYXRhWzJdID0gJmRldi0+bGt1bDsKPiArCQkJZGV2LT5mdW5jX2RhdGFbMV0gPSAmZGV2LT5s
-a3VsLmF1dGhvcml0eTsKPiArCQkJY29tcGxldGlvbiA9IGRldi0+Y29tcGxldGlvbjsKPiArCQkJ
-bmV4dCgwLCBkZXYpOwo+ICsJCQl3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsK
-PiArCQl9Cj4gKwl9Cj4gKwlzcGluX3VubG9jaygmbGlzdF9zcGlubG9jayk7Cj4gKwo+ICsJaWYg
-KCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICtFWFBPUlRf
-U1lNQk9MKG9wYWxfdW5sb2NrX2Zyb21fc3VzcGVuZCk7Cj4gZGlmZiAtLWdpdCBhL2xpYi9zZWQt
-b3BhbF9pbnRlcm5hbC5oIGIvbGliL3NlZC1vcGFsX2ludGVybmFsLmgKPiBuZXcgZmlsZSBtb2Rl
-IDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLmM5ZDM4ODMKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIv
-bGliL3NlZC1vcGFsX2ludGVybmFsLmgKPiBAQCAtMCwwICsxLDU4NiBAQAo+ICsvKgo+ICsgKiBD
-b3B5cmlnaHQgwqkgMjAxNiBJbnRlbCBDb3Jwb3JhdGlvbgo+ICsgKgo+ICsgKiBQZXJtaXNzaW9u
-IGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5p
-bmcgYQo+ICsgKiBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRh
-dGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLAo+ICsgKiB0byBkZWFsIGluIHRoZSBTb2Z0d2Fy
-ZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uCj4gKyAq
-IHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmli
-dXRlLCBzdWJsaWNlbnNlLAo+ICsgKiBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJl
-LCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUKPiArICogU29mdHdhcmUgaXMgZnVy
-bmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKPiAr
-ICoKPiArICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBu
-b3RpY2UgKGluY2x1ZGluZyB0aGUgbmV4dAo+ICsgKiBwYXJhZ3JhcGgpIHNoYWxsIGJlIGluY2x1
-ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlCj4gKyAqIFNv
-ZnR3YXJlLgo+ICsgKgo+ICsgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lU
-SE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgo+ICsgKiBJTVBMSUVELCBJTkNM
-VURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElU
-WSwKPiArICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdF
-TUVOVC4gIElOIE5PIEVWRU5UIFNIQUxMCj4gKyAqIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBI
-T0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCj4gKyAqIExJ
-QUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJX
-SVNFLCBBUklTSU5HCj4gKyAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhF
-IFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MKPiArICogSU4gVEhFIFNPRlRX
-QVJFLgo+ICsgKgo+ICsgKiBBdXRob3I6Cj4gKyAqICAgIFJhZmFlbCBBbnRvZ25vbGxpIDxyYWZh
-ZWwuYW50b2dub2xsaUBpbnRlbC5jb20+Cj4gKyAqICAgIFNjb3R0ICBCYXVlciAgICAgIDxzY290
-dC5iYXVlckBpbnRlbC5jb20+Cj4gKyAqLwo+ICsKPiArI2lmbmRlZiBfTlZNRV9PUEFMX0lOVEVS
-TkFMX0gKPiArI2RlZmluZSBfTlZNRV9PUEFMX0lOVEVSTkFMX0gKPiArCj4gKyNpbmNsdWRlIDxs
-aW51eC9rZXktdHlwZS5oPgo+ICsjaW5jbHVkZSA8a2V5cy91c2VyLXR5cGUuaD4KPiArCj4gKyNk
-ZWZpbmUgRFRBRVJST1JfTk9fTUVUSE9EX1NUQVRVUyAweDg5Cj4gKwo+ICtzdGF0aWMgY29uc3Qg
-Y2hhciAqb3BhbF9lcnJvcnNbMTldID0gewpSZW1vdmUgdGhlIDE5IHNvIGl0J3MganVzdCBvcGFs
-X2Vycm9yc1tdIChkb2VzbnQgc2lsZW50bHkgdHJ1bmNhdGUgYW55Cm5ldyBhZGRpdGlvbnMpCgoK
-PiArCSJTdWNjZXNzIiwKPiArCSJOb3QgQXV0aG9yaXplZCIsCj4gKwkiVW5rbm93biBFcnJvciIs
-Cj4gKwkiU1AgQnVzeSIsCj4gKwkiU1AgRmFpbGVkIiwKPiArCSJTUCBEaXNhYmxlZCIsCj4gKwki
-U1AgRnJvemVuIiwKPiArCSJObyBTZXNzaW9ucyBBdmFpbGFibGUiLAo+ICsJIlVuaXF1ZW5lc3Mg
-Q29uZmxpY3QiLAo+ICsJIkluc3VmZmljaWVudCBTcGFjZSIsCj4gKwkiSW5zdWZmaWNpZW50IFJv
-d3MiLAo+ICsJIkludmFsaWQgRnVuY3Rpb24iLAo+ICsJIkludmFsaWQgUGFyYW1ldGVyIiwKPiAr
-CSJJbnZhbGlkIFJlZmVyZW5jZSIsCj4gKwkiVW5rbm93biBFcnJvciIsCj4gKwkiVFBFUiBNYWxm
-dW5jdGlvbiIsCj4gKwkiVHJhbnNhY3Rpb24gRmFpbHVyZSIsCj4gKwkiUmVzcG9uc2UgT3ZlcmZs
-b3ciLAo+ICsJIkF1dGhvcml0eSBMb2NrZWQgT3V0IiwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25z
-dCBjaGFyICpvcGFsX2Vycm9yX3RvX2h1bWFuKGludCBlcnJvcikKPiArewo+ICsJaWYgKGVycm9y
-ID09IDB4M2YpCj4gKwkJcmV0dXJuICJGYWlsZWQiOwo+ICsKPiArCWlmIChlcnJvciA+PSBzaXpl
-b2Yob3BhbF9lcnJvcnMpIHx8IGVycm9yIDwgMCkKWW91IHdhbnQgc2l6ZW9mKG9wYWxfZXJyb3Jz
-KS9zaXplb2YoKm9wYWxfZXJyb3JzKSBoZXJlLCBidXQgeW91IGNhbiBqdXN0CnVzZSB0aGUgQVJS
-QVlfU0laRSBtYWNybyBpbnN0ZWFkCgoKPiArCQlyZXR1cm4gIlVua25vd24gRXJyb3IiOwo+ICsK
-PiArCXJldHVybiBvcGFsX2Vycm9yc1tlcnJvcl07Cj4gK30KPiArCj4gKy8qIFVzZXIgSURzIHVz
-ZWQgaW4gdGhlIFRDRyBzdG9yYWdlIFNTQ3MgKi8KPiArc3RhdGljIGNvbnN0IHU4IE9QQUxVSURb
-XVs4XSA9IHsKPiArCS8qIHVzZXJzICovCj4gKwo+ICsJLyogc2Vzc2lvbiBtYW5hZ2VtZW50ICAq
-Lwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweGZmfSwK
-PiArCS8qIHNwZWNpYWwgInRoaXNTUCIgc3ludGF4ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAs
-IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEgfSwKPiArCS8qIEFkbWluaXN0cmF0aXZlIFNQ
-ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDIsIDB4MDUsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEg
-fSwKPiArCS8qIExvY2tpbmcgU1AgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMiwgMHgwNSwgMHgw
-MCwgMHgwMCwgMHgwMCwgMHgwMiB9LAo+ICsJLyogRU5URVJQUklTRSBMb2NraW5nIFNQICAqLwo+
-ICsJeyAweDAwLCAweDAwLCAweDAyLCAweDA1LCAweDAwLCAweDAxLCAweDAwLCAweDAxIH0sCj4g
-KwkvKiBhbnlib2R5ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDAs
-IDB4MDAsIDB4MDEgfSwKPiArCS8qIFNJRCAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA5
-LCAweDAwLCAweDAwLCAweDAwLCAweDA2IH0sCj4gKwkvKiBBRE1JTjEgKi8KPiArCXsgMHgwMCwg
-MHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMSwgMHgwMCwgMHgwMSB9LAo+ICsJLyogVVNFUjEg
-Ki8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMywgMHgwMCwgMHgwMSB9
-LAo+ICsJLyogVVNFUjIgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgw
-MywgMHgwMCwgMHgwMiB9LAo+ICsJLyogUFNJRCB1c2VyICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4
-MDAsIDB4MDksIDB4MDAsIDB4MDEsIDB4ZmYsIDB4MDEgfSwKPiArCS8qIEJhbmRNYXN0ZXIgMCAq
-Lwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAwLCAweDgwLCAweDAxIH0s
-Cj4gKwkgLyogRXJhc2VNYXN0ZXIgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgw
-MCwgMHgwMCwgMHg4NCwgMHgwMSB9LAo+ICsKPiArCS8qIHRhYmxlcyAqLwo+ICsKPiArCS8qIExv
-Y2tpbmdfR2xvYmFsUmFuZ2UgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwOCwgMHgwMiwgMHgwMCwg
-MHgwMCwgMHgwMCwgMHgwMSB9LAo+ICsJLyogQUNFX0xvY2tpbmdfUmFuZ2VfU2V0X1JkTG9ja2Vk
-IFVJRCAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA4LCAweDAwLCAweDAzLCAweEUwLCAw
-eDAxIH0sCj4gKwkvKiBBQ0VfTG9ja2luZ19SYW5nZV9TZXRfV3JMb2NrZWQgVUlEICovCj4gKwl7
-IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDgsIDB4MDAsIDB4MDMsIDB4RTgsIDB4MDEgfSwKPiArCS8q
-IE1CUiBDb250cm9sICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDgsIDB4MDMsIDB4MDAsIDB4MDAs
-IDB4MDAsIDB4MDEgfSwKPiArCS8qIFNoYWRvdyBNQlIgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgw
-OCwgMHgwNCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCB9LAo+ICsJLyogQVVUSE9SSVRZX1RBQkxF
-ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDB9
-LAo+ICsJLyogQ19QSU5fVEFCTEUgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwQiwgMHgw
-MCwgMHgwMCwgMHgwMCwgMHgwMH0sCj4gKwkvKiBPUEFMIExvY2tpbmcgSW5mbyAqLwo+ICsJeyAw
-eDAwLCAweDAwLCAweDA4LCAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAxIH0sCj4gKwkvKiBF
-bnRlcnByaXNlIExvY2tpbmcgSW5mbyAqLwo+ICsJeyAweDAwLCAweDAwLCAweDA4LCAweDAxLCAw
-eDAwLCAweDAwLCAweDAwLCAweDAwIH0sCj4gKwo+ICsJLyogQ19QSU5fVEFCTEUgb2JqZWN0IElE
-J3MgKi8KPiArCj4gKwkvKiBDX1BJTl9NU0lEICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4
-MEIsIDB4MDAsIDB4MDAsIDB4ODQsIDB4MDJ9LAo+ICsJLyogQ19QSU5fU0lEICovCj4gKwl7IDB4
-MDAsIDB4MDAsIDB4MDAsIDB4MEIsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDF9LAo+ICsJIC8qIENf
-UElOX0FETUlOMSAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDBCLCAweDAwLCAweDAxLCAw
-eDAwLCAweDAxfSwKPiArCj4gKwkvKiBoYWxmIFVJRCdzIChvbmx5IGZpcnN0IDQgYnl0ZXMgdXNl
-ZCkgKi8KPiArCj4gKwkvKiBIYWxmLVVJRCDigJMgQXV0aG9yaXR5X29iamVjdF9yZWYgKi8KPiAr
-CXsgMHgwMCwgMHgwMCwgMHgwQywgMHgwNSwgMHhmZiwgMHhmZiwgMHhmZiwgMHhmZiB9LAo+ICsJ
-LyogSGFsZi1VSUQg4oCTIEJvb2xlYW4gQUNFICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDQsIDB4
-MEUsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYgfSwKPiArCj4gKwkvKiBzcGVjaWFsIHZhbHVlIGZv
-ciBvbWl0dGVkIG9wdGlvbmFsIHBhcmFtZXRlciAqLwo+ICsKPiArCS8qIEhFWEZGIGZvciBvbWl0
-dGVkICovCj4gKwl7IDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4
-ZmZ9LAo+ICt9Owo+ICtzdGF0aWMgY29uc3Qgc2l6ZV90IE9QQUxfVUlEX0xFTkdUSCA9IDg7Cj4g
-K3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9NU0lEX0tFWUxFTiA9IDE1Owo+ICtzdGF0aWMgY29u
-c3Qgc2l6ZV90IE9QQUxfVUlEX0xFTkdUSF9IQUxGID0gNDsKPiArCj4gKwo+ICsvKiBFbnVtIHRv
-IGluZGV4IE9QQUxVSUQgYXJyYXkgKi8KPiArZW51bSBPUEFMX1VJRCB7Cj4gKwkvKiB1c2VycyAq
-Lwo+ICsJT1BBTF9TTVVJRF9VSUQsCj4gKwlPUEFMX1RISVNTUF9VSUQsCj4gKwlPUEFMX0FETUlO
-U1BfVUlELAo+ICsJT1BBTF9MT0NLSU5HU1BfVUlELAo+ICsJT1BBTF9FTlRFUlBSSVNFX0xPQ0tJ
-TkdTUF9VSUQsCj4gKwlPUEFMX0FOWUJPRFlfVUlELAo+ICsJT1BBTF9TSURfVUlELAo+ICsJT1BB
-TF9BRE1JTjFfVUlELAo+ICsJT1BBTF9VU0VSMV9VSUQsCj4gKwlPUEFMX1VTRVIyX1VJRCwKPiAr
-CU9QQUxfUFNJRF9VSUQsCj4gKwlPUEFMX0VOVEVSUFJJU0VfQkFORE1BU1RFUjBfVUlELAo+ICsJ
-T1BBTF9FTlRFUlBSSVNFX0VSQVNFTUFTVEVSX1VJRCwKPiArCS8qIHRhYmxlcyAqLwo+ICsJT1BB
-TF9MT0NLSU5HUkFOR0VfR0xPQkFMLAo+ICsJT1BBTF9MT0NLSU5HUkFOR0VfQUNFX1JETE9DS0VE
-LAo+ICsJT1BBTF9MT0NLSU5HUkFOR0VfQUNFX1dSTE9DS0VELAo+ICsJT1BBTF9NQlJDT05UUk9M
-LAo+ICsJT1BBTF9NQlIsCj4gKwlPUEFMX0FVVEhPUklUWV9UQUJMRSwKPiArCU9QQUxfQ19QSU5f
-VEFCTEUsCj4gKwlPUEFMX0xPQ0tJTkdfSU5GT19UQUJMRSwKPiArCU9QQUxfRU5URVJQUklTRV9M
-T0NLSU5HX0lORk9fVEFCTEUsCj4gKwkvKiBDX1BJTl9UQUJMRSBvYmplY3QgSUQncyAqLwo+ICsJ
-T1BBTF9DX1BJTl9NU0lELAo+ICsJT1BBTF9DX1BJTl9TSUQsCj4gKwlPUEFMX0NfUElOX0FETUlO
-MSwKPiArCS8qIGhhbGYgVUlEJ3MgKG9ubHkgZmlyc3QgNCBieXRlcyB1c2VkKSAqLwo+ICsJT1BB
-TF9IQUxGX1VJRF9BVVRIT1JJVFlfT0JKX1JFRiwKPiArCU9QQUxfSEFMRl9VSURfQk9PTEVBTl9B
-Q0UsCj4gKwkvKiBvbWl0dGVkIG9wdGlvbmFsIHBhcmFtZXRlciAqLwo+ICsJT1BBTF9VSURfSEVY
-RkYsCj4gK307Cj4gKwo+ICsvKgo+ICsgKiBUQ0cgU3RvcmFnZSBTU0MgTWV0aG9kcy4KPiArICov
-Cj4gK3N0YXRpYyBjb25zdCB1OCBPUEFMTUVUSE9EW11bOF0gPSB7Cj4gKwkvKiBQcm9wZXJ0aWVz
-ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4ZmYsIDB4MDEg
-fSwKPiArCS8qIFNUQVJUU0VTU0lPTiAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw
-eDAwLCAweDAwLCAweGZmLCAweDAyIH0sCj4gKwkvKiBSZXZlcnQgKi8KPiArCXsgMHgwMCwgMHgw
-MCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMiwgMHgwMiB9LAo+ICsJLyogQWN0aXZhdGUg
-Ki8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMiwgMHgwMyB9
-LAo+ICsJLyogRW50ZXJwcmlzZSBHZXQgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwg
-MHgwMCwgMHgwMCwgMHgwMCwgMHgwNiB9LAo+ICsJLyogRW50ZXJwcmlzZSBTZXQgKi8KPiArCXsg
-MHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNyB9LAo+ICsJLyog
-TkVYVCAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAw
-eDA4IH0sCj4gKwkvKiBFbnRlcnByaXNlIEF1dGhlbnRpY2F0ZSAqLwo+ICsJeyAweDAwLCAweDAw
-LCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDBjIH0sCj4gKwkvKiBHZXRBQ0wgKi8K
-PiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwZCB9LAo+
-ICsJLyogR2VuS2V5ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAs
-IDB4MDAsIDB4MTAgfSwKPiArCS8qIHJldmVydFNQICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAs
-IDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MTEgfSwKPiArCS8qIEdldCAqLwo+ICsJeyAweDAw
-LCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDE2IH0sCj4gKwkvKiBTZXQg
-Ki8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgxNyB9
-LAo+ICsJLyogQXV0aGVudGljYXRlICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4
-MDAsIDB4MDAsIDB4MDAsIDB4MWMgfSwKPiArCS8qIFJhbmRvbSAqLwo+ICsJeyAweDAwLCAweDAw
-LCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDA2LCAweDAxIH0sCj4gKwkvKiBFcmFzZSAqLwo+
-ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDA4LCAweDAzIH0sCj4g
-K307Cj4gK3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9NRVRIT0RfTEVOR1RIID0gODsKPiArCj4g
-Ky8qIEVudW0gZm9yIGluZGV4aW5nIHRoZSBPUEFMTUVUSE9EIGFycmF5ICovCj4gK2VudW0gT1BB
-TF9NRVRIT0Qgewo+ICsJT1BBTF9QUk9QRVJUSUVTLAo+ICsJT1BBTF9TVEFSVFNFU1NJT04sCj4g
-KwlPUEFMX1JFVkVSVCwKPiArCU9QQUxfQUNUSVZBVEUsCj4gKwlPUEFMX0VHRVQsCj4gKwlPUEFM
-X0VTRVQsCj4gKwlPUEFMX05FWFQsCj4gKwlPUEFMX0VBVVRIRU5USUNBVEUsCj4gKwlPUEFMX0dF
-VEFDTCwKPiArCU9QQUxfR0VOS0VZLAo+ICsJT1BBTF9SRVZFUlRTUCwKPiArCU9QQUxfR0VULAo+
-ICsJT1BBTF9TRVQsCj4gKwlPUEFMX0FVVEhFTlRJQ0FURSwKPiArCU9QQUxfUkFORE9NLAo+ICsJ
-T1BBTF9FUkFTRSwKPiArfTsKPiArCj4gK2VudW0gT1BBTF9SRVNQT05TRV9UT0tFTiB7Cj4gKwlP
-UEFMX0RUQV9UT0tFTklEX0JZVEVTVFJJTkcgPSAweGUwLAo+ICsJT1BBTF9EVEFfVE9LRU5JRF9T
-SU5UID0gMHhlMSwKPiArCU9QQUxfRFRBX1RPS0VOSURfVUlOVCA9IDB4ZTIsCj4gKwlPUEFMX0RU
-QV9UT0tFTklEX1RPS0VOID0gMHhlMywgLyogYWN0dWFsIHRva2VuIGlzIHJldHVybmVkICovCj4g
-KwlPUEFMX0RUQV9UT0tFTklEX0lOVkFMSUQgPSAwWDAKPiArfTsKPiArCj4gK2VudW0gT1BBTF9U
-T0tFTiB7Cj4gKwkvKiBCb29sZWFuICovCj4gKwlPUEFMX1RSVUUgPSAweDAxLAo+ICsJT1BBTF9G
-QUxTRSA9IDB4MDAsCj4gKwlPUEFMX0JPT0xFQU5fRVhQUiA9IDB4MDMsCj4gKwkvKiBjZWxsYmxv
-Y2tzICovCj4gKwlPUEFMX1RBQkxFID0gMHgwMCwKPiArCU9QQUxfU1RBUlRST1cgPSAweDAxLAo+
-ICsJT1BBTF9FTkRST1cgPSAweDAyLAo+ICsJT1BBTF9TVEFSVENPTFVNTiA9IDB4MDMsCj4gKwlP
-UEFMX0VORENPTFVNTiA9IDB4MDQsCj4gKwlPUEFMX1ZBTFVFUyA9IDB4MDEsCj4gKwkvKiBhdXRo
-b3JpdHkgdGFibGUgKi8KPiArCU9QQUxfUElOID0gMHgwMywKPiArCS8qIGxvY2tpbmcgdG9rZW5z
-ICovCj4gKwlPUEFMX1JBTkdFU1RBUlQgPSAweDAzLAo+ICsJT1BBTF9SQU5HRUxFTkdUSCA9IDB4
-MDQsCj4gKwlPUEFMX1JFQURMT0NLRU5BQkxFRCA9IDB4MDUsCj4gKwlPUEFMX1dSSVRFTE9DS0VO
-QUJMRUQgPSAweDA2LAo+ICsJT1BBTF9SRUFETE9DS0VEID0gMHgwNywKPiArCU9QQUxfV1JJVEVM
-T0NLRUQgPSAweDA4LAo+ICsJT1BBTF9BQ1RJVkVLRVkgPSAweDBBLAo+ICsJLyogbG9ja2luZyBp
-bmZvIHRhYmxlICovCj4gKwlPUEFMX01BWFJBTkdFUyA9IDB4MDQsCj4gKwkgLyogbWJyIGNvbnRy
-b2wgKi8KPiArCU9QQUxfTUJSRU5BQkxFID0gMHgwMSwKPiArCU9QQUxfTUJSRE9ORSA9IDB4MDIs
-Cj4gKwkvKiBwcm9wZXJ0aWVzICovCj4gKwlPUEFMX0hPU1RQUk9QRVJUSUVTID0gMHgwMCwKPiAr
-CS8qIGF0b21zICovCj4gKwlPUEFMX1NUQVJUTElTVCA9IDB4ZjAsCj4gKwlPUEFMX0VORExJU1Qg
-PSAweGYxLAo+ICsJT1BBTF9TVEFSVE5BTUUgPSAweGYyLAo+ICsJT1BBTF9FTkROQU1FID0gMHhm
-MywKPiArCU9QQUxfQ0FMTCA9IDB4ZjgsCj4gKwlPUEFMX0VORE9GREFUQSA9IDB4ZjksCj4gKwlP
-UEFMX0VORE9GU0VTU0lPTiA9IDB4ZmEsCj4gKwlPUEFMX1NUQVJUVFJBTlNBQ1RPTiA9IDB4ZmIs
-Cj4gKwlPUEFMX0VORFRSQU5TQUNUT04gPSAweGZDLAo+ICsJT1BBTF9FTVBUWUFUT00gPSAweGZm
-LAo+ICsJT1BBTF9XSEVSRSA9IDB4MDAsCj4gK307Cj4gKwo+ICsvKiBVc2VmdWwgdGlueSBhdG9t
-cy4KPiArICogVXNlZnVsIGZvciB0YWJsZSBjb2x1bW5zIGV0Ywo+ICsgKi8KPiArZW51bSBPUEFM
-X1RJTllfQVRPTSB7Cj4gKwlPUEFMX1RJTllfVUlOVF8wMCA9IDB4MDAsCj4gKwlPUEFMX1RJTllf
-VUlOVF8wMSA9IDB4MDEsCj4gKwlPUEFMX1RJTllfVUlOVF8wMiA9IDB4MDIsCj4gKwlPUEFMX1RJ
-TllfVUlOVF8wMyA9IDB4MDMsCj4gKwlPUEFMX1RJTllfVUlOVF8wNCA9IDB4MDQsCj4gKwlPUEFM
-X1RJTllfVUlOVF8wNSA9IDB4MDUsCj4gKwlPUEFMX1RJTllfVUlOVF8wNiA9IDB4MDYsCj4gKwlP
-UEFMX1RJTllfVUlOVF8wNyA9IDB4MDcsCj4gKwlPUEFMX1RJTllfVUlOVF8wOCA9IDB4MDgsCj4g
-KwlPUEFMX1RJTllfVUlOVF8wOSA9IDB4MDksCj4gKwlPUEFMX1RJTllfVUlOVF8xMCA9IDB4MGEs
-Cj4gKwlPUEFMX1RJTllfVUlOVF8xMSA9IDB4MGIsCj4gKwlPUEFMX1RJTllfVUlOVF8xMiA9IDB4
-MGMsCj4gKwlPUEFMX1RJTllfVUlOVF8xMyA9IDB4MGQsCj4gKwlPUEFMX1RJTllfVUlOVF8xNCA9
-IDB4MGUsCj4gKwlPUEFMX1RJTllfVUlOVF8xNSA9IDB4MGYsCj4gK307Cj4gKwo+ICtlbnVtIE9Q
-QUxfQVRPTV9XSURUSCB7Cj4gKwlPUEFMX1dJRFRIX1RJTlksCj4gKwlPUEFMX1dJRFRIX1NIT1JU
-LAo+ICsJT1BBTF9XSURUSF9NRURJVU0sCj4gKwlPUEFMX1dJRFRIX0xPTkcsCj4gKwlPUEFMX1dJ
-RFRIX1RPS0VOCj4gK307Cj4gKwo+ICsvKiBMb2NraW5nIHN0YXRlIGZvciBhIGxvY2tpbmcgcmFu
-Z2UgKi8KPiArZW51bSBPUEFMX0xPQ0tJTkdTVEFURSB7Cj4gKwlPUEFMX0xPQ0tJTkdfUkVBRFdS
-SVRFID0gMHgwMSwKPiArCU9QQUxfTE9DS0lOR19SRUFET05MWSA9IDB4MDIsCj4gKwlPUEFMX0xP
-Q0tJTkdfTE9DS0VEID0gMHgwMywKPiArfTsKPiArCj4gKy8qCj4gKyAqIFN0cnVjdHVyZXMgdG8g
-YnVpbGQgYW5kIGRlY29kZSB0aGUgT3BhbCBTU0MgbWVzc2FnZXMKPiArICogZmllbGRzIHRoYXQg
-YXJlIE5PVCByZWFsbHkgbnVtZXJpYyBhcmUgZGVmaW5lZCBhcyB1OFtdIHRvCj4gKyAqIGhlbHAg
-cmVkdWNlIHRoZSBlbmRpYW5uZXNzIGlzc3Vlcwo+ICsgKi8KPiArCj4gKy8qIENvbW0gUGFja2V0
-IChoZWFkZXIpIGZvciB0cmFuc21pc3Npb25zLiAqLwo+ICtzdHJ1Y3Qgb3BhbF9jb21wYWNrZXQg
-ewo+ICsJdTMyIHJlc2VydmVkMDsKPiArCXU4IGV4dGVuZGVkQ29tSURbNF07Cj4gKwl1MzIgb3V0
-c3RhbmRpbmdEYXRhOwo+ICsJdTMyIG1pblRyYW5zZmVyOwo+ICsJdTMyIGxlbmd0aDsKPiArfTsK
-PiArCj4gKy8qIFBhY2tldCBzdHJ1Y3R1cmUuICovCj4gK3N0cnVjdCBvcGFsX3BhY2tldCB7Cj4g
-Kwl1MzIgVFNOOwo+ICsJdTMyIEhTTjsKPiArCXUzMiBzZXFfbnVtYmVyOwo+ICsJdTE2IHJlc2Vy
-dmVkMDsKPiArCXUxNiBhY2tfdHlwZTsKPiArCXUzMiBhY2tub3dsZWRnbWVudDsKPiArCXUzMiBs
-ZW5ndGg7Cj4gK307Cj4gKwo+ICsvKiBEYXRhIHN1YiBwYWNrZXQgaGVhZGVyICovCj4gK3N0cnVj
-dCBvcGFsX2RhdGFfc3VicGFja2V0IHsKPiArCXU4IHJlc2VydmVkMFs2XTsKPiArCXUxNiBraW5k
-Owo+ICsJdTMyIGxlbmd0aDsKPiArfTsKPiArCj4gKy8qIGhlYWRlciBvZiBhIHJlc3BvbnNlICov
-Cj4gK3N0cnVjdCBvcGFsX2hlYWRlciB7Cj4gKwlzdHJ1Y3Qgb3BhbF9jb21wYWNrZXQgY3A7Cj4g
-KwlzdHJ1Y3Qgb3BhbF9wYWNrZXQgcGt0Owo+ICsJc3RydWN0IG9wYWxfZGF0YV9zdWJwYWNrZXQg
-c3VicGt0Owo+ICt9Owo+ICsKPiArI2RlZmluZSBGQ19UUEVSICAgICAgIDB4MDAwMQo+ICsjZGVm
-aW5lIEZDX0xPQ0tJTkcgICAgMHgwMDAyCj4gKyNkZWZpbmUgRkNfR0VPTUVUUlkgICAweDAwMDMK
-PiArI2RlZmluZSBGQ19FTlRFUlBSSVNFIDB4MDEwMAo+ICsjZGVmaW5lIEZDX0RBVEFTVE9SRSAg
-MHgwMjAyCj4gKyNkZWZpbmUgRkNfU0lOR0xFVVNFUiAweDAyMDEKPiArI2RlZmluZSBGQ19PUEFM
-VjEwMCAgIDB4MDIwMAo+ICsjZGVmaW5lIEZDX09QQUxWMjAwICAgMHgwMjAzCj4gKwo+ICsvKgo+
-ICsgKiBUaGUgRGlzY292ZXJ5IDAgSGVhZGVyLiBBcyBkZWZpbmVkIGluCj4gKyAqIE9wYWwgU1ND
-IERvY3VtZW50YXRpb24KPiArICovCj4gK3N0cnVjdCBkMF9oZWFkZXIgewo+ICsJdTMyIGxlbmd0
-aDsgLyogdGhlIGxlbmd0aCBvZiB0aGUgaGVhZGVyIDQ4IGluIDIuMDAuMTAwICovCj4gKwl1MzIg
-cmV2aXNpb247IC8qKjwgcmV2aXNpb24gb2YgdGhlIGhlYWRlciAxIGluIDIuMDAuMTAwICovCj4g
-Kwl1MzIgcmVzZXJ2ZWQwMTsKPiArCXUzMiByZXNlcnZlZDAyOwo+ICsJLyoKPiArCSAqIHRoZSBy
-ZW1haW5kZXIgb2YgdGhlIHN0cnVjdHVyZSBpcyB2ZW5kb3Igc3BlY2lmaWMgYW5kIHdpbGwgbm90
-IGJlCj4gKwkgKiBhZGRyZXNzZWQgbm93Cj4gKwkgKi8KPiArCXU4IGlnbm9yZWRbMzJdOwo+ICt9
-Owo+ICsKPiArLyoKPiArICogVFBlciBGZWF0dXJlIERlc2NyaXB0b3IuIENvbnRhaW5zIGZsYWdz
-IGluZGljYXRpbmcgc3VwcG9ydCBmb3IgdGhlCj4gKyAqIFRQZXIgZmVhdHVyZXMgZGVzY3JpYmVk
-IGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRjaCB0aGUKPiArICogT1BB
-TCB0ZXJtaW5vbG9neQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDAxIGluIDIuMDAuMTAwCj4gKyAq
-Lwo+ICtzdHJ1Y3QgZDBfdHBlcl9mZWF0dXJlcyB7Cj4gKwkvKgo+ICsJICogc3VwcG9ydGVkX2Zl
-YXR1cmVzIGJpdHM6Cj4gKwkgKiBiaXQgNzogcmVzZXJ2ZWQKPiArCSAqIGJpdCA2OiBjb20gSUQg
-bWFuYWdlbWVudAo+ICsJICogYml0IDU6IHJlc2VydmVkCj4gKwkgKiBiaXQgNDogc3RyZWFtaW5n
-IHN1cHBvcnQKPiArCSAqIGJpdCAzOiBidWZmZXIgbWFuYWdlbWVudAo+ICsJICogYml0IDI6IEFD
-Sy9OQUNLCj4gKwkgKiBiaXQgMTogYXN5bmMKPiArCSAqIGJpdCAwOiBzeW5jCj4gKwkgKi8KPiAr
-CXU4IHN1cHBvcnRlZF9mZWF0dXJlczsKPiArCS8qCj4gKwkgKiBieXRlcyA1IHRocm91Z2ggMTUg
-YXJlIHJlc2VydmVkLCBidXQgd2UgcmVwcmVzZW50IHRoZSBmaXJzdCAzIGFzCj4gKwkgKiB1OCB0
-byBrZWVwIHRoZSBvdGhlciB0d28gMzJiaXRzIGludGVnZXJzIGFsaWduZWQuCj4gKwkgKi8KPiAr
-CXU4IHJlc2VydmVkMDFbM107Cj4gKwl1MzIgcmVzZXJ2ZWQwMjsKPiArCXUzMiByZXNlcnZlZDAz
-Owo+ICt9Owo+ICsKPiArLyoKPiArICogTG9ja2luZyBGZWF0dXJlIERlc2NyaXB0b3IuIENvbnRh
-aW5zIGZsYWdzIGluZGljYXRpbmcgc3VwcG9ydCBmb3IgdGhlCj4gKyAqIGxvY2tpbmcgZmVhdHVy
-ZXMgZGVzY3JpYmVkIGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRjaCB0
-aGUKPiArICogT1BBTCB0ZXJtaW5vbG9neQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDAwMiBpbiAy
-LjAwLjEwMAo+ICsgKi8KPiArc3RydWN0IGQwX2xvY2tpbmdfZmVhdHVyZXMgewo+ICsJLyoKPiAr
-CSAqIHN1cHBvcnRlZF9mZWF0dXJlcyBiaXRzOgo+ICsJICogYml0cyA2LTc6IHJlc2VydmVkCj4g
-KwkgKiBiaXQgNTogTUJSIGRvbmUKPiArCSAqIGJpdCA0OiBNQlIgZW5hYmxlZAo+ICsJICogYml0
-IDM6IG1lZGlhIGVuY3J5cHRpb24KPiArCSAqIGJpdCAyOiBsb2NrZWQKPiArCSAqIGJpdCAxOiBs
-b2NraW5nIGVuYWJsZWQKPiArCSAqIGJpdCAwOiBsb2NraW5nIHN1cHBvcnRlZAo+ICsJICovCj4g
-Kwl1OCBzdXBwb3J0ZWRfZmVhdHVyZXM7Cj4gKwkvKgo+ICsJICogYnl0ZXMgNSB0aHJvdWdoIDE1
-IGFyZSByZXNlcnZlZCwgYnV0IHdlIHJlcHJlc2VudCB0aGUgZmlyc3QgMyBhcwo+ICsJICogdTgg
-dG8ga2VlcCB0aGUgb3RoZXIgdHdvIDMyYml0cyBpbnRlZ2VycyBhbGlnbmVkLgo+ICsJICovCj4g
-Kwl1OCByZXNlcnZlZDAxWzNdOwo+ICsJdTMyIHJlc2VydmVkMDI7Cj4gKwl1MzIgcmVzZXJ2ZWQw
-MzsKPiArfTsKPiArCj4gKy8qCj4gKyAqIEdlb21ldHJ5IEZlYXR1cmUgRGVzY3JpcHRvci4gQ29u
-dGFpbnMgZmxhZ3MgaW5kaWNhdGluZyBzdXBwb3J0IGZvciB0aGUKPiArICogZ2VvbWV0cnkgZmVh
-dHVyZXMgZGVzY3JpYmVkIGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRj
-aCB0aGUKPiArICogT1BBTCB0ZXJtaW5vbG9neQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDAwMyBp
-biAyLjAwLjEwMAo+ICsgKi8KPiArc3RydWN0IGQwX2dlb21ldHJ5X2ZlYXR1cmVzIHsKPiArCS8q
-Cj4gKwkgKiBza2lwIDMyIGJpdHMgZnJvbSBoZWFkZXIsIG5lZWRlZCB0byBhbGlnbiB0aGUgc3Ry
-dWN0IHRvIDY0IGJpdHMuCj4gKwkgKi8KPiArCXU4IGhlYWRlcls0XTsKPiArCS8qCj4gKwkgKiBy
-ZXNlcnZlZDAxOgo+ICsJICogYml0cyAxLTY6IHJlc2VydmVkCj4gKwkgKiBiaXQgMDogYWxpZ24K
-PiArCSAqLwo+ICsJdTggcmVzZXJ2ZWQwMTsKPiArCXU4IHJlc2VydmVkMDJbN107Cj4gKwl1MzIg
-bG9naWNhbF9ibG9ja19zaXplOwo+ICsJdTY0IGFsaWdubWVudF9ncmFudWxhcml0eTsKPiArCXU2
-NCBsb3dlc3RfYWxpZ25lZF9sYmE7Cj4gK307Cj4gKwo+ICsvKgo+ICsgKiBFbnRlcnByaXNlIFNT
-QyBGZWF0dXJlCj4gKyAqCj4gKyAqIGNvZGUgPT0gMHgwMTAwCj4gKyAqLwo+ICtzdHJ1Y3QgZDBf
-ZW50ZXJwcmlzZV9zc2Mgewo+ICsJdTE2IGJhc2VDb21JRDsKPiArCXUxNiBudW1Db21JRHM7Cj4g
-KwkvKiByYW5nZV9jcm9zc2luZzoKPiArCSAqIGJpdHMgMS02OiByZXNlcnZlZAo+ICsJICogYml0
-IDA6IHJhbmdlIGNyb3NzaW5nCj4gKwkgKi8KPiArCXU4IHJhbmdlX2Nyb3NzaW5nOwo+ICsJdTgg
-cmVzZXJ2ZWQwMTsKPiArCXUxNiByZXNlcnZlZDAyOwo+ICsJdTMyIHJlc2VydmVkMDM7Cj4gKwl1
-MzIgcmVzZXJ2ZWQwNDsKPiArfTsKPiArCj4gKy8qCj4gKyAqIE9wYWwgVjEgZmVhdHVyZQo+ICsg
-Kgo+ICsgKiBjb2RlID09IDB4MDIwMAo+ICsgKi8KPiArc3RydWN0IGQwX29wYWxfdjEwMCB7Cj4g
-Kwl1MTYgYmFzZUNvbUlEOwo+ICsJdTE2IG51bUNvbUlEczsKPiArfTsKPiArCj4gKy8qCj4gKyAq
-IFNpbmdsZSBVc2VyIE1vZGUgZmVhdHVyZQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDIwMQo+ICsg
-Ki8KPiArc3RydWN0IGQwX3NpbmdsZV91c2VyX21vZGUgewo+ICsJdTMyIG51bV9sb2NraW5nX29i
-amVjdHM7Cj4gKwkvKiByZXNlcnZlZDAxOgo+ICsJICogYml0IDA6IGFueQo+ICsJICogYml0IDE6
-IGFsbAo+ICsJICogYml0IDI6IHBvbGljeQo+ICsJICogYml0cyAzLTc6IHJlc2VydmVkCj4gKwkg
-Ki8KPiArCXU4IHJlc2VydmVkMDE7Cj4gKwl1OCByZXNlcnZlZDAyOwo+ICsJdTE2IHJlc2VydmVk
-MDM7Cj4gKwl1MzIgcmVzZXJ2ZWQwNDsKPiArfTsKPiArCj4gKy8qCj4gKyAqIEFkZGl0b25hbCBE
-YXRhc3RvcmVzIGZlYXR1cmUKPiArICoKPiArICogY29kZSA9PSAweDAyMDIKPiArICovCj4gK3N0
-cnVjdCBkMF9kYXRhc3RvcmVfdGFibGUgewo+ICsJdTE2IHJlc2VydmVkMDE7Cj4gKwl1MTYgbWF4
-X3RhYmxlczsKPiArCXUzMiBtYXhfc2l6ZV90YWJsZXM7Cj4gKwl1MzIgdGFibGVfc2l6ZV9hbGln
-bm1lbnQ7Cj4gK307Cj4gKwo+ICsvKgo+ICsgKiBPUEFMIDIuMCBmZWF0dXJlCj4gKyAqCj4gKyAq
-IGNvZGUgPT0gMHgwMjAzCj4gKyAqLwo+ICtzdHJ1Y3QgZDBfb3BhbF92MjAwIHsKPiArCXUxNiBi
-YXNlQ29tSUQ7Cj4gKwl1MTYgbnVtQ29tSURzOwo+ICsJLyogcmFuZ2VfY3Jvc3Npbmc6Cj4gKwkg
-KiBiaXRzIDEtNjogcmVzZXJ2ZWQKPiArCSAqIGJpdCAwOiByYW5nZSBjcm9zc2luZwo+ICsJICov
-Cj4gKwl1OCByYW5nZV9jcm9zc2luZzsKPiArCS8qIG51bV9sb2NraW5nX2FkbWluX2F1dGg6Cj4g
-KwkgKiBub3QgYWxpZ25lZCB0byAxNiBiaXRzLCBzbyB1c2UgdHdvIHU4Lgo+ICsJICogc3RvcmVk
-IGluIGJpZyBlbmRpYW46Cj4gKwkgKiAwOiBNU0IKPiArCSAqIDE6IExTQgo+ICsJICovCj4gKwl1
-OCBudW1fbG9ja2luZ19hZG1pbl9hdXRoWzJdOwo+ICsJLyogbnVtX2xvY2tpbmdfdXNlcl9hdXRo
-Ogo+ICsJICogbm90IGFsaWduZWQgdG8gMTYgYml0cywgc28gdXNlIHR3byB1OC4KPiArCSAqIHN0
-b3JlZCBpbiBiaWcgZW5kaWFuOgo+ICsJICogMDogTVNCCj4gKwkgKiAxOiBMU0IKPiArCSAqLwo+
-ICsJdTggbnVtX2xvY2tpbmdfdXNlcl9hdXRoWzJdOwo+ICsJdTggaW5pdGlhbFBJTjsKPiArCXU4
-IHJldmVydGVkUElOOwo+ICsJdTggcmVzZXJ2ZWQwMTsKPiArCXUzMiByZXNlcnZlZDAyOwo+ICt9
-Owo+ICsKPiArLyogVW5pb24gb2YgZmVhdHVyZXMgdXNlZCB0byBwYXJzZSB0aGUgZGlzY292ZXJ5
-IDAgcmVzcG9uc2UgKi8KPiArc3RydWN0IGQwX2ZlYXR1cmVzIHsKPiArCXUxNiBjb2RlOwo+ICsJ
-LyoKPiArCSAqIHJfdmVyc2lvbiBiaXRzOgo+ICsJICogYml0cyA0LTc6IHZlcnNpb24KPiArCSAq
-IGJpdHMgMC0zOiByZXNlcnZlZAo+ICsJICovCj4gKwl1OCByX3ZlcnNpb247Cj4gKwl1OCBsZW5n
-dGg7Cj4gKwl1OCBmZWF0dXJlc1tdOwo+ICt9Owo+ICsKPiArc3RydWN0IGtleSAqcmVxdWVzdF91
-c2VyX2tleShjb25zdCBjaGFyICptYXN0ZXJfZGVzYywgY29uc3QgdTggKiptYXN0ZXJfa2V5LAo+
-ICsJCQkgICAgIHNpemVfdCAqbWFzdGVyX2tleWxlbik7Cj4gKwo+ICsjZW5kaWYgLyogX05WTUVf
-T1BBTF9JTlRFUk5BTF9IICovCj4gZGlmZiAtLWdpdCBhL2xpYi9zZWQtb3BhbF9rZXkuYyBiL2xp
-Yi9zZWQtb3BhbF9rZXkuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4u
-MGI0ZGUwMQo+IC0tLSAvZGV2L251bGwKPiArKysgYi9saWIvc2VkLW9wYWxfa2V5LmMKPiBAQCAt
-MCwwICsxLDQ2IEBACj4gKy8qCj4gKyAqIENvcHlyaWdodCDCqSAyMDE2IEludGVsIENvcnBvcmF0
-aW9uCj4gKyAqCj4gKyAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hh
-cmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhCj4gKyAqIGNvcHkgb2YgdGhpcyBzb2Z0d2Fy
-ZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCj4g
-KyAqIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGlu
-ZyB3aXRob3V0IGxpbWl0YXRpb24KPiArICogdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlm
-eSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsCj4gKyAqIGFuZC9vciBz
-ZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9t
-IHRoZQo+ICsgKiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhl
-IGZvbGxvd2luZyBjb25kaXRpb25zOgo+ICsgKgo+ICsgKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5v
-dGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSAoaW5jbHVkaW5nIHRoZSBuZXh0Cj4gKyAq
-IHBhcmFncmFwaCkgc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlh
-bCBwb3J0aW9ucyBvZiB0aGUKPiArICogU29mdHdhcmUuCj4gKyAqCj4gKyAqIFRIRSBTT0ZUV0FS
-RSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBS
-RVNTIE9SCj4gKyAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdB
-UlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAo+ICsgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VM
-QVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiAgSU4gTk8gRVZFTlQgU0hBTEwKPiArICog
-VEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0s
-IERBTUFHRVMgT1IgT1RIRVIKPiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBP
-RiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcKPiArICogRlJPTSwgT1VUIE9G
-IE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBE
-RUFMSU5HUwo+ICsgKiBJTiBUSEUgU09GVFdBUkUuCj4gKyAqCj4gKyAqIEF1dGhvcjoKPiArICog
-ICAgUmFmYWVsIEFudG9nbm9sbGkgPHJhZmFlbC5hbnRvZ25vbGxpQGludGVsLmNvbT4KPiArICov
-Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgva2V5Lmg+Cj4gKyNpbmNsdWRlICJzZWQtb3BhbF9pbnRl
-cm5hbC5oIgo+ICsKPiArc3RydWN0IGtleSAqcmVxdWVzdF91c2VyX2tleShjb25zdCBjaGFyICpt
-YXN0ZXJfZGVzYywgY29uc3QgdTggKiptYXN0ZXJfa2V5LAo+ICsJCQkgICAgIHNpemVfdCAqbWFz
-dGVyX2tleWxlbikKPiArewo+ICsJY29uc3Qgc3RydWN0IHVzZXJfa2V5X3BheWxvYWQgKnVwYXls
-b2FkOwo+ICsJc3RydWN0IGtleSAqdWtleTsKPiArCj4gKwl1a2V5ID0gcmVxdWVzdF9rZXkoJmtl
-eV90eXBlX3VzZXIsIG1hc3Rlcl9kZXNjLCBOVUxMKTsKPiArCWlmIChJU19FUlIodWtleSkpCj4g
-KwkJZ290byBlcnJvcjsKPiArCj4gKwlkb3duX3JlYWQoJnVrZXktPnNlbSk7Cj4gKwl1cGF5bG9h
-ZCA9IHVzZXJfa2V5X3BheWxvYWQodWtleSk7Cj4gKwkqbWFzdGVyX2tleSA9IHVwYXlsb2FkLT5k
-YXRhOwo+ICsJKm1hc3Rlcl9rZXlsZW4gPSB1cGF5bG9hZC0+ZGF0YWxlbjsKPiArZXJyb3I6Cj4g
-KwlyZXR1cm4gdWtleTsKPiArfQo+IGRpZmYgLS1naXQgYS9saWIvc2VkLmMgYi9saWIvc2VkLmMK
-PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLjA2Y2FjZDkKPiAtLS0gL2Rl
-di9udWxsCj4gKysrIGIvbGliL3NlZC5jCj4gQEAgLTAsMCArMSwzMDMgQEAKPiArI2luY2x1ZGUg
-PGxpbnV4L2Jsa2Rldi5oPgo+ICsjaW5jbHVkZSA8bGludXgvc2VkLmg+Cj4gKyNpbmNsdWRlIDxs
-aW51eC9zZWQtb3BhbC5oPgo+ICsKPiArI2lmbmRlZiBDT05GSUdfU0VEX09QQUwKPiArc3RhdGlj
-IGludCBzZWRfb3BhbF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf
-a2V5ICpzZWQpCj4gKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9v
-cGFsX2xvY2tfdW5sb2NrKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5
-ICprZXkpCj4gKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9vcGFs
-X3Rha2Vfb3duZXJzaGlwKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5
-ICprZXkpCj4gKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9vcGFs
-X2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAq
-a2V5KQo+ICsJeyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KPiArc3RhdGljIGludCBzZWRfb3BhbF9z
-ZXRfcHcoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiAr
-CXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9Cj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfYWN0aXZhdGVf
-dXNlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICsJ
-eyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KPiArc3RhdGljIGludCBzZWRfb3BhbF9yZXZlcnR0cGVy
-KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gKwl7IHJl
-dHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3NldHVwX2xvY2tpbmdf
-cmFuZ2Uoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiAr
-CXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9Cj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfYWRkdXNlcl90
-b19scihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICsJ
-eyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KPiArc3RhdGljIGludCBzZWRfb3BhbF9kb19tYnIoc3Ry
-dWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArCXsgcmV0dXJu
-IC1FT1BOT1RTVVBQOyB9Cj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfZXJhc2VfbHIoc3RydWN0IGJs
-b2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArCXsgcmV0dXJuIC1FT1BO
-T1RTVVBQOyB9Cj4gKwo+ICsjZWxzZQo+ICsKPiArc3RhdGljIGludCBzZWRfb3BhbF9zYXZlKHN0
-cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sKPiArCj4g
-KwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwK
-PiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5P
-VFNVUFA7CllvdSBtaWdodCBjb25zaWRlciBwdWxsaW5nIHRoaXMgYm9pbGVycGxhdGUgb3V0IGlu
-dG8gc29tZXRoaW5nIGxpa2U6CnN0YXRpYyBpbmxpbmUgYm9vbCBiZGV2X3NlY19jYXBhYmxlKHN0
-cnVjdCBibG9ja19kZXZpY2UgKmJkZXYpCnsKCXJldHVybiBiZGV2ICYmIGJkZXYtPmJkX2Rpc2sg
-JiYgYmRldi0+YmRfZGlzay0+Zm9wcyAmJgoJICAgICAgIGJkZXYtPmJkX2Rpc2stPmZvcHMtPnNl
-Y19vcHM7Cn0KCgo+ICsKPiArCXJldHVybiBvcGFsX3NhdmUoYmRldiwga2V5KTsKPiArfQo+ICsK
-PiArc3RhdGljIGludCBzZWRfb3BhbF9sb2NrX3VubG9jayhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpi
-ZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2
-LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rp
-c2stPmZvcHMtPnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXJldHVy
-biBvcGFsX2xvY2tfdW5sb2NrKGJkZXYsIGtleSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgc2Vk
-X29wYWxfdGFrZV9vd25lcnNoaXAoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKPiArCQkJCSAg
-IHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sKPiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJk
-X2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+
-Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9w
-YWxfdGFrZV9vd25lcnNoaXAoYmRldiwga2V5KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzZWRf
-b3BhbF9hY3RpdmF0ZV9sc3Aoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKPiArCQkJCSBzdHJ1
-Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNr
-IHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMt
-PnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXJldHVybiBvcGFsX2Fj
-dGl2YXRlX2xzcChiZGV2LCBrZXkpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3Nl
-dF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LAo+ICsJCQkgICBzdHJ1Y3Qgc2VkX2tleSAq
-a2V5KQo+ICt7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5i
-ZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCj4g
-KwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXJldHVybiBvcGFsX3NldF9uZXdfcHcoYmRl
-diwga2V5KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzZWRfb3BhbF9hY3RpdmF0ZV91c2VyKHN0
-cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQkgIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4g
-K3sKPiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2st
-PmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1
-cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfYWN0aXZhdGVfdXNlcihiZGV2LCBr
-ZXkpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3JldmVydHRwZXIoc3RydWN0IGJs
-b2NrX2RldmljZSAqYmRldiwKPiArCQkJICAgICAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sK
-PiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZv
-cHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4g
-LUVPUE5PVFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfcmV2ZXJ0dHBlcihiZGV2LCBrZXkpOwo+
-ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3NldHVwX2xyKHN0cnVjdCBibG9ja19kZXZp
-Y2UgKmJkZXYsCj4gKwkJCSAgICAgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsKPiArCWlm
-ICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAo+ICsJ
-ICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ICsJCXJldHVybiAtRU9QTk9UU1VQ
-UDsKPiArCj4gKwlyZXR1cm4gb3BhbF9zZXR1cF9sb2NraW5nX3JhbmdlKGJkZXYsIGtleSk7Cj4g
-K30KPiArCj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfYWRkdXNlcl90b19scihzdHJ1Y3QgYmxvY2tf
-ZGV2aWNlICpiZGV2LAo+ICsJCQkgICAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sKPiArCj4g
-KwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwK
-PiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5P
-VFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfYWRkX3VzZXJfdG9fbHIoYmRldiwga2V5KTsKPiAr
-fQo+ICsKPiArc3RhdGljIGludCBzZWRfb3BhbF9kb19tYnIoc3RydWN0IGJsb2NrX2RldmljZSAq
-YmRldiwKPiArCQkJICAgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsKPiArCWlmICghYmRl
-diB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFi
-ZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiAr
-Cj4gKwlyZXR1cm4gb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFkb3dfbWJyKGJkZXYsIGtleSk7Cj4g
-K30KPiArCj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfZXJhc2VfbHIoc3RydWN0IGJsb2NrX2Rldmlj
-ZSAqYmRldiwKPiArCQkJICAgICBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwo+ICsJaWYg
-KCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkg
-ICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQ
-Owo+ICsKPiArCXJldHVybiBvcGFsX2VyYXNlX2xvY2tpbmdfcmFuZ2UoYmRldiwga2V5KTsKPiAr
-fQo+ICsjZW5kaWYKPiArCj4gK2ludCBzZWRfc2F2ZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2
-LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rp
-c2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9w
-cy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChrZXkt
-PnNlZF90eXBlKSB7Cj4gKwljYXNlIE9QQUxfTE9DS19VTkxPQ0s6Cj4gKwkJcmV0dXJuIHNlZF9v
-cGFsX3NhdmUoYmRldiwga2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4g
-K30KPiArCj4gK2ludCBzZWRfbG9ja191bmxvY2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg
-c3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNr
-IHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMt
-PnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXN3aXRjaCAoa2V5LT5z
-ZWRfdHlwZSkgewo+ICsJY2FzZSBPUEFMX0xPQ0tfVU5MT0NLOgo+ICsJCXJldHVybiBzZWRfb3Bh
-bF9sb2NrX3VubG9jayhiZGV2LCBrZXkpOwo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQ
-UDsKPiArfQo+ICsKPiAraW50IHNlZF90YWtlX293bmVyc2hpcChzdHJ1Y3QgYmxvY2tfZGV2aWNl
-ICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYt
-PmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlz
-ay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNo
-IChrZXktPnNlZF90eXBlKSB7Cj4gKwljYXNlIE9QQUw6Cj4gKwkJcmV0dXJuIHNlZF9vcGFsX3Rh
-a2Vfb3duZXJzaGlwKGJkZXYsIGtleSk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIC1FT1BOT1RTVVBQ
-Owo+ICt9Cj4gKwo+ICtpbnQgc2VkX2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpi
-ZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJk
-X2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+
-Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChr
-ZXktPnNlZF90eXBlKSB7Cj4gKwljYXNlIE9QQUw6Cj4gKwkJcmV0dXJuIHNlZF9vcGFsX2FjdGl2
-YXRlX2xzcChiZGV2LCBrZXkpOwo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQUDsKPiAr
-fQo+ICsKPiAraW50IHNlZF9zZXRfcHcoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0
-IHNlZF9rZXkgKmtleSkKPiArewo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFi
-ZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19v
-cHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXN3aXRjaCAoa2V5LT5zZWRfdHlw
-ZSkgewo+ICsJY2FzZSBPUEFMX1BXOgo+ICsJCXJldHVybiBzZWRfb3BhbF9zZXRfcHcoYmRldiwg
-a2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30KPiArCj4gK2ludCBz
-ZWRfYWN0aXZhdGVfdXNlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tl
-eSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJk
-X2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiAr
-CQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7Cj4g
-KwljYXNlIE9QQUxfQUNUX1VTUjoKPiArCQlyZXR1cm4gc2VkX29wYWxfYWN0aXZhdGVfdXNlcihi
-ZGV2LCBrZXkpOwo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQUDsKPiArfQo+ICsKPiAr
-aW50IHNlZF9yZXZlcnR0cGVyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf
-a2V5ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+
-YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+
-ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsK
-PiArCWNhc2UgT1BBTDoKPiArCQlyZXR1cm4gc2VkX29wYWxfcmV2ZXJ0dHBlcihiZGV2LCBrZXkp
-Owo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQUDsKPiArfQo+ICsKPiAraW50IHNlZF9z
-ZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf
-a2V5ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+
-YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+
-ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsK
-PiArCWNhc2UgT1BBTF9MUl9TRVRVUDoKPiArCQlyZXR1cm4gc2VkX29wYWxfc2V0dXBfbHIoYmRl
-diwga2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30KPiArCj4gK2lu
-dCBzZWRfYWRkdXNlcl90b19scihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk
-X2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYt
-PmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykK
-PiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7
-Cj4gKwljYXNlIE9QQUxfTE9DS19VTkxPQ0s6Cj4gKwkJcmV0dXJuIHNlZF9vcGFsX2FkZHVzZXJf
-dG9fbHIoYmRldiwga2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30K
-PiArCj4gK2ludCBzZWRfZG9fbWJyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBz
-ZWRfa2V5ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRl
-di0+YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3Bz
-KQo+ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUp
-IHsKPiArCWNhc2UgT1BBTF9NQlJfREFUQToKPiArCQlyZXR1cm4gc2VkX29wYWxfZG9fbWJyKGJk
-ZXYsIGtleSk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICt9Cj4gKwo+ICtp
-bnQgc2VkX2VyYXNlX2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5
-ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRf
-ZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ICsJ
-CXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsKPiAr
-CWNhc2UgT1BBTDoKPiArCQlyZXR1cm4gc2VkX29wYWxfZXJhc2VfbHIoYmRldiwga2V5KTsKPiAr
-CX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30KPiAtLSAKPiAyLjcuNAo+IAoKX19f
-X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGludXgtbnZtZSBt
-YWlsaW5nIGxpc3QKTGludXgtbnZtZUBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5p
-bmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtbnZtZQo=
+Hi Rafael, Scott,
+
+
+First off, congrats on the set! It looks good so far.
+
+Just some small nits below since you have to respin it anyways :)
+
+On Mon, Oct 31, 2016@03:58:15PM -0600, Scott Bauer wrote:
+> This patch implements the necessary logic to bring an Opal
+> enabled drive out of a factory-enabled into a working
+> Opal state.
+> 
+> This patch set also enables logic to save a password to
+> be replayed during a resume from suspend. The key can be
+> saved in the driver or in the Kernel's Key managment.
+> 
+> Signed-off-by: Scott Bauer <scott.bauer at intel.com>
+> Signed-off-by: Rafael Antognolli <Rafael.Antognolli at intel.com>
+> ---
+>  lib/sed-opal.c          | 3337 +++++++++++++++++++++++++++++++++++++++++++++++
+>  lib/sed-opal_internal.h |  586 +++++++++
+>  lib/sed-opal_key.c      |   46 +
+>  lib/sed.c               |  303 +++++
+>  4 files changed, 4272 insertions(+)
+>  create mode 100644 lib/sed-opal.c
+>  create mode 100644 lib/sed-opal_internal.h
+>  create mode 100644 lib/sed-opal_key.c
+>  create mode 100644 lib/sed.c
+> 
+> diff --git a/lib/sed-opal.c b/lib/sed-opal.c
+> new file mode 100644
+> index 0000000..10b3348
+> --- /dev/null
+> +++ b/lib/sed-opal.c
+> @@ -0,0 +1,3337 @@
+> +/*
+> + * Copyright ? 2016 Intel Corporation
+> + *
+> + * Permission is hereby granted, free of charge, to any person obtaining a
+> + * copy of this software and associated documentation files (the "Software"),
+> + * to deal in the Software without restriction, including without limitation
+> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+> + * and/or sell copies of the Software, and to permit persons to whom the
+> + * Software is furnished to do so, subject to the following conditions:
+> + *
+> + * The above copyright notice and this permission notice (including the next
+> + * paragraph) shall be included in all copies or substantial portions of the
+> + * Software.
+> + *
+> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+> + * IN THE SOFTWARE.
+> + *
+> + * Authors:
+> + *    Rafael Antognolli <rafael.antognolli at intel.com>
+> + *    Scott  Bauer      <scott.bauer at intel.com>
+> + */
+> +
+> +#define pr_fmt(fmt) KBUILD_MODNAME ":OPAL: " fmt
+> +
+> +#include <linux/delay.h>
+> +#include <linux/device.h>
+> +#include <linux/kernel.h>
+> +#include <linux/list.h>
+> +#include <linux/genhd.h>
+> +#include <linux/slab.h>
+> +#include <linux/uaccess.h>
+> +#include <uapi/linux/sed-opal.h>
+> +#include <linux/sed.h>
+> +#include <linux/sed-opal.h>
+> +#include <linux/string.h>
+> +
+> +#include "sed-opal_internal.h"
+> +
+> +#define IO_BUFFER_LENGTH 2048
+> +
+> +#define MAX_TOKS 64
+> +
+> +struct opal_cmd {
+> +	struct block_device *bdev;
+> +	sec_cb *cb;
+> +	void *cb_data;
+> +
+> +	size_t pos;
+> +	u8 cmd_buf[IO_BUFFER_LENGTH * 2];
+> +	u8 resp_buf[IO_BUFFER_LENGTH * 2];
+> +	u8 *cmd;
+> +	u8 *resp;
+> +};
+> +
+> +/*
+> + * On the parsed response, we don't store again the toks that are already
+> + * stored in the response buffer. Instead, for each token, we just store a
+> + * pointer to the position in the buffer where the token starts, and the size
+> + * of the token in bytes.
+> + */
+> +struct opal_resp_tok {
+> +	const u8 *pos;
+> +	size_t len;
+> +	enum OPAL_RESPONSE_TOKEN type;
+> +	enum OPAL_ATOM_WIDTH width;
+> +	union {
+> +		u64 u;
+> +		s64 s;
+> +	} stored;
+> +};
+> +
+> +/*
+> + * From the response header it's not possible to know how many tokens there are
+> + * on the payload. So we hardcode that the maximum will be MAX_TOKS, and later
+> + * if we start dealing with messages that have more than that, we can increase
+> + * this number. This is done to avoid having to make two passes through the
+> + * response, the first one counting how many tokens we have and the second one
+> + * actually storing the positions.
+> + */
+> +struct parsed_resp {
+> +	int num;
+> +	struct opal_resp_tok toks[MAX_TOKS];
+> +};
+> +
+> +struct opal_dev;
+> +
+> +typedef void (*opal_cb)(int error, struct opal_dev *dev);
+> +
+> +typedef int (*opal_step)(struct opal_dev *dev);
+> +
+> +struct opal_completion {
+> +	struct completion cmd_completion;
+> +	int completion_status;
+> +};
+> +
+> +struct opal_dev {
+> +	struct block_device *bdev;
+> +	struct opal_completion *completion;
+> +	struct opal_lock_unlock lkul;
+> +	const opal_step *funcs;
+> +	void **func_data;
+> +	bool resume_from_suspend;
+> +	struct opal_suspend_unlk *resume_data;
+> +	size_t num_func_data;
+> +	atomic_t in_use;
+> +	sector_t start;
+> +	sector_t length;
+> +	u8 lr;
+> +	u8 key_type;
+> +	u8 key_name[OPAL_KEY_MAX];
+> +	size_t key_name_len;
+> +	u8 key[OPAL_KEY_MAX];
+> +	size_t key_len;
+> +	u16 comID;
+> +	u32 HSN;
+> +	u32 TSN;
+> +	u64 align;
+> +	u64 lowest_lba;
+> +	struct list_head node;
+> +	char disk_name[DISK_NAME_LEN];
+> +	int state;
+> +
+> +	struct opal_cmd cmd;
+> +	struct parsed_resp parsed;
+> +
+> +	size_t prev_d_len;
+> +	void *prev_data;
+> +
+> +	sec_cb *final_cb;
+> +	void *final_cb_data;
+> +	opal_step error_cb;
+> +	void *error_cb_data;
+> +	opal_cb oper_cb;
+> +};
+> +
+> +LIST_HEAD(opal_list);
+> +DEFINE_SPINLOCK(list_spinlock);
+> +
+> +static void print_buffer(const u8 *ptr, u32 length)
+> +{
+> +#ifdef DEBUG
+> +	print_hex_dump_bytes("OPAL: ", DUMP_PREFIX_OFFSET, ptr, length);
+> +	pr_debug("\n");
+> +#endif
+> +}
+> +
+> +#define TPER_SYNC_SUPPORTED BIT(0)
+> +
+> +static bool check_tper(const void *data)
+> +{
+> +	const struct d0_tper_features *tper = data;
+> +	u8 flags = tper->supported_features;
+> +
+> +	if (!(flags & TPER_SYNC_SUPPORTED)) {
+> +		pr_err("TPer sync not supported. flags = %d\n",
+> +		       tper->supported_features);
+> +		return false;
+> +	}
+> +
+> +	return true;
+> +}
+> +
+> +static bool check_SUM(const void *data)
+> +{
+> +	const struct d0_single_user_mode *sum = data;
+> +	u32 nlo = be32_to_cpu(sum->num_locking_objects);
+> +
+> +	if (nlo == 0) {
+> +		pr_err("Need at least one locking object.\n");
+> +		return false;
+> +	}
+> +
+> +	pr_debug("Number of locking objects: %d\n", nlo);
+> +
+> +	return true;
+> +}
+> +
+> +static u16 get_comID_v100(const void *data)
+> +{
+> +	const struct d0_opal_v100 *v100 = data;
+> +
+> +	return be16_to_cpu(v100->baseComID);
+> +}
+> +
+> +static u16 get_comID_v200(const void *data)
+> +{
+> +	const struct d0_opal_v200 *v200 = data;
+> +
+> +	return be16_to_cpu(v200->baseComID);
+> +}
+> +
+> +static int __opal_send_cmd(struct opal_suspend_unlk *data, u16 comID,
+> +			   void *buffer, size_t buflen, sec_cb *cb,
+> +			   void *cb_data)
+> +{
+> +	return data->ops.send(data->data, comID, TCG_SECP_01, buffer, buflen,
+> +			     cb, cb_data);
+> +}
+> +static int _opal_send_cmd(struct block_device *bdev, u16 comID,
+> +			  void *buffer, size_t buflen,
+> +			  sec_cb *cb, void *cb_data)
+> +{
+> +	const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops;
+> +
+> +	return ops->send(bdev->bd_disk->private_data, comID,
+> +			 TCG_SECP_01, buffer, buflen,
+> +			 cb, cb_data);
+> +}
+> +
+> +static int __opal_recv_cmd(struct opal_suspend_unlk *data, u16 comID,
+> +			   void *buffer, size_t buflen, sec_cb *cb,
+> +			   void *cb_data)
+> +{
+> +	return data->ops.recv(data->data, comID, TCG_SECP_01, buffer, buflen,
+> +			     cb, cb_data);
+> +}
+> +
+> +static int _opal_recv_cmd(struct block_device *bdev, u16 comID,
+> +			  void *buffer, size_t buflen,
+> +			  sec_cb *cb, void *cb_data)
+> +{
+> +	const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops;
+> +
+> +	return ops->recv(bdev->bd_disk->private_data, comID,
+> +			 TCG_SECP_01, buffer, buflen,
+> +			 cb, cb_data);
+> +}
+> +
+> +static void opal_send_cb_cont(int error, void *data)
+> +{
+> +	struct opal_dev *dev = data;
+> +	size_t buflen = IO_BUFFER_LENGTH;
+> +	void *buffer = dev->cmd.resp;
+> +	struct opal_header *hdr = buffer;
+> +
+> +	pr_debug("%s: Sent OPAL command: error=%d, outstanding=%d, minTransfer=%d\n",
+> +	       dev->disk_name, error, hdr->cp.outstandingData,
+> +	       hdr->cp.minTransfer);
+> +
+> +	if (error || hdr->cp.outstandingData == 0 ||
+> +	    hdr->cp.minTransfer != 0) {
+> +		if (dev->cmd.cb)
+> +			dev->cmd.cb(error, dev->cmd.cb_data);
+> +		return;
+> +	}
+> +
+> +	memset(buffer, 0, buflen);
+> +	if (dev->resume_from_suspend)
+> +		__opal_recv_cmd(dev->resume_data, dev->comID,
+> +				buffer, buflen, opal_send_cb_cont, dev);
+> +	else
+> +		_opal_recv_cmd(dev->bdev, dev->comID, buffer, buflen,
+> +			       opal_send_cb_cont, dev);
+> +}
+> +
+> +static void opal_send_cb(int error, void *data)
+> +{
+> +	struct opal_dev *dev = data;
+> +	size_t buflen = IO_BUFFER_LENGTH;
+> +	void *buffer = dev->cmd.resp;
+> +
+> +	if (error) {
+> +		if (dev->cmd.cb)
+> +			dev->cmd.cb(error, dev->cmd.cb_data);
+> +		return;
+> +	}
+> +
+> +	memset(buffer, 0, buflen);
+> +	if (dev->resume_from_suspend)
+> +		__opal_recv_cmd(dev->resume_data, dev->comID,
+> +				buffer, buflen, opal_send_cb_cont, dev);
+> +	else
+> +		_opal_recv_cmd(dev->bdev, dev->comID, buffer, buflen,
+> +			       opal_send_cb_cont, dev);
+> +}
+> +
+> +static int opal_send_recv(struct opal_dev *dev, sec_cb *cb, void *cb_data)
+> +{
+> +	size_t buflen = IO_BUFFER_LENGTH;
+> +	void *buffer = dev->cmd.cmd;
+> +	int ret;
+> +
+> +	dev->cmd.cb = cb;
+> +	dev->cmd.cb_data = cb_data;
+> +	if (dev->resume_from_suspend)
+> +		ret = __opal_send_cmd(dev->resume_data, dev->comID, buffer,
+> +				      buflen, opal_send_cb, dev);
+> +	else
+> +		ret = _opal_send_cmd(dev->bdev, dev->comID, buffer, buflen,
+> +				     opal_send_cb, dev);
+> +
+> +	return ret;
+> +}
+> +
+> +static void check_geometry(struct opal_dev *dev, const void *data)
+> +{
+> +	const struct d0_geometry_features *geo = data;
+> +
+> +	dev->align = geo->alignment_granularity;
+> +	dev->lowest_lba = geo->lowest_aligned_lba;
+> +}
+> +
+> +static void opal_discovery0_end(int error, void *data)
+> +{
+> +	bool foundComID = false, supported = true, single_user = false;
+> +	struct opal_dev *dev = data;
+> +	const struct d0_header *hdr;
+> +	const u8 *epos, *cpos;
+> +	u16 comID = 0;
+> +
+> +	if (error) {
+> +		pr_err("%s: Sending discovery0 failed\n", dev->disk_name);
+> +		goto err_callback;
+> +	}
+> +
+> +	epos = dev->cmd.resp;
+> +	cpos = dev->cmd.resp;
+> +	hdr = (struct d0_header *)dev->cmd.resp;
+> +
+> +	print_buffer(dev->cmd.resp, be32_to_cpu(hdr->length));
+> +
+> +	epos += be32_to_cpu(hdr->length); /* end of buffer */
+> +	cpos += sizeof(*hdr); /* current position on buffer */
+> +
+> +	while (cpos < epos && supported) {
+> +		const struct d0_features *body =
+> +			(const struct d0_features *)cpos;
+> +
+> +		switch (be16_to_cpu(body->code)) {
+> +		case FC_TPER:
+> +			supported = check_tper(body->features);
+> +			break;
+> +		case FC_SINGLEUSER:
+> +			single_user = check_SUM(body->features);
+> +			break;
+> +		case FC_GEOMETRY:
+> +			check_geometry(dev, body);
+> +			break;
+> +		case FC_LOCKING:
+> +		case FC_ENTERPRISE:
+> +		case FC_DATASTORE:
+> +			/* some ignored properties */
+> +			pr_debug("%s: Found OPAL feature description: %d\n",
+> +				 dev->disk_name, be16_to_cpu(body->code));
+> +			break;
+> +		case FC_OPALV100:
+> +			comID = get_comID_v100(body->features);
+> +			foundComID = true;
+> +			break;
+> +		case FC_OPALV200:
+> +			comID = get_comID_v200(body->features);
+> +			foundComID = true;
+> +			break;
+> +		default:
+> +			if (be16_to_cpu(body->code) > 0xbfff) {
+> +				/* vendor specific, just ignore */
+> +			} else {
+> +				pr_warn("%s: OPAL Unknown feature: %d\n",
+> +					dev->disk_name, be16_to_cpu(body->code));
+> +			}
+Small nit, how about:
+
+case 0xbfff ... 0xffff:
+	/* vendor specific, just ignore */
+	break;
+default:
+	pr_warn(...
+
+
+
+> +		}
+> +		cpos += body->length + 4;
+> +	}
+> +
+> +	if (!supported) {
+> +		pr_err("%s: Device not supported\n", dev->disk_name);
+> +		goto err_callback;
+> +	}
+> +
+> +	if (!single_user)
+> +		pr_warn("%s: Device doesn't support single user mode\n",
+> +			dev->disk_name);
+> +
+> +	if (!foundComID) {
+> +		pr_warn("%s: Could not find OPAL comID for device. OPAL kernel unlocking will be disabled\n",
+> +			dev->disk_name);
+> +		goto err_callback;
+> +	}
+> +
+> +	dev->comID = comID;
+> +
+> +err_callback:
+> +	if (dev->oper_cb)
+> +		dev->oper_cb(error, dev);
+> +}
+> +
+> +static int opal_discovery0(struct opal_dev *dev)
+> +{
+> +	memset(dev->cmd.resp, 0, IO_BUFFER_LENGTH);
+> +
+> +	if (dev->resume_from_suspend)
+> +		return __opal_recv_cmd(dev->resume_data, 0x0001,
+> +				       dev->cmd.resp, IO_BUFFER_LENGTH,
+> +				       opal_discovery0_end, dev);
+> +
+> +	return _opal_recv_cmd(dev->bdev, 0x0001, dev->cmd.resp,
+> +			      IO_BUFFER_LENGTH, opal_discovery0_end,
+> +			      dev);
+> +}
+> +
+> +static void add_token_u8(struct opal_cmd *cmd, u8 tok)
+> +{
+> +	cmd->cmd[cmd->pos++] = tok;
+> +}
+> +
+> +static ssize_t test_and_add_token_u8(struct opal_cmd *cmd, u8 tok)
+> +{
+> +	BUILD_BUG_ON(IO_BUFFER_LENGTH >= SIZE_MAX);
+> +
+> +	if (cmd->pos >= IO_BUFFER_LENGTH - 1) {
+> +		pr_err("Error adding u8: end of buffer.\n");
+> +		return -ERANGE;
+> +	}
+> +
+> +	add_token_u8(cmd, tok);
+> +
+> +	return 1;
+> +}
+> +
+> +#define TINY_ATOM_DATA_MASK GENMASK(5, 0)
+> +#define TINY_ATOM_SIGNED BIT(6)
+> +
+> +#define SHORT_ATOM_ID BIT(7)
+> +#define SHORT_ATOM_BYTESTRING BIT(5)
+> +#define SHORT_ATOM_SIGNED BIT(4)
+> +#define SHORT_ATOM_LEN_MASK GENMASK(3, 0)
+> +
+> +static void add_short_atom_header(struct opal_cmd *cmd, bool bytestring,
+> +				  bool has_sign, int len)
+> +{
+> +	u8 atom;
+> +
+> +	atom = SHORT_ATOM_ID;
+> +	atom |= bytestring ? SHORT_ATOM_BYTESTRING : 0;
+> +	atom |= has_sign ? SHORT_ATOM_SIGNED : 0;
+> +	atom |= len & SHORT_ATOM_LEN_MASK;
+> +
+> +	add_token_u8(cmd, atom);
+> +}
+> +
+> +#define MEDIUM_ATOM_ID (BIT(7) | BIT(6))
+> +#define MEDIUM_ATOM_BYTESTRING BIT(4)
+> +#define MEDIUM_ATOM_SIGNED BIT(3)
+> +#define MEDIUM_ATOM_LEN_MASK GENMASK(2, 0)
+> +
+> +static void add_medium_atom_header(struct opal_cmd *cmd, bool bytestring,
+> +				   bool has_sign, int len)
+> +{
+> +	u8 header0;
+> +
+> +	header0 = MEDIUM_ATOM_ID;
+> +	header0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0;
+> +	header0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0;
+> +	header0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK;
+> +	cmd->cmd[cmd->pos++] = header0;
+> +	cmd->cmd[cmd->pos++] = len;
+> +}
+> +
+> +static void add_token_u64(struct opal_cmd *cmd, u64 number, size_t len)
+> +{
+> +	add_short_atom_header(cmd, false, false, len);
+> +
+> +	while (len--) {
+> +		u8 n = number >> (len * 8);
+> +
+> +		add_token_u8(cmd, n);
+> +	}
+> +}
+> +
+> +static ssize_t test_and_add_token_u64(struct opal_cmd *cmd, u64 number)
+> +{
+> +	int len;
+> +	int msb;
+> +
+> +	if (!(number & ~TINY_ATOM_DATA_MASK))
+> +		return test_and_add_token_u8(cmd, number);
+> +
+> +	msb = fls(number);
+> +	len = DIV_ROUND_UP(msb, 4);
+> +
+> +	if (cmd->pos >= IO_BUFFER_LENGTH - len - 1) {
+> +		pr_err("Error adding u64: end of buffer.\n");
+> +		return -ERANGE;
+> +	}
+> +
+> +	add_token_u64(cmd, number, len);
+> +
+> +	/* return length of token plus atom */
+> +	return len + 1;
+> +}
+> +
+> +static void add_token_bytestring(struct opal_cmd *cmd,
+> +				 const u8 *bytestring, size_t len)
+> +{
+> +	memcpy(&cmd->cmd[cmd->pos], bytestring, len);
+> +	cmd->pos += len;
+> +}
+> +
+> +static ssize_t test_and_add_token_bytestring(struct opal_cmd *cmd,
+> +					     const u8 *bytestring, size_t len)
+> +{
+> +	size_t header_len = 1;
+> +	bool is_short_atom = true;
+> +
+> +	if (len & ~SHORT_ATOM_LEN_MASK) {
+> +		header_len = 2;
+> +		is_short_atom = false;
+> +	}
+> +
+> +	if (cmd->pos >= IO_BUFFER_LENGTH - len - header_len) {
+> +		pr_err("Error adding bytestring: end of buffer.\n");
+> +		return -ERANGE;
+> +	}
+> +
+> +	if (is_short_atom)
+> +		add_short_atom_header(cmd, true, false, len);
+> +	else
+> +		add_medium_atom_header(cmd, true, false, len);
+> +
+> +	add_token_bytestring(cmd, bytestring, len);
+> +
+> +	return header_len + len;
+> +}
+> +
+> +#define LOCKING_RANGE_NON_GLOBAL 0x03
+> +
+> +static int build_locking_range(u8 *buffer, size_t length, u8 lr)
+> +{
+> +	if (length < OPAL_UID_LENGTH)
+> +		return -ERANGE;
+> +
+> +	memcpy(buffer, OPALUID[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
+> +
+> +	if (lr == 0)
+> +		return 0;
+> +	buffer[5] = LOCKING_RANGE_NON_GLOBAL;
+> +	buffer[7] = lr;
+> +
+> +	return 0;
+> +}
+> +
+> +static int build_locking_user(u8 *buffer, size_t length, u8 lr)
+> +{
+> +	if (length < OPAL_UID_LENGTH)
+> +		return -ERANGE;
+> +
+> +	memcpy(buffer, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH);
+> +
+> +	buffer[7] = lr + 1;
+> +
+> +	return 0;
+> +}
+> +
+> +/*
+> + * N = number of format specifiers (1-999) to be replicated
+> + * c = u8
+> + * u = u64
+> + * s = bytestring, length
+> + *
+> + * ret = test_and_add_token_va(cmd, "c",
+> + *			       u8_val1);
+> + *
+> + * ret = test_and_add_token_va(cmd, "2c2u",
+> + *			       u8_val1, u8_val2, u64_val1, u64_val2);
+> + *
+> + * ret = test_and_add_token_va(cmd, "3s",
+> + *			       bytestring1, length1,
+> + *			       bytestring2, length2,
+> + *			       bytestring3, length3);
+> + */
+> +static int test_and_add_token_va(struct opal_cmd *cmd,
+> +				 const char *fmt, ...)
+> +{
+> +	const u8 *it = fmt, *tmp;
+> +	int ret, num = 1, sum = 0;
+> +	va_list ap;
+> +
+> +	va_start(ap, fmt);
+> +
+> +	while (*it != '\0') {
+> +		u64 tok64 = 0;
+> +		u8 tok, *bstr;
+> +		size_t len;
+> +
+> +		ret = 0;
+> +
+> +		switch (*it) {
+> +		case '1' ... '9':
+> +			tmp = it;
+> +			num = 0;
+> +			while (*tmp >= '0' && *tmp <= '9')
+> +				num = num * 10 + (*tmp++ - '0');
+> +			it = tmp;
+> +			continue;
+> +		case 'c':
+> +			while (num--) {
+> +				tok = va_arg(ap, unsigned int);
+> +				ret = test_and_add_token_u8(cmd, tok);
+> +				if (ret < 0)
+> +					goto err;
+> +			}
+> +			num = 1;
+> +			break;
+> +		case 'u':
+> +			while (num--) {
+> +				tok64 = va_arg(ap, u64);
+> +				ret = test_and_add_token_u64(cmd, tok64);
+> +				if (ret < 0)
+> +					goto err;
+> +			}
+> +			num = 1;
+> +			break;
+> +		case 's':
+> +			while (num--) {
+> +				bstr = va_arg(ap, u8 *);
+> +				len = va_arg(ap, size_t);
+> +				ret = test_and_add_token_bytestring(cmd, bstr,
+> +								    len);
+> +				if (ret < 0)
+> +					goto err;
+> +			}
+> +			num = 1;
+> +			break;
+> +		case ' ':
+> +		case '\t':
+> +			/* ignored */
+> +			break;
+> +		default:
+> +			pr_warn("Unrecognized type.\n");
+> +		}
+> +
+> +		it++;
+> +		sum += ret;
+> +	}
+> +
+> +	va_end(ap);
+> +
+> +	return sum;
+> +
+> + err:
+> +	pr_err("Token failed to be added.\n");
+> +	return ret;
+> +}
+> +
+> +static void set_comID(struct opal_cmd *cmd, u16 comID)
+> +{
+> +	struct opal_header *hdr = (struct opal_header *)cmd->cmd;
+> +
+> +	hdr->cp.extendedComID[0] = comID >> 8;
+> +	hdr->cp.extendedComID[1] = comID;
+> +	hdr->cp.extendedComID[2] = 0;
+> +	hdr->cp.extendedComID[3] = 0;
+> +}
+> +
+> +static int cmd_finalize(struct opal_cmd *cmd, u32 hsn, u32 tsn)
+> +{
+> +	struct opal_header *hdr;
+> +	int ret;
+> +
+> +	ret = test_and_add_token_va(cmd, "6c",
+> +				    OPAL_ENDOFDATA, OPAL_STARTLIST,
+> +				    0, 0, 0, OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("Error finalizing command.\n");
+> +		return -EFAULT;
+> +	}
+> +
+> +	hdr = (struct opal_header *) cmd->cmd;
+> +
+> +	hdr->pkt.TSN = cpu_to_be32(tsn);
+> +	hdr->pkt.HSN = cpu_to_be32(hsn);
+> +
+> +	hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr));
+> +	while (cmd->pos % 4) {
+> +		if (cmd->pos >= IO_BUFFER_LENGTH) {
+> +			pr_err("Error: Buffer overrun\n");
+> +			return -ERANGE;
+> +		}
+> +		cmd->cmd[cmd->pos++] = 0;
+> +	}
+> +	hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) -
+> +				      sizeof(hdr->pkt));
+> +	hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp));
+> +
+> +	return 0;
+> +}
+> +
+> +static enum OPAL_RESPONSE_TOKEN token_type(const struct parsed_resp *resp,
+> +					   int n)
+> +{
+> +	const struct opal_resp_tok *tok;
+> +
+> +	if (n >= resp->num) {
+> +		pr_err("Token number doesn't exist: %d, resp: %d\n",
+> +		       n, resp->num);
+> +		return OPAL_DTA_TOKENID_INVALID;
+> +	}
+> +
+> +	tok = &resp->toks[n];
+> +	if (tok->len == 0) {
+> +		pr_err("Token length must be non-zero\n");
+> +		return OPAL_DTA_TOKENID_INVALID;
+> +	}
+> +
+> +	return tok->type;
+> +}
+> +
+> +/*
+> + * This function returns 0 in case of invalid token. One should call
+> + * token_type() first to find out if the token is valid or not.
+> + */
+> +static enum OPAL_TOKEN response_get_token(const struct parsed_resp *resp,
+> +					  int n)
+> +{
+> +	const struct opal_resp_tok *tok;
+> +
+> +	if (n >= resp->num) {
+> +		pr_err("Token number doesn't exist: %d, resp: %d\n",
+> +		       n, resp->num);
+> +		return 0;
+> +	}
+> +
+> +	tok = &resp->toks[n];
+> +	if (tok->len == 0) {
+> +		pr_err("Token length must be non-zero\n");
+> +		return 0;
+> +	}
+> +
+> +	return tok->pos[0];
+> +}
+> +
+> +static size_t response_parse_tiny(struct opal_resp_tok *tok,
+> +				  const u8 *pos)
+> +{
+> +	tok->pos = pos;
+> +	tok->len = 1;
+> +	tok->width = OPAL_WIDTH_TINY;
+> +
+> +	if (pos[0] & TINY_ATOM_SIGNED) {
+> +		tok->type = OPAL_DTA_TOKENID_SINT;
+> +	} else {
+> +		tok->type = OPAL_DTA_TOKENID_UINT;
+> +		tok->stored.u = pos[0] & 0x3f;
+> +	}
+> +
+> +	return tok->len;
+> +}
+> +
+> +static size_t response_parse_short(struct opal_resp_tok *tok,
+> +				   const u8 *pos)
+> +{
+> +	tok->pos = pos;
+> +	tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1;
+> +	tok->width = OPAL_WIDTH_SHORT;
+> +
+> +	if (pos[0] & SHORT_ATOM_BYTESTRING) {
+> +		tok->type = OPAL_DTA_TOKENID_BYTESTRING;
+> +	} else if (pos[0] & SHORT_ATOM_SIGNED) {
+> +		tok->type = OPAL_DTA_TOKENID_SINT;
+> +	} else {
+> +		u64 u_integer = 0;
+> +		int i, b = 0;
+> +
+> +		tok->type = OPAL_DTA_TOKENID_UINT;
+> +		if (tok->len > 9)
+Should this be len > 8 or len >= 9 ?
+
+> +			pr_warn("uint64 with more than 8 bytes\n");
+> +		for (i = tok->len - 1; i > 0; i--) {
+> +			u_integer |= ((u64)pos[i] << (8 * b));
+> +			b++;
+> +		}
+It doesn't look particularly safe to keep using this driver on a drive
+if it returns a len > 8. But the specs do allow 16-byte data in a short
+atom, so maybe we should bail on allowing the driver to manage the
+drive, or change the types to some 16-byte type?
+
+> +		tok->stored.u = u_integer;
+> +	}
+> +
+> +	return tok->len;
+> +}
+> +
+> +static size_t response_parse_medium(struct opal_resp_tok *tok,
+> +				    const u8 *pos)
+> +{
+> +	tok->pos = pos;
+> +	tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2;
+> +	tok->width = OPAL_WIDTH_MEDIUM;
+> +
+> +	if (pos[0] & MEDIUM_ATOM_BYTESTRING)
+> +		tok->type = OPAL_DTA_TOKENID_BYTESTRING;
+> +	else if (pos[0] & MEDIUM_ATOM_SIGNED)
+> +		tok->type = OPAL_DTA_TOKENID_SINT;
+> +	else
+> +		tok->type = OPAL_DTA_TOKENID_UINT;
+> +
+> +	return tok->len;
+> +}
+> +
+> +#define LONG_ATOM_ID (BIT(7) | BIT(6) | BIT(5))
+> +#define LONG_ATOM_BYTESTRING BIT(1)
+> +#define LONG_ATOM_SIGNED BIT(0)
+> +static size_t response_parse_long(struct opal_resp_tok *tok,
+> +				  const u8 *pos)
+> +{
+> +	tok->pos = pos;
+> +	tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4;
+> +	tok->width = OPAL_WIDTH_LONG;
+> +
+> +	if (pos[0] & LONG_ATOM_BYTESTRING)
+> +		tok->type = OPAL_DTA_TOKENID_BYTESTRING;
+> +	else if (pos[0] & LONG_ATOM_SIGNED)
+> +		tok->type = OPAL_DTA_TOKENID_SINT;
+> +	else
+> +		tok->type = OPAL_DTA_TOKENID_UINT;
+> +
+> +	return tok->len;
+> +}
+> +
+> +static size_t response_parse_token(struct opal_resp_tok *tok,
+> +				   const u8 *pos)
+> +{
+> +	tok->pos = pos;
+> +	tok->len = 1;
+> +	tok->type = OPAL_DTA_TOKENID_TOKEN;
+> +	tok->width = OPAL_WIDTH_TOKEN;
+> +
+> +	return tok->len;
+> +}
+> +
+> +static int response_parse(const u8 *buf, size_t length,
+> +			  struct parsed_resp *resp)
+> +{
+> +	const struct opal_header *hdr;
+> +	struct opal_resp_tok *iter;
+> +	int ret, num_entries = 0;
+> +	u32 cpos = 0, total;
+> +	size_t token_length;
+> +	const u8 *pos;
+> +
+> +	if (!buf)
+> +		return -EFAULT;
+> +
+> +	if (!resp)
+> +		return -EFAULT;
+> +
+> +	hdr = (struct opal_header *)buf;
+> +	pos = buf;
+> +	pos += sizeof(*hdr);
+> +
+> +	pr_debug("Response size: cp: %d, pkt: %d, subpkt: %d\n",
+> +		 be32_to_cpu(hdr->cp.length),
+> +		 be32_to_cpu(hdr->pkt.length),
+> +		 be32_to_cpu(hdr->subpkt.length));
+> +
+> +	if ((hdr->cp.length == 0)
+> +	    || (hdr->pkt.length == 0)
+> +	    || (hdr->subpkt.length == 0)) {
+> +		pr_err("Bad header length. cp: %d, pkt: %d, subpkt: %d\n",
+> +		       be32_to_cpu(hdr->cp.length),
+> +		       be32_to_cpu(hdr->pkt.length),
+> +		       be32_to_cpu(hdr->subpkt.length));
+> +		print_buffer(pos, sizeof(*hdr));
+> +		ret = -EINVAL;
+> +		goto err;
+> +	}
+> +
+> +	if (pos > buf + length) {
+> +		ret = -EFAULT;
+> +		goto err;
+> +	}
+> +
+> +	iter = resp->toks;
+> +	total = be32_to_cpu(hdr->subpkt.length);
+> +	print_buffer(pos, total);
+> +	while (cpos < total) {
+> +		if (!(pos[0] & 0x80)) /* tiny atom */
+> +			token_length = response_parse_tiny(iter, pos);
+> +		else if (!(pos[0] & 0x40)) /* short atom */
+> +			token_length = response_parse_short(iter, pos);
+> +		else if (!(pos[0] & 0x20)) /* medium atom */
+> +			token_length = response_parse_medium(iter, pos);
+> +		else if (!(pos[0] & 0x10)) /* long atom */
+> +			token_length = response_parse_long(iter, pos);
+> +		else /* TOKEN */
+> +			token_length = response_parse_token(iter, pos);
+> +
+> +		pos += token_length;
+> +		cpos += token_length;
+> +		iter++;
+> +		num_entries++;
+> +	}
+> +
+> +	if (num_entries == 0) {
+> +		pr_err("Couldn't parse response.\n");
+> +		ret = -EINVAL;
+> +		goto err;
+> +	}
+> +	resp->num = num_entries;
+> +
+> +	return 0;
+> +err:
+> +	return ret;
+> +}
+> +
+> +static size_t response_get_string(const struct parsed_resp *resp, int n,
+> +				  const char **store)
+> +{
+> +	*store = NULL;
+> +	if (!resp) {
+> +		pr_err("Response is NULL\n");
+> +		return 0;
+> +	}
+> +
+> +	if (n > resp->num) {
+> +		pr_err("Response has %d tokens. Can't access %d\n",
+> +		       resp->num, n);
+> +		return 0;
+> +	}
+> +
+> +	if (resp->toks[n].type != OPAL_DTA_TOKENID_BYTESTRING) {
+> +		pr_err("Token is not a byte string!\n");
+> +		return 0;
+> +	}
+> +
+> +	*store = resp->toks[n].pos + 1;
+> +	return resp->toks[n].len - 1;
+> +}
+> +
+> +static u64 response_get_u64(const struct parsed_resp *resp, int n)
+> +{
+> +	if (!resp) {
+> +		pr_err("Response is NULL\n");
+> +		return 0;
+> +	}
+> +
+> +	if (n > resp->num) {
+> +		pr_err("Response has %d tokens. Can't access %d\n",
+> +		       resp->num, n);
+> +		return 0;
+> +	}
+> +
+> +	if (resp->toks[n].type != OPAL_DTA_TOKENID_UINT) {
+> +		pr_err("Token is not unsigned it: %d\n",
+> +		       resp->toks[n].type);
+> +		return 0;
+> +	}
+> +
+> +	if (!((resp->toks[n].width == OPAL_WIDTH_TINY) ||
+> +	      (resp->toks[n].width == OPAL_WIDTH_SHORT))) {
+> +		pr_err("Atom is not short or tiny: %d\n",
+> +		       resp->toks[n].width);
+> +		return 0;
+> +	}
+> +
+> +	return resp->toks[n].stored.u;
+> +}
+> +
+> +static u8 response_status(const struct parsed_resp *resp)
+> +{
+> +	if ((token_type(resp, 0) == OPAL_DTA_TOKENID_TOKEN)
+> +	    && (response_get_token(resp, 0) == OPAL_ENDOFSESSION)) {
+> +		return 0;
+> +	}
+> +
+> +	if (resp->num < 5)
+> +		return DTAERROR_NO_METHOD_STATUS;
+> +
+> +	if ((token_type(resp, resp->num - 1) != OPAL_DTA_TOKENID_TOKEN) ||
+> +	    (token_type(resp, resp->num - 5) != OPAL_DTA_TOKENID_TOKEN) ||
+> +	    (response_get_token(resp, resp->num - 1) != OPAL_ENDLIST) ||
+> +	    (response_get_token(resp, resp->num - 5) != OPAL_STARTLIST))
+> +		return DTAERROR_NO_METHOD_STATUS;
+> +
+> +	return response_get_u64(resp, resp->num - 4);
+> +}
+> +
+> +/* Parses and checks for errors */
+> +static int parse_and_check_status(struct opal_dev *dev)
+> +{
+> +	struct opal_cmd *cmd;
+> +	int error;
+> +
+> +	cmd = &dev->cmd;
+> +	print_buffer(cmd->cmd, cmd->pos);
+> +
+> +	error = response_parse(cmd->resp, IO_BUFFER_LENGTH, &dev->parsed);
+> +	if (error) {
+> +		pr_err("%s: Couldn't parse response.\n", dev->disk_name);
+> +		goto err_return;
+> +	}
+> +
+> +	error = response_status(&dev->parsed);
+> +	if (error)
+> +		pr_err("%s: Response Status: %d\n", dev->disk_name,
+> +		       error);
+> +
+> + err_return:
+> +	return error;
+> +}
+> +
+> +static void clear_opal_cmd(struct opal_cmd *cmd)
+> +{
+> +	cmd->pos = sizeof(struct opal_header);
+> +	memset(cmd->cmd, 0, IO_BUFFER_LENGTH);
+> +	cmd->cb = NULL;
+> +	cmd->cb_data = NULL;
+> +}
+> +
+> +static void start_opal_session_cont(int error, void *data)
+> +{
+> +	struct opal_dev *dev = data;
+> +	u32 HSN, TSN;
+> +
+> +	if (error)
+> +		goto err_return;
+> +
+> +	error = parse_and_check_status(dev);
+> +	if (error)
+> +		goto err_return;
+> +
+> +	HSN = response_get_u64(&dev->parsed, 4);
+> +	TSN = response_get_u64(&dev->parsed, 5);
+> +
+> +	if (HSN == 0 && TSN == 0) {
+> +		pr_err("%s: Couldn't authenticate session\n", dev->disk_name);
+> +		error = -EPERM;
+> +		goto err_return;
+> +	}
+> +
+> +	dev->HSN = HSN;
+> +	dev->TSN = TSN;
+> +
+> +err_return:
+> +	if (dev->oper_cb)
+> +		dev->oper_cb(error, dev);
+> +}
+> +
+> +static int get_opal_key(struct opal_dev *dev)
+> +{
+> +	struct key *ukey = NULL;
+> +	const u8 *tmpkey = NULL;
+> +	size_t tmplen;
+> +	int ret = 0;
+> +
+> +	if (dev->key_type == OPAL_KEY_PLAIN) {
+> +		tmpkey = dev->key_name;
+> +		tmplen = dev->key_name_len;
+> +	} else if (dev->key_type == OPAL_KEY_KEYRING) {
+> +		ukey = request_user_key(dev->key_name, &tmpkey, &tmplen);
+> +		if (IS_ERR(ukey)) {
+> +			pr_err("%s: Can't retrieve key: %ld\n", dev->disk_name,
+> +			       PTR_ERR(ukey));
+> +			return PTR_ERR(ukey);
+> +		}
+> +	} else {
+> +		pr_err("Requested invalid key type: %d\n", dev->key_type);
+> +		return -EINVAL;
+> +	}
+> +
+> +	if (tmplen > OPAL_KEY_MAX) {
+> +		pr_err("Requested key with invalid size: %zd\n", tmplen);
+> +		ret = -EINVAL;
+> +		goto err_exit;
+> +	}
+> +
+> +	dev->key_len = tmplen;
+> +	if (!memcpy(dev->key, tmpkey, tmplen)) {
+> +		pr_err("Error when copying key");
+> +		ret = -EFAULT;
+> +		goto err_exit;
+> +	}
+> +
+> +err_exit:
+> +	key_put(ukey);
+> +
+> +	return 0;
+> +}
+> +
+> +static void clean_opal_key(struct opal_dev *dev)
+> +{
+> +	memset(dev->key, 0, OPAL_KEY_MAX);
+> +	dev->key_len = 0;
+> +}
+> +
+> +static inline void clean_function_data(struct opal_dev *dev)
+> +{
+> +		dev->func_data = NULL;
+> +		dev->num_func_data = 0;
+> +}
+> +
+> +/* This is a generic continue fn.
+> + * We use this when we don't care about the response data
+> + * and simply want to check the status and continue.
+> + */
+> +static void generic_cont(int error, void *data)
+> +{
+> +	struct opal_dev *dev = data;
+> +
+> +	if (error)
+> +		goto err_return;
+> +
+> +	error = parse_and_check_status(dev);
+> +
+> + err_return:
+> +	if (dev->oper_cb)
+> +		dev->oper_cb(error, dev);
+> +}
+
+How about:
+
+static void generic_cont(int error, void *data)
+{
+	struct opal_dev *dev = data;
+
+	if (!error)
+		error = parse_and_check_status(dev);
+
+	if (dev->oper_cb)
+		dev->oper_cb(error, dev);
+}
+
+> +
+> +static void end_session_cont(int error, void *data)
+> +{
+> +	struct opal_dev *dev = data;
+> +
+> +	dev->HSN = 0;
+> +	dev->TSN = 0;
+> +	generic_cont(error, data);
+> +}
+> +
+> +static int finalize_and_send(struct opal_dev *dev, struct opal_cmd *cmd,
+> +			     sec_cb cont)
+> +{
+> +	int ret;
+> +
+> +	ret = cmd_finalize(cmd, dev->HSN, dev->TSN);
+> +	if (ret) {
+> +		pr_err("%s: Error finalizing command buffer: %d\n",
+> +		       dev->disk_name, ret);
+> +		return ret;
+> +	}
+> +
+> +	print_buffer(cmd->cmd, cmd->pos);
+> +
+> +	ret = opal_send_recv(dev, cont, dev);
+> +	if (ret)
+> +		pr_err("%s: Error running command: %d\n",
+> +		       dev->disk_name, ret);
+> +
+> +	return ret;
+> +}
+> +
+> +static int wait_for_cmd_completion(struct opal_completion *completion)
+> +{
+> +	wait_for_completion_interruptible(&completion->cmd_completion);
+> +	return completion->completion_status;
+> +}
+> +
+> +static int gen_key(struct opal_dev *dev)
+> +{
+> +	const u8 *method;
+> +	u8 uid[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len));
+> +	method = OPALMETHOD[OPAL_GENKEY];
+> +	kfree(dev->prev_data);
+> +	dev->prev_data = NULL;
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 2c",
+> +				    OPAL_CALL,
+> +				    uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_ENDLIST);
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building gen key command\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static void get_active_key_cont(int error, void *data)
+> +{
+> +	struct opal_dev *dev = data;
+> +	const char *activekey;
+> +	size_t keylen;
+> +
+> +	if (error)
+> +		goto err_return;
+> +
+> +	error = parse_and_check_status(dev);
+> +	if (error)
+> +		goto err_return;
+> +	keylen = response_get_string(&dev->parsed, 4, &activekey);
+> +	if (!activekey) {
+> +		pr_err("%s: Couldn't extract the Activekey from the response\n",
+> +		       __func__);
+> +		error = 0x0A;
+> +		goto err_return;
+> +	}
+> +	dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL);
+> +
+> +	if (!dev->prev_data)
+> +		error = -ENOMEM;
+> +
+> +	dev->prev_d_len = keylen;
+> +
+> +err_return:
+> +	if (dev->oper_cb)
+> +		dev->oper_cb(error, dev);
+> +}
+> +
+> +static int get_active_key(struct opal_dev *dev)
+> +{
+> +	const u8 *method;
+> +	u8 uid[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	method = OPALMETHOD[OPAL_GET];
+> +
+> +	ret = build_locking_range(uid, sizeof(uid), dev->lr);
+> +	if (ret < 0) {
+> +		pr_err("%s: Can't build locking range\n", dev->disk_name);
+> +		return -EINVAL;
+> +	}
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 6c 4c 2c",
+> +				    OPAL_CALL,
+> +				    uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_03, /* startCloumn */
+> +				    OPAL_TINY_UINT_10, /* ActiveKey */
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_04, /* endColumn */
+> +				    OPAL_TINY_UINT_10, /* ActiveKey */
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_ENDLIST,
+> +				    OPAL_ENDLIST);
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building get active key command\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, get_active_key_cont);
+> +}
+> +
+> +static int setup_locking_range(struct opal_dev *dev)
+> +{
+> +	const u8 *method;
+> +	u8 uid[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	struct opal_user_lr_setup *setup;
+> +	int ret;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	method = OPALMETHOD[OPAL_SET];
+> +	ret = build_locking_range(uid, sizeof(uid), dev->lr);
+> +	if (ret < 0) {
+> +		pr_err("%s: Can't build locking range\n", dev->disk_name);
+> +		return -EINVAL;
+> +	}
+> +	setup = dev->func_data[dev->state - 1];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s  4c 2cuc 2cuc 2cuc 2cu 4c",
+> +				    OPAL_CALL,
+> +				    uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_VALUES,
+> +				    OPAL_STARTLIST,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_03, /* Range Start */
+> +				    setup->range_start,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_04, /* Range Length */
+> +				    setup->range_length,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_05, /* ReadLockEnabled */
+> +				    !!setup->RLE,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_06, /* WriteLockEnabled */
+> +				    !!setup->WLE,
+> +
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST);
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building Setup Locking range command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static int start_adminsp_opal_session(struct opal_dev *dev,
+> +				      enum OPAL_UID auth,
+> +				      const char *key,
+> +				      u8 key_len)
+> +{
+> +	const u8 *method, *smuid, *admin_sp, *hsa;
+> +	struct opal_cmd *cmd;
+> +	u32 HSN;
+> +	int ret;
+> +
+> +	if (key == NULL && auth != OPAL_ANYBODY_UID) {
+> +		pr_err("%s: Attempted to open ADMIN_SP Session without a Host" \
+> +		       "Challenge, and not as the Anybody UID\n", __func__);
+> +		return 1;
+> +	}
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +
+> +	set_comID(cmd, dev->comID);
+> +	HSN = 0x41;
+> +
+> +	smuid = OPALUID[OPAL_SMUID_UID];
+> +	method = OPALMETHOD[OPAL_STARTSESSION];
+> +	admin_sp = OPALUID[OPAL_ADMINSP_UID];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s cusc",
+> +				    OPAL_CALL,
+> +				    smuid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +				    OPAL_STARTLIST,
+> +				    HSN,
+> +				    admin_sp, OPAL_UID_LENGTH,
+> +				    OPAL_TINY_UINT_01);
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building start adminsp session command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	switch (auth) {
+> +	case OPAL_ANYBODY_UID:
+> +		/* nothing left to do for anybody, just end and finalize */
+> +		ret = test_and_add_token_va(cmd, "c",
+> +					    OPAL_ENDLIST);
+> +		break;
+> +	case OPAL_SID_UID:
+> +		hsa = OPALUID[OPAL_SID_UID];
+> +		ret = test_and_add_token_va(cmd, "2c s 3c s 2c",
+> +					    OPAL_STARTNAME,
+> +					    OPAL_TINY_UINT_00, /* HostChallenge */
+> +					    key, key_len,
+> +					    OPAL_ENDNAME,
+> +					    OPAL_STARTNAME,
+> +					    OPAL_TINY_UINT_03, /* HostSignAuth */
+> +					    hsa, OPAL_UID_LENGTH,
+> +					    OPAL_ENDNAME,
+> +					    OPAL_ENDLIST);
+> +		break;
+> +	default:
+> +		pr_err("Cannot start Admin SP session with auth %d\n", auth);
+> +		return 1;
+> +	}
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building start adminsp session command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, start_opal_session_cont);
+> +}
+> +
+> +static int start_anybodyASP_opal_session(struct opal_dev *dev)
+> +{
+> +	return start_adminsp_opal_session(dev, OPAL_ANYBODY_UID, NULL, 0);
+> +}
+> +
+> +static int start_SIDASP_opal_session(struct opal_dev *dev)
+> +{
+> +	int ret;
+> +	const u8 *key = dev->prev_data;
+> +
+> +	if (!key)
+> +		ret = start_adminsp_opal_session(dev, OPAL_SID_UID, dev->key,
+> +						 dev->key_len);
+> +	else {
+> +		ret = start_adminsp_opal_session(dev, OPAL_SID_UID, key,
+> +						 dev->prev_d_len);
+> +		kfree(key);
+> +		dev->prev_data = NULL;
+> +	}
+> +	return ret;
+> +}
+> +
+> +static int start_lockingsp_opal_session(struct opal_dev *dev,
+> +					enum OPAL_UID auth, const u8 *key,
+> +					u8 key_len)
+> +{
+> +
+> +	const u8 *method, *smuid, *locking_sp, *hsa;
+> +	struct opal_cmd *cmd;
+> +	size_t klen = key_len;
+> +	u32 HSN;
+> +	int ret;
+> +
+> +	if (key == NULL) {
+> +		pr_err("Cannot start Locking SP session without a key\n");
+> +		return -EINVAL;
+> +	}
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +
+> +	set_comID(cmd, dev->comID);
+> +	HSN = 0x41;
+> +
+> +	smuid = OPALUID[OPAL_SMUID_UID];
+> +	method = OPALMETHOD[OPAL_STARTSESSION];
+> +	locking_sp = OPALUID[OPAL_LOCKINGSP_UID];
+> +	hsa = OPALUID[auth];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s cusc 2csc 2csc c",
+> +				    OPAL_CALL,
+> +				    smuid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    HSN,
+> +				    locking_sp, OPAL_UID_LENGTH,
+> +				    OPAL_TINY_UINT_01,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_00, /* HostChallenge */
+> +				    key, klen,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_03, /* Host Sign Authority */
+> +				    hsa, OPAL_UID_LENGTH,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building start adminsp session command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +	return finalize_and_send(dev, cmd, start_opal_session_cont);
+> +}
+> +
+> +static inline int start_admin1LSP_opal_session(struct opal_dev *dev)
+> +{
+> +	return start_lockingsp_opal_session(dev, OPAL_ADMIN1_UID,
+> +					    dev->key, dev->key_len);
+> +}
+> +
+> +static int start_auth_opal_session(struct opal_dev *dev)
+> +{
+> +	const u8 *method, *smuid, *locking_sp;
+> +	u8 lk_ul_user[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	u32 HSN;
+> +	int ret;
+> +	struct opal_user_info *uinfo;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +
+> +	set_comID(cmd, dev->comID);
+> +
+> +	HSN = 0x41;
+Can we #define this; it's used a few other places and is magicky
+
+> +
+> +	uinfo = dev->func_data[dev->state - 1];
+> +
+> +	smuid = OPALUID[OPAL_SMUID_UID];
+> +	method = OPALMETHOD[OPAL_STARTSESSION];
+> +	locking_sp = OPALUID[OPAL_LOCKINGSP_UID];
+> +
+> +	if (uinfo->SUM) {
+> +		ret = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
+> +					 dev->lr);
+> +		if (ret < 0) {
+> +			pr_err("%s: Can't build locking user\n",
+> +			       dev->disk_name);
+> +			return ret;
+> +		}
+> +	} else if (uinfo->who != OPAL_ADMIN1 && !uinfo->SUM) {
+> +		ret = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
+> +					 uinfo->who - 1);
+> +		if (ret < 0) {
+> +			pr_err("%s: Can't build locking user\n",
+> +			       dev->disk_name);
+> +			return ret;
+> +		}
+> +	} else
+> +		memcpy(lk_ul_user, OPALUID[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);
+> +
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s cus3cs3c s 2c",
+> +				    OPAL_CALL,
+> +				    smuid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    HSN,
+> +				    locking_sp, OPAL_UID_LENGTH,
+> +				    OPAL_TINY_UINT_01,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_00,
+> +				    dev->key, dev->key_len,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_03,
+> +
+> +				    lk_ul_user, OPAL_UID_LENGTH,
+> +
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building STARTSESSION command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, start_opal_session_cont);
+> +}
+> +
+> +static int revert_tper(struct opal_dev *dev)
+> +{
+> +	const u8 *method, *smuid;
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +
+> +	set_comID(cmd, dev->comID);
+> +
+> +	smuid = OPALUID[OPAL_ADMINSP_UID];
+> +	method = OPALMETHOD[OPAL_REVERT];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 2c",
+> +				    OPAL_CALL,
+> +				    smuid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +				    OPAL_STARTLIST,
+> +				    OPAL_ENDLIST);
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building REVERT TPER command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static int internal_activate_user(struct opal_dev *dev)
+> +{
+> +	const u8 *method;
+> +	u8 uid[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +	struct opal_activate_user *act;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	act = dev->func_data[dev->state - 1];
+> +
+> +	memcpy(uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH);
+> +	uid[7] = act->who.who;
+> +
+> +	method = OPALMETHOD[OPAL_SET];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 3c c 4c 3c",
+> +				    OPAL_CALL,
+> +				    uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_01, /* Values */
+> +
+> +				    OPAL_STARTLIST,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_05, /* Enabled */
+> +				    OPAL_TINY_UINT_01, /* True */
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_ENDLIST,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building Activate UserN command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static int erase_locking_range(struct opal_dev *dev)
+> +{
+> +	const u8 *method;
+> +	u8 uid[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	method = OPALMETHOD[OPAL_ERASE];
+> +
+> +	if (build_locking_range(uid, sizeof(uid), dev->lr) < 0) {
+> +		pr_err("%s: Can't build locking range\n", dev->disk_name);
+> +		return -EINVAL;
+> +	}
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 2c",
+> +				    OPAL_CALL,
+> +				    uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building Erase Locking Range Cmmand.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static int set_mbr_done(struct opal_dev *dev)
+> +{
+> +	const u8 *method, *uid;
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +
+> +	u8 mbr_done_tf = *(u8 *)dev->func_data[dev->state - 1];
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	method = OPALMETHOD[OPAL_SET];
+> +	uid = OPALUID[OPAL_MBRCONTROL];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 3c 6c 2c",
+> +				    OPAL_CALL,
+> +				    uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_VALUES,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_02, /* Done */
+> +				    mbr_done_tf,       /* Done T or F */
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST,
+> +
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST);
+> +	if (ret < 0) {
+> +		pr_err("%s: Error Building set MBR Dont/Not done command\n",
+s/Dont/Done/ ?
+
+
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static int set_mbr_enable_disable(struct opal_dev *dev)
+> +{
+> +	const u8 *method, *uid;
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +
+> +	u8 mbr_en_dis = *(u8 *)dev->func_data[dev->state - 1];
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	method = OPALMETHOD[OPAL_SET];
+> +	uid = OPALUID[OPAL_MBRCONTROL];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 3c 6c 2c",
+> +				    OPAL_CALL,
+> +				    uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_VALUES,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_01, /* Enable */
+> +				    mbr_en_dis,        /* Enable or Disable */
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST,
+> +
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST);
+> +	if (ret < 0) {
+> +		pr_err("%s: Error Building set MBR Dont/Not done command\n",
+s/Dont/Done/ ?
+
+
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static int set_new_pw(struct opal_dev *dev)
+> +{
+> +	const u8 *method;
+> +	u8 cpin_uid[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +	struct opal_new_pw *pw;
+> +	size_t key_len;
+> +	u8 *key;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	pw = dev->func_data[dev->state - 1];
+> +	key = pw->new_pin.key;
+> +	key_len = pw->new_pin.key_len;
+> +	memcpy(cpin_uid, OPALUID[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);
+> +
+> +	if (pw->user_for_pw != OPAL_ADMIN1) {
+> +		cpin_uid[5] = 0x03;
+> +		if (pw->who.SUM)
+> +			cpin_uid[7] = pw->new_pin.lr + 1;
+> +		else
+> +			cpin_uid[7] = pw->user_for_pw;
+> +	}
+> +
+> +	method = OPALMETHOD[OPAL_SET];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 3c 3cs2c 2c",
+> +				    OPAL_CALL,
+> +				    cpin_uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_01, /* Values */
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_03, /* PIN */
+> +				    key, key_len,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST,
+> +
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building SET AMIN1 PIN command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static int set_sid_cpin_pin(struct opal_dev *dev)
+> +{
+> +	const u8 *method, *cpin_uid;
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	cpin_uid = OPALUID[OPAL_C_PIN_SID];
+> +	method = OPALMETHOD[OPAL_SET];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 2c 4cs2c 2c",
+> +				    OPAL_CALL,
+> +				    cpin_uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +
+> +				    OPAL_TINY_UINT_01, /* Values */
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_03, /* PIN */
+> +				    dev->key, dev->key_len,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST,
+> +
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building SET CPIN PIN command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static void query_locking_range_cont(int error, void *data)
+> +{
+> +	struct opal_dev *dev = data;
+> +
+> +	if (error)
+> +		goto err_return;
+> +
+> +	error = parse_and_check_status(dev);
+> +	if (error)
+> +		goto err_return;
+> +
+> +	dev->start = response_get_u64(&dev->parsed, 4);
+> +	dev->length = response_get_u64(&dev->parsed, 8);
+> +
+> +err_return:
+> +	if (dev->oper_cb)
+> +		dev->oper_cb(error, dev);
+> +}
+> +
+> +static int query_locking_range(struct opal_dev *dev)
+> +{
+> +	u8 lr_buffer[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	const u8 *method;
+> +	int ret;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +
+> +	method = OPALMETHOD[OPAL_GET];
+> +
+> +	if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) {
+> +		pr_err("%s: Can't build locking range\n", dev->disk_name);
+> +		return -EINVAL;
+> +	}
+> +
+> +	set_comID(cmd, dev->comID);
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 12c",
+> +				    OPAL_CALL,
+> +				    lr_buffer, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_STARTCOLUMN,
+> +				    OPAL_RANGESTART,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_ENDCOLUMN,
+> +				    OPAL_RANGELENGTH,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST,
+> +				    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building GET Locking Range command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, query_locking_range_cont);
+> +}
+> +
+> +static int add_user_to_lr(struct opal_dev *dev)
+> +{
+> +	u8 lr_buffer[OPAL_UID_LENGTH];
+> +	u8 user_uid[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	const u8 *method;
+> +	struct opal_lock_unlock *lkul;
+> +	int ret;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	method = OPALMETHOD[OPAL_SET];
+> +
+> +	lkul = dev->func_data[dev->state - 1];
+> +
+> +	memcpy(lr_buffer, OPALUID[OPAL_LOCKINGRANGE_ACE_RDLOCKED],
+> +	       OPAL_UID_LENGTH);
+> +
+> +	if (lkul->l_state == OPAL_RW)
+> +		memcpy(lr_buffer, OPALUID[OPAL_LOCKINGRANGE_ACE_WRLOCKED],
+> +		       OPAL_UID_LENGTH);
+> +
+> +	lr_buffer[7] = dev->lr;
+> +
+> +	memcpy(user_uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH);
+> +	user_uid[7] = lkul->authority.who;
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 3c 3c 2c 2sc c2sc cs2c 5c",
+> +				    OPAL_CALL,
+> +				    lr_buffer, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_01, /* Values */
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_03, /* BooleanExpr */
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +
+> +				    OPALUID[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
+> +				    OPAL_UID_LENGTH_HALF,
+> +				    user_uid, OPAL_UID_LENGTH,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPALUID[OPAL_HALF_UID_AUTHORITY_OBJ_REF],
+> +				    OPAL_UID_LENGTH_HALF,
+> +				    user_uid, OPAL_UID_LENGTH,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPALUID[OPAL_HALF_UID_BOOLEAN_ACE],
+> +				    OPAL_UID_LENGTH_HALF,
+> +				    OPAL_TINY_UINT_01,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_ENDLIST,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST);
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building add user to locking range command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static int lock_unlock_locking_range(struct opal_dev *dev)
+> +{
+> +	u8 lr_buffer[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	const u8 *method;
+> +	struct opal_lock_unlock *lkul;
+> +	int ret;
+> +	u8 read_locked = 1, write_locked = 1;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	method = OPALMETHOD[OPAL_SET];
+> +	lkul = dev->func_data[dev->state - 1];
+> +	if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) {
+> +		pr_err("%s: Can't build locking range\n", dev->disk_name);
+> +		return -EINVAL;
+> +	}
+> +
+> +	switch (lkul->l_state) {
+> +	case OPAL_RO:
+> +		read_locked = 0;
+> +		write_locked = 1;
+> +		break;
+> +	case OPAL_RW:
+> +		read_locked = 0;
+> +		write_locked = 0;
+> +		break;
+> +	case OPAL_LK:
+> +		/* vars are initalized to locked */
+> +		break;
+> +	default:
+> +		pr_err("Tried to set an invalid locking state... returning to uland\n");
+> +		return 1;
+> +	}
+> +
+> +	ret = test_and_add_token_va(cmd, "c2sc 3c 4c 4c 3c",
+> +				    OPAL_CALL,
+> +				    lr_buffer, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +				    OPAL_STARTLIST,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_VALUES,
+> +				    OPAL_STARTLIST,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_READLOCKED,
+> +				    read_locked,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_WRITELOCKED,
+> +				    write_locked,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_ENDLIST,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building SET command.\n", dev->disk_name);
+> +		return ret;
+> +	}
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +
+> +static int lock_unlock_locking_range_SUM(struct opal_dev *dev)
+> +{
+> +	u8 lr_buffer[OPAL_UID_LENGTH];
+> +	struct opal_cmd *cmd;
+> +	const u8 *method;
+> +	struct opal_lock_unlock *lkul;
+> +	int ret;
+> +	u8 read_locked = 1, write_locked = 1;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	method = OPALMETHOD[OPAL_SET];
+> +	lkul = dev->func_data[dev->state - 1];
+> +	if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) {
+> +		pr_err("%s: Can't build locking range\n", dev->disk_name);
+> +		return -EINVAL;
+> +	}
+> +
+> +	switch (lkul->l_state) {
+> +	case OPAL_RO:
+> +		read_locked = 0;
+> +		write_locked = 1;
+> +		break;
+> +	case OPAL_RW:
+> +		read_locked = 0;
+> +		write_locked = 0;
+> +		break;
+> +	case OPAL_LK:
+> +		/* vars are initalized to locked */
+> +		break;
+> +	default:
+> +		pr_err("Tried to set an invalid locking state.\n");
+> +		return 1;
+> +	}
+> +
+> +	ret = test_and_add_token_va(cmd, "c2sc 3c 4c 4c 4c 4c 3c",
+> +				    OPAL_CALL,
+> +				    lr_buffer, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +				    OPAL_STARTLIST,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_VALUES,
+> +				    OPAL_STARTLIST,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_READLOCKENABLED,
+> +				    OPAL_TRUE,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_WRITELOCKENABLED,
+> +				    OPAL_TRUE,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_READLOCKED,
+> +				    read_locked,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_WRITELOCKED,
+> +				    write_locked,
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_ENDLIST,
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST);
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building SET command.\n", dev->disk_name);
+> +		return ret;
+> +	}
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +int activate_lsp(struct opal_dev *dev)
+> +{
+> +	u8 user_lr[OPAL_UID_LENGTH];
+> +	const u8 *method, *uid;
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +	size_t uint_3 = 0x83;
+> +
+> +	cmd = &dev->cmd;
+> +
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	uid = OPALUID[OPAL_LOCKINGSP_UID];
+> +	method = OPALMETHOD[OPAL_ACTIVATE];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s",
+> +				    OPAL_CALL,
+> +				    uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH);
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building Activate LockingSP command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +	/* Activating as SUM */
+> +	if (dev->lr > 0) {
+> +		ret = build_locking_range(user_lr, sizeof(user_lr), dev->lr);
+> +		if (ret < 0) {
+> +			pr_err("%s: Can't build locking user\n",
+> +			       dev->disk_name);
+> +			return ret;
+> +		}
+> +		test_and_add_token_va(cmd, "2c 4c csc 2c",
+> +				      OPAL_STARTLIST,
+> +				      OPAL_STARTNAME,
+> +
+> +				      uint_3,
+> +				      OPAL_TINY_UINT_06,
+> +				      OPAL_TINY_UINT_00,
+> +				      OPAL_TINY_UINT_00,
+> +
+> +				      OPAL_STARTLIST,
+> +				      user_lr, OPAL_UID_LENGTH,
+> +				      OPAL_ENDLIST,
+> +
+> +				      OPAL_ENDNAME,
+> +				      OPAL_ENDLIST);
+> +	} else /* Actiave Normal Mode */
+> +		ret = test_and_add_token_va(cmd, "2c",
+> +					    OPAL_STARTLIST,
+> +					    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building Activate LockingSP command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, generic_cont);
+> +}
+> +
+> +static void get_lsp_lifecycle_cont(int error, void *data)
+> +{
+> +
+> +	struct opal_dev *dev = data;
+> +	u8 lc_status;
+> +
+> +	if (error)
+> +		goto err_return;
+> +
+> +	error = parse_and_check_status(dev);
+> +	if (error)
+> +		goto err_return;
+> +
+> +	lc_status = response_get_u64(&dev->parsed, 4);
+> +	/* 0x08 is Manufacured Inactive */
+> +	/* 0x09 is Manufactured */
+> +	if (lc_status != 0x08) {
+> +		pr_err("%s: Couldn't determine the status of the Lifcycle state\n",
+> +		       dev->disk_name);
+> +		error = -ENODEV;
+> +	}
+> +
+> +err_return:
+> +	if (dev->oper_cb)
+> +		dev->oper_cb(error, dev);
+> +}
+> +
+> +/* Determine if we're in the Manufactured Inactive or Active state */
+> +int get_lsp_lifecycle(struct opal_dev *dev)
+> +{
+> +	struct opal_cmd *cmd;
+> +	const u8 *method, *uid;
+> +	int ret;
+> +
+> +	cmd = &dev->cmd;
+> +
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	uid = OPALUID[OPAL_LOCKINGSP_UID];
+> +	method = OPALMETHOD[OPAL_GET];
+> +
+> +	ret = test_and_add_token_va(cmd, "c2s 2c 4c 4c 2c",
+> +				    OPAL_CALL,
+> +				    uid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTLIST,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_03, /* Start Column */
+> +				    OPAL_TINY_UINT_06, /* Lifcycle Column */
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_04, /* End Column */
+> +				    OPAL_TINY_UINT_06, /* Lifecycle Column */
+> +				    OPAL_ENDNAME,
+> +
+> +				    OPAL_ENDLIST,
+> +				    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error Building GET Lifecycle Status command\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, get_lsp_lifecycle_cont);
+> +}
+> +
+> +static void get_msid_cpin_pin_cont(int error, void *data)
+> +{
+> +	const char *msid_pin;
+> +	struct opal_dev *dev = data;
+> +	size_t strlen;
+> +
+> +	if (error)
+> +		goto err_return;
+> +
+> +	error = parse_and_check_status(dev);
+> +	if (error)
+> +		goto err_return;
+> +
+> +	strlen = response_get_string(&dev->parsed, 4, &msid_pin);
+> +	if (!msid_pin) {
+> +		pr_err("%s: Couldn't extract PIN from response\n", __func__);
+> +		error = 1;
+> +		goto err_return;
+> +	}
+> +
+> +	dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL);
+> +	if (!dev->prev_data)
+> +		error = -ENOMEM;
+> +
+> +	dev->prev_d_len = strlen;
+> +
+> + err_return:
+> +	if (dev->oper_cb)
+> +		dev->oper_cb(error, dev);
+> +}
+> +
+> +static int get_msid_cpin_pin(struct opal_dev *dev)
+> +{
+> +	const u8 *method, *smuid;
+> +	int ret;
+> +	struct opal_cmd *cmd;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +	set_comID(cmd, dev->comID);
+> +
+> +	smuid = OPALUID[OPAL_C_PIN_MSID];
+> +	method = OPALMETHOD[OPAL_GET];
+> +
+> +	ret = test_and_add_token_va(cmd, "c 2s 12c",
+> +				    OPAL_CALL,
+> +
+> +				    smuid, OPAL_UID_LENGTH,
+> +				    method, OPAL_METHOD_LENGTH,
+> +
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTLIST,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_03, /* Sart Column */
+> +				    OPAL_TINY_UINT_03, /* PIN */
+> +				    OPAL_ENDNAME,
+> +				    OPAL_STARTNAME,
+> +				    OPAL_TINY_UINT_04, /* End Column */
+> +				    OPAL_TINY_UINT_03, /* PIN */
+> +				    OPAL_ENDNAME,
+> +				    OPAL_ENDLIST,
+> +				    OPAL_ENDLIST);
+> +
+> +	if (ret < 0) {
+> +		pr_err("%s: Error building Get MSID CPIN PIN command.\n",
+> +		       dev->disk_name);
+> +		return ret;
+> +	}
+> +
+> +	return finalize_and_send(dev, cmd, get_msid_cpin_pin_cont);
+> +}
+> +
+> +static void unlock_suspend_final(int error, void *data)
+> +{
+> +	struct opal_dev *dev = data;
+> +
+> +	dev->resume_from_suspend = false;
+> +	dev->resume_data = NULL;
+> +	dev->func_data = NULL;
+> +	dev->bdev = NULL;
+> +}
+> +
+> +static int build_end_opal_session(struct opal_dev *dev)
+> +{
+> +	struct opal_cmd *cmd;
+> +
+> +	cmd = &dev->cmd;
+> +	clear_opal_cmd(cmd);
+> +
+> +	set_comID(cmd, dev->comID);
+> +	return test_and_add_token_u8(cmd, OPAL_ENDOFSESSION);
+> +}
+> +
+> +static int end_opal_session(struct opal_dev *dev)
+> +{
+> +	if (build_end_opal_session(dev) < 0)
+> +		return -1;
+> +	return finalize_and_send(dev, &dev->cmd, end_session_cont);
+> +}
+Any reason we cant:
+
+int ret = build_...
+if (ret < 0)
+	return ret;
+
+
+> +
+> +static struct opal_dev *find_opal_dev(struct block_device *bdev, u8 lr)
+> +{
+> +	struct opal_dev *iter, *opal_dev = NULL;
+> +
+> +	list_for_each_entry(iter, &opal_list, node) {
+> +		if (strncmp(iter->disk_name, bdev->bd_disk->disk_name,
+> +			    DISK_NAME_LEN))
+> +			continue;
+> +		if (iter->lr == lr) {
+> +			opal_dev = iter;
+> +			break;
+> +		}
+> +	}
+> +
+> +	return opal_dev;
+> +}
+> +
+> +static int update_opal_dev(struct opal_dev *old_dev, struct opal_dev *new_dev)
+> +{
+> +	if (!atomic_add_unless(&old_dev->in_use, 1, 1)) {
+> +		pr_err("%s: dev was in use\n", __func__);
+> +		return -EBUSY;
+> +	}
+> +
+> +	old_dev->key_name_len = new_dev->key_name_len;
+> +	if (!memcpy(old_dev->key_name, new_dev->key_name, old_dev->key_name_len)) {
+> +		pr_err("%s: Error updating device:\n", old_dev->disk_name);
+> +		return -EFAULT;
+> +	}
+> +
+> +	if (!strncpy(old_dev->disk_name, new_dev->disk_name, DISK_NAME_LEN)) {
+> +		pr_err("%s: Error registering device: copying disk name\n",
+> +		       old_dev->disk_name);
+> +		return -EFAULT;
+> +	}
+> +
+> +	old_dev->comID = new_dev->comID;
+> +	old_dev->start = new_dev->start;
+> +	old_dev->length = new_dev->length;
+> +	old_dev->align = new_dev->align;
+> +	old_dev->lowest_lba = new_dev->lowest_lba;
+> +	old_dev->bdev = NULL;
+> +	old_dev->final_cb = new_dev->final_cb;
+> +	old_dev->final_cb_data = new_dev->final_cb_data;
+> +	old_dev->oper_cb = new_dev->oper_cb;
+> +	old_dev->state = new_dev->state;
+> +	old_dev->funcs = new_dev->funcs;
+> +
+> +	kfree(old_dev->completion);
+> +	clean_function_data(old_dev);
+> +
+> +	old_dev->completion = new_dev->completion;
+> +
+> +	/*
+> +	 * Won't be able to auto unlock this locking range based on block
+> +	 * requestes.
+> +	 */
+> +	if (old_dev->length == 0)
+> +		pr_warn("%s: Missing block information for locking range %d\n",
+> +			old_dev->disk_name, old_dev->lr);
+> +
+> +	return 0;
+> +}
+> +
+> +int opal_register_cont(struct opal_dev *new_dev)
+> +{
+> +	struct opal_dev *old_dev;
+> +	unsigned long flags;
+> +	int error = 0;
+> +
+> +	spin_lock_irqsave(&list_spinlock, flags);
+> +
+> +	old_dev = find_opal_dev(new_dev->bdev, new_dev->lr);
+> +	if (!old_dev) {
+> +		list_add_tail(&new_dev->node, &opal_list);
+> +		old_dev = new_dev;
+> +	} else {
+> +		if (old_dev == new_dev)
+> +			error = 0;
+> +		else {
+> +			error = update_opal_dev(old_dev, new_dev);
+> +			clean_opal_key(new_dev);
+> +			kfree(new_dev);
+> +		}
+> +	}
+> +
+> +	if (error)
+> +		list_del(&old_dev->node);
+> +
+> +	spin_unlock_irqrestore(&list_spinlock, flags);
+> +
+> +	if (!error)
+> +		pr_info("%s: Registered key for locking range: %d\n",
+> +			old_dev->disk_name, old_dev->lr);
+> +
+> +	if (old_dev->oper_cb)
+> +		old_dev->oper_cb(error, old_dev);
+> +
+> +	return 0;
+> +}
+> +
+> +static void next(int error, struct opal_dev *dev)
+> +{
+> +	opal_step func = dev->funcs[dev->state];
+> +	void *cb_data = dev->final_cb_data;
+> +	sec_cb *cb = dev->final_cb;
+> +	bool done = false;
+> +
+> +
+> +	if (error || !func) {
+> +		done = true;
+> +		goto next_exit;
+> +	}
+> +	dev->state++;
+> +	dev->oper_cb = next;
+> +	error = func(dev);
+> + next_exit:
+> +	if (error) {
+> +		pr_err("%s: Error on step function: %d with error %d: %s\n",
+> +		       dev->disk_name, dev->state, error,
+> +		       opal_error_to_human(error));
+> +
+> +
+> +		atomic_dec(&dev->in_use);
+> +		if (dev->error_cb) {
+> +			dev->error_cb(dev->error_cb_data);
+> +			return;
+> +		}
+> +		if (cb)
+> +			cb(error, cb_data);
+> +
+> +		dev->completion->completion_status = error;
+> +		complete(&dev->completion->cmd_completion);
+> +	} else if (!error && done) {
+> +		atomic_dec(&dev->in_use);
+> +		if (cb)
+> +			cb(error, cb_data);
+> +		dev->completion->completion_status = error;
+> +		complete(&dev->completion->cmd_completion);
+> +	}
+> +}
+> +
+> +const opal_step error_end_session[] = {
+> +	end_opal_session,
+> +	NULL,
+> +};
+> +static int end_opal_session_error(struct opal_dev *dev)
+> +{
+> +
+> +	dev->funcs = error_end_session;
+> +	dev->state = 0;
+> +	dev->error_cb = NULL;
+> +	next(0, dev);
+> +	return 0;
+> +}
+> +
+> +static struct opal_dev *alloc_opal_dev(struct block_device *bdev, u8 lr)
+> +{
+> +	struct opal_dev *opal_dev;
+> +	struct request_queue *q;
+> +	unsigned long dma_align;
+> +	const char *disk_name;
+> +	struct opal_cmd *cmd;
+> +	int ret;
+> +
+> +	opal_dev = kzalloc(sizeof(*opal_dev), GFP_KERNEL);
+> +	if (!opal_dev)
+> +		return ERR_PTR(-ENOMEM);
+> +
+> +	opal_dev->bdev = bdev;
+> +	opal_dev->lr = lr;
+> +	cmd = &opal_dev->cmd;
+> +	cmd->cmd = cmd->cmd_buf;
+> +	cmd->resp = cmd->resp_buf;
+> +
+> +	disk_name = bdev->bd_disk->disk_name;
+> +	if (!strncpy(opal_dev->disk_name, disk_name, DISK_NAME_LEN)) {
+> +		pr_err("%s: Error registering device: copying disk name\n",
+> +		       disk_name);
+> +		ret = -EFAULT;
+> +		goto err_free_dev;
+> +	}
+> +
+> +	q = bdev->bd_queue;
+> +	dma_align = (queue_dma_alignment(q) | q->dma_pad_mask) + 1;
+> +	cmd->cmd = (u8 *)round_up((uintptr_t)cmd->cmd, dma_align);
+> +	cmd->resp = (u8 *)round_up((uintptr_t)cmd->resp, dma_align);
+> +
+> +	INIT_LIST_HEAD(&opal_dev->node);
+> +	atomic_set(&opal_dev->in_use, 1);
+> +
+> +	opal_dev->completion = kzalloc(sizeof(*opal_dev->completion),
+> +				       GFP_KERNEL);
+> +
+> +	if (!opal_dev->completion)
+> +		goto err_free_dev;
+> +
+> +	init_completion(&opal_dev->completion->cmd_completion);
+> +	opal_dev->completion->completion_status = 0;
+> +	opal_dev->state = 0;
+> +
+> +	return opal_dev;
+> +
+> +err_free_dev:
+> +	kfree(opal_dev);
+> +	return ERR_PTR(ret);
+> +}
+> +
+> +int opal_register(struct block_device *bdev, struct opal_key *key_cmd,
+> +		  const opal_step *funcs)
+> +{
+> +	struct opal_dev *new_dev = NULL;
+> +	u8 key_len = key_cmd->key_len;
+> +	u8 lr = key_cmd->lr;
+> +	struct opal_completion *completion;
+> +	int ret;
+> +
+> +	new_dev = alloc_opal_dev(bdev, lr);
+> +	if (IS_ERR(new_dev)) {
+> +		pr_err("%s: Error registering device: allocation\n",
+> +		       bdev->bd_disk->disk_name);
+> +		return PTR_ERR(new_dev);
+> +	}
+> +
+> +	if (!memcpy(new_dev->key_name, key_cmd->key, key_len)) {
+> +		pr_err("%s: Error registering key: couldn't copy key\n",
+> +		       new_dev->disk_name);
+> +		return -EFAULT;
+> +	}
+> +
+> +	new_dev->key_name_len = key_len;
+> +	new_dev->key_type = key_cmd->key_type;
+> +	ret = get_opal_key(new_dev);
+> +	if (ret) {
+> +		pr_err("%s: Couldn't get key: %d\n", new_dev->disk_name, ret);
+> +		return ret;
+> +	}
+> +
+> +	new_dev->funcs = funcs;
+> +
+> +	new_dev->state = 0;
+> +	completion = new_dev->completion;
+> +	next(0, new_dev);
+> +
+> +	return wait_for_cmd_completion(completion);
+> +}
+> +
+> +static struct opal_dev *get_registered_opal_dev(struct block_device *bdev,
+> +						u8 lr)
+> +{
+> +	const char *diskname = bdev->bd_disk->disk_name;
+> +	struct opal_dev *iter, *dev = NULL;
+> +	unsigned long flags;
+> +	bool in_use = false;
+> +
+> +	spin_lock_irqsave(&list_spinlock, flags);
+> +	list_for_each_entry(iter, &opal_list, node) {
+> +		if (strncmp(iter->disk_name, diskname, DISK_NAME_LEN))
+> +			continue;
+> +		if (iter->lr == lr) {
+> +			dev = iter;
+> +			if (!atomic_add_unless(&iter->in_use, 1, 1)) {
+> +				dev = NULL;
+> +				in_use = true;
+> +			}
+> +			break;
+> +		}
+> +	}
+> +
+> +	spin_unlock_irqrestore(&list_spinlock, flags);
+> +
+> +	if (!dev)
+> +		return NULL;
+> +
+> +	dev->bdev = bdev;
+> +	return dev;
+> +}
+> +
+> +/* Free up the Opal dev and its keys during two scenarios:
+> + *
+> + * 1) When a command is complete that no longer requires
+> + *    the opal dev to be around.
+> + * 2) When a command, including Opal Save fails we clean
+> + *    and free the opal dev.
+> + *
+> + *    If we find the opal dev structure in the list of
+> + *    saved passwords we will *not* remove it.
+> + */
+> +static void remove_and_clean_opal_dev(struct opal_dev *dev)
+> +{
+> +	struct opal_dev *iter;
+> +	bool found = false;
+> +
+> +	spin_lock(&list_spinlock);
+> +	list_for_each_entry(iter, &opal_list, node) {
+> +		if (iter == dev) {
+> +			found = true;
+> +			break;
+> +		}
+> +	}
+> +
+> +	spin_unlock(&list_spinlock);
+> +	if (!found) {
+> +		clean_opal_key(dev);
+> +		clean_function_data(dev);
+> +		kfree(dev);
+> +	}
+> +}
+> +
+> +static struct opal_dev *get_or_create_opal_dev(struct block_device *bdev,
+> +					       u8 lr, bool use_new)
+> +{
+> +	struct opal_dev *dev;
+> +
+> +	if (use_new)
+> +		return alloc_opal_dev(bdev, lr);
+> +
+> +	dev = get_registered_opal_dev(bdev, lr);
+> +	if (!dev) {
+> +		dev = alloc_opal_dev(bdev, lr);
+> +		if (!dev)
+> +			return NULL;
+No need for this check when you already return dev
+
+
+> +	}
+> +	return dev;
+> +}
+Instead, how about:
+static struct opal_dev *get_or_create_opal_dev(struct block_device *bdev,
+					       u8 lr, bool use_new)
+{
+	struct opal_dev *dev = NULL;
+
+	if (!use_new)
+		dev = get_registered_opal_dev(bdev, lr);
+
+	if (!dev)
+		dev = alloc_opal_dev(bdev, lr);
+
+	return dev;
+}
+
+
+> +
+> +static struct opal_completion *setup_opal_dev(struct block_device *bdev,
+> +					      struct opal_dev *dev,
+> +					      const opal_step *funcs,
+> +					      struct opal_key *key)
+> +{
+> +	int ret;
+> +
+> +	dev->bdev = bdev;
+> +	dev->state = 0;
+> +	dev->funcs = funcs;
+> +	dev->TSN = 0;
+> +	dev->HSN = 0;
+> +	dev->final_cb = NULL;
+> +	dev->final_cb_data = NULL;
+> +	dev->lr = key->lr;
+> +	dev->error_cb = end_opal_session_error;
+> +	dev->error_cb_data = dev;
+> +
+> +	if (key) {
+> +		memcpy(dev->key_name, key->key, key->key_len);
+> +		dev->key_name_len = key->key_len;
+> +		dev->key_type = key->key_type;
+> +
+> +		ret = get_opal_key(dev);
+> +		if (ret) {
+> +			kfree(dev->completion);
+> +			pr_err("%s: Couldn't get key: %d\n",
+> +			       dev->disk_name, ret);
+> +			return ERR_PTR(ret);
+> +		}
+> +	}
+> +	dev->func_data = NULL;
+> +	dev->completion->completion_status = 0;
+> +
+> +	return dev->completion;
+> +}
+> +
+> +static int internal_setup_lr(struct block_device *bdev,
+> +			     struct opal_user_lr_setup *setup)
+> +{
+> +	struct opal_dev *dev;
+> +	struct opal_completion *completion;
+> +	void *data[3] = { NULL };
+> +	const opal_step lr_funcs[] = {
+> +		opal_discovery0,
+> +		start_auth_opal_session,
+> +		setup_locking_range,
+> +		get_active_key,
+> +		gen_key,
+> +		end_opal_session,
+> +		NULL,
+> +	};
+> +	int ret;
+> +
+> +	dev = get_or_create_opal_dev(bdev, setup->key.lr, true);
+> +	if (!dev)
+> +		return -ENOMEM;
+> +
+> +	completion = setup_opal_dev(bdev, dev, lr_funcs, &setup->key);
+> +	if (IS_ERR(completion)) {
+> +		ret = PTR_ERR(completion);
+> +		goto error_return;
+> +	}
+> +
+> +	dev->func_data = data;
+> +	dev->num_func_data = 3;
+> +	dev->func_data[1] = &setup->who;
+> +	dev->func_data[2] = setup;
+> +
+> +	next(0, dev);
+> +	ret = wait_for_cmd_completion(completion);
+> +
+> + error_return:
+> +	remove_and_clean_opal_dev(dev);
+> +	return ret;
+> +}
+> +
+> +int opal_revert(struct block_device *bdev, struct opal_key *key)
+> +{
+> +	const opal_step revert_funcs[] = {
+> +		opal_discovery0,
+> +		start_SIDASP_opal_session,
+> +		revert_tper, /* controller will terminate session */
+> +		NULL,
+> +	};
+> +
+> +	return opal_register(bdev, key, revert_funcs);
+> +}
+> +
+> +int activate_user(struct block_device *bdev, struct opal_activate_user *act)
+> +{
+> +	const opal_step act_funcs[] = {
+> +		opal_discovery0,
+> +		start_admin1LSP_opal_session,
+> +		internal_activate_user,
+> +		end_opal_session,
+> +		NULL
+> +	};
+> +	struct opal_dev *dev;
+> +	struct opal_completion *completion;
+> +	void *data[3] = { NULL };
+> +	int ret;
+> +
+> +	dev = get_or_create_opal_dev(bdev, act->key.lr, true);
+> +	if (!dev)
+> +		return -ENOMEM;
+> +
+> +	completion = setup_opal_dev(bdev, dev, act_funcs, &act->key);
+> +	if (IS_ERR(completion)) {
+> +		ret = PTR_ERR(completion);
+> +		goto error_return;
+> +	}
+> +
+> +	dev->num_func_data = 3;
+> +	dev->func_data = data;
+> +	dev->func_data[1] = act;
+> +	dev->func_data[2] = act;
+> +
+> +	next(0, dev);
+> +	ret = wait_for_cmd_completion(completion);
+> +
+> + error_return:
+> +	remove_and_clean_opal_dev(dev);
+> +	return ret;
+> +}
+> +
+> +int opal_set_pw(struct block_device *bdev, struct opal_new_pw *pw)
+> +
+> +{
+> +	const opal_step pw_funcs[] = {
+> +		opal_discovery0,
+> +		start_auth_opal_session,
+> +		set_new_pw,
+> +		end_opal_session,
+> +		NULL
+> +	};
+> +	struct opal_dev *dev;
+> +	struct opal_completion *completion;
+> +	void *data[3] = { NULL };
+> +	int ret;
+> +
+> +	dev = get_or_create_opal_dev(bdev, pw->current_pin.lr, true);
+> +	if (!dev)
+> +		return -ENOMEM;
+> +
+> +	completion = setup_opal_dev(bdev, dev, pw_funcs, &pw->current_pin);
+> +	if (IS_ERR(completion)) {
+> +		ret = PTR_ERR(completion);
+> +		goto error_return;
+> +	}
+> +
+> +	dev->num_func_data = 3;
+> +	dev->func_data = data;
+> +	dev->func_data[1] = (void *) &pw->who;
+> +	dev->func_data[2] = (void *) pw;
+> +
+> +	next(0, dev);
+> +	ret = wait_for_cmd_completion(completion);
+> +
+> + error_return:
+> +	remove_and_clean_opal_dev(dev);
+> +	return ret;
+> +}
+> +
+> +int opal_act_lsp_int(struct block_device *bdev, struct opal_key *key,
+> +		     const opal_step *funcs)
+> +{
+> +	struct opal_dev *dev;
+> +	struct opal_completion *completion;
+> +	int ret;
+> +
+> +	dev = get_or_create_opal_dev(bdev, key->lr, true);
+> +	if (!dev)
+> +		return -ENOMEM;
+> +	completion = setup_opal_dev(bdev, dev, funcs, key);
+> +	if (IS_ERR(completion)) {
+> +		ret = PTR_ERR(completion);
+> +		goto error_return;
+> +	}
+> +
+> +	next(0, dev);
+> +	ret = wait_for_cmd_completion(completion);
+> +
+> + error_return:
+> +	remove_and_clean_opal_dev(dev);
+> +	return ret;
+> +}
+> +
+> +
+> +static int opal_save_internal(struct block_device *bdev,
+> +			      struct opal_lock_unlock *lk)
+> +{
+> +	void *func_data[3] = { NULL };
+> +	struct opal_dev *dev;
+> +	struct opal_completion *completion;
+> +	const opal_step _auth_funcs[] = {
+> +		opal_discovery0,
+> +		start_auth_opal_session,
+> +		query_locking_range,
+> +		end_opal_session,
+> +		opal_register_cont,
+> +		NULL
+> +	};
+> +	int ret;
+> +
+> +	dev = get_or_create_opal_dev(bdev, lk->key.lr, false);
+> +	if (!dev)
+> +		return -ENOMEM;
+> +	completion = setup_opal_dev(bdev, dev, _auth_funcs, &lk->key);
+> +	if (IS_ERR(completion)) {
+> +		ret = PTR_ERR(completion);
+> +		goto error_return;
+> +	}
+> +
+> +	dev->num_func_data = 3;
+> +	dev->func_data = func_data;
+> +	dev->func_data[1] = &lk->authority;
+> +	dev->lkul = *lk;
+> +
+> +	next(0, dev);
+> +	ret = wait_for_cmd_completion(completion);
+> +
+> + error_return:
+> +	remove_and_clean_opal_dev(dev);
+> +	return ret;
+> +}
+> +
+> +static int add_user_lr_internal(struct block_device *bdev,
+> +				struct opal_lock_unlock *lk)
+> +{
+> +	void *func_data[3] = { NULL };
+> +	struct opal_dev *dev;
+> +	struct opal_completion *completion;
+> +	const opal_step funcs[] = {
+> +		opal_discovery0,
+> +		start_admin1LSP_opal_session,
+> +		add_user_to_lr,
+> +		end_opal_session,
+> +		NULL
+> +	};
+> +	int ret;
+> +
+> +	dev = get_or_create_opal_dev(bdev, lk->key.lr, true);
+> +	if (!dev)
+> +		return -ENOMEM;
+> +	completion = setup_opal_dev(bdev, dev, funcs, &lk->key);
+> +	if (IS_ERR(completion)) {
+> +		ret = PTR_ERR(completion);
+> +		goto error_return;
+> +	}
+> +
+> +	dev->num_func_data = 3;
+> +	dev->func_data = func_data;
+> +	dev->func_data[2] = lk;
+> +
+> +	next(0, dev);
+> +	ret = wait_for_cmd_completion(completion);
+> +
+> + error_return:
+> +	remove_and_clean_opal_dev(dev);
+> +	return ret;
+> +}
+> +
+> +static int lock_unlock_internal(struct block_device *bdev,
+> +				struct opal_lock_unlock *lk)
+> +{
+> +	void *func_data[3] = { NULL };
+> +	struct opal_dev *dev;
+> +	struct opal_completion *completion;
+> +
+> +	const opal_step ulk_funcs_SUM[] = {
+> +		opal_discovery0,
+> +		start_auth_opal_session,
+> +		lock_unlock_locking_range_SUM,
+> +		end_opal_session,
+> +		NULL
+> +	};
+> +	const opal_step _unlock_funcs[] = {
+> +		opal_discovery0,
+> +		start_auth_opal_session,
+> +		lock_unlock_locking_range,
+> +		end_opal_session,
+> +		NULL
+> +	};
+> +	int ret;
+> +
+> +	dev = get_or_create_opal_dev(bdev, lk->key.lr, true);
+> +	if (!dev)
+> +		return -ENOMEM;
+> +
+> +	if (lk->authority.SUM)
+> +		completion = setup_opal_dev(bdev, dev, ulk_funcs_SUM, &lk->key);
+> +	else
+> +		completion = setup_opal_dev(bdev, dev, _unlock_funcs, &lk->key);
+> +
+> +	if (IS_ERR(completion)) {
+> +		ret = PTR_ERR(completion);
+> +		goto error_return;
+> +	}
+> +
+> +	dev->num_func_data = 3;
+> +	dev->func_data = func_data;
+> +	dev->func_data[1] = &lk->authority;
+> +	dev->func_data[2] = lk;
+> +
+> +	next(0, dev);
+> +	ret = wait_for_cmd_completion(completion);
+> +
+> + error_return:
+> +	remove_and_clean_opal_dev(dev);
+> +	return ret;
+> +}
+> +
+> +int opal_erase_locking_range(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	struct opal_dev *dev;
+> +	struct opal_completion *completion;
+> +	struct opal_key k;
+> +	int ret;
+> +	const opal_step erase_funcs[] = {
+> +		opal_discovery0,
+> +		start_admin1LSP_opal_session,
+> +		erase_locking_range,
+> +		end_opal_session,
+> +		NULL,
+> +	};
+> +
+> +	if (!bdev || !bdev->bd_disk) {
+> +		pr_err("Can't save password for NULL block device.\n");
+> +		return -EINVAL;
+> +	}
+> +
+> +	if (copy_from_user(&k, key->opal, sizeof(*key->opal)))
+> +		return -EFAULT;
+> +
+> +	dev = get_or_create_opal_dev(bdev, k.lr, true);
+> +	if (!dev)
+> +		return -ENOMEM;
+> +
+> +	completion = setup_opal_dev(bdev, dev, erase_funcs, &k);
+> +	if (IS_ERR(completion)) {
+> +		ret = PTR_ERR(completion);
+> +		goto error_return;
+> +	}
+> +
+> +	next(0, dev);
+> +	ret = wait_for_cmd_completion(completion);
+> +
+> + error_return:
+> +	remove_and_clean_opal_dev(dev);
+> +	return ret;
+> +}
+> +EXPORT_SYMBOL(opal_erase_locking_range);
+> +
+> +int opal_enable_disable_shadow_mbr(struct block_device *bdev,
+> +				   struct sed_key *key)
+> +{
+> +	void *func_data[6] = { NULL };
+> +	struct opal_mbr_data mbr;
+> +	struct opal_dev *dev;
+> +	struct opal_completion *completion;
+> +	const opal_step mbr_funcs[] = {
+> +		opal_discovery0,
+> +		start_admin1LSP_opal_session,
+> +		set_mbr_done,
+> +		end_opal_session,
+> +		start_admin1LSP_opal_session,
+> +		set_mbr_enable_disable,
+> +		end_opal_session,
+> +		NULL,
+> +	};
+> +	int ret;
+> +
+> +	if (!bdev || !bdev->bd_disk) {
+> +		pr_err("Can't save password for NULL block device.\n");
+> +		return -EINVAL;
+> +	}
+> +
+> +	if (copy_from_user(&mbr, key->opal_mbr, sizeof(*key->opal_mbr)))
+> +		return -EFAULT;
+> +
+> +	if (mbr.enable_disable != OPAL_MBR_ENABLE &&
+> +	    mbr.enable_disable != OPAL_MBR_DISABLE)
+> +		return -EINVAL;
+> +
+> +	dev = get_or_create_opal_dev(bdev, mbr.key.lr, true);
+> +	if (!dev)
+> +		return -ENOMEM;
+> +
+> +	completion = setup_opal_dev(bdev, dev, mbr_funcs, &mbr.key);
+> +	if (IS_ERR(completion)) {
+> +		ret = PTR_ERR(completion);
+> +		goto error_return;
+> +	}
+> +
+> +	dev->num_func_data = 6;
+> +	dev->func_data = func_data;
+> +	dev->func_data[2] = &mbr.enable_disable;
+> +	dev->func_data[5] = &mbr.enable_disable;
+> +
+> +	next(0, dev);
+> +	ret = wait_for_cmd_completion(completion);
+> +
+> + error_return:
+> +	remove_and_clean_opal_dev(dev);
+> +	return ret;
+> +
+> +}
+> +EXPORT_SYMBOL(opal_enable_disable_shadow_mbr);
+> +
+> +int opal_save(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	struct opal_lock_unlock lkul;
+> +
+> +	if (!bdev || !bdev->bd_disk) {
+> +		pr_err("Can't save password for NULL block device.\n");
+> +		return -EINVAL;
+> +	}
+> +
+> +	if (copy_from_user(&lkul, key->opal_lk_unlk, sizeof(*key->opal)))
+> +		return -EFAULT;
+> +
+> +	return opal_save_internal(bdev, &lkul);
+> +}
+> +EXPORT_SYMBOL(opal_save);
+> +
+> +int opal_add_user_to_lr(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	struct opal_lock_unlock lkul;
+> +
+> +	if (copy_from_user(&lkul, key->opal_lk_unlk, sizeof(lkul)))
+> +		return -EFAULT;
+> +
+> +	if (!bdev || !bdev->bd_disk) {
+> +		pr_err("Can't assign user to LR without backing disk\n");
+> +		return -EFAULT;
+> +	}
+> +	if (lkul.l_state != OPAL_RO && lkul.l_state != OPAL_RW) {
+> +		pr_err("Locking state was not RO or RW\n");
+> +		return -EINVAL;
+> +	}
+> +	if (lkul.authority.who < OPAL_USER1 &&
+> +	    lkul.authority.who > OPAL_USER9) {
+> +		pr_err("Authority was not within the range of users: %d\n",
+> +		       lkul.authority.who);
+> +		return -EINVAL;
+> +	}
+> +	if (lkul.authority.SUM) {
+> +		pr_err("%s not supported in SUM. Use setup locking range\n",
+> +		       __func__);
+> +		return -EINVAL;
+> +	}
+> +
+> +	return add_user_lr_internal(bdev, &lkul);
+> +}
+> +EXPORT_SYMBOL(opal_add_user_to_lr);
+> +
+> +int opal_reverttper(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	struct opal_key k;
+> +
+> +	if (copy_from_user(&k, key->opal, sizeof(*key->opal)))
+> +		return -EFAULT;
+> +
+> +	return opal_revert(bdev, &k);
+> +}
+> +EXPORT_SYMBOL(opal_reverttper);
+> +
+> +int opal_lock_unlock(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	struct opal_lock_unlock k;
+> +
+> +	if (copy_from_user(&k, key->opal_lk_unlk, sizeof(*key->opal_lk_unlk)))
+> +		return -EFAULT;
+> +
+> +	if (k.authority.who < OPAL_ADMIN1 || k.authority.who >= OPAL_USER9)
+Should this be > OPAL_USER9 ?
+
+
+> +		return -EINVAL;
+> +
+> +	return lock_unlock_internal(bdev, &k);
+> +}
+> +EXPORT_SYMBOL(opal_lock_unlock);
+> +
+> +int opal_take_ownership(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	struct opal_key k;
+> +	const opal_step owner_funcs[] = {
+> +		opal_discovery0,
+> +		start_anybodyASP_opal_session,
+> +		get_msid_cpin_pin,
+> +		end_opal_session,
+> +		start_SIDASP_opal_session,
+> +		set_sid_cpin_pin,
+> +		end_opal_session,
+> +		NULL
+> +	};
+> +
+> +	if (!bdev || !bdev->bd_disk) {
+> +		pr_err("Can't save password for NULL block device.\n");
+> +		return -EINVAL;
+> +	}
+> +
+> +	if (copy_from_user(&k, key->opal, sizeof(*key->opal)))
+> +		return -EFAULT;
+> +
+> +	return opal_register(bdev, &k, owner_funcs);
+> +}
+> +EXPORT_SYMBOL(opal_take_ownership);
+> +
+> +int opal_activate_lsp(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	struct opal_key k;
+> +	const opal_step active_funcs[] = {
+> +		opal_discovery0,
+> +		start_SIDASP_opal_session, /* Open session as SID auth */
+> +		get_lsp_lifecycle,
+> +		activate_lsp,
+> +		end_opal_session,
+> +		NULL
+> +	};
+> +
+> +	if (!bdev || !bdev->bd_disk) {
+> +		pr_err("Can't save password for NULL block device.\n");
+> +		return -EINVAL;
+> +	}
+> +
+> +	if (copy_from_user(&k, key->opal, sizeof(*key->opal)))
+> +		return -EFAULT;
+> +
+> +	return opal_act_lsp_int(bdev, &k, active_funcs);
+> +}
+> +EXPORT_SYMBOL(opal_activate_lsp);
+> +
+> +int opal_setup_locking_range(struct block_device *bdev, struct sed_key *pw)
+> +{
+> +	struct opal_user_lr_setup k;
+> +
+> +	if (!bdev || !bdev->bd_disk) {
+> +		pr_err("Can't save password for NULL block device.\n");
+> +		return -EINVAL;
+> +	}
+> +
+> +	if (copy_from_user(&k, pw->opal_lrs, sizeof(*pw->opal_lrs)))
+> +		return -EFAULT;
+> +
+> +	return internal_setup_lr(bdev, &k);
+> +}
+> +
+> +int opal_set_new_pw(struct block_device *bdev, struct sed_key *pw)
+> +{
+> +	struct opal_new_pw k;
+> +
+> +	if (pw->sed_type != OPAL_PW)
+> +		return -EINVAL;
+> +
+> +	if (copy_from_user(&k, pw->opal_pw, sizeof(*pw->opal_pw)))
+> +		return -EFAULT;
+> +
+> +	if (k.who.who < OPAL_ADMIN1 || k.who.who > OPAL_USER9)
+> +		return -EINVAL;
+> +
+> +	return opal_set_pw(bdev, &k);
+> +}
+> +EXPORT_SYMBOL(opal_set_new_pw);
+> +
+> +int opal_activate_user(struct block_device *bdev, struct sed_key *pw)
+> +{
+> +	struct opal_activate_user k;
+> +
+> +	if (pw->sed_type != OPAL_ACT_USR) {
+> +		pr_err("Sed type was not act user\n");
+> +		return -EINVAL;
+> +	}
+> +
+> +	if (copy_from_user(&k, pw->opal_act, sizeof(*pw->opal_act))) {
+> +		pr_err("copy from user error\n");
+> +		return -EFAULT;
+> +	}
+> +
+> +	/* We can't activate Admin1 it's active as manufactured */
+> +	if (k.who.who < OPAL_USER1 && k.who.who > OPAL_USER9) {
+> +		pr_err("Who was not a valid user: %d \n", k.who.who);
+> +		return -EINVAL;
+> +	}
+> +
+> +	return activate_user(bdev, &k);
+> +
+> +}
+> +EXPORT_SYMBOL(opal_activate_user);
+> +
+> +int opal_unlock_from_suspend(struct opal_suspend_unlk *data)
+> +{
+> +	const char *diskname = data->name;
+> +	struct opal_dev *iter, *dev = NULL;
+> +	struct opal_completion *completion;
+> +	void *func_data[3] = { NULL };
+> +	const opal_step _unlock_funcs_SUM[] = {
+> +		opal_discovery0,
+> +		start_auth_opal_session,
+> +		lock_unlock_locking_range,
+Did you mean to use lock_unlock_locking_range_SUM ?
+Can we pull these two arrays out since they are required for both this
+function and lock_unlock_internal ?
+
+
+> +		end_opal_session,
+> +		NULL
+> +	};
+> +	const opal_step _unlock_funcs[] = {
+> +		opal_discovery0,
+> +		start_auth_opal_session,
+> +		lock_unlock_locking_range,
+> +		end_opal_session,
+> +		NULL
+> +	};
+> +
+> +
+> +	spin_lock(&list_spinlock);
+> +	list_for_each_entry(iter, &opal_list, node) {
+> +		if (strncmp(iter->disk_name, diskname, DISK_NAME_LEN)) {
+> +			pr_err("iterdisk was %s and diskname is %s\n",
+> +			       iter->disk_name, diskname);
+> +			continue;
+> +		}
+> +		if (atomic_add_unless(&iter->in_use, 1, 1)) {
+> +			dev = iter;
+> +			dev->func_data = func_data;
+> +			dev->resume_from_suspend = true;
+> +			dev->resume_data = data;
+> +			dev->final_cb = unlock_suspend_final;
+> +			dev->final_cb_data = dev;
+> +			dev->error_cb = end_opal_session_error;
+> +			dev->error_cb_data = dev;
+> +			dev->state = 0;
+> +			if (dev->lkul.authority.SUM)
+> +				dev->funcs = _unlock_funcs_SUM;
+> +			else
+> +				dev->funcs = _unlock_funcs;
+> +			dev->TSN = 0;
+> +			dev->HSN = 0;
+> +			dev->func_data[2] = &dev->lkul;
+> +			dev->func_data[1] = &dev->lkul.authority;
+> +			completion = dev->completion;
+> +			next(0, dev);
+> +			wait_for_cmd_completion(completion);
+> +		}
+> +	}
+> +	spin_unlock(&list_spinlock);
+> +
+> +	if (!dev)
+> +		return -ENODEV;
+> +	return 0;
+> +}
+> +EXPORT_SYMBOL(opal_unlock_from_suspend);
+> diff --git a/lib/sed-opal_internal.h b/lib/sed-opal_internal.h
+> new file mode 100644
+> index 0000000..c9d3883
+> --- /dev/null
+> +++ b/lib/sed-opal_internal.h
+> @@ -0,0 +1,586 @@
+> +/*
+> + * Copyright ? 2016 Intel Corporation
+> + *
+> + * Permission is hereby granted, free of charge, to any person obtaining a
+> + * copy of this software and associated documentation files (the "Software"),
+> + * to deal in the Software without restriction, including without limitation
+> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+> + * and/or sell copies of the Software, and to permit persons to whom the
+> + * Software is furnished to do so, subject to the following conditions:
+> + *
+> + * The above copyright notice and this permission notice (including the next
+> + * paragraph) shall be included in all copies or substantial portions of the
+> + * Software.
+> + *
+> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+> + * IN THE SOFTWARE.
+> + *
+> + * Author:
+> + *    Rafael Antognolli <rafael.antognolli at intel.com>
+> + *    Scott  Bauer      <scott.bauer at intel.com>
+> + */
+> +
+> +#ifndef _NVME_OPAL_INTERNAL_H
+> +#define _NVME_OPAL_INTERNAL_H
+> +
+> +#include <linux/key-type.h>
+> +#include <keys/user-type.h>
+> +
+> +#define DTAERROR_NO_METHOD_STATUS 0x89
+> +
+> +static const char *opal_errors[19] = {
+Remove the 19 so it's just opal_errors[] (doesnt silently truncate any
+new additions)
+
+
+> +	"Success",
+> +	"Not Authorized",
+> +	"Unknown Error",
+> +	"SP Busy",
+> +	"SP Failed",
+> +	"SP Disabled",
+> +	"SP Frozen",
+> +	"No Sessions Available",
+> +	"Uniqueness Conflict",
+> +	"Insufficient Space",
+> +	"Insufficient Rows",
+> +	"Invalid Function",
+> +	"Invalid Parameter",
+> +	"Invalid Reference",
+> +	"Unknown Error",
+> +	"TPER Malfunction",
+> +	"Transaction Failure",
+> +	"Response Overflow",
+> +	"Authority Locked Out",
+> +};
+> +
+> +static const char *opal_error_to_human(int error)
+> +{
+> +	if (error == 0x3f)
+> +		return "Failed";
+> +
+> +	if (error >= sizeof(opal_errors) || error < 0)
+You want sizeof(opal_errors)/sizeof(*opal_errors) here, but you can just
+use the ARRAY_SIZE macro instead
+
+
+> +		return "Unknown Error";
+> +
+> +	return opal_errors[error];
+> +}
+> +
+> +/* User IDs used in the TCG storage SSCs */
+> +static const u8 OPALUID[][8] = {
+> +	/* users */
+> +
+> +	/* session management  */
+> +	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff},
+> +	/* special "thisSP" syntax */
+> +	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+> +	/* Administrative SP */
+> +	{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 },
+> +	/* Locking SP */
+> +	{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 },
+> +	/* ENTERPRISE Locking SP  */
+> +	{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, 0x01 },
+> +	/* anybody */
+> +	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 },
+> +	/* SID */
+> +	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 },
+> +	/* ADMIN1 */
+> +	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 },
+> +	/* USER1 */
+> +	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 },
+> +	/* USER2 */
+> +	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 },
+> +	/* PSID user */
+> +	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 },
+> +	/* BandMaster 0 */
+> +	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x01 },
+> +	 /* EraseMaster */
+> +	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x84, 0x01 },
+> +
+> +	/* tables */
+> +
+> +	/* Locking_GlobalRange */
+> +	{ 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 },
+> +	/* ACE_Locking_Range_Set_RdLocked UID */
+> +	{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x01 },
+> +	/* ACE_Locking_Range_Set_WrLocked UID */
+> +	{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x01 },
+> +	/* MBR Control */
+> +	{ 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01 },
+> +	/* Shadow MBR */
+> +	{ 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 },
+> +	/* AUTHORITY_TABLE */
+> +	{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00},
+> +	/* C_PIN_TABLE */
+> +	{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00},
+> +	/* OPAL Locking Info */
+> +	{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 },
+> +	/* Enterprise Locking Info */
+> +	{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 },
+> +
+> +	/* C_PIN_TABLE object ID's */
+> +
+> +	/* C_PIN_MSID */
+> +	{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02},
+> +	/* C_PIN_SID */
+> +	{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01},
+> +	 /* C_PIN_ADMIN1 */
+> +	{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01},
+> +
+> +	/* half UID's (only first 4 bytes used) */
+> +
+> +	/* Half-UID ? Authority_object_ref */
+> +	{ 0x00, 0x00, 0x0C, 0x05, 0xff, 0xff, 0xff, 0xff },
+> +	/* Half-UID ? Boolean ACE */
+> +	{ 0x00, 0x00, 0x04, 0x0E, 0xff, 0xff, 0xff, 0xff },
+> +
+> +	/* special value for omitted optional parameter */
+> +
+> +	/* HEXFF for omitted */
+> +	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+> +};
+> +static const size_t OPAL_UID_LENGTH = 8;
+> +static const size_t OPAL_MSID_KEYLEN = 15;
+> +static const size_t OPAL_UID_LENGTH_HALF = 4;
+> +
+> +
+> +/* Enum to index OPALUID array */
+> +enum OPAL_UID {
+> +	/* users */
+> +	OPAL_SMUID_UID,
+> +	OPAL_THISSP_UID,
+> +	OPAL_ADMINSP_UID,
+> +	OPAL_LOCKINGSP_UID,
+> +	OPAL_ENTERPRISE_LOCKINGSP_UID,
+> +	OPAL_ANYBODY_UID,
+> +	OPAL_SID_UID,
+> +	OPAL_ADMIN1_UID,
+> +	OPAL_USER1_UID,
+> +	OPAL_USER2_UID,
+> +	OPAL_PSID_UID,
+> +	OPAL_ENTERPRISE_BANDMASTER0_UID,
+> +	OPAL_ENTERPRISE_ERASEMASTER_UID,
+> +	/* tables */
+> +	OPAL_LOCKINGRANGE_GLOBAL,
+> +	OPAL_LOCKINGRANGE_ACE_RDLOCKED,
+> +	OPAL_LOCKINGRANGE_ACE_WRLOCKED,
+> +	OPAL_MBRCONTROL,
+> +	OPAL_MBR,
+> +	OPAL_AUTHORITY_TABLE,
+> +	OPAL_C_PIN_TABLE,
+> +	OPAL_LOCKING_INFO_TABLE,
+> +	OPAL_ENTERPRISE_LOCKING_INFO_TABLE,
+> +	/* C_PIN_TABLE object ID's */
+> +	OPAL_C_PIN_MSID,
+> +	OPAL_C_PIN_SID,
+> +	OPAL_C_PIN_ADMIN1,
+> +	/* half UID's (only first 4 bytes used) */
+> +	OPAL_HALF_UID_AUTHORITY_OBJ_REF,
+> +	OPAL_HALF_UID_BOOLEAN_ACE,
+> +	/* omitted optional parameter */
+> +	OPAL_UID_HEXFF,
+> +};
+> +
+> +/*
+> + * TCG Storage SSC Methods.
+> + */
+> +static const u8 OPALMETHOD[][8] = {
+> +	/* Properties */
+> +	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01 },
+> +	/* STARTSESSION */
+> +	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02 },
+> +	/* Revert */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02 },
+> +	/* Activate */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03 },
+> +	/* Enterprise Get */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06 },
+> +	/* Enterprise Set */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07 },
+> +	/* NEXT */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08 },
+> +	/* Enterprise Authenticate */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c },
+> +	/* GetACL */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d },
+> +	/* GenKey */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10 },
+> +	/* revertSP */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11 },
+> +	/* Get */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16 },
+> +	/* Set */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17 },
+> +	/* Authenticate */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c },
+> +	/* Random */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 },
+> +	/* Erase */
+> +	{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 },
+> +};
+> +static const size_t OPAL_METHOD_LENGTH = 8;
+> +
+> +/* Enum for indexing the OPALMETHOD array */
+> +enum OPAL_METHOD {
+> +	OPAL_PROPERTIES,
+> +	OPAL_STARTSESSION,
+> +	OPAL_REVERT,
+> +	OPAL_ACTIVATE,
+> +	OPAL_EGET,
+> +	OPAL_ESET,
+> +	OPAL_NEXT,
+> +	OPAL_EAUTHENTICATE,
+> +	OPAL_GETACL,
+> +	OPAL_GENKEY,
+> +	OPAL_REVERTSP,
+> +	OPAL_GET,
+> +	OPAL_SET,
+> +	OPAL_AUTHENTICATE,
+> +	OPAL_RANDOM,
+> +	OPAL_ERASE,
+> +};
+> +
+> +enum OPAL_RESPONSE_TOKEN {
+> +	OPAL_DTA_TOKENID_BYTESTRING = 0xe0,
+> +	OPAL_DTA_TOKENID_SINT = 0xe1,
+> +	OPAL_DTA_TOKENID_UINT = 0xe2,
+> +	OPAL_DTA_TOKENID_TOKEN = 0xe3, /* actual token is returned */
+> +	OPAL_DTA_TOKENID_INVALID = 0X0
+> +};
+> +
+> +enum OPAL_TOKEN {
+> +	/* Boolean */
+> +	OPAL_TRUE = 0x01,
+> +	OPAL_FALSE = 0x00,
+> +	OPAL_BOOLEAN_EXPR = 0x03,
+> +	/* cellblocks */
+> +	OPAL_TABLE = 0x00,
+> +	OPAL_STARTROW = 0x01,
+> +	OPAL_ENDROW = 0x02,
+> +	OPAL_STARTCOLUMN = 0x03,
+> +	OPAL_ENDCOLUMN = 0x04,
+> +	OPAL_VALUES = 0x01,
+> +	/* authority table */
+> +	OPAL_PIN = 0x03,
+> +	/* locking tokens */
+> +	OPAL_RANGESTART = 0x03,
+> +	OPAL_RANGELENGTH = 0x04,
+> +	OPAL_READLOCKENABLED = 0x05,
+> +	OPAL_WRITELOCKENABLED = 0x06,
+> +	OPAL_READLOCKED = 0x07,
+> +	OPAL_WRITELOCKED = 0x08,
+> +	OPAL_ACTIVEKEY = 0x0A,
+> +	/* locking info table */
+> +	OPAL_MAXRANGES = 0x04,
+> +	 /* mbr control */
+> +	OPAL_MBRENABLE = 0x01,
+> +	OPAL_MBRDONE = 0x02,
+> +	/* properties */
+> +	OPAL_HOSTPROPERTIES = 0x00,
+> +	/* atoms */
+> +	OPAL_STARTLIST = 0xf0,
+> +	OPAL_ENDLIST = 0xf1,
+> +	OPAL_STARTNAME = 0xf2,
+> +	OPAL_ENDNAME = 0xf3,
+> +	OPAL_CALL = 0xf8,
+> +	OPAL_ENDOFDATA = 0xf9,
+> +	OPAL_ENDOFSESSION = 0xfa,
+> +	OPAL_STARTTRANSACTON = 0xfb,
+> +	OPAL_ENDTRANSACTON = 0xfC,
+> +	OPAL_EMPTYATOM = 0xff,
+> +	OPAL_WHERE = 0x00,
+> +};
+> +
+> +/* Useful tiny atoms.
+> + * Useful for table columns etc
+> + */
+> +enum OPAL_TINY_ATOM {
+> +	OPAL_TINY_UINT_00 = 0x00,
+> +	OPAL_TINY_UINT_01 = 0x01,
+> +	OPAL_TINY_UINT_02 = 0x02,
+> +	OPAL_TINY_UINT_03 = 0x03,
+> +	OPAL_TINY_UINT_04 = 0x04,
+> +	OPAL_TINY_UINT_05 = 0x05,
+> +	OPAL_TINY_UINT_06 = 0x06,
+> +	OPAL_TINY_UINT_07 = 0x07,
+> +	OPAL_TINY_UINT_08 = 0x08,
+> +	OPAL_TINY_UINT_09 = 0x09,
+> +	OPAL_TINY_UINT_10 = 0x0a,
+> +	OPAL_TINY_UINT_11 = 0x0b,
+> +	OPAL_TINY_UINT_12 = 0x0c,
+> +	OPAL_TINY_UINT_13 = 0x0d,
+> +	OPAL_TINY_UINT_14 = 0x0e,
+> +	OPAL_TINY_UINT_15 = 0x0f,
+> +};
+> +
+> +enum OPAL_ATOM_WIDTH {
+> +	OPAL_WIDTH_TINY,
+> +	OPAL_WIDTH_SHORT,
+> +	OPAL_WIDTH_MEDIUM,
+> +	OPAL_WIDTH_LONG,
+> +	OPAL_WIDTH_TOKEN
+> +};
+> +
+> +/* Locking state for a locking range */
+> +enum OPAL_LOCKINGSTATE {
+> +	OPAL_LOCKING_READWRITE = 0x01,
+> +	OPAL_LOCKING_READONLY = 0x02,
+> +	OPAL_LOCKING_LOCKED = 0x03,
+> +};
+> +
+> +/*
+> + * Structures to build and decode the Opal SSC messages
+> + * fields that are NOT really numeric are defined as u8[] to
+> + * help reduce the endianness issues
+> + */
+> +
+> +/* Comm Packet (header) for transmissions. */
+> +struct opal_compacket {
+> +	u32 reserved0;
+> +	u8 extendedComID[4];
+> +	u32 outstandingData;
+> +	u32 minTransfer;
+> +	u32 length;
+> +};
+> +
+> +/* Packet structure. */
+> +struct opal_packet {
+> +	u32 TSN;
+> +	u32 HSN;
+> +	u32 seq_number;
+> +	u16 reserved0;
+> +	u16 ack_type;
+> +	u32 acknowledgment;
+> +	u32 length;
+> +};
+> +
+> +/* Data sub packet header */
+> +struct opal_data_subpacket {
+> +	u8 reserved0[6];
+> +	u16 kind;
+> +	u32 length;
+> +};
+> +
+> +/* header of a response */
+> +struct opal_header {
+> +	struct opal_compacket cp;
+> +	struct opal_packet pkt;
+> +	struct opal_data_subpacket subpkt;
+> +};
+> +
+> +#define FC_TPER       0x0001
+> +#define FC_LOCKING    0x0002
+> +#define FC_GEOMETRY   0x0003
+> +#define FC_ENTERPRISE 0x0100
+> +#define FC_DATASTORE  0x0202
+> +#define FC_SINGLEUSER 0x0201
+> +#define FC_OPALV100   0x0200
+> +#define FC_OPALV200   0x0203
+> +
+> +/*
+> + * The Discovery 0 Header. As defined in
+> + * Opal SSC Documentation
+> + */
+> +struct d0_header {
+> +	u32 length; /* the length of the header 48 in 2.00.100 */
+> +	u32 revision; /**< revision of the header 1 in 2.00.100 */
+> +	u32 reserved01;
+> +	u32 reserved02;
+> +	/*
+> +	 * the remainder of the structure is vendor specific and will not be
+> +	 * addressed now
+> +	 */
+> +	u8 ignored[32];
+> +};
+> +
+> +/*
+> + * TPer Feature Descriptor. Contains flags indicating support for the
+> + * TPer features described in the OPAL specification. The names match the
+> + * OPAL terminology
+> + *
+> + * code == 0x001 in 2.00.100
+> + */
+> +struct d0_tper_features {
+> +	/*
+> +	 * supported_features bits:
+> +	 * bit 7: reserved
+> +	 * bit 6: com ID management
+> +	 * bit 5: reserved
+> +	 * bit 4: streaming support
+> +	 * bit 3: buffer management
+> +	 * bit 2: ACK/NACK
+> +	 * bit 1: async
+> +	 * bit 0: sync
+> +	 */
+> +	u8 supported_features;
+> +	/*
+> +	 * bytes 5 through 15 are reserved, but we represent the first 3 as
+> +	 * u8 to keep the other two 32bits integers aligned.
+> +	 */
+> +	u8 reserved01[3];
+> +	u32 reserved02;
+> +	u32 reserved03;
+> +};
+> +
+> +/*
+> + * Locking Feature Descriptor. Contains flags indicating support for the
+> + * locking features described in the OPAL specification. The names match the
+> + * OPAL terminology
+> + *
+> + * code == 0x0002 in 2.00.100
+> + */
+> +struct d0_locking_features {
+> +	/*
+> +	 * supported_features bits:
+> +	 * bits 6-7: reserved
+> +	 * bit 5: MBR done
+> +	 * bit 4: MBR enabled
+> +	 * bit 3: media encryption
+> +	 * bit 2: locked
+> +	 * bit 1: locking enabled
+> +	 * bit 0: locking supported
+> +	 */
+> +	u8 supported_features;
+> +	/*
+> +	 * bytes 5 through 15 are reserved, but we represent the first 3 as
+> +	 * u8 to keep the other two 32bits integers aligned.
+> +	 */
+> +	u8 reserved01[3];
+> +	u32 reserved02;
+> +	u32 reserved03;
+> +};
+> +
+> +/*
+> + * Geometry Feature Descriptor. Contains flags indicating support for the
+> + * geometry features described in the OPAL specification. The names match the
+> + * OPAL terminology
+> + *
+> + * code == 0x0003 in 2.00.100
+> + */
+> +struct d0_geometry_features {
+> +	/*
+> +	 * skip 32 bits from header, needed to align the struct to 64 bits.
+> +	 */
+> +	u8 header[4];
+> +	/*
+> +	 * reserved01:
+> +	 * bits 1-6: reserved
+> +	 * bit 0: align
+> +	 */
+> +	u8 reserved01;
+> +	u8 reserved02[7];
+> +	u32 logical_block_size;
+> +	u64 alignment_granularity;
+> +	u64 lowest_aligned_lba;
+> +};
+> +
+> +/*
+> + * Enterprise SSC Feature
+> + *
+> + * code == 0x0100
+> + */
+> +struct d0_enterprise_ssc {
+> +	u16 baseComID;
+> +	u16 numComIDs;
+> +	/* range_crossing:
+> +	 * bits 1-6: reserved
+> +	 * bit 0: range crossing
+> +	 */
+> +	u8 range_crossing;
+> +	u8 reserved01;
+> +	u16 reserved02;
+> +	u32 reserved03;
+> +	u32 reserved04;
+> +};
+> +
+> +/*
+> + * Opal V1 feature
+> + *
+> + * code == 0x0200
+> + */
+> +struct d0_opal_v100 {
+> +	u16 baseComID;
+> +	u16 numComIDs;
+> +};
+> +
+> +/*
+> + * Single User Mode feature
+> + *
+> + * code == 0x0201
+> + */
+> +struct d0_single_user_mode {
+> +	u32 num_locking_objects;
+> +	/* reserved01:
+> +	 * bit 0: any
+> +	 * bit 1: all
+> +	 * bit 2: policy
+> +	 * bits 3-7: reserved
+> +	 */
+> +	u8 reserved01;
+> +	u8 reserved02;
+> +	u16 reserved03;
+> +	u32 reserved04;
+> +};
+> +
+> +/*
+> + * Additonal Datastores feature
+> + *
+> + * code == 0x0202
+> + */
+> +struct d0_datastore_table {
+> +	u16 reserved01;
+> +	u16 max_tables;
+> +	u32 max_size_tables;
+> +	u32 table_size_alignment;
+> +};
+> +
+> +/*
+> + * OPAL 2.0 feature
+> + *
+> + * code == 0x0203
+> + */
+> +struct d0_opal_v200 {
+> +	u16 baseComID;
+> +	u16 numComIDs;
+> +	/* range_crossing:
+> +	 * bits 1-6: reserved
+> +	 * bit 0: range crossing
+> +	 */
+> +	u8 range_crossing;
+> +	/* num_locking_admin_auth:
+> +	 * not aligned to 16 bits, so use two u8.
+> +	 * stored in big endian:
+> +	 * 0: MSB
+> +	 * 1: LSB
+> +	 */
+> +	u8 num_locking_admin_auth[2];
+> +	/* num_locking_user_auth:
+> +	 * not aligned to 16 bits, so use two u8.
+> +	 * stored in big endian:
+> +	 * 0: MSB
+> +	 * 1: LSB
+> +	 */
+> +	u8 num_locking_user_auth[2];
+> +	u8 initialPIN;
+> +	u8 revertedPIN;
+> +	u8 reserved01;
+> +	u32 reserved02;
+> +};
+> +
+> +/* Union of features used to parse the discovery 0 response */
+> +struct d0_features {
+> +	u16 code;
+> +	/*
+> +	 * r_version bits:
+> +	 * bits 4-7: version
+> +	 * bits 0-3: reserved
+> +	 */
+> +	u8 r_version;
+> +	u8 length;
+> +	u8 features[];
+> +};
+> +
+> +struct key *request_user_key(const char *master_desc, const u8 **master_key,
+> +			     size_t *master_keylen);
+> +
+> +#endif /* _NVME_OPAL_INTERNAL_H */
+> diff --git a/lib/sed-opal_key.c b/lib/sed-opal_key.c
+> new file mode 100644
+> index 0000000..0b4de01
+> --- /dev/null
+> +++ b/lib/sed-opal_key.c
+> @@ -0,0 +1,46 @@
+> +/*
+> + * Copyright ? 2016 Intel Corporation
+> + *
+> + * Permission is hereby granted, free of charge, to any person obtaining a
+> + * copy of this software and associated documentation files (the "Software"),
+> + * to deal in the Software without restriction, including without limitation
+> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+> + * and/or sell copies of the Software, and to permit persons to whom the
+> + * Software is furnished to do so, subject to the following conditions:
+> + *
+> + * The above copyright notice and this permission notice (including the next
+> + * paragraph) shall be included in all copies or substantial portions of the
+> + * Software.
+> + *
+> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+> + * IN THE SOFTWARE.
+> + *
+> + * Author:
+> + *    Rafael Antognolli <rafael.antognolli at intel.com>
+> + */
+> +
+> +#include <linux/key.h>
+> +#include "sed-opal_internal.h"
+> +
+> +struct key *request_user_key(const char *master_desc, const u8 **master_key,
+> +			     size_t *master_keylen)
+> +{
+> +	const struct user_key_payload *upayload;
+> +	struct key *ukey;
+> +
+> +	ukey = request_key(&key_type_user, master_desc, NULL);
+> +	if (IS_ERR(ukey))
+> +		goto error;
+> +
+> +	down_read(&ukey->sem);
+> +	upayload = user_key_payload(ukey);
+> +	*master_key = upayload->data;
+> +	*master_keylen = upayload->datalen;
+> +error:
+> +	return ukey;
+> +}
+> diff --git a/lib/sed.c b/lib/sed.c
+> new file mode 100644
+> index 0000000..06cacd9
+> --- /dev/null
+> +++ b/lib/sed.c
+> @@ -0,0 +1,303 @@
+> +#include <linux/blkdev.h>
+> +#include <linux/sed.h>
+> +#include <linux/sed-opal.h>
+> +
+> +#ifndef CONFIG_SED_OPAL
+> +static int sed_opal_save(struct block_device *bdev, struct sed_key *sed)
+> +	{ return -EOPNOTSUPP; }
+> +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key)
+> +	{ return -EOPNOTSUPP; }
+> +static int sed_opal_take_ownership(struct block_device *bdev, struct sed_key *key)
+> +	{ return -EOPNOTSUPP; }
+> +static int sed_opal_activate_lsp(struct block_device *bdev, struct sed_key *key)
+> +	{ return -EOPNOTSUPP; }
+> +static int sed_opal_set_pw(struct block_device *bdev, struct sed_key *key)
+> +	{ return -EOPNOTSUPP; }
+> +static int sed_opal_activate_user(struct block_device *bdev, struct sed_key *key)
+> +	{ return -EOPNOTSUPP; }
+> +static int sed_opal_reverttper(struct block_device *bdev, struct sed_key *key)
+> +	{ return -EOPNOTSUPP; }
+> +static int sed_opal_setup_locking_range(struct block_device *bdev, struct sed_key *key)
+> +	{ return -EOPNOTSUPP; }
+> +static int sed_opal_adduser_to_lr(struct block_device *bdev, struct sed_key *key)
+> +	{ return -EOPNOTSUPP; }
+> +static int sed_opal_do_mbr(struct block_device *bdev, struct sed_key *key)
+> +	{ return -EOPNOTSUPP; }
+> +static int sed_opal_erase_lr(struct block_device *bdev, struct sed_key *key)
+> +	{ return -EOPNOTSUPP; }
+> +
+> +#else
+> +
+> +static int sed_opal_save(struct block_device *bdev, struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+You might consider pulling this boilerplate out into something like:
+static inline bool bdev_sec_capable(struct block_device *bdev)
+{
+	return bdev && bdev->bd_disk && bdev->bd_disk->fops &&
+	       bdev->bd_disk->fops->sec_ops;
+}
+
+
+> +
+> +	return opal_save(bdev, key);
+> +}
+> +
+> +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	return opal_lock_unlock(bdev, key);
+> +}
+> +
+> +static int sed_opal_take_ownership(struct block_device *bdev,
+> +				   struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	return opal_take_ownership(bdev, key);
+> +}
+> +
+> +static int sed_opal_activate_lsp(struct block_device *bdev,
+> +				 struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	return opal_activate_lsp(bdev, key);
+> +}
+> +
+> +static int sed_opal_set_pw(struct block_device *bdev,
+> +			   struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	return opal_set_new_pw(bdev, key);
+> +}
+> +
+> +static int sed_opal_activate_user(struct block_device *bdev,
+> +				  struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	return opal_activate_user(bdev, key);
+> +}
+> +
+> +static int sed_opal_reverttper(struct block_device *bdev,
+> +			       struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	return opal_reverttper(bdev, key);
+> +}
+> +
+> +static int sed_opal_setup_lr(struct block_device *bdev,
+> +			     struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	return opal_setup_locking_range(bdev, key);
+> +}
+> +
+> +static int sed_opal_adduser_to_lr(struct block_device *bdev,
+> +			     struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	return opal_add_user_to_lr(bdev, key);
+> +}
+> +
+> +static int sed_opal_do_mbr(struct block_device *bdev,
+> +			   struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	return opal_enable_disable_shadow_mbr(bdev, key);
+> +}
+> +
+> +static int sed_opal_erase_lr(struct block_device *bdev,
+> +			     struct sed_key *key)
+> +{
+> +
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	return opal_erase_locking_range(bdev, key);
+> +}
+> +#endif
+> +
+> +int sed_save(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL_LOCK_UNLOCK:
+> +		return sed_opal_save(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> +
+> +int sed_lock_unlock(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL_LOCK_UNLOCK:
+> +		return sed_opal_lock_unlock(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> +
+> +int sed_take_ownership(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL:
+> +		return sed_opal_take_ownership(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> +
+> +int sed_activate_lsp(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL:
+> +		return sed_opal_activate_lsp(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> +
+> +int sed_set_pw(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL_PW:
+> +		return sed_opal_set_pw(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> +
+> +int sed_activate_user(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL_ACT_USR:
+> +		return sed_opal_activate_user(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> +
+> +int sed_reverttper(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL:
+> +		return sed_opal_reverttper(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> +
+> +int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL_LR_SETUP:
+> +		return sed_opal_setup_lr(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> +
+> +int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL_LOCK_UNLOCK:
+> +		return sed_opal_adduser_to_lr(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> +
+> +int sed_do_mbr(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL_MBR_DATA:
+> +		return sed_opal_do_mbr(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> +
+> +int sed_erase_lr(struct block_device *bdev, struct sed_key *key)
+> +{
+> +	if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||
+> +	    !bdev->bd_disk->fops->sec_ops)
+> +		return -EOPNOTSUPP;
+> +
+> +	switch (key->sed_type) {
+> +	case OPAL:
+> +		return sed_opal_erase_lr(bdev, key);
+> +	}
+> +
+> +	return -EOPNOTSUPP;
+> +}
+> -- 
+> 2.7.4
+>
diff --git a/a/content_digest b/N1/content_digest
index dfb67ed..6f0b57e 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -1,2015 +1,4426 @@
  "ref\01477951099-3127-1-git-send-email-scott.bauer@intel.com\0"
  "ref\01477951099-3127-3-git-send-email-scott.bauer@intel.com\0"
- "From\0Jon Derrick <jonathan.derrick@intel.com>\0"
- "Subject\0Re: [RFC PATCH 2/6] lib: Add Sed-opal library\0"
+ "From\0jonathan.derrick@intel.com (Jon Derrick)\0"
+ "Subject\0[RFC PATCH 2/6] lib: Add Sed-opal library\0"
  "Date\0Tue, 1 Nov 2016 12:56:11 -0600\0"
- "To\0Scott Bauer <scott.bauer@intel.com>\0"
- "Cc\0keith.busch@intel.com"
-  hch@infradead.org
-  Rafael.Antognolli@intel.com
-  linux-nvme@lists.infradead.org
-  axboe@fb.com
-  linux-block@vger.kernel.org
- " j.naumann@fu-berlin.de\0"
  "\00:1\0"
  "b\0"
- "SGkgUmFmYWVsLCBTY290dCwKCgpGaXJzdCBvZmYsIGNvbmdyYXRzIG9uIHRoZSBzZXQhIEl0IGxv\n"
- "b2tzIGdvb2Qgc28gZmFyLgoKSnVzdCBzb21lIHNtYWxsIG5pdHMgYmVsb3cgc2luY2UgeW91IGhh\n"
- "dmUgdG8gcmVzcGluIGl0IGFueXdheXMgOikKCk9uIE1vbiwgT2N0IDMxLCAyMDE2IGF0IDAzOjU4\n"
- "OjE1UE0gLTA2MDAsIFNjb3R0IEJhdWVyIHdyb3RlOgo+IFRoaXMgcGF0Y2ggaW1wbGVtZW50cyB0\n"
- "aGUgbmVjZXNzYXJ5IGxvZ2ljIHRvIGJyaW5nIGFuIE9wYWwKPiBlbmFibGVkIGRyaXZlIG91dCBv\n"
- "ZiBhIGZhY3RvcnktZW5hYmxlZCBpbnRvIGEgd29ya2luZwo+IE9wYWwgc3RhdGUuCj4gCj4gVGhp\n"
- "cyBwYXRjaCBzZXQgYWxzbyBlbmFibGVzIGxvZ2ljIHRvIHNhdmUgYSBwYXNzd29yZCB0bwo+IGJl\n"
- "IHJlcGxheWVkIGR1cmluZyBhIHJlc3VtZSBmcm9tIHN1c3BlbmQuIFRoZSBrZXkgY2FuIGJlCj4g\n"
- "c2F2ZWQgaW4gdGhlIGRyaXZlciBvciBpbiB0aGUgS2VybmVsJ3MgS2V5IG1hbmFnbWVudC4KPiAK\n"
- "PiBTaWduZWQtb2ZmLWJ5OiBTY290dCBCYXVlciA8c2NvdHQuYmF1ZXJAaW50ZWwuY29tPgo+IFNp\n"
- "Z25lZC1vZmYtYnk6IFJhZmFlbCBBbnRvZ25vbGxpIDxSYWZhZWwuQW50b2dub2xsaUBpbnRlbC5j\n"
- "b20+Cj4gLS0tCj4gIGxpYi9zZWQtb3BhbC5jICAgICAgICAgIHwgMzMzNyArKysrKysrKysrKysr\n"
- "KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwo+ICBsaWIvc2VkLW9wYWxfaW50ZXJu\n"
- "YWwuaCB8ICA1ODYgKysrKysrKysrCj4gIGxpYi9zZWQtb3BhbF9rZXkuYyAgICAgIHwgICA0NiAr\n"
- "Cj4gIGxpYi9zZWQuYyAgICAgICAgICAgICAgIHwgIDMwMyArKysrKwo+ICA0IGZpbGVzIGNoYW5n\n"
- "ZWQsIDQyNzIgaW5zZXJ0aW9ucygrKQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL3NlZC1vcGFs\n"
- "LmMKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGxpYi9zZWQtb3BhbF9pbnRlcm5hbC5oCj4gIGNyZWF0\n"
- "ZSBtb2RlIDEwMDY0NCBsaWIvc2VkLW9wYWxfa2V5LmMKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGxp\n"
- "Yi9zZWQuYwo+IAo+IGRpZmYgLS1naXQgYS9saWIvc2VkLW9wYWwuYyBiL2xpYi9zZWQtb3BhbC5j\n"
- "Cj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwLi4xMGIzMzQ4Cj4gLS0tIC9k\n"
- "ZXYvbnVsbAo+ICsrKyBiL2xpYi9zZWQtb3BhbC5jCj4gQEAgLTAsMCArMSwzMzM3IEBACj4gKy8q\n"
- "Cj4gKyAqIENvcHlyaWdodCDCqSAyMDE2IEludGVsIENvcnBvcmF0aW9uCj4gKyAqCj4gKyAqIFBl\n"
- "cm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29u\n"
- "IG9idGFpbmluZyBhCj4gKyAqIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBk\n"
- "b2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCj4gKyAqIHRvIGRlYWwgaW4gdGhl\n"
- "IFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRp\n"
- "b24KPiArICogdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gs\n"
- "IGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsCj4gKyAqIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUg\n"
- "U29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZQo+ICsgKiBTb2Z0d2Fy\n"
- "ZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRp\n"
- "b25zOgo+ICsgKgo+ICsgKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJt\n"
- "aXNzaW9uIG5vdGljZSAoaW5jbHVkaW5nIHRoZSBuZXh0Cj4gKyAqIHBhcmFncmFwaCkgc2hhbGwg\n"
- "YmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUK\n"
- "PiArICogU29mdHdhcmUuCj4gKyAqCj4gKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMg\n"
- "SVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCj4gKyAqIElNUExJ\n"
- "RUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hB\n"
- "TlRBQklMSVRZLAo+ICsgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9O\n"
- "SU5GUklOR0VNRU5ULiAgSU4gTk8gRVZFTlQgU0hBTEwKPiArICogVEhFIEFVVEhPUlMgT1IgQ09Q\n"
- "WVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIK\n"
- "PiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBP\n"
- "UiBPVEhFUldJU0UsIEFSSVNJTkcKPiArICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04g\n"
- "V0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUwo+ICsgKiBJTiBU\n"
- "SEUgU09GVFdBUkUuCj4gKyAqCj4gKyAqIEF1dGhvcnM6Cj4gKyAqICAgIFJhZmFlbCBBbnRvZ25v\n"
- "bGxpIDxyYWZhZWwuYW50b2dub2xsaUBpbnRlbC5jb20+Cj4gKyAqICAgIFNjb3R0ICBCYXVlciAg\n"
- "ICAgIDxzY290dC5iYXVlckBpbnRlbC5jb20+Cj4gKyAqLwo+ICsKPiArI2RlZmluZSBwcl9mbXQo\n"
- "Zm10KSBLQlVJTERfTU9ETkFNRSAiOk9QQUw6ICIgZm10Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgv\n"
- "ZGVsYXkuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2RldmljZS5oPgo+ICsjaW5jbHVkZSA8bGludXgv\n"
- "a2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9saXN0Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9n\n"
- "ZW5oZC5oPgo+ICsjaW5jbHVkZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvdWFj\n"
- "Y2Vzcy5oPgo+ICsjaW5jbHVkZSA8dWFwaS9saW51eC9zZWQtb3BhbC5oPgo+ICsjaW5jbHVkZSA8\n"
- "bGludXgvc2VkLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zZWQtb3BhbC5oPgo+ICsjaW5jbHVkZSA8\n"
- "bGludXgvc3RyaW5nLmg+Cj4gKwo+ICsjaW5jbHVkZSAic2VkLW9wYWxfaW50ZXJuYWwuaCIKPiAr\n"
- "Cj4gKyNkZWZpbmUgSU9fQlVGRkVSX0xFTkdUSCAyMDQ4Cj4gKwo+ICsjZGVmaW5lIE1BWF9UT0tT\n"
- "IDY0Cj4gKwo+ICtzdHJ1Y3Qgb3BhbF9jbWQgewo+ICsJc3RydWN0IGJsb2NrX2RldmljZSAqYmRl\n"
- "djsKPiArCXNlY19jYiAqY2I7Cj4gKwl2b2lkICpjYl9kYXRhOwo+ICsKPiArCXNpemVfdCBwb3M7\n"
- "Cj4gKwl1OCBjbWRfYnVmW0lPX0JVRkZFUl9MRU5HVEggKiAyXTsKPiArCXU4IHJlc3BfYnVmW0lP\n"
- "X0JVRkZFUl9MRU5HVEggKiAyXTsKPiArCXU4ICpjbWQ7Cj4gKwl1OCAqcmVzcDsKPiArfTsKPiAr\n"
- "Cj4gKy8qCj4gKyAqIE9uIHRoZSBwYXJzZWQgcmVzcG9uc2UsIHdlIGRvbid0IHN0b3JlIGFnYWlu\n"
- "IHRoZSB0b2tzIHRoYXQgYXJlIGFscmVhZHkKPiArICogc3RvcmVkIGluIHRoZSByZXNwb25zZSBi\n"
- "dWZmZXIuIEluc3RlYWQsIGZvciBlYWNoIHRva2VuLCB3ZSBqdXN0IHN0b3JlIGEKPiArICogcG9p\n"
- "bnRlciB0byB0aGUgcG9zaXRpb24gaW4gdGhlIGJ1ZmZlciB3aGVyZSB0aGUgdG9rZW4gc3RhcnRz\n"
- "LCBhbmQgdGhlIHNpemUKPiArICogb2YgdGhlIHRva2VuIGluIGJ5dGVzLgo+ICsgKi8KPiArc3Ry\n"
- "dWN0IG9wYWxfcmVzcF90b2sgewo+ICsJY29uc3QgdTggKnBvczsKPiArCXNpemVfdCBsZW47Cj4g\n"
- "KwllbnVtIE9QQUxfUkVTUE9OU0VfVE9LRU4gdHlwZTsKPiArCWVudW0gT1BBTF9BVE9NX1dJRFRI\n"
- "IHdpZHRoOwo+ICsJdW5pb24gewo+ICsJCXU2NCB1Owo+ICsJCXM2NCBzOwo+ICsJfSBzdG9yZWQ7\n"
- "Cj4gK307Cj4gKwo+ICsvKgo+ICsgKiBGcm9tIHRoZSByZXNwb25zZSBoZWFkZXIgaXQncyBub3Qg\n"
- "cG9zc2libGUgdG8ga25vdyBob3cgbWFueSB0b2tlbnMgdGhlcmUgYXJlCj4gKyAqIG9uIHRoZSBw\n"
- "YXlsb2FkLiBTbyB3ZSBoYXJkY29kZSB0aGF0IHRoZSBtYXhpbXVtIHdpbGwgYmUgTUFYX1RPS1Ms\n"
- "IGFuZCBsYXRlcgo+ICsgKiBpZiB3ZSBzdGFydCBkZWFsaW5nIHdpdGggbWVzc2FnZXMgdGhhdCBo\n"
- "YXZlIG1vcmUgdGhhbiB0aGF0LCB3ZSBjYW4gaW5jcmVhc2UKPiArICogdGhpcyBudW1iZXIuIFRo\n"
- "aXMgaXMgZG9uZSB0byBhdm9pZCBoYXZpbmcgdG8gbWFrZSB0d28gcGFzc2VzIHRocm91Z2ggdGhl\n"
- "Cj4gKyAqIHJlc3BvbnNlLCB0aGUgZmlyc3Qgb25lIGNvdW50aW5nIGhvdyBtYW55IHRva2VucyB3\n"
- "ZSBoYXZlIGFuZCB0aGUgc2Vjb25kIG9uZQo+ICsgKiBhY3R1YWxseSBzdG9yaW5nIHRoZSBwb3Np\n"
- "dGlvbnMuCj4gKyAqLwo+ICtzdHJ1Y3QgcGFyc2VkX3Jlc3Agewo+ICsJaW50IG51bTsKPiArCXN0\n"
- "cnVjdCBvcGFsX3Jlc3BfdG9rIHRva3NbTUFYX1RPS1NdOwo+ICt9Owo+ICsKPiArc3RydWN0IG9w\n"
- "YWxfZGV2Owo+ICsKPiArdHlwZWRlZiB2b2lkICgqb3BhbF9jYikoaW50IGVycm9yLCBzdHJ1Y3Qg\n"
- "b3BhbF9kZXYgKmRldik7Cj4gKwo+ICt0eXBlZGVmIGludCAoKm9wYWxfc3RlcCkoc3RydWN0IG9w\n"
- "YWxfZGV2ICpkZXYpOwo+ICsKPiArc3RydWN0IG9wYWxfY29tcGxldGlvbiB7Cj4gKwlzdHJ1Y3Qg\n"
- "Y29tcGxldGlvbiBjbWRfY29tcGxldGlvbjsKPiArCWludCBjb21wbGV0aW9uX3N0YXR1czsKPiAr\n"
- "fTsKPiArCj4gK3N0cnVjdCBvcGFsX2RldiB7Cj4gKwlzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2\n"
- "Owo+ICsJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCXN0cnVjdCBvcGFs\n"
- "X2xvY2tfdW5sb2NrIGxrdWw7Cj4gKwljb25zdCBvcGFsX3N0ZXAgKmZ1bmNzOwo+ICsJdm9pZCAq\n"
- "KmZ1bmNfZGF0YTsKPiArCWJvb2wgcmVzdW1lX2Zyb21fc3VzcGVuZDsKPiArCXN0cnVjdCBvcGFs\n"
- "X3N1c3BlbmRfdW5sayAqcmVzdW1lX2RhdGE7Cj4gKwlzaXplX3QgbnVtX2Z1bmNfZGF0YTsKPiAr\n"
- "CWF0b21pY190IGluX3VzZTsKPiArCXNlY3Rvcl90IHN0YXJ0Owo+ICsJc2VjdG9yX3QgbGVuZ3Ro\n"
- "Owo+ICsJdTggbHI7Cj4gKwl1OCBrZXlfdHlwZTsKPiArCXU4IGtleV9uYW1lW09QQUxfS0VZX01B\n"
- "WF07Cj4gKwlzaXplX3Qga2V5X25hbWVfbGVuOwo+ICsJdTgga2V5W09QQUxfS0VZX01BWF07Cj4g\n"
- "KwlzaXplX3Qga2V5X2xlbjsKPiArCXUxNiBjb21JRDsKPiArCXUzMiBIU047Cj4gKwl1MzIgVFNO\n"
- "Owo+ICsJdTY0IGFsaWduOwo+ICsJdTY0IGxvd2VzdF9sYmE7Cj4gKwlzdHJ1Y3QgbGlzdF9oZWFk\n"
- "IG5vZGU7Cj4gKwljaGFyIGRpc2tfbmFtZVtESVNLX05BTUVfTEVOXTsKPiArCWludCBzdGF0ZTsK\n"
- "PiArCj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgY21kOwo+ICsJc3RydWN0IHBhcnNlZF9yZXNwIHBhcnNl\n"
- "ZDsKPiArCj4gKwlzaXplX3QgcHJldl9kX2xlbjsKPiArCXZvaWQgKnByZXZfZGF0YTsKPiArCj4g\n"
- "KwlzZWNfY2IgKmZpbmFsX2NiOwo+ICsJdm9pZCAqZmluYWxfY2JfZGF0YTsKPiArCW9wYWxfc3Rl\n"
- "cCBlcnJvcl9jYjsKPiArCXZvaWQgKmVycm9yX2NiX2RhdGE7Cj4gKwlvcGFsX2NiIG9wZXJfY2I7\n"
- "Cj4gK307Cj4gKwo+ICtMSVNUX0hFQUQob3BhbF9saXN0KTsKPiArREVGSU5FX1NQSU5MT0NLKGxp\n"
- "c3Rfc3BpbmxvY2spOwo+ICsKPiArc3RhdGljIHZvaWQgcHJpbnRfYnVmZmVyKGNvbnN0IHU4ICpw\n"
- "dHIsIHUzMiBsZW5ndGgpCj4gK3sKPiArI2lmZGVmIERFQlVHCj4gKwlwcmludF9oZXhfZHVtcF9i\n"
- "eXRlcygiT1BBTDogIiwgRFVNUF9QUkVGSVhfT0ZGU0VULCBwdHIsIGxlbmd0aCk7Cj4gKwlwcl9k\n"
- "ZWJ1ZygiXG4iKTsKPiArI2VuZGlmCj4gK30KPiArCj4gKyNkZWZpbmUgVFBFUl9TWU5DX1NVUFBP\n"
- "UlRFRCBCSVQoMCkKPiArCj4gK3N0YXRpYyBib29sIGNoZWNrX3RwZXIoY29uc3Qgdm9pZCAqZGF0\n"
- "YSkKPiArewo+ICsJY29uc3Qgc3RydWN0IGQwX3RwZXJfZmVhdHVyZXMgKnRwZXIgPSBkYXRhOwo+\n"
- "ICsJdTggZmxhZ3MgPSB0cGVyLT5zdXBwb3J0ZWRfZmVhdHVyZXM7Cj4gKwo+ICsJaWYgKCEoZmxh\n"
- "Z3MgJiBUUEVSX1NZTkNfU1VQUE9SVEVEKSkgewo+ICsJCXByX2VycigiVFBlciBzeW5jIG5vdCBz\n"
- "dXBwb3J0ZWQuIGZsYWdzID0gJWRcbiIsCj4gKwkJICAgICAgIHRwZXItPnN1cHBvcnRlZF9mZWF0\n"
- "dXJlcyk7Cj4gKwkJcmV0dXJuIGZhbHNlOwo+ICsJfQo+ICsKPiArCXJldHVybiB0cnVlOwo+ICt9\n"
- "Cj4gKwo+ICtzdGF0aWMgYm9vbCBjaGVja19TVU0oY29uc3Qgdm9pZCAqZGF0YSkKPiArewo+ICsJ\n"
- "Y29uc3Qgc3RydWN0IGQwX3NpbmdsZV91c2VyX21vZGUgKnN1bSA9IGRhdGE7Cj4gKwl1MzIgbmxv\n"
- "ID0gYmUzMl90b19jcHUoc3VtLT5udW1fbG9ja2luZ19vYmplY3RzKTsKPiArCj4gKwlpZiAobmxv\n"
- "ID09IDApIHsKPiArCQlwcl9lcnIoIk5lZWQgYXQgbGVhc3Qgb25lIGxvY2tpbmcgb2JqZWN0Llxu\n"
- "Iik7Cj4gKwkJcmV0dXJuIGZhbHNlOwo+ICsJfQo+ICsKPiArCXByX2RlYnVnKCJOdW1iZXIgb2Yg\n"
- "bG9ja2luZyBvYmplY3RzOiAlZFxuIiwgbmxvKTsKPiArCj4gKwlyZXR1cm4gdHJ1ZTsKPiArfQo+\n"
- "ICsKPiArc3RhdGljIHUxNiBnZXRfY29tSURfdjEwMChjb25zdCB2b2lkICpkYXRhKQo+ICt7Cj4g\n"
- "Kwljb25zdCBzdHJ1Y3QgZDBfb3BhbF92MTAwICp2MTAwID0gZGF0YTsKPiArCj4gKwlyZXR1cm4g\n"
- "YmUxNl90b19jcHUodjEwMC0+YmFzZUNvbUlEKTsKPiArfQo+ICsKPiArc3RhdGljIHUxNiBnZXRf\n"
- "Y29tSURfdjIwMChjb25zdCB2b2lkICpkYXRhKQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3QgZDBfb3Bh\n"
- "bF92MjAwICp2MjAwID0gZGF0YTsKPiArCj4gKwlyZXR1cm4gYmUxNl90b19jcHUodjIwMC0+YmFz\n"
- "ZUNvbUlEKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBfX29wYWxfc2VuZF9jbWQoc3RydWN0IG9w\n"
- "YWxfc3VzcGVuZF91bmxrICpkYXRhLCB1MTYgY29tSUQsCj4gKwkJCSAgIHZvaWQgKmJ1ZmZlciwg\n"
- "c2l6ZV90IGJ1Zmxlbiwgc2VjX2NiICpjYiwKPiArCQkJICAgdm9pZCAqY2JfZGF0YSkKPiArewo+\n"
- "ICsJcmV0dXJuIGRhdGEtPm9wcy5zZW5kKGRhdGEtPmRhdGEsIGNvbUlELCBUQ0dfU0VDUF8wMSwg\n"
- "YnVmZmVyLCBidWZsZW4sCj4gKwkJCSAgICAgY2IsIGNiX2RhdGEpOwo+ICt9Cj4gK3N0YXRpYyBp\n"
- "bnQgX29wYWxfc2VuZF9jbWQoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgdTE2IGNvbUlELAo+\n"
- "ICsJCQkgIHZvaWQgKmJ1ZmZlciwgc2l6ZV90IGJ1ZmxlbiwKPiArCQkJICBzZWNfY2IgKmNiLCB2\n"
- "b2lkICpjYl9kYXRhKQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3Qgc2VjX29wcyAqb3BzID0gYmRldi0+\n"
- "YmRfZGlzay0+Zm9wcy0+c2VjX29wczsKPiArCj4gKwlyZXR1cm4gb3BzLT5zZW5kKGJkZXYtPmJk\n"
- "X2Rpc2stPnByaXZhdGVfZGF0YSwgY29tSUQsCj4gKwkJCSBUQ0dfU0VDUF8wMSwgYnVmZmVyLCBi\n"
- "dWZsZW4sCj4gKwkJCSBjYiwgY2JfZGF0YSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgX19vcGFs\n"
- "X3JlY3ZfY21kKHN0cnVjdCBvcGFsX3N1c3BlbmRfdW5sayAqZGF0YSwgdTE2IGNvbUlELAo+ICsJ\n"
- "CQkgICB2b2lkICpidWZmZXIsIHNpemVfdCBidWZsZW4sIHNlY19jYiAqY2IsCj4gKwkJCSAgIHZv\n"
- "aWQgKmNiX2RhdGEpCj4gK3sKPiArCXJldHVybiBkYXRhLT5vcHMucmVjdihkYXRhLT5kYXRhLCBj\n"
- "b21JRCwgVENHX1NFQ1BfMDEsIGJ1ZmZlciwgYnVmbGVuLAo+ICsJCQkgICAgIGNiLCBjYl9kYXRh\n"
- "KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBfb3BhbF9yZWN2X2NtZChzdHJ1Y3QgYmxvY2tfZGV2\n"
- "aWNlICpiZGV2LCB1MTYgY29tSUQsCj4gKwkJCSAgdm9pZCAqYnVmZmVyLCBzaXplX3QgYnVmbGVu\n"
- "LAo+ICsJCQkgIHNlY19jYiAqY2IsIHZvaWQgKmNiX2RhdGEpCj4gK3sKPiArCWNvbnN0IHN0cnVj\n"
- "dCBzZWNfb3BzICpvcHMgPSBiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzOwo+ICsKPiArCXJl\n"
- "dHVybiBvcHMtPnJlY3YoYmRldi0+YmRfZGlzay0+cHJpdmF0ZV9kYXRhLCBjb21JRCwKPiArCQkJ\n"
- "IFRDR19TRUNQXzAxLCBidWZmZXIsIGJ1ZmxlbiwKPiArCQkJIGNiLCBjYl9kYXRhKTsKPiArfQo+\n"
- "ICsKPiArc3RhdGljIHZvaWQgb3BhbF9zZW5kX2NiX2NvbnQoaW50IGVycm9yLCB2b2lkICpkYXRh\n"
- "KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7Cj4gKwlzaXplX3QgYnVmbGVu\n"
- "ID0gSU9fQlVGRkVSX0xFTkdUSDsKPiArCXZvaWQgKmJ1ZmZlciA9IGRldi0+Y21kLnJlc3A7Cj4g\n"
- "KwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9IGJ1ZmZlcjsKPiArCj4gKwlwcl9kZWJ1ZygiJXM6\n"
- "IFNlbnQgT1BBTCBjb21tYW5kOiBlcnJvcj0lZCwgb3V0c3RhbmRpbmc9JWQsIG1pblRyYW5zZmVy\n"
- "PSVkXG4iLAo+ICsJICAgICAgIGRldi0+ZGlza19uYW1lLCBlcnJvciwgaGRyLT5jcC5vdXRzdGFu\n"
- "ZGluZ0RhdGEsCj4gKwkgICAgICAgaGRyLT5jcC5taW5UcmFuc2Zlcik7Cj4gKwo+ICsJaWYgKGVy\n"
- "cm9yIHx8IGhkci0+Y3Aub3V0c3RhbmRpbmdEYXRhID09IDAgfHwKPiArCSAgICBoZHItPmNwLm1p\n"
- "blRyYW5zZmVyICE9IDApIHsKPiArCQlpZiAoZGV2LT5jbWQuY2IpCj4gKwkJCWRldi0+Y21kLmNi\n"
- "KGVycm9yLCBkZXYtPmNtZC5jYl9kYXRhKTsKPiArCQlyZXR1cm47Cj4gKwl9Cj4gKwo+ICsJbWVt\n"
- "c2V0KGJ1ZmZlciwgMCwgYnVmbGVuKTsKPiArCWlmIChkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQp\n"
- "Cj4gKwkJX19vcGFsX3JlY3ZfY21kKGRldi0+cmVzdW1lX2RhdGEsIGRldi0+Y29tSUQsCj4gKwkJ\n"
- "CQlidWZmZXIsIGJ1Zmxlbiwgb3BhbF9zZW5kX2NiX2NvbnQsIGRldik7Cj4gKwllbHNlCj4gKwkJ\n"
- "X29wYWxfcmVjdl9jbWQoZGV2LT5iZGV2LCBkZXYtPmNvbUlELCBidWZmZXIsIGJ1ZmxlbiwKPiAr\n"
- "CQkJICAgICAgIG9wYWxfc2VuZF9jYl9jb250LCBkZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9p\n"
- "ZCBvcGFsX3NlbmRfY2IoaW50IGVycm9yLCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3Qgb3Bh\n"
- "bF9kZXYgKmRldiA9IGRhdGE7Cj4gKwlzaXplX3QgYnVmbGVuID0gSU9fQlVGRkVSX0xFTkdUSDsK\n"
- "PiArCXZvaWQgKmJ1ZmZlciA9IGRldi0+Y21kLnJlc3A7Cj4gKwo+ICsJaWYgKGVycm9yKSB7Cj4g\n"
- "KwkJaWYgKGRldi0+Y21kLmNiKQo+ICsJCQlkZXYtPmNtZC5jYihlcnJvciwgZGV2LT5jbWQuY2Jf\n"
- "ZGF0YSk7Cj4gKwkJcmV0dXJuOwo+ICsJfQo+ICsKPiArCW1lbXNldChidWZmZXIsIDAsIGJ1Zmxl\n"
- "bik7Cj4gKwlpZiAoZGV2LT5yZXN1bWVfZnJvbV9zdXNwZW5kKQo+ICsJCV9fb3BhbF9yZWN2X2Nt\n"
- "ZChkZXYtPnJlc3VtZV9kYXRhLCBkZXYtPmNvbUlELAo+ICsJCQkJYnVmZmVyLCBidWZsZW4sIG9w\n"
- "YWxfc2VuZF9jYl9jb250LCBkZXYpOwo+ICsJZWxzZQo+ICsJCV9vcGFsX3JlY3ZfY21kKGRldi0+\n"
- "YmRldiwgZGV2LT5jb21JRCwgYnVmZmVyLCBidWZsZW4sCj4gKwkJCSAgICAgICBvcGFsX3NlbmRf\n"
- "Y2JfY29udCwgZGV2KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBvcGFsX3NlbmRfcmVjdihzdHJ1\n"
- "Y3Qgb3BhbF9kZXYgKmRldiwgc2VjX2NiICpjYiwgdm9pZCAqY2JfZGF0YSkKPiArewo+ICsJc2l6\n"
- "ZV90IGJ1ZmxlbiA9IElPX0JVRkZFUl9MRU5HVEg7Cj4gKwl2b2lkICpidWZmZXIgPSBkZXYtPmNt\n"
- "ZC5jbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWRldi0+Y21kLmNiID0gY2I7Cj4gKwlkZXYtPmNt\n"
- "ZC5jYl9kYXRhID0gY2JfZGF0YTsKPiArCWlmIChkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQpCj4g\n"
- "KwkJcmV0ID0gX19vcGFsX3NlbmRfY21kKGRldi0+cmVzdW1lX2RhdGEsIGRldi0+Y29tSUQsIGJ1\n"
- "ZmZlciwKPiArCQkJCSAgICAgIGJ1Zmxlbiwgb3BhbF9zZW5kX2NiLCBkZXYpOwo+ICsJZWxzZQo+\n"
- "ICsJCXJldCA9IF9vcGFsX3NlbmRfY21kKGRldi0+YmRldiwgZGV2LT5jb21JRCwgYnVmZmVyLCBi\n"
- "dWZsZW4sCj4gKwkJCQkgICAgIG9wYWxfc2VuZF9jYiwgZGV2KTsKPiArCj4gKwlyZXR1cm4gcmV0\n"
- "Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjaGVja19nZW9tZXRyeShzdHJ1Y3Qgb3BhbF9kZXYg\n"
- "KmRldiwgY29uc3Qgdm9pZCAqZGF0YSkKPiArewo+ICsJY29uc3Qgc3RydWN0IGQwX2dlb21ldHJ5\n"
- "X2ZlYXR1cmVzICpnZW8gPSBkYXRhOwo+ICsKPiArCWRldi0+YWxpZ24gPSBnZW8tPmFsaWdubWVu\n"
- "dF9ncmFudWxhcml0eTsKPiArCWRldi0+bG93ZXN0X2xiYSA9IGdlby0+bG93ZXN0X2FsaWduZWRf\n"
- "bGJhOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBvcGFsX2Rpc2NvdmVyeTBfZW5kKGludCBlcnJv\n"
- "ciwgdm9pZCAqZGF0YSkKPiArewo+ICsJYm9vbCBmb3VuZENvbUlEID0gZmFsc2UsIHN1cHBvcnRl\n"
- "ZCA9IHRydWUsIHNpbmdsZV91c2VyID0gZmFsc2U7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9\n"
- "IGRhdGE7Cj4gKwljb25zdCBzdHJ1Y3QgZDBfaGVhZGVyICpoZHI7Cj4gKwljb25zdCB1OCAqZXBv\n"
- "cywgKmNwb3M7Cj4gKwl1MTYgY29tSUQgPSAwOwo+ICsKPiArCWlmIChlcnJvcikgewo+ICsJCXBy\n"
- "X2VycigiJXM6IFNlbmRpbmcgZGlzY292ZXJ5MCBmYWlsZWRcbiIsIGRldi0+ZGlza19uYW1lKTsK\n"
- "PiArCQlnb3RvIGVycl9jYWxsYmFjazsKPiArCX0KPiArCj4gKwllcG9zID0gZGV2LT5jbWQucmVz\n"
- "cDsKPiArCWNwb3MgPSBkZXYtPmNtZC5yZXNwOwo+ICsJaGRyID0gKHN0cnVjdCBkMF9oZWFkZXIg\n"
- "KilkZXYtPmNtZC5yZXNwOwo+ICsKPiArCXByaW50X2J1ZmZlcihkZXYtPmNtZC5yZXNwLCBiZTMy\n"
- "X3RvX2NwdShoZHItPmxlbmd0aCkpOwo+ICsKPiArCWVwb3MgKz0gYmUzMl90b19jcHUoaGRyLT5s\n"
- "ZW5ndGgpOyAvKiBlbmQgb2YgYnVmZmVyICovCj4gKwljcG9zICs9IHNpemVvZigqaGRyKTsgLyog\n"
- "Y3VycmVudCBwb3NpdGlvbiBvbiBidWZmZXIgKi8KPiArCj4gKwl3aGlsZSAoY3BvcyA8IGVwb3Mg\n"
- "JiYgc3VwcG9ydGVkKSB7Cj4gKwkJY29uc3Qgc3RydWN0IGQwX2ZlYXR1cmVzICpib2R5ID0KPiAr\n"
- "CQkJKGNvbnN0IHN0cnVjdCBkMF9mZWF0dXJlcyAqKWNwb3M7Cj4gKwo+ICsJCXN3aXRjaCAoYmUx\n"
- "Nl90b19jcHUoYm9keS0+Y29kZSkpIHsKPiArCQljYXNlIEZDX1RQRVI6Cj4gKwkJCXN1cHBvcnRl\n"
- "ZCA9IGNoZWNrX3RwZXIoYm9keS0+ZmVhdHVyZXMpOwo+ICsJCQlicmVhazsKPiArCQljYXNlIEZD\n"
- "X1NJTkdMRVVTRVI6Cj4gKwkJCXNpbmdsZV91c2VyID0gY2hlY2tfU1VNKGJvZHktPmZlYXR1cmVz\n"
- "KTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBGQ19HRU9NRVRSWToKPiArCQkJY2hlY2tfZ2VvbWV0\n"
- "cnkoZGV2LCBib2R5KTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBGQ19MT0NLSU5HOgo+ICsJCWNh\n"
- "c2UgRkNfRU5URVJQUklTRToKPiArCQljYXNlIEZDX0RBVEFTVE9SRToKPiArCQkJLyogc29tZSBp\n"
- "Z25vcmVkIHByb3BlcnRpZXMgKi8KPiArCQkJcHJfZGVidWcoIiVzOiBGb3VuZCBPUEFMIGZlYXR1\n"
- "cmUgZGVzY3JpcHRpb246ICVkXG4iLAo+ICsJCQkJIGRldi0+ZGlza19uYW1lLCBiZTE2X3RvX2Nw\n"
- "dShib2R5LT5jb2RlKSk7Cj4gKwkJCWJyZWFrOwo+ICsJCWNhc2UgRkNfT1BBTFYxMDA6Cj4gKwkJ\n"
- "CWNvbUlEID0gZ2V0X2NvbUlEX3YxMDAoYm9keS0+ZmVhdHVyZXMpOwo+ICsJCQlmb3VuZENvbUlE\n"
- "ID0gdHJ1ZTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBGQ19PUEFMVjIwMDoKPiArCQkJY29tSUQg\n"
- "PSBnZXRfY29tSURfdjIwMChib2R5LT5mZWF0dXJlcyk7Cj4gKwkJCWZvdW5kQ29tSUQgPSB0cnVl\n"
- "Owo+ICsJCQlicmVhazsKPiArCQlkZWZhdWx0Ogo+ICsJCQlpZiAoYmUxNl90b19jcHUoYm9keS0+\n"
- "Y29kZSkgPiAweGJmZmYpIHsKPiArCQkJCS8qIHZlbmRvciBzcGVjaWZpYywganVzdCBpZ25vcmUg\n"
- "Ki8KPiArCQkJfSBlbHNlIHsKPiArCQkJCXByX3dhcm4oIiVzOiBPUEFMIFVua25vd24gZmVhdHVy\n"
- "ZTogJWRcbiIsCj4gKwkJCQkJZGV2LT5kaXNrX25hbWUsIGJlMTZfdG9fY3B1KGJvZHktPmNvZGUp\n"
- "KTsKPiArCQkJfQpTbWFsbCBuaXQsIGhvdyBhYm91dDoKCmNhc2UgMHhiZmZmIC4uLiAweGZmZmY6\n"
- "CgkvKiB2ZW5kb3Igc3BlY2lmaWMsIGp1c3QgaWdub3JlICovCglicmVhazsKZGVmYXVsdDoKCXBy\n"
- "X3dhcm4oLi4uCgoKCj4gKwkJfQo+ICsJCWNwb3MgKz0gYm9keS0+bGVuZ3RoICsgNDsKPiArCX0K\n"
- "PiArCj4gKwlpZiAoIXN1cHBvcnRlZCkgewo+ICsJCXByX2VycigiJXM6IERldmljZSBub3Qgc3Vw\n"
- "cG9ydGVkXG4iLCBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJZ290byBlcnJfY2FsbGJhY2s7Cj4gKwl9\n"
- "Cj4gKwo+ICsJaWYgKCFzaW5nbGVfdXNlcikKPiArCQlwcl93YXJuKCIlczogRGV2aWNlIGRvZXNu\n"
- "J3Qgc3VwcG9ydCBzaW5nbGUgdXNlciBtb2RlXG4iLAo+ICsJCQlkZXYtPmRpc2tfbmFtZSk7Cj4g\n"
- "Kwo+ICsJaWYgKCFmb3VuZENvbUlEKSB7Cj4gKwkJcHJfd2FybigiJXM6IENvdWxkIG5vdCBmaW5k\n"
- "IE9QQUwgY29tSUQgZm9yIGRldmljZS4gT1BBTCBrZXJuZWwgdW5sb2NraW5nIHdpbGwgYmUgZGlz\n"
- "YWJsZWRcbiIsCj4gKwkJCWRldi0+ZGlza19uYW1lKTsKPiArCQlnb3RvIGVycl9jYWxsYmFjazsK\n"
- "PiArCX0KPiArCj4gKwlkZXYtPmNvbUlEID0gY29tSUQ7Cj4gKwo+ICtlcnJfY2FsbGJhY2s6Cj4g\n"
- "KwlpZiAoZGV2LT5vcGVyX2NiKQo+ICsJCWRldi0+b3Blcl9jYihlcnJvciwgZGV2KTsKPiArfQo+\n"
- "ICsKPiArc3RhdGljIGludCBvcGFsX2Rpc2NvdmVyeTAoc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4g\n"
- "K3sKPiArCW1lbXNldChkZXYtPmNtZC5yZXNwLCAwLCBJT19CVUZGRVJfTEVOR1RIKTsKPiArCj4g\n"
- "KwlpZiAoZGV2LT5yZXN1bWVfZnJvbV9zdXNwZW5kKQo+ICsJCXJldHVybiBfX29wYWxfcmVjdl9j\n"
- "bWQoZGV2LT5yZXN1bWVfZGF0YSwgMHgwMDAxLAo+ICsJCQkJICAgICAgIGRldi0+Y21kLnJlc3As\n"
- "IElPX0JVRkZFUl9MRU5HVEgsCj4gKwkJCQkgICAgICAgb3BhbF9kaXNjb3ZlcnkwX2VuZCwgZGV2\n"
- "KTsKPiArCj4gKwlyZXR1cm4gX29wYWxfcmVjdl9jbWQoZGV2LT5iZGV2LCAweDAwMDEsIGRldi0+\n"
- "Y21kLnJlc3AsCj4gKwkJCSAgICAgIElPX0JVRkZFUl9MRU5HVEgsIG9wYWxfZGlzY292ZXJ5MF9l\n"
- "bmQsCj4gKwkJCSAgICAgIGRldik7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGFkZF90b2tlbl91\n"
- "OChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTggdG9rKQo+ICt7Cj4gKwljbWQtPmNtZFtjbWQtPnBv\n"
- "cysrXSA9IHRvazsKPiArfQo+ICsKPiArc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRkX3Rva2Vu\n"
- "X3U4KHN0cnVjdCBvcGFsX2NtZCAqY21kLCB1OCB0b2spCj4gK3sKPiArCUJVSUxEX0JVR19PTihJ\n"
- "T19CVUZGRVJfTEVOR1RIID49IFNJWkVfTUFYKTsKPiArCj4gKwlpZiAoY21kLT5wb3MgPj0gSU9f\n"
- "QlVGRkVSX0xFTkdUSCAtIDEpIHsKPiArCQlwcl9lcnIoIkVycm9yIGFkZGluZyB1ODogZW5kIG9m\n"
- "IGJ1ZmZlci5cbiIpOwo+ICsJCXJldHVybiAtRVJBTkdFOwo+ICsJfQo+ICsKPiArCWFkZF90b2tl\n"
- "bl91OChjbWQsIHRvayk7Cj4gKwo+ICsJcmV0dXJuIDE7Cj4gK30KPiArCj4gKyNkZWZpbmUgVElO\n"
- "WV9BVE9NX0RBVEFfTUFTSyBHRU5NQVNLKDUsIDApCj4gKyNkZWZpbmUgVElOWV9BVE9NX1NJR05F\n"
- "RCBCSVQoNikKPiArCj4gKyNkZWZpbmUgU0hPUlRfQVRPTV9JRCBCSVQoNykKPiArI2RlZmluZSBT\n"
- "SE9SVF9BVE9NX0JZVEVTVFJJTkcgQklUKDUpCj4gKyNkZWZpbmUgU0hPUlRfQVRPTV9TSUdORUQg\n"
- "QklUKDQpCj4gKyNkZWZpbmUgU0hPUlRfQVRPTV9MRU5fTUFTSyBHRU5NQVNLKDMsIDApCj4gKwo+\n"
- "ICtzdGF0aWMgdm9pZCBhZGRfc2hvcnRfYXRvbV9oZWFkZXIoc3RydWN0IG9wYWxfY21kICpjbWQs\n"
- "IGJvb2wgYnl0ZXN0cmluZywKPiArCQkJCSAgYm9vbCBoYXNfc2lnbiwgaW50IGxlbikKPiArewo+\n"
- "ICsJdTggYXRvbTsKPiArCj4gKwlhdG9tID0gU0hPUlRfQVRPTV9JRDsKPiArCWF0b20gfD0gYnl0\n"
- "ZXN0cmluZyA/IFNIT1JUX0FUT01fQllURVNUUklORyA6IDA7Cj4gKwlhdG9tIHw9IGhhc19zaWdu\n"
- "ID8gU0hPUlRfQVRPTV9TSUdORUQgOiAwOwo+ICsJYXRvbSB8PSBsZW4gJiBTSE9SVF9BVE9NX0xF\n"
- "Tl9NQVNLOwo+ICsKPiArCWFkZF90b2tlbl91OChjbWQsIGF0b20pOwo+ICt9Cj4gKwo+ICsjZGVm\n"
- "aW5lIE1FRElVTV9BVE9NX0lEIChCSVQoNykgfCBCSVQoNikpCj4gKyNkZWZpbmUgTUVESVVNX0FU\n"
- "T01fQllURVNUUklORyBCSVQoNCkKPiArI2RlZmluZSBNRURJVU1fQVRPTV9TSUdORUQgQklUKDMp\n"
- "Cj4gKyNkZWZpbmUgTUVESVVNX0FUT01fTEVOX01BU0sgR0VOTUFTSygyLCAwKQo+ICsKPiArc3Rh\n"
- "dGljIHZvaWQgYWRkX21lZGl1bV9hdG9tX2hlYWRlcihzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgYm9v\n"
- "bCBieXRlc3RyaW5nLAo+ICsJCQkJICAgYm9vbCBoYXNfc2lnbiwgaW50IGxlbikKPiArewo+ICsJ\n"
- "dTggaGVhZGVyMDsKPiArCj4gKwloZWFkZXIwID0gTUVESVVNX0FUT01fSUQ7Cj4gKwloZWFkZXIw\n"
- "IHw9IGJ5dGVzdHJpbmcgPyBNRURJVU1fQVRPTV9CWVRFU1RSSU5HIDogMDsKPiArCWhlYWRlcjAg\n"
- "fD0gaGFzX3NpZ24gPyBNRURJVU1fQVRPTV9TSUdORUQgOiAwOwo+ICsJaGVhZGVyMCB8PSAobGVu\n"
- "ID4+IDgpICYgTUVESVVNX0FUT01fTEVOX01BU0s7Cj4gKwljbWQtPmNtZFtjbWQtPnBvcysrXSA9\n"
- "IGhlYWRlcjA7Cj4gKwljbWQtPmNtZFtjbWQtPnBvcysrXSA9IGxlbjsKPiArfQo+ICsKPiArc3Rh\n"
- "dGljIHZvaWQgYWRkX3Rva2VuX3U2NChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTY0IG51bWJlciwg\n"
- "c2l6ZV90IGxlbikKPiArewo+ICsJYWRkX3Nob3J0X2F0b21faGVhZGVyKGNtZCwgZmFsc2UsIGZh\n"
- "bHNlLCBsZW4pOwo+ICsKPiArCXdoaWxlIChsZW4tLSkgewo+ICsJCXU4IG4gPSBudW1iZXIgPj4g\n"
- "KGxlbiAqIDgpOwo+ICsKPiArCQlhZGRfdG9rZW5fdTgoY21kLCBuKTsKPiArCX0KPiArfQo+ICsK\n"
- "PiArc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRkX3Rva2VuX3U2NChzdHJ1Y3Qgb3BhbF9jbWQg\n"
- "KmNtZCwgdTY0IG51bWJlcikKPiArewo+ICsJaW50IGxlbjsKPiArCWludCBtc2I7Cj4gKwo+ICsJ\n"
- "aWYgKCEobnVtYmVyICYgflRJTllfQVRPTV9EQVRBX01BU0spKQo+ICsJCXJldHVybiB0ZXN0X2Fu\n"
- "ZF9hZGRfdG9rZW5fdTgoY21kLCBudW1iZXIpOwo+ICsKPiArCW1zYiA9IGZscyhudW1iZXIpOwo+\n"
- "ICsJbGVuID0gRElWX1JPVU5EX1VQKG1zYiwgNCk7Cj4gKwo+ICsJaWYgKGNtZC0+cG9zID49IElP\n"
- "X0JVRkZFUl9MRU5HVEggLSBsZW4gLSAxKSB7Cj4gKwkJcHJfZXJyKCJFcnJvciBhZGRpbmcgdTY0\n"
- "OiBlbmQgb2YgYnVmZmVyLlxuIik7Cj4gKwkJcmV0dXJuIC1FUkFOR0U7Cj4gKwl9Cj4gKwo+ICsJ\n"
- "YWRkX3Rva2VuX3U2NChjbWQsIG51bWJlciwgbGVuKTsKPiArCj4gKwkvKiByZXR1cm4gbGVuZ3Ro\n"
- "IG9mIHRva2VuIHBsdXMgYXRvbSAqLwo+ICsJcmV0dXJuIGxlbiArIDE7Cj4gK30KPiArCj4gK3N0\n"
- "YXRpYyB2b2lkIGFkZF90b2tlbl9ieXRlc3RyaW5nKHN0cnVjdCBvcGFsX2NtZCAqY21kLAo+ICsJ\n"
- "CQkJIGNvbnN0IHU4ICpieXRlc3RyaW5nLCBzaXplX3QgbGVuKQo+ICt7Cj4gKwltZW1jcHkoJmNt\n"
- "ZC0+Y21kW2NtZC0+cG9zXSwgYnl0ZXN0cmluZywgbGVuKTsKPiArCWNtZC0+cG9zICs9IGxlbjsK\n"
- "PiArfQo+ICsKPiArc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRkX3Rva2VuX2J5dGVzdHJpbmco\n"
- "c3RydWN0IG9wYWxfY21kICpjbWQsCj4gKwkJCQkJICAgICBjb25zdCB1OCAqYnl0ZXN0cmluZywg\n"
- "c2l6ZV90IGxlbikKPiArewo+ICsJc2l6ZV90IGhlYWRlcl9sZW4gPSAxOwo+ICsJYm9vbCBpc19z\n"
- "aG9ydF9hdG9tID0gdHJ1ZTsKPiArCj4gKwlpZiAobGVuICYgflNIT1JUX0FUT01fTEVOX01BU0sp\n"
- "IHsKPiArCQloZWFkZXJfbGVuID0gMjsKPiArCQlpc19zaG9ydF9hdG9tID0gZmFsc2U7Cj4gKwl9\n"
- "Cj4gKwo+ICsJaWYgKGNtZC0+cG9zID49IElPX0JVRkZFUl9MRU5HVEggLSBsZW4gLSBoZWFkZXJf\n"
- "bGVuKSB7Cj4gKwkJcHJfZXJyKCJFcnJvciBhZGRpbmcgYnl0ZXN0cmluZzogZW5kIG9mIGJ1ZmZl\n"
- "ci5cbiIpOwo+ICsJCXJldHVybiAtRVJBTkdFOwo+ICsJfQo+ICsKPiArCWlmIChpc19zaG9ydF9h\n"
- "dG9tKQo+ICsJCWFkZF9zaG9ydF9hdG9tX2hlYWRlcihjbWQsIHRydWUsIGZhbHNlLCBsZW4pOwo+\n"
- "ICsJZWxzZQo+ICsJCWFkZF9tZWRpdW1fYXRvbV9oZWFkZXIoY21kLCB0cnVlLCBmYWxzZSwgbGVu\n"
- "KTsKPiArCj4gKwlhZGRfdG9rZW5fYnl0ZXN0cmluZyhjbWQsIGJ5dGVzdHJpbmcsIGxlbik7Cj4g\n"
- "Kwo+ICsJcmV0dXJuIGhlYWRlcl9sZW4gKyBsZW47Cj4gK30KPiArCj4gKyNkZWZpbmUgTE9DS0lO\n"
- "R19SQU5HRV9OT05fR0xPQkFMIDB4MDMKPiArCj4gK3N0YXRpYyBpbnQgYnVpbGRfbG9ja2luZ19y\n"
- "YW5nZSh1OCAqYnVmZmVyLCBzaXplX3QgbGVuZ3RoLCB1OCBscikKPiArewo+ICsJaWYgKGxlbmd0\n"
- "aCA8IE9QQUxfVUlEX0xFTkdUSCkKPiArCQlyZXR1cm4gLUVSQU5HRTsKPiArCj4gKwltZW1jcHko\n"
- "YnVmZmVyLCBPUEFMVUlEW09QQUxfTE9DS0lOR1JBTkdFX0dMT0JBTF0sIE9QQUxfVUlEX0xFTkdU\n"
- "SCk7Cj4gKwo+ICsJaWYgKGxyID09IDApCj4gKwkJcmV0dXJuIDA7Cj4gKwlidWZmZXJbNV0gPSBM\n"
- "T0NLSU5HX1JBTkdFX05PTl9HTE9CQUw7Cj4gKwlidWZmZXJbN10gPSBscjsKPiArCj4gKwlyZXR1\n"
- "cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBidWlsZF9sb2NraW5nX3VzZXIodTggKmJ1ZmZl\n"
- "ciwgc2l6ZV90IGxlbmd0aCwgdTggbHIpCj4gK3sKPiArCWlmIChsZW5ndGggPCBPUEFMX1VJRF9M\n"
- "RU5HVEgpCj4gKwkJcmV0dXJuIC1FUkFOR0U7Cj4gKwo+ICsJbWVtY3B5KGJ1ZmZlciwgT1BBTFVJ\n"
- "RFtPUEFMX1VTRVIxX1VJRF0sIE9QQUxfVUlEX0xFTkdUSCk7Cj4gKwo+ICsJYnVmZmVyWzddID0g\n"
- "bHIgKyAxOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBOID0gbnVtYmVy\n"
- "IG9mIGZvcm1hdCBzcGVjaWZpZXJzICgxLTk5OSkgdG8gYmUgcmVwbGljYXRlZAo+ICsgKiBjID0g\n"
- "dTgKPiArICogdSA9IHU2NAo+ICsgKiBzID0gYnl0ZXN0cmluZywgbGVuZ3RoCj4gKyAqCj4gKyAq\n"
- "IHJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjIiwKPiArICoJCQkgICAgICAgdThf\n"
- "dmFsMSk7Cj4gKyAqCj4gKyAqIHJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICIyYzJ1\n"
- "IiwKPiArICoJCQkgICAgICAgdThfdmFsMSwgdThfdmFsMiwgdTY0X3ZhbDEsIHU2NF92YWwyKTsK\n"
- "PiArICoKPiArICogcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgIjNzIiwKPiArICoJ\n"
- "CQkgICAgICAgYnl0ZXN0cmluZzEsIGxlbmd0aDEsCj4gKyAqCQkJICAgICAgIGJ5dGVzdHJpbmcy\n"
- "LCBsZW5ndGgyLAo+ICsgKgkJCSAgICAgICBieXRlc3RyaW5nMywgbGVuZ3RoMyk7Cj4gKyAqLwo+\n"
- "ICtzdGF0aWMgaW50IHRlc3RfYW5kX2FkZF90b2tlbl92YShzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwK\n"
- "PiArCQkJCSBjb25zdCBjaGFyICpmbXQsIC4uLikKPiArewo+ICsJY29uc3QgdTggKml0ID0gZm10\n"
- "LCAqdG1wOwo+ICsJaW50IHJldCwgbnVtID0gMSwgc3VtID0gMDsKPiArCXZhX2xpc3QgYXA7Cj4g\n"
- "Kwo+ICsJdmFfc3RhcnQoYXAsIGZtdCk7Cj4gKwo+ICsJd2hpbGUgKCppdCAhPSAnXDAnKSB7Cj4g\n"
- "KwkJdTY0IHRvazY0ID0gMDsKPiArCQl1OCB0b2ssICpic3RyOwo+ICsJCXNpemVfdCBsZW47Cj4g\n"
- "Kwo+ICsJCXJldCA9IDA7Cj4gKwo+ICsJCXN3aXRjaCAoKml0KSB7Cj4gKwkJY2FzZSAnMScgLi4u\n"
- "ICc5JzoKPiArCQkJdG1wID0gaXQ7Cj4gKwkJCW51bSA9IDA7Cj4gKwkJCXdoaWxlICgqdG1wID49\n"
- "ICcwJyAmJiAqdG1wIDw9ICc5JykKPiArCQkJCW51bSA9IG51bSAqIDEwICsgKCp0bXArKyAtICcw\n"
- "Jyk7Cj4gKwkJCWl0ID0gdG1wOwo+ICsJCQljb250aW51ZTsKPiArCQljYXNlICdjJzoKPiArCQkJ\n"
- "d2hpbGUgKG51bS0tKSB7Cj4gKwkJCQl0b2sgPSB2YV9hcmcoYXAsIHVuc2lnbmVkIGludCk7Cj4g\n"
- "KwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdTgoY21kLCB0b2spOwo+ICsJCQkJaWYgKHJl\n"
- "dCA8IDApCj4gKwkJCQkJZ290byBlcnI7Cj4gKwkJCX0KPiArCQkJbnVtID0gMTsKPiArCQkJYnJl\n"
- "YWs7Cj4gKwkJY2FzZSAndSc6Cj4gKwkJCXdoaWxlIChudW0tLSkgewo+ICsJCQkJdG9rNjQgPSB2\n"
- "YV9hcmcoYXAsIHU2NCk7Cj4gKwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdTY0KGNtZCwg\n"
- "dG9rNjQpOwo+ICsJCQkJaWYgKHJldCA8IDApCj4gKwkJCQkJZ290byBlcnI7Cj4gKwkJCX0KPiAr\n"
- "CQkJbnVtID0gMTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSAncyc6Cj4gKwkJCXdoaWxlIChudW0t\n"
- "LSkgewo+ICsJCQkJYnN0ciA9IHZhX2FyZyhhcCwgdTggKik7Cj4gKwkJCQlsZW4gPSB2YV9hcmco\n"
- "YXAsIHNpemVfdCk7Cj4gKwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fYnl0ZXN0cmluZyhj\n"
- "bWQsIGJzdHIsCj4gKwkJCQkJCQkJICAgIGxlbik7Cj4gKwkJCQlpZiAocmV0IDwgMCkKPiArCQkJ\n"
- "CQlnb3RvIGVycjsKPiArCQkJfQo+ICsJCQludW0gPSAxOwo+ICsJCQlicmVhazsKPiArCQljYXNl\n"
- "ICcgJzoKPiArCQljYXNlICdcdCc6Cj4gKwkJCS8qIGlnbm9yZWQgKi8KPiArCQkJYnJlYWs7Cj4g\n"
- "KwkJZGVmYXVsdDoKPiArCQkJcHJfd2FybigiVW5yZWNvZ25pemVkIHR5cGUuXG4iKTsKPiArCQl9\n"
- "Cj4gKwo+ICsJCWl0Kys7Cj4gKwkJc3VtICs9IHJldDsKPiArCX0KPiArCj4gKwl2YV9lbmQoYXAp\n"
- "Owo+ICsKPiArCXJldHVybiBzdW07Cj4gKwo+ICsgZXJyOgo+ICsJcHJfZXJyKCJUb2tlbiBmYWls\n"
- "ZWQgdG8gYmUgYWRkZWQuXG4iKTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyB2\n"
- "b2lkIHNldF9jb21JRChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTE2IGNvbUlEKQo+ICt7Cj4gKwlz\n"
- "dHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9IChzdHJ1Y3Qgb3BhbF9oZWFkZXIgKiljbWQtPmNtZDsK\n"
- "PiArCj4gKwloZHItPmNwLmV4dGVuZGVkQ29tSURbMF0gPSBjb21JRCA+PiA4Owo+ICsJaGRyLT5j\n"
- "cC5leHRlbmRlZENvbUlEWzFdID0gY29tSUQ7Cj4gKwloZHItPmNwLmV4dGVuZGVkQ29tSURbMl0g\n"
- "PSAwOwo+ICsJaGRyLT5jcC5leHRlbmRlZENvbUlEWzNdID0gMDsKPiArfQo+ICsKPiArc3RhdGlj\n"
- "IGludCBjbWRfZmluYWxpemUoc3RydWN0IG9wYWxfY21kICpjbWQsIHUzMiBoc24sIHUzMiB0c24p\n"
- "Cj4gK3sKPiArCXN0cnVjdCBvcGFsX2hlYWRlciAqaGRyOwo+ICsJaW50IHJldDsKPiArCj4gKwly\n"
- "ZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiNmMiLAo+ICsJCQkJICAgIE9QQUxfRU5E\n"
- "T0ZEQVRBLCBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICAwLCAwLCAwLCBPUEFMX0VORExJU1Qp\n"
- "Owo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCJFcnJvciBmaW5hbGl6aW5nIGNv\n"
- "bW1hbmQuXG4iKTsKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCX0KPiArCj4gKwloZHIgPSAoc3Ry\n"
- "dWN0IG9wYWxfaGVhZGVyICopIGNtZC0+Y21kOwo+ICsKPiArCWhkci0+cGt0LlRTTiA9IGNwdV90\n"
- "b19iZTMyKHRzbik7Cj4gKwloZHItPnBrdC5IU04gPSBjcHVfdG9fYmUzMihoc24pOwo+ICsKPiAr\n"
- "CWhkci0+c3VicGt0Lmxlbmd0aCA9IGNwdV90b19iZTMyKGNtZC0+cG9zIC0gc2l6ZW9mKCpoZHIp\n"
- "KTsKPiArCXdoaWxlIChjbWQtPnBvcyAlIDQpIHsKPiArCQlpZiAoY21kLT5wb3MgPj0gSU9fQlVG\n"
- "RkVSX0xFTkdUSCkgewo+ICsJCQlwcl9lcnIoIkVycm9yOiBCdWZmZXIgb3ZlcnJ1blxuIik7Cj4g\n"
- "KwkJCXJldHVybiAtRVJBTkdFOwo+ICsJCX0KPiArCQljbWQtPmNtZFtjbWQtPnBvcysrXSA9IDA7\n"
- "Cj4gKwl9Cj4gKwloZHItPnBrdC5sZW5ndGggPSBjcHVfdG9fYmUzMihjbWQtPnBvcyAtIHNpemVv\n"
- "ZihoZHItPmNwKSAtCj4gKwkJCQkgICAgICBzaXplb2YoaGRyLT5wa3QpKTsKPiArCWhkci0+Y3Au\n"
- "bGVuZ3RoID0gY3B1X3RvX2JlMzIoY21kLT5wb3MgLSBzaXplb2YoaGRyLT5jcCkpOwo+ICsKPiAr\n"
- "CXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZW51bSBPUEFMX1JFU1BPTlNFX1RPS0VOIHRv\n"
- "a2VuX3R5cGUoY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLAo+ICsJCQkJCSAgIGludCBu\n"
- "KQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rOwo+ICsKPiArCWlmIChu\n"
- "ID49IHJlc3AtPm51bSkgewo+ICsJCXByX2VycigiVG9rZW4gbnVtYmVyIGRvZXNuJ3QgZXhpc3Q6\n"
- "ICVkLCByZXNwOiAlZFxuIiwKPiArCQkgICAgICAgbiwgcmVzcC0+bnVtKTsKPiArCQlyZXR1cm4g\n"
- "T1BBTF9EVEFfVE9LRU5JRF9JTlZBTElEOwo+ICsJfQo+ICsKPiArCXRvayA9ICZyZXNwLT50b2tz\n"
- "W25dOwo+ICsJaWYgKHRvay0+bGVuID09IDApIHsKPiArCQlwcl9lcnIoIlRva2VuIGxlbmd0aCBt\n"
- "dXN0IGJlIG5vbi16ZXJvXG4iKTsKPiArCQlyZXR1cm4gT1BBTF9EVEFfVE9LRU5JRF9JTlZBTElE\n"
- "Owo+ICsJfQo+ICsKPiArCXJldHVybiB0b2stPnR5cGU7Cj4gK30KPiArCj4gKy8qCj4gKyAqIFRo\n"
- "aXMgZnVuY3Rpb24gcmV0dXJucyAwIGluIGNhc2Ugb2YgaW52YWxpZCB0b2tlbi4gT25lIHNob3Vs\n"
- "ZCBjYWxsCj4gKyAqIHRva2VuX3R5cGUoKSBmaXJzdCB0byBmaW5kIG91dCBpZiB0aGUgdG9rZW4g\n"
- "aXMgdmFsaWQgb3Igbm90Lgo+ICsgKi8KPiArc3RhdGljIGVudW0gT1BBTF9UT0tFTiByZXNwb25z\n"
- "ZV9nZXRfdG9rZW4oY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLAo+ICsJCQkJCSAgaW50\n"
- "IG4pCj4gK3sKPiArCWNvbnN0IHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2s7Cj4gKwo+ICsJaWYg\n"
- "KG4gPj0gcmVzcC0+bnVtKSB7Cj4gKwkJcHJfZXJyKCJUb2tlbiBudW1iZXIgZG9lc24ndCBleGlz\n"
- "dDogJWQsIHJlc3A6ICVkXG4iLAo+ICsJCSAgICAgICBuLCByZXNwLT5udW0pOwo+ICsJCXJldHVy\n"
- "biAwOwo+ICsJfQo+ICsKPiArCXRvayA9ICZyZXNwLT50b2tzW25dOwo+ICsJaWYgKHRvay0+bGVu\n"
- "ID09IDApIHsKPiArCQlwcl9lcnIoIlRva2VuIGxlbmd0aCBtdXN0IGJlIG5vbi16ZXJvXG4iKTsK\n"
- "PiArCQlyZXR1cm4gMDsKPiArCX0KPiArCj4gKwlyZXR1cm4gdG9rLT5wb3NbMF07Cj4gK30KPiAr\n"
- "Cj4gK3N0YXRpYyBzaXplX3QgcmVzcG9uc2VfcGFyc2VfdGlueShzdHJ1Y3Qgb3BhbF9yZXNwX3Rv\n"
- "ayAqdG9rLAo+ICsJCQkJICBjb25zdCB1OCAqcG9zKQo+ICt7Cj4gKwl0b2stPnBvcyA9IHBvczsK\n"
- "PiArCXRvay0+bGVuID0gMTsKPiArCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX1RJTlk7Cj4gKwo+\n"
- "ICsJaWYgKHBvc1swXSAmIFRJTllfQVRPTV9TSUdORUQpIHsKPiArCQl0b2stPnR5cGUgPSBPUEFM\n"
- "X0RUQV9UT0tFTklEX1NJTlQ7Cj4gKwl9IGVsc2Ugewo+ICsJCXRvay0+dHlwZSA9IE9QQUxfRFRB\n"
- "X1RPS0VOSURfVUlOVDsKPiArCQl0b2stPnN0b3JlZC51ID0gcG9zWzBdICYgMHgzZjsKPiArCX0K\n"
- "PiArCj4gKwlyZXR1cm4gdG9rLT5sZW47Cj4gK30KPiArCj4gK3N0YXRpYyBzaXplX3QgcmVzcG9u\n"
- "c2VfcGFyc2Vfc2hvcnQoc3RydWN0IG9wYWxfcmVzcF90b2sgKnRvaywKPiArCQkJCSAgIGNvbnN0\n"
- "IHU4ICpwb3MpCj4gK3sKPiArCXRvay0+cG9zID0gcG9zOwo+ICsJdG9rLT5sZW4gPSAocG9zWzBd\n"
- "ICYgU0hPUlRfQVRPTV9MRU5fTUFTSykgKyAxOwo+ICsJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhf\n"
- "U0hPUlQ7Cj4gKwo+ICsJaWYgKHBvc1swXSAmIFNIT1JUX0FUT01fQllURVNUUklORykgewo+ICsJ\n"
- "CXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfQllURVNUUklORzsKPiArCX0gZWxzZSBpZiAo\n"
- "cG9zWzBdICYgU0hPUlRfQVRPTV9TSUdORUQpIHsKPiArCQl0b2stPnR5cGUgPSBPUEFMX0RUQV9U\n"
- "T0tFTklEX1NJTlQ7Cj4gKwl9IGVsc2Ugewo+ICsJCXU2NCB1X2ludGVnZXIgPSAwOwo+ICsJCWlu\n"
- "dCBpLCBiID0gMDsKPiArCj4gKwkJdG9rLT50eXBlID0gT1BBTF9EVEFfVE9LRU5JRF9VSU5UOwo+\n"
- "ICsJCWlmICh0b2stPmxlbiA+IDkpClNob3VsZCB0aGlzIGJlIGxlbiA+IDggb3IgbGVuID49IDkg\n"
- "PwoKPiArCQkJcHJfd2FybigidWludDY0IHdpdGggbW9yZSB0aGFuIDggYnl0ZXNcbiIpOwo+ICsJ\n"
- "CWZvciAoaSA9IHRvay0+bGVuIC0gMTsgaSA+IDA7IGktLSkgewo+ICsJCQl1X2ludGVnZXIgfD0g\n"
- "KCh1NjQpcG9zW2ldIDw8ICg4ICogYikpOwo+ICsJCQliKys7Cj4gKwkJfQpJdCBkb2Vzbid0IGxv\n"
- "b2sgcGFydGljdWxhcmx5IHNhZmUgdG8ga2VlcCB1c2luZyB0aGlzIGRyaXZlciBvbiBhIGRyaXZl\n"
- "CmlmIGl0IHJldHVybnMgYSBsZW4gPiA4LiBCdXQgdGhlIHNwZWNzIGRvIGFsbG93IDE2LWJ5dGUg\n"
- "ZGF0YSBpbiBhIHNob3J0CmF0b20sIHNvIG1heWJlIHdlIHNob3VsZCBiYWlsIG9uIGFsbG93aW5n\n"
- "IHRoZSBkcml2ZXIgdG8gbWFuYWdlIHRoZQpkcml2ZSwgb3IgY2hhbmdlIHRoZSB0eXBlcyB0byBz\n"
- "b21lIDE2LWJ5dGUgdHlwZT8KCj4gKwkJdG9rLT5zdG9yZWQudSA9IHVfaW50ZWdlcjsKPiArCX0K\n"
- "PiArCj4gKwlyZXR1cm4gdG9rLT5sZW47Cj4gK30KPiArCj4gK3N0YXRpYyBzaXplX3QgcmVzcG9u\n"
- "c2VfcGFyc2VfbWVkaXVtKHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2ssCj4gKwkJCQkgICAgY29u\n"
- "c3QgdTggKnBvcykKPiArewo+ICsJdG9rLT5wb3MgPSBwb3M7Cj4gKwl0b2stPmxlbiA9ICgoKHBv\n"
- "c1swXSAmIE1FRElVTV9BVE9NX0xFTl9NQVNLKSA8PCA4KSB8IHBvc1sxXSkgKyAyOwo+ICsJdG9r\n"
- "LT53aWR0aCA9IE9QQUxfV0lEVEhfTUVESVVNOwo+ICsKPiArCWlmIChwb3NbMF0gJiBNRURJVU1f\n"
- "QVRPTV9CWVRFU1RSSU5HKQo+ICsJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfQllURVNU\n"
- "UklORzsKPiArCWVsc2UgaWYgKHBvc1swXSAmIE1FRElVTV9BVE9NX1NJR05FRCkKPiArCQl0b2st\n"
- "PnR5cGUgPSBPUEFMX0RUQV9UT0tFTklEX1NJTlQ7Cj4gKwllbHNlCj4gKwkJdG9rLT50eXBlID0g\n"
- "T1BBTF9EVEFfVE9LRU5JRF9VSU5UOwo+ICsKPiArCXJldHVybiB0b2stPmxlbjsKPiArfQo+ICsK\n"
- "PiArI2RlZmluZSBMT05HX0FUT01fSUQgKEJJVCg3KSB8IEJJVCg2KSB8IEJJVCg1KSkKPiArI2Rl\n"
- "ZmluZSBMT05HX0FUT01fQllURVNUUklORyBCSVQoMSkKPiArI2RlZmluZSBMT05HX0FUT01fU0lH\n"
- "TkVEIEJJVCgwKQo+ICtzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX3BhcnNlX2xvbmcoc3RydWN0IG9w\n"
- "YWxfcmVzcF90b2sgKnRvaywKPiArCQkJCSAgY29uc3QgdTggKnBvcykKPiArewo+ICsJdG9rLT5w\n"
- "b3MgPSBwb3M7Cj4gKwl0b2stPmxlbiA9ICgocG9zWzFdIDw8IDE2KSB8IChwb3NbMl0gPDwgOCkg\n"
- "fCBwb3NbM10pICsgNDsKPiArCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX0xPTkc7Cj4gKwo+ICsJ\n"
- "aWYgKHBvc1swXSAmIExPTkdfQVRPTV9CWVRFU1RSSU5HKQo+ICsJCXRvay0+dHlwZSA9IE9QQUxf\n"
- "RFRBX1RPS0VOSURfQllURVNUUklORzsKPiArCWVsc2UgaWYgKHBvc1swXSAmIExPTkdfQVRPTV9T\n"
- "SUdORUQpCj4gKwkJdG9rLT50eXBlID0gT1BBTF9EVEFfVE9LRU5JRF9TSU5UOwo+ICsJZWxzZQo+\n"
- "ICsJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKPiArCj4gKwlyZXR1cm4gdG9r\n"
- "LT5sZW47Cj4gK30KPiArCj4gK3N0YXRpYyBzaXplX3QgcmVzcG9uc2VfcGFyc2VfdG9rZW4oc3Ry\n"
- "dWN0IG9wYWxfcmVzcF90b2sgKnRvaywKPiArCQkJCSAgIGNvbnN0IHU4ICpwb3MpCj4gK3sKPiAr\n"
- "CXRvay0+cG9zID0gcG9zOwo+ICsJdG9rLT5sZW4gPSAxOwo+ICsJdG9rLT50eXBlID0gT1BBTF9E\n"
- "VEFfVE9LRU5JRF9UT0tFTjsKPiArCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX1RPS0VOOwo+ICsK\n"
- "PiArCXJldHVybiB0b2stPmxlbjsKPiArfQo+ICsKPiArc3RhdGljIGludCByZXNwb25zZV9wYXJz\n"
- "ZShjb25zdCB1OCAqYnVmLCBzaXplX3QgbGVuZ3RoLAo+ICsJCQkgIHN0cnVjdCBwYXJzZWRfcmVz\n"
- "cCAqcmVzcCkKPiArewo+ICsJY29uc3Qgc3RydWN0IG9wYWxfaGVhZGVyICpoZHI7Cj4gKwlzdHJ1\n"
- "Y3Qgb3BhbF9yZXNwX3RvayAqaXRlcjsKPiArCWludCByZXQsIG51bV9lbnRyaWVzID0gMDsKPiAr\n"
- "CXUzMiBjcG9zID0gMCwgdG90YWw7Cj4gKwlzaXplX3QgdG9rZW5fbGVuZ3RoOwo+ICsJY29uc3Qg\n"
- "dTggKnBvczsKPiArCj4gKwlpZiAoIWJ1ZikKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlp\n"
- "ZiAoIXJlc3ApCj4gKwkJcmV0dXJuIC1FRkFVTFQ7Cj4gKwo+ICsJaGRyID0gKHN0cnVjdCBvcGFs\n"
- "X2hlYWRlciAqKWJ1ZjsKPiArCXBvcyA9IGJ1ZjsKPiArCXBvcyArPSBzaXplb2YoKmhkcik7Cj4g\n"
- "Kwo+ICsJcHJfZGVidWcoIlJlc3BvbnNlIHNpemU6IGNwOiAlZCwgcGt0OiAlZCwgc3VicGt0OiAl\n"
- "ZFxuIiwKPiArCQkgYmUzMl90b19jcHUoaGRyLT5jcC5sZW5ndGgpLAo+ICsJCSBiZTMyX3RvX2Nw\n"
- "dShoZHItPnBrdC5sZW5ndGgpLAo+ICsJCSBiZTMyX3RvX2NwdShoZHItPnN1YnBrdC5sZW5ndGgp\n"
- "KTsKPiArCj4gKwlpZiAoKGhkci0+Y3AubGVuZ3RoID09IDApCj4gKwkgICAgfHwgKGhkci0+cGt0\n"
- "Lmxlbmd0aCA9PSAwKQo+ICsJICAgIHx8IChoZHItPnN1YnBrdC5sZW5ndGggPT0gMCkpIHsKPiAr\n"
- "CQlwcl9lcnIoIkJhZCBoZWFkZXIgbGVuZ3RoLiBjcDogJWQsIHBrdDogJWQsIHN1YnBrdDogJWRc\n"
- "biIsCj4gKwkJICAgICAgIGJlMzJfdG9fY3B1KGhkci0+Y3AubGVuZ3RoKSwKPiArCQkgICAgICAg\n"
- "YmUzMl90b19jcHUoaGRyLT5wa3QubGVuZ3RoKSwKPiArCQkgICAgICAgYmUzMl90b19jcHUoaGRy\n"
- "LT5zdWJwa3QubGVuZ3RoKSk7Cj4gKwkJcHJpbnRfYnVmZmVyKHBvcywgc2l6ZW9mKCpoZHIpKTsK\n"
- "PiArCQlyZXQgPSAtRUlOVkFMOwo+ICsJCWdvdG8gZXJyOwo+ICsJfQo+ICsKPiArCWlmIChwb3Mg\n"
- "PiBidWYgKyBsZW5ndGgpIHsKPiArCQlyZXQgPSAtRUZBVUxUOwo+ICsJCWdvdG8gZXJyOwo+ICsJ\n"
- "fQo+ICsKPiArCWl0ZXIgPSByZXNwLT50b2tzOwo+ICsJdG90YWwgPSBiZTMyX3RvX2NwdShoZHIt\n"
- "PnN1YnBrdC5sZW5ndGgpOwo+ICsJcHJpbnRfYnVmZmVyKHBvcywgdG90YWwpOwo+ICsJd2hpbGUg\n"
- "KGNwb3MgPCB0b3RhbCkgewo+ICsJCWlmICghKHBvc1swXSAmIDB4ODApKSAvKiB0aW55IGF0b20g\n"
- "Ki8KPiArCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfdGlueShpdGVyLCBwb3MpOwo+\n"
- "ICsJCWVsc2UgaWYgKCEocG9zWzBdICYgMHg0MCkpIC8qIHNob3J0IGF0b20gKi8KPiArCQkJdG9r\n"
- "ZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2Vfc2hvcnQoaXRlciwgcG9zKTsKPiArCQllbHNlIGlm\n"
- "ICghKHBvc1swXSAmIDB4MjApKSAvKiBtZWRpdW0gYXRvbSAqLwo+ICsJCQl0b2tlbl9sZW5ndGgg\n"
- "PSByZXNwb25zZV9wYXJzZV9tZWRpdW0oaXRlciwgcG9zKTsKPiArCQllbHNlIGlmICghKHBvc1sw\n"
- "XSAmIDB4MTApKSAvKiBsb25nIGF0b20gKi8KPiArCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2Vf\n"
- "cGFyc2VfbG9uZyhpdGVyLCBwb3MpOwo+ICsJCWVsc2UgLyogVE9LRU4gKi8KPiArCQkJdG9rZW5f\n"
- "bGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfdG9rZW4oaXRlciwgcG9zKTsKPiArCj4gKwkJcG9zICs9\n"
- "IHRva2VuX2xlbmd0aDsKPiArCQljcG9zICs9IHRva2VuX2xlbmd0aDsKPiArCQlpdGVyKys7Cj4g\n"
- "KwkJbnVtX2VudHJpZXMrKzsKPiArCX0KPiArCj4gKwlpZiAobnVtX2VudHJpZXMgPT0gMCkgewo+\n"
- "ICsJCXByX2VycigiQ291bGRuJ3QgcGFyc2UgcmVzcG9uc2UuXG4iKTsKPiArCQlyZXQgPSAtRUlO\n"
- "VkFMOwo+ICsJCWdvdG8gZXJyOwo+ICsJfQo+ICsJcmVzcC0+bnVtID0gbnVtX2VudHJpZXM7Cj4g\n"
- "Kwo+ICsJcmV0dXJuIDA7Cj4gK2VycjoKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRp\n"
- "YyBzaXplX3QgcmVzcG9uc2VfZ2V0X3N0cmluZyhjb25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJl\n"
- "c3AsIGludCBuLAo+ICsJCQkJICBjb25zdCBjaGFyICoqc3RvcmUpCj4gK3sKPiArCSpzdG9yZSA9\n"
- "IE5VTEw7Cj4gKwlpZiAoIXJlc3ApIHsKPiArCQlwcl9lcnIoIlJlc3BvbnNlIGlzIE5VTExcbiIp\n"
- "Owo+ICsJCXJldHVybiAwOwo+ICsJfQo+ICsKPiArCWlmIChuID4gcmVzcC0+bnVtKSB7Cj4gKwkJ\n"
- "cHJfZXJyKCJSZXNwb25zZSBoYXMgJWQgdG9rZW5zLiBDYW4ndCBhY2Nlc3MgJWRcbiIsCj4gKwkJ\n"
- "ICAgICAgIHJlc3AtPm51bSwgbik7Cj4gKwkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ICsJaWYgKHJl\n"
- "c3AtPnRva3Nbbl0udHlwZSAhPSBPUEFMX0RUQV9UT0tFTklEX0JZVEVTVFJJTkcpIHsKPiArCQlw\n"
- "cl9lcnIoIlRva2VuIGlzIG5vdCBhIGJ5dGUgc3RyaW5nIVxuIik7Cj4gKwkJcmV0dXJuIDA7Cj4g\n"
- "Kwl9Cj4gKwo+ICsJKnN0b3JlID0gcmVzcC0+dG9rc1tuXS5wb3MgKyAxOwo+ICsJcmV0dXJuIHJl\n"
- "c3AtPnRva3Nbbl0ubGVuIC0gMTsKPiArfQo+ICsKPiArc3RhdGljIHU2NCByZXNwb25zZV9nZXRf\n"
- "dTY0KGNvbnN0IHN0cnVjdCBwYXJzZWRfcmVzcCAqcmVzcCwgaW50IG4pCj4gK3sKPiArCWlmICgh\n"
- "cmVzcCkgewo+ICsJCXByX2VycigiUmVzcG9uc2UgaXMgTlVMTFxuIik7Cj4gKwkJcmV0dXJuIDA7\n"
- "Cj4gKwl9Cj4gKwo+ICsJaWYgKG4gPiByZXNwLT5udW0pIHsKPiArCQlwcl9lcnIoIlJlc3BvbnNl\n"
- "IGhhcyAlZCB0b2tlbnMuIENhbid0IGFjY2VzcyAlZFxuIiwKPiArCQkgICAgICAgcmVzcC0+bnVt\n"
- "LCBuKTsKPiArCQlyZXR1cm4gMDsKPiArCX0KPiArCj4gKwlpZiAocmVzcC0+dG9rc1tuXS50eXBl\n"
- "ICE9IE9QQUxfRFRBX1RPS0VOSURfVUlOVCkgewo+ICsJCXByX2VycigiVG9rZW4gaXMgbm90IHVu\n"
- "c2lnbmVkIGl0OiAlZFxuIiwKPiArCQkgICAgICAgcmVzcC0+dG9rc1tuXS50eXBlKTsKPiArCQly\n"
- "ZXR1cm4gMDsKPiArCX0KPiArCj4gKwlpZiAoISgocmVzcC0+dG9rc1tuXS53aWR0aCA9PSBPUEFM\n"
- "X1dJRFRIX1RJTlkpIHx8Cj4gKwkgICAgICAocmVzcC0+dG9rc1tuXS53aWR0aCA9PSBPUEFMX1dJ\n"
- "RFRIX1NIT1JUKSkpIHsKPiArCQlwcl9lcnIoIkF0b20gaXMgbm90IHNob3J0IG9yIHRpbnk6ICVk\n"
- "XG4iLAo+ICsJCSAgICAgICByZXNwLT50b2tzW25dLndpZHRoKTsKPiArCQlyZXR1cm4gMDsKPiAr\n"
- "CX0KPiArCj4gKwlyZXR1cm4gcmVzcC0+dG9rc1tuXS5zdG9yZWQudTsKPiArfQo+ICsKPiArc3Rh\n"
- "dGljIHU4IHJlc3BvbnNlX3N0YXR1cyhjb25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJlc3ApCj4g\n"
- "K3sKPiArCWlmICgodG9rZW5fdHlwZShyZXNwLCAwKSA9PSBPUEFMX0RUQV9UT0tFTklEX1RPS0VO\n"
- "KQo+ICsJICAgICYmIChyZXNwb25zZV9nZXRfdG9rZW4ocmVzcCwgMCkgPT0gT1BBTF9FTkRPRlNF\n"
- "U1NJT04pKSB7Cj4gKwkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ICsJaWYgKHJlc3AtPm51bSA8IDUp\n"
- "Cj4gKwkJcmV0dXJuIERUQUVSUk9SX05PX01FVEhPRF9TVEFUVVM7Cj4gKwo+ICsJaWYgKCh0b2tl\n"
- "bl90eXBlKHJlc3AsIHJlc3AtPm51bSAtIDEpICE9IE9QQUxfRFRBX1RPS0VOSURfVE9LRU4pIHx8\n"
- "Cj4gKwkgICAgKHRva2VuX3R5cGUocmVzcCwgcmVzcC0+bnVtIC0gNSkgIT0gT1BBTF9EVEFfVE9L\n"
- "RU5JRF9UT0tFTikgfHwKPiArCSAgICAocmVzcG9uc2VfZ2V0X3Rva2VuKHJlc3AsIHJlc3AtPm51\n"
- "bSAtIDEpICE9IE9QQUxfRU5ETElTVCkgfHwKPiArCSAgICAocmVzcG9uc2VfZ2V0X3Rva2VuKHJl\n"
- "c3AsIHJlc3AtPm51bSAtIDUpICE9IE9QQUxfU1RBUlRMSVNUKSkKPiArCQlyZXR1cm4gRFRBRVJS\n"
- "T1JfTk9fTUVUSE9EX1NUQVRVUzsKPiArCj4gKwlyZXR1cm4gcmVzcG9uc2VfZ2V0X3U2NChyZXNw\n"
- "LCByZXNwLT5udW0gLSA0KTsKPiArfQo+ICsKPiArLyogUGFyc2VzIGFuZCBjaGVja3MgZm9yIGVy\n"
- "cm9ycyAqLwo+ICtzdGF0aWMgaW50IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoc3RydWN0IG9wYWxf\n"
- "ZGV2ICpkZXYpCj4gK3sKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJaW50IGVycm9yOwo+\n"
- "ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsKPiArCXByaW50X2J1ZmZlcihjbWQtPmNtZCwgY21kLT5w\n"
- "b3MpOwo+ICsKPiArCWVycm9yID0gcmVzcG9uc2VfcGFyc2UoY21kLT5yZXNwLCBJT19CVUZGRVJf\n"
- "TEVOR1RILCAmZGV2LT5wYXJzZWQpOwo+ICsJaWYgKGVycm9yKSB7Cj4gKwkJcHJfZXJyKCIlczog\n"
- "Q291bGRuJ3QgcGFyc2UgcmVzcG9uc2UuXG4iLCBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJZ290byBl\n"
- "cnJfcmV0dXJuOwo+ICsJfQo+ICsKPiArCWVycm9yID0gcmVzcG9uc2Vfc3RhdHVzKCZkZXYtPnBh\n"
- "cnNlZCk7Cj4gKwlpZiAoZXJyb3IpCj4gKwkJcHJfZXJyKCIlczogUmVzcG9uc2UgU3RhdHVzOiAl\n"
- "ZFxuIiwgZGV2LT5kaXNrX25hbWUsCj4gKwkJICAgICAgIGVycm9yKTsKPiArCj4gKyBlcnJfcmV0\n"
- "dXJuOgo+ICsJcmV0dXJuIGVycm9yOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjbGVhcl9vcGFs\n"
- "X2NtZChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCkKPiArewo+ICsJY21kLT5wb3MgPSBzaXplb2Yoc3Ry\n"
- "dWN0IG9wYWxfaGVhZGVyKTsKPiArCW1lbXNldChjbWQtPmNtZCwgMCwgSU9fQlVGRkVSX0xFTkdU\n"
- "SCk7Cj4gKwljbWQtPmNiID0gTlVMTDsKPiArCWNtZC0+Y2JfZGF0YSA9IE5VTEw7Cj4gK30KPiAr\n"
- "Cj4gK3N0YXRpYyB2b2lkIHN0YXJ0X29wYWxfc2Vzc2lvbl9jb250KGludCBlcnJvciwgdm9pZCAq\n"
- "ZGF0YSkKPiArewo+ICsJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwo+ICsJdTMyIEhTTiwg\n"
- "VFNOOwo+ICsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4gKwo+ICsJZXJy\n"
- "b3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7Cj4gKwlpZiAoZXJyb3IpCj4gKwkJZ290\n"
- "byBlcnJfcmV0dXJuOwo+ICsKPiArCUhTTiA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2Vk\n"
- "LCA0KTsKPiArCVRTTiA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2VkLCA1KTsKPiArCj4g\n"
- "KwlpZiAoSFNOID09IDAgJiYgVFNOID09IDApIHsKPiArCQlwcl9lcnIoIiVzOiBDb3VsZG4ndCBh\n"
- "dXRoZW50aWNhdGUgc2Vzc2lvblxuIiwgZGV2LT5kaXNrX25hbWUpOwo+ICsJCWVycm9yID0gLUVQ\n"
- "RVJNOwo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCX0KPiArCj4gKwlkZXYtPkhTTiA9IEhTTjsK\n"
- "PiArCWRldi0+VFNOID0gVFNOOwo+ICsKPiArZXJyX3JldHVybjoKPiArCWlmIChkZXYtPm9wZXJf\n"
- "Y2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50\n"
- "IGdldF9vcGFsX2tleShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJc3RydWN0IGtleSAq\n"
- "dWtleSA9IE5VTEw7Cj4gKwljb25zdCB1OCAqdG1wa2V5ID0gTlVMTDsKPiArCXNpemVfdCB0bXBs\n"
- "ZW47Cj4gKwlpbnQgcmV0ID0gMDsKPiArCj4gKwlpZiAoZGV2LT5rZXlfdHlwZSA9PSBPUEFMX0tF\n"
- "WV9QTEFJTikgewo+ICsJCXRtcGtleSA9IGRldi0+a2V5X25hbWU7Cj4gKwkJdG1wbGVuID0gZGV2\n"
- "LT5rZXlfbmFtZV9sZW47Cj4gKwl9IGVsc2UgaWYgKGRldi0+a2V5X3R5cGUgPT0gT1BBTF9LRVlf\n"
- "S0VZUklORykgewo+ICsJCXVrZXkgPSByZXF1ZXN0X3VzZXJfa2V5KGRldi0+a2V5X25hbWUsICZ0\n"
- "bXBrZXksICZ0bXBsZW4pOwo+ICsJCWlmIChJU19FUlIodWtleSkpIHsKPiArCQkJcHJfZXJyKCIl\n"
- "czogQ2FuJ3QgcmV0cmlldmUga2V5OiAlbGRcbiIsIGRldi0+ZGlza19uYW1lLAo+ICsJCQkgICAg\n"
- "ICAgUFRSX0VSUih1a2V5KSk7Cj4gKwkJCXJldHVybiBQVFJfRVJSKHVrZXkpOwo+ICsJCX0KPiAr\n"
- "CX0gZWxzZSB7Cj4gKwkJcHJfZXJyKCJSZXF1ZXN0ZWQgaW52YWxpZCBrZXkgdHlwZTogJWRcbiIs\n"
- "IGRldi0+a2V5X3R5cGUpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWlmICh0\n"
- "bXBsZW4gPiBPUEFMX0tFWV9NQVgpIHsKPiArCQlwcl9lcnIoIlJlcXVlc3RlZCBrZXkgd2l0aCBp\n"
- "bnZhbGlkIHNpemU6ICV6ZFxuIiwgdG1wbGVuKTsKPiArCQlyZXQgPSAtRUlOVkFMOwo+ICsJCWdv\n"
- "dG8gZXJyX2V4aXQ7Cj4gKwl9Cj4gKwo+ICsJZGV2LT5rZXlfbGVuID0gdG1wbGVuOwo+ICsJaWYg\n"
- "KCFtZW1jcHkoZGV2LT5rZXksIHRtcGtleSwgdG1wbGVuKSkgewo+ICsJCXByX2VycigiRXJyb3Ig\n"
- "d2hlbiBjb3B5aW5nIGtleSIpOwo+ICsJCXJldCA9IC1FRkFVTFQ7Cj4gKwkJZ290byBlcnJfZXhp\n"
- "dDsKPiArCX0KPiArCj4gK2Vycl9leGl0Ogo+ICsJa2V5X3B1dCh1a2V5KTsKPiArCj4gKwlyZXR1\n"
- "cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgY2xlYW5fb3BhbF9rZXkoc3RydWN0IG9wYWxf\n"
- "ZGV2ICpkZXYpCj4gK3sKPiArCW1lbXNldChkZXYtPmtleSwgMCwgT1BBTF9LRVlfTUFYKTsKPiAr\n"
- "CWRldi0+a2V5X2xlbiA9IDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgdm9pZCBjbGVhbl9m\n"
- "dW5jdGlvbl9kYXRhKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwkJZGV2LT5mdW5jX2Rh\n"
- "dGEgPSBOVUxMOwo+ICsJCWRldi0+bnVtX2Z1bmNfZGF0YSA9IDA7Cj4gK30KPiArCj4gKy8qIFRo\n"
- "aXMgaXMgYSBnZW5lcmljIGNvbnRpbnVlIGZuLgo+ICsgKiBXZSB1c2UgdGhpcyB3aGVuIHdlIGRv\n"
- "bid0IGNhcmUgYWJvdXQgdGhlIHJlc3BvbnNlIGRhdGEKPiArICogYW5kIHNpbXBseSB3YW50IHRv\n"
- "IGNoZWNrIHRoZSBzdGF0dXMgYW5kIGNvbnRpbnVlLgo+ICsgKi8KPiArc3RhdGljIHZvaWQgZ2Vu\n"
- "ZXJpY19jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKPiArewo+ICsJc3RydWN0IG9wYWxfZGV2\n"
- "ICpkZXYgPSBkYXRhOwo+ICsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4g\n"
- "Kwo+ICsJZXJyb3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7Cj4gKwo+ICsgZXJyX3Jl\n"
- "dHVybjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYp\n"
- "Owo+ICt9CgpIb3cgYWJvdXQ6CgpzdGF0aWMgdm9pZCBnZW5lcmljX2NvbnQoaW50IGVycm9yLCB2\n"
- "b2lkICpkYXRhKQp7CglzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CgoJaWYgKCFlcnJvcikK\n"
- "CQllcnJvciA9IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoZGV2KTsKCglpZiAoZGV2LT5vcGVyX2Ni\n"
- "KQoJCWRldi0+b3Blcl9jYihlcnJvciwgZGV2KTsKfQoKPiArCj4gK3N0YXRpYyB2b2lkIGVuZF9z\n"
- "ZXNzaW9uX2NvbnQoaW50IGVycm9yLCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9k\n"
- "ZXYgKmRldiA9IGRhdGE7Cj4gKwo+ICsJZGV2LT5IU04gPSAwOwo+ICsJZGV2LT5UU04gPSAwOwo+\n"
- "ICsJZ2VuZXJpY19jb250KGVycm9yLCBkYXRhKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBmaW5h\n"
- "bGl6ZV9hbmRfc2VuZChzdHJ1Y3Qgb3BhbF9kZXYgKmRldiwgc3RydWN0IG9wYWxfY21kICpjbWQs\n"
- "Cj4gKwkJCSAgICAgc2VjX2NiIGNvbnQpCj4gK3sKPiArCWludCByZXQ7Cj4gKwo+ICsJcmV0ID0g\n"
- "Y21kX2ZpbmFsaXplKGNtZCwgZGV2LT5IU04sIGRldi0+VFNOKTsKPiArCWlmIChyZXQpIHsKPiAr\n"
- "CQlwcl9lcnIoIiVzOiBFcnJvciBmaW5hbGl6aW5nIGNvbW1hbmQgYnVmZmVyOiAlZFxuIiwKPiAr\n"
- "CQkgICAgICAgZGV2LT5kaXNrX25hbWUsIHJldCk7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiAr\n"
- "Cj4gKwlwcmludF9idWZmZXIoY21kLT5jbWQsIGNtZC0+cG9zKTsKPiArCj4gKwlyZXQgPSBvcGFs\n"
- "X3NlbmRfcmVjdihkZXYsIGNvbnQsIGRldik7Cj4gKwlpZiAocmV0KQo+ICsJCXByX2VycigiJXM6\n"
- "IEVycm9yIHJ1bm5pbmcgY29tbWFuZDogJWRcbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1l\n"
- "LCByZXQpOwo+ICsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgd2FpdF9m\n"
- "b3JfY21kX2NvbXBsZXRpb24oc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbikKPiAr\n"
- "ewo+ICsJd2FpdF9mb3JfY29tcGxldGlvbl9pbnRlcnJ1cHRpYmxlKCZjb21wbGV0aW9uLT5jbWRf\n"
- "Y29tcGxldGlvbik7Cj4gKwlyZXR1cm4gY29tcGxldGlvbi0+Y29tcGxldGlvbl9zdGF0dXM7Cj4g\n"
- "K30KPiArCj4gK3N0YXRpYyBpbnQgZ2VuX2tleShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+\n"
- "ICsJY29uc3QgdTggKm1ldGhvZDsKPiArCXU4IHVpZFtPUEFMX1VJRF9MRU5HVEhdOwo+ICsJc3Ry\n"
- "dWN0IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsK\n"
- "PiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsK\n"
- "PiArCj4gKwltZW1jcHkodWlkLCBkZXYtPnByZXZfZGF0YSwgbWluKHNpemVvZih1aWQpLCBkZXYt\n"
- "PnByZXZfZF9sZW4pKTsKPiArCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRU5LRVldOwo+ICsJ\n"
- "a2ZyZWUoZGV2LT5wcmV2X2RhdGEpOwo+ICsJZGV2LT5wcmV2X2RhdGEgPSBOVUxMOwo+ICsKPiAr\n"
- "CXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgMmMiLAo+ICsJCQkJICAgIE9Q\n"
- "QUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRo\n"
- "b2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4g\n"
- "KwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIl\n"
- "czogRXJyb3IgYnVpbGRpbmcgZ2VuIGtleSBjb21tYW5kXG4iLAo+ICsJCSAgICAgICBkZXYtPmRp\n"
- "c2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVf\n"
- "YW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29udCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lk\n"
- "IGdldF9hY3RpdmVfa2V5X2NvbnQoaW50IGVycm9yLCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1\n"
- "Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7Cj4gKwljb25zdCBjaGFyICphY3RpdmVrZXk7Cj4gKwlz\n"
- "aXplX3Qga2V5bGVuOwo+ICsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4g\n"
- "Kwo+ICsJZXJyb3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7Cj4gKwlpZiAoZXJyb3Ip\n"
- "Cj4gKwkJZ290byBlcnJfcmV0dXJuOwo+ICsJa2V5bGVuID0gcmVzcG9uc2VfZ2V0X3N0cmluZygm\n"
- "ZGV2LT5wYXJzZWQsIDQsICZhY3RpdmVrZXkpOwo+ICsJaWYgKCFhY3RpdmVrZXkpIHsKPiArCQlw\n"
- "cl9lcnIoIiVzOiBDb3VsZG4ndCBleHRyYWN0IHRoZSBBY3RpdmVrZXkgZnJvbSB0aGUgcmVzcG9u\n"
- "c2VcbiIsCj4gKwkJICAgICAgIF9fZnVuY19fKTsKPiArCQllcnJvciA9IDB4MEE7Cj4gKwkJZ290\n"
- "byBlcnJfcmV0dXJuOwo+ICsJfQo+ICsJZGV2LT5wcmV2X2RhdGEgPSBrbWVtZHVwKGFjdGl2ZWtl\n"
- "eSwga2V5bGVuLCBHRlBfS0VSTkVMKTsKPiArCj4gKwlpZiAoIWRldi0+cHJldl9kYXRhKQo+ICsJ\n"
- "CWVycm9yID0gLUVOT01FTTsKPiArCj4gKwlkZXYtPnByZXZfZF9sZW4gPSBrZXlsZW47Cj4gKwo+\n"
- "ICtlcnJfcmV0dXJuOgo+ICsJaWYgKGRldi0+b3Blcl9jYikKPiArCQlkZXYtPm9wZXJfY2IoZXJy\n"
- "b3IsIGRldik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZ2V0X2FjdGl2ZV9rZXkoc3RydWN0IG9w\n"
- "YWxfZGV2ICpkZXYpCj4gK3sKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwl1OCB1aWRbT1BBTF9V\n"
- "SURfTEVOR1RIXTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJaW50IHJldDsKPiArCj4g\n"
- "KwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsJc2V0X2NvbUlE\n"
- "KGNtZCwgZGV2LT5jb21JRCk7Cj4gKwo+ICsJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0dFVF07\n"
- "Cj4gKwo+ICsJcmV0ID0gYnVpbGRfbG9ja2luZ19yYW5nZSh1aWQsIHNpemVvZih1aWQpLCBkZXYt\n"
- "PmxyKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9j\n"
- "a2luZyByYW5nZVxuIiwgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJ\n"
- "fQo+ICsKPiArCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgNmMgNGMgMmMi\n"
- "LAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwK\n"
- "PiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BB\n"
- "TF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9T\n"
- "VEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIHN0YXJ0Q2xvdW1uICov\n"
- "Cj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMTAsIC8qIEFjdGl2ZUtleSAqLwo+ICsJCQkJICAg\n"
- "IE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAg\n"
- "T1BBTF9USU5ZX1VJTlRfMDQsIC8qIGVuZENvbHVtbiAqLwo+ICsJCQkJICAgIE9QQUxfVElOWV9V\n"
- "SU5UXzEwLCAvKiBBY3RpdmVLZXkgKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJ\n"
- "CQkJICAgIE9QQUxfRU5ETElTVCwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsJaWYgKHJl\n"
- "dCA8IDApIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBnZXQgYWN0aXZlIGtleSBj\n"
- "b21tYW5kXG4iLAo+ICsJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsK\n"
- "PiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdldF9hY3Rp\n"
- "dmVfa2V5X2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNldHVwX2xvY2tpbmdfcmFuZ2Uo\n"
- "c3RydWN0IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwl1OCB1\n"
- "aWRbT1BBTF9VSURfTEVOR1RIXTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJc3RydWN0\n"
- "IG9wYWxfdXNlcl9scl9zZXR1cCAqc2V0dXA7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZk\n"
- "ZXYtPmNtZDsKPiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwlzZXRfY29tSUQoY21kLCBkZXYt\n"
- "PmNvbUlEKTsKPiArCj4gKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU0VUXTsKPiArCXJldCA9\n"
- "IGJ1aWxkX2xvY2tpbmdfcmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5scik7Cj4gKwlpZiAo\n"
- "cmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIs\n"
- "IGRldi0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCXNldHVwID0g\n"
- "ZGV2LT5mdW5jX2RhdGFbZGV2LT5zdGF0ZSAtIDFdOwo+ICsKPiArCXJldCA9IHRlc3RfYW5kX2Fk\n"
- "ZF90b2tlbl92YShjbWQsICJjMnMgIDRjIDJjdWMgMmN1YyAyY3VjIDJjdSA0YyIsCj4gKwkJCQkg\n"
- "ICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIHVpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAg\n"
- "IG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElT\n"
- "VCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywKPiAr\n"
- "CQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4g\n"
- "KwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIFJhbmdlIFN0YXJ0ICovCj4gKwkJCQkgICAg\n"
- "c2V0dXAtPnJhbmdlX3N0YXJ0LAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkg\n"
- "ICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDQsIC8qIFJhbmdl\n"
- "IExlbmd0aCAqLwo+ICsJCQkJICAgIHNldHVwLT5yYW5nZV9sZW5ndGgsCj4gKwkJCQkgICAgT1BB\n"
- "TF9FTkROQU1FLAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFM\n"
- "X1RJTllfVUlOVF8wNSwgLyogUmVhZExvY2tFbmFibGVkICovCj4gKwkJCQkgICAgISFzZXR1cC0+\n"
- "UkxFLAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5B\n"
- "TUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIFdyaXRlTG9ja0VuYWJsZWQgKi8K\n"
- "PiArCQkJCSAgICAhIXNldHVwLT5XTEUsCj4gKwo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiAr\n"
- "CQkJCSAgICBPUEFMX0VORExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+ICsJCQkJICAg\n"
- "IE9QQUxfRU5ETElTVCk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9y\n"
- "IGJ1aWxkaW5nIFNldHVwIExvY2tpbmcgcmFuZ2UgY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRl\n"
- "di0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCX0KPiArCj4gKwlyZXR1cm4g\n"
- "ZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29udCk7Cj4gK30KPiArCj4gK3N0\n"
- "YXRpYyBpbnQgc3RhcnRfYWRtaW5zcF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYs\n"
- "Cj4gKwkJCQkgICAgICBlbnVtIE9QQUxfVUlEIGF1dGgsCj4gKwkJCQkgICAgICBjb25zdCBjaGFy\n"
- "ICprZXksCj4gKwkJCQkgICAgICB1OCBrZXlfbGVuKQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9k\n"
- "LCAqc211aWQsICphZG1pbl9zcCwgKmhzYTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJ\n"
- "dTMyIEhTTjsKPiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKGtleSA9PSBOVUxMICYmIGF1dGggIT0g\n"
- "T1BBTF9BTllCT0RZX1VJRCkgewo+ICsJCXByX2VycigiJXM6IEF0dGVtcHRlZCB0byBvcGVuIEFE\n"
- "TUlOX1NQIFNlc3Npb24gd2l0aG91dCBhIEhvc3QiIFwKPiArCQkgICAgICAgIkNoYWxsZW5nZSwg\n"
- "YW5kIG5vdCBhcyB0aGUgQW55Ym9keSBVSURcbiIsIF9fZnVuY19fKTsKPiArCQlyZXR1cm4gMTsK\n"
- "PiArCX0KPiArCj4gKwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+\n"
- "ICsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsJSFNOID0gMHg0MTsKPiArCj4g\n"
- "KwlzbXVpZCA9IE9QQUxVSURbT1BBTF9TTVVJRF9VSURdOwo+ICsJbWV0aG9kID0gT1BBTE1FVEhP\n"
- "RFtPUEFMX1NUQVJUU0VTU0lPTl07Cj4gKwlhZG1pbl9zcCA9IE9QQUxVSURbT1BBTF9BRE1JTlNQ\n"
- "X1VJRF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyBjdXNj\n"
- "IiwKPiArCQkJCSAgICBPUEFMX0NBTEwsCj4gKwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdU\n"
- "SCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCQkJCSAgICBPUEFM\n"
- "X1NUQVJUTElTVCwKPiArCQkJCSAgICBIU04sCj4gKwkJCQkgICAgYWRtaW5fc3AsIE9QQUxfVUlE\n"
- "X0xFTkdUSCwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSk7Cj4gKwlpZiAocmV0IDwgMCkg\n"
- "ewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIHN0YXJ0IGFkbWluc3Agc2Vzc2lvbiBj\n"
- "b21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7\n"
- "Cj4gKwl9Cj4gKwo+ICsJc3dpdGNoIChhdXRoKSB7Cj4gKwljYXNlIE9QQUxfQU5ZQk9EWV9VSUQ6\n"
- "Cj4gKwkJLyogbm90aGluZyBsZWZ0IHRvIGRvIGZvciBhbnlib2R5LCBqdXN0IGVuZCBhbmQgZmlu\n"
- "YWxpemUgKi8KPiArCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYyIsCj4gKwkJ\n"
- "CQkJICAgIE9QQUxfRU5ETElTVCk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIE9QQUxfU0lEX1VJRDoK\n"
- "PiArCQloc2EgPSBPUEFMVUlEW09QQUxfU0lEX1VJRF07Cj4gKwkJcmV0ID0gdGVzdF9hbmRfYWRk\n"
- "X3Rva2VuX3ZhKGNtZCwgIjJjIHMgM2MgcyAyYyIsCj4gKwkJCQkJICAgIE9QQUxfU1RBUlROQU1F\n"
- "LAo+ICsJCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMCwgLyogSG9zdENoYWxsZW5nZSAqLwo+ICsJ\n"
- "CQkJCSAgICBrZXksIGtleV9sZW4sCj4gKwkJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJCQkg\n"
- "ICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAvKiBIb3N0\n"
- "U2lnbkF1dGggKi8KPiArCQkJCQkgICAgaHNhLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkJICAg\n"
- "IE9QQUxfRU5ETkFNRSwKPiArCQkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCQlicmVhazsKPiAr\n"
- "CWRlZmF1bHQ6Cj4gKwkJcHJfZXJyKCJDYW5ub3Qgc3RhcnQgQWRtaW4gU1Agc2Vzc2lvbiB3aXRo\n"
- "IGF1dGggJWRcbiIsIGF1dGgpOwo+ICsJCXJldHVybiAxOwo+ICsJfQo+ICsKPiArCWlmIChyZXQg\n"
- "PCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgc3RhcnQgYWRtaW5zcCBzZXNz\n"
- "aW9uIGNvbW1hbmQuXG4iLAo+ICsJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJu\n"
- "IHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0\n"
- "YXJ0X29wYWxfc2Vzc2lvbl9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzdGFydF9hbnli\n"
- "b2R5QVNQX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJcmV0dXJu\n"
- "IHN0YXJ0X2FkbWluc3Bfb3BhbF9zZXNzaW9uKGRldiwgT1BBTF9BTllCT0RZX1VJRCwgTlVMTCwg\n"
- "MCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgc3RhcnRfU0lEQVNQX29wYWxfc2Vzc2lvbihzdHJ1\n"
- "Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJaW50IHJldDsKPiArCWNvbnN0IHU4ICprZXkgPSBk\n"
- "ZXYtPnByZXZfZGF0YTsKPiArCj4gKwlpZiAoIWtleSkKPiArCQlyZXQgPSBzdGFydF9hZG1pbnNw\n"
- "X29wYWxfc2Vzc2lvbihkZXYsIE9QQUxfU0lEX1VJRCwgZGV2LT5rZXksCj4gKwkJCQkJCSBkZXYt\n"
- "PmtleV9sZW4pOwo+ICsJZWxzZSB7Cj4gKwkJcmV0ID0gc3RhcnRfYWRtaW5zcF9vcGFsX3Nlc3Np\n"
- "b24oZGV2LCBPUEFMX1NJRF9VSUQsIGtleSwKPiArCQkJCQkJIGRldi0+cHJldl9kX2xlbik7Cj4g\n"
- "KwkJa2ZyZWUoa2V5KTsKPiArCQlkZXYtPnByZXZfZGF0YSA9IE5VTEw7Cj4gKwl9Cj4gKwlyZXR1\n"
- "cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHN0YXJ0X2xvY2tpbmdzcF9vcGFsX3Nlc3Np\n"
- "b24oc3RydWN0IG9wYWxfZGV2ICpkZXYsCj4gKwkJCQkJZW51bSBPUEFMX1VJRCBhdXRoLCBjb25z\n"
- "dCB1OCAqa2V5LAo+ICsJCQkJCXU4IGtleV9sZW4pCj4gK3sKPiArCj4gKwljb25zdCB1OCAqbWV0\n"
- "aG9kLCAqc211aWQsICpsb2NraW5nX3NwLCAqaHNhOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7\n"
- "Cj4gKwlzaXplX3Qga2xlbiA9IGtleV9sZW47Cj4gKwl1MzIgSFNOOwo+ICsJaW50IHJldDsKPiAr\n"
- "Cj4gKwlpZiAoa2V5ID09IE5VTEwpIHsKPiArCQlwcl9lcnIoIkNhbm5vdCBzdGFydCBMb2NraW5n\n"
- "IFNQIHNlc3Npb24gd2l0aG91dCBhIGtleVxuIik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9\n"
- "Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCj4g\n"
- "KwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKPiArCUhTTiA9IDB4NDE7Cj4gKwo+ICsJc211\n"
- "aWQgPSBPUEFMVUlEW09QQUxfU01VSURfVUlEXTsKPiArCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BB\n"
- "TF9TVEFSVFNFU1NJT05dOwo+ICsJbG9ja2luZ19zcCA9IE9QQUxVSURbT1BBTF9MT0NLSU5HU1Bf\n"
- "VUlEXTsKPiArCWhzYSA9IE9QQUxVSURbYXV0aF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk\n"
- "X3Rva2VuX3ZhKGNtZCwgImMycyBjdXNjIDJjc2MgMmNzYyBjIiwKPiArCQkJCSAgICBPUEFMX0NB\n"
- "TEwsCj4gKwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2Qs\n"
- "IE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJ\n"
- "CQkgICAgSFNOLAo+ICsJCQkJICAgIGxvY2tpbmdfc3AsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJ\n"
- "CSAgICBPUEFMX1RJTllfVUlOVF8wMSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4g\n"
- "KwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDAsIC8qIEhvc3RDaGFsbGVuZ2UgKi8KPiArCQkJCSAg\n"
- "ICBrZXksIGtsZW4sCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+ICsKPiArCQkJCSAgICBPUEFM\n"
- "X1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogSG9zdCBTaWduIEF1\n"
- "dGhvcml0eSAqLwo+ICsJCQkJICAgIGhzYSwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9Q\n"
- "QUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlpZiAocmV0\n"
- "IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIHN0YXJ0IGFkbWluc3Agc2Vz\n"
- "c2lvbiBjb21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVy\n"
- "biByZXQ7Cj4gKwl9Cj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0YXJ0\n"
- "X29wYWxfc2Vzc2lvbl9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBpbnQgc3RhcnRf\n"
- "YWRtaW4xTFNQX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJcmV0\n"
- "dXJuIHN0YXJ0X2xvY2tpbmdzcF9vcGFsX3Nlc3Npb24oZGV2LCBPUEFMX0FETUlOMV9VSUQsCj4g\n"
- "KwkJCQkJICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4pOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50\n"
- "IHN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwlj\n"
- "b25zdCB1OCAqbWV0aG9kLCAqc211aWQsICpsb2NraW5nX3NwOwo+ICsJdTggbGtfdWxfdXNlcltP\n"
- "UEFMX1VJRF9MRU5HVEhdOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwl1MzIgSFNOOwo+\n"
- "ICsJaW50IHJldDsKPiArCXN0cnVjdCBvcGFsX3VzZXJfaW5mbyAqdWluZm87Cj4gKwo+ICsJY21k\n"
- "ID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCj4gKwlzZXRfY29tSUQo\n"
- "Y21kLCBkZXYtPmNvbUlEKTsKPiArCj4gKwlIU04gPSAweDQxOwpDYW4gd2UgI2RlZmluZSB0aGlz\n"
- "OyBpdCdzIHVzZWQgYSBmZXcgb3RoZXIgcGxhY2VzIGFuZCBpcyBtYWdpY2t5Cgo+ICsKPiArCXVp\n"
- "bmZvID0gZGV2LT5mdW5jX2RhdGFbZGV2LT5zdGF0ZSAtIDFdOwo+ICsKPiArCXNtdWlkID0gT1BB\n"
- "TFVJRFtPUEFMX1NNVUlEX1VJRF07Cj4gKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU1RBUlRT\n"
- "RVNTSU9OXTsKPiArCWxvY2tpbmdfc3AgPSBPUEFMVUlEW09QQUxfTE9DS0lOR1NQX1VJRF07Cj4g\n"
- "Kwo+ICsJaWYgKHVpbmZvLT5TVU0pIHsKPiArCQlyZXQgPSBidWlsZF9sb2NraW5nX3VzZXIobGtf\n"
- "dWxfdXNlciwgc2l6ZW9mKGxrX3VsX3VzZXIpLAo+ICsJCQkJCSBkZXYtPmxyKTsKPiArCQlpZiAo\n"
- "cmV0IDwgMCkgewo+ICsJCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHVzZXJcbiIs\n"
- "Cj4gKwkJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJCXJldHVybiByZXQ7Cj4gKwkJfQo+\n"
- "ICsJfSBlbHNlIGlmICh1aW5mby0+d2hvICE9IE9QQUxfQURNSU4xICYmICF1aW5mby0+U1VNKSB7\n"
- "Cj4gKwkJcmV0ID0gYnVpbGRfbG9ja2luZ191c2VyKGxrX3VsX3VzZXIsIHNpemVvZihsa191bF91\n"
- "c2VyKSwKPiArCQkJCQkgdWluZm8tPndobyAtIDEpOwo+ICsJCWlmIChyZXQgPCAwKSB7Cj4gKwkJ\n"
- "CXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgdXNlclxuIiwKPiArCQkJICAgICAgIGRl\n"
- "di0+ZGlza19uYW1lKTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwl9IGVsc2UKPiArCQlt\n"
- "ZW1jcHkobGtfdWxfdXNlciwgT1BBTFVJRFtPUEFMX0FETUlOMV9VSURdLCBPUEFMX1VJRF9MRU5H\n"
- "VEgpOwo+ICsKPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIGN1\n"
- "czNjczNjIHMgMmMiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICBzbXVpZCwgT1BB\n"
- "TF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsK\n"
- "PiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBIU04sCj4gKwkJCQkgICAgbG9j\n"
- "a2luZ19zcCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLAo+\n"
- "ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAwLAo+\n"
- "ICsJCQkJICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4sCj4gKwkJCQkgICAgT1BBTF9FTkROQU1F\n"
- "LAo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAz\n"
- "LAo+ICsKPiArCQkJCSAgICBsa191bF91c2VyLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwo+ICsJCQkJ\n"
- "ICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsKPiArCWlmIChy\n"
- "ZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgU1RBUlRTRVNTSU9OIGNv\n"
- "bW1hbmQuXG4iLAo+ICsJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsK\n"
- "PiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0YXJ0X29w\n"
- "YWxfc2Vzc2lvbl9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCByZXZlcnRfdHBlcihzdHJ1\n"
- "Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJY29uc3QgdTggKm1ldGhvZCwgKnNtdWlkOwo+ICsJ\n"
- "c3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZkZXYtPmNt\n"
- "ZDsKPiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5j\n"
- "b21JRCk7Cj4gKwo+ICsJc211aWQgPSBPUEFMVUlEW09QQUxfQURNSU5TUF9VSURdOwo+ICsJbWV0\n"
- "aG9kID0gT1BBTE1FVEhPRFtPUEFMX1JFVkVSVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk\n"
- "X3Rva2VuX3ZhKGNtZCwgImMycyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAg\n"
- "IHNtdWlkLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9M\n"
- "RU5HVEgsCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNU\n"
- "KTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgUkVW\n"
- "RVJUIFRQRVIgY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKPiArCQly\n"
- "ZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNt\n"
- "ZCwgZ2VuZXJpY19jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBpbnRlcm5hbF9hY3RpdmF0\n"
- "ZV91c2VyKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9kOwo+\n"
- "ICsJdTggdWlkW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiAr\n"
- "CWludCByZXQ7Cj4gKwlzdHJ1Y3Qgb3BhbF9hY3RpdmF0ZV91c2VyICphY3Q7Cj4gKwo+ICsJY21k\n"
- "ID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQs\n"
- "IGRldi0+Y29tSUQpOwo+ICsKPiArCWFjdCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAx\n"
- "XTsKPiArCj4gKwltZW1jcHkodWlkLCBPUEFMVUlEW09QQUxfVVNFUjFfVUlEXSwgT1BBTF9VSURf\n"
- "TEVOR1RIKTsKPiArCXVpZFs3XSA9IGFjdC0+d2hvLndobzsKPiArCj4gKwltZXRob2QgPSBPUEFM\n"
- "TUVUSE9EW09QQUxfU0VUXTsKPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21k\n"
- "LCAiYzJzIDNjIGMgNGMgM2MiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQs\n"
- "IE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwK\n"
- "PiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUs\n"
- "Cj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDEsIC8qIFZhbHVlcyAqLwo+ICsKPiArCQkJCSAg\n"
- "ICBPUEFMX1NUQVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkg\n"
- "ICAgT1BBTF9USU5ZX1VJTlRfMDUsIC8qIEVuYWJsZWQgKi8KPiArCQkJCSAgICBPUEFMX1RJTllf\n"
- "VUlOVF8wMSwgLyogVHJ1ZSAqLwo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkg\n"
- "ICAgT1BBTF9FTkRMSVNULAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJCSAgICBPUEFM\n"
- "X0VORExJU1QpOwo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3Ig\n"
- "YnVpbGRpbmcgQWN0aXZhdGUgVXNlck4gY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlz\n"
- "a19uYW1lKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9h\n"
- "bmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBl\n"
- "cmFzZV9sb2NraW5nX3JhbmdlKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1\n"
- "OCAqbWV0aG9kOwo+ICsJdTggdWlkW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9j\n"
- "bWQgKmNtZDsKPiArCWludCByZXQ7Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJf\n"
- "b3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1l\n"
- "dGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9FUkFTRV07Cj4gKwo+ICsJaWYgKGJ1aWxkX2xvY2tpbmdf\n"
- "cmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5scikgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczog\n"
- "Q2FuJ3QgYnVpbGQgbG9ja2luZyByYW5nZVxuIiwgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVy\n"
- "biAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQs\n"
- "ICJjMnMgMmMiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlE\n"
- "X0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJ\n"
- "CQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlp\n"
- "ZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEVyYXNlIExvY2tp\n"
- "bmcgUmFuZ2UgQ21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJl\n"
- "dHVybiByZXQ7Cj4gKwl9Cj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdl\n"
- "bmVyaWNfY29udCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgc2V0X21icl9kb25lKHN0cnVjdCBv\n"
- "cGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9kLCAqdWlkOwo+ICsJc3RydWN0\n"
- "IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXU4IG1icl9kb25lX3RmID0gKih1\n"
- "OCAqKWRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKPiArCj4gKwljbWQgPSAmZGV2LT5j\n"
- "bWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21J\n"
- "RCk7Cj4gKwo+ICsJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07Cj4gKwl1aWQgPSBPUEFM\n"
- "VUlEW09QQUxfTUJSQ09OVFJPTF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3Zh\n"
- "KGNtZCwgImMycyAzYyA2YyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIHVp\n"
- "ZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RI\n"
- "LAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFN\n"
- "RSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1Qs\n"
- "Cj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDIs\n"
- "IC8qIERvbmUgKi8KPiArCQkJCSAgICBtYnJfZG9uZV90ZiwgICAgICAgLyogRG9uZSBUIG9yIEYg\n"
- "Ki8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsK\n"
- "PiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCWlm\n"
- "IChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgc2V0IE1CUiBEb250\n"
- "L05vdCBkb25lIGNvbW1hbmRcbiIsCnMvRG9udC9Eb25lLyA/CgoKPiArCQkgICAgICAgZGV2LT5k\n"
- "aXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXpl\n"
- "X2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50\n"
- "IHNldF9tYnJfZW5hYmxlX2Rpc2FibGUoc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCWNv\n"
- "bnN0IHU4ICptZXRob2QsICp1aWQ7Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWludCBy\n"
- "ZXQ7Cj4gKwo+ICsJdTggbWJyX2VuX2RpcyA9ICoodTggKilkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0\n"
- "YXRlIC0gMV07Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21k\n"
- "KTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9QQUxN\n"
- "RVRIT0RbT1BBTF9TRVRdOwo+ICsJdWlkID0gT1BBTFVJRFtPUEFMX01CUkNPTlRST0xdOwo+ICsK\n"
- "PiArCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgM2MgNmMgMmMiLAo+ICsJ\n"
- "CQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJ\n"
- "CSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFS\n"
- "VExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9WQUxVRVMs\n"
- "Cj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1F\n"
- "LAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLCAvKiBFbmFibGUgKi8KPiArCQkJCSAgICBt\n"
- "YnJfZW5fZGlzLCAgICAgICAgLyogRW5hYmxlIG9yIERpc2FibGUgKi8KPiArCQkJCSAgICBPUEFM\n"
- "X0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsKPiArCQkJCSAgICBPUEFMX0VO\n"
- "RE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJ\n"
- "cHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgc2V0IE1CUiBEb250L05vdCBkb25lIGNvbW1hbmRc\n"
- "biIsCnMvRG9udC9Eb25lLyA/CgoKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJl\n"
- "dHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21k\n"
- "LCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNldF9uZXdfcHcoc3RydWN0\n"
- "IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwl1OCBjcGluX3Vp\n"
- "ZFtPUEFMX1VJRF9MRU5HVEhdOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0\n"
- "Owo+ICsJc3RydWN0IG9wYWxfbmV3X3B3ICpwdzsKPiArCXNpemVfdCBrZXlfbGVuOwo+ICsJdTgg\n"
- "KmtleTsKPiArCj4gKwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+\n"
- "ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7Cj4gKwo+ICsJcHcgPSBkZXYtPmZ1bmNfZGF0\n"
- "YVtkZXYtPnN0YXRlIC0gMV07Cj4gKwlrZXkgPSBwdy0+bmV3X3Bpbi5rZXk7Cj4gKwlrZXlfbGVu\n"
- "ID0gcHctPm5ld19waW4ua2V5X2xlbjsKPiArCW1lbWNweShjcGluX3VpZCwgT1BBTFVJRFtPUEFM\n"
- "X0NfUElOX0FETUlOMV0sIE9QQUxfVUlEX0xFTkdUSCk7Cj4gKwo+ICsJaWYgKHB3LT51c2VyX2Zv\n"
- "cl9wdyAhPSBPUEFMX0FETUlOMSkgewo+ICsJCWNwaW5fdWlkWzVdID0gMHgwMzsKPiArCQlpZiAo\n"
- "cHctPndoby5TVU0pCj4gKwkJCWNwaW5fdWlkWzddID0gcHctPm5ld19waW4ubHIgKyAxOwo+ICsJ\n"
- "CWVsc2UKPiArCQkJY3Bpbl91aWRbN10gPSBwdy0+dXNlcl9mb3JfcHc7Cj4gKwl9Cj4gKwo+ICsJ\n"
- "bWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk\n"
- "X3Rva2VuX3ZhKGNtZCwgImMycyAzYyAzY3MyYyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+\n"
- "ICsJCQkJICAgIGNwaW5fdWlkLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkgICAgbWV0aG9kLCBP\n"
- "UEFMX01FVEhPRF9MRU5HVEgsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsJCQkJ\n"
- "ICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLCAvKiBWYWx1\n"
- "ZXMgKi8KPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFS\n"
- "VE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIFBJTiAqLwo+ICsJCQkJICAg\n"
- "IGtleSwga2V5X2xlbiwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9F\n"
- "TkRMSVNULAo+ICsKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRM\n"
- "SVNUKTsKPiArCj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxk\n"
- "aW5nIFNFVCBBTUlOMSBQSU4gY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1l\n"
- "KTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2Vu\n"
- "ZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzZXRfc2lk\n"
- "X2NwaW5fcGluKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9k\n"
- "LCAqY3Bpbl91aWQ7Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWludCByZXQ7Cj4gKwo+\n"
- "ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21J\n"
- "RChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCWNwaW5fdWlkID0gT1BBTFVJRFtPUEFMX0NfUElO\n"
- "X1NJRF07Cj4gKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU0VUXTsKPiArCj4gKwlyZXQgPSB0\n"
- "ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDJjIDRjczJjIDJjIiwKPiArCQkJCSAgICBP\n"
- "UEFMX0NBTEwsCj4gKwkJCQkgICAgY3Bpbl91aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAg\n"
- "ICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJ\n"
- "U1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfVElOWV9V\n"
- "SU5UXzAxLCAvKiBWYWx1ZXMgKi8KPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAg\n"
- "ICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElOICov\n"
- "Cj4gKwkJCQkgICAgZGV2LT5rZXksIGRldi0+a2V5X2xlbiwKPiArCQkJCSAgICBPUEFMX0VORE5B\n"
- "TUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsKPiArCQkJCSAgICBPUEFMX0VORE5BTUUs\n"
- "Cj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXBy\n"
- "X2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIFNFVCBDUElOIFBJTiBjb21tYW5kLlxuIiwKPiArCQkg\n"
- "ICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0\n"
- "dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+\n"
- "ICtzdGF0aWMgdm9pZCBxdWVyeV9sb2NraW5nX3JhbmdlX2NvbnQoaW50IGVycm9yLCB2b2lkICpk\n"
- "YXRhKQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7Cj4gKwo+ICsJaWYgKGVy\n"
- "cm9yKQo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCj4gKwllcnJvciA9IHBhcnNlX2FuZF9jaGVj\n"
- "a19zdGF0dXMoZGV2KTsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4gKwo+\n"
- "ICsJZGV2LT5zdGFydCA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2VkLCA0KTsKPiArCWRl\n"
- "di0+bGVuZ3RoID0gcmVzcG9uc2VfZ2V0X3U2NCgmZGV2LT5wYXJzZWQsIDgpOwo+ICsKPiArZXJy\n"
- "X3JldHVybjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBk\n"
- "ZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHF1ZXJ5X2xvY2tpbmdfcmFuZ2Uoc3RydWN0IG9w\n"
- "YWxfZGV2ICpkZXYpCj4gK3sKPiArCXU4IGxyX2J1ZmZlcltPUEFMX1VJRF9MRU5HVEhdOwo+ICsJ\n"
- "c3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwljb25zdCB1OCAqbWV0aG9kOwo+ICsJaW50IHJldDsK\n"
- "PiArCj4gKwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsKPiAr\n"
- "CW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRVRdOwo+ICsKPiArCWlmIChidWlsZF9sb2NraW5n\n"
- "X3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1ZmZlciksIGRldi0+bHIpIDwgMCkgewo+ICsJ\n"
- "CXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIsIGRldi0+ZGlza19uYW1l\n"
- "KTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlzZXRfY29tSUQoY21kLCBkZXYt\n"
- "PmNvbUlEKTsKPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDEy\n"
- "YyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURf\n"
- "TEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsKPiArCQkJ\n"
- "CSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAg\n"
- "ICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1NUQVJUQ09MVU1OLAo+ICsJCQkJICAg\n"
- "IE9QQUxfUkFOR0VTVEFSVCwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BB\n"
- "TF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRDT0xVTU4sCj4gKwkJCQkgICAgT1BBTF9S\n"
- "QU5HRUxFTkdUSCwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRM\n"
- "SVNULAo+ICsJCQkJICAgIE9QQUxfRU5ETElTVCk7Cj4gKwo+ICsJaWYgKHJldCA8IDApIHsKPiAr\n"
- "CQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBHRVQgTG9ja2luZyBSYW5nZSBjb21tYW5kLlxu\n"
- "IiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4g\n"
- "Kwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBxdWVyeV9sb2NraW5nX3Jh\n"
- "bmdlX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkZF91c2VyX3RvX2xyKHN0cnVjdCBv\n"
- "cGFsX2RldiAqZGV2KQo+ICt7Cj4gKwl1OCBscl9idWZmZXJbT1BBTF9VSURfTEVOR1RIXTsKPiAr\n"
- "CXU4IHVzZXJfdWlkW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsK\n"
- "PiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayAqbGt1bDsK\n"
- "PiArCWludCByZXQ7Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQo\n"
- "Y21kKTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9Q\n"
- "QUxNRVRIT0RbT1BBTF9TRVRdOwo+ICsKPiArCWxrdWwgPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0\n"
- "YXRlIC0gMV07Cj4gKwo+ICsJbWVtY3B5KGxyX2J1ZmZlciwgT1BBTFVJRFtPUEFMX0xPQ0tJTkdS\n"
- "QU5HRV9BQ0VfUkRMT0NLRURdLAo+ICsJICAgICAgIE9QQUxfVUlEX0xFTkdUSCk7Cj4gKwo+ICsJ\n"
- "aWYgKGxrdWwtPmxfc3RhdGUgPT0gT1BBTF9SVykKPiArCQltZW1jcHkobHJfYnVmZmVyLCBPUEFM\n"
- "VUlEW09QQUxfTE9DS0lOR1JBTkdFX0FDRV9XUkxPQ0tFRF0sCj4gKwkJICAgICAgIE9QQUxfVUlE\n"
- "X0xFTkdUSCk7Cj4gKwo+ICsJbHJfYnVmZmVyWzddID0gZGV2LT5scjsKPiArCj4gKwltZW1jcHko\n"
- "dXNlcl91aWQsIE9QQUxVSURbT1BBTF9VU0VSMV9VSURdLCBPUEFMX1VJRF9MRU5HVEgpOwo+ICsJ\n"
- "dXNlcl91aWRbN10gPSBsa3VsLT5hdXRob3JpdHkud2hvOwo+ICsKPiArCXJldCA9IHRlc3RfYW5k\n"
- "X2FkZF90b2tlbl92YShjbWQsICJjMnMgM2MgM2MgMmMgMnNjIGMyc2MgY3MyYyA1YyIsCj4gKwkJ\n"
- "CQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVOR1RILAo+\n"
- "ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsKPiArCQkJCSAgICBPUEFM\n"
- "X1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1RJ\n"
- "TllfVUlOVF8wMSwgLyogVmFsdWVzICovCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+\n"
- "ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAv\n"
- "KiBCb29sZWFuRXhwciAqLwo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAg\n"
- "ICBPUEFMX1NUQVJUTkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTFVJRFtPUEFMX0hBTEZfVUlEX0FV\n"
- "VEhPUklUWV9PQkpfUkVGXSwKPiArCQkJCSAgICBPUEFMX1VJRF9MRU5HVEhfSEFMRiwKPiArCQkJ\n"
- "CSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwK\n"
- "PiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTFVJRFtPUEFMX0hB\n"
- "TEZfVUlEX0FVVEhPUklUWV9PQkpfUkVGXSwKPiArCQkJCSAgICBPUEFMX1VJRF9MRU5HVEhfSEFM\n"
- "RiwKPiArCQkJCSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxf\n"
- "RU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTFVJ\n"
- "RFtPUEFMX0hBTEZfVUlEX0JPT0xFQU5fQUNFXSwKPiArCQkJCSAgICBPUEFMX1VJRF9MRU5HVEhf\n"
- "SEFMRiwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSwKPiArCQkJCSAgICBPUEFMX0VORE5B\n"
- "TUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfRU5ETElTVCwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUs\n"
- "Cj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJ\n"
- "CSAgICBPUEFMX0VORExJU1QpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlwcl9lcnIoIiVzOiBF\n"
- "cnJvciBidWlsZGluZyBhZGQgdXNlciB0byBsb2NraW5nIHJhbmdlIGNvbW1hbmQuXG4iLAo+ICsJ\n"
- "CSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwly\n"
- "ZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29udCk7Cj4gK30KPiAr\n"
- "Cj4gK3N0YXRpYyBpbnQgbG9ja191bmxvY2tfbG9ja2luZ19yYW5nZShzdHJ1Y3Qgb3BhbF9kZXYg\n"
- "KmRldikKPiArewo+ICsJdTggbHJfYnVmZmVyW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qg\n"
- "b3BhbF9jbWQgKmNtZDsKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2Nr\n"
- "X3VubG9jayAqbGt1bDsKPiArCWludCByZXQ7Cj4gKwl1OCByZWFkX2xvY2tlZCA9IDEsIHdyaXRl\n"
- "X2xvY2tlZCA9IDE7Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQo\n"
- "Y21kKTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9Q\n"
- "QUxNRVRIT0RbT1BBTF9TRVRdOwo+ICsJbGt1bCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUg\n"
- "LSAxXTsKPiArCWlmIChidWlsZF9sb2NraW5nX3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1\n"
- "ZmZlciksIGRldi0+bHIpIDwgMCkgewo+ICsJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tp\n"
- "bmcgcmFuZ2VcbiIsIGRldi0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0K\n"
- "PiArCj4gKwlzd2l0Y2ggKGxrdWwtPmxfc3RhdGUpIHsKPiArCWNhc2UgT1BBTF9STzoKPiArCQly\n"
- "ZWFkX2xvY2tlZCA9IDA7Cj4gKwkJd3JpdGVfbG9ja2VkID0gMTsKPiArCQlicmVhazsKPiArCWNh\n"
- "c2UgT1BBTF9SVzoKPiArCQlyZWFkX2xvY2tlZCA9IDA7Cj4gKwkJd3JpdGVfbG9ja2VkID0gMDsK\n"
- "PiArCQlicmVhazsKPiArCWNhc2UgT1BBTF9MSzoKPiArCQkvKiB2YXJzIGFyZSBpbml0YWxpemVk\n"
- "IHRvIGxvY2tlZCAqLwo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoKPiArCQlwcl9lcnIoIlRyaWVk\n"
- "IHRvIHNldCBhbiBpbnZhbGlkIGxvY2tpbmcgc3RhdGUuLi4gcmV0dXJuaW5nIHRvIHVsYW5kXG4i\n"
- "KTsKPiArCQlyZXR1cm4gMTsKPiArCX0KPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5f\n"
- "dmEoY21kLCAiYzJzYyAzYyA0YyA0YyAzYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJ\n"
- "ICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9N\n"
- "RVRIT0RfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsKPiArCQkJCSAgICBP\n"
- "UEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywKPiArCQkJCSAgICBPUEFMX1NU\n"
- "QVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9S\n"
- "RUFETE9DS0VELAo+ICsJCQkJICAgIHJlYWRfbG9ja2VkLAo+ICsJCQkJICAgIE9QQUxfRU5ETkFN\n"
- "RSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9XUklURUxP\n"
- "Q0tFRCwKPiArCQkJCSAgICB3cml0ZV9sb2NrZWQsCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+\n"
- "ICsKPiArCQkJCSAgICBPUEFMX0VORExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+ICsJ\n"
- "CQkJICAgIE9QQUxfRU5ETElTVCk7Cj4gKwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlwcl9lcnIo\n"
- "IiVzOiBFcnJvciBidWlsZGluZyBTRVQgY29tbWFuZC5cbiIsIGRldi0+ZGlza19uYW1lKTsKPiAr\n"
- "CQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21k\n"
- "LCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICsKPiArc3RhdGljIGludCBsb2NrX3VubG9ja19s\n"
- "b2NraW5nX3JhbmdlX1NVTShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJdTggbHJfYnVm\n"
- "ZmVyW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWNvbnN0\n"
- "IHU4ICptZXRob2Q7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayAqbGt1bDsKPiArCWludCBy\n"
- "ZXQ7Cj4gKwl1OCByZWFkX2xvY2tlZCA9IDEsIHdyaXRlX2xvY2tlZCA9IDE7Cj4gKwo+ICsJY21k\n"
- "ID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQs\n"
- "IGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOwo+ICsJ\n"
- "bGt1bCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKPiArCWlmIChidWlsZF9sb2Nr\n"
- "aW5nX3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1ZmZlciksIGRldi0+bHIpIDwgMCkgewo+\n"
- "ICsJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIsIGRldi0+ZGlza19u\n"
- "YW1lKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlzd2l0Y2ggKGxrdWwtPmxf\n"
- "c3RhdGUpIHsKPiArCWNhc2UgT1BBTF9STzoKPiArCQlyZWFkX2xvY2tlZCA9IDA7Cj4gKwkJd3Jp\n"
- "dGVfbG9ja2VkID0gMTsKPiArCQlicmVhazsKPiArCWNhc2UgT1BBTF9SVzoKPiArCQlyZWFkX2xv\n"
- "Y2tlZCA9IDA7Cj4gKwkJd3JpdGVfbG9ja2VkID0gMDsKPiArCQlicmVhazsKPiArCWNhc2UgT1BB\n"
- "TF9MSzoKPiArCQkvKiB2YXJzIGFyZSBpbml0YWxpemVkIHRvIGxvY2tlZCAqLwo+ICsJCWJyZWFr\n"
- "Owo+ICsJZGVmYXVsdDoKPiArCQlwcl9lcnIoIlRyaWVkIHRvIHNldCBhbiBpbnZhbGlkIGxvY2tp\n"
- "bmcgc3RhdGUuXG4iKTsKPiArCQlyZXR1cm4gMTsKPiArCX0KPiArCj4gKwlyZXQgPSB0ZXN0X2Fu\n"
- "ZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzYyAzYyA0YyA0YyA0YyA0YyAzYyIsCj4gKwkJCQkgICAg\n"
- "T1BBTF9DQUxMLAo+ICsJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJ\n"
- "ICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNU\n"
- "LAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywK\n"
- "PiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUs\n"
- "Cj4gKwkJCQkgICAgT1BBTF9SRUFETE9DS0VOQUJMRUQsCj4gKwkJCQkgICAgT1BBTF9UUlVFLAo+\n"
- "ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4g\n"
- "KwkJCQkgICAgT1BBTF9XUklURUxPQ0tFTkFCTEVELAo+ICsJCQkJICAgIE9QQUxfVFJVRSwKPiAr\n"
- "CQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJ\n"
- "CQkJICAgIE9QQUxfUkVBRExPQ0tFRCwKPiArCQkJCSAgICByZWFkX2xvY2tlZCwKPiArCQkJCSAg\n"
- "ICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAg\n"
- "IE9QQUxfV1JJVEVMT0NLRUQsCj4gKwkJCQkgICAgd3JpdGVfbG9ja2VkLAo+ICsJCQkJICAgIE9Q\n"
- "QUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsJCQkJICAgIE9QQUxf\n"
- "RU5ETkFNRSwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsJaWYgKHJldCA8IDApIHsKPiAr\n"
- "CQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBTRVQgY29tbWFuZC5cbiIsIGRldi0+ZGlza19u\n"
- "YW1lKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5k\n"
- "KGRldiwgY21kLCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtpbnQgYWN0aXZhdGVfbHNwKHN0\n"
- "cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwl1OCB1c2VyX2xyW09QQUxfVUlEX0xFTkdUSF07\n"
- "Cj4gKwljb25zdCB1OCAqbWV0aG9kLCAqdWlkOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4g\n"
- "KwlpbnQgcmV0Owo+ICsJc2l6ZV90IHVpbnRfMyA9IDB4ODM7Cj4gKwo+ICsJY21kID0gJmRldi0+\n"
- "Y21kOwo+ICsKPiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwlzZXRfY29tSUQoY21kLCBkZXYt\n"
- "PmNvbUlEKTsKPiArCj4gKwl1aWQgPSBPUEFMVUlEW09QQUxfTE9DS0lOR1NQX1VJRF07Cj4gKwlt\n"
- "ZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfQUNUSVZBVEVdOwo+ICsKPiArCXJldCA9IHRlc3RfYW5k\n"
- "X2FkZF90b2tlbl92YShjbWQsICJjMnMiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAg\n"
- "ICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xF\n"
- "TkdUSCk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5n\n"
- "IEFjdGl2YXRlIExvY2tpbmdTUCBjb21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25h\n"
- "bWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwkvKiBBY3RpdmF0aW5nIGFzIFNVTSAqLwo+\n"
- "ICsJaWYgKGRldi0+bHIgPiAwKSB7Cj4gKwkJcmV0ID0gYnVpbGRfbG9ja2luZ19yYW5nZSh1c2Vy\n"
- "X2xyLCBzaXplb2YodXNlcl9sciksIGRldi0+bHIpOwo+ICsJCWlmIChyZXQgPCAwKSB7Cj4gKwkJ\n"
- "CXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgdXNlclxuIiwKPiArCQkJICAgICAgIGRl\n"
- "di0+ZGlza19uYW1lKTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwkJdGVzdF9hbmRfYWRk\n"
- "X3Rva2VuX3ZhKGNtZCwgIjJjIDRjIGNzYyAyYyIsCj4gKwkJCQkgICAgICBPUEFMX1NUQVJUTElT\n"
- "VCwKPiArCQkJCSAgICAgIE9QQUxfU1RBUlROQU1FLAo+ICsKPiArCQkJCSAgICAgIHVpbnRfMywK\n"
- "PiArCQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzA2LAo+ICsJCQkJICAgICAgT1BBTF9USU5ZX1VJ\n"
- "TlRfMDAsCj4gKwkJCQkgICAgICBPUEFMX1RJTllfVUlOVF8wMCwKPiArCj4gKwkJCQkgICAgICBP\n"
- "UEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICAgIHVzZXJfbHIsIE9QQUxfVUlEX0xFTkdUSCwKPiAr\n"
- "CQkJCSAgICAgIE9QQUxfRU5ETElTVCwKPiArCj4gKwkJCQkgICAgICBPUEFMX0VORE5BTUUsCj4g\n"
- "KwkJCQkgICAgICBPUEFMX0VORExJU1QpOwo+ICsJfSBlbHNlIC8qIEFjdGlhdmUgTm9ybWFsIE1v\n"
- "ZGUgKi8KPiArCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiMmMiLAo+ICsJCQkJ\n"
- "CSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlp\n"
- "ZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEFjdGl2YXRlIExv\n"
- "Y2tpbmdTUCBjb21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJl\n"
- "dHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21k\n"
- "LCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBnZXRfbHNwX2xpZmVjeWNs\n"
- "ZV9jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKPiArewo+ICsKPiArCXN0cnVjdCBvcGFsX2Rl\n"
- "diAqZGV2ID0gZGF0YTsKPiArCXU4IGxjX3N0YXR1czsKPiArCj4gKwlpZiAoZXJyb3IpCj4gKwkJ\n"
- "Z290byBlcnJfcmV0dXJuOwo+ICsKPiArCWVycm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhk\n"
- "ZXYpOwo+ICsJaWYgKGVycm9yKQo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCj4gKwlsY19zdGF0\n"
- "dXMgPSByZXNwb25zZV9nZXRfdTY0KCZkZXYtPnBhcnNlZCwgNCk7Cj4gKwkvKiAweDA4IGlzIE1h\n"
- "bnVmYWN1cmVkIEluYWN0aXZlICovCj4gKwkvKiAweDA5IGlzIE1hbnVmYWN0dXJlZCAqLwo+ICsJ\n"
- "aWYgKGxjX3N0YXR1cyAhPSAweDA4KSB7Cj4gKwkJcHJfZXJyKCIlczogQ291bGRuJ3QgZGV0ZXJt\n"
- "aW5lIHRoZSBzdGF0dXMgb2YgdGhlIExpZmN5Y2xlIHN0YXRlXG4iLAo+ICsJCSAgICAgICBkZXYt\n"
- "PmRpc2tfbmFtZSk7Cj4gKwkJZXJyb3IgPSAtRU5PREVWOwo+ICsJfQo+ICsKPiArZXJyX3JldHVy\n"
- "bjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYpOwo+\n"
- "ICt9Cj4gKwo+ICsvKiBEZXRlcm1pbmUgaWYgd2UncmUgaW4gdGhlIE1hbnVmYWN0dXJlZCBJbmFj\n"
- "dGl2ZSBvciBBY3RpdmUgc3RhdGUgKi8KPiAraW50IGdldF9sc3BfbGlmZWN5Y2xlKHN0cnVjdCBv\n"
- "cGFsX2RldiAqZGV2KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWNvbnN0IHU4\n"
- "ICptZXRob2QsICp1aWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsKPiAr\n"
- "Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7\n"
- "Cj4gKwo+ICsJdWlkID0gT1BBTFVJRFtPUEFMX0xPQ0tJTkdTUF9VSURdOwo+ICsJbWV0aG9kID0g\n"
- "T1BBTE1FVEhPRFtPUEFMX0dFVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3Zh\n"
- "KGNtZCwgImMycyAyYyA0YyA0YyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAg\n"
- "IHVpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVO\n"
- "R1RILAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJU\n"
- "TElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5Z\n"
- "X1VJTlRfMDMsIC8qIFN0YXJ0IENvbHVtbiAqLwo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzA2\n"
- "LCAvKiBMaWZjeWNsZSBDb2x1bW4gKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJ\n"
- "CQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzA0LCAvKiBF\n"
- "bmQgQ29sdW1uICovCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIExpZmVjeWNsZSBD\n"
- "b2x1bW4gKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfRU5E\n"
- "TElTVCwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4g\n"
- "KwkJcHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgR0VUIExpZmVjeWNsZSBTdGF0dXMgY29tbWFu\n"
- "ZFxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9\n"
- "Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZXRfbHNwX2xpZmVj\n"
- "eWNsZV9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgZ2V0X21zaWRfY3Bpbl9waW5fY29u\n"
- "dChpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCj4gK3sKPiArCWNvbnN0IGNoYXIgKm1zaWRfcGluOwo+\n"
- "ICsJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwo+ICsJc2l6ZV90IHN0cmxlbjsKPiArCj4g\n"
- "KwlpZiAoZXJyb3IpCj4gKwkJZ290byBlcnJfcmV0dXJuOwo+ICsKPiArCWVycm9yID0gcGFyc2Vf\n"
- "YW5kX2NoZWNrX3N0YXR1cyhkZXYpOwo+ICsJaWYgKGVycm9yKQo+ICsJCWdvdG8gZXJyX3JldHVy\n"
- "bjsKPiArCj4gKwlzdHJsZW4gPSByZXNwb25zZV9nZXRfc3RyaW5nKCZkZXYtPnBhcnNlZCwgNCwg\n"
- "Jm1zaWRfcGluKTsKPiArCWlmICghbXNpZF9waW4pIHsKPiArCQlwcl9lcnIoIiVzOiBDb3VsZG4n\n"
- "dCBleHRyYWN0IFBJTiBmcm9tIHJlc3BvbnNlXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJZXJyb3IgPSAx\n"
- "Owo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCX0KPiArCj4gKwlkZXYtPnByZXZfZGF0YSA9IGtt\n"
- "ZW1kdXAobXNpZF9waW4sIHN0cmxlbiwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWRldi0+cHJldl9k\n"
- "YXRhKQo+ICsJCWVycm9yID0gLUVOT01FTTsKPiArCj4gKwlkZXYtPnByZXZfZF9sZW4gPSBzdHJs\n"
- "ZW47Cj4gKwo+ICsgZXJyX3JldHVybjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5v\n"
- "cGVyX2NiKGVycm9yLCBkZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGdldF9tc2lkX2NwaW5f\n"
- "cGluKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9kLCAqc211\n"
- "aWQ7Cj4gKwlpbnQgcmV0Owo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwo+ICsJY21kID0g\n"
- "JmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQsIGRl\n"
- "di0+Y29tSUQpOwo+ICsKPiArCXNtdWlkID0gT1BBTFVJRFtPUEFMX0NfUElOX01TSURdOwo+ICsJ\n"
- "bWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0dFVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk\n"
- "X3Rva2VuX3ZhKGNtZCwgImMgMnMgMTJjIiwKPiArCQkJCSAgICBPUEFMX0NBTEwsCj4gKwo+ICsJ\n"
- "CQkJICAgIHNtdWlkLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkgICAgbWV0aG9kLCBPUEFMX01F\n"
- "VEhPRF9MRU5HVEgsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsJCQkJICAgIE9Q\n"
- "QUxfU1RBUlRMSVNULAo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxf\n"
- "VElOWV9VSU5UXzAzLCAvKiBTYXJ0IENvbHVtbiAqLwo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5U\n"
- "XzAzLCAvKiBQSU4gKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9T\n"
- "VEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDQsIC8qIEVuZCBDb2x1bW4gKi8K\n"
- "PiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElOICovCj4gKwkJCQkgICAgT1BBTF9F\n"
- "TkROQU1FLAo+ICsJCQkJICAgIE9QQUxfRU5ETElTVCwKPiArCQkJCSAgICBPUEFMX0VORExJU1Qp\n"
- "Owo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcg\n"
- "R2V0IE1TSUQgQ1BJTiBQSU4gY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1l\n"
- "KTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2Vu\n"
- "ZChkZXYsIGNtZCwgZ2V0X21zaWRfY3Bpbl9waW5fY29udCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2\n"
- "b2lkIHVubG9ja19zdXNwZW5kX2ZpbmFsKGludCBlcnJvciwgdm9pZCAqZGF0YSkKPiArewo+ICsJ\n"
- "c3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwo+ICsKPiArCWRldi0+cmVzdW1lX2Zyb21fc3Vz\n"
- "cGVuZCA9IGZhbHNlOwo+ICsJZGV2LT5yZXN1bWVfZGF0YSA9IE5VTEw7Cj4gKwlkZXYtPmZ1bmNf\n"
- "ZGF0YSA9IE5VTEw7Cj4gKwlkZXYtPmJkZXYgPSBOVUxMOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50\n"
- "IGJ1aWxkX2VuZF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCXN0\n"
- "cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsKPiArCWNsZWFyX29w\n"
- "YWxfY21kKGNtZCk7Cj4gKwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7Cj4gKwlyZXR1\n"
- "cm4gdGVzdF9hbmRfYWRkX3Rva2VuX3U4KGNtZCwgT1BBTF9FTkRPRlNFU1NJT04pOwo+ICt9Cj4g\n"
- "Kwo+ICtzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4g\n"
- "K3sKPiArCWlmIChidWlsZF9lbmRfb3BhbF9zZXNzaW9uKGRldikgPCAwKQo+ICsJCXJldHVybiAt\n"
- "MTsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsICZkZXYtPmNtZCwgZW5kX3Nlc3Np\n"
- "b25fY29udCk7Cj4gK30KQW55IHJlYXNvbiB3ZSBjYW50OgoKaW50IHJldCA9IGJ1aWxkXy4uLgpp\n"
- "ZiAocmV0IDwgMCkKCXJldHVybiByZXQ7CgoKPiArCj4gK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9kZXYg\n"
- "KmZpbmRfb3BhbF9kZXYoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgdTggbHIpCj4gK3sKPiAr\n"
- "CXN0cnVjdCBvcGFsX2RldiAqaXRlciwgKm9wYWxfZGV2ID0gTlVMTDsKPiArCj4gKwlsaXN0X2Zv\n"
- "cl9lYWNoX2VudHJ5KGl0ZXIsICZvcGFsX2xpc3QsIG5vZGUpIHsKPiArCQlpZiAoc3RybmNtcChp\n"
- "dGVyLT5kaXNrX25hbWUsIGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZSwKPiArCQkJICAgIERJU0tf\n"
- "TkFNRV9MRU4pKQo+ICsJCQljb250aW51ZTsKPiArCQlpZiAoaXRlci0+bHIgPT0gbHIpIHsKPiAr\n"
- "CQkJb3BhbF9kZXYgPSBpdGVyOwo+ICsJCQlicmVhazsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJcmV0\n"
- "dXJuIG9wYWxfZGV2Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHVwZGF0ZV9vcGFsX2RldihzdHJ1\n"
- "Y3Qgb3BhbF9kZXYgKm9sZF9kZXYsIHN0cnVjdCBvcGFsX2RldiAqbmV3X2RldikKPiArewo+ICsJ\n"
- "aWYgKCFhdG9taWNfYWRkX3VubGVzcygmb2xkX2Rldi0+aW5fdXNlLCAxLCAxKSkgewo+ICsJCXBy\n"
- "X2VycigiJXM6IGRldiB3YXMgaW4gdXNlXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJcmV0dXJuIC1FQlVT\n"
- "WTsKPiArCX0KPiArCj4gKwlvbGRfZGV2LT5rZXlfbmFtZV9sZW4gPSBuZXdfZGV2LT5rZXlfbmFt\n"
- "ZV9sZW47Cj4gKwlpZiAoIW1lbWNweShvbGRfZGV2LT5rZXlfbmFtZSwgbmV3X2Rldi0+a2V5X25h\n"
- "bWUsIG9sZF9kZXYtPmtleV9uYW1lX2xlbikpIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJvciB1cGRh\n"
- "dGluZyBkZXZpY2U6XG4iLCBvbGRfZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiAtRUZBVUxU\n"
- "Owo+ICsJfQo+ICsKPiArCWlmICghc3RybmNweShvbGRfZGV2LT5kaXNrX25hbWUsIG5ld19kZXYt\n"
- "PmRpc2tfbmFtZSwgRElTS19OQU1FX0xFTikpIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJvciByZWdp\n"
- "c3RlcmluZyBkZXZpY2U6IGNvcHlpbmcgZGlzayBuYW1lXG4iLAo+ICsJCSAgICAgICBvbGRfZGV2\n"
- "LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsJfQo+ICsKPiArCW9sZF9kZXYt\n"
- "PmNvbUlEID0gbmV3X2Rldi0+Y29tSUQ7Cj4gKwlvbGRfZGV2LT5zdGFydCA9IG5ld19kZXYtPnN0\n"
- "YXJ0Owo+ICsJb2xkX2Rldi0+bGVuZ3RoID0gbmV3X2Rldi0+bGVuZ3RoOwo+ICsJb2xkX2Rldi0+\n"
- "YWxpZ24gPSBuZXdfZGV2LT5hbGlnbjsKPiArCW9sZF9kZXYtPmxvd2VzdF9sYmEgPSBuZXdfZGV2\n"
- "LT5sb3dlc3RfbGJhOwo+ICsJb2xkX2Rldi0+YmRldiA9IE5VTEw7Cj4gKwlvbGRfZGV2LT5maW5h\n"
- "bF9jYiA9IG5ld19kZXYtPmZpbmFsX2NiOwo+ICsJb2xkX2Rldi0+ZmluYWxfY2JfZGF0YSA9IG5l\n"
- "d19kZXYtPmZpbmFsX2NiX2RhdGE7Cj4gKwlvbGRfZGV2LT5vcGVyX2NiID0gbmV3X2Rldi0+b3Bl\n"
- "cl9jYjsKPiArCW9sZF9kZXYtPnN0YXRlID0gbmV3X2Rldi0+c3RhdGU7Cj4gKwlvbGRfZGV2LT5m\n"
- "dW5jcyA9IG5ld19kZXYtPmZ1bmNzOwo+ICsKPiArCWtmcmVlKG9sZF9kZXYtPmNvbXBsZXRpb24p\n"
- "Owo+ICsJY2xlYW5fZnVuY3Rpb25fZGF0YShvbGRfZGV2KTsKPiArCj4gKwlvbGRfZGV2LT5jb21w\n"
- "bGV0aW9uID0gbmV3X2Rldi0+Y29tcGxldGlvbjsKPiArCj4gKwkvKgo+ICsJICogV29uJ3QgYmUg\n"
- "YWJsZSB0byBhdXRvIHVubG9jayB0aGlzIGxvY2tpbmcgcmFuZ2UgYmFzZWQgb24gYmxvY2sKPiAr\n"
- "CSAqIHJlcXVlc3Rlcy4KPiArCSAqLwo+ICsJaWYgKG9sZF9kZXYtPmxlbmd0aCA9PSAwKQo+ICsJ\n"
- "CXByX3dhcm4oIiVzOiBNaXNzaW5nIGJsb2NrIGluZm9ybWF0aW9uIGZvciBsb2NraW5nIHJhbmdl\n"
- "ICVkXG4iLAo+ICsJCQlvbGRfZGV2LT5kaXNrX25hbWUsIG9sZF9kZXYtPmxyKTsKPiArCj4gKwly\n"
- "ZXR1cm4gMDsKPiArfQo+ICsKPiAraW50IG9wYWxfcmVnaXN0ZXJfY29udChzdHJ1Y3Qgb3BhbF9k\n"
- "ZXYgKm5ld19kZXYpCj4gK3sKPiArCXN0cnVjdCBvcGFsX2RldiAqb2xkX2RldjsKPiArCXVuc2ln\n"
- "bmVkIGxvbmcgZmxhZ3M7Cj4gKwlpbnQgZXJyb3IgPSAwOwo+ICsKPiArCXNwaW5fbG9ja19pcnFz\n"
- "YXZlKCZsaXN0X3NwaW5sb2NrLCBmbGFncyk7Cj4gKwo+ICsJb2xkX2RldiA9IGZpbmRfb3BhbF9k\n"
- "ZXYobmV3X2Rldi0+YmRldiwgbmV3X2Rldi0+bHIpOwo+ICsJaWYgKCFvbGRfZGV2KSB7Cj4gKwkJ\n"
- "bGlzdF9hZGRfdGFpbCgmbmV3X2Rldi0+bm9kZSwgJm9wYWxfbGlzdCk7Cj4gKwkJb2xkX2RldiA9\n"
- "IG5ld19kZXY7Cj4gKwl9IGVsc2Ugewo+ICsJCWlmIChvbGRfZGV2ID09IG5ld19kZXYpCj4gKwkJ\n"
- "CWVycm9yID0gMDsKPiArCQllbHNlIHsKPiArCQkJZXJyb3IgPSB1cGRhdGVfb3BhbF9kZXYob2xk\n"
- "X2RldiwgbmV3X2Rldik7Cj4gKwkJCWNsZWFuX29wYWxfa2V5KG5ld19kZXYpOwo+ICsJCQlrZnJl\n"
- "ZShuZXdfZGV2KTsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJaWYgKGVycm9yKQo+ICsJCWxpc3RfZGVs\n"
- "KCZvbGRfZGV2LT5ub2RlKTsKPiArCj4gKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZsaXN0X3Nw\n"
- "aW5sb2NrLCBmbGFncyk7Cj4gKwo+ICsJaWYgKCFlcnJvcikKPiArCQlwcl9pbmZvKCIlczogUmVn\n"
- "aXN0ZXJlZCBrZXkgZm9yIGxvY2tpbmcgcmFuZ2U6ICVkXG4iLAo+ICsJCQlvbGRfZGV2LT5kaXNr\n"
- "X25hbWUsIG9sZF9kZXYtPmxyKTsKPiArCj4gKwlpZiAob2xkX2Rldi0+b3Blcl9jYikKPiArCQlv\n"
- "bGRfZGV2LT5vcGVyX2NiKGVycm9yLCBvbGRfZGV2KTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+\n"
- "ICsKPiArc3RhdGljIHZvaWQgbmV4dChpbnQgZXJyb3IsIHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+\n"
- "ICt7Cj4gKwlvcGFsX3N0ZXAgZnVuYyA9IGRldi0+ZnVuY3NbZGV2LT5zdGF0ZV07Cj4gKwl2b2lk\n"
- "ICpjYl9kYXRhID0gZGV2LT5maW5hbF9jYl9kYXRhOwo+ICsJc2VjX2NiICpjYiA9IGRldi0+Zmlu\n"
- "YWxfY2I7Cj4gKwlib29sIGRvbmUgPSBmYWxzZTsKPiArCj4gKwo+ICsJaWYgKGVycm9yIHx8ICFm\n"
- "dW5jKSB7Cj4gKwkJZG9uZSA9IHRydWU7Cj4gKwkJZ290byBuZXh0X2V4aXQ7Cj4gKwl9Cj4gKwlk\n"
- "ZXYtPnN0YXRlKys7Cj4gKwlkZXYtPm9wZXJfY2IgPSBuZXh0Owo+ICsJZXJyb3IgPSBmdW5jKGRl\n"
- "dik7Cj4gKyBuZXh0X2V4aXQ6Cj4gKwlpZiAoZXJyb3IpIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJv\n"
- "ciBvbiBzdGVwIGZ1bmN0aW9uOiAlZCB3aXRoIGVycm9yICVkOiAlc1xuIiwKPiArCQkgICAgICAg\n"
- "ZGV2LT5kaXNrX25hbWUsIGRldi0+c3RhdGUsIGVycm9yLAo+ICsJCSAgICAgICBvcGFsX2Vycm9y\n"
- "X3RvX2h1bWFuKGVycm9yKSk7Cj4gKwo+ICsKPiArCQlhdG9taWNfZGVjKCZkZXYtPmluX3VzZSk7\n"
- "Cj4gKwkJaWYgKGRldi0+ZXJyb3JfY2IpIHsKPiArCQkJZGV2LT5lcnJvcl9jYihkZXYtPmVycm9y\n"
- "X2NiX2RhdGEpOwo+ICsJCQlyZXR1cm47Cj4gKwkJfQo+ICsJCWlmIChjYikKPiArCQkJY2IoZXJy\n"
- "b3IsIGNiX2RhdGEpOwo+ICsKPiArCQlkZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVz\n"
- "ID0gZXJyb3I7Cj4gKwkJY29tcGxldGUoJmRldi0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24p\n"
- "Owo+ICsJfSBlbHNlIGlmICghZXJyb3IgJiYgZG9uZSkgewo+ICsJCWF0b21pY19kZWMoJmRldi0+\n"
- "aW5fdXNlKTsKPiArCQlpZiAoY2IpCj4gKwkJCWNiKGVycm9yLCBjYl9kYXRhKTsKPiArCQlkZXYt\n"
- "PmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVzID0gZXJyb3I7Cj4gKwkJY29tcGxldGUoJmRl\n"
- "di0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24pOwo+ICsJfQo+ICt9Cj4gKwo+ICtjb25zdCBv\n"
- "cGFsX3N0ZXAgZXJyb3JfZW5kX3Nlc3Npb25bXSA9IHsKPiArCWVuZF9vcGFsX3Nlc3Npb24sCj4g\n"
- "KwlOVUxMLAo+ICt9Owo+ICtzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb25fZXJyb3Ioc3RydWN0\n"
- "IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCj4gKwlkZXYtPmZ1bmNzID0gZXJyb3JfZW5kX3Nlc3Np\n"
- "b247Cj4gKwlkZXYtPnN0YXRlID0gMDsKPiArCWRldi0+ZXJyb3JfY2IgPSBOVUxMOwo+ICsJbmV4\n"
- "dCgwLCBkZXYpOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9k\n"
- "ZXYgKmFsbG9jX29wYWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHU4IGxyKQo+ICt7\n"
- "Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKm9wYWxfZGV2Owo+ICsJc3RydWN0IHJlcXVlc3RfcXVldWUg\n"
- "KnE7Cj4gKwl1bnNpZ25lZCBsb25nIGRtYV9hbGlnbjsKPiArCWNvbnN0IGNoYXIgKmRpc2tfbmFt\n"
- "ZTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJaW50IHJldDsKPiArCj4gKwlvcGFsX2Rl\n"
- "diA9IGt6YWxsb2Moc2l6ZW9mKCpvcGFsX2RldiksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCFvcGFs\n"
- "X2RldikKPiArCQlyZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKPiArCj4gKwlvcGFsX2Rldi0+YmRl\n"
- "diA9IGJkZXY7Cj4gKwlvcGFsX2Rldi0+bHIgPSBscjsKPiArCWNtZCA9ICZvcGFsX2Rldi0+Y21k\n"
- "Owo+ICsJY21kLT5jbWQgPSBjbWQtPmNtZF9idWY7Cj4gKwljbWQtPnJlc3AgPSBjbWQtPnJlc3Bf\n"
- "YnVmOwo+ICsKPiArCWRpc2tfbmFtZSA9IGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZTsKPiArCWlm\n"
- "ICghc3RybmNweShvcGFsX2Rldi0+ZGlza19uYW1lLCBkaXNrX25hbWUsIERJU0tfTkFNRV9MRU4p\n"
- "KSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgcmVnaXN0ZXJpbmcgZGV2aWNlOiBjb3B5aW5nIGRp\n"
- "c2sgbmFtZVxuIiwKPiArCQkgICAgICAgZGlza19uYW1lKTsKPiArCQlyZXQgPSAtRUZBVUxUOwo+\n"
- "ICsJCWdvdG8gZXJyX2ZyZWVfZGV2Owo+ICsJfQo+ICsKPiArCXEgPSBiZGV2LT5iZF9xdWV1ZTsK\n"
- "PiArCWRtYV9hbGlnbiA9IChxdWV1ZV9kbWFfYWxpZ25tZW50KHEpIHwgcS0+ZG1hX3BhZF9tYXNr\n"
- "KSArIDE7Cj4gKwljbWQtPmNtZCA9ICh1OCAqKXJvdW5kX3VwKCh1aW50cHRyX3QpY21kLT5jbWQs\n"
- "IGRtYV9hbGlnbik7Cj4gKwljbWQtPnJlc3AgPSAodTggKilyb3VuZF91cCgodWludHB0cl90KWNt\n"
- "ZC0+cmVzcCwgZG1hX2FsaWduKTsKPiArCj4gKwlJTklUX0xJU1RfSEVBRCgmb3BhbF9kZXYtPm5v\n"
- "ZGUpOwo+ICsJYXRvbWljX3NldCgmb3BhbF9kZXYtPmluX3VzZSwgMSk7Cj4gKwo+ICsJb3BhbF9k\n"
- "ZXYtPmNvbXBsZXRpb24gPSBremFsbG9jKHNpemVvZigqb3BhbF9kZXYtPmNvbXBsZXRpb24pLAo+\n"
- "ICsJCQkJICAgICAgIEdGUF9LRVJORUwpOwo+ICsKPiArCWlmICghb3BhbF9kZXYtPmNvbXBsZXRp\n"
- "b24pCj4gKwkJZ290byBlcnJfZnJlZV9kZXY7Cj4gKwo+ICsJaW5pdF9jb21wbGV0aW9uKCZvcGFs\n"
- "X2Rldi0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24pOwo+ICsJb3BhbF9kZXYtPmNvbXBsZXRp\n"
- "b24tPmNvbXBsZXRpb25fc3RhdHVzID0gMDsKPiArCW9wYWxfZGV2LT5zdGF0ZSA9IDA7Cj4gKwo+\n"
- "ICsJcmV0dXJuIG9wYWxfZGV2Owo+ICsKPiArZXJyX2ZyZWVfZGV2Ogo+ICsJa2ZyZWUob3BhbF9k\n"
- "ZXYpOwo+ICsJcmV0dXJuIEVSUl9QVFIocmV0KTsKPiArfQo+ICsKPiAraW50IG9wYWxfcmVnaXN0\n"
- "ZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IG9wYWxfa2V5ICprZXlfY21kLAo+\n"
- "ICsJCSAgY29uc3Qgb3BhbF9zdGVwICpmdW5jcykKPiArewo+ICsJc3RydWN0IG9wYWxfZGV2ICpu\n"
- "ZXdfZGV2ID0gTlVMTDsKPiArCXU4IGtleV9sZW4gPSBrZXlfY21kLT5rZXlfbGVuOwo+ICsJdTgg\n"
- "bHIgPSBrZXlfY21kLT5scjsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247\n"
- "Cj4gKwlpbnQgcmV0Owo+ICsKPiArCW5ld19kZXYgPSBhbGxvY19vcGFsX2RldihiZGV2LCBscik7\n"
- "Cj4gKwlpZiAoSVNfRVJSKG5ld19kZXYpKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgcmVnaXN0\n"
- "ZXJpbmcgZGV2aWNlOiBhbGxvY2F0aW9uXG4iLAo+ICsJCSAgICAgICBiZGV2LT5iZF9kaXNrLT5k\n"
- "aXNrX25hbWUpOwo+ICsJCXJldHVybiBQVFJfRVJSKG5ld19kZXYpOwo+ICsJfQo+ICsKPiArCWlm\n"
- "ICghbWVtY3B5KG5ld19kZXYtPmtleV9uYW1lLCBrZXlfY21kLT5rZXksIGtleV9sZW4pKSB7Cj4g\n"
- "KwkJcHJfZXJyKCIlczogRXJyb3IgcmVnaXN0ZXJpbmcga2V5OiBjb3VsZG4ndCBjb3B5IGtleVxu\n"
- "IiwKPiArCQkgICAgICAgbmV3X2Rldi0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gLUVGQVVMVDsK\n"
- "PiArCX0KPiArCj4gKwluZXdfZGV2LT5rZXlfbmFtZV9sZW4gPSBrZXlfbGVuOwo+ICsJbmV3X2Rl\n"
- "di0+a2V5X3R5cGUgPSBrZXlfY21kLT5rZXlfdHlwZTsKPiArCXJldCA9IGdldF9vcGFsX2tleShu\n"
- "ZXdfZGV2KTsKPiArCWlmIChyZXQpIHsKPiArCQlwcl9lcnIoIiVzOiBDb3VsZG4ndCBnZXQga2V5\n"
- "OiAlZFxuIiwgbmV3X2Rldi0+ZGlza19uYW1lLCByZXQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9\n"
- "Cj4gKwo+ICsJbmV3X2Rldi0+ZnVuY3MgPSBmdW5jczsKPiArCj4gKwluZXdfZGV2LT5zdGF0ZSA9\n"
- "IDA7Cj4gKwljb21wbGV0aW9uID0gbmV3X2Rldi0+Y29tcGxldGlvbjsKPiArCW5leHQoMCwgbmV3\n"
- "X2Rldik7Cj4gKwo+ICsJcmV0dXJuIHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24p\n"
- "Owo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IG9wYWxfZGV2ICpnZXRfcmVnaXN0ZXJlZF9vcGFs\n"
- "X2RldihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LAo+ICsJCQkJCQl1OCBscikKPiArewo+ICsJ\n"
- "Y29uc3QgY2hhciAqZGlza25hbWUgPSBiZGV2LT5iZF9kaXNrLT5kaXNrX25hbWU7Cj4gKwlzdHJ1\n"
- "Y3Qgb3BhbF9kZXYgKml0ZXIsICpkZXYgPSBOVUxMOwo+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsK\n"
- "PiArCWJvb2wgaW5fdXNlID0gZmFsc2U7Cj4gKwo+ICsJc3Bpbl9sb2NrX2lycXNhdmUoJmxpc3Rf\n"
- "c3BpbmxvY2ssIGZsYWdzKTsKPiArCWxpc3RfZm9yX2VhY2hfZW50cnkoaXRlciwgJm9wYWxfbGlz\n"
- "dCwgbm9kZSkgewo+ICsJCWlmIChzdHJuY21wKGl0ZXItPmRpc2tfbmFtZSwgZGlza25hbWUsIERJ\n"
- "U0tfTkFNRV9MRU4pKQo+ICsJCQljb250aW51ZTsKPiArCQlpZiAoaXRlci0+bHIgPT0gbHIpIHsK\n"
- "PiArCQkJZGV2ID0gaXRlcjsKPiArCQkJaWYgKCFhdG9taWNfYWRkX3VubGVzcygmaXRlci0+aW5f\n"
- "dXNlLCAxLCAxKSkgewo+ICsJCQkJZGV2ID0gTlVMTDsKPiArCQkJCWluX3VzZSA9IHRydWU7Cj4g\n"
- "KwkJCX0KPiArCQkJYnJlYWs7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCXNwaW5fdW5sb2NrX2lycXJl\n"
- "c3RvcmUoJmxpc3Rfc3BpbmxvY2ssIGZsYWdzKTsKPiArCj4gKwlpZiAoIWRldikKPiArCQlyZXR1\n"
- "cm4gTlVMTDsKPiArCj4gKwlkZXYtPmJkZXYgPSBiZGV2Owo+ICsJcmV0dXJuIGRldjsKPiArfQo+\n"
- "ICsKPiArLyogRnJlZSB1cCB0aGUgT3BhbCBkZXYgYW5kIGl0cyBrZXlzIGR1cmluZyB0d28gc2Nl\n"
- "bmFyaW9zOgo+ICsgKgo+ICsgKiAxKSBXaGVuIGEgY29tbWFuZCBpcyBjb21wbGV0ZSB0aGF0IG5v\n"
- "IGxvbmdlciByZXF1aXJlcwo+ICsgKiAgICB0aGUgb3BhbCBkZXYgdG8gYmUgYXJvdW5kLgo+ICsg\n"
- "KiAyKSBXaGVuIGEgY29tbWFuZCwgaW5jbHVkaW5nIE9wYWwgU2F2ZSBmYWlscyB3ZSBjbGVhbgo+\n"
- "ICsgKiAgICBhbmQgZnJlZSB0aGUgb3BhbCBkZXYuCj4gKyAqCj4gKyAqICAgIElmIHdlIGZpbmQg\n"
- "dGhlIG9wYWwgZGV2IHN0cnVjdHVyZSBpbiB0aGUgbGlzdCBvZgo+ICsgKiAgICBzYXZlZCBwYXNz\n"
- "d29yZHMgd2Ugd2lsbCAqbm90KiByZW1vdmUgaXQuCj4gKyAqLwo+ICtzdGF0aWMgdm9pZCByZW1v\n"
- "dmVfYW5kX2NsZWFuX29wYWxfZGV2KHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwlzdHJ1\n"
- "Y3Qgb3BhbF9kZXYgKml0ZXI7Cj4gKwlib29sIGZvdW5kID0gZmFsc2U7Cj4gKwo+ICsJc3Bpbl9s\n"
- "b2NrKCZsaXN0X3NwaW5sb2NrKTsKPiArCWxpc3RfZm9yX2VhY2hfZW50cnkoaXRlciwgJm9wYWxf\n"
- "bGlzdCwgbm9kZSkgewo+ICsJCWlmIChpdGVyID09IGRldikgewo+ICsJCQlmb3VuZCA9IHRydWU7\n"
- "Cj4gKwkJCWJyZWFrOwo+ICsJCX0KPiArCX0KPiArCj4gKwlzcGluX3VubG9jaygmbGlzdF9zcGlu\n"
- "bG9jayk7Cj4gKwlpZiAoIWZvdW5kKSB7Cj4gKwkJY2xlYW5fb3BhbF9rZXkoZGV2KTsKPiArCQlj\n"
- "bGVhbl9mdW5jdGlvbl9kYXRhKGRldik7Cj4gKwkJa2ZyZWUoZGV2KTsKPiArCX0KPiArfQo+ICsK\n"
- "PiArc3RhdGljIHN0cnVjdCBvcGFsX2RldiAqZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihzdHJ1Y3Qg\n"
- "YmxvY2tfZGV2aWNlICpiZGV2LAo+ICsJCQkJCSAgICAgICB1OCBsciwgYm9vbCB1c2VfbmV3KQo+\n"
- "ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKPiArCj4gKwlpZiAodXNlX25ldykKPiArCQly\n"
- "ZXR1cm4gYWxsb2Nfb3BhbF9kZXYoYmRldiwgbHIpOwo+ICsKPiArCWRldiA9IGdldF9yZWdpc3Rl\n"
- "cmVkX29wYWxfZGV2KGJkZXYsIGxyKTsKPiArCWlmICghZGV2KSB7Cj4gKwkJZGV2ID0gYWxsb2Nf\n"
- "b3BhbF9kZXYoYmRldiwgbHIpOwo+ICsJCWlmICghZGV2KQo+ICsJCQlyZXR1cm4gTlVMTDsKTm8g\n"
- "bmVlZCBmb3IgdGhpcyBjaGVjayB3aGVuIHlvdSBhbHJlYWR5IHJldHVybiBkZXYKCgo+ICsJfQo+\n"
- "ICsJcmV0dXJuIGRldjsKPiArfQpJbnN0ZWFkLCBob3cgYWJvdXQ6CnN0YXRpYyBzdHJ1Y3Qgb3Bh\n"
- "bF9kZXYgKmdldF9vcl9jcmVhdGVfb3BhbF9kZXYoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwK\n"
- "CQkJCQkgICAgICAgdTggbHIsIGJvb2wgdXNlX25ldykKewoJc3RydWN0IG9wYWxfZGV2ICpkZXYg\n"
- "PSBOVUxMOwoKCWlmICghdXNlX25ldykKCQlkZXYgPSBnZXRfcmVnaXN0ZXJlZF9vcGFsX2Rldihi\n"
- "ZGV2LCBscik7CgoJaWYgKCFkZXYpCgkJZGV2ID0gYWxsb2Nfb3BhbF9kZXYoYmRldiwgbHIpOwoK\n"
- "CXJldHVybiBkZXY7Cn0KCgo+ICsKPiArc3RhdGljIHN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKnNl\n"
- "dHVwX29wYWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQkJICAgICAgc3Ry\n"
- "dWN0IG9wYWxfZGV2ICpkZXYsCj4gKwkJCQkJICAgICAgY29uc3Qgb3BhbF9zdGVwICpmdW5jcywK\n"
- "PiArCQkJCQkgICAgICBzdHJ1Y3Qgb3BhbF9rZXkgKmtleSkKPiArewo+ICsJaW50IHJldDsKPiAr\n"
- "Cj4gKwlkZXYtPmJkZXYgPSBiZGV2Owo+ICsJZGV2LT5zdGF0ZSA9IDA7Cj4gKwlkZXYtPmZ1bmNz\n"
- "ID0gZnVuY3M7Cj4gKwlkZXYtPlRTTiA9IDA7Cj4gKwlkZXYtPkhTTiA9IDA7Cj4gKwlkZXYtPmZp\n"
- "bmFsX2NiID0gTlVMTDsKPiArCWRldi0+ZmluYWxfY2JfZGF0YSA9IE5VTEw7Cj4gKwlkZXYtPmxy\n"
- "ID0ga2V5LT5scjsKPiArCWRldi0+ZXJyb3JfY2IgPSBlbmRfb3BhbF9zZXNzaW9uX2Vycm9yOwo+\n"
- "ICsJZGV2LT5lcnJvcl9jYl9kYXRhID0gZGV2Owo+ICsKPiArCWlmIChrZXkpIHsKPiArCQltZW1j\n"
- "cHkoZGV2LT5rZXlfbmFtZSwga2V5LT5rZXksIGtleS0+a2V5X2xlbik7Cj4gKwkJZGV2LT5rZXlf\n"
- "bmFtZV9sZW4gPSBrZXktPmtleV9sZW47Cj4gKwkJZGV2LT5rZXlfdHlwZSA9IGtleS0+a2V5X3R5\n"
- "cGU7Cj4gKwo+ICsJCXJldCA9IGdldF9vcGFsX2tleShkZXYpOwo+ICsJCWlmIChyZXQpIHsKPiAr\n"
- "CQkJa2ZyZWUoZGV2LT5jb21wbGV0aW9uKTsKPiArCQkJcHJfZXJyKCIlczogQ291bGRuJ3QgZ2V0\n"
- "IGtleTogJWRcbiIsCj4gKwkJCSAgICAgICBkZXYtPmRpc2tfbmFtZSwgcmV0KTsKPiArCQkJcmV0\n"
- "dXJuIEVSUl9QVFIocmV0KTsKPiArCQl9Cj4gKwl9Cj4gKwlkZXYtPmZ1bmNfZGF0YSA9IE5VTEw7\n"
- "Cj4gKwlkZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVzID0gMDsKPiArCj4gKwlyZXR1\n"
- "cm4gZGV2LT5jb21wbGV0aW9uOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGludGVybmFsX3NldHVw\n"
- "X2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCSAgICAgc3RydWN0IG9wYWxfdXNl\n"
- "cl9scl9zZXR1cCAqc2V0dXApCj4gK3sKPiArCXN0cnVjdCBvcGFsX2RldiAqZGV2Owo+ICsJc3Ry\n"
- "dWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCXZvaWQgKmRhdGFbM10gPSB7IE5V\n"
- "TEwgfTsKPiArCWNvbnN0IG9wYWxfc3RlcCBscl9mdW5jc1tdID0gewo+ICsJCW9wYWxfZGlzY292\n"
- "ZXJ5MCwKPiArCQlzdGFydF9hdXRoX29wYWxfc2Vzc2lvbiwKPiArCQlzZXR1cF9sb2NraW5nX3Jh\n"
- "bmdlLAo+ICsJCWdldF9hY3RpdmVfa2V5LAo+ICsJCWdlbl9rZXksCj4gKwkJZW5kX29wYWxfc2Vz\n"
- "c2lvbiwKPiArCQlOVUxMLAo+ICsJfTsKPiArCWludCByZXQ7Cj4gKwo+ICsJZGV2ID0gZ2V0X29y\n"
- "X2NyZWF0ZV9vcGFsX2RldihiZGV2LCBzZXR1cC0+a2V5LmxyLCB0cnVlKTsKPiArCWlmICghZGV2\n"
- "KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2Rl\n"
- "dihiZGV2LCBkZXYsIGxyX2Z1bmNzLCAmc2V0dXAtPmtleSk7Cj4gKwlpZiAoSVNfRVJSKGNvbXBs\n"
- "ZXRpb24pKSB7Cj4gKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKPiArCQlnb3RvIGVycm9y\n"
- "X3JldHVybjsKPiArCX0KPiArCj4gKwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7Cj4gKwlkZXYtPm51\n"
- "bV9mdW5jX2RhdGEgPSAzOwo+ICsJZGV2LT5mdW5jX2RhdGFbMV0gPSAmc2V0dXAtPndobzsKPiAr\n"
- "CWRldi0+ZnVuY19kYXRhWzJdID0gc2V0dXA7Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0\n"
- "ID0gd2FpdF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0\n"
- "dXJuOgo+ICsJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsK\n"
- "PiArfQo+ICsKPiAraW50IG9wYWxfcmV2ZXJ0KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0\n"
- "cnVjdCBvcGFsX2tleSAqa2V5KQo+ICt7Cj4gKwljb25zdCBvcGFsX3N0ZXAgcmV2ZXJ0X2Z1bmNz\n"
- "W10gPSB7Cj4gKwkJb3BhbF9kaXNjb3ZlcnkwLAo+ICsJCXN0YXJ0X1NJREFTUF9vcGFsX3Nlc3Np\n"
- "b24sCj4gKwkJcmV2ZXJ0X3RwZXIsIC8qIGNvbnRyb2xsZXIgd2lsbCB0ZXJtaW5hdGUgc2Vzc2lv\n"
- "biAqLwo+ICsJCU5VTEwsCj4gKwl9Owo+ICsKPiArCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYs\n"
- "IGtleSwgcmV2ZXJ0X2Z1bmNzKTsKPiArfQo+ICsKPiAraW50IGFjdGl2YXRlX3VzZXIoc3RydWN0\n"
- "IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IG9wYWxfYWN0aXZhdGVfdXNlciAqYWN0KQo+ICt7\n"
- "Cj4gKwljb25zdCBvcGFsX3N0ZXAgYWN0X2Z1bmNzW10gPSB7Cj4gKwkJb3BhbF9kaXNjb3Zlcnkw\n"
- "LAo+ICsJCXN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24sCj4gKwkJaW50ZXJuYWxfYWN0aXZh\n"
- "dGVfdXNlciwKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCU5VTEwKPiArCX07Cj4gKwlzdHJ1\n"
- "Y3Qgb3BhbF9kZXYgKmRldjsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247\n"
- "Cj4gKwl2b2lkICpkYXRhWzNdID0geyBOVUxMIH07Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWRldiA9\n"
- "IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgYWN0LT5rZXkubHIsIHRydWUpOwo+ICsJaWYg\n"
- "KCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJY29tcGxldGlvbiA9IHNldHVwX29w\n"
- "YWxfZGV2KGJkZXYsIGRldiwgYWN0X2Z1bmNzLCAmYWN0LT5rZXkpOwo+ICsJaWYgKElTX0VSUihj\n"
- "b21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBl\n"
- "cnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKPiArCWRl\n"
- "di0+ZnVuY19kYXRhID0gZGF0YTsKPiArCWRldi0+ZnVuY19kYXRhWzFdID0gYWN0Owo+ICsJZGV2\n"
- "LT5mdW5jX2RhdGFbMl0gPSBhY3Q7Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0ID0gd2Fp\n"
- "dF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0dXJuOgo+\n"
- "ICsJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+\n"
- "ICsKPiAraW50IG9wYWxfc2V0X3B3KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBv\n"
- "cGFsX25ld19wdyAqcHcpCj4gKwo+ICt7Cj4gKwljb25zdCBvcGFsX3N0ZXAgcHdfZnVuY3NbXSA9\n"
- "IHsKPiArCQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCj4g\n"
- "KwkJc2V0X25ld19wdywKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCU5VTEwKPiArCX07Cj4g\n"
- "KwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBs\n"
- "ZXRpb247Cj4gKwl2b2lkICpkYXRhWzNdID0geyBOVUxMIH07Cj4gKwlpbnQgcmV0Owo+ICsKPiAr\n"
- "CWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgcHctPmN1cnJlbnRfcGluLmxyLCB0\n"
- "cnVlKTsKPiArCWlmICghZGV2KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWNvbXBsZXRp\n"
- "b24gPSBzZXR1cF9vcGFsX2RldihiZGV2LCBkZXYsIHB3X2Z1bmNzLCAmcHctPmN1cnJlbnRfcGlu\n"
- "KTsKPiArCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsKPiArCQlyZXQgPSBQVFJfRVJSKGNvbXBs\n"
- "ZXRpb24pOwo+ICsJCWdvdG8gZXJyb3JfcmV0dXJuOwo+ICsJfQo+ICsKPiArCWRldi0+bnVtX2Z1\n"
- "bmNfZGF0YSA9IDM7Cj4gKwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7Cj4gKwlkZXYtPmZ1bmNfZGF0\n"
- "YVsxXSA9ICh2b2lkICopICZwdy0+d2hvOwo+ICsJZGV2LT5mdW5jX2RhdGFbMl0gPSAodm9pZCAq\n"
- "KSBwdzsKPiArCj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxl\n"
- "dGlvbihjb21wbGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVfYW5kX2Ns\n"
- "ZWFuX29wYWxfZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtpbnQgb3BhbF9h\n"
- "Y3RfbHNwX2ludChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgb3BhbF9rZXkgKmtl\n"
- "eSwKPiArCQkgICAgIGNvbnN0IG9wYWxfc3RlcCAqZnVuY3MpCj4gK3sKPiArCXN0cnVjdCBvcGFs\n"
- "X2RldiAqZGV2Owo+ICsJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCWlu\n"
- "dCByZXQ7Cj4gKwo+ICsJZGV2ID0gZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihiZGV2LCBrZXktPmxy\n"
- "LCB0cnVlKTsKPiArCWlmICghZGV2KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsJY29tcGxldGlv\n"
- "biA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwgZnVuY3MsIGtleSk7Cj4gKwlpZiAoSVNfRVJS\n"
- "KGNvbXBsZXRpb24pKSB7Cj4gKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKPiArCQlnb3Rv\n"
- "IGVycm9yX3JldHVybjsKPiArCX0KPiArCj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0\n"
- "X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4g\n"
- "KwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4g\n"
- "Kwo+ICsKPiArc3RhdGljIGludCBvcGFsX3NhdmVfaW50ZXJuYWwoc3RydWN0IGJsb2NrX2Rldmlj\n"
- "ZSAqYmRldiwKPiArCQkJICAgICAgc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrKQo+ICt7Cj4g\n"
- "Kwl2b2lkICpmdW5jX2RhdGFbM10gPSB7IE5VTEwgfTsKPiArCXN0cnVjdCBvcGFsX2RldiAqZGV2\n"
- "Owo+ICsJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCWNvbnN0IG9wYWxf\n"
- "c3RlcCBfYXV0aF9mdW5jc1tdID0gewo+ICsJCW9wYWxfZGlzY292ZXJ5MCwKPiArCQlzdGFydF9h\n"
- "dXRoX29wYWxfc2Vzc2lvbiwKPiArCQlxdWVyeV9sb2NraW5nX3JhbmdlLAo+ICsJCWVuZF9vcGFs\n"
- "X3Nlc3Npb24sCj4gKwkJb3BhbF9yZWdpc3Rlcl9jb250LAo+ICsJCU5VTEwKPiArCX07Cj4gKwlp\n"
- "bnQgcmV0Owo+ICsKPiArCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgbGstPmtl\n"
- "eS5sciwgZmFsc2UpOwo+ICsJaWYgKCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwljb21w\n"
- "bGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBfYXV0aF9mdW5jcywgJmxrLT5rZXkp\n"
- "Owo+ICsJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBUUl9FUlIoY29tcGxl\n"
- "dGlvbik7Cj4gKwkJZ290byBlcnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZGV2LT5udW1fZnVu\n"
- "Y19kYXRhID0gMzsKPiArCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOwo+ICsJZGV2LT5mdW5j\n"
- "X2RhdGFbMV0gPSAmbGstPmF1dGhvcml0eTsKPiArCWRldi0+bGt1bCA9ICpsazsKPiArCj4gKwlu\n"
- "ZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9u\n"
- "KTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRl\n"
- "dik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkZF91c2VyX2xyX2lu\n"
- "dGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQlzdHJ1Y3Qgb3BhbF9sb2Nr\n"
- "X3VubG9jayAqbGspCj4gK3sKPiArCXZvaWQgKmZ1bmNfZGF0YVszXSA9IHsgTlVMTCB9Owo+ICsJ\n"
- "c3RydWN0IG9wYWxfZGV2ICpkZXY7Cj4gKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpjb21wbGV0\n"
- "aW9uOwo+ICsJY29uc3Qgb3BhbF9zdGVwIGZ1bmNzW10gPSB7Cj4gKwkJb3BhbF9kaXNjb3Zlcnkw\n"
- "LAo+ICsJCXN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24sCj4gKwkJYWRkX3VzZXJfdG9fbHIs\n"
- "Cj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlOVUxMCj4gKwl9Owo+ICsJaW50IHJldDsKPiAr\n"
- "Cj4gKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJkZXYsIGxrLT5rZXkubHIsIHRydWUp\n"
- "Owo+ICsJaWYgKCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwljb21wbGV0aW9uID0gc2V0\n"
- "dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBmdW5jcywgJmxrLT5rZXkpOwo+ICsJaWYgKElTX0VSUihj\n"
- "b21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBl\n"
- "cnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKPiArCWRl\n"
- "di0+ZnVuY19kYXRhID0gZnVuY19kYXRhOwo+ICsJZGV2LT5mdW5jX2RhdGFbMl0gPSBsazsKPiAr\n"
- "Cj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21w\n"
- "bGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxf\n"
- "ZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGxvY2tfdW5s\n"
- "b2NrX2ludGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQlzdHJ1Y3Qgb3Bh\n"
- "bF9sb2NrX3VubG9jayAqbGspCj4gK3sKPiArCXZvaWQgKmZ1bmNfZGF0YVszXSA9IHsgTlVMTCB9\n"
- "Owo+ICsJc3RydWN0IG9wYWxfZGV2ICpkZXY7Cj4gKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpj\n"
- "b21wbGV0aW9uOwo+ICsKPiArCWNvbnN0IG9wYWxfc3RlcCB1bGtfZnVuY3NfU1VNW10gPSB7Cj4g\n"
- "KwkJb3BhbF9kaXNjb3ZlcnkwLAo+ICsJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAo+ICsJCWxv\n"
- "Y2tfdW5sb2NrX2xvY2tpbmdfcmFuZ2VfU1VNLAo+ICsJCWVuZF9vcGFsX3Nlc3Npb24sCj4gKwkJ\n"
- "TlVMTAo+ICsJfTsKPiArCWNvbnN0IG9wYWxfc3RlcCBfdW5sb2NrX2Z1bmNzW10gPSB7Cj4gKwkJ\n"
- "b3BhbF9kaXNjb3ZlcnkwLAo+ICsJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAo+ICsJCWxvY2tf\n"
- "dW5sb2NrX2xvY2tpbmdfcmFuZ2UsCj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlOVUxMCj4g\n"
- "Kwl9Owo+ICsJaW50IHJldDsKPiArCj4gKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJk\n"
- "ZXYsIGxrLT5rZXkubHIsIHRydWUpOwo+ICsJaWYgKCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07\n"
- "Cj4gKwo+ICsJaWYgKGxrLT5hdXRob3JpdHkuU1VNKQo+ICsJCWNvbXBsZXRpb24gPSBzZXR1cF9v\n"
- "cGFsX2RldihiZGV2LCBkZXYsIHVsa19mdW5jc19TVU0sICZsay0+a2V5KTsKPiArCWVsc2UKPiAr\n"
- "CQljb21wbGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBfdW5sb2NrX2Z1bmNzLCAm\n"
- "bGstPmtleSk7Cj4gKwo+ICsJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBU\n"
- "Ul9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBlcnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJ\n"
- "ZGV2LT5udW1fZnVuY19kYXRhID0gMzsKPiArCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOwo+\n"
- "ICsJZGV2LT5mdW5jX2RhdGFbMV0gPSAmbGstPmF1dGhvcml0eTsKPiArCWRldi0+ZnVuY19kYXRh\n"
- "WzJdID0gbGs7Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0ID0gd2FpdF9mb3JfY21kX2Nv\n"
- "bXBsZXRpb24oY29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0dXJuOgo+ICsJcmVtb3ZlX2Fu\n"
- "ZF9jbGVhbl9vcGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiAraW50IG9w\n"
- "YWxfZXJhc2VfbG9ja2luZ19yYW5nZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qg\n"
- "c2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKPiArCXN0cnVjdCBv\n"
- "cGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247Cj4gKwlzdHJ1Y3Qgb3BhbF9rZXkgazsKPiArCWlu\n"
- "dCByZXQ7Cj4gKwljb25zdCBvcGFsX3N0ZXAgZXJhc2VfZnVuY3NbXSA9IHsKPiArCQlvcGFsX2Rp\n"
- "c2NvdmVyeTAsCj4gKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxfc2Vzc2lvbiwKPiArCQllcmFzZV9s\n"
- "b2NraW5nX3JhbmdlLAo+ICsJCWVuZF9vcGFsX3Nlc3Npb24sCj4gKwkJTlVMTCwKPiArCX07Cj4g\n"
- "Kwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBz\n"
- "YXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlO\n"
- "VkFMOwo+ICsJfQo+ICsKPiArCWlmIChjb3B5X2Zyb21fdXNlcigmaywga2V5LT5vcGFsLCBzaXpl\n"
- "b2YoKmtleS0+b3BhbCkpKQo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsKPiArCWRldiA9IGdldF9v\n"
- "cl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgay5sciwgdHJ1ZSk7Cj4gKwlpZiAoIWRldikKPiArCQly\n"
- "ZXR1cm4gLUVOT01FTTsKPiArCj4gKwljb21wbGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwg\n"
- "ZGV2LCBlcmFzZV9mdW5jcywgJmspOwo+ICsJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgewo+ICsJ\n"
- "CXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBlcnJvcl9yZXR1cm47Cj4gKwl9\n"
- "Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0ID0gd2FpdF9mb3JfY21kX2NvbXBsZXRpb24o\n"
- "Y29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0dXJuOgo+ICsJcmVtb3ZlX2FuZF9jbGVhbl9v\n"
- "cGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICtFWFBPUlRfU1lNQk9MKG9wYWxf\n"
- "ZXJhc2VfbG9ja2luZ19yYW5nZSk7Cj4gKwo+ICtpbnQgb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFk\n"
- "b3dfbWJyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQkgICBzdHJ1Y3Qgc2VkX2tl\n"
- "eSAqa2V5KQo+ICt7Cj4gKwl2b2lkICpmdW5jX2RhdGFbNl0gPSB7IE5VTEwgfTsKPiArCXN0cnVj\n"
- "dCBvcGFsX21icl9kYXRhIG1icjsKPiArCXN0cnVjdCBvcGFsX2RldiAqZGV2Owo+ICsJc3RydWN0\n"
- "IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCWNvbnN0IG9wYWxfc3RlcCBtYnJfZnVu\n"
- "Y3NbXSA9IHsKPiArCQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxf\n"
- "c2Vzc2lvbiwKPiArCQlzZXRfbWJyX2RvbmUsCj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlz\n"
- "dGFydF9hZG1pbjFMU1Bfb3BhbF9zZXNzaW9uLAo+ICsJCXNldF9tYnJfZW5hYmxlX2Rpc2FibGUs\n"
- "Cj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlOVUxMLAo+ICsJfTsKPiArCWludCByZXQ7Cj4g\n"
- "Kwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBz\n"
- "YXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlO\n"
- "VkFMOwo+ICsJfQo+ICsKPiArCWlmIChjb3B5X2Zyb21fdXNlcigmbWJyLCBrZXktPm9wYWxfbWJy\n"
- "LCBzaXplb2YoKmtleS0+b3BhbF9tYnIpKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlp\n"
- "ZiAobWJyLmVuYWJsZV9kaXNhYmxlICE9IE9QQUxfTUJSX0VOQUJMRSAmJgo+ICsJICAgIG1ici5l\n"
- "bmFibGVfZGlzYWJsZSAhPSBPUEFMX01CUl9ESVNBQkxFKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+\n"
- "ICsKPiArCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgbWJyLmtleS5sciwgdHJ1\n"
- "ZSk7Cj4gKwlpZiAoIWRldikKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwljb21wbGV0aW9u\n"
- "ID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBtYnJfZnVuY3MsICZtYnIua2V5KTsKPiArCWlm\n"
- "IChJU19FUlIoY29tcGxldGlvbikpIHsKPiArCQlyZXQgPSBQVFJfRVJSKGNvbXBsZXRpb24pOwo+\n"
- "ICsJCWdvdG8gZXJyb3JfcmV0dXJuOwo+ICsJfQo+ICsKPiArCWRldi0+bnVtX2Z1bmNfZGF0YSA9\n"
- "IDY7Cj4gKwlkZXYtPmZ1bmNfZGF0YSA9IGZ1bmNfZGF0YTsKPiArCWRldi0+ZnVuY19kYXRhWzJd\n"
- "ID0gJm1ici5lbmFibGVfZGlzYWJsZTsKPiArCWRldi0+ZnVuY19kYXRhWzVdID0gJm1ici5lbmFi\n"
- "bGVfZGlzYWJsZTsKPiArCj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRf\n"
- "Y29tcGxldGlvbihjb21wbGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVf\n"
- "YW5kX2NsZWFuX29wYWxfZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICsKPiArfQo+ICtFWFBP\n"
- "UlRfU1lNQk9MKG9wYWxfZW5hYmxlX2Rpc2FibGVfc2hhZG93X21icik7Cj4gKwo+ICtpbnQgb3Bh\n"
- "bF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4g\n"
- "K3sKPiArCXN0cnVjdCBvcGFsX2xvY2tfdW5sb2NrIGxrdWw7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8\n"
- "ICFiZGV2LT5iZF9kaXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBzYXZlIHBhc3N3b3JkIGZvciBO\n"
- "VUxMIGJsb2NrIGRldmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiAr\n"
- "CWlmIChjb3B5X2Zyb21fdXNlcigmbGt1bCwga2V5LT5vcGFsX2xrX3VubGssIHNpemVvZigqa2V5\n"
- "LT5vcGFsKSkpCj4gKwkJcmV0dXJuIC1FRkFVTFQ7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfc2F2ZV9p\n"
- "bnRlcm5hbChiZGV2LCAmbGt1bCk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX3NhdmUpOwo+\n"
- "ICsKPiAraW50IG9wYWxfYWRkX3VzZXJfdG9fbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg\n"
- "c3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgbGt1\n"
- "bDsKPiArCj4gKwlpZiAoY29weV9mcm9tX3VzZXIoJmxrdWwsIGtleS0+b3BhbF9sa191bmxrLCBz\n"
- "aXplb2YobGt1bCkpKQo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsKPiArCWlmICghYmRldiB8fCAh\n"
- "YmRldi0+YmRfZGlzaykgewo+ICsJCXByX2VycigiQ2FuJ3QgYXNzaWduIHVzZXIgdG8gTFIgd2l0\n"
- "aG91dCBiYWNraW5nIGRpc2tcbiIpOwo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsJfQo+ICsJaWYg\n"
- "KGxrdWwubF9zdGF0ZSAhPSBPUEFMX1JPICYmIGxrdWwubF9zdGF0ZSAhPSBPUEFMX1JXKSB7Cj4g\n"
- "KwkJcHJfZXJyKCJMb2NraW5nIHN0YXRlIHdhcyBub3QgUk8gb3IgUldcbiIpOwo+ICsJCXJldHVy\n"
- "biAtRUlOVkFMOwo+ICsJfQo+ICsJaWYgKGxrdWwuYXV0aG9yaXR5LndobyA8IE9QQUxfVVNFUjEg\n"
- "JiYKPiArCSAgICBsa3VsLmF1dGhvcml0eS53aG8gPiBPUEFMX1VTRVI5KSB7Cj4gKwkJcHJfZXJy\n"
- "KCJBdXRob3JpdHkgd2FzIG5vdCB3aXRoaW4gdGhlIHJhbmdlIG9mIHVzZXJzOiAlZFxuIiwKPiAr\n"
- "CQkgICAgICAgbGt1bC5hdXRob3JpdHkud2hvKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0K\n"
- "PiArCWlmIChsa3VsLmF1dGhvcml0eS5TVU0pIHsKPiArCQlwcl9lcnIoIiVzIG5vdCBzdXBwb3J0\n"
- "ZWQgaW4gU1VNLiBVc2Ugc2V0dXAgbG9ja2luZyByYW5nZVxuIiwKPiArCQkgICAgICAgX19mdW5j\n"
- "X18pOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXJldHVybiBhZGRfdXNlcl9s\n"
- "cl9pbnRlcm5hbChiZGV2LCAmbGt1bCk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX2FkZF91\n"
- "c2VyX3RvX2xyKTsKPiArCj4gK2ludCBvcGFsX3JldmVydHRwZXIoc3RydWN0IGJsb2NrX2Rldmlj\n"
- "ZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsJc3RydWN0IG9wYWxfa2V5IGs7\n"
- "Cj4gKwo+ICsJaWYgKGNvcHlfZnJvbV91c2VyKCZrLCBrZXktPm9wYWwsIHNpemVvZigqa2V5LT5v\n"
- "cGFsKSkpCj4gKwkJcmV0dXJuIC1FRkFVTFQ7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfcmV2ZXJ0KGJk\n"
- "ZXYsICZrKTsKPiArfQo+ICtFWFBPUlRfU1lNQk9MKG9wYWxfcmV2ZXJ0dHBlcik7Cj4gKwo+ICtp\n"
- "bnQgb3BhbF9sb2NrX3VubG9jayhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk\n"
- "X2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayBrOwo+ICsKPiArCWlm\n"
- "IChjb3B5X2Zyb21fdXNlcigmaywga2V5LT5vcGFsX2xrX3VubGssIHNpemVvZigqa2V5LT5vcGFs\n"
- "X2xrX3VubGspKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlpZiAoay5hdXRob3JpdHku\n"
- "d2hvIDwgT1BBTF9BRE1JTjEgfHwgay5hdXRob3JpdHkud2hvID49IE9QQUxfVVNFUjkpClNob3Vs\n"
- "ZCB0aGlzIGJlID4gT1BBTF9VU0VSOSA/CgoKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwly\n"
- "ZXR1cm4gbG9ja191bmxvY2tfaW50ZXJuYWwoYmRldiwgJmspOwo+ICt9Cj4gK0VYUE9SVF9TWU1C\n"
- "T0wob3BhbF9sb2NrX3VubG9jayk7Cj4gKwo+ICtpbnQgb3BhbF90YWtlX293bmVyc2hpcChzdHJ1\n"
- "Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1\n"
- "Y3Qgb3BhbF9rZXkgazsKPiArCWNvbnN0IG9wYWxfc3RlcCBvd25lcl9mdW5jc1tdID0gewo+ICsJ\n"
- "CW9wYWxfZGlzY292ZXJ5MCwKPiArCQlzdGFydF9hbnlib2R5QVNQX29wYWxfc2Vzc2lvbiwKPiAr\n"
- "CQlnZXRfbXNpZF9jcGluX3BpbiwKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCXN0YXJ0X1NJ\n"
- "REFTUF9vcGFsX3Nlc3Npb24sCj4gKwkJc2V0X3NpZF9jcGluX3BpbiwKPiArCQllbmRfb3BhbF9z\n"
- "ZXNzaW9uLAo+ICsJCU5VTEwKPiArCX07Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9k\n"
- "aXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBzYXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRl\n"
- "dmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWlmIChjb3B5X2Zy\n"
- "b21fdXNlcigmaywga2V5LT5vcGFsLCBzaXplb2YoKmtleS0+b3BhbCkpKQo+ICsJCXJldHVybiAt\n"
- "RUZBVUxUOwo+ICsKPiArCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYsICZrLCBvd25lcl9mdW5j\n"
- "cyk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX3Rha2Vfb3duZXJzaGlwKTsKPiArCj4gK2lu\n"
- "dCBvcGFsX2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk\n"
- "X2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9rZXkgazsKPiArCWNvbnN0IG9wYWxfc3Rl\n"
- "cCBhY3RpdmVfZnVuY3NbXSA9IHsKPiArCQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfU0lE\n"
- "QVNQX29wYWxfc2Vzc2lvbiwgLyogT3BlbiBzZXNzaW9uIGFzIFNJRCBhdXRoICovCj4gKwkJZ2V0\n"
- "X2xzcF9saWZlY3ljbGUsCj4gKwkJYWN0aXZhdGVfbHNwLAo+ICsJCWVuZF9vcGFsX3Nlc3Npb24s\n"
- "Cj4gKwkJTlVMTAo+ICsJfTsKPiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2spIHsK\n"
- "PiArCQlwcl9lcnIoIkNhbid0IHNhdmUgcGFzc3dvcmQgZm9yIE5VTEwgYmxvY2sgZGV2aWNlLlxu\n"
- "Iik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJaWYgKGNvcHlfZnJvbV91c2Vy\n"
- "KCZrLCBrZXktPm9wYWwsIHNpemVvZigqa2V5LT5vcGFsKSkpCj4gKwkJcmV0dXJuIC1FRkFVTFQ7\n"
- "Cj4gKwo+ICsJcmV0dXJuIG9wYWxfYWN0X2xzcF9pbnQoYmRldiwgJmssIGFjdGl2ZV9mdW5jcyk7\n"
- "Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX2FjdGl2YXRlX2xzcCk7Cj4gKwo+ICtpbnQgb3Bh\n"
- "bF9zZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBz\n"
- "ZWRfa2V5ICpwdykKPiArewo+ICsJc3RydWN0IG9wYWxfdXNlcl9scl9zZXR1cCBrOwo+ICsKPiAr\n"
- "CWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzaykgewo+ICsJCXByX2VycigiQ2FuJ3Qgc2F2ZSBw\n"
- "YXNzd29yZCBmb3IgTlVMTCBibG9jayBkZXZpY2UuXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsK\n"
- "PiArCX0KPiArCj4gKwlpZiAoY29weV9mcm9tX3VzZXIoJmssIHB3LT5vcGFsX2xycywgc2l6ZW9m\n"
- "KCpwdy0+b3BhbF9scnMpKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlyZXR1cm4gaW50\n"
- "ZXJuYWxfc2V0dXBfbHIoYmRldiwgJmspOwo+ICt9Cj4gKwo+ICtpbnQgb3BhbF9zZXRfbmV3X3B3\n"
- "KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICpwdykKPiArewo+ICsJ\n"
- "c3RydWN0IG9wYWxfbmV3X3B3IGs7Cj4gKwo+ICsJaWYgKHB3LT5zZWRfdHlwZSAhPSBPUEFMX1BX\n"
- "KQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWlmIChjb3B5X2Zyb21fdXNlcigmaywgcHct\n"
- "Pm9wYWxfcHcsIHNpemVvZigqcHctPm9wYWxfcHcpKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiAr\n"
- "Cj4gKwlpZiAoay53aG8ud2hvIDwgT1BBTF9BRE1JTjEgfHwgay53aG8ud2hvID4gT1BBTF9VU0VS\n"
- "OSkKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlyZXR1cm4gb3BhbF9zZXRfcHcoYmRldiwg\n"
- "JmspOwo+ICt9Cj4gK0VYUE9SVF9TWU1CT0wob3BhbF9zZXRfbmV3X3B3KTsKPiArCj4gK2ludCBv\n"
- "cGFsX2FjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9r\n"
- "ZXkgKnB3KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9hY3RpdmF0ZV91c2VyIGs7Cj4gKwo+ICsJaWYg\n"
- "KHB3LT5zZWRfdHlwZSAhPSBPUEFMX0FDVF9VU1IpIHsKPiArCQlwcl9lcnIoIlNlZCB0eXBlIHdh\n"
- "cyBub3QgYWN0IHVzZXJcbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWlm\n"
- "IChjb3B5X2Zyb21fdXNlcigmaywgcHctPm9wYWxfYWN0LCBzaXplb2YoKnB3LT5vcGFsX2FjdCkp\n"
- "KSB7Cj4gKwkJcHJfZXJyKCJjb3B5IGZyb20gdXNlciBlcnJvclxuIik7Cj4gKwkJcmV0dXJuIC1F\n"
- "RkFVTFQ7Cj4gKwl9Cj4gKwo+ICsJLyogV2UgY2FuJ3QgYWN0aXZhdGUgQWRtaW4xIGl0J3MgYWN0\n"
- "aXZlIGFzIG1hbnVmYWN0dXJlZCAqLwo+ICsJaWYgKGsud2hvLndobyA8IE9QQUxfVVNFUjEgJiYg\n"
- "ay53aG8ud2hvID4gT1BBTF9VU0VSOSkgewo+ICsJCXByX2VycigiV2hvIHdhcyBub3QgYSB2YWxp\n"
- "ZCB1c2VyOiAlZCBcbiIsIGsud2hvLndobyk7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4g\n"
- "Kwo+ICsJcmV0dXJuIGFjdGl2YXRlX3VzZXIoYmRldiwgJmspOwo+ICsKPiArfQo+ICtFWFBPUlRf\n"
- "U1lNQk9MKG9wYWxfYWN0aXZhdGVfdXNlcik7Cj4gKwo+ICtpbnQgb3BhbF91bmxvY2tfZnJvbV9z\n"
- "dXNwZW5kKHN0cnVjdCBvcGFsX3N1c3BlbmRfdW5sayAqZGF0YSkKPiArewo+ICsJY29uc3QgY2hh\n"
- "ciAqZGlza25hbWUgPSBkYXRhLT5uYW1lOwo+ICsJc3RydWN0IG9wYWxfZGV2ICppdGVyLCAqZGV2\n"
- "ID0gTlVMTDsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247Cj4gKwl2b2lk\n"
- "ICpmdW5jX2RhdGFbM10gPSB7IE5VTEwgfTsKPiArCWNvbnN0IG9wYWxfc3RlcCBfdW5sb2NrX2Z1\n"
- "bmNzX1NVTVtdID0gewo+ICsJCW9wYWxfZGlzY292ZXJ5MCwKPiArCQlzdGFydF9hdXRoX29wYWxf\n"
- "c2Vzc2lvbiwKPiArCQlsb2NrX3VubG9ja19sb2NraW5nX3JhbmdlLApEaWQgeW91IG1lYW4gdG8g\n"
- "dXNlIGxvY2tfdW5sb2NrX2xvY2tpbmdfcmFuZ2VfU1VNID8KQ2FuIHdlIHB1bGwgdGhlc2UgdHdv\n"
- "IGFycmF5cyBvdXQgc2luY2UgdGhleSBhcmUgcmVxdWlyZWQgZm9yIGJvdGggdGhpcwpmdW5jdGlv\n"
- "biBhbmQgbG9ja191bmxvY2tfaW50ZXJuYWwgPwoKCj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiAr\n"
- "CQlOVUxMCj4gKwl9Owo+ICsJY29uc3Qgb3BhbF9zdGVwIF91bmxvY2tfZnVuY3NbXSA9IHsKPiAr\n"
- "CQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCj4gKwkJbG9j\n"
- "a191bmxvY2tfbG9ja2luZ19yYW5nZSwKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCU5VTEwK\n"
- "PiArCX07Cj4gKwo+ICsKPiArCXNwaW5fbG9jaygmbGlzdF9zcGlubG9jayk7Cj4gKwlsaXN0X2Zv\n"
- "cl9lYWNoX2VudHJ5KGl0ZXIsICZvcGFsX2xpc3QsIG5vZGUpIHsKPiArCQlpZiAoc3RybmNtcChp\n"
- "dGVyLT5kaXNrX25hbWUsIGRpc2tuYW1lLCBESVNLX05BTUVfTEVOKSkgewo+ICsJCQlwcl9lcnIo\n"
- "Iml0ZXJkaXNrIHdhcyAlcyBhbmQgZGlza25hbWUgaXMgJXNcbiIsCj4gKwkJCSAgICAgICBpdGVy\n"
- "LT5kaXNrX25hbWUsIGRpc2tuYW1lKTsKPiArCQkJY29udGludWU7Cj4gKwkJfQo+ICsJCWlmIChh\n"
- "dG9taWNfYWRkX3VubGVzcygmaXRlci0+aW5fdXNlLCAxLCAxKSkgewo+ICsJCQlkZXYgPSBpdGVy\n"
- "Owo+ICsJCQlkZXYtPmZ1bmNfZGF0YSA9IGZ1bmNfZGF0YTsKPiArCQkJZGV2LT5yZXN1bWVfZnJv\n"
- "bV9zdXNwZW5kID0gdHJ1ZTsKPiArCQkJZGV2LT5yZXN1bWVfZGF0YSA9IGRhdGE7Cj4gKwkJCWRl\n"
- "di0+ZmluYWxfY2IgPSB1bmxvY2tfc3VzcGVuZF9maW5hbDsKPiArCQkJZGV2LT5maW5hbF9jYl9k\n"
- "YXRhID0gZGV2Owo+ICsJCQlkZXYtPmVycm9yX2NiID0gZW5kX29wYWxfc2Vzc2lvbl9lcnJvcjsK\n"
- "PiArCQkJZGV2LT5lcnJvcl9jYl9kYXRhID0gZGV2Owo+ICsJCQlkZXYtPnN0YXRlID0gMDsKPiAr\n"
- "CQkJaWYgKGRldi0+bGt1bC5hdXRob3JpdHkuU1VNKQo+ICsJCQkJZGV2LT5mdW5jcyA9IF91bmxv\n"
- "Y2tfZnVuY3NfU1VNOwo+ICsJCQllbHNlCj4gKwkJCQlkZXYtPmZ1bmNzID0gX3VubG9ja19mdW5j\n"
- "czsKPiArCQkJZGV2LT5UU04gPSAwOwo+ICsJCQlkZXYtPkhTTiA9IDA7Cj4gKwkJCWRldi0+ZnVu\n"
- "Y19kYXRhWzJdID0gJmRldi0+bGt1bDsKPiArCQkJZGV2LT5mdW5jX2RhdGFbMV0gPSAmZGV2LT5s\n"
- "a3VsLmF1dGhvcml0eTsKPiArCQkJY29tcGxldGlvbiA9IGRldi0+Y29tcGxldGlvbjsKPiArCQkJ\n"
- "bmV4dCgwLCBkZXYpOwo+ICsJCQl3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsK\n"
- "PiArCQl9Cj4gKwl9Cj4gKwlzcGluX3VubG9jaygmbGlzdF9zcGlubG9jayk7Cj4gKwo+ICsJaWYg\n"
- "KCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICtFWFBPUlRf\n"
- "U1lNQk9MKG9wYWxfdW5sb2NrX2Zyb21fc3VzcGVuZCk7Cj4gZGlmZiAtLWdpdCBhL2xpYi9zZWQt\n"
- "b3BhbF9pbnRlcm5hbC5oIGIvbGliL3NlZC1vcGFsX2ludGVybmFsLmgKPiBuZXcgZmlsZSBtb2Rl\n"
- "IDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLmM5ZDM4ODMKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIv\n"
- "bGliL3NlZC1vcGFsX2ludGVybmFsLmgKPiBAQCAtMCwwICsxLDU4NiBAQAo+ICsvKgo+ICsgKiBD\n"
- "b3B5cmlnaHQgwqkgMjAxNiBJbnRlbCBDb3Jwb3JhdGlvbgo+ICsgKgo+ICsgKiBQZXJtaXNzaW9u\n"
- "IGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5p\n"
- "bmcgYQo+ICsgKiBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRh\n"
- "dGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLAo+ICsgKiB0byBkZWFsIGluIHRoZSBTb2Z0d2Fy\n"
- "ZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uCj4gKyAq\n"
- "IHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmli\n"
- "dXRlLCBzdWJsaWNlbnNlLAo+ICsgKiBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJl\n"
- "LCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUKPiArICogU29mdHdhcmUgaXMgZnVy\n"
- "bmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKPiAr\n"
- "ICoKPiArICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBu\n"
- "b3RpY2UgKGluY2x1ZGluZyB0aGUgbmV4dAo+ICsgKiBwYXJhZ3JhcGgpIHNoYWxsIGJlIGluY2x1\n"
- "ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlCj4gKyAqIFNv\n"
- "ZnR3YXJlLgo+ICsgKgo+ICsgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lU\n"
- "SE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgo+ICsgKiBJTVBMSUVELCBJTkNM\n"
- "VURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElU\n"
- "WSwKPiArICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdF\n"
- "TUVOVC4gIElOIE5PIEVWRU5UIFNIQUxMCj4gKyAqIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBI\n"
- "T0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCj4gKyAqIExJ\n"
- "QUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJX\n"
- "SVNFLCBBUklTSU5HCj4gKyAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhF\n"
- "IFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MKPiArICogSU4gVEhFIFNPRlRX\n"
- "QVJFLgo+ICsgKgo+ICsgKiBBdXRob3I6Cj4gKyAqICAgIFJhZmFlbCBBbnRvZ25vbGxpIDxyYWZh\n"
- "ZWwuYW50b2dub2xsaUBpbnRlbC5jb20+Cj4gKyAqICAgIFNjb3R0ICBCYXVlciAgICAgIDxzY290\n"
- "dC5iYXVlckBpbnRlbC5jb20+Cj4gKyAqLwo+ICsKPiArI2lmbmRlZiBfTlZNRV9PUEFMX0lOVEVS\n"
- "TkFMX0gKPiArI2RlZmluZSBfTlZNRV9PUEFMX0lOVEVSTkFMX0gKPiArCj4gKyNpbmNsdWRlIDxs\n"
- "aW51eC9rZXktdHlwZS5oPgo+ICsjaW5jbHVkZSA8a2V5cy91c2VyLXR5cGUuaD4KPiArCj4gKyNk\n"
- "ZWZpbmUgRFRBRVJST1JfTk9fTUVUSE9EX1NUQVRVUyAweDg5Cj4gKwo+ICtzdGF0aWMgY29uc3Qg\n"
- "Y2hhciAqb3BhbF9lcnJvcnNbMTldID0gewpSZW1vdmUgdGhlIDE5IHNvIGl0J3MganVzdCBvcGFs\n"
- "X2Vycm9yc1tdIChkb2VzbnQgc2lsZW50bHkgdHJ1bmNhdGUgYW55Cm5ldyBhZGRpdGlvbnMpCgoK\n"
- "PiArCSJTdWNjZXNzIiwKPiArCSJOb3QgQXV0aG9yaXplZCIsCj4gKwkiVW5rbm93biBFcnJvciIs\n"
- "Cj4gKwkiU1AgQnVzeSIsCj4gKwkiU1AgRmFpbGVkIiwKPiArCSJTUCBEaXNhYmxlZCIsCj4gKwki\n"
- "U1AgRnJvemVuIiwKPiArCSJObyBTZXNzaW9ucyBBdmFpbGFibGUiLAo+ICsJIlVuaXF1ZW5lc3Mg\n"
- "Q29uZmxpY3QiLAo+ICsJIkluc3VmZmljaWVudCBTcGFjZSIsCj4gKwkiSW5zdWZmaWNpZW50IFJv\n"
- "d3MiLAo+ICsJIkludmFsaWQgRnVuY3Rpb24iLAo+ICsJIkludmFsaWQgUGFyYW1ldGVyIiwKPiAr\n"
- "CSJJbnZhbGlkIFJlZmVyZW5jZSIsCj4gKwkiVW5rbm93biBFcnJvciIsCj4gKwkiVFBFUiBNYWxm\n"
- "dW5jdGlvbiIsCj4gKwkiVHJhbnNhY3Rpb24gRmFpbHVyZSIsCj4gKwkiUmVzcG9uc2UgT3ZlcmZs\n"
- "b3ciLAo+ICsJIkF1dGhvcml0eSBMb2NrZWQgT3V0IiwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25z\n"
- "dCBjaGFyICpvcGFsX2Vycm9yX3RvX2h1bWFuKGludCBlcnJvcikKPiArewo+ICsJaWYgKGVycm9y\n"
- "ID09IDB4M2YpCj4gKwkJcmV0dXJuICJGYWlsZWQiOwo+ICsKPiArCWlmIChlcnJvciA+PSBzaXpl\n"
- "b2Yob3BhbF9lcnJvcnMpIHx8IGVycm9yIDwgMCkKWW91IHdhbnQgc2l6ZW9mKG9wYWxfZXJyb3Jz\n"
- "KS9zaXplb2YoKm9wYWxfZXJyb3JzKSBoZXJlLCBidXQgeW91IGNhbiBqdXN0CnVzZSB0aGUgQVJS\n"
- "QVlfU0laRSBtYWNybyBpbnN0ZWFkCgoKPiArCQlyZXR1cm4gIlVua25vd24gRXJyb3IiOwo+ICsK\n"
- "PiArCXJldHVybiBvcGFsX2Vycm9yc1tlcnJvcl07Cj4gK30KPiArCj4gKy8qIFVzZXIgSURzIHVz\n"
- "ZWQgaW4gdGhlIFRDRyBzdG9yYWdlIFNTQ3MgKi8KPiArc3RhdGljIGNvbnN0IHU4IE9QQUxVSURb\n"
- "XVs4XSA9IHsKPiArCS8qIHVzZXJzICovCj4gKwo+ICsJLyogc2Vzc2lvbiBtYW5hZ2VtZW50ICAq\n"
- "Lwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweGZmfSwK\n"
- "PiArCS8qIHNwZWNpYWwgInRoaXNTUCIgc3ludGF4ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAs\n"
- "IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEgfSwKPiArCS8qIEFkbWluaXN0cmF0aXZlIFNQ\n"
- "ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDIsIDB4MDUsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEg\n"
- "fSwKPiArCS8qIExvY2tpbmcgU1AgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMiwgMHgwNSwgMHgw\n"
- "MCwgMHgwMCwgMHgwMCwgMHgwMiB9LAo+ICsJLyogRU5URVJQUklTRSBMb2NraW5nIFNQICAqLwo+\n"
- "ICsJeyAweDAwLCAweDAwLCAweDAyLCAweDA1LCAweDAwLCAweDAxLCAweDAwLCAweDAxIH0sCj4g\n"
- "KwkvKiBhbnlib2R5ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDAs\n"
- "IDB4MDAsIDB4MDEgfSwKPiArCS8qIFNJRCAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA5\n"
- "LCAweDAwLCAweDAwLCAweDAwLCAweDA2IH0sCj4gKwkvKiBBRE1JTjEgKi8KPiArCXsgMHgwMCwg\n"
- "MHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMSwgMHgwMCwgMHgwMSB9LAo+ICsJLyogVVNFUjEg\n"
- "Ki8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMywgMHgwMCwgMHgwMSB9\n"
- "LAo+ICsJLyogVVNFUjIgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgw\n"
- "MywgMHgwMCwgMHgwMiB9LAo+ICsJLyogUFNJRCB1c2VyICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4\n"
- "MDAsIDB4MDksIDB4MDAsIDB4MDEsIDB4ZmYsIDB4MDEgfSwKPiArCS8qIEJhbmRNYXN0ZXIgMCAq\n"
- "Lwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAwLCAweDgwLCAweDAxIH0s\n"
- "Cj4gKwkgLyogRXJhc2VNYXN0ZXIgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgw\n"
- "MCwgMHgwMCwgMHg4NCwgMHgwMSB9LAo+ICsKPiArCS8qIHRhYmxlcyAqLwo+ICsKPiArCS8qIExv\n"
- "Y2tpbmdfR2xvYmFsUmFuZ2UgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwOCwgMHgwMiwgMHgwMCwg\n"
- "MHgwMCwgMHgwMCwgMHgwMSB9LAo+ICsJLyogQUNFX0xvY2tpbmdfUmFuZ2VfU2V0X1JkTG9ja2Vk\n"
- "IFVJRCAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA4LCAweDAwLCAweDAzLCAweEUwLCAw\n"
- "eDAxIH0sCj4gKwkvKiBBQ0VfTG9ja2luZ19SYW5nZV9TZXRfV3JMb2NrZWQgVUlEICovCj4gKwl7\n"
- "IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDgsIDB4MDAsIDB4MDMsIDB4RTgsIDB4MDEgfSwKPiArCS8q\n"
- "IE1CUiBDb250cm9sICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDgsIDB4MDMsIDB4MDAsIDB4MDAs\n"
- "IDB4MDAsIDB4MDEgfSwKPiArCS8qIFNoYWRvdyBNQlIgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgw\n"
- "OCwgMHgwNCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCB9LAo+ICsJLyogQVVUSE9SSVRZX1RBQkxF\n"
- "ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDB9\n"
- "LAo+ICsJLyogQ19QSU5fVEFCTEUgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwQiwgMHgw\n"
- "MCwgMHgwMCwgMHgwMCwgMHgwMH0sCj4gKwkvKiBPUEFMIExvY2tpbmcgSW5mbyAqLwo+ICsJeyAw\n"
- "eDAwLCAweDAwLCAweDA4LCAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAxIH0sCj4gKwkvKiBF\n"
- "bnRlcnByaXNlIExvY2tpbmcgSW5mbyAqLwo+ICsJeyAweDAwLCAweDAwLCAweDA4LCAweDAxLCAw\n"
- "eDAwLCAweDAwLCAweDAwLCAweDAwIH0sCj4gKwo+ICsJLyogQ19QSU5fVEFCTEUgb2JqZWN0IElE\n"
- "J3MgKi8KPiArCj4gKwkvKiBDX1BJTl9NU0lEICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4\n"
- "MEIsIDB4MDAsIDB4MDAsIDB4ODQsIDB4MDJ9LAo+ICsJLyogQ19QSU5fU0lEICovCj4gKwl7IDB4\n"
- "MDAsIDB4MDAsIDB4MDAsIDB4MEIsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDF9LAo+ICsJIC8qIENf\n"
- "UElOX0FETUlOMSAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDBCLCAweDAwLCAweDAxLCAw\n"
- "eDAwLCAweDAxfSwKPiArCj4gKwkvKiBoYWxmIFVJRCdzIChvbmx5IGZpcnN0IDQgYnl0ZXMgdXNl\n"
- "ZCkgKi8KPiArCj4gKwkvKiBIYWxmLVVJRCDigJMgQXV0aG9yaXR5X29iamVjdF9yZWYgKi8KPiAr\n"
- "CXsgMHgwMCwgMHgwMCwgMHgwQywgMHgwNSwgMHhmZiwgMHhmZiwgMHhmZiwgMHhmZiB9LAo+ICsJ\n"
- "LyogSGFsZi1VSUQg4oCTIEJvb2xlYW4gQUNFICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDQsIDB4\n"
- "MEUsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYgfSwKPiArCj4gKwkvKiBzcGVjaWFsIHZhbHVlIGZv\n"
- "ciBvbWl0dGVkIG9wdGlvbmFsIHBhcmFtZXRlciAqLwo+ICsKPiArCS8qIEhFWEZGIGZvciBvbWl0\n"
- "dGVkICovCj4gKwl7IDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4\n"
- "ZmZ9LAo+ICt9Owo+ICtzdGF0aWMgY29uc3Qgc2l6ZV90IE9QQUxfVUlEX0xFTkdUSCA9IDg7Cj4g\n"
- "K3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9NU0lEX0tFWUxFTiA9IDE1Owo+ICtzdGF0aWMgY29u\n"
- "c3Qgc2l6ZV90IE9QQUxfVUlEX0xFTkdUSF9IQUxGID0gNDsKPiArCj4gKwo+ICsvKiBFbnVtIHRv\n"
- "IGluZGV4IE9QQUxVSUQgYXJyYXkgKi8KPiArZW51bSBPUEFMX1VJRCB7Cj4gKwkvKiB1c2VycyAq\n"
- "Lwo+ICsJT1BBTF9TTVVJRF9VSUQsCj4gKwlPUEFMX1RISVNTUF9VSUQsCj4gKwlPUEFMX0FETUlO\n"
- "U1BfVUlELAo+ICsJT1BBTF9MT0NLSU5HU1BfVUlELAo+ICsJT1BBTF9FTlRFUlBSSVNFX0xPQ0tJ\n"
- "TkdTUF9VSUQsCj4gKwlPUEFMX0FOWUJPRFlfVUlELAo+ICsJT1BBTF9TSURfVUlELAo+ICsJT1BB\n"
- "TF9BRE1JTjFfVUlELAo+ICsJT1BBTF9VU0VSMV9VSUQsCj4gKwlPUEFMX1VTRVIyX1VJRCwKPiAr\n"
- "CU9QQUxfUFNJRF9VSUQsCj4gKwlPUEFMX0VOVEVSUFJJU0VfQkFORE1BU1RFUjBfVUlELAo+ICsJ\n"
- "T1BBTF9FTlRFUlBSSVNFX0VSQVNFTUFTVEVSX1VJRCwKPiArCS8qIHRhYmxlcyAqLwo+ICsJT1BB\n"
- "TF9MT0NLSU5HUkFOR0VfR0xPQkFMLAo+ICsJT1BBTF9MT0NLSU5HUkFOR0VfQUNFX1JETE9DS0VE\n"
- "LAo+ICsJT1BBTF9MT0NLSU5HUkFOR0VfQUNFX1dSTE9DS0VELAo+ICsJT1BBTF9NQlJDT05UUk9M\n"
- "LAo+ICsJT1BBTF9NQlIsCj4gKwlPUEFMX0FVVEhPUklUWV9UQUJMRSwKPiArCU9QQUxfQ19QSU5f\n"
- "VEFCTEUsCj4gKwlPUEFMX0xPQ0tJTkdfSU5GT19UQUJMRSwKPiArCU9QQUxfRU5URVJQUklTRV9M\n"
- "T0NLSU5HX0lORk9fVEFCTEUsCj4gKwkvKiBDX1BJTl9UQUJMRSBvYmplY3QgSUQncyAqLwo+ICsJ\n"
- "T1BBTF9DX1BJTl9NU0lELAo+ICsJT1BBTF9DX1BJTl9TSUQsCj4gKwlPUEFMX0NfUElOX0FETUlO\n"
- "MSwKPiArCS8qIGhhbGYgVUlEJ3MgKG9ubHkgZmlyc3QgNCBieXRlcyB1c2VkKSAqLwo+ICsJT1BB\n"
- "TF9IQUxGX1VJRF9BVVRIT1JJVFlfT0JKX1JFRiwKPiArCU9QQUxfSEFMRl9VSURfQk9PTEVBTl9B\n"
- "Q0UsCj4gKwkvKiBvbWl0dGVkIG9wdGlvbmFsIHBhcmFtZXRlciAqLwo+ICsJT1BBTF9VSURfSEVY\n"
- "RkYsCj4gK307Cj4gKwo+ICsvKgo+ICsgKiBUQ0cgU3RvcmFnZSBTU0MgTWV0aG9kcy4KPiArICov\n"
- "Cj4gK3N0YXRpYyBjb25zdCB1OCBPUEFMTUVUSE9EW11bOF0gPSB7Cj4gKwkvKiBQcm9wZXJ0aWVz\n"
- "ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4ZmYsIDB4MDEg\n"
- "fSwKPiArCS8qIFNUQVJUU0VTU0lPTiAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw\n"
- "eDAwLCAweDAwLCAweGZmLCAweDAyIH0sCj4gKwkvKiBSZXZlcnQgKi8KPiArCXsgMHgwMCwgMHgw\n"
- "MCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMiwgMHgwMiB9LAo+ICsJLyogQWN0aXZhdGUg\n"
- "Ki8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMiwgMHgwMyB9\n"
- "LAo+ICsJLyogRW50ZXJwcmlzZSBHZXQgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwg\n"
- "MHgwMCwgMHgwMCwgMHgwMCwgMHgwNiB9LAo+ICsJLyogRW50ZXJwcmlzZSBTZXQgKi8KPiArCXsg\n"
- "MHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNyB9LAo+ICsJLyog\n"
- "TkVYVCAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAw\n"
- "eDA4IH0sCj4gKwkvKiBFbnRlcnByaXNlIEF1dGhlbnRpY2F0ZSAqLwo+ICsJeyAweDAwLCAweDAw\n"
- "LCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDBjIH0sCj4gKwkvKiBHZXRBQ0wgKi8K\n"
- "PiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwZCB9LAo+\n"
- "ICsJLyogR2VuS2V5ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAs\n"
- "IDB4MDAsIDB4MTAgfSwKPiArCS8qIHJldmVydFNQICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAs\n"
- "IDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MTEgfSwKPiArCS8qIEdldCAqLwo+ICsJeyAweDAw\n"
- "LCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDE2IH0sCj4gKwkvKiBTZXQg\n"
- "Ki8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgxNyB9\n"
- "LAo+ICsJLyogQXV0aGVudGljYXRlICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4\n"
- "MDAsIDB4MDAsIDB4MDAsIDB4MWMgfSwKPiArCS8qIFJhbmRvbSAqLwo+ICsJeyAweDAwLCAweDAw\n"
- "LCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDA2LCAweDAxIH0sCj4gKwkvKiBFcmFzZSAqLwo+\n"
- "ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDA4LCAweDAzIH0sCj4g\n"
- "K307Cj4gK3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9NRVRIT0RfTEVOR1RIID0gODsKPiArCj4g\n"
- "Ky8qIEVudW0gZm9yIGluZGV4aW5nIHRoZSBPUEFMTUVUSE9EIGFycmF5ICovCj4gK2VudW0gT1BB\n"
- "TF9NRVRIT0Qgewo+ICsJT1BBTF9QUk9QRVJUSUVTLAo+ICsJT1BBTF9TVEFSVFNFU1NJT04sCj4g\n"
- "KwlPUEFMX1JFVkVSVCwKPiArCU9QQUxfQUNUSVZBVEUsCj4gKwlPUEFMX0VHRVQsCj4gKwlPUEFM\n"
- "X0VTRVQsCj4gKwlPUEFMX05FWFQsCj4gKwlPUEFMX0VBVVRIRU5USUNBVEUsCj4gKwlPUEFMX0dF\n"
- "VEFDTCwKPiArCU9QQUxfR0VOS0VZLAo+ICsJT1BBTF9SRVZFUlRTUCwKPiArCU9QQUxfR0VULAo+\n"
- "ICsJT1BBTF9TRVQsCj4gKwlPUEFMX0FVVEhFTlRJQ0FURSwKPiArCU9QQUxfUkFORE9NLAo+ICsJ\n"
- "T1BBTF9FUkFTRSwKPiArfTsKPiArCj4gK2VudW0gT1BBTF9SRVNQT05TRV9UT0tFTiB7Cj4gKwlP\n"
- "UEFMX0RUQV9UT0tFTklEX0JZVEVTVFJJTkcgPSAweGUwLAo+ICsJT1BBTF9EVEFfVE9LRU5JRF9T\n"
- "SU5UID0gMHhlMSwKPiArCU9QQUxfRFRBX1RPS0VOSURfVUlOVCA9IDB4ZTIsCj4gKwlPUEFMX0RU\n"
- "QV9UT0tFTklEX1RPS0VOID0gMHhlMywgLyogYWN0dWFsIHRva2VuIGlzIHJldHVybmVkICovCj4g\n"
- "KwlPUEFMX0RUQV9UT0tFTklEX0lOVkFMSUQgPSAwWDAKPiArfTsKPiArCj4gK2VudW0gT1BBTF9U\n"
- "T0tFTiB7Cj4gKwkvKiBCb29sZWFuICovCj4gKwlPUEFMX1RSVUUgPSAweDAxLAo+ICsJT1BBTF9G\n"
- "QUxTRSA9IDB4MDAsCj4gKwlPUEFMX0JPT0xFQU5fRVhQUiA9IDB4MDMsCj4gKwkvKiBjZWxsYmxv\n"
- "Y2tzICovCj4gKwlPUEFMX1RBQkxFID0gMHgwMCwKPiArCU9QQUxfU1RBUlRST1cgPSAweDAxLAo+\n"
- "ICsJT1BBTF9FTkRST1cgPSAweDAyLAo+ICsJT1BBTF9TVEFSVENPTFVNTiA9IDB4MDMsCj4gKwlP\n"
- "UEFMX0VORENPTFVNTiA9IDB4MDQsCj4gKwlPUEFMX1ZBTFVFUyA9IDB4MDEsCj4gKwkvKiBhdXRo\n"
- "b3JpdHkgdGFibGUgKi8KPiArCU9QQUxfUElOID0gMHgwMywKPiArCS8qIGxvY2tpbmcgdG9rZW5z\n"
- "ICovCj4gKwlPUEFMX1JBTkdFU1RBUlQgPSAweDAzLAo+ICsJT1BBTF9SQU5HRUxFTkdUSCA9IDB4\n"
- "MDQsCj4gKwlPUEFMX1JFQURMT0NLRU5BQkxFRCA9IDB4MDUsCj4gKwlPUEFMX1dSSVRFTE9DS0VO\n"
- "QUJMRUQgPSAweDA2LAo+ICsJT1BBTF9SRUFETE9DS0VEID0gMHgwNywKPiArCU9QQUxfV1JJVEVM\n"
- "T0NLRUQgPSAweDA4LAo+ICsJT1BBTF9BQ1RJVkVLRVkgPSAweDBBLAo+ICsJLyogbG9ja2luZyBp\n"
- "bmZvIHRhYmxlICovCj4gKwlPUEFMX01BWFJBTkdFUyA9IDB4MDQsCj4gKwkgLyogbWJyIGNvbnRy\n"
- "b2wgKi8KPiArCU9QQUxfTUJSRU5BQkxFID0gMHgwMSwKPiArCU9QQUxfTUJSRE9ORSA9IDB4MDIs\n"
- "Cj4gKwkvKiBwcm9wZXJ0aWVzICovCj4gKwlPUEFMX0hPU1RQUk9QRVJUSUVTID0gMHgwMCwKPiAr\n"
- "CS8qIGF0b21zICovCj4gKwlPUEFMX1NUQVJUTElTVCA9IDB4ZjAsCj4gKwlPUEFMX0VORExJU1Qg\n"
- "PSAweGYxLAo+ICsJT1BBTF9TVEFSVE5BTUUgPSAweGYyLAo+ICsJT1BBTF9FTkROQU1FID0gMHhm\n"
- "MywKPiArCU9QQUxfQ0FMTCA9IDB4ZjgsCj4gKwlPUEFMX0VORE9GREFUQSA9IDB4ZjksCj4gKwlP\n"
- "UEFMX0VORE9GU0VTU0lPTiA9IDB4ZmEsCj4gKwlPUEFMX1NUQVJUVFJBTlNBQ1RPTiA9IDB4ZmIs\n"
- "Cj4gKwlPUEFMX0VORFRSQU5TQUNUT04gPSAweGZDLAo+ICsJT1BBTF9FTVBUWUFUT00gPSAweGZm\n"
- "LAo+ICsJT1BBTF9XSEVSRSA9IDB4MDAsCj4gK307Cj4gKwo+ICsvKiBVc2VmdWwgdGlueSBhdG9t\n"
- "cy4KPiArICogVXNlZnVsIGZvciB0YWJsZSBjb2x1bW5zIGV0Ywo+ICsgKi8KPiArZW51bSBPUEFM\n"
- "X1RJTllfQVRPTSB7Cj4gKwlPUEFMX1RJTllfVUlOVF8wMCA9IDB4MDAsCj4gKwlPUEFMX1RJTllf\n"
- "VUlOVF8wMSA9IDB4MDEsCj4gKwlPUEFMX1RJTllfVUlOVF8wMiA9IDB4MDIsCj4gKwlPUEFMX1RJ\n"
- "TllfVUlOVF8wMyA9IDB4MDMsCj4gKwlPUEFMX1RJTllfVUlOVF8wNCA9IDB4MDQsCj4gKwlPUEFM\n"
- "X1RJTllfVUlOVF8wNSA9IDB4MDUsCj4gKwlPUEFMX1RJTllfVUlOVF8wNiA9IDB4MDYsCj4gKwlP\n"
- "UEFMX1RJTllfVUlOVF8wNyA9IDB4MDcsCj4gKwlPUEFMX1RJTllfVUlOVF8wOCA9IDB4MDgsCj4g\n"
- "KwlPUEFMX1RJTllfVUlOVF8wOSA9IDB4MDksCj4gKwlPUEFMX1RJTllfVUlOVF8xMCA9IDB4MGEs\n"
- "Cj4gKwlPUEFMX1RJTllfVUlOVF8xMSA9IDB4MGIsCj4gKwlPUEFMX1RJTllfVUlOVF8xMiA9IDB4\n"
- "MGMsCj4gKwlPUEFMX1RJTllfVUlOVF8xMyA9IDB4MGQsCj4gKwlPUEFMX1RJTllfVUlOVF8xNCA9\n"
- "IDB4MGUsCj4gKwlPUEFMX1RJTllfVUlOVF8xNSA9IDB4MGYsCj4gK307Cj4gKwo+ICtlbnVtIE9Q\n"
- "QUxfQVRPTV9XSURUSCB7Cj4gKwlPUEFMX1dJRFRIX1RJTlksCj4gKwlPUEFMX1dJRFRIX1NIT1JU\n"
- "LAo+ICsJT1BBTF9XSURUSF9NRURJVU0sCj4gKwlPUEFMX1dJRFRIX0xPTkcsCj4gKwlPUEFMX1dJ\n"
- "RFRIX1RPS0VOCj4gK307Cj4gKwo+ICsvKiBMb2NraW5nIHN0YXRlIGZvciBhIGxvY2tpbmcgcmFu\n"
- "Z2UgKi8KPiArZW51bSBPUEFMX0xPQ0tJTkdTVEFURSB7Cj4gKwlPUEFMX0xPQ0tJTkdfUkVBRFdS\n"
- "SVRFID0gMHgwMSwKPiArCU9QQUxfTE9DS0lOR19SRUFET05MWSA9IDB4MDIsCj4gKwlPUEFMX0xP\n"
- "Q0tJTkdfTE9DS0VEID0gMHgwMywKPiArfTsKPiArCj4gKy8qCj4gKyAqIFN0cnVjdHVyZXMgdG8g\n"
- "YnVpbGQgYW5kIGRlY29kZSB0aGUgT3BhbCBTU0MgbWVzc2FnZXMKPiArICogZmllbGRzIHRoYXQg\n"
- "YXJlIE5PVCByZWFsbHkgbnVtZXJpYyBhcmUgZGVmaW5lZCBhcyB1OFtdIHRvCj4gKyAqIGhlbHAg\n"
- "cmVkdWNlIHRoZSBlbmRpYW5uZXNzIGlzc3Vlcwo+ICsgKi8KPiArCj4gKy8qIENvbW0gUGFja2V0\n"
- "IChoZWFkZXIpIGZvciB0cmFuc21pc3Npb25zLiAqLwo+ICtzdHJ1Y3Qgb3BhbF9jb21wYWNrZXQg\n"
- "ewo+ICsJdTMyIHJlc2VydmVkMDsKPiArCXU4IGV4dGVuZGVkQ29tSURbNF07Cj4gKwl1MzIgb3V0\n"
- "c3RhbmRpbmdEYXRhOwo+ICsJdTMyIG1pblRyYW5zZmVyOwo+ICsJdTMyIGxlbmd0aDsKPiArfTsK\n"
- "PiArCj4gKy8qIFBhY2tldCBzdHJ1Y3R1cmUuICovCj4gK3N0cnVjdCBvcGFsX3BhY2tldCB7Cj4g\n"
- "Kwl1MzIgVFNOOwo+ICsJdTMyIEhTTjsKPiArCXUzMiBzZXFfbnVtYmVyOwo+ICsJdTE2IHJlc2Vy\n"
- "dmVkMDsKPiArCXUxNiBhY2tfdHlwZTsKPiArCXUzMiBhY2tub3dsZWRnbWVudDsKPiArCXUzMiBs\n"
- "ZW5ndGg7Cj4gK307Cj4gKwo+ICsvKiBEYXRhIHN1YiBwYWNrZXQgaGVhZGVyICovCj4gK3N0cnVj\n"
- "dCBvcGFsX2RhdGFfc3VicGFja2V0IHsKPiArCXU4IHJlc2VydmVkMFs2XTsKPiArCXUxNiBraW5k\n"
- "Owo+ICsJdTMyIGxlbmd0aDsKPiArfTsKPiArCj4gKy8qIGhlYWRlciBvZiBhIHJlc3BvbnNlICov\n"
- "Cj4gK3N0cnVjdCBvcGFsX2hlYWRlciB7Cj4gKwlzdHJ1Y3Qgb3BhbF9jb21wYWNrZXQgY3A7Cj4g\n"
- "KwlzdHJ1Y3Qgb3BhbF9wYWNrZXQgcGt0Owo+ICsJc3RydWN0IG9wYWxfZGF0YV9zdWJwYWNrZXQg\n"
- "c3VicGt0Owo+ICt9Owo+ICsKPiArI2RlZmluZSBGQ19UUEVSICAgICAgIDB4MDAwMQo+ICsjZGVm\n"
- "aW5lIEZDX0xPQ0tJTkcgICAgMHgwMDAyCj4gKyNkZWZpbmUgRkNfR0VPTUVUUlkgICAweDAwMDMK\n"
- "PiArI2RlZmluZSBGQ19FTlRFUlBSSVNFIDB4MDEwMAo+ICsjZGVmaW5lIEZDX0RBVEFTVE9SRSAg\n"
- "MHgwMjAyCj4gKyNkZWZpbmUgRkNfU0lOR0xFVVNFUiAweDAyMDEKPiArI2RlZmluZSBGQ19PUEFM\n"
- "VjEwMCAgIDB4MDIwMAo+ICsjZGVmaW5lIEZDX09QQUxWMjAwICAgMHgwMjAzCj4gKwo+ICsvKgo+\n"
- "ICsgKiBUaGUgRGlzY292ZXJ5IDAgSGVhZGVyLiBBcyBkZWZpbmVkIGluCj4gKyAqIE9wYWwgU1ND\n"
- "IERvY3VtZW50YXRpb24KPiArICovCj4gK3N0cnVjdCBkMF9oZWFkZXIgewo+ICsJdTMyIGxlbmd0\n"
- "aDsgLyogdGhlIGxlbmd0aCBvZiB0aGUgaGVhZGVyIDQ4IGluIDIuMDAuMTAwICovCj4gKwl1MzIg\n"
- "cmV2aXNpb247IC8qKjwgcmV2aXNpb24gb2YgdGhlIGhlYWRlciAxIGluIDIuMDAuMTAwICovCj4g\n"
- "Kwl1MzIgcmVzZXJ2ZWQwMTsKPiArCXUzMiByZXNlcnZlZDAyOwo+ICsJLyoKPiArCSAqIHRoZSBy\n"
- "ZW1haW5kZXIgb2YgdGhlIHN0cnVjdHVyZSBpcyB2ZW5kb3Igc3BlY2lmaWMgYW5kIHdpbGwgbm90\n"
- "IGJlCj4gKwkgKiBhZGRyZXNzZWQgbm93Cj4gKwkgKi8KPiArCXU4IGlnbm9yZWRbMzJdOwo+ICt9\n"
- "Owo+ICsKPiArLyoKPiArICogVFBlciBGZWF0dXJlIERlc2NyaXB0b3IuIENvbnRhaW5zIGZsYWdz\n"
- "IGluZGljYXRpbmcgc3VwcG9ydCBmb3IgdGhlCj4gKyAqIFRQZXIgZmVhdHVyZXMgZGVzY3JpYmVk\n"
- "IGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRjaCB0aGUKPiArICogT1BB\n"
- "TCB0ZXJtaW5vbG9neQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDAxIGluIDIuMDAuMTAwCj4gKyAq\n"
- "Lwo+ICtzdHJ1Y3QgZDBfdHBlcl9mZWF0dXJlcyB7Cj4gKwkvKgo+ICsJICogc3VwcG9ydGVkX2Zl\n"
- "YXR1cmVzIGJpdHM6Cj4gKwkgKiBiaXQgNzogcmVzZXJ2ZWQKPiArCSAqIGJpdCA2OiBjb20gSUQg\n"
- "bWFuYWdlbWVudAo+ICsJICogYml0IDU6IHJlc2VydmVkCj4gKwkgKiBiaXQgNDogc3RyZWFtaW5n\n"
- "IHN1cHBvcnQKPiArCSAqIGJpdCAzOiBidWZmZXIgbWFuYWdlbWVudAo+ICsJICogYml0IDI6IEFD\n"
- "Sy9OQUNLCj4gKwkgKiBiaXQgMTogYXN5bmMKPiArCSAqIGJpdCAwOiBzeW5jCj4gKwkgKi8KPiAr\n"
- "CXU4IHN1cHBvcnRlZF9mZWF0dXJlczsKPiArCS8qCj4gKwkgKiBieXRlcyA1IHRocm91Z2ggMTUg\n"
- "YXJlIHJlc2VydmVkLCBidXQgd2UgcmVwcmVzZW50IHRoZSBmaXJzdCAzIGFzCj4gKwkgKiB1OCB0\n"
- "byBrZWVwIHRoZSBvdGhlciB0d28gMzJiaXRzIGludGVnZXJzIGFsaWduZWQuCj4gKwkgKi8KPiAr\n"
- "CXU4IHJlc2VydmVkMDFbM107Cj4gKwl1MzIgcmVzZXJ2ZWQwMjsKPiArCXUzMiByZXNlcnZlZDAz\n"
- "Owo+ICt9Owo+ICsKPiArLyoKPiArICogTG9ja2luZyBGZWF0dXJlIERlc2NyaXB0b3IuIENvbnRh\n"
- "aW5zIGZsYWdzIGluZGljYXRpbmcgc3VwcG9ydCBmb3IgdGhlCj4gKyAqIGxvY2tpbmcgZmVhdHVy\n"
- "ZXMgZGVzY3JpYmVkIGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRjaCB0\n"
- "aGUKPiArICogT1BBTCB0ZXJtaW5vbG9neQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDAwMiBpbiAy\n"
- "LjAwLjEwMAo+ICsgKi8KPiArc3RydWN0IGQwX2xvY2tpbmdfZmVhdHVyZXMgewo+ICsJLyoKPiAr\n"
- "CSAqIHN1cHBvcnRlZF9mZWF0dXJlcyBiaXRzOgo+ICsJICogYml0cyA2LTc6IHJlc2VydmVkCj4g\n"
- "KwkgKiBiaXQgNTogTUJSIGRvbmUKPiArCSAqIGJpdCA0OiBNQlIgZW5hYmxlZAo+ICsJICogYml0\n"
- "IDM6IG1lZGlhIGVuY3J5cHRpb24KPiArCSAqIGJpdCAyOiBsb2NrZWQKPiArCSAqIGJpdCAxOiBs\n"
- "b2NraW5nIGVuYWJsZWQKPiArCSAqIGJpdCAwOiBsb2NraW5nIHN1cHBvcnRlZAo+ICsJICovCj4g\n"
- "Kwl1OCBzdXBwb3J0ZWRfZmVhdHVyZXM7Cj4gKwkvKgo+ICsJICogYnl0ZXMgNSB0aHJvdWdoIDE1\n"
- "IGFyZSByZXNlcnZlZCwgYnV0IHdlIHJlcHJlc2VudCB0aGUgZmlyc3QgMyBhcwo+ICsJICogdTgg\n"
- "dG8ga2VlcCB0aGUgb3RoZXIgdHdvIDMyYml0cyBpbnRlZ2VycyBhbGlnbmVkLgo+ICsJICovCj4g\n"
- "Kwl1OCByZXNlcnZlZDAxWzNdOwo+ICsJdTMyIHJlc2VydmVkMDI7Cj4gKwl1MzIgcmVzZXJ2ZWQw\n"
- "MzsKPiArfTsKPiArCj4gKy8qCj4gKyAqIEdlb21ldHJ5IEZlYXR1cmUgRGVzY3JpcHRvci4gQ29u\n"
- "dGFpbnMgZmxhZ3MgaW5kaWNhdGluZyBzdXBwb3J0IGZvciB0aGUKPiArICogZ2VvbWV0cnkgZmVh\n"
- "dHVyZXMgZGVzY3JpYmVkIGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRj\n"
- "aCB0aGUKPiArICogT1BBTCB0ZXJtaW5vbG9neQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDAwMyBp\n"
- "biAyLjAwLjEwMAo+ICsgKi8KPiArc3RydWN0IGQwX2dlb21ldHJ5X2ZlYXR1cmVzIHsKPiArCS8q\n"
- "Cj4gKwkgKiBza2lwIDMyIGJpdHMgZnJvbSBoZWFkZXIsIG5lZWRlZCB0byBhbGlnbiB0aGUgc3Ry\n"
- "dWN0IHRvIDY0IGJpdHMuCj4gKwkgKi8KPiArCXU4IGhlYWRlcls0XTsKPiArCS8qCj4gKwkgKiBy\n"
- "ZXNlcnZlZDAxOgo+ICsJICogYml0cyAxLTY6IHJlc2VydmVkCj4gKwkgKiBiaXQgMDogYWxpZ24K\n"
- "PiArCSAqLwo+ICsJdTggcmVzZXJ2ZWQwMTsKPiArCXU4IHJlc2VydmVkMDJbN107Cj4gKwl1MzIg\n"
- "bG9naWNhbF9ibG9ja19zaXplOwo+ICsJdTY0IGFsaWdubWVudF9ncmFudWxhcml0eTsKPiArCXU2\n"
- "NCBsb3dlc3RfYWxpZ25lZF9sYmE7Cj4gK307Cj4gKwo+ICsvKgo+ICsgKiBFbnRlcnByaXNlIFNT\n"
- "QyBGZWF0dXJlCj4gKyAqCj4gKyAqIGNvZGUgPT0gMHgwMTAwCj4gKyAqLwo+ICtzdHJ1Y3QgZDBf\n"
- "ZW50ZXJwcmlzZV9zc2Mgewo+ICsJdTE2IGJhc2VDb21JRDsKPiArCXUxNiBudW1Db21JRHM7Cj4g\n"
- "KwkvKiByYW5nZV9jcm9zc2luZzoKPiArCSAqIGJpdHMgMS02OiByZXNlcnZlZAo+ICsJICogYml0\n"
- "IDA6IHJhbmdlIGNyb3NzaW5nCj4gKwkgKi8KPiArCXU4IHJhbmdlX2Nyb3NzaW5nOwo+ICsJdTgg\n"
- "cmVzZXJ2ZWQwMTsKPiArCXUxNiByZXNlcnZlZDAyOwo+ICsJdTMyIHJlc2VydmVkMDM7Cj4gKwl1\n"
- "MzIgcmVzZXJ2ZWQwNDsKPiArfTsKPiArCj4gKy8qCj4gKyAqIE9wYWwgVjEgZmVhdHVyZQo+ICsg\n"
- "Kgo+ICsgKiBjb2RlID09IDB4MDIwMAo+ICsgKi8KPiArc3RydWN0IGQwX29wYWxfdjEwMCB7Cj4g\n"
- "Kwl1MTYgYmFzZUNvbUlEOwo+ICsJdTE2IG51bUNvbUlEczsKPiArfTsKPiArCj4gKy8qCj4gKyAq\n"
- "IFNpbmdsZSBVc2VyIE1vZGUgZmVhdHVyZQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDIwMQo+ICsg\n"
- "Ki8KPiArc3RydWN0IGQwX3NpbmdsZV91c2VyX21vZGUgewo+ICsJdTMyIG51bV9sb2NraW5nX29i\n"
- "amVjdHM7Cj4gKwkvKiByZXNlcnZlZDAxOgo+ICsJICogYml0IDA6IGFueQo+ICsJICogYml0IDE6\n"
- "IGFsbAo+ICsJICogYml0IDI6IHBvbGljeQo+ICsJICogYml0cyAzLTc6IHJlc2VydmVkCj4gKwkg\n"
- "Ki8KPiArCXU4IHJlc2VydmVkMDE7Cj4gKwl1OCByZXNlcnZlZDAyOwo+ICsJdTE2IHJlc2VydmVk\n"
- "MDM7Cj4gKwl1MzIgcmVzZXJ2ZWQwNDsKPiArfTsKPiArCj4gKy8qCj4gKyAqIEFkZGl0b25hbCBE\n"
- "YXRhc3RvcmVzIGZlYXR1cmUKPiArICoKPiArICogY29kZSA9PSAweDAyMDIKPiArICovCj4gK3N0\n"
- "cnVjdCBkMF9kYXRhc3RvcmVfdGFibGUgewo+ICsJdTE2IHJlc2VydmVkMDE7Cj4gKwl1MTYgbWF4\n"
- "X3RhYmxlczsKPiArCXUzMiBtYXhfc2l6ZV90YWJsZXM7Cj4gKwl1MzIgdGFibGVfc2l6ZV9hbGln\n"
- "bm1lbnQ7Cj4gK307Cj4gKwo+ICsvKgo+ICsgKiBPUEFMIDIuMCBmZWF0dXJlCj4gKyAqCj4gKyAq\n"
- "IGNvZGUgPT0gMHgwMjAzCj4gKyAqLwo+ICtzdHJ1Y3QgZDBfb3BhbF92MjAwIHsKPiArCXUxNiBi\n"
- "YXNlQ29tSUQ7Cj4gKwl1MTYgbnVtQ29tSURzOwo+ICsJLyogcmFuZ2VfY3Jvc3Npbmc6Cj4gKwkg\n"
- "KiBiaXRzIDEtNjogcmVzZXJ2ZWQKPiArCSAqIGJpdCAwOiByYW5nZSBjcm9zc2luZwo+ICsJICov\n"
- "Cj4gKwl1OCByYW5nZV9jcm9zc2luZzsKPiArCS8qIG51bV9sb2NraW5nX2FkbWluX2F1dGg6Cj4g\n"
- "KwkgKiBub3QgYWxpZ25lZCB0byAxNiBiaXRzLCBzbyB1c2UgdHdvIHU4Lgo+ICsJICogc3RvcmVk\n"
- "IGluIGJpZyBlbmRpYW46Cj4gKwkgKiAwOiBNU0IKPiArCSAqIDE6IExTQgo+ICsJICovCj4gKwl1\n"
- "OCBudW1fbG9ja2luZ19hZG1pbl9hdXRoWzJdOwo+ICsJLyogbnVtX2xvY2tpbmdfdXNlcl9hdXRo\n"
- "Ogo+ICsJICogbm90IGFsaWduZWQgdG8gMTYgYml0cywgc28gdXNlIHR3byB1OC4KPiArCSAqIHN0\n"
- "b3JlZCBpbiBiaWcgZW5kaWFuOgo+ICsJICogMDogTVNCCj4gKwkgKiAxOiBMU0IKPiArCSAqLwo+\n"
- "ICsJdTggbnVtX2xvY2tpbmdfdXNlcl9hdXRoWzJdOwo+ICsJdTggaW5pdGlhbFBJTjsKPiArCXU4\n"
- "IHJldmVydGVkUElOOwo+ICsJdTggcmVzZXJ2ZWQwMTsKPiArCXUzMiByZXNlcnZlZDAyOwo+ICt9\n"
- "Owo+ICsKPiArLyogVW5pb24gb2YgZmVhdHVyZXMgdXNlZCB0byBwYXJzZSB0aGUgZGlzY292ZXJ5\n"
- "IDAgcmVzcG9uc2UgKi8KPiArc3RydWN0IGQwX2ZlYXR1cmVzIHsKPiArCXUxNiBjb2RlOwo+ICsJ\n"
- "LyoKPiArCSAqIHJfdmVyc2lvbiBiaXRzOgo+ICsJICogYml0cyA0LTc6IHZlcnNpb24KPiArCSAq\n"
- "IGJpdHMgMC0zOiByZXNlcnZlZAo+ICsJICovCj4gKwl1OCByX3ZlcnNpb247Cj4gKwl1OCBsZW5n\n"
- "dGg7Cj4gKwl1OCBmZWF0dXJlc1tdOwo+ICt9Owo+ICsKPiArc3RydWN0IGtleSAqcmVxdWVzdF91\n"
- "c2VyX2tleShjb25zdCBjaGFyICptYXN0ZXJfZGVzYywgY29uc3QgdTggKiptYXN0ZXJfa2V5LAo+\n"
- "ICsJCQkgICAgIHNpemVfdCAqbWFzdGVyX2tleWxlbik7Cj4gKwo+ICsjZW5kaWYgLyogX05WTUVf\n"
- "T1BBTF9JTlRFUk5BTF9IICovCj4gZGlmZiAtLWdpdCBhL2xpYi9zZWQtb3BhbF9rZXkuYyBiL2xp\n"
- "Yi9zZWQtb3BhbF9rZXkuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4u\n"
- "MGI0ZGUwMQo+IC0tLSAvZGV2L251bGwKPiArKysgYi9saWIvc2VkLW9wYWxfa2V5LmMKPiBAQCAt\n"
- "MCwwICsxLDQ2IEBACj4gKy8qCj4gKyAqIENvcHlyaWdodCDCqSAyMDE2IEludGVsIENvcnBvcmF0\n"
- "aW9uCj4gKyAqCj4gKyAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hh\n"
- "cmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhCj4gKyAqIGNvcHkgb2YgdGhpcyBzb2Z0d2Fy\n"
- "ZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCj4g\n"
- "KyAqIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGlu\n"
- "ZyB3aXRob3V0IGxpbWl0YXRpb24KPiArICogdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlm\n"
- "eSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsCj4gKyAqIGFuZC9vciBz\n"
- "ZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9t\n"
- "IHRoZQo+ICsgKiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhl\n"
- "IGZvbGxvd2luZyBjb25kaXRpb25zOgo+ICsgKgo+ICsgKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5v\n"
- "dGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSAoaW5jbHVkaW5nIHRoZSBuZXh0Cj4gKyAq\n"
- "IHBhcmFncmFwaCkgc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlh\n"
- "bCBwb3J0aW9ucyBvZiB0aGUKPiArICogU29mdHdhcmUuCj4gKyAqCj4gKyAqIFRIRSBTT0ZUV0FS\n"
- "RSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBS\n"
- "RVNTIE9SCj4gKyAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdB\n"
- "UlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAo+ICsgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VM\n"
- "QVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiAgSU4gTk8gRVZFTlQgU0hBTEwKPiArICog\n"
- "VEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0s\n"
- "IERBTUFHRVMgT1IgT1RIRVIKPiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBP\n"
- "RiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcKPiArICogRlJPTSwgT1VUIE9G\n"
- "IE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBE\n"
- "RUFMSU5HUwo+ICsgKiBJTiBUSEUgU09GVFdBUkUuCj4gKyAqCj4gKyAqIEF1dGhvcjoKPiArICog\n"
- "ICAgUmFmYWVsIEFudG9nbm9sbGkgPHJhZmFlbC5hbnRvZ25vbGxpQGludGVsLmNvbT4KPiArICov\n"
- "Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgva2V5Lmg+Cj4gKyNpbmNsdWRlICJzZWQtb3BhbF9pbnRl\n"
- "cm5hbC5oIgo+ICsKPiArc3RydWN0IGtleSAqcmVxdWVzdF91c2VyX2tleShjb25zdCBjaGFyICpt\n"
- "YXN0ZXJfZGVzYywgY29uc3QgdTggKiptYXN0ZXJfa2V5LAo+ICsJCQkgICAgIHNpemVfdCAqbWFz\n"
- "dGVyX2tleWxlbikKPiArewo+ICsJY29uc3Qgc3RydWN0IHVzZXJfa2V5X3BheWxvYWQgKnVwYXls\n"
- "b2FkOwo+ICsJc3RydWN0IGtleSAqdWtleTsKPiArCj4gKwl1a2V5ID0gcmVxdWVzdF9rZXkoJmtl\n"
- "eV90eXBlX3VzZXIsIG1hc3Rlcl9kZXNjLCBOVUxMKTsKPiArCWlmIChJU19FUlIodWtleSkpCj4g\n"
- "KwkJZ290byBlcnJvcjsKPiArCj4gKwlkb3duX3JlYWQoJnVrZXktPnNlbSk7Cj4gKwl1cGF5bG9h\n"
- "ZCA9IHVzZXJfa2V5X3BheWxvYWQodWtleSk7Cj4gKwkqbWFzdGVyX2tleSA9IHVwYXlsb2FkLT5k\n"
- "YXRhOwo+ICsJKm1hc3Rlcl9rZXlsZW4gPSB1cGF5bG9hZC0+ZGF0YWxlbjsKPiArZXJyb3I6Cj4g\n"
- "KwlyZXR1cm4gdWtleTsKPiArfQo+IGRpZmYgLS1naXQgYS9saWIvc2VkLmMgYi9saWIvc2VkLmMK\n"
- "PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLjA2Y2FjZDkKPiAtLS0gL2Rl\n"
- "di9udWxsCj4gKysrIGIvbGliL3NlZC5jCj4gQEAgLTAsMCArMSwzMDMgQEAKPiArI2luY2x1ZGUg\n"
- "PGxpbnV4L2Jsa2Rldi5oPgo+ICsjaW5jbHVkZSA8bGludXgvc2VkLmg+Cj4gKyNpbmNsdWRlIDxs\n"
- "aW51eC9zZWQtb3BhbC5oPgo+ICsKPiArI2lmbmRlZiBDT05GSUdfU0VEX09QQUwKPiArc3RhdGlj\n"
- "IGludCBzZWRfb3BhbF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf\n"
- "a2V5ICpzZWQpCj4gKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9v\n"
- "cGFsX2xvY2tfdW5sb2NrKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5\n"
- "ICprZXkpCj4gKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9vcGFs\n"
- "X3Rha2Vfb3duZXJzaGlwKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5\n"
- "ICprZXkpCj4gKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9vcGFs\n"
- "X2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAq\n"
- "a2V5KQo+ICsJeyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KPiArc3RhdGljIGludCBzZWRfb3BhbF9z\n"
- "ZXRfcHcoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiAr\n"
- "CXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9Cj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfYWN0aXZhdGVf\n"
- "dXNlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICsJ\n"
- "eyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KPiArc3RhdGljIGludCBzZWRfb3BhbF9yZXZlcnR0cGVy\n"
- "KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gKwl7IHJl\n"
- "dHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3NldHVwX2xvY2tpbmdf\n"
- "cmFuZ2Uoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiAr\n"
- "CXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9Cj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfYWRkdXNlcl90\n"
- "b19scihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICsJ\n"
- "eyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KPiArc3RhdGljIGludCBzZWRfb3BhbF9kb19tYnIoc3Ry\n"
- "dWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArCXsgcmV0dXJu\n"
- "IC1FT1BOT1RTVVBQOyB9Cj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfZXJhc2VfbHIoc3RydWN0IGJs\n"
- "b2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArCXsgcmV0dXJuIC1FT1BO\n"
- "T1RTVVBQOyB9Cj4gKwo+ICsjZWxzZQo+ICsKPiArc3RhdGljIGludCBzZWRfb3BhbF9zYXZlKHN0\n"
- "cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sKPiArCj4g\n"
- "KwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwK\n"
- "PiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5P\n"
- "VFNVUFA7CllvdSBtaWdodCBjb25zaWRlciBwdWxsaW5nIHRoaXMgYm9pbGVycGxhdGUgb3V0IGlu\n"
- "dG8gc29tZXRoaW5nIGxpa2U6CnN0YXRpYyBpbmxpbmUgYm9vbCBiZGV2X3NlY19jYXBhYmxlKHN0\n"
- "cnVjdCBibG9ja19kZXZpY2UgKmJkZXYpCnsKCXJldHVybiBiZGV2ICYmIGJkZXYtPmJkX2Rpc2sg\n"
- "JiYgYmRldi0+YmRfZGlzay0+Zm9wcyAmJgoJICAgICAgIGJkZXYtPmJkX2Rpc2stPmZvcHMtPnNl\n"
- "Y19vcHM7Cn0KCgo+ICsKPiArCXJldHVybiBvcGFsX3NhdmUoYmRldiwga2V5KTsKPiArfQo+ICsK\n"
- "PiArc3RhdGljIGludCBzZWRfb3BhbF9sb2NrX3VubG9jayhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpi\n"
- "ZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2\n"
- "LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rp\n"
- "c2stPmZvcHMtPnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXJldHVy\n"
- "biBvcGFsX2xvY2tfdW5sb2NrKGJkZXYsIGtleSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgc2Vk\n"
- "X29wYWxfdGFrZV9vd25lcnNoaXAoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKPiArCQkJCSAg\n"
- "IHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sKPiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJk\n"
- "X2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+\n"
- "Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9w\n"
- "YWxfdGFrZV9vd25lcnNoaXAoYmRldiwga2V5KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzZWRf\n"
- "b3BhbF9hY3RpdmF0ZV9sc3Aoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKPiArCQkJCSBzdHJ1\n"
- "Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNr\n"
- "IHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMt\n"
- "PnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXJldHVybiBvcGFsX2Fj\n"
- "dGl2YXRlX2xzcChiZGV2LCBrZXkpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3Nl\n"
- "dF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LAo+ICsJCQkgICBzdHJ1Y3Qgc2VkX2tleSAq\n"
- "a2V5KQo+ICt7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5i\n"
- "ZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCj4g\n"
- "KwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXJldHVybiBvcGFsX3NldF9uZXdfcHcoYmRl\n"
- "diwga2V5KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzZWRfb3BhbF9hY3RpdmF0ZV91c2VyKHN0\n"
- "cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQkgIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4g\n"
- "K3sKPiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2st\n"
- "PmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1\n"
- "cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfYWN0aXZhdGVfdXNlcihiZGV2LCBr\n"
- "ZXkpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3JldmVydHRwZXIoc3RydWN0IGJs\n"
- "b2NrX2RldmljZSAqYmRldiwKPiArCQkJICAgICAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sK\n"
- "PiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZv\n"
- "cHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4g\n"
- "LUVPUE5PVFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfcmV2ZXJ0dHBlcihiZGV2LCBrZXkpOwo+\n"
- "ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3NldHVwX2xyKHN0cnVjdCBibG9ja19kZXZp\n"
- "Y2UgKmJkZXYsCj4gKwkJCSAgICAgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsKPiArCWlm\n"
- "ICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAo+ICsJ\n"
- "ICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ICsJCXJldHVybiAtRU9QTk9UU1VQ\n"
- "UDsKPiArCj4gKwlyZXR1cm4gb3BhbF9zZXR1cF9sb2NraW5nX3JhbmdlKGJkZXYsIGtleSk7Cj4g\n"
- "K30KPiArCj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfYWRkdXNlcl90b19scihzdHJ1Y3QgYmxvY2tf\n"
- "ZGV2aWNlICpiZGV2LAo+ICsJCQkgICAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sKPiArCj4g\n"
- "KwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwK\n"
- "PiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5P\n"
- "VFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfYWRkX3VzZXJfdG9fbHIoYmRldiwga2V5KTsKPiAr\n"
- "fQo+ICsKPiArc3RhdGljIGludCBzZWRfb3BhbF9kb19tYnIoc3RydWN0IGJsb2NrX2RldmljZSAq\n"
- "YmRldiwKPiArCQkJICAgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsKPiArCWlmICghYmRl\n"
- "diB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFi\n"
- "ZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiAr\n"
- "Cj4gKwlyZXR1cm4gb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFkb3dfbWJyKGJkZXYsIGtleSk7Cj4g\n"
- "K30KPiArCj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfZXJhc2VfbHIoc3RydWN0IGJsb2NrX2Rldmlj\n"
- "ZSAqYmRldiwKPiArCQkJICAgICBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwo+ICsJaWYg\n"
- "KCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkg\n"
- "ICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQ\n"
- "Owo+ICsKPiArCXJldHVybiBvcGFsX2VyYXNlX2xvY2tpbmdfcmFuZ2UoYmRldiwga2V5KTsKPiAr\n"
- "fQo+ICsjZW5kaWYKPiArCj4gK2ludCBzZWRfc2F2ZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2\n"
- "LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rp\n"
- "c2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9w\n"
- "cy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChrZXkt\n"
- "PnNlZF90eXBlKSB7Cj4gKwljYXNlIE9QQUxfTE9DS19VTkxPQ0s6Cj4gKwkJcmV0dXJuIHNlZF9v\n"
- "cGFsX3NhdmUoYmRldiwga2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4g\n"
- "K30KPiArCj4gK2ludCBzZWRfbG9ja191bmxvY2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg\n"
- "c3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNr\n"
- "IHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMt\n"
- "PnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXN3aXRjaCAoa2V5LT5z\n"
- "ZWRfdHlwZSkgewo+ICsJY2FzZSBPUEFMX0xPQ0tfVU5MT0NLOgo+ICsJCXJldHVybiBzZWRfb3Bh\n"
- "bF9sb2NrX3VubG9jayhiZGV2LCBrZXkpOwo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQ\n"
- "UDsKPiArfQo+ICsKPiAraW50IHNlZF90YWtlX293bmVyc2hpcChzdHJ1Y3QgYmxvY2tfZGV2aWNl\n"
- "ICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYt\n"
- "PmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlz\n"
- "ay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNo\n"
- "IChrZXktPnNlZF90eXBlKSB7Cj4gKwljYXNlIE9QQUw6Cj4gKwkJcmV0dXJuIHNlZF9vcGFsX3Rh\n"
- "a2Vfb3duZXJzaGlwKGJkZXYsIGtleSk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIC1FT1BOT1RTVVBQ\n"
- "Owo+ICt9Cj4gKwo+ICtpbnQgc2VkX2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpi\n"
- "ZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJk\n"
- "X2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+\n"
- "Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChr\n"
- "ZXktPnNlZF90eXBlKSB7Cj4gKwljYXNlIE9QQUw6Cj4gKwkJcmV0dXJuIHNlZF9vcGFsX2FjdGl2\n"
- "YXRlX2xzcChiZGV2LCBrZXkpOwo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQUDsKPiAr\n"
- "fQo+ICsKPiAraW50IHNlZF9zZXRfcHcoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0\n"
- "IHNlZF9rZXkgKmtleSkKPiArewo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFi\n"
- "ZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19v\n"
- "cHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXN3aXRjaCAoa2V5LT5zZWRfdHlw\n"
- "ZSkgewo+ICsJY2FzZSBPUEFMX1BXOgo+ICsJCXJldHVybiBzZWRfb3BhbF9zZXRfcHcoYmRldiwg\n"
- "a2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30KPiArCj4gK2ludCBz\n"
- "ZWRfYWN0aXZhdGVfdXNlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tl\n"
- "eSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJk\n"
- "X2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiAr\n"
- "CQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7Cj4g\n"
- "KwljYXNlIE9QQUxfQUNUX1VTUjoKPiArCQlyZXR1cm4gc2VkX29wYWxfYWN0aXZhdGVfdXNlcihi\n"
- "ZGV2LCBrZXkpOwo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQUDsKPiArfQo+ICsKPiAr\n"
- "aW50IHNlZF9yZXZlcnR0cGVyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf\n"
- "a2V5ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+\n"
- "YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+\n"
- "ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsK\n"
- "PiArCWNhc2UgT1BBTDoKPiArCQlyZXR1cm4gc2VkX29wYWxfcmV2ZXJ0dHBlcihiZGV2LCBrZXkp\n"
- "Owo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQUDsKPiArfQo+ICsKPiAraW50IHNlZF9z\n"
- "ZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf\n"
- "a2V5ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+\n"
- "YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+\n"
- "ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsK\n"
- "PiArCWNhc2UgT1BBTF9MUl9TRVRVUDoKPiArCQlyZXR1cm4gc2VkX29wYWxfc2V0dXBfbHIoYmRl\n"
- "diwga2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30KPiArCj4gK2lu\n"
- "dCBzZWRfYWRkdXNlcl90b19scihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk\n"
- "X2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYt\n"
- "PmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykK\n"
- "PiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7\n"
- "Cj4gKwljYXNlIE9QQUxfTE9DS19VTkxPQ0s6Cj4gKwkJcmV0dXJuIHNlZF9vcGFsX2FkZHVzZXJf\n"
- "dG9fbHIoYmRldiwga2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30K\n"
- "PiArCj4gK2ludCBzZWRfZG9fbWJyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBz\n"
- "ZWRfa2V5ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRl\n"
- "di0+YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3Bz\n"
- "KQo+ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUp\n"
- "IHsKPiArCWNhc2UgT1BBTF9NQlJfREFUQToKPiArCQlyZXR1cm4gc2VkX29wYWxfZG9fbWJyKGJk\n"
- "ZXYsIGtleSk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICt9Cj4gKwo+ICtp\n"
- "bnQgc2VkX2VyYXNlX2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5\n"
- "ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRf\n"
- "ZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ICsJ\n"
- "CXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsKPiAr\n"
- "CWNhc2UgT1BBTDoKPiArCQlyZXR1cm4gc2VkX29wYWxfZXJhc2VfbHIoYmRldiwga2V5KTsKPiAr\n"
- "CX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30KPiAtLSAKPiAyLjcuNAo+IAoKX19f\n"
- "X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGludXgtbnZtZSBt\n"
- "YWlsaW5nIGxpc3QKTGludXgtbnZtZUBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5p\n"
- bmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtbnZtZQo=
+ "Hi Rafael, Scott,\n"
+ "\n"
+ "\n"
+ "First off, congrats on the set! It looks good so far.\n"
+ "\n"
+ "Just some small nits below since you have to respin it anyways :)\n"
+ "\n"
+ "On Mon, Oct 31, 2016@03:58:15PM -0600, Scott Bauer wrote:\n"
+ "> This patch implements the necessary logic to bring an Opal\n"
+ "> enabled drive out of a factory-enabled into a working\n"
+ "> Opal state.\n"
+ "> \n"
+ "> This patch set also enables logic to save a password to\n"
+ "> be replayed during a resume from suspend. The key can be\n"
+ "> saved in the driver or in the Kernel's Key managment.\n"
+ "> \n"
+ "> Signed-off-by: Scott Bauer <scott.bauer at intel.com>\n"
+ "> Signed-off-by: Rafael Antognolli <Rafael.Antognolli at intel.com>\n"
+ "> ---\n"
+ ">  lib/sed-opal.c          | 3337 +++++++++++++++++++++++++++++++++++++++++++++++\n"
+ ">  lib/sed-opal_internal.h |  586 +++++++++\n"
+ ">  lib/sed-opal_key.c      |   46 +\n"
+ ">  lib/sed.c               |  303 +++++\n"
+ ">  4 files changed, 4272 insertions(+)\n"
+ ">  create mode 100644 lib/sed-opal.c\n"
+ ">  create mode 100644 lib/sed-opal_internal.h\n"
+ ">  create mode 100644 lib/sed-opal_key.c\n"
+ ">  create mode 100644 lib/sed.c\n"
+ "> \n"
+ "> diff --git a/lib/sed-opal.c b/lib/sed-opal.c\n"
+ "> new file mode 100644\n"
+ "> index 0000000..10b3348\n"
+ "> --- /dev/null\n"
+ "> +++ b/lib/sed-opal.c\n"
+ "> @@ -0,0 +1,3337 @@\n"
+ "> +/*\n"
+ "> + * Copyright ? 2016 Intel Corporation\n"
+ "> + *\n"
+ "> + * Permission is hereby granted, free of charge, to any person obtaining a\n"
+ "> + * copy of this software and associated documentation files (the \"Software\"),\n"
+ "> + * to deal in the Software without restriction, including without limitation\n"
+ "> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n"
+ "> + * and/or sell copies of the Software, and to permit persons to whom the\n"
+ "> + * Software is furnished to do so, subject to the following conditions:\n"
+ "> + *\n"
+ "> + * The above copyright notice and this permission notice (including the next\n"
+ "> + * paragraph) shall be included in all copies or substantial portions of the\n"
+ "> + * Software.\n"
+ "> + *\n"
+ "> + * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
+ "> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
+ "> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n"
+ "> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
+ "> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n"
+ "> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n"
+ "> + * IN THE SOFTWARE.\n"
+ "> + *\n"
+ "> + * Authors:\n"
+ "> + *    Rafael Antognolli <rafael.antognolli at intel.com>\n"
+ "> + *    Scott  Bauer      <scott.bauer at intel.com>\n"
+ "> + */\n"
+ "> +\n"
+ "> +#define pr_fmt(fmt) KBUILD_MODNAME \":OPAL: \" fmt\n"
+ "> +\n"
+ "> +#include <linux/delay.h>\n"
+ "> +#include <linux/device.h>\n"
+ "> +#include <linux/kernel.h>\n"
+ "> +#include <linux/list.h>\n"
+ "> +#include <linux/genhd.h>\n"
+ "> +#include <linux/slab.h>\n"
+ "> +#include <linux/uaccess.h>\n"
+ "> +#include <uapi/linux/sed-opal.h>\n"
+ "> +#include <linux/sed.h>\n"
+ "> +#include <linux/sed-opal.h>\n"
+ "> +#include <linux/string.h>\n"
+ "> +\n"
+ "> +#include \"sed-opal_internal.h\"\n"
+ "> +\n"
+ "> +#define IO_BUFFER_LENGTH 2048\n"
+ "> +\n"
+ "> +#define MAX_TOKS 64\n"
+ "> +\n"
+ "> +struct opal_cmd {\n"
+ "> +\tstruct block_device *bdev;\n"
+ "> +\tsec_cb *cb;\n"
+ "> +\tvoid *cb_data;\n"
+ "> +\n"
+ "> +\tsize_t pos;\n"
+ "> +\tu8 cmd_buf[IO_BUFFER_LENGTH * 2];\n"
+ "> +\tu8 resp_buf[IO_BUFFER_LENGTH * 2];\n"
+ "> +\tu8 *cmd;\n"
+ "> +\tu8 *resp;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * On the parsed response, we don't store again the toks that are already\n"
+ "> + * stored in the response buffer. Instead, for each token, we just store a\n"
+ "> + * pointer to the position in the buffer where the token starts, and the size\n"
+ "> + * of the token in bytes.\n"
+ "> + */\n"
+ "> +struct opal_resp_tok {\n"
+ "> +\tconst u8 *pos;\n"
+ "> +\tsize_t len;\n"
+ "> +\tenum OPAL_RESPONSE_TOKEN type;\n"
+ "> +\tenum OPAL_ATOM_WIDTH width;\n"
+ "> +\tunion {\n"
+ "> +\t\tu64 u;\n"
+ "> +\t\ts64 s;\n"
+ "> +\t} stored;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * From the response header it's not possible to know how many tokens there are\n"
+ "> + * on the payload. So we hardcode that the maximum will be MAX_TOKS, and later\n"
+ "> + * if we start dealing with messages that have more than that, we can increase\n"
+ "> + * this number. This is done to avoid having to make two passes through the\n"
+ "> + * response, the first one counting how many tokens we have and the second one\n"
+ "> + * actually storing the positions.\n"
+ "> + */\n"
+ "> +struct parsed_resp {\n"
+ "> +\tint num;\n"
+ "> +\tstruct opal_resp_tok toks[MAX_TOKS];\n"
+ "> +};\n"
+ "> +\n"
+ "> +struct opal_dev;\n"
+ "> +\n"
+ "> +typedef void (*opal_cb)(int error, struct opal_dev *dev);\n"
+ "> +\n"
+ "> +typedef int (*opal_step)(struct opal_dev *dev);\n"
+ "> +\n"
+ "> +struct opal_completion {\n"
+ "> +\tstruct completion cmd_completion;\n"
+ "> +\tint completion_status;\n"
+ "> +};\n"
+ "> +\n"
+ "> +struct opal_dev {\n"
+ "> +\tstruct block_device *bdev;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tstruct opal_lock_unlock lkul;\n"
+ "> +\tconst opal_step *funcs;\n"
+ "> +\tvoid **func_data;\n"
+ "> +\tbool resume_from_suspend;\n"
+ "> +\tstruct opal_suspend_unlk *resume_data;\n"
+ "> +\tsize_t num_func_data;\n"
+ "> +\tatomic_t in_use;\n"
+ "> +\tsector_t start;\n"
+ "> +\tsector_t length;\n"
+ "> +\tu8 lr;\n"
+ "> +\tu8 key_type;\n"
+ "> +\tu8 key_name[OPAL_KEY_MAX];\n"
+ "> +\tsize_t key_name_len;\n"
+ "> +\tu8 key[OPAL_KEY_MAX];\n"
+ "> +\tsize_t key_len;\n"
+ "> +\tu16 comID;\n"
+ "> +\tu32 HSN;\n"
+ "> +\tu32 TSN;\n"
+ "> +\tu64 align;\n"
+ "> +\tu64 lowest_lba;\n"
+ "> +\tstruct list_head node;\n"
+ "> +\tchar disk_name[DISK_NAME_LEN];\n"
+ "> +\tint state;\n"
+ "> +\n"
+ "> +\tstruct opal_cmd cmd;\n"
+ "> +\tstruct parsed_resp parsed;\n"
+ "> +\n"
+ "> +\tsize_t prev_d_len;\n"
+ "> +\tvoid *prev_data;\n"
+ "> +\n"
+ "> +\tsec_cb *final_cb;\n"
+ "> +\tvoid *final_cb_data;\n"
+ "> +\topal_step error_cb;\n"
+ "> +\tvoid *error_cb_data;\n"
+ "> +\topal_cb oper_cb;\n"
+ "> +};\n"
+ "> +\n"
+ "> +LIST_HEAD(opal_list);\n"
+ "> +DEFINE_SPINLOCK(list_spinlock);\n"
+ "> +\n"
+ "> +static void print_buffer(const u8 *ptr, u32 length)\n"
+ "> +{\n"
+ "> +#ifdef DEBUG\n"
+ "> +\tprint_hex_dump_bytes(\"OPAL: \", DUMP_PREFIX_OFFSET, ptr, length);\n"
+ "> +\tpr_debug(\"\\n\");\n"
+ "> +#endif\n"
+ "> +}\n"
+ "> +\n"
+ "> +#define TPER_SYNC_SUPPORTED BIT(0)\n"
+ "> +\n"
+ "> +static bool check_tper(const void *data)\n"
+ "> +{\n"
+ "> +\tconst struct d0_tper_features *tper = data;\n"
+ "> +\tu8 flags = tper->supported_features;\n"
+ "> +\n"
+ "> +\tif (!(flags & TPER_SYNC_SUPPORTED)) {\n"
+ "> +\t\tpr_err(\"TPer sync not supported. flags = %d\\n\",\n"
+ "> +\t\t       tper->supported_features);\n"
+ "> +\t\treturn false;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn true;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static bool check_SUM(const void *data)\n"
+ "> +{\n"
+ "> +\tconst struct d0_single_user_mode *sum = data;\n"
+ "> +\tu32 nlo = be32_to_cpu(sum->num_locking_objects);\n"
+ "> +\n"
+ "> +\tif (nlo == 0) {\n"
+ "> +\t\tpr_err(\"Need at least one locking object.\\n\");\n"
+ "> +\t\treturn false;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tpr_debug(\"Number of locking objects: %d\\n\", nlo);\n"
+ "> +\n"
+ "> +\treturn true;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static u16 get_comID_v100(const void *data)\n"
+ "> +{\n"
+ "> +\tconst struct d0_opal_v100 *v100 = data;\n"
+ "> +\n"
+ "> +\treturn be16_to_cpu(v100->baseComID);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static u16 get_comID_v200(const void *data)\n"
+ "> +{\n"
+ "> +\tconst struct d0_opal_v200 *v200 = data;\n"
+ "> +\n"
+ "> +\treturn be16_to_cpu(v200->baseComID);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int __opal_send_cmd(struct opal_suspend_unlk *data, u16 comID,\n"
+ "> +\t\t\t   void *buffer, size_t buflen, sec_cb *cb,\n"
+ "> +\t\t\t   void *cb_data)\n"
+ "> +{\n"
+ "> +\treturn data->ops.send(data->data, comID, TCG_SECP_01, buffer, buflen,\n"
+ "> +\t\t\t     cb, cb_data);\n"
+ "> +}\n"
+ "> +static int _opal_send_cmd(struct block_device *bdev, u16 comID,\n"
+ "> +\t\t\t  void *buffer, size_t buflen,\n"
+ "> +\t\t\t  sec_cb *cb, void *cb_data)\n"
+ "> +{\n"
+ "> +\tconst struct sec_ops *ops = bdev->bd_disk->fops->sec_ops;\n"
+ "> +\n"
+ "> +\treturn ops->send(bdev->bd_disk->private_data, comID,\n"
+ "> +\t\t\t TCG_SECP_01, buffer, buflen,\n"
+ "> +\t\t\t cb, cb_data);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int __opal_recv_cmd(struct opal_suspend_unlk *data, u16 comID,\n"
+ "> +\t\t\t   void *buffer, size_t buflen, sec_cb *cb,\n"
+ "> +\t\t\t   void *cb_data)\n"
+ "> +{\n"
+ "> +\treturn data->ops.recv(data->data, comID, TCG_SECP_01, buffer, buflen,\n"
+ "> +\t\t\t     cb, cb_data);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int _opal_recv_cmd(struct block_device *bdev, u16 comID,\n"
+ "> +\t\t\t  void *buffer, size_t buflen,\n"
+ "> +\t\t\t  sec_cb *cb, void *cb_data)\n"
+ "> +{\n"
+ "> +\tconst struct sec_ops *ops = bdev->bd_disk->fops->sec_ops;\n"
+ "> +\n"
+ "> +\treturn ops->recv(bdev->bd_disk->private_data, comID,\n"
+ "> +\t\t\t TCG_SECP_01, buffer, buflen,\n"
+ "> +\t\t\t cb, cb_data);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void opal_send_cb_cont(int error, void *data)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\tsize_t buflen = IO_BUFFER_LENGTH;\n"
+ "> +\tvoid *buffer = dev->cmd.resp;\n"
+ "> +\tstruct opal_header *hdr = buffer;\n"
+ "> +\n"
+ "> +\tpr_debug(\"%s: Sent OPAL command: error=%d, outstanding=%d, minTransfer=%d\\n\",\n"
+ "> +\t       dev->disk_name, error, hdr->cp.outstandingData,\n"
+ "> +\t       hdr->cp.minTransfer);\n"
+ "> +\n"
+ "> +\tif (error || hdr->cp.outstandingData == 0 ||\n"
+ "> +\t    hdr->cp.minTransfer != 0) {\n"
+ "> +\t\tif (dev->cmd.cb)\n"
+ "> +\t\t\tdev->cmd.cb(error, dev->cmd.cb_data);\n"
+ "> +\t\treturn;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tmemset(buffer, 0, buflen);\n"
+ "> +\tif (dev->resume_from_suspend)\n"
+ "> +\t\t__opal_recv_cmd(dev->resume_data, dev->comID,\n"
+ "> +\t\t\t\tbuffer, buflen, opal_send_cb_cont, dev);\n"
+ "> +\telse\n"
+ "> +\t\t_opal_recv_cmd(dev->bdev, dev->comID, buffer, buflen,\n"
+ "> +\t\t\t       opal_send_cb_cont, dev);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void opal_send_cb(int error, void *data)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\tsize_t buflen = IO_BUFFER_LENGTH;\n"
+ "> +\tvoid *buffer = dev->cmd.resp;\n"
+ "> +\n"
+ "> +\tif (error) {\n"
+ "> +\t\tif (dev->cmd.cb)\n"
+ "> +\t\t\tdev->cmd.cb(error, dev->cmd.cb_data);\n"
+ "> +\t\treturn;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tmemset(buffer, 0, buflen);\n"
+ "> +\tif (dev->resume_from_suspend)\n"
+ "> +\t\t__opal_recv_cmd(dev->resume_data, dev->comID,\n"
+ "> +\t\t\t\tbuffer, buflen, opal_send_cb_cont, dev);\n"
+ "> +\telse\n"
+ "> +\t\t_opal_recv_cmd(dev->bdev, dev->comID, buffer, buflen,\n"
+ "> +\t\t\t       opal_send_cb_cont, dev);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int opal_send_recv(struct opal_dev *dev, sec_cb *cb, void *cb_data)\n"
+ "> +{\n"
+ "> +\tsize_t buflen = IO_BUFFER_LENGTH;\n"
+ "> +\tvoid *buffer = dev->cmd.cmd;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tdev->cmd.cb = cb;\n"
+ "> +\tdev->cmd.cb_data = cb_data;\n"
+ "> +\tif (dev->resume_from_suspend)\n"
+ "> +\t\tret = __opal_send_cmd(dev->resume_data, dev->comID, buffer,\n"
+ "> +\t\t\t\t      buflen, opal_send_cb, dev);\n"
+ "> +\telse\n"
+ "> +\t\tret = _opal_send_cmd(dev->bdev, dev->comID, buffer, buflen,\n"
+ "> +\t\t\t\t     opal_send_cb, dev);\n"
+ "> +\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void check_geometry(struct opal_dev *dev, const void *data)\n"
+ "> +{\n"
+ "> +\tconst struct d0_geometry_features *geo = data;\n"
+ "> +\n"
+ "> +\tdev->align = geo->alignment_granularity;\n"
+ "> +\tdev->lowest_lba = geo->lowest_aligned_lba;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void opal_discovery0_end(int error, void *data)\n"
+ "> +{\n"
+ "> +\tbool foundComID = false, supported = true, single_user = false;\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\tconst struct d0_header *hdr;\n"
+ "> +\tconst u8 *epos, *cpos;\n"
+ "> +\tu16 comID = 0;\n"
+ "> +\n"
+ "> +\tif (error) {\n"
+ "> +\t\tpr_err(\"%s: Sending discovery0 failed\\n\", dev->disk_name);\n"
+ "> +\t\tgoto err_callback;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tepos = dev->cmd.resp;\n"
+ "> +\tcpos = dev->cmd.resp;\n"
+ "> +\thdr = (struct d0_header *)dev->cmd.resp;\n"
+ "> +\n"
+ "> +\tprint_buffer(dev->cmd.resp, be32_to_cpu(hdr->length));\n"
+ "> +\n"
+ "> +\tepos += be32_to_cpu(hdr->length); /* end of buffer */\n"
+ "> +\tcpos += sizeof(*hdr); /* current position on buffer */\n"
+ "> +\n"
+ "> +\twhile (cpos < epos && supported) {\n"
+ "> +\t\tconst struct d0_features *body =\n"
+ "> +\t\t\t(const struct d0_features *)cpos;\n"
+ "> +\n"
+ "> +\t\tswitch (be16_to_cpu(body->code)) {\n"
+ "> +\t\tcase FC_TPER:\n"
+ "> +\t\t\tsupported = check_tper(body->features);\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\tcase FC_SINGLEUSER:\n"
+ "> +\t\t\tsingle_user = check_SUM(body->features);\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\tcase FC_GEOMETRY:\n"
+ "> +\t\t\tcheck_geometry(dev, body);\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\tcase FC_LOCKING:\n"
+ "> +\t\tcase FC_ENTERPRISE:\n"
+ "> +\t\tcase FC_DATASTORE:\n"
+ "> +\t\t\t/* some ignored properties */\n"
+ "> +\t\t\tpr_debug(\"%s: Found OPAL feature description: %d\\n\",\n"
+ "> +\t\t\t\t dev->disk_name, be16_to_cpu(body->code));\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\tcase FC_OPALV100:\n"
+ "> +\t\t\tcomID = get_comID_v100(body->features);\n"
+ "> +\t\t\tfoundComID = true;\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\tcase FC_OPALV200:\n"
+ "> +\t\t\tcomID = get_comID_v200(body->features);\n"
+ "> +\t\t\tfoundComID = true;\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\tdefault:\n"
+ "> +\t\t\tif (be16_to_cpu(body->code) > 0xbfff) {\n"
+ "> +\t\t\t\t/* vendor specific, just ignore */\n"
+ "> +\t\t\t} else {\n"
+ "> +\t\t\t\tpr_warn(\"%s: OPAL Unknown feature: %d\\n\",\n"
+ "> +\t\t\t\t\tdev->disk_name, be16_to_cpu(body->code));\n"
+ "> +\t\t\t}\n"
+ "Small nit, how about:\n"
+ "\n"
+ "case 0xbfff ... 0xffff:\n"
+ "\t/* vendor specific, just ignore */\n"
+ "\tbreak;\n"
+ "default:\n"
+ "\tpr_warn(...\n"
+ "\n"
+ "\n"
+ "\n"
+ "> +\t\t}\n"
+ "> +\t\tcpos += body->length + 4;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (!supported) {\n"
+ "> +\t\tpr_err(\"%s: Device not supported\\n\", dev->disk_name);\n"
+ "> +\t\tgoto err_callback;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (!single_user)\n"
+ "> +\t\tpr_warn(\"%s: Device doesn't support single user mode\\n\",\n"
+ "> +\t\t\tdev->disk_name);\n"
+ "> +\n"
+ "> +\tif (!foundComID) {\n"
+ "> +\t\tpr_warn(\"%s: Could not find OPAL comID for device. OPAL kernel unlocking will be disabled\\n\",\n"
+ "> +\t\t\tdev->disk_name);\n"
+ "> +\t\tgoto err_callback;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->comID = comID;\n"
+ "> +\n"
+ "> +err_callback:\n"
+ "> +\tif (dev->oper_cb)\n"
+ "> +\t\tdev->oper_cb(error, dev);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int opal_discovery0(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tmemset(dev->cmd.resp, 0, IO_BUFFER_LENGTH);\n"
+ "> +\n"
+ "> +\tif (dev->resume_from_suspend)\n"
+ "> +\t\treturn __opal_recv_cmd(dev->resume_data, 0x0001,\n"
+ "> +\t\t\t\t       dev->cmd.resp, IO_BUFFER_LENGTH,\n"
+ "> +\t\t\t\t       opal_discovery0_end, dev);\n"
+ "> +\n"
+ "> +\treturn _opal_recv_cmd(dev->bdev, 0x0001, dev->cmd.resp,\n"
+ "> +\t\t\t      IO_BUFFER_LENGTH, opal_discovery0_end,\n"
+ "> +\t\t\t      dev);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void add_token_u8(struct opal_cmd *cmd, u8 tok)\n"
+ "> +{\n"
+ "> +\tcmd->cmd[cmd->pos++] = tok;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static ssize_t test_and_add_token_u8(struct opal_cmd *cmd, u8 tok)\n"
+ "> +{\n"
+ "> +\tBUILD_BUG_ON(IO_BUFFER_LENGTH >= SIZE_MAX);\n"
+ "> +\n"
+ "> +\tif (cmd->pos >= IO_BUFFER_LENGTH - 1) {\n"
+ "> +\t\tpr_err(\"Error adding u8: end of buffer.\\n\");\n"
+ "> +\t\treturn -ERANGE;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tadd_token_u8(cmd, tok);\n"
+ "> +\n"
+ "> +\treturn 1;\n"
+ "> +}\n"
+ "> +\n"
+ "> +#define TINY_ATOM_DATA_MASK GENMASK(5, 0)\n"
+ "> +#define TINY_ATOM_SIGNED BIT(6)\n"
+ "> +\n"
+ "> +#define SHORT_ATOM_ID BIT(7)\n"
+ "> +#define SHORT_ATOM_BYTESTRING BIT(5)\n"
+ "> +#define SHORT_ATOM_SIGNED BIT(4)\n"
+ "> +#define SHORT_ATOM_LEN_MASK GENMASK(3, 0)\n"
+ "> +\n"
+ "> +static void add_short_atom_header(struct opal_cmd *cmd, bool bytestring,\n"
+ "> +\t\t\t\t  bool has_sign, int len)\n"
+ "> +{\n"
+ "> +\tu8 atom;\n"
+ "> +\n"
+ "> +\tatom = SHORT_ATOM_ID;\n"
+ "> +\tatom |= bytestring ? SHORT_ATOM_BYTESTRING : 0;\n"
+ "> +\tatom |= has_sign ? SHORT_ATOM_SIGNED : 0;\n"
+ "> +\tatom |= len & SHORT_ATOM_LEN_MASK;\n"
+ "> +\n"
+ "> +\tadd_token_u8(cmd, atom);\n"
+ "> +}\n"
+ "> +\n"
+ "> +#define MEDIUM_ATOM_ID (BIT(7) | BIT(6))\n"
+ "> +#define MEDIUM_ATOM_BYTESTRING BIT(4)\n"
+ "> +#define MEDIUM_ATOM_SIGNED BIT(3)\n"
+ "> +#define MEDIUM_ATOM_LEN_MASK GENMASK(2, 0)\n"
+ "> +\n"
+ "> +static void add_medium_atom_header(struct opal_cmd *cmd, bool bytestring,\n"
+ "> +\t\t\t\t   bool has_sign, int len)\n"
+ "> +{\n"
+ "> +\tu8 header0;\n"
+ "> +\n"
+ "> +\theader0 = MEDIUM_ATOM_ID;\n"
+ "> +\theader0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0;\n"
+ "> +\theader0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0;\n"
+ "> +\theader0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK;\n"
+ "> +\tcmd->cmd[cmd->pos++] = header0;\n"
+ "> +\tcmd->cmd[cmd->pos++] = len;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void add_token_u64(struct opal_cmd *cmd, u64 number, size_t len)\n"
+ "> +{\n"
+ "> +\tadd_short_atom_header(cmd, false, false, len);\n"
+ "> +\n"
+ "> +\twhile (len--) {\n"
+ "> +\t\tu8 n = number >> (len * 8);\n"
+ "> +\n"
+ "> +\t\tadd_token_u8(cmd, n);\n"
+ "> +\t}\n"
+ "> +}\n"
+ "> +\n"
+ "> +static ssize_t test_and_add_token_u64(struct opal_cmd *cmd, u64 number)\n"
+ "> +{\n"
+ "> +\tint len;\n"
+ "> +\tint msb;\n"
+ "> +\n"
+ "> +\tif (!(number & ~TINY_ATOM_DATA_MASK))\n"
+ "> +\t\treturn test_and_add_token_u8(cmd, number);\n"
+ "> +\n"
+ "> +\tmsb = fls(number);\n"
+ "> +\tlen = DIV_ROUND_UP(msb, 4);\n"
+ "> +\n"
+ "> +\tif (cmd->pos >= IO_BUFFER_LENGTH - len - 1) {\n"
+ "> +\t\tpr_err(\"Error adding u64: end of buffer.\\n\");\n"
+ "> +\t\treturn -ERANGE;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tadd_token_u64(cmd, number, len);\n"
+ "> +\n"
+ "> +\t/* return length of token plus atom */\n"
+ "> +\treturn len + 1;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void add_token_bytestring(struct opal_cmd *cmd,\n"
+ "> +\t\t\t\t const u8 *bytestring, size_t len)\n"
+ "> +{\n"
+ "> +\tmemcpy(&cmd->cmd[cmd->pos], bytestring, len);\n"
+ "> +\tcmd->pos += len;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static ssize_t test_and_add_token_bytestring(struct opal_cmd *cmd,\n"
+ "> +\t\t\t\t\t     const u8 *bytestring, size_t len)\n"
+ "> +{\n"
+ "> +\tsize_t header_len = 1;\n"
+ "> +\tbool is_short_atom = true;\n"
+ "> +\n"
+ "> +\tif (len & ~SHORT_ATOM_LEN_MASK) {\n"
+ "> +\t\theader_len = 2;\n"
+ "> +\t\tis_short_atom = false;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (cmd->pos >= IO_BUFFER_LENGTH - len - header_len) {\n"
+ "> +\t\tpr_err(\"Error adding bytestring: end of buffer.\\n\");\n"
+ "> +\t\treturn -ERANGE;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (is_short_atom)\n"
+ "> +\t\tadd_short_atom_header(cmd, true, false, len);\n"
+ "> +\telse\n"
+ "> +\t\tadd_medium_atom_header(cmd, true, false, len);\n"
+ "> +\n"
+ "> +\tadd_token_bytestring(cmd, bytestring, len);\n"
+ "> +\n"
+ "> +\treturn header_len + len;\n"
+ "> +}\n"
+ "> +\n"
+ "> +#define LOCKING_RANGE_NON_GLOBAL 0x03\n"
+ "> +\n"
+ "> +static int build_locking_range(u8 *buffer, size_t length, u8 lr)\n"
+ "> +{\n"
+ "> +\tif (length < OPAL_UID_LENGTH)\n"
+ "> +\t\treturn -ERANGE;\n"
+ "> +\n"
+ "> +\tmemcpy(buffer, OPALUID[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);\n"
+ "> +\n"
+ "> +\tif (lr == 0)\n"
+ "> +\t\treturn 0;\n"
+ "> +\tbuffer[5] = LOCKING_RANGE_NON_GLOBAL;\n"
+ "> +\tbuffer[7] = lr;\n"
+ "> +\n"
+ "> +\treturn 0;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int build_locking_user(u8 *buffer, size_t length, u8 lr)\n"
+ "> +{\n"
+ "> +\tif (length < OPAL_UID_LENGTH)\n"
+ "> +\t\treturn -ERANGE;\n"
+ "> +\n"
+ "> +\tmemcpy(buffer, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH);\n"
+ "> +\n"
+ "> +\tbuffer[7] = lr + 1;\n"
+ "> +\n"
+ "> +\treturn 0;\n"
+ "> +}\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * N = number of format specifiers (1-999) to be replicated\n"
+ "> + * c = u8\n"
+ "> + * u = u64\n"
+ "> + * s = bytestring, length\n"
+ "> + *\n"
+ "> + * ret = test_and_add_token_va(cmd, \"c\",\n"
+ "> + *\t\t\t       u8_val1);\n"
+ "> + *\n"
+ "> + * ret = test_and_add_token_va(cmd, \"2c2u\",\n"
+ "> + *\t\t\t       u8_val1, u8_val2, u64_val1, u64_val2);\n"
+ "> + *\n"
+ "> + * ret = test_and_add_token_va(cmd, \"3s\",\n"
+ "> + *\t\t\t       bytestring1, length1,\n"
+ "> + *\t\t\t       bytestring2, length2,\n"
+ "> + *\t\t\t       bytestring3, length3);\n"
+ "> + */\n"
+ "> +static int test_and_add_token_va(struct opal_cmd *cmd,\n"
+ "> +\t\t\t\t const char *fmt, ...)\n"
+ "> +{\n"
+ "> +\tconst u8 *it = fmt, *tmp;\n"
+ "> +\tint ret, num = 1, sum = 0;\n"
+ "> +\tva_list ap;\n"
+ "> +\n"
+ "> +\tva_start(ap, fmt);\n"
+ "> +\n"
+ "> +\twhile (*it != '\\0') {\n"
+ "> +\t\tu64 tok64 = 0;\n"
+ "> +\t\tu8 tok, *bstr;\n"
+ "> +\t\tsize_t len;\n"
+ "> +\n"
+ "> +\t\tret = 0;\n"
+ "> +\n"
+ "> +\t\tswitch (*it) {\n"
+ "> +\t\tcase '1' ... '9':\n"
+ "> +\t\t\ttmp = it;\n"
+ "> +\t\t\tnum = 0;\n"
+ "> +\t\t\twhile (*tmp >= '0' && *tmp <= '9')\n"
+ "> +\t\t\t\tnum = num * 10 + (*tmp++ - '0');\n"
+ "> +\t\t\tit = tmp;\n"
+ "> +\t\t\tcontinue;\n"
+ "> +\t\tcase 'c':\n"
+ "> +\t\t\twhile (num--) {\n"
+ "> +\t\t\t\ttok = va_arg(ap, unsigned int);\n"
+ "> +\t\t\t\tret = test_and_add_token_u8(cmd, tok);\n"
+ "> +\t\t\t\tif (ret < 0)\n"
+ "> +\t\t\t\t\tgoto err;\n"
+ "> +\t\t\t}\n"
+ "> +\t\t\tnum = 1;\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\tcase 'u':\n"
+ "> +\t\t\twhile (num--) {\n"
+ "> +\t\t\t\ttok64 = va_arg(ap, u64);\n"
+ "> +\t\t\t\tret = test_and_add_token_u64(cmd, tok64);\n"
+ "> +\t\t\t\tif (ret < 0)\n"
+ "> +\t\t\t\t\tgoto err;\n"
+ "> +\t\t\t}\n"
+ "> +\t\t\tnum = 1;\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\tcase 's':\n"
+ "> +\t\t\twhile (num--) {\n"
+ "> +\t\t\t\tbstr = va_arg(ap, u8 *);\n"
+ "> +\t\t\t\tlen = va_arg(ap, size_t);\n"
+ "> +\t\t\t\tret = test_and_add_token_bytestring(cmd, bstr,\n"
+ "> +\t\t\t\t\t\t\t\t    len);\n"
+ "> +\t\t\t\tif (ret < 0)\n"
+ "> +\t\t\t\t\tgoto err;\n"
+ "> +\t\t\t}\n"
+ "> +\t\t\tnum = 1;\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\tcase ' ':\n"
+ "> +\t\tcase '\\t':\n"
+ "> +\t\t\t/* ignored */\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\tdefault:\n"
+ "> +\t\t\tpr_warn(\"Unrecognized type.\\n\");\n"
+ "> +\t\t}\n"
+ "> +\n"
+ "> +\t\tit++;\n"
+ "> +\t\tsum += ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tva_end(ap);\n"
+ "> +\n"
+ "> +\treturn sum;\n"
+ "> +\n"
+ "> + err:\n"
+ "> +\tpr_err(\"Token failed to be added.\\n\");\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void set_comID(struct opal_cmd *cmd, u16 comID)\n"
+ "> +{\n"
+ "> +\tstruct opal_header *hdr = (struct opal_header *)cmd->cmd;\n"
+ "> +\n"
+ "> +\thdr->cp.extendedComID[0] = comID >> 8;\n"
+ "> +\thdr->cp.extendedComID[1] = comID;\n"
+ "> +\thdr->cp.extendedComID[2] = 0;\n"
+ "> +\thdr->cp.extendedComID[3] = 0;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int cmd_finalize(struct opal_cmd *cmd, u32 hsn, u32 tsn)\n"
+ "> +{\n"
+ "> +\tstruct opal_header *hdr;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"6c\",\n"
+ "> +\t\t\t\t    OPAL_ENDOFDATA, OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    0, 0, 0, OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"Error finalizing command.\\n\");\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\thdr = (struct opal_header *) cmd->cmd;\n"
+ "> +\n"
+ "> +\thdr->pkt.TSN = cpu_to_be32(tsn);\n"
+ "> +\thdr->pkt.HSN = cpu_to_be32(hsn);\n"
+ "> +\n"
+ "> +\thdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr));\n"
+ "> +\twhile (cmd->pos % 4) {\n"
+ "> +\t\tif (cmd->pos >= IO_BUFFER_LENGTH) {\n"
+ "> +\t\t\tpr_err(\"Error: Buffer overrun\\n\");\n"
+ "> +\t\t\treturn -ERANGE;\n"
+ "> +\t\t}\n"
+ "> +\t\tcmd->cmd[cmd->pos++] = 0;\n"
+ "> +\t}\n"
+ "> +\thdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) -\n"
+ "> +\t\t\t\t      sizeof(hdr->pkt));\n"
+ "> +\thdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp));\n"
+ "> +\n"
+ "> +\treturn 0;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static enum OPAL_RESPONSE_TOKEN token_type(const struct parsed_resp *resp,\n"
+ "> +\t\t\t\t\t   int n)\n"
+ "> +{\n"
+ "> +\tconst struct opal_resp_tok *tok;\n"
+ "> +\n"
+ "> +\tif (n >= resp->num) {\n"
+ "> +\t\tpr_err(\"Token number doesn't exist: %d, resp: %d\\n\",\n"
+ "> +\t\t       n, resp->num);\n"
+ "> +\t\treturn OPAL_DTA_TOKENID_INVALID;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\ttok = &resp->toks[n];\n"
+ "> +\tif (tok->len == 0) {\n"
+ "> +\t\tpr_err(\"Token length must be non-zero\\n\");\n"
+ "> +\t\treturn OPAL_DTA_TOKENID_INVALID;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn tok->type;\n"
+ "> +}\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * This function returns 0 in case of invalid token. One should call\n"
+ "> + * token_type() first to find out if the token is valid or not.\n"
+ "> + */\n"
+ "> +static enum OPAL_TOKEN response_get_token(const struct parsed_resp *resp,\n"
+ "> +\t\t\t\t\t  int n)\n"
+ "> +{\n"
+ "> +\tconst struct opal_resp_tok *tok;\n"
+ "> +\n"
+ "> +\tif (n >= resp->num) {\n"
+ "> +\t\tpr_err(\"Token number doesn't exist: %d, resp: %d\\n\",\n"
+ "> +\t\t       n, resp->num);\n"
+ "> +\t\treturn 0;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\ttok = &resp->toks[n];\n"
+ "> +\tif (tok->len == 0) {\n"
+ "> +\t\tpr_err(\"Token length must be non-zero\\n\");\n"
+ "> +\t\treturn 0;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn tok->pos[0];\n"
+ "> +}\n"
+ "> +\n"
+ "> +static size_t response_parse_tiny(struct opal_resp_tok *tok,\n"
+ "> +\t\t\t\t  const u8 *pos)\n"
+ "> +{\n"
+ "> +\ttok->pos = pos;\n"
+ "> +\ttok->len = 1;\n"
+ "> +\ttok->width = OPAL_WIDTH_TINY;\n"
+ "> +\n"
+ "> +\tif (pos[0] & TINY_ATOM_SIGNED) {\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_SINT;\n"
+ "> +\t} else {\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_UINT;\n"
+ "> +\t\ttok->stored.u = pos[0] & 0x3f;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn tok->len;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static size_t response_parse_short(struct opal_resp_tok *tok,\n"
+ "> +\t\t\t\t   const u8 *pos)\n"
+ "> +{\n"
+ "> +\ttok->pos = pos;\n"
+ "> +\ttok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1;\n"
+ "> +\ttok->width = OPAL_WIDTH_SHORT;\n"
+ "> +\n"
+ "> +\tif (pos[0] & SHORT_ATOM_BYTESTRING) {\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_BYTESTRING;\n"
+ "> +\t} else if (pos[0] & SHORT_ATOM_SIGNED) {\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_SINT;\n"
+ "> +\t} else {\n"
+ "> +\t\tu64 u_integer = 0;\n"
+ "> +\t\tint i, b = 0;\n"
+ "> +\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_UINT;\n"
+ "> +\t\tif (tok->len > 9)\n"
+ "Should this be len > 8 or len >= 9 ?\n"
+ "\n"
+ "> +\t\t\tpr_warn(\"uint64 with more than 8 bytes\\n\");\n"
+ "> +\t\tfor (i = tok->len - 1; i > 0; i--) {\n"
+ "> +\t\t\tu_integer |= ((u64)pos[i] << (8 * b));\n"
+ "> +\t\t\tb++;\n"
+ "> +\t\t}\n"
+ "It doesn't look particularly safe to keep using this driver on a drive\n"
+ "if it returns a len > 8. But the specs do allow 16-byte data in a short\n"
+ "atom, so maybe we should bail on allowing the driver to manage the\n"
+ "drive, or change the types to some 16-byte type?\n"
+ "\n"
+ "> +\t\ttok->stored.u = u_integer;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn tok->len;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static size_t response_parse_medium(struct opal_resp_tok *tok,\n"
+ "> +\t\t\t\t    const u8 *pos)\n"
+ "> +{\n"
+ "> +\ttok->pos = pos;\n"
+ "> +\ttok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2;\n"
+ "> +\ttok->width = OPAL_WIDTH_MEDIUM;\n"
+ "> +\n"
+ "> +\tif (pos[0] & MEDIUM_ATOM_BYTESTRING)\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_BYTESTRING;\n"
+ "> +\telse if (pos[0] & MEDIUM_ATOM_SIGNED)\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_SINT;\n"
+ "> +\telse\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_UINT;\n"
+ "> +\n"
+ "> +\treturn tok->len;\n"
+ "> +}\n"
+ "> +\n"
+ "> +#define LONG_ATOM_ID (BIT(7) | BIT(6) | BIT(5))\n"
+ "> +#define LONG_ATOM_BYTESTRING BIT(1)\n"
+ "> +#define LONG_ATOM_SIGNED BIT(0)\n"
+ "> +static size_t response_parse_long(struct opal_resp_tok *tok,\n"
+ "> +\t\t\t\t  const u8 *pos)\n"
+ "> +{\n"
+ "> +\ttok->pos = pos;\n"
+ "> +\ttok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4;\n"
+ "> +\ttok->width = OPAL_WIDTH_LONG;\n"
+ "> +\n"
+ "> +\tif (pos[0] & LONG_ATOM_BYTESTRING)\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_BYTESTRING;\n"
+ "> +\telse if (pos[0] & LONG_ATOM_SIGNED)\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_SINT;\n"
+ "> +\telse\n"
+ "> +\t\ttok->type = OPAL_DTA_TOKENID_UINT;\n"
+ "> +\n"
+ "> +\treturn tok->len;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static size_t response_parse_token(struct opal_resp_tok *tok,\n"
+ "> +\t\t\t\t   const u8 *pos)\n"
+ "> +{\n"
+ "> +\ttok->pos = pos;\n"
+ "> +\ttok->len = 1;\n"
+ "> +\ttok->type = OPAL_DTA_TOKENID_TOKEN;\n"
+ "> +\ttok->width = OPAL_WIDTH_TOKEN;\n"
+ "> +\n"
+ "> +\treturn tok->len;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int response_parse(const u8 *buf, size_t length,\n"
+ "> +\t\t\t  struct parsed_resp *resp)\n"
+ "> +{\n"
+ "> +\tconst struct opal_header *hdr;\n"
+ "> +\tstruct opal_resp_tok *iter;\n"
+ "> +\tint ret, num_entries = 0;\n"
+ "> +\tu32 cpos = 0, total;\n"
+ "> +\tsize_t token_length;\n"
+ "> +\tconst u8 *pos;\n"
+ "> +\n"
+ "> +\tif (!buf)\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\tif (!resp)\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\thdr = (struct opal_header *)buf;\n"
+ "> +\tpos = buf;\n"
+ "> +\tpos += sizeof(*hdr);\n"
+ "> +\n"
+ "> +\tpr_debug(\"Response size: cp: %d, pkt: %d, subpkt: %d\\n\",\n"
+ "> +\t\t be32_to_cpu(hdr->cp.length),\n"
+ "> +\t\t be32_to_cpu(hdr->pkt.length),\n"
+ "> +\t\t be32_to_cpu(hdr->subpkt.length));\n"
+ "> +\n"
+ "> +\tif ((hdr->cp.length == 0)\n"
+ "> +\t    || (hdr->pkt.length == 0)\n"
+ "> +\t    || (hdr->subpkt.length == 0)) {\n"
+ "> +\t\tpr_err(\"Bad header length. cp: %d, pkt: %d, subpkt: %d\\n\",\n"
+ "> +\t\t       be32_to_cpu(hdr->cp.length),\n"
+ "> +\t\t       be32_to_cpu(hdr->pkt.length),\n"
+ "> +\t\t       be32_to_cpu(hdr->subpkt.length));\n"
+ "> +\t\tprint_buffer(pos, sizeof(*hdr));\n"
+ "> +\t\tret = -EINVAL;\n"
+ "> +\t\tgoto err;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (pos > buf + length) {\n"
+ "> +\t\tret = -EFAULT;\n"
+ "> +\t\tgoto err;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\titer = resp->toks;\n"
+ "> +\ttotal = be32_to_cpu(hdr->subpkt.length);\n"
+ "> +\tprint_buffer(pos, total);\n"
+ "> +\twhile (cpos < total) {\n"
+ "> +\t\tif (!(pos[0] & 0x80)) /* tiny atom */\n"
+ "> +\t\t\ttoken_length = response_parse_tiny(iter, pos);\n"
+ "> +\t\telse if (!(pos[0] & 0x40)) /* short atom */\n"
+ "> +\t\t\ttoken_length = response_parse_short(iter, pos);\n"
+ "> +\t\telse if (!(pos[0] & 0x20)) /* medium atom */\n"
+ "> +\t\t\ttoken_length = response_parse_medium(iter, pos);\n"
+ "> +\t\telse if (!(pos[0] & 0x10)) /* long atom */\n"
+ "> +\t\t\ttoken_length = response_parse_long(iter, pos);\n"
+ "> +\t\telse /* TOKEN */\n"
+ "> +\t\t\ttoken_length = response_parse_token(iter, pos);\n"
+ "> +\n"
+ "> +\t\tpos += token_length;\n"
+ "> +\t\tcpos += token_length;\n"
+ "> +\t\titer++;\n"
+ "> +\t\tnum_entries++;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (num_entries == 0) {\n"
+ "> +\t\tpr_err(\"Couldn't parse response.\\n\");\n"
+ "> +\t\tret = -EINVAL;\n"
+ "> +\t\tgoto err;\n"
+ "> +\t}\n"
+ "> +\tresp->num = num_entries;\n"
+ "> +\n"
+ "> +\treturn 0;\n"
+ "> +err:\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static size_t response_get_string(const struct parsed_resp *resp, int n,\n"
+ "> +\t\t\t\t  const char **store)\n"
+ "> +{\n"
+ "> +\t*store = NULL;\n"
+ "> +\tif (!resp) {\n"
+ "> +\t\tpr_err(\"Response is NULL\\n\");\n"
+ "> +\t\treturn 0;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (n > resp->num) {\n"
+ "> +\t\tpr_err(\"Response has %d tokens. Can't access %d\\n\",\n"
+ "> +\t\t       resp->num, n);\n"
+ "> +\t\treturn 0;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (resp->toks[n].type != OPAL_DTA_TOKENID_BYTESTRING) {\n"
+ "> +\t\tpr_err(\"Token is not a byte string!\\n\");\n"
+ "> +\t\treturn 0;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\t*store = resp->toks[n].pos + 1;\n"
+ "> +\treturn resp->toks[n].len - 1;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static u64 response_get_u64(const struct parsed_resp *resp, int n)\n"
+ "> +{\n"
+ "> +\tif (!resp) {\n"
+ "> +\t\tpr_err(\"Response is NULL\\n\");\n"
+ "> +\t\treturn 0;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (n > resp->num) {\n"
+ "> +\t\tpr_err(\"Response has %d tokens. Can't access %d\\n\",\n"
+ "> +\t\t       resp->num, n);\n"
+ "> +\t\treturn 0;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (resp->toks[n].type != OPAL_DTA_TOKENID_UINT) {\n"
+ "> +\t\tpr_err(\"Token is not unsigned it: %d\\n\",\n"
+ "> +\t\t       resp->toks[n].type);\n"
+ "> +\t\treturn 0;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (!((resp->toks[n].width == OPAL_WIDTH_TINY) ||\n"
+ "> +\t      (resp->toks[n].width == OPAL_WIDTH_SHORT))) {\n"
+ "> +\t\tpr_err(\"Atom is not short or tiny: %d\\n\",\n"
+ "> +\t\t       resp->toks[n].width);\n"
+ "> +\t\treturn 0;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn resp->toks[n].stored.u;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static u8 response_status(const struct parsed_resp *resp)\n"
+ "> +{\n"
+ "> +\tif ((token_type(resp, 0) == OPAL_DTA_TOKENID_TOKEN)\n"
+ "> +\t    && (response_get_token(resp, 0) == OPAL_ENDOFSESSION)) {\n"
+ "> +\t\treturn 0;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (resp->num < 5)\n"
+ "> +\t\treturn DTAERROR_NO_METHOD_STATUS;\n"
+ "> +\n"
+ "> +\tif ((token_type(resp, resp->num - 1) != OPAL_DTA_TOKENID_TOKEN) ||\n"
+ "> +\t    (token_type(resp, resp->num - 5) != OPAL_DTA_TOKENID_TOKEN) ||\n"
+ "> +\t    (response_get_token(resp, resp->num - 1) != OPAL_ENDLIST) ||\n"
+ "> +\t    (response_get_token(resp, resp->num - 5) != OPAL_STARTLIST))\n"
+ "> +\t\treturn DTAERROR_NO_METHOD_STATUS;\n"
+ "> +\n"
+ "> +\treturn response_get_u64(resp, resp->num - 4);\n"
+ "> +}\n"
+ "> +\n"
+ "> +/* Parses and checks for errors */\n"
+ "> +static int parse_and_check_status(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint error;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tprint_buffer(cmd->cmd, cmd->pos);\n"
+ "> +\n"
+ "> +\terror = response_parse(cmd->resp, IO_BUFFER_LENGTH, &dev->parsed);\n"
+ "> +\tif (error) {\n"
+ "> +\t\tpr_err(\"%s: Couldn't parse response.\\n\", dev->disk_name);\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\terror = response_status(&dev->parsed);\n"
+ "> +\tif (error)\n"
+ "> +\t\tpr_err(\"%s: Response Status: %d\\n\", dev->disk_name,\n"
+ "> +\t\t       error);\n"
+ "> +\n"
+ "> + err_return:\n"
+ "> +\treturn error;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void clear_opal_cmd(struct opal_cmd *cmd)\n"
+ "> +{\n"
+ "> +\tcmd->pos = sizeof(struct opal_header);\n"
+ "> +\tmemset(cmd->cmd, 0, IO_BUFFER_LENGTH);\n"
+ "> +\tcmd->cb = NULL;\n"
+ "> +\tcmd->cb_data = NULL;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void start_opal_session_cont(int error, void *data)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\tu32 HSN, TSN;\n"
+ "> +\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\n"
+ "> +\terror = parse_and_check_status(dev);\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\n"
+ "> +\tHSN = response_get_u64(&dev->parsed, 4);\n"
+ "> +\tTSN = response_get_u64(&dev->parsed, 5);\n"
+ "> +\n"
+ "> +\tif (HSN == 0 && TSN == 0) {\n"
+ "> +\t\tpr_err(\"%s: Couldn't authenticate session\\n\", dev->disk_name);\n"
+ "> +\t\terror = -EPERM;\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->HSN = HSN;\n"
+ "> +\tdev->TSN = TSN;\n"
+ "> +\n"
+ "> +err_return:\n"
+ "> +\tif (dev->oper_cb)\n"
+ "> +\t\tdev->oper_cb(error, dev);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int get_opal_key(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tstruct key *ukey = NULL;\n"
+ "> +\tconst u8 *tmpkey = NULL;\n"
+ "> +\tsize_t tmplen;\n"
+ "> +\tint ret = 0;\n"
+ "> +\n"
+ "> +\tif (dev->key_type == OPAL_KEY_PLAIN) {\n"
+ "> +\t\ttmpkey = dev->key_name;\n"
+ "> +\t\ttmplen = dev->key_name_len;\n"
+ "> +\t} else if (dev->key_type == OPAL_KEY_KEYRING) {\n"
+ "> +\t\tukey = request_user_key(dev->key_name, &tmpkey, &tmplen);\n"
+ "> +\t\tif (IS_ERR(ukey)) {\n"
+ "> +\t\t\tpr_err(\"%s: Can't retrieve key: %ld\\n\", dev->disk_name,\n"
+ "> +\t\t\t       PTR_ERR(ukey));\n"
+ "> +\t\t\treturn PTR_ERR(ukey);\n"
+ "> +\t\t}\n"
+ "> +\t} else {\n"
+ "> +\t\tpr_err(\"Requested invalid key type: %d\\n\", dev->key_type);\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (tmplen > OPAL_KEY_MAX) {\n"
+ "> +\t\tpr_err(\"Requested key with invalid size: %zd\\n\", tmplen);\n"
+ "> +\t\tret = -EINVAL;\n"
+ "> +\t\tgoto err_exit;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->key_len = tmplen;\n"
+ "> +\tif (!memcpy(dev->key, tmpkey, tmplen)) {\n"
+ "> +\t\tpr_err(\"Error when copying key\");\n"
+ "> +\t\tret = -EFAULT;\n"
+ "> +\t\tgoto err_exit;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +err_exit:\n"
+ "> +\tkey_put(ukey);\n"
+ "> +\n"
+ "> +\treturn 0;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void clean_opal_key(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tmemset(dev->key, 0, OPAL_KEY_MAX);\n"
+ "> +\tdev->key_len = 0;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static inline void clean_function_data(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\t\tdev->func_data = NULL;\n"
+ "> +\t\tdev->num_func_data = 0;\n"
+ "> +}\n"
+ "> +\n"
+ "> +/* This is a generic continue fn.\n"
+ "> + * We use this when we don't care about the response data\n"
+ "> + * and simply want to check the status and continue.\n"
+ "> + */\n"
+ "> +static void generic_cont(int error, void *data)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\n"
+ "> +\terror = parse_and_check_status(dev);\n"
+ "> +\n"
+ "> + err_return:\n"
+ "> +\tif (dev->oper_cb)\n"
+ "> +\t\tdev->oper_cb(error, dev);\n"
+ "> +}\n"
+ "\n"
+ "How about:\n"
+ "\n"
+ "static void generic_cont(int error, void *data)\n"
+ "{\n"
+ "\tstruct opal_dev *dev = data;\n"
+ "\n"
+ "\tif (!error)\n"
+ "\t\terror = parse_and_check_status(dev);\n"
+ "\n"
+ "\tif (dev->oper_cb)\n"
+ "\t\tdev->oper_cb(error, dev);\n"
+ "}\n"
+ "\n"
+ "> +\n"
+ "> +static void end_session_cont(int error, void *data)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\n"
+ "> +\tdev->HSN = 0;\n"
+ "> +\tdev->TSN = 0;\n"
+ "> +\tgeneric_cont(error, data);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int finalize_and_send(struct opal_dev *dev, struct opal_cmd *cmd,\n"
+ "> +\t\t\t     sec_cb cont)\n"
+ "> +{\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tret = cmd_finalize(cmd, dev->HSN, dev->TSN);\n"
+ "> +\tif (ret) {\n"
+ "> +\t\tpr_err(\"%s: Error finalizing command buffer: %d\\n\",\n"
+ "> +\t\t       dev->disk_name, ret);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tprint_buffer(cmd->cmd, cmd->pos);\n"
+ "> +\n"
+ "> +\tret = opal_send_recv(dev, cont, dev);\n"
+ "> +\tif (ret)\n"
+ "> +\t\tpr_err(\"%s: Error running command: %d\\n\",\n"
+ "> +\t\t       dev->disk_name, ret);\n"
+ "> +\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int wait_for_cmd_completion(struct opal_completion *completion)\n"
+ "> +{\n"
+ "> +\twait_for_completion_interruptible(&completion->cmd_completion);\n"
+ "> +\treturn completion->completion_status;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int gen_key(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method;\n"
+ "> +\tu8 uid[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tmemcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len));\n"
+ "> +\tmethod = OPALMETHOD[OPAL_GENKEY];\n"
+ "> +\tkfree(dev->prev_data);\n"
+ "> +\tdev->prev_data = NULL;\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 2c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building gen key command\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void get_active_key_cont(int error, void *data)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\tconst char *activekey;\n"
+ "> +\tsize_t keylen;\n"
+ "> +\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\n"
+ "> +\terror = parse_and_check_status(dev);\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\tkeylen = response_get_string(&dev->parsed, 4, &activekey);\n"
+ "> +\tif (!activekey) {\n"
+ "> +\t\tpr_err(\"%s: Couldn't extract the Activekey from the response\\n\",\n"
+ "> +\t\t       __func__);\n"
+ "> +\t\terror = 0x0A;\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\t}\n"
+ "> +\tdev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL);\n"
+ "> +\n"
+ "> +\tif (!dev->prev_data)\n"
+ "> +\t\terror = -ENOMEM;\n"
+ "> +\n"
+ "> +\tdev->prev_d_len = keylen;\n"
+ "> +\n"
+ "> +err_return:\n"
+ "> +\tif (dev->oper_cb)\n"
+ "> +\t\tdev->oper_cb(error, dev);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int get_active_key(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method;\n"
+ "> +\tu8 uid[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_GET];\n"
+ "> +\n"
+ "> +\tret = build_locking_range(uid, sizeof(uid), dev->lr);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Can't build locking range\\n\", dev->disk_name);\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 6c 4c 2c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03, /* startCloumn */\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_10, /* ActiveKey */\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_04, /* endColumn */\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_10, /* ActiveKey */\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building get active key command\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, get_active_key_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int setup_locking_range(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method;\n"
+ "> +\tu8 uid[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tstruct opal_user_lr_setup *setup;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_SET];\n"
+ "> +\tret = build_locking_range(uid, sizeof(uid), dev->lr);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Can't build locking range\\n\", dev->disk_name);\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\tsetup = dev->func_data[dev->state - 1];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s  4c 2cuc 2cuc 2cuc 2cu 4c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_VALUES,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03, /* Range Start */\n"
+ "> +\t\t\t\t    setup->range_start,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_04, /* Range Length */\n"
+ "> +\t\t\t\t    setup->range_length,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_05, /* ReadLockEnabled */\n"
+ "> +\t\t\t\t    !!setup->RLE,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_06, /* WriteLockEnabled */\n"
+ "> +\t\t\t\t    !!setup->WLE,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building Setup Locking range command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int start_adminsp_opal_session(struct opal_dev *dev,\n"
+ "> +\t\t\t\t      enum OPAL_UID auth,\n"
+ "> +\t\t\t\t      const char *key,\n"
+ "> +\t\t\t\t      u8 key_len)\n"
+ "> +{\n"
+ "> +\tconst u8 *method, *smuid, *admin_sp, *hsa;\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tu32 HSN;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tif (key == NULL && auth != OPAL_ANYBODY_UID) {\n"
+ "> +\t\tpr_err(\"%s: Attempted to open ADMIN_SP Session without a Host\" \\\n"
+ "> +\t\t       \"Challenge, and not as the Anybody UID\\n\", __func__);\n"
+ "> +\t\treturn 1;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\tHSN = 0x41;\n"
+ "> +\n"
+ "> +\tsmuid = OPALUID[OPAL_SMUID_UID];\n"
+ "> +\tmethod = OPALMETHOD[OPAL_STARTSESSION];\n"
+ "> +\tadmin_sp = OPALUID[OPAL_ADMINSP_UID];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s cusc\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    smuid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    HSN,\n"
+ "> +\t\t\t\t    admin_sp, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_01);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building start adminsp session command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tswitch (auth) {\n"
+ "> +\tcase OPAL_ANYBODY_UID:\n"
+ "> +\t\t/* nothing left to do for anybody, just end and finalize */\n"
+ "> +\t\tret = test_and_add_token_va(cmd, \"c\",\n"
+ "> +\t\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\t\tbreak;\n"
+ "> +\tcase OPAL_SID_UID:\n"
+ "> +\t\thsa = OPALUID[OPAL_SID_UID];\n"
+ "> +\t\tret = test_and_add_token_va(cmd, \"2c s 3c s 2c\",\n"
+ "> +\t\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t\t    OPAL_TINY_UINT_00, /* HostChallenge */\n"
+ "> +\t\t\t\t\t    key, key_len,\n"
+ "> +\t\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t\t    OPAL_TINY_UINT_03, /* HostSignAuth */\n"
+ "> +\t\t\t\t\t    hsa, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\t\tbreak;\n"
+ "> +\tdefault:\n"
+ "> +\t\tpr_err(\"Cannot start Admin SP session with auth %d\\n\", auth);\n"
+ "> +\t\treturn 1;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building start adminsp session command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, start_opal_session_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int start_anybodyASP_opal_session(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\treturn start_adminsp_opal_session(dev, OPAL_ANYBODY_UID, NULL, 0);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int start_SIDASP_opal_session(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tint ret;\n"
+ "> +\tconst u8 *key = dev->prev_data;\n"
+ "> +\n"
+ "> +\tif (!key)\n"
+ "> +\t\tret = start_adminsp_opal_session(dev, OPAL_SID_UID, dev->key,\n"
+ "> +\t\t\t\t\t\t dev->key_len);\n"
+ "> +\telse {\n"
+ "> +\t\tret = start_adminsp_opal_session(dev, OPAL_SID_UID, key,\n"
+ "> +\t\t\t\t\t\t dev->prev_d_len);\n"
+ "> +\t\tkfree(key);\n"
+ "> +\t\tdev->prev_data = NULL;\n"
+ "> +\t}\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int start_lockingsp_opal_session(struct opal_dev *dev,\n"
+ "> +\t\t\t\t\tenum OPAL_UID auth, const u8 *key,\n"
+ "> +\t\t\t\t\tu8 key_len)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tconst u8 *method, *smuid, *locking_sp, *hsa;\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tsize_t klen = key_len;\n"
+ "> +\tu32 HSN;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tif (key == NULL) {\n"
+ "> +\t\tpr_err(\"Cannot start Locking SP session without a key\\n\");\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\tHSN = 0x41;\n"
+ "> +\n"
+ "> +\tsmuid = OPALUID[OPAL_SMUID_UID];\n"
+ "> +\tmethod = OPALMETHOD[OPAL_STARTSESSION];\n"
+ "> +\tlocking_sp = OPALUID[OPAL_LOCKINGSP_UID];\n"
+ "> +\thsa = OPALUID[auth];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s cusc 2csc 2csc c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    smuid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    HSN,\n"
+ "> +\t\t\t\t    locking_sp, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_01,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_00, /* HostChallenge */\n"
+ "> +\t\t\t\t    key, klen,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03, /* Host Sign Authority */\n"
+ "> +\t\t\t\t    hsa, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building start adminsp session command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\treturn finalize_and_send(dev, cmd, start_opal_session_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static inline int start_admin1LSP_opal_session(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\treturn start_lockingsp_opal_session(dev, OPAL_ADMIN1_UID,\n"
+ "> +\t\t\t\t\t    dev->key, dev->key_len);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int start_auth_opal_session(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method, *smuid, *locking_sp;\n"
+ "> +\tu8 lk_ul_user[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tu32 HSN;\n"
+ "> +\tint ret;\n"
+ "> +\tstruct opal_user_info *uinfo;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tHSN = 0x41;\n"
+ "Can we #define this; it's used a few other places and is magicky\n"
+ "\n"
+ "> +\n"
+ "> +\tuinfo = dev->func_data[dev->state - 1];\n"
+ "> +\n"
+ "> +\tsmuid = OPALUID[OPAL_SMUID_UID];\n"
+ "> +\tmethod = OPALMETHOD[OPAL_STARTSESSION];\n"
+ "> +\tlocking_sp = OPALUID[OPAL_LOCKINGSP_UID];\n"
+ "> +\n"
+ "> +\tif (uinfo->SUM) {\n"
+ "> +\t\tret = build_locking_user(lk_ul_user, sizeof(lk_ul_user),\n"
+ "> +\t\t\t\t\t dev->lr);\n"
+ "> +\t\tif (ret < 0) {\n"
+ "> +\t\t\tpr_err(\"%s: Can't build locking user\\n\",\n"
+ "> +\t\t\t       dev->disk_name);\n"
+ "> +\t\t\treturn ret;\n"
+ "> +\t\t}\n"
+ "> +\t} else if (uinfo->who != OPAL_ADMIN1 && !uinfo->SUM) {\n"
+ "> +\t\tret = build_locking_user(lk_ul_user, sizeof(lk_ul_user),\n"
+ "> +\t\t\t\t\t uinfo->who - 1);\n"
+ "> +\t\tif (ret < 0) {\n"
+ "> +\t\t\tpr_err(\"%s: Can't build locking user\\n\",\n"
+ "> +\t\t\t       dev->disk_name);\n"
+ "> +\t\t\treturn ret;\n"
+ "> +\t\t}\n"
+ "> +\t} else\n"
+ "> +\t\tmemcpy(lk_ul_user, OPALUID[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);\n"
+ "> +\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s cus3cs3c s 2c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    smuid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    HSN,\n"
+ "> +\t\t\t\t    locking_sp, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_01,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_00,\n"
+ "> +\t\t\t\t    dev->key, dev->key_len,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03,\n"
+ "> +\n"
+ "> +\t\t\t\t    lk_ul_user, OPAL_UID_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building STARTSESSION command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, start_opal_session_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int revert_tper(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method, *smuid;\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tsmuid = OPALUID[OPAL_ADMINSP_UID];\n"
+ "> +\tmethod = OPALMETHOD[OPAL_REVERT];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 2c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    smuid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building REVERT TPER command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int internal_activate_user(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method;\n"
+ "> +\tu8 uid[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\tstruct opal_activate_user *act;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tact = dev->func_data[dev->state - 1];\n"
+ "> +\n"
+ "> +\tmemcpy(uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH);\n"
+ "> +\tuid[7] = act->who.who;\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_SET];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 3c c 4c 3c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_01, /* Values */\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_05, /* Enabled */\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_01, /* True */\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building Activate UserN command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int erase_locking_range(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method;\n"
+ "> +\tu8 uid[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_ERASE];\n"
+ "> +\n"
+ "> +\tif (build_locking_range(uid, sizeof(uid), dev->lr) < 0) {\n"
+ "> +\t\tpr_err(\"%s: Can't build locking range\\n\", dev->disk_name);\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 2c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building Erase Locking Range Cmmand.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int set_mbr_done(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method, *uid;\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tu8 mbr_done_tf = *(u8 *)dev->func_data[dev->state - 1];\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_SET];\n"
+ "> +\tuid = OPALUID[OPAL_MBRCONTROL];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 3c 6c 2c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_VALUES,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_02, /* Done */\n"
+ "> +\t\t\t\t    mbr_done_tf,       /* Done T or F */\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error Building set MBR Dont/Not done command\\n\",\n"
+ "s/Dont/Done/ ?\n"
+ "\n"
+ "\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int set_mbr_enable_disable(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method, *uid;\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tu8 mbr_en_dis = *(u8 *)dev->func_data[dev->state - 1];\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_SET];\n"
+ "> +\tuid = OPALUID[OPAL_MBRCONTROL];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 3c 6c 2c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_VALUES,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_01, /* Enable */\n"
+ "> +\t\t\t\t    mbr_en_dis,        /* Enable or Disable */\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error Building set MBR Dont/Not done command\\n\",\n"
+ "s/Dont/Done/ ?\n"
+ "\n"
+ "\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int set_new_pw(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method;\n"
+ "> +\tu8 cpin_uid[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\tstruct opal_new_pw *pw;\n"
+ "> +\tsize_t key_len;\n"
+ "> +\tu8 *key;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tpw = dev->func_data[dev->state - 1];\n"
+ "> +\tkey = pw->new_pin.key;\n"
+ "> +\tkey_len = pw->new_pin.key_len;\n"
+ "> +\tmemcpy(cpin_uid, OPALUID[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);\n"
+ "> +\n"
+ "> +\tif (pw->user_for_pw != OPAL_ADMIN1) {\n"
+ "> +\t\tcpin_uid[5] = 0x03;\n"
+ "> +\t\tif (pw->who.SUM)\n"
+ "> +\t\t\tcpin_uid[7] = pw->new_pin.lr + 1;\n"
+ "> +\t\telse\n"
+ "> +\t\t\tcpin_uid[7] = pw->user_for_pw;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_SET];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 3c 3cs2c 2c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    cpin_uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_01, /* Values */\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03, /* PIN */\n"
+ "> +\t\t\t\t    key, key_len,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building SET AMIN1 PIN command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int set_sid_cpin_pin(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method, *cpin_uid;\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tcpin_uid = OPALUID[OPAL_C_PIN_SID];\n"
+ "> +\tmethod = OPALMETHOD[OPAL_SET];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 2c 4cs2c 2c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    cpin_uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_01, /* Values */\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03, /* PIN */\n"
+ "> +\t\t\t\t    dev->key, dev->key_len,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building SET CPIN PIN command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void query_locking_range_cont(int error, void *data)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\n"
+ "> +\terror = parse_and_check_status(dev);\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\n"
+ "> +\tdev->start = response_get_u64(&dev->parsed, 4);\n"
+ "> +\tdev->length = response_get_u64(&dev->parsed, 8);\n"
+ "> +\n"
+ "> +err_return:\n"
+ "> +\tif (dev->oper_cb)\n"
+ "> +\t\tdev->oper_cb(error, dev);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int query_locking_range(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tu8 lr_buffer[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tconst u8 *method;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_GET];\n"
+ "> +\n"
+ "> +\tif (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) {\n"
+ "> +\t\tpr_err(\"%s: Can't build locking range\\n\", dev->disk_name);\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 12c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    lr_buffer, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_STARTCOLUMN,\n"
+ "> +\t\t\t\t    OPAL_RANGESTART,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDCOLUMN,\n"
+ "> +\t\t\t\t    OPAL_RANGELENGTH,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building GET Locking Range command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, query_locking_range_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int add_user_to_lr(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tu8 lr_buffer[OPAL_UID_LENGTH];\n"
+ "> +\tu8 user_uid[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tconst u8 *method;\n"
+ "> +\tstruct opal_lock_unlock *lkul;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_SET];\n"
+ "> +\n"
+ "> +\tlkul = dev->func_data[dev->state - 1];\n"
+ "> +\n"
+ "> +\tmemcpy(lr_buffer, OPALUID[OPAL_LOCKINGRANGE_ACE_RDLOCKED],\n"
+ "> +\t       OPAL_UID_LENGTH);\n"
+ "> +\n"
+ "> +\tif (lkul->l_state == OPAL_RW)\n"
+ "> +\t\tmemcpy(lr_buffer, OPALUID[OPAL_LOCKINGRANGE_ACE_WRLOCKED],\n"
+ "> +\t\t       OPAL_UID_LENGTH);\n"
+ "> +\n"
+ "> +\tlr_buffer[7] = dev->lr;\n"
+ "> +\n"
+ "> +\tmemcpy(user_uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH);\n"
+ "> +\tuser_uid[7] = lkul->authority.who;\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 3c 3c 2c 2sc c2sc cs2c 5c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    lr_buffer, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_01, /* Values */\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03, /* BooleanExpr */\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPALUID[OPAL_HALF_UID_AUTHORITY_OBJ_REF],\n"
+ "> +\t\t\t\t    OPAL_UID_LENGTH_HALF,\n"
+ "> +\t\t\t\t    user_uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPALUID[OPAL_HALF_UID_AUTHORITY_OBJ_REF],\n"
+ "> +\t\t\t\t    OPAL_UID_LENGTH_HALF,\n"
+ "> +\t\t\t\t    user_uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPALUID[OPAL_HALF_UID_BOOLEAN_ACE],\n"
+ "> +\t\t\t\t    OPAL_UID_LENGTH_HALF,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_01,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building add user to locking range command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int lock_unlock_locking_range(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tu8 lr_buffer[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tconst u8 *method;\n"
+ "> +\tstruct opal_lock_unlock *lkul;\n"
+ "> +\tint ret;\n"
+ "> +\tu8 read_locked = 1, write_locked = 1;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_SET];\n"
+ "> +\tlkul = dev->func_data[dev->state - 1];\n"
+ "> +\tif (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) {\n"
+ "> +\t\tpr_err(\"%s: Can't build locking range\\n\", dev->disk_name);\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tswitch (lkul->l_state) {\n"
+ "> +\tcase OPAL_RO:\n"
+ "> +\t\tread_locked = 0;\n"
+ "> +\t\twrite_locked = 1;\n"
+ "> +\t\tbreak;\n"
+ "> +\tcase OPAL_RW:\n"
+ "> +\t\tread_locked = 0;\n"
+ "> +\t\twrite_locked = 0;\n"
+ "> +\t\tbreak;\n"
+ "> +\tcase OPAL_LK:\n"
+ "> +\t\t/* vars are initalized to locked */\n"
+ "> +\t\tbreak;\n"
+ "> +\tdefault:\n"
+ "> +\t\tpr_err(\"Tried to set an invalid locking state... returning to uland\\n\");\n"
+ "> +\t\treturn 1;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2sc 3c 4c 4c 3c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    lr_buffer, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_VALUES,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_READLOCKED,\n"
+ "> +\t\t\t\t    read_locked,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_WRITELOCKED,\n"
+ "> +\t\t\t\t    write_locked,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building SET command.\\n\", dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +\n"
+ "> +static int lock_unlock_locking_range_SUM(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tu8 lr_buffer[OPAL_UID_LENGTH];\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tconst u8 *method;\n"
+ "> +\tstruct opal_lock_unlock *lkul;\n"
+ "> +\tint ret;\n"
+ "> +\tu8 read_locked = 1, write_locked = 1;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tmethod = OPALMETHOD[OPAL_SET];\n"
+ "> +\tlkul = dev->func_data[dev->state - 1];\n"
+ "> +\tif (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) {\n"
+ "> +\t\tpr_err(\"%s: Can't build locking range\\n\", dev->disk_name);\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tswitch (lkul->l_state) {\n"
+ "> +\tcase OPAL_RO:\n"
+ "> +\t\tread_locked = 0;\n"
+ "> +\t\twrite_locked = 1;\n"
+ "> +\t\tbreak;\n"
+ "> +\tcase OPAL_RW:\n"
+ "> +\t\tread_locked = 0;\n"
+ "> +\t\twrite_locked = 0;\n"
+ "> +\t\tbreak;\n"
+ "> +\tcase OPAL_LK:\n"
+ "> +\t\t/* vars are initalized to locked */\n"
+ "> +\t\tbreak;\n"
+ "> +\tdefault:\n"
+ "> +\t\tpr_err(\"Tried to set an invalid locking state.\\n\");\n"
+ "> +\t\treturn 1;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2sc 3c 4c 4c 4c 4c 3c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    lr_buffer, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_VALUES,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_READLOCKENABLED,\n"
+ "> +\t\t\t\t    OPAL_TRUE,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_WRITELOCKENABLED,\n"
+ "> +\t\t\t\t    OPAL_TRUE,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_READLOCKED,\n"
+ "> +\t\t\t\t    read_locked,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_WRITELOCKED,\n"
+ "> +\t\t\t\t    write_locked,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building SET command.\\n\", dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +int activate_lsp(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tu8 user_lr[OPAL_UID_LENGTH];\n"
+ "> +\tconst u8 *method, *uid;\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\tsize_t uint_3 = 0x83;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tuid = OPALUID[OPAL_LOCKINGSP_UID];\n"
+ "> +\tmethod = OPALMETHOD[OPAL_ACTIVATE];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH);\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building Activate LockingSP command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\t/* Activating as SUM */\n"
+ "> +\tif (dev->lr > 0) {\n"
+ "> +\t\tret = build_locking_range(user_lr, sizeof(user_lr), dev->lr);\n"
+ "> +\t\tif (ret < 0) {\n"
+ "> +\t\t\tpr_err(\"%s: Can't build locking user\\n\",\n"
+ "> +\t\t\t       dev->disk_name);\n"
+ "> +\t\t\treturn ret;\n"
+ "> +\t\t}\n"
+ "> +\t\ttest_and_add_token_va(cmd, \"2c 4c csc 2c\",\n"
+ "> +\t\t\t\t      OPAL_STARTLIST,\n"
+ "> +\t\t\t\t      OPAL_STARTNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t      uint_3,\n"
+ "> +\t\t\t\t      OPAL_TINY_UINT_06,\n"
+ "> +\t\t\t\t      OPAL_TINY_UINT_00,\n"
+ "> +\t\t\t\t      OPAL_TINY_UINT_00,\n"
+ "> +\n"
+ "> +\t\t\t\t      OPAL_STARTLIST,\n"
+ "> +\t\t\t\t      user_lr, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t      OPAL_ENDLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t      OPAL_ENDNAME,\n"
+ "> +\t\t\t\t      OPAL_ENDLIST);\n"
+ "> +\t} else /* Actiave Normal Mode */\n"
+ "> +\t\tret = test_and_add_token_va(cmd, \"2c\",\n"
+ "> +\t\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building Activate LockingSP command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, generic_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void get_lsp_lifecycle_cont(int error, void *data)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\tu8 lc_status;\n"
+ "> +\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\n"
+ "> +\terror = parse_and_check_status(dev);\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\n"
+ "> +\tlc_status = response_get_u64(&dev->parsed, 4);\n"
+ "> +\t/* 0x08 is Manufacured Inactive */\n"
+ "> +\t/* 0x09 is Manufactured */\n"
+ "> +\tif (lc_status != 0x08) {\n"
+ "> +\t\tpr_err(\"%s: Couldn't determine the status of the Lifcycle state\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\terror = -ENODEV;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +err_return:\n"
+ "> +\tif (dev->oper_cb)\n"
+ "> +\t\tdev->oper_cb(error, dev);\n"
+ "> +}\n"
+ "> +\n"
+ "> +/* Determine if we're in the Manufactured Inactive or Active state */\n"
+ "> +int get_lsp_lifecycle(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tconst u8 *method, *uid;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tuid = OPALUID[OPAL_LOCKINGSP_UID];\n"
+ "> +\tmethod = OPALMETHOD[OPAL_GET];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c2s 2c 4c 4c 2c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\t\t\t\t    uid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03, /* Start Column */\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_06, /* Lifcycle Column */\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_04, /* End Column */\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_06, /* Lifecycle Column */\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error Building GET Lifecycle Status command\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, get_lsp_lifecycle_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void get_msid_cpin_pin_cont(int error, void *data)\n"
+ "> +{\n"
+ "> +\tconst char *msid_pin;\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\tsize_t strlen;\n"
+ "> +\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\n"
+ "> +\terror = parse_and_check_status(dev);\n"
+ "> +\tif (error)\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\n"
+ "> +\tstrlen = response_get_string(&dev->parsed, 4, &msid_pin);\n"
+ "> +\tif (!msid_pin) {\n"
+ "> +\t\tpr_err(\"%s: Couldn't extract PIN from response\\n\", __func__);\n"
+ "> +\t\terror = 1;\n"
+ "> +\t\tgoto err_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL);\n"
+ "> +\tif (!dev->prev_data)\n"
+ "> +\t\terror = -ENOMEM;\n"
+ "> +\n"
+ "> +\tdev->prev_d_len = strlen;\n"
+ "> +\n"
+ "> + err_return:\n"
+ "> +\tif (dev->oper_cb)\n"
+ "> +\t\tdev->oper_cb(error, dev);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int get_msid_cpin_pin(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tconst u8 *method, *smuid;\n"
+ "> +\tint ret;\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\n"
+ "> +\tsmuid = OPALUID[OPAL_C_PIN_MSID];\n"
+ "> +\tmethod = OPALMETHOD[OPAL_GET];\n"
+ "> +\n"
+ "> +\tret = test_and_add_token_va(cmd, \"c 2s 12c\",\n"
+ "> +\t\t\t\t    OPAL_CALL,\n"
+ "> +\n"
+ "> +\t\t\t\t    smuid, OPAL_UID_LENGTH,\n"
+ "> +\t\t\t\t    method, OPAL_METHOD_LENGTH,\n"
+ "> +\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTLIST,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03, /* Sart Column */\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03, /* PIN */\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_STARTNAME,\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_04, /* End Column */\n"
+ "> +\t\t\t\t    OPAL_TINY_UINT_03, /* PIN */\n"
+ "> +\t\t\t\t    OPAL_ENDNAME,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST,\n"
+ "> +\t\t\t\t    OPAL_ENDLIST);\n"
+ "> +\n"
+ "> +\tif (ret < 0) {\n"
+ "> +\t\tpr_err(\"%s: Error building Get MSID CPIN PIN command.\\n\",\n"
+ "> +\t\t       dev->disk_name);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn finalize_and_send(dev, cmd, get_msid_cpin_pin_cont);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void unlock_suspend_final(int error, void *data)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev = data;\n"
+ "> +\n"
+ "> +\tdev->resume_from_suspend = false;\n"
+ "> +\tdev->resume_data = NULL;\n"
+ "> +\tdev->func_data = NULL;\n"
+ "> +\tdev->bdev = NULL;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int build_end_opal_session(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\n"
+ "> +\tcmd = &dev->cmd;\n"
+ "> +\tclear_opal_cmd(cmd);\n"
+ "> +\n"
+ "> +\tset_comID(cmd, dev->comID);\n"
+ "> +\treturn test_and_add_token_u8(cmd, OPAL_ENDOFSESSION);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int end_opal_session(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tif (build_end_opal_session(dev) < 0)\n"
+ "> +\t\treturn -1;\n"
+ "> +\treturn finalize_and_send(dev, &dev->cmd, end_session_cont);\n"
+ "> +}\n"
+ "Any reason we cant:\n"
+ "\n"
+ "int ret = build_...\n"
+ "if (ret < 0)\n"
+ "\treturn ret;\n"
+ "\n"
+ "\n"
+ "> +\n"
+ "> +static struct opal_dev *find_opal_dev(struct block_device *bdev, u8 lr)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *iter, *opal_dev = NULL;\n"
+ "> +\n"
+ "> +\tlist_for_each_entry(iter, &opal_list, node) {\n"
+ "> +\t\tif (strncmp(iter->disk_name, bdev->bd_disk->disk_name,\n"
+ "> +\t\t\t    DISK_NAME_LEN))\n"
+ "> +\t\t\tcontinue;\n"
+ "> +\t\tif (iter->lr == lr) {\n"
+ "> +\t\t\topal_dev = iter;\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\t}\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn opal_dev;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int update_opal_dev(struct opal_dev *old_dev, struct opal_dev *new_dev)\n"
+ "> +{\n"
+ "> +\tif (!atomic_add_unless(&old_dev->in_use, 1, 1)) {\n"
+ "> +\t\tpr_err(\"%s: dev was in use\\n\", __func__);\n"
+ "> +\t\treturn -EBUSY;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\told_dev->key_name_len = new_dev->key_name_len;\n"
+ "> +\tif (!memcpy(old_dev->key_name, new_dev->key_name, old_dev->key_name_len)) {\n"
+ "> +\t\tpr_err(\"%s: Error updating device:\\n\", old_dev->disk_name);\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (!strncpy(old_dev->disk_name, new_dev->disk_name, DISK_NAME_LEN)) {\n"
+ "> +\t\tpr_err(\"%s: Error registering device: copying disk name\\n\",\n"
+ "> +\t\t       old_dev->disk_name);\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\told_dev->comID = new_dev->comID;\n"
+ "> +\told_dev->start = new_dev->start;\n"
+ "> +\told_dev->length = new_dev->length;\n"
+ "> +\told_dev->align = new_dev->align;\n"
+ "> +\told_dev->lowest_lba = new_dev->lowest_lba;\n"
+ "> +\told_dev->bdev = NULL;\n"
+ "> +\told_dev->final_cb = new_dev->final_cb;\n"
+ "> +\told_dev->final_cb_data = new_dev->final_cb_data;\n"
+ "> +\told_dev->oper_cb = new_dev->oper_cb;\n"
+ "> +\told_dev->state = new_dev->state;\n"
+ "> +\told_dev->funcs = new_dev->funcs;\n"
+ "> +\n"
+ "> +\tkfree(old_dev->completion);\n"
+ "> +\tclean_function_data(old_dev);\n"
+ "> +\n"
+ "> +\told_dev->completion = new_dev->completion;\n"
+ "> +\n"
+ "> +\t/*\n"
+ "> +\t * Won't be able to auto unlock this locking range based on block\n"
+ "> +\t * requestes.\n"
+ "> +\t */\n"
+ "> +\tif (old_dev->length == 0)\n"
+ "> +\t\tpr_warn(\"%s: Missing block information for locking range %d\\n\",\n"
+ "> +\t\t\told_dev->disk_name, old_dev->lr);\n"
+ "> +\n"
+ "> +\treturn 0;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int opal_register_cont(struct opal_dev *new_dev)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *old_dev;\n"
+ "> +\tunsigned long flags;\n"
+ "> +\tint error = 0;\n"
+ "> +\n"
+ "> +\tspin_lock_irqsave(&list_spinlock, flags);\n"
+ "> +\n"
+ "> +\told_dev = find_opal_dev(new_dev->bdev, new_dev->lr);\n"
+ "> +\tif (!old_dev) {\n"
+ "> +\t\tlist_add_tail(&new_dev->node, &opal_list);\n"
+ "> +\t\told_dev = new_dev;\n"
+ "> +\t} else {\n"
+ "> +\t\tif (old_dev == new_dev)\n"
+ "> +\t\t\terror = 0;\n"
+ "> +\t\telse {\n"
+ "> +\t\t\terror = update_opal_dev(old_dev, new_dev);\n"
+ "> +\t\t\tclean_opal_key(new_dev);\n"
+ "> +\t\t\tkfree(new_dev);\n"
+ "> +\t\t}\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (error)\n"
+ "> +\t\tlist_del(&old_dev->node);\n"
+ "> +\n"
+ "> +\tspin_unlock_irqrestore(&list_spinlock, flags);\n"
+ "> +\n"
+ "> +\tif (!error)\n"
+ "> +\t\tpr_info(\"%s: Registered key for locking range: %d\\n\",\n"
+ "> +\t\t\told_dev->disk_name, old_dev->lr);\n"
+ "> +\n"
+ "> +\tif (old_dev->oper_cb)\n"
+ "> +\t\told_dev->oper_cb(error, old_dev);\n"
+ "> +\n"
+ "> +\treturn 0;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static void next(int error, struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\topal_step func = dev->funcs[dev->state];\n"
+ "> +\tvoid *cb_data = dev->final_cb_data;\n"
+ "> +\tsec_cb *cb = dev->final_cb;\n"
+ "> +\tbool done = false;\n"
+ "> +\n"
+ "> +\n"
+ "> +\tif (error || !func) {\n"
+ "> +\t\tdone = true;\n"
+ "> +\t\tgoto next_exit;\n"
+ "> +\t}\n"
+ "> +\tdev->state++;\n"
+ "> +\tdev->oper_cb = next;\n"
+ "> +\terror = func(dev);\n"
+ "> + next_exit:\n"
+ "> +\tif (error) {\n"
+ "> +\t\tpr_err(\"%s: Error on step function: %d with error %d: %s\\n\",\n"
+ "> +\t\t       dev->disk_name, dev->state, error,\n"
+ "> +\t\t       opal_error_to_human(error));\n"
+ "> +\n"
+ "> +\n"
+ "> +\t\tatomic_dec(&dev->in_use);\n"
+ "> +\t\tif (dev->error_cb) {\n"
+ "> +\t\t\tdev->error_cb(dev->error_cb_data);\n"
+ "> +\t\t\treturn;\n"
+ "> +\t\t}\n"
+ "> +\t\tif (cb)\n"
+ "> +\t\t\tcb(error, cb_data);\n"
+ "> +\n"
+ "> +\t\tdev->completion->completion_status = error;\n"
+ "> +\t\tcomplete(&dev->completion->cmd_completion);\n"
+ "> +\t} else if (!error && done) {\n"
+ "> +\t\tatomic_dec(&dev->in_use);\n"
+ "> +\t\tif (cb)\n"
+ "> +\t\t\tcb(error, cb_data);\n"
+ "> +\t\tdev->completion->completion_status = error;\n"
+ "> +\t\tcomplete(&dev->completion->cmd_completion);\n"
+ "> +\t}\n"
+ "> +}\n"
+ "> +\n"
+ "> +const opal_step error_end_session[] = {\n"
+ "> +\tend_opal_session,\n"
+ "> +\tNULL,\n"
+ "> +};\n"
+ "> +static int end_opal_session_error(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tdev->funcs = error_end_session;\n"
+ "> +\tdev->state = 0;\n"
+ "> +\tdev->error_cb = NULL;\n"
+ "> +\tnext(0, dev);\n"
+ "> +\treturn 0;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static struct opal_dev *alloc_opal_dev(struct block_device *bdev, u8 lr)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *opal_dev;\n"
+ "> +\tstruct request_queue *q;\n"
+ "> +\tunsigned long dma_align;\n"
+ "> +\tconst char *disk_name;\n"
+ "> +\tstruct opal_cmd *cmd;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\topal_dev = kzalloc(sizeof(*opal_dev), GFP_KERNEL);\n"
+ "> +\tif (!opal_dev)\n"
+ "> +\t\treturn ERR_PTR(-ENOMEM);\n"
+ "> +\n"
+ "> +\topal_dev->bdev = bdev;\n"
+ "> +\topal_dev->lr = lr;\n"
+ "> +\tcmd = &opal_dev->cmd;\n"
+ "> +\tcmd->cmd = cmd->cmd_buf;\n"
+ "> +\tcmd->resp = cmd->resp_buf;\n"
+ "> +\n"
+ "> +\tdisk_name = bdev->bd_disk->disk_name;\n"
+ "> +\tif (!strncpy(opal_dev->disk_name, disk_name, DISK_NAME_LEN)) {\n"
+ "> +\t\tpr_err(\"%s: Error registering device: copying disk name\\n\",\n"
+ "> +\t\t       disk_name);\n"
+ "> +\t\tret = -EFAULT;\n"
+ "> +\t\tgoto err_free_dev;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tq = bdev->bd_queue;\n"
+ "> +\tdma_align = (queue_dma_alignment(q) | q->dma_pad_mask) + 1;\n"
+ "> +\tcmd->cmd = (u8 *)round_up((uintptr_t)cmd->cmd, dma_align);\n"
+ "> +\tcmd->resp = (u8 *)round_up((uintptr_t)cmd->resp, dma_align);\n"
+ "> +\n"
+ "> +\tINIT_LIST_HEAD(&opal_dev->node);\n"
+ "> +\tatomic_set(&opal_dev->in_use, 1);\n"
+ "> +\n"
+ "> +\topal_dev->completion = kzalloc(sizeof(*opal_dev->completion),\n"
+ "> +\t\t\t\t       GFP_KERNEL);\n"
+ "> +\n"
+ "> +\tif (!opal_dev->completion)\n"
+ "> +\t\tgoto err_free_dev;\n"
+ "> +\n"
+ "> +\tinit_completion(&opal_dev->completion->cmd_completion);\n"
+ "> +\topal_dev->completion->completion_status = 0;\n"
+ "> +\topal_dev->state = 0;\n"
+ "> +\n"
+ "> +\treturn opal_dev;\n"
+ "> +\n"
+ "> +err_free_dev:\n"
+ "> +\tkfree(opal_dev);\n"
+ "> +\treturn ERR_PTR(ret);\n"
+ "> +}\n"
+ "> +\n"
+ "> +int opal_register(struct block_device *bdev, struct opal_key *key_cmd,\n"
+ "> +\t\t  const opal_step *funcs)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *new_dev = NULL;\n"
+ "> +\tu8 key_len = key_cmd->key_len;\n"
+ "> +\tu8 lr = key_cmd->lr;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tnew_dev = alloc_opal_dev(bdev, lr);\n"
+ "> +\tif (IS_ERR(new_dev)) {\n"
+ "> +\t\tpr_err(\"%s: Error registering device: allocation\\n\",\n"
+ "> +\t\t       bdev->bd_disk->disk_name);\n"
+ "> +\t\treturn PTR_ERR(new_dev);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (!memcpy(new_dev->key_name, key_cmd->key, key_len)) {\n"
+ "> +\t\tpr_err(\"%s: Error registering key: couldn't copy key\\n\",\n"
+ "> +\t\t       new_dev->disk_name);\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tnew_dev->key_name_len = key_len;\n"
+ "> +\tnew_dev->key_type = key_cmd->key_type;\n"
+ "> +\tret = get_opal_key(new_dev);\n"
+ "> +\tif (ret) {\n"
+ "> +\t\tpr_err(\"%s: Couldn't get key: %d\\n\", new_dev->disk_name, ret);\n"
+ "> +\t\treturn ret;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tnew_dev->funcs = funcs;\n"
+ "> +\n"
+ "> +\tnew_dev->state = 0;\n"
+ "> +\tcompletion = new_dev->completion;\n"
+ "> +\tnext(0, new_dev);\n"
+ "> +\n"
+ "> +\treturn wait_for_cmd_completion(completion);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static struct opal_dev *get_registered_opal_dev(struct block_device *bdev,\n"
+ "> +\t\t\t\t\t\tu8 lr)\n"
+ "> +{\n"
+ "> +\tconst char *diskname = bdev->bd_disk->disk_name;\n"
+ "> +\tstruct opal_dev *iter, *dev = NULL;\n"
+ "> +\tunsigned long flags;\n"
+ "> +\tbool in_use = false;\n"
+ "> +\n"
+ "> +\tspin_lock_irqsave(&list_spinlock, flags);\n"
+ "> +\tlist_for_each_entry(iter, &opal_list, node) {\n"
+ "> +\t\tif (strncmp(iter->disk_name, diskname, DISK_NAME_LEN))\n"
+ "> +\t\t\tcontinue;\n"
+ "> +\t\tif (iter->lr == lr) {\n"
+ "> +\t\t\tdev = iter;\n"
+ "> +\t\t\tif (!atomic_add_unless(&iter->in_use, 1, 1)) {\n"
+ "> +\t\t\t\tdev = NULL;\n"
+ "> +\t\t\t\tin_use = true;\n"
+ "> +\t\t\t}\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\t}\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tspin_unlock_irqrestore(&list_spinlock, flags);\n"
+ "> +\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn NULL;\n"
+ "> +\n"
+ "> +\tdev->bdev = bdev;\n"
+ "> +\treturn dev;\n"
+ "> +}\n"
+ "> +\n"
+ "> +/* Free up the Opal dev and its keys during two scenarios:\n"
+ "> + *\n"
+ "> + * 1) When a command is complete that no longer requires\n"
+ "> + *    the opal dev to be around.\n"
+ "> + * 2) When a command, including Opal Save fails we clean\n"
+ "> + *    and free the opal dev.\n"
+ "> + *\n"
+ "> + *    If we find the opal dev structure in the list of\n"
+ "> + *    saved passwords we will *not* remove it.\n"
+ "> + */\n"
+ "> +static void remove_and_clean_opal_dev(struct opal_dev *dev)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *iter;\n"
+ "> +\tbool found = false;\n"
+ "> +\n"
+ "> +\tspin_lock(&list_spinlock);\n"
+ "> +\tlist_for_each_entry(iter, &opal_list, node) {\n"
+ "> +\t\tif (iter == dev) {\n"
+ "> +\t\t\tfound = true;\n"
+ "> +\t\t\tbreak;\n"
+ "> +\t\t}\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tspin_unlock(&list_spinlock);\n"
+ "> +\tif (!found) {\n"
+ "> +\t\tclean_opal_key(dev);\n"
+ "> +\t\tclean_function_data(dev);\n"
+ "> +\t\tkfree(dev);\n"
+ "> +\t}\n"
+ "> +}\n"
+ "> +\n"
+ "> +static struct opal_dev *get_or_create_opal_dev(struct block_device *bdev,\n"
+ "> +\t\t\t\t\t       u8 lr, bool use_new)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev;\n"
+ "> +\n"
+ "> +\tif (use_new)\n"
+ "> +\t\treturn alloc_opal_dev(bdev, lr);\n"
+ "> +\n"
+ "> +\tdev = get_registered_opal_dev(bdev, lr);\n"
+ "> +\tif (!dev) {\n"
+ "> +\t\tdev = alloc_opal_dev(bdev, lr);\n"
+ "> +\t\tif (!dev)\n"
+ "> +\t\t\treturn NULL;\n"
+ "No need for this check when you already return dev\n"
+ "\n"
+ "\n"
+ "> +\t}\n"
+ "> +\treturn dev;\n"
+ "> +}\n"
+ "Instead, how about:\n"
+ "static struct opal_dev *get_or_create_opal_dev(struct block_device *bdev,\n"
+ "\t\t\t\t\t       u8 lr, bool use_new)\n"
+ "{\n"
+ "\tstruct opal_dev *dev = NULL;\n"
+ "\n"
+ "\tif (!use_new)\n"
+ "\t\tdev = get_registered_opal_dev(bdev, lr);\n"
+ "\n"
+ "\tif (!dev)\n"
+ "\t\tdev = alloc_opal_dev(bdev, lr);\n"
+ "\n"
+ "\treturn dev;\n"
+ "}\n"
+ "\n"
+ "\n"
+ "> +\n"
+ "> +static struct opal_completion *setup_opal_dev(struct block_device *bdev,\n"
+ "> +\t\t\t\t\t      struct opal_dev *dev,\n"
+ "> +\t\t\t\t\t      const opal_step *funcs,\n"
+ "> +\t\t\t\t\t      struct opal_key *key)\n"
+ "> +{\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tdev->bdev = bdev;\n"
+ "> +\tdev->state = 0;\n"
+ "> +\tdev->funcs = funcs;\n"
+ "> +\tdev->TSN = 0;\n"
+ "> +\tdev->HSN = 0;\n"
+ "> +\tdev->final_cb = NULL;\n"
+ "> +\tdev->final_cb_data = NULL;\n"
+ "> +\tdev->lr = key->lr;\n"
+ "> +\tdev->error_cb = end_opal_session_error;\n"
+ "> +\tdev->error_cb_data = dev;\n"
+ "> +\n"
+ "> +\tif (key) {\n"
+ "> +\t\tmemcpy(dev->key_name, key->key, key->key_len);\n"
+ "> +\t\tdev->key_name_len = key->key_len;\n"
+ "> +\t\tdev->key_type = key->key_type;\n"
+ "> +\n"
+ "> +\t\tret = get_opal_key(dev);\n"
+ "> +\t\tif (ret) {\n"
+ "> +\t\t\tkfree(dev->completion);\n"
+ "> +\t\t\tpr_err(\"%s: Couldn't get key: %d\\n\",\n"
+ "> +\t\t\t       dev->disk_name, ret);\n"
+ "> +\t\t\treturn ERR_PTR(ret);\n"
+ "> +\t\t}\n"
+ "> +\t}\n"
+ "> +\tdev->func_data = NULL;\n"
+ "> +\tdev->completion->completion_status = 0;\n"
+ "> +\n"
+ "> +\treturn dev->completion;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int internal_setup_lr(struct block_device *bdev,\n"
+ "> +\t\t\t     struct opal_user_lr_setup *setup)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tvoid *data[3] = { NULL };\n"
+ "> +\tconst opal_step lr_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_auth_opal_session,\n"
+ "> +\t\tsetup_locking_range,\n"
+ "> +\t\tget_active_key,\n"
+ "> +\t\tgen_key,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL,\n"
+ "> +\t};\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tdev = get_or_create_opal_dev(bdev, setup->key.lr, true);\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn -ENOMEM;\n"
+ "> +\n"
+ "> +\tcompletion = setup_opal_dev(bdev, dev, lr_funcs, &setup->key);\n"
+ "> +\tif (IS_ERR(completion)) {\n"
+ "> +\t\tret = PTR_ERR(completion);\n"
+ "> +\t\tgoto error_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->func_data = data;\n"
+ "> +\tdev->num_func_data = 3;\n"
+ "> +\tdev->func_data[1] = &setup->who;\n"
+ "> +\tdev->func_data[2] = setup;\n"
+ "> +\n"
+ "> +\tnext(0, dev);\n"
+ "> +\tret = wait_for_cmd_completion(completion);\n"
+ "> +\n"
+ "> + error_return:\n"
+ "> +\tremove_and_clean_opal_dev(dev);\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int opal_revert(struct block_device *bdev, struct opal_key *key)\n"
+ "> +{\n"
+ "> +\tconst opal_step revert_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_SIDASP_opal_session,\n"
+ "> +\t\trevert_tper, /* controller will terminate session */\n"
+ "> +\t\tNULL,\n"
+ "> +\t};\n"
+ "> +\n"
+ "> +\treturn opal_register(bdev, key, revert_funcs);\n"
+ "> +}\n"
+ "> +\n"
+ "> +int activate_user(struct block_device *bdev, struct opal_activate_user *act)\n"
+ "> +{\n"
+ "> +\tconst opal_step act_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_admin1LSP_opal_session,\n"
+ "> +\t\tinternal_activate_user,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL\n"
+ "> +\t};\n"
+ "> +\tstruct opal_dev *dev;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tvoid *data[3] = { NULL };\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tdev = get_or_create_opal_dev(bdev, act->key.lr, true);\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn -ENOMEM;\n"
+ "> +\n"
+ "> +\tcompletion = setup_opal_dev(bdev, dev, act_funcs, &act->key);\n"
+ "> +\tif (IS_ERR(completion)) {\n"
+ "> +\t\tret = PTR_ERR(completion);\n"
+ "> +\t\tgoto error_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->num_func_data = 3;\n"
+ "> +\tdev->func_data = data;\n"
+ "> +\tdev->func_data[1] = act;\n"
+ "> +\tdev->func_data[2] = act;\n"
+ "> +\n"
+ "> +\tnext(0, dev);\n"
+ "> +\tret = wait_for_cmd_completion(completion);\n"
+ "> +\n"
+ "> + error_return:\n"
+ "> +\tremove_and_clean_opal_dev(dev);\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int opal_set_pw(struct block_device *bdev, struct opal_new_pw *pw)\n"
+ "> +\n"
+ "> +{\n"
+ "> +\tconst opal_step pw_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_auth_opal_session,\n"
+ "> +\t\tset_new_pw,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL\n"
+ "> +\t};\n"
+ "> +\tstruct opal_dev *dev;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tvoid *data[3] = { NULL };\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tdev = get_or_create_opal_dev(bdev, pw->current_pin.lr, true);\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn -ENOMEM;\n"
+ "> +\n"
+ "> +\tcompletion = setup_opal_dev(bdev, dev, pw_funcs, &pw->current_pin);\n"
+ "> +\tif (IS_ERR(completion)) {\n"
+ "> +\t\tret = PTR_ERR(completion);\n"
+ "> +\t\tgoto error_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->num_func_data = 3;\n"
+ "> +\tdev->func_data = data;\n"
+ "> +\tdev->func_data[1] = (void *) &pw->who;\n"
+ "> +\tdev->func_data[2] = (void *) pw;\n"
+ "> +\n"
+ "> +\tnext(0, dev);\n"
+ "> +\tret = wait_for_cmd_completion(completion);\n"
+ "> +\n"
+ "> + error_return:\n"
+ "> +\tremove_and_clean_opal_dev(dev);\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int opal_act_lsp_int(struct block_device *bdev, struct opal_key *key,\n"
+ "> +\t\t     const opal_step *funcs)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tdev = get_or_create_opal_dev(bdev, key->lr, true);\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn -ENOMEM;\n"
+ "> +\tcompletion = setup_opal_dev(bdev, dev, funcs, key);\n"
+ "> +\tif (IS_ERR(completion)) {\n"
+ "> +\t\tret = PTR_ERR(completion);\n"
+ "> +\t\tgoto error_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tnext(0, dev);\n"
+ "> +\tret = wait_for_cmd_completion(completion);\n"
+ "> +\n"
+ "> + error_return:\n"
+ "> +\tremove_and_clean_opal_dev(dev);\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +\n"
+ "> +static int opal_save_internal(struct block_device *bdev,\n"
+ "> +\t\t\t      struct opal_lock_unlock *lk)\n"
+ "> +{\n"
+ "> +\tvoid *func_data[3] = { NULL };\n"
+ "> +\tstruct opal_dev *dev;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tconst opal_step _auth_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_auth_opal_session,\n"
+ "> +\t\tquery_locking_range,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\topal_register_cont,\n"
+ "> +\t\tNULL\n"
+ "> +\t};\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tdev = get_or_create_opal_dev(bdev, lk->key.lr, false);\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn -ENOMEM;\n"
+ "> +\tcompletion = setup_opal_dev(bdev, dev, _auth_funcs, &lk->key);\n"
+ "> +\tif (IS_ERR(completion)) {\n"
+ "> +\t\tret = PTR_ERR(completion);\n"
+ "> +\t\tgoto error_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->num_func_data = 3;\n"
+ "> +\tdev->func_data = func_data;\n"
+ "> +\tdev->func_data[1] = &lk->authority;\n"
+ "> +\tdev->lkul = *lk;\n"
+ "> +\n"
+ "> +\tnext(0, dev);\n"
+ "> +\tret = wait_for_cmd_completion(completion);\n"
+ "> +\n"
+ "> + error_return:\n"
+ "> +\tremove_and_clean_opal_dev(dev);\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int add_user_lr_internal(struct block_device *bdev,\n"
+ "> +\t\t\t\tstruct opal_lock_unlock *lk)\n"
+ "> +{\n"
+ "> +\tvoid *func_data[3] = { NULL };\n"
+ "> +\tstruct opal_dev *dev;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tconst opal_step funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_admin1LSP_opal_session,\n"
+ "> +\t\tadd_user_to_lr,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL\n"
+ "> +\t};\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tdev = get_or_create_opal_dev(bdev, lk->key.lr, true);\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn -ENOMEM;\n"
+ "> +\tcompletion = setup_opal_dev(bdev, dev, funcs, &lk->key);\n"
+ "> +\tif (IS_ERR(completion)) {\n"
+ "> +\t\tret = PTR_ERR(completion);\n"
+ "> +\t\tgoto error_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->num_func_data = 3;\n"
+ "> +\tdev->func_data = func_data;\n"
+ "> +\tdev->func_data[2] = lk;\n"
+ "> +\n"
+ "> +\tnext(0, dev);\n"
+ "> +\tret = wait_for_cmd_completion(completion);\n"
+ "> +\n"
+ "> + error_return:\n"
+ "> +\tremove_and_clean_opal_dev(dev);\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int lock_unlock_internal(struct block_device *bdev,\n"
+ "> +\t\t\t\tstruct opal_lock_unlock *lk)\n"
+ "> +{\n"
+ "> +\tvoid *func_data[3] = { NULL };\n"
+ "> +\tstruct opal_dev *dev;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\n"
+ "> +\tconst opal_step ulk_funcs_SUM[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_auth_opal_session,\n"
+ "> +\t\tlock_unlock_locking_range_SUM,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL\n"
+ "> +\t};\n"
+ "> +\tconst opal_step _unlock_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_auth_opal_session,\n"
+ "> +\t\tlock_unlock_locking_range,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL\n"
+ "> +\t};\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tdev = get_or_create_opal_dev(bdev, lk->key.lr, true);\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn -ENOMEM;\n"
+ "> +\n"
+ "> +\tif (lk->authority.SUM)\n"
+ "> +\t\tcompletion = setup_opal_dev(bdev, dev, ulk_funcs_SUM, &lk->key);\n"
+ "> +\telse\n"
+ "> +\t\tcompletion = setup_opal_dev(bdev, dev, _unlock_funcs, &lk->key);\n"
+ "> +\n"
+ "> +\tif (IS_ERR(completion)) {\n"
+ "> +\t\tret = PTR_ERR(completion);\n"
+ "> +\t\tgoto error_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->num_func_data = 3;\n"
+ "> +\tdev->func_data = func_data;\n"
+ "> +\tdev->func_data[1] = &lk->authority;\n"
+ "> +\tdev->func_data[2] = lk;\n"
+ "> +\n"
+ "> +\tnext(0, dev);\n"
+ "> +\tret = wait_for_cmd_completion(completion);\n"
+ "> +\n"
+ "> + error_return:\n"
+ "> +\tremove_and_clean_opal_dev(dev);\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int opal_erase_locking_range(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tstruct opal_dev *dev;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tstruct opal_key k;\n"
+ "> +\tint ret;\n"
+ "> +\tconst opal_step erase_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_admin1LSP_opal_session,\n"
+ "> +\t\terase_locking_range,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL,\n"
+ "> +\t};\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk) {\n"
+ "> +\t\tpr_err(\"Can't save password for NULL block device.\\n\");\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&k, key->opal, sizeof(*key->opal)))\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\tdev = get_or_create_opal_dev(bdev, k.lr, true);\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn -ENOMEM;\n"
+ "> +\n"
+ "> +\tcompletion = setup_opal_dev(bdev, dev, erase_funcs, &k);\n"
+ "> +\tif (IS_ERR(completion)) {\n"
+ "> +\t\tret = PTR_ERR(completion);\n"
+ "> +\t\tgoto error_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tnext(0, dev);\n"
+ "> +\tret = wait_for_cmd_completion(completion);\n"
+ "> +\n"
+ "> + error_return:\n"
+ "> +\tremove_and_clean_opal_dev(dev);\n"
+ "> +\treturn ret;\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_erase_locking_range);\n"
+ "> +\n"
+ "> +int opal_enable_disable_shadow_mbr(struct block_device *bdev,\n"
+ "> +\t\t\t\t   struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tvoid *func_data[6] = { NULL };\n"
+ "> +\tstruct opal_mbr_data mbr;\n"
+ "> +\tstruct opal_dev *dev;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tconst opal_step mbr_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_admin1LSP_opal_session,\n"
+ "> +\t\tset_mbr_done,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tstart_admin1LSP_opal_session,\n"
+ "> +\t\tset_mbr_enable_disable,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL,\n"
+ "> +\t};\n"
+ "> +\tint ret;\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk) {\n"
+ "> +\t\tpr_err(\"Can't save password for NULL block device.\\n\");\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&mbr, key->opal_mbr, sizeof(*key->opal_mbr)))\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\tif (mbr.enable_disable != OPAL_MBR_ENABLE &&\n"
+ "> +\t    mbr.enable_disable != OPAL_MBR_DISABLE)\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\n"
+ "> +\tdev = get_or_create_opal_dev(bdev, mbr.key.lr, true);\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn -ENOMEM;\n"
+ "> +\n"
+ "> +\tcompletion = setup_opal_dev(bdev, dev, mbr_funcs, &mbr.key);\n"
+ "> +\tif (IS_ERR(completion)) {\n"
+ "> +\t\tret = PTR_ERR(completion);\n"
+ "> +\t\tgoto error_return;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tdev->num_func_data = 6;\n"
+ "> +\tdev->func_data = func_data;\n"
+ "> +\tdev->func_data[2] = &mbr.enable_disable;\n"
+ "> +\tdev->func_data[5] = &mbr.enable_disable;\n"
+ "> +\n"
+ "> +\tnext(0, dev);\n"
+ "> +\tret = wait_for_cmd_completion(completion);\n"
+ "> +\n"
+ "> + error_return:\n"
+ "> +\tremove_and_clean_opal_dev(dev);\n"
+ "> +\treturn ret;\n"
+ "> +\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_enable_disable_shadow_mbr);\n"
+ "> +\n"
+ "> +int opal_save(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tstruct opal_lock_unlock lkul;\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk) {\n"
+ "> +\t\tpr_err(\"Can't save password for NULL block device.\\n\");\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&lkul, key->opal_lk_unlk, sizeof(*key->opal)))\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\treturn opal_save_internal(bdev, &lkul);\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_save);\n"
+ "> +\n"
+ "> +int opal_add_user_to_lr(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tstruct opal_lock_unlock lkul;\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&lkul, key->opal_lk_unlk, sizeof(lkul)))\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk) {\n"
+ "> +\t\tpr_err(\"Can't assign user to LR without backing disk\\n\");\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\t}\n"
+ "> +\tif (lkul.l_state != OPAL_RO && lkul.l_state != OPAL_RW) {\n"
+ "> +\t\tpr_err(\"Locking state was not RO or RW\\n\");\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\tif (lkul.authority.who < OPAL_USER1 &&\n"
+ "> +\t    lkul.authority.who > OPAL_USER9) {\n"
+ "> +\t\tpr_err(\"Authority was not within the range of users: %d\\n\",\n"
+ "> +\t\t       lkul.authority.who);\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\tif (lkul.authority.SUM) {\n"
+ "> +\t\tpr_err(\"%s not supported in SUM. Use setup locking range\\n\",\n"
+ "> +\t\t       __func__);\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn add_user_lr_internal(bdev, &lkul);\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_add_user_to_lr);\n"
+ "> +\n"
+ "> +int opal_reverttper(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tstruct opal_key k;\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&k, key->opal, sizeof(*key->opal)))\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\treturn opal_revert(bdev, &k);\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_reverttper);\n"
+ "> +\n"
+ "> +int opal_lock_unlock(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tstruct opal_lock_unlock k;\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&k, key->opal_lk_unlk, sizeof(*key->opal_lk_unlk)))\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\tif (k.authority.who < OPAL_ADMIN1 || k.authority.who >= OPAL_USER9)\n"
+ "Should this be > OPAL_USER9 ?\n"
+ "\n"
+ "\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\n"
+ "> +\treturn lock_unlock_internal(bdev, &k);\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_lock_unlock);\n"
+ "> +\n"
+ "> +int opal_take_ownership(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tstruct opal_key k;\n"
+ "> +\tconst opal_step owner_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_anybodyASP_opal_session,\n"
+ "> +\t\tget_msid_cpin_pin,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tstart_SIDASP_opal_session,\n"
+ "> +\t\tset_sid_cpin_pin,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL\n"
+ "> +\t};\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk) {\n"
+ "> +\t\tpr_err(\"Can't save password for NULL block device.\\n\");\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&k, key->opal, sizeof(*key->opal)))\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\treturn opal_register(bdev, &k, owner_funcs);\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_take_ownership);\n"
+ "> +\n"
+ "> +int opal_activate_lsp(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tstruct opal_key k;\n"
+ "> +\tconst opal_step active_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_SIDASP_opal_session, /* Open session as SID auth */\n"
+ "> +\t\tget_lsp_lifecycle,\n"
+ "> +\t\tactivate_lsp,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL\n"
+ "> +\t};\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk) {\n"
+ "> +\t\tpr_err(\"Can't save password for NULL block device.\\n\");\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&k, key->opal, sizeof(*key->opal)))\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\treturn opal_act_lsp_int(bdev, &k, active_funcs);\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_activate_lsp);\n"
+ "> +\n"
+ "> +int opal_setup_locking_range(struct block_device *bdev, struct sed_key *pw)\n"
+ "> +{\n"
+ "> +\tstruct opal_user_lr_setup k;\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk) {\n"
+ "> +\t\tpr_err(\"Can't save password for NULL block device.\\n\");\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&k, pw->opal_lrs, sizeof(*pw->opal_lrs)))\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\treturn internal_setup_lr(bdev, &k);\n"
+ "> +}\n"
+ "> +\n"
+ "> +int opal_set_new_pw(struct block_device *bdev, struct sed_key *pw)\n"
+ "> +{\n"
+ "> +\tstruct opal_new_pw k;\n"
+ "> +\n"
+ "> +\tif (pw->sed_type != OPAL_PW)\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&k, pw->opal_pw, sizeof(*pw->opal_pw)))\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\n"
+ "> +\tif (k.who.who < OPAL_ADMIN1 || k.who.who > OPAL_USER9)\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\n"
+ "> +\treturn opal_set_pw(bdev, &k);\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_set_new_pw);\n"
+ "> +\n"
+ "> +int opal_activate_user(struct block_device *bdev, struct sed_key *pw)\n"
+ "> +{\n"
+ "> +\tstruct opal_activate_user k;\n"
+ "> +\n"
+ "> +\tif (pw->sed_type != OPAL_ACT_USR) {\n"
+ "> +\t\tpr_err(\"Sed type was not act user\\n\");\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\tif (copy_from_user(&k, pw->opal_act, sizeof(*pw->opal_act))) {\n"
+ "> +\t\tpr_err(\"copy from user error\\n\");\n"
+ "> +\t\treturn -EFAULT;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\t/* We can't activate Admin1 it's active as manufactured */\n"
+ "> +\tif (k.who.who < OPAL_USER1 && k.who.who > OPAL_USER9) {\n"
+ "> +\t\tpr_err(\"Who was not a valid user: %d \\n\", k.who.who);\n"
+ "> +\t\treturn -EINVAL;\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn activate_user(bdev, &k);\n"
+ "> +\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_activate_user);\n"
+ "> +\n"
+ "> +int opal_unlock_from_suspend(struct opal_suspend_unlk *data)\n"
+ "> +{\n"
+ "> +\tconst char *diskname = data->name;\n"
+ "> +\tstruct opal_dev *iter, *dev = NULL;\n"
+ "> +\tstruct opal_completion *completion;\n"
+ "> +\tvoid *func_data[3] = { NULL };\n"
+ "> +\tconst opal_step _unlock_funcs_SUM[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_auth_opal_session,\n"
+ "> +\t\tlock_unlock_locking_range,\n"
+ "Did you mean to use lock_unlock_locking_range_SUM ?\n"
+ "Can we pull these two arrays out since they are required for both this\n"
+ "function and lock_unlock_internal ?\n"
+ "\n"
+ "\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL\n"
+ "> +\t};\n"
+ "> +\tconst opal_step _unlock_funcs[] = {\n"
+ "> +\t\topal_discovery0,\n"
+ "> +\t\tstart_auth_opal_session,\n"
+ "> +\t\tlock_unlock_locking_range,\n"
+ "> +\t\tend_opal_session,\n"
+ "> +\t\tNULL\n"
+ "> +\t};\n"
+ "> +\n"
+ "> +\n"
+ "> +\tspin_lock(&list_spinlock);\n"
+ "> +\tlist_for_each_entry(iter, &opal_list, node) {\n"
+ "> +\t\tif (strncmp(iter->disk_name, diskname, DISK_NAME_LEN)) {\n"
+ "> +\t\t\tpr_err(\"iterdisk was %s and diskname is %s\\n\",\n"
+ "> +\t\t\t       iter->disk_name, diskname);\n"
+ "> +\t\t\tcontinue;\n"
+ "> +\t\t}\n"
+ "> +\t\tif (atomic_add_unless(&iter->in_use, 1, 1)) {\n"
+ "> +\t\t\tdev = iter;\n"
+ "> +\t\t\tdev->func_data = func_data;\n"
+ "> +\t\t\tdev->resume_from_suspend = true;\n"
+ "> +\t\t\tdev->resume_data = data;\n"
+ "> +\t\t\tdev->final_cb = unlock_suspend_final;\n"
+ "> +\t\t\tdev->final_cb_data = dev;\n"
+ "> +\t\t\tdev->error_cb = end_opal_session_error;\n"
+ "> +\t\t\tdev->error_cb_data = dev;\n"
+ "> +\t\t\tdev->state = 0;\n"
+ "> +\t\t\tif (dev->lkul.authority.SUM)\n"
+ "> +\t\t\t\tdev->funcs = _unlock_funcs_SUM;\n"
+ "> +\t\t\telse\n"
+ "> +\t\t\t\tdev->funcs = _unlock_funcs;\n"
+ "> +\t\t\tdev->TSN = 0;\n"
+ "> +\t\t\tdev->HSN = 0;\n"
+ "> +\t\t\tdev->func_data[2] = &dev->lkul;\n"
+ "> +\t\t\tdev->func_data[1] = &dev->lkul.authority;\n"
+ "> +\t\t\tcompletion = dev->completion;\n"
+ "> +\t\t\tnext(0, dev);\n"
+ "> +\t\t\twait_for_cmd_completion(completion);\n"
+ "> +\t\t}\n"
+ "> +\t}\n"
+ "> +\tspin_unlock(&list_spinlock);\n"
+ "> +\n"
+ "> +\tif (!dev)\n"
+ "> +\t\treturn -ENODEV;\n"
+ "> +\treturn 0;\n"
+ "> +}\n"
+ "> +EXPORT_SYMBOL(opal_unlock_from_suspend);\n"
+ "> diff --git a/lib/sed-opal_internal.h b/lib/sed-opal_internal.h\n"
+ "> new file mode 100644\n"
+ "> index 0000000..c9d3883\n"
+ "> --- /dev/null\n"
+ "> +++ b/lib/sed-opal_internal.h\n"
+ "> @@ -0,0 +1,586 @@\n"
+ "> +/*\n"
+ "> + * Copyright ? 2016 Intel Corporation\n"
+ "> + *\n"
+ "> + * Permission is hereby granted, free of charge, to any person obtaining a\n"
+ "> + * copy of this software and associated documentation files (the \"Software\"),\n"
+ "> + * to deal in the Software without restriction, including without limitation\n"
+ "> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n"
+ "> + * and/or sell copies of the Software, and to permit persons to whom the\n"
+ "> + * Software is furnished to do so, subject to the following conditions:\n"
+ "> + *\n"
+ "> + * The above copyright notice and this permission notice (including the next\n"
+ "> + * paragraph) shall be included in all copies or substantial portions of the\n"
+ "> + * Software.\n"
+ "> + *\n"
+ "> + * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
+ "> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
+ "> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n"
+ "> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
+ "> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n"
+ "> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n"
+ "> + * IN THE SOFTWARE.\n"
+ "> + *\n"
+ "> + * Author:\n"
+ "> + *    Rafael Antognolli <rafael.antognolli at intel.com>\n"
+ "> + *    Scott  Bauer      <scott.bauer at intel.com>\n"
+ "> + */\n"
+ "> +\n"
+ "> +#ifndef _NVME_OPAL_INTERNAL_H\n"
+ "> +#define _NVME_OPAL_INTERNAL_H\n"
+ "> +\n"
+ "> +#include <linux/key-type.h>\n"
+ "> +#include <keys/user-type.h>\n"
+ "> +\n"
+ "> +#define DTAERROR_NO_METHOD_STATUS 0x89\n"
+ "> +\n"
+ "> +static const char *opal_errors[19] = {\n"
+ "Remove the 19 so it's just opal_errors[] (doesnt silently truncate any\n"
+ "new additions)\n"
+ "\n"
+ "\n"
+ "> +\t\"Success\",\n"
+ "> +\t\"Not Authorized\",\n"
+ "> +\t\"Unknown Error\",\n"
+ "> +\t\"SP Busy\",\n"
+ "> +\t\"SP Failed\",\n"
+ "> +\t\"SP Disabled\",\n"
+ "> +\t\"SP Frozen\",\n"
+ "> +\t\"No Sessions Available\",\n"
+ "> +\t\"Uniqueness Conflict\",\n"
+ "> +\t\"Insufficient Space\",\n"
+ "> +\t\"Insufficient Rows\",\n"
+ "> +\t\"Invalid Function\",\n"
+ "> +\t\"Invalid Parameter\",\n"
+ "> +\t\"Invalid Reference\",\n"
+ "> +\t\"Unknown Error\",\n"
+ "> +\t\"TPER Malfunction\",\n"
+ "> +\t\"Transaction Failure\",\n"
+ "> +\t\"Response Overflow\",\n"
+ "> +\t\"Authority Locked Out\",\n"
+ "> +};\n"
+ "> +\n"
+ "> +static const char *opal_error_to_human(int error)\n"
+ "> +{\n"
+ "> +\tif (error == 0x3f)\n"
+ "> +\t\treturn \"Failed\";\n"
+ "> +\n"
+ "> +\tif (error >= sizeof(opal_errors) || error < 0)\n"
+ "You want sizeof(opal_errors)/sizeof(*opal_errors) here, but you can just\n"
+ "use the ARRAY_SIZE macro instead\n"
+ "\n"
+ "\n"
+ "> +\t\treturn \"Unknown Error\";\n"
+ "> +\n"
+ "> +\treturn opal_errors[error];\n"
+ "> +}\n"
+ "> +\n"
+ "> +/* User IDs used in the TCG storage SSCs */\n"
+ "> +static const u8 OPALUID[][8] = {\n"
+ "> +\t/* users */\n"
+ "> +\n"
+ "> +\t/* session management  */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff},\n"
+ "> +\t/* special \"thisSP\" syntax */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },\n"
+ "> +\t/* Administrative SP */\n"
+ "> +\t{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 },\n"
+ "> +\t/* Locking SP */\n"
+ "> +\t{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 },\n"
+ "> +\t/* ENTERPRISE Locking SP  */\n"
+ "> +\t{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, 0x01 },\n"
+ "> +\t/* anybody */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 },\n"
+ "> +\t/* SID */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 },\n"
+ "> +\t/* ADMIN1 */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 },\n"
+ "> +\t/* USER1 */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 },\n"
+ "> +\t/* USER2 */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 },\n"
+ "> +\t/* PSID user */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 },\n"
+ "> +\t/* BandMaster 0 */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x01 },\n"
+ "> +\t /* EraseMaster */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x84, 0x01 },\n"
+ "> +\n"
+ "> +\t/* tables */\n"
+ "> +\n"
+ "> +\t/* Locking_GlobalRange */\n"
+ "> +\t{ 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 },\n"
+ "> +\t/* ACE_Locking_Range_Set_RdLocked UID */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x01 },\n"
+ "> +\t/* ACE_Locking_Range_Set_WrLocked UID */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x01 },\n"
+ "> +\t/* MBR Control */\n"
+ "> +\t{ 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01 },\n"
+ "> +\t/* Shadow MBR */\n"
+ "> +\t{ 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 },\n"
+ "> +\t/* AUTHORITY_TABLE */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00},\n"
+ "> +\t/* C_PIN_TABLE */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00},\n"
+ "> +\t/* OPAL Locking Info */\n"
+ "> +\t{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 },\n"
+ "> +\t/* Enterprise Locking Info */\n"
+ "> +\t{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 },\n"
+ "> +\n"
+ "> +\t/* C_PIN_TABLE object ID's */\n"
+ "> +\n"
+ "> +\t/* C_PIN_MSID */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02},\n"
+ "> +\t/* C_PIN_SID */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01},\n"
+ "> +\t /* C_PIN_ADMIN1 */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01},\n"
+ "> +\n"
+ "> +\t/* half UID's (only first 4 bytes used) */\n"
+ "> +\n"
+ "> +\t/* Half-UID ? Authority_object_ref */\n"
+ "> +\t{ 0x00, 0x00, 0x0C, 0x05, 0xff, 0xff, 0xff, 0xff },\n"
+ "> +\t/* Half-UID ? Boolean ACE */\n"
+ "> +\t{ 0x00, 0x00, 0x04, 0x0E, 0xff, 0xff, 0xff, 0xff },\n"
+ "> +\n"
+ "> +\t/* special value for omitted optional parameter */\n"
+ "> +\n"
+ "> +\t/* HEXFF for omitted */\n"
+ "> +\t{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},\n"
+ "> +};\n"
+ "> +static const size_t OPAL_UID_LENGTH = 8;\n"
+ "> +static const size_t OPAL_MSID_KEYLEN = 15;\n"
+ "> +static const size_t OPAL_UID_LENGTH_HALF = 4;\n"
+ "> +\n"
+ "> +\n"
+ "> +/* Enum to index OPALUID array */\n"
+ "> +enum OPAL_UID {\n"
+ "> +\t/* users */\n"
+ "> +\tOPAL_SMUID_UID,\n"
+ "> +\tOPAL_THISSP_UID,\n"
+ "> +\tOPAL_ADMINSP_UID,\n"
+ "> +\tOPAL_LOCKINGSP_UID,\n"
+ "> +\tOPAL_ENTERPRISE_LOCKINGSP_UID,\n"
+ "> +\tOPAL_ANYBODY_UID,\n"
+ "> +\tOPAL_SID_UID,\n"
+ "> +\tOPAL_ADMIN1_UID,\n"
+ "> +\tOPAL_USER1_UID,\n"
+ "> +\tOPAL_USER2_UID,\n"
+ "> +\tOPAL_PSID_UID,\n"
+ "> +\tOPAL_ENTERPRISE_BANDMASTER0_UID,\n"
+ "> +\tOPAL_ENTERPRISE_ERASEMASTER_UID,\n"
+ "> +\t/* tables */\n"
+ "> +\tOPAL_LOCKINGRANGE_GLOBAL,\n"
+ "> +\tOPAL_LOCKINGRANGE_ACE_RDLOCKED,\n"
+ "> +\tOPAL_LOCKINGRANGE_ACE_WRLOCKED,\n"
+ "> +\tOPAL_MBRCONTROL,\n"
+ "> +\tOPAL_MBR,\n"
+ "> +\tOPAL_AUTHORITY_TABLE,\n"
+ "> +\tOPAL_C_PIN_TABLE,\n"
+ "> +\tOPAL_LOCKING_INFO_TABLE,\n"
+ "> +\tOPAL_ENTERPRISE_LOCKING_INFO_TABLE,\n"
+ "> +\t/* C_PIN_TABLE object ID's */\n"
+ "> +\tOPAL_C_PIN_MSID,\n"
+ "> +\tOPAL_C_PIN_SID,\n"
+ "> +\tOPAL_C_PIN_ADMIN1,\n"
+ "> +\t/* half UID's (only first 4 bytes used) */\n"
+ "> +\tOPAL_HALF_UID_AUTHORITY_OBJ_REF,\n"
+ "> +\tOPAL_HALF_UID_BOOLEAN_ACE,\n"
+ "> +\t/* omitted optional parameter */\n"
+ "> +\tOPAL_UID_HEXFF,\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * TCG Storage SSC Methods.\n"
+ "> + */\n"
+ "> +static const u8 OPALMETHOD[][8] = {\n"
+ "> +\t/* Properties */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01 },\n"
+ "> +\t/* STARTSESSION */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02 },\n"
+ "> +\t/* Revert */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02 },\n"
+ "> +\t/* Activate */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03 },\n"
+ "> +\t/* Enterprise Get */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06 },\n"
+ "> +\t/* Enterprise Set */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07 },\n"
+ "> +\t/* NEXT */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08 },\n"
+ "> +\t/* Enterprise Authenticate */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c },\n"
+ "> +\t/* GetACL */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d },\n"
+ "> +\t/* GenKey */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10 },\n"
+ "> +\t/* revertSP */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11 },\n"
+ "> +\t/* Get */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16 },\n"
+ "> +\t/* Set */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17 },\n"
+ "> +\t/* Authenticate */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c },\n"
+ "> +\t/* Random */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 },\n"
+ "> +\t/* Erase */\n"
+ "> +\t{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 },\n"
+ "> +};\n"
+ "> +static const size_t OPAL_METHOD_LENGTH = 8;\n"
+ "> +\n"
+ "> +/* Enum for indexing the OPALMETHOD array */\n"
+ "> +enum OPAL_METHOD {\n"
+ "> +\tOPAL_PROPERTIES,\n"
+ "> +\tOPAL_STARTSESSION,\n"
+ "> +\tOPAL_REVERT,\n"
+ "> +\tOPAL_ACTIVATE,\n"
+ "> +\tOPAL_EGET,\n"
+ "> +\tOPAL_ESET,\n"
+ "> +\tOPAL_NEXT,\n"
+ "> +\tOPAL_EAUTHENTICATE,\n"
+ "> +\tOPAL_GETACL,\n"
+ "> +\tOPAL_GENKEY,\n"
+ "> +\tOPAL_REVERTSP,\n"
+ "> +\tOPAL_GET,\n"
+ "> +\tOPAL_SET,\n"
+ "> +\tOPAL_AUTHENTICATE,\n"
+ "> +\tOPAL_RANDOM,\n"
+ "> +\tOPAL_ERASE,\n"
+ "> +};\n"
+ "> +\n"
+ "> +enum OPAL_RESPONSE_TOKEN {\n"
+ "> +\tOPAL_DTA_TOKENID_BYTESTRING = 0xe0,\n"
+ "> +\tOPAL_DTA_TOKENID_SINT = 0xe1,\n"
+ "> +\tOPAL_DTA_TOKENID_UINT = 0xe2,\n"
+ "> +\tOPAL_DTA_TOKENID_TOKEN = 0xe3, /* actual token is returned */\n"
+ "> +\tOPAL_DTA_TOKENID_INVALID = 0X0\n"
+ "> +};\n"
+ "> +\n"
+ "> +enum OPAL_TOKEN {\n"
+ "> +\t/* Boolean */\n"
+ "> +\tOPAL_TRUE = 0x01,\n"
+ "> +\tOPAL_FALSE = 0x00,\n"
+ "> +\tOPAL_BOOLEAN_EXPR = 0x03,\n"
+ "> +\t/* cellblocks */\n"
+ "> +\tOPAL_TABLE = 0x00,\n"
+ "> +\tOPAL_STARTROW = 0x01,\n"
+ "> +\tOPAL_ENDROW = 0x02,\n"
+ "> +\tOPAL_STARTCOLUMN = 0x03,\n"
+ "> +\tOPAL_ENDCOLUMN = 0x04,\n"
+ "> +\tOPAL_VALUES = 0x01,\n"
+ "> +\t/* authority table */\n"
+ "> +\tOPAL_PIN = 0x03,\n"
+ "> +\t/* locking tokens */\n"
+ "> +\tOPAL_RANGESTART = 0x03,\n"
+ "> +\tOPAL_RANGELENGTH = 0x04,\n"
+ "> +\tOPAL_READLOCKENABLED = 0x05,\n"
+ "> +\tOPAL_WRITELOCKENABLED = 0x06,\n"
+ "> +\tOPAL_READLOCKED = 0x07,\n"
+ "> +\tOPAL_WRITELOCKED = 0x08,\n"
+ "> +\tOPAL_ACTIVEKEY = 0x0A,\n"
+ "> +\t/* locking info table */\n"
+ "> +\tOPAL_MAXRANGES = 0x04,\n"
+ "> +\t /* mbr control */\n"
+ "> +\tOPAL_MBRENABLE = 0x01,\n"
+ "> +\tOPAL_MBRDONE = 0x02,\n"
+ "> +\t/* properties */\n"
+ "> +\tOPAL_HOSTPROPERTIES = 0x00,\n"
+ "> +\t/* atoms */\n"
+ "> +\tOPAL_STARTLIST = 0xf0,\n"
+ "> +\tOPAL_ENDLIST = 0xf1,\n"
+ "> +\tOPAL_STARTNAME = 0xf2,\n"
+ "> +\tOPAL_ENDNAME = 0xf3,\n"
+ "> +\tOPAL_CALL = 0xf8,\n"
+ "> +\tOPAL_ENDOFDATA = 0xf9,\n"
+ "> +\tOPAL_ENDOFSESSION = 0xfa,\n"
+ "> +\tOPAL_STARTTRANSACTON = 0xfb,\n"
+ "> +\tOPAL_ENDTRANSACTON = 0xfC,\n"
+ "> +\tOPAL_EMPTYATOM = 0xff,\n"
+ "> +\tOPAL_WHERE = 0x00,\n"
+ "> +};\n"
+ "> +\n"
+ "> +/* Useful tiny atoms.\n"
+ "> + * Useful for table columns etc\n"
+ "> + */\n"
+ "> +enum OPAL_TINY_ATOM {\n"
+ "> +\tOPAL_TINY_UINT_00 = 0x00,\n"
+ "> +\tOPAL_TINY_UINT_01 = 0x01,\n"
+ "> +\tOPAL_TINY_UINT_02 = 0x02,\n"
+ "> +\tOPAL_TINY_UINT_03 = 0x03,\n"
+ "> +\tOPAL_TINY_UINT_04 = 0x04,\n"
+ "> +\tOPAL_TINY_UINT_05 = 0x05,\n"
+ "> +\tOPAL_TINY_UINT_06 = 0x06,\n"
+ "> +\tOPAL_TINY_UINT_07 = 0x07,\n"
+ "> +\tOPAL_TINY_UINT_08 = 0x08,\n"
+ "> +\tOPAL_TINY_UINT_09 = 0x09,\n"
+ "> +\tOPAL_TINY_UINT_10 = 0x0a,\n"
+ "> +\tOPAL_TINY_UINT_11 = 0x0b,\n"
+ "> +\tOPAL_TINY_UINT_12 = 0x0c,\n"
+ "> +\tOPAL_TINY_UINT_13 = 0x0d,\n"
+ "> +\tOPAL_TINY_UINT_14 = 0x0e,\n"
+ "> +\tOPAL_TINY_UINT_15 = 0x0f,\n"
+ "> +};\n"
+ "> +\n"
+ "> +enum OPAL_ATOM_WIDTH {\n"
+ "> +\tOPAL_WIDTH_TINY,\n"
+ "> +\tOPAL_WIDTH_SHORT,\n"
+ "> +\tOPAL_WIDTH_MEDIUM,\n"
+ "> +\tOPAL_WIDTH_LONG,\n"
+ "> +\tOPAL_WIDTH_TOKEN\n"
+ "> +};\n"
+ "> +\n"
+ "> +/* Locking state for a locking range */\n"
+ "> +enum OPAL_LOCKINGSTATE {\n"
+ "> +\tOPAL_LOCKING_READWRITE = 0x01,\n"
+ "> +\tOPAL_LOCKING_READONLY = 0x02,\n"
+ "> +\tOPAL_LOCKING_LOCKED = 0x03,\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * Structures to build and decode the Opal SSC messages\n"
+ "> + * fields that are NOT really numeric are defined as u8[] to\n"
+ "> + * help reduce the endianness issues\n"
+ "> + */\n"
+ "> +\n"
+ "> +/* Comm Packet (header) for transmissions. */\n"
+ "> +struct opal_compacket {\n"
+ "> +\tu32 reserved0;\n"
+ "> +\tu8 extendedComID[4];\n"
+ "> +\tu32 outstandingData;\n"
+ "> +\tu32 minTransfer;\n"
+ "> +\tu32 length;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/* Packet structure. */\n"
+ "> +struct opal_packet {\n"
+ "> +\tu32 TSN;\n"
+ "> +\tu32 HSN;\n"
+ "> +\tu32 seq_number;\n"
+ "> +\tu16 reserved0;\n"
+ "> +\tu16 ack_type;\n"
+ "> +\tu32 acknowledgment;\n"
+ "> +\tu32 length;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/* Data sub packet header */\n"
+ "> +struct opal_data_subpacket {\n"
+ "> +\tu8 reserved0[6];\n"
+ "> +\tu16 kind;\n"
+ "> +\tu32 length;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/* header of a response */\n"
+ "> +struct opal_header {\n"
+ "> +\tstruct opal_compacket cp;\n"
+ "> +\tstruct opal_packet pkt;\n"
+ "> +\tstruct opal_data_subpacket subpkt;\n"
+ "> +};\n"
+ "> +\n"
+ "> +#define FC_TPER       0x0001\n"
+ "> +#define FC_LOCKING    0x0002\n"
+ "> +#define FC_GEOMETRY   0x0003\n"
+ "> +#define FC_ENTERPRISE 0x0100\n"
+ "> +#define FC_DATASTORE  0x0202\n"
+ "> +#define FC_SINGLEUSER 0x0201\n"
+ "> +#define FC_OPALV100   0x0200\n"
+ "> +#define FC_OPALV200   0x0203\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * The Discovery 0 Header. As defined in\n"
+ "> + * Opal SSC Documentation\n"
+ "> + */\n"
+ "> +struct d0_header {\n"
+ "> +\tu32 length; /* the length of the header 48 in 2.00.100 */\n"
+ "> +\tu32 revision; /**< revision of the header 1 in 2.00.100 */\n"
+ "> +\tu32 reserved01;\n"
+ "> +\tu32 reserved02;\n"
+ "> +\t/*\n"
+ "> +\t * the remainder of the structure is vendor specific and will not be\n"
+ "> +\t * addressed now\n"
+ "> +\t */\n"
+ "> +\tu8 ignored[32];\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * TPer Feature Descriptor. Contains flags indicating support for the\n"
+ "> + * TPer features described in the OPAL specification. The names match the\n"
+ "> + * OPAL terminology\n"
+ "> + *\n"
+ "> + * code == 0x001 in 2.00.100\n"
+ "> + */\n"
+ "> +struct d0_tper_features {\n"
+ "> +\t/*\n"
+ "> +\t * supported_features bits:\n"
+ "> +\t * bit 7: reserved\n"
+ "> +\t * bit 6: com ID management\n"
+ "> +\t * bit 5: reserved\n"
+ "> +\t * bit 4: streaming support\n"
+ "> +\t * bit 3: buffer management\n"
+ "> +\t * bit 2: ACK/NACK\n"
+ "> +\t * bit 1: async\n"
+ "> +\t * bit 0: sync\n"
+ "> +\t */\n"
+ "> +\tu8 supported_features;\n"
+ "> +\t/*\n"
+ "> +\t * bytes 5 through 15 are reserved, but we represent the first 3 as\n"
+ "> +\t * u8 to keep the other two 32bits integers aligned.\n"
+ "> +\t */\n"
+ "> +\tu8 reserved01[3];\n"
+ "> +\tu32 reserved02;\n"
+ "> +\tu32 reserved03;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * Locking Feature Descriptor. Contains flags indicating support for the\n"
+ "> + * locking features described in the OPAL specification. The names match the\n"
+ "> + * OPAL terminology\n"
+ "> + *\n"
+ "> + * code == 0x0002 in 2.00.100\n"
+ "> + */\n"
+ "> +struct d0_locking_features {\n"
+ "> +\t/*\n"
+ "> +\t * supported_features bits:\n"
+ "> +\t * bits 6-7: reserved\n"
+ "> +\t * bit 5: MBR done\n"
+ "> +\t * bit 4: MBR enabled\n"
+ "> +\t * bit 3: media encryption\n"
+ "> +\t * bit 2: locked\n"
+ "> +\t * bit 1: locking enabled\n"
+ "> +\t * bit 0: locking supported\n"
+ "> +\t */\n"
+ "> +\tu8 supported_features;\n"
+ "> +\t/*\n"
+ "> +\t * bytes 5 through 15 are reserved, but we represent the first 3 as\n"
+ "> +\t * u8 to keep the other two 32bits integers aligned.\n"
+ "> +\t */\n"
+ "> +\tu8 reserved01[3];\n"
+ "> +\tu32 reserved02;\n"
+ "> +\tu32 reserved03;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * Geometry Feature Descriptor. Contains flags indicating support for the\n"
+ "> + * geometry features described in the OPAL specification. The names match the\n"
+ "> + * OPAL terminology\n"
+ "> + *\n"
+ "> + * code == 0x0003 in 2.00.100\n"
+ "> + */\n"
+ "> +struct d0_geometry_features {\n"
+ "> +\t/*\n"
+ "> +\t * skip 32 bits from header, needed to align the struct to 64 bits.\n"
+ "> +\t */\n"
+ "> +\tu8 header[4];\n"
+ "> +\t/*\n"
+ "> +\t * reserved01:\n"
+ "> +\t * bits 1-6: reserved\n"
+ "> +\t * bit 0: align\n"
+ "> +\t */\n"
+ "> +\tu8 reserved01;\n"
+ "> +\tu8 reserved02[7];\n"
+ "> +\tu32 logical_block_size;\n"
+ "> +\tu64 alignment_granularity;\n"
+ "> +\tu64 lowest_aligned_lba;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * Enterprise SSC Feature\n"
+ "> + *\n"
+ "> + * code == 0x0100\n"
+ "> + */\n"
+ "> +struct d0_enterprise_ssc {\n"
+ "> +\tu16 baseComID;\n"
+ "> +\tu16 numComIDs;\n"
+ "> +\t/* range_crossing:\n"
+ "> +\t * bits 1-6: reserved\n"
+ "> +\t * bit 0: range crossing\n"
+ "> +\t */\n"
+ "> +\tu8 range_crossing;\n"
+ "> +\tu8 reserved01;\n"
+ "> +\tu16 reserved02;\n"
+ "> +\tu32 reserved03;\n"
+ "> +\tu32 reserved04;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * Opal V1 feature\n"
+ "> + *\n"
+ "> + * code == 0x0200\n"
+ "> + */\n"
+ "> +struct d0_opal_v100 {\n"
+ "> +\tu16 baseComID;\n"
+ "> +\tu16 numComIDs;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * Single User Mode feature\n"
+ "> + *\n"
+ "> + * code == 0x0201\n"
+ "> + */\n"
+ "> +struct d0_single_user_mode {\n"
+ "> +\tu32 num_locking_objects;\n"
+ "> +\t/* reserved01:\n"
+ "> +\t * bit 0: any\n"
+ "> +\t * bit 1: all\n"
+ "> +\t * bit 2: policy\n"
+ "> +\t * bits 3-7: reserved\n"
+ "> +\t */\n"
+ "> +\tu8 reserved01;\n"
+ "> +\tu8 reserved02;\n"
+ "> +\tu16 reserved03;\n"
+ "> +\tu32 reserved04;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * Additonal Datastores feature\n"
+ "> + *\n"
+ "> + * code == 0x0202\n"
+ "> + */\n"
+ "> +struct d0_datastore_table {\n"
+ "> +\tu16 reserved01;\n"
+ "> +\tu16 max_tables;\n"
+ "> +\tu32 max_size_tables;\n"
+ "> +\tu32 table_size_alignment;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/*\n"
+ "> + * OPAL 2.0 feature\n"
+ "> + *\n"
+ "> + * code == 0x0203\n"
+ "> + */\n"
+ "> +struct d0_opal_v200 {\n"
+ "> +\tu16 baseComID;\n"
+ "> +\tu16 numComIDs;\n"
+ "> +\t/* range_crossing:\n"
+ "> +\t * bits 1-6: reserved\n"
+ "> +\t * bit 0: range crossing\n"
+ "> +\t */\n"
+ "> +\tu8 range_crossing;\n"
+ "> +\t/* num_locking_admin_auth:\n"
+ "> +\t * not aligned to 16 bits, so use two u8.\n"
+ "> +\t * stored in big endian:\n"
+ "> +\t * 0: MSB\n"
+ "> +\t * 1: LSB\n"
+ "> +\t */\n"
+ "> +\tu8 num_locking_admin_auth[2];\n"
+ "> +\t/* num_locking_user_auth:\n"
+ "> +\t * not aligned to 16 bits, so use two u8.\n"
+ "> +\t * stored in big endian:\n"
+ "> +\t * 0: MSB\n"
+ "> +\t * 1: LSB\n"
+ "> +\t */\n"
+ "> +\tu8 num_locking_user_auth[2];\n"
+ "> +\tu8 initialPIN;\n"
+ "> +\tu8 revertedPIN;\n"
+ "> +\tu8 reserved01;\n"
+ "> +\tu32 reserved02;\n"
+ "> +};\n"
+ "> +\n"
+ "> +/* Union of features used to parse the discovery 0 response */\n"
+ "> +struct d0_features {\n"
+ "> +\tu16 code;\n"
+ "> +\t/*\n"
+ "> +\t * r_version bits:\n"
+ "> +\t * bits 4-7: version\n"
+ "> +\t * bits 0-3: reserved\n"
+ "> +\t */\n"
+ "> +\tu8 r_version;\n"
+ "> +\tu8 length;\n"
+ "> +\tu8 features[];\n"
+ "> +};\n"
+ "> +\n"
+ "> +struct key *request_user_key(const char *master_desc, const u8 **master_key,\n"
+ "> +\t\t\t     size_t *master_keylen);\n"
+ "> +\n"
+ "> +#endif /* _NVME_OPAL_INTERNAL_H */\n"
+ "> diff --git a/lib/sed-opal_key.c b/lib/sed-opal_key.c\n"
+ "> new file mode 100644\n"
+ "> index 0000000..0b4de01\n"
+ "> --- /dev/null\n"
+ "> +++ b/lib/sed-opal_key.c\n"
+ "> @@ -0,0 +1,46 @@\n"
+ "> +/*\n"
+ "> + * Copyright ? 2016 Intel Corporation\n"
+ "> + *\n"
+ "> + * Permission is hereby granted, free of charge, to any person obtaining a\n"
+ "> + * copy of this software and associated documentation files (the \"Software\"),\n"
+ "> + * to deal in the Software without restriction, including without limitation\n"
+ "> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n"
+ "> + * and/or sell copies of the Software, and to permit persons to whom the\n"
+ "> + * Software is furnished to do so, subject to the following conditions:\n"
+ "> + *\n"
+ "> + * The above copyright notice and this permission notice (including the next\n"
+ "> + * paragraph) shall be included in all copies or substantial portions of the\n"
+ "> + * Software.\n"
+ "> + *\n"
+ "> + * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
+ "> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
+ "> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n"
+ "> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
+ "> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n"
+ "> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n"
+ "> + * IN THE SOFTWARE.\n"
+ "> + *\n"
+ "> + * Author:\n"
+ "> + *    Rafael Antognolli <rafael.antognolli at intel.com>\n"
+ "> + */\n"
+ "> +\n"
+ "> +#include <linux/key.h>\n"
+ "> +#include \"sed-opal_internal.h\"\n"
+ "> +\n"
+ "> +struct key *request_user_key(const char *master_desc, const u8 **master_key,\n"
+ "> +\t\t\t     size_t *master_keylen)\n"
+ "> +{\n"
+ "> +\tconst struct user_key_payload *upayload;\n"
+ "> +\tstruct key *ukey;\n"
+ "> +\n"
+ "> +\tukey = request_key(&key_type_user, master_desc, NULL);\n"
+ "> +\tif (IS_ERR(ukey))\n"
+ "> +\t\tgoto error;\n"
+ "> +\n"
+ "> +\tdown_read(&ukey->sem);\n"
+ "> +\tupayload = user_key_payload(ukey);\n"
+ "> +\t*master_key = upayload->data;\n"
+ "> +\t*master_keylen = upayload->datalen;\n"
+ "> +error:\n"
+ "> +\treturn ukey;\n"
+ "> +}\n"
+ "> diff --git a/lib/sed.c b/lib/sed.c\n"
+ "> new file mode 100644\n"
+ "> index 0000000..06cacd9\n"
+ "> --- /dev/null\n"
+ "> +++ b/lib/sed.c\n"
+ "> @@ -0,0 +1,303 @@\n"
+ "> +#include <linux/blkdev.h>\n"
+ "> +#include <linux/sed.h>\n"
+ "> +#include <linux/sed-opal.h>\n"
+ "> +\n"
+ "> +#ifndef CONFIG_SED_OPAL\n"
+ "> +static int sed_opal_save(struct block_device *bdev, struct sed_key *sed)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +static int sed_opal_take_ownership(struct block_device *bdev, struct sed_key *key)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +static int sed_opal_activate_lsp(struct block_device *bdev, struct sed_key *key)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +static int sed_opal_set_pw(struct block_device *bdev, struct sed_key *key)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +static int sed_opal_activate_user(struct block_device *bdev, struct sed_key *key)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +static int sed_opal_reverttper(struct block_device *bdev, struct sed_key *key)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +static int sed_opal_setup_locking_range(struct block_device *bdev, struct sed_key *key)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +static int sed_opal_adduser_to_lr(struct block_device *bdev, struct sed_key *key)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +static int sed_opal_do_mbr(struct block_device *bdev, struct sed_key *key)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +static int sed_opal_erase_lr(struct block_device *bdev, struct sed_key *key)\n"
+ "> +\t{ return -EOPNOTSUPP; }\n"
+ "> +\n"
+ "> +#else\n"
+ "> +\n"
+ "> +static int sed_opal_save(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "You might consider pulling this boilerplate out into something like:\n"
+ "static inline bool bdev_sec_capable(struct block_device *bdev)\n"
+ "{\n"
+ "\treturn bdev && bdev->bd_disk && bdev->bd_disk->fops &&\n"
+ "\t       bdev->bd_disk->fops->sec_ops;\n"
+ "}\n"
+ "\n"
+ "\n"
+ "> +\n"
+ "> +\treturn opal_save(bdev, key);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\treturn opal_lock_unlock(bdev, key);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int sed_opal_take_ownership(struct block_device *bdev,\n"
+ "> +\t\t\t\t   struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\treturn opal_take_ownership(bdev, key);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int sed_opal_activate_lsp(struct block_device *bdev,\n"
+ "> +\t\t\t\t struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\treturn opal_activate_lsp(bdev, key);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int sed_opal_set_pw(struct block_device *bdev,\n"
+ "> +\t\t\t   struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\treturn opal_set_new_pw(bdev, key);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int sed_opal_activate_user(struct block_device *bdev,\n"
+ "> +\t\t\t\t  struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\treturn opal_activate_user(bdev, key);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int sed_opal_reverttper(struct block_device *bdev,\n"
+ "> +\t\t\t       struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\treturn opal_reverttper(bdev, key);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int sed_opal_setup_lr(struct block_device *bdev,\n"
+ "> +\t\t\t     struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\treturn opal_setup_locking_range(bdev, key);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int sed_opal_adduser_to_lr(struct block_device *bdev,\n"
+ "> +\t\t\t     struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\treturn opal_add_user_to_lr(bdev, key);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int sed_opal_do_mbr(struct block_device *bdev,\n"
+ "> +\t\t\t   struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\treturn opal_enable_disable_shadow_mbr(bdev, key);\n"
+ "> +}\n"
+ "> +\n"
+ "> +static int sed_opal_erase_lr(struct block_device *bdev,\n"
+ "> +\t\t\t     struct sed_key *key)\n"
+ "> +{\n"
+ "> +\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\treturn opal_erase_locking_range(bdev, key);\n"
+ "> +}\n"
+ "> +#endif\n"
+ "> +\n"
+ "> +int sed_save(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL_LOCK_UNLOCK:\n"
+ "> +\t\treturn sed_opal_save(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int sed_lock_unlock(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL_LOCK_UNLOCK:\n"
+ "> +\t\treturn sed_opal_lock_unlock(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int sed_take_ownership(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL:\n"
+ "> +\t\treturn sed_opal_take_ownership(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int sed_activate_lsp(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL:\n"
+ "> +\t\treturn sed_opal_activate_lsp(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int sed_set_pw(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL_PW:\n"
+ "> +\t\treturn sed_opal_set_pw(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int sed_activate_user(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL_ACT_USR:\n"
+ "> +\t\treturn sed_opal_activate_user(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int sed_reverttper(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL:\n"
+ "> +\t\treturn sed_opal_reverttper(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL_LR_SETUP:\n"
+ "> +\t\treturn sed_opal_setup_lr(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL_LOCK_UNLOCK:\n"
+ "> +\t\treturn sed_opal_adduser_to_lr(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int sed_do_mbr(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL_MBR_DATA:\n"
+ "> +\t\treturn sed_opal_do_mbr(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> +\n"
+ "> +int sed_erase_lr(struct block_device *bdev, struct sed_key *key)\n"
+ "> +{\n"
+ "> +\tif (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops ||\n"
+ "> +\t    !bdev->bd_disk->fops->sec_ops)\n"
+ "> +\t\treturn -EOPNOTSUPP;\n"
+ "> +\n"
+ "> +\tswitch (key->sed_type) {\n"
+ "> +\tcase OPAL:\n"
+ "> +\t\treturn sed_opal_erase_lr(bdev, key);\n"
+ "> +\t}\n"
+ "> +\n"
+ "> +\treturn -EOPNOTSUPP;\n"
+ "> +}\n"
+ "> -- \n"
+ "> 2.7.4\n"
+ >
 
-62cf4897561e4d8b58790969c0fea5a770d1084ea226a7cbca291bc8e7564116
+78cf69019b1ed9a92cb63b1fc5031e1d930afeabe0583451d3c08980d0d5254b

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.