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.