From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Tue, 1 Nov 2016 12:56:11 -0600 From: Jon Derrick To: Scott Bauer Subject: Re: [RFC PATCH 2/6] lib: Add Sed-opal library Message-ID: <20161101185611.GA1999@localhost.localdomain> References: <1477951099-3127-1-git-send-email-scott.bauer@intel.com> <1477951099-3127-3-git-send-email-scott.bauer@intel.com> MIME-Version: 1.0 In-Reply-To: <1477951099-3127-3-git-send-email-scott.bauer@intel.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: keith.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 Content-Type: text/plain; charset="utf-8" Sender: "Linux-nvme" Errors-To: linux-nvme-bounces+axboe=kernel.dk@lists.infradead.org List-ID: 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= From mboxrd@z Thu Jan 1 00:00:00 1970 From: jonathan.derrick@intel.com (Jon Derrick) Date: Tue, 1 Nov 2016 12:56:11 -0600 Subject: [RFC PATCH 2/6] lib: Add Sed-opal library In-Reply-To: <1477951099-3127-3-git-send-email-scott.bauer@intel.com> References: <1477951099-3127-1-git-send-email-scott.bauer@intel.com> <1477951099-3127-3-git-send-email-scott.bauer@intel.com> Message-ID: <20161101185611.GA1999@localhost.localdomain> 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 > Signed-off-by: Rafael Antognolli > --- > 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 > + * Scott Bauer > + */ > + > +#define pr_fmt(fmt) KBUILD_MODNAME ":OPAL: " fmt > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#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 > + * Scott Bauer > + */ > + > +#ifndef _NVME_OPAL_INTERNAL_H > +#define _NVME_OPAL_INTERNAL_H > + > +#include > +#include > + > +#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 > + */ > + > +#include > +#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 > +#include > +#include > + > +#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 >