From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Scott Bauer To: linux-nvme@lists.infradead.org Subject: [PATCH v1 2/7] lib: Add Sed-opal library Date: Wed, 16 Nov 2016 16:17:27 -0700 Message-Id: <1479338252-8777-3-git-send-email-scott.bauer@intel.com> In-Reply-To: <1479338252-8777-1-git-send-email-scott.bauer@intel.com> References: <1479338252-8777-1-git-send-email-scott.bauer@intel.com> MIME-Version: 1.0 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: keith.busch@intel.com, sagi@grimberg.me, hch@infradead.org, Rafael.Antognolli@intel.com, axboe@fb.com, linux-block@vger.kernel.org, Scott Bauer , jonathan.derrick@intel.com, 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: VGhpcyBwYXRjaCBpbXBsZW1lbnRzIHRoZSBuZWNlc3NhcnkgbG9naWMgdG8gYnJpbmcgYW4gT3Bh bAplbmFibGVkIGRyaXZlIG91dCBvZiBhIGZhY3RvcnktZW5hYmxlZCBpbnRvIGEgd29ya2luZwpP cGFsIHN0YXRlLgoKVGhpcyBwYXRjaCBzZXQgYWxzbyBlbmFibGVzIGxvZ2ljIHRvIHNhdmUgYSBw YXNzd29yZCB0bwpiZSByZXBsYXllZCBkdXJpbmcgYSByZXN1bWUgZnJvbSBzdXNwZW5kLiBUaGUg a2V5IGNhbiBiZQpzYXZlZCBpbiB0aGUgZHJpdmVyIG9yIGluIHRoZSBLZXJuZWwncyBLZXkgbWFu YWdtZW50LgoKU2lnbmVkLW9mZi1ieTogU2NvdHQgQmF1ZXIgPHNjb3R0LmJhdWVyQGludGVsLmNv bT4KU2lnbmVkLW9mZi1ieTogUmFmYWVsIEFudG9nbm9sbGkgPFJhZmFlbC5BbnRvZ25vbGxpQGlu dGVsLmNvbT4KLS0tCiBsaWIvc2VkLW9wYWwuYyAgICAgICAgICB8IDMzMzggKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIGxpYi9zZWQtb3BhbF9pbnRlcm5h bC5oIHwgIDU4NyArKysrKysrKysKIGxpYi9zZWQtb3BhbF9rZXkuYyAgICAgIHwgICA0NiArCiBs aWIvc2VkLmMgICAgICAgICAgICAgICB8ICAyNTAgKysrKwogNCBmaWxlcyBjaGFuZ2VkLCA0MjIx IGluc2VydGlvbnMoKykKIGNyZWF0ZSBtb2RlIDEwMDY0NCBsaWIvc2VkLW9wYWwuYwogY3JlYXRl IG1vZGUgMTAwNjQ0IGxpYi9zZWQtb3BhbF9pbnRlcm5hbC5oCiBjcmVhdGUgbW9kZSAxMDA2NDQg bGliL3NlZC1vcGFsX2tleS5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL3NlZC5jCgpkaWZmIC0t Z2l0IGEvbGliL3NlZC1vcGFsLmMgYi9saWIvc2VkLW9wYWwuYwpuZXcgZmlsZSBtb2RlIDEwMDY0 NAppbmRleCAwMDAwMDAwLi4zY2UxMTI2Ci0tLSAvZGV2L251bGwKKysrIGIvbGliL3NlZC1vcGFs LmMKQEAgLTAsMCArMSwzMzM4IEBACisvKgorICogQ29weXJpZ2h0IMKpIDIwMTYgSW50ZWwgQ29y cG9yYXRpb24KKyAqCisgKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNo YXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYQorICogY29weSBvZiB0aGlzIHNvZnR3YXJl IGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSAiU29mdHdhcmUiKSwKKyAq IHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3 aXRob3V0IGxpbWl0YXRpb24KKyAqIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1l cmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLAorICogYW5kL29yIHNlbGwgY29w aWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlCisg KiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2lu ZyBjb25kaXRpb25zOgorICoKKyAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlz IHBlcm1pc3Npb24gbm90aWNlIChpbmNsdWRpbmcgdGhlIG5leHQKKyAqIHBhcmFncmFwaCkgc2hh bGwgYmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0 aGUKKyAqIFNvZnR3YXJlLgorICoKKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMi LCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCisgKiBJTVBMSUVELCBJ TkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJ TElUWSwKKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5H RU1FTlQuICBJTiBOTyBFVkVOVCBTSEFMTAorICogVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhP TERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJ TElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNF LCBBUklTSU5HCisgKiBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZU V0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTCisgKiBJTiBUSEUgU09GVFdBUkUuCisg KgorICogQXV0aG9yczoKKyAqICAgIFJhZmFlbCBBbnRvZ25vbGxpIDxyYWZhZWwuYW50b2dub2xs aUBpbnRlbC5jb20+CisgKiAgICBTY290dCAgQmF1ZXIgICAgICA8c2NvdHQuYmF1ZXJAaW50ZWwu Y29tPgorICovCisKKyNkZWZpbmUgcHJfZm10KGZtdCkgS0JVSUxEX01PRE5BTUUgIjpPUEFMOiAi IGZtdAorCisjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4KKyNpbmNsdWRlIDxsaW51eC9kZXZpY2Uu aD4KKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KKyNpbmNsdWRlIDxsaW51eC9saXN0Lmg+Cisj aW5jbHVkZSA8bGludXgvZ2VuaGQuaD4KKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CisjaW5jbHVk ZSA8bGludXgvdWFjY2Vzcy5oPgorI2luY2x1ZGUgPHVhcGkvbGludXgvc2VkLW9wYWwuaD4KKyNp bmNsdWRlIDxsaW51eC9zZWQuaD4KKyNpbmNsdWRlIDxsaW51eC9zZWQtb3BhbC5oPgorI2luY2x1 ZGUgPGxpbnV4L3N0cmluZy5oPgorCisjaW5jbHVkZSAic2VkLW9wYWxfaW50ZXJuYWwuaCIKKwor I2RlZmluZSBJT19CVUZGRVJfTEVOR1RIIDIwNDgKKworI2RlZmluZSBNQVhfVE9LUyA2NAorCitz dHJ1Y3Qgb3BhbF9jbWQgeworCXN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXY7CisJc2VjX2NiICpj YjsKKwl2b2lkICpjYl9kYXRhOworCisJc2l6ZV90IHBvczsKKwl1OCBjbWRfYnVmW0lPX0JVRkZF Ul9MRU5HVEggKiAyXTsKKwl1OCByZXNwX2J1ZltJT19CVUZGRVJfTEVOR1RIICogMl07CisJdTgg KmNtZDsKKwl1OCAqcmVzcDsKK307CisKKy8qCisgKiBPbiB0aGUgcGFyc2VkIHJlc3BvbnNlLCB3 ZSBkb24ndCBzdG9yZSBhZ2FpbiB0aGUgdG9rcyB0aGF0IGFyZSBhbHJlYWR5CisgKiBzdG9yZWQg aW4gdGhlIHJlc3BvbnNlIGJ1ZmZlci4gSW5zdGVhZCwgZm9yIGVhY2ggdG9rZW4sIHdlIGp1c3Qg c3RvcmUgYQorICogcG9pbnRlciB0byB0aGUgcG9zaXRpb24gaW4gdGhlIGJ1ZmZlciB3aGVyZSB0 aGUgdG9rZW4gc3RhcnRzLCBhbmQgdGhlIHNpemUKKyAqIG9mIHRoZSB0b2tlbiBpbiBieXRlcy4K KyAqLworc3RydWN0IG9wYWxfcmVzcF90b2sgeworCWNvbnN0IHU4ICpwb3M7CisJc2l6ZV90IGxl bjsKKwllbnVtIE9QQUxfUkVTUE9OU0VfVE9LRU4gdHlwZTsKKwllbnVtIE9QQUxfQVRPTV9XSURU SCB3aWR0aDsKKwl1bmlvbiB7CisJCXU2NCB1OworCQlzNjQgczsKKwl9IHN0b3JlZDsKK307CisK Ky8qCisgKiBGcm9tIHRoZSByZXNwb25zZSBoZWFkZXIgaXQncyBub3QgcG9zc2libGUgdG8ga25v dyBob3cgbWFueSB0b2tlbnMgdGhlcmUgYXJlCisgKiBvbiB0aGUgcGF5bG9hZC4gU28gd2UgaGFy ZGNvZGUgdGhhdCB0aGUgbWF4aW11bSB3aWxsIGJlIE1BWF9UT0tTLCBhbmQgbGF0ZXIKKyAqIGlm IHdlIHN0YXJ0IGRlYWxpbmcgd2l0aCBtZXNzYWdlcyB0aGF0IGhhdmUgbW9yZSB0aGFuIHRoYXQs IHdlIGNhbiBpbmNyZWFzZQorICogdGhpcyBudW1iZXIuIFRoaXMgaXMgZG9uZSB0byBhdm9pZCBo YXZpbmcgdG8gbWFrZSB0d28gcGFzc2VzIHRocm91Z2ggdGhlCisgKiByZXNwb25zZSwgdGhlIGZp cnN0IG9uZSBjb3VudGluZyBob3cgbWFueSB0b2tlbnMgd2UgaGF2ZSBhbmQgdGhlIHNlY29uZCBv bmUKKyAqIGFjdHVhbGx5IHN0b3JpbmcgdGhlIHBvc2l0aW9ucy4KKyAqLworc3RydWN0IHBhcnNl ZF9yZXNwIHsKKwlpbnQgbnVtOworCXN0cnVjdCBvcGFsX3Jlc3BfdG9rIHRva3NbTUFYX1RPS1Nd OworfTsKKworc3RydWN0IG9wYWxfZGV2OworCit0eXBlZGVmIHZvaWQgKCpvcGFsX2NiKShpbnQg ZXJyb3IsIHN0cnVjdCBvcGFsX2RldiAqZGV2KTsKKwordHlwZWRlZiBpbnQgKCpvcGFsX3N0ZXAp KHN0cnVjdCBvcGFsX2RldiAqZGV2KTsKKworc3RydWN0IG9wYWxfY29tcGxldGlvbiB7CisJc3Ry dWN0IGNvbXBsZXRpb24gY21kX2NvbXBsZXRpb247CisJaW50IGNvbXBsZXRpb25fc3RhdHVzOwor fTsKKworc3RydWN0IG9wYWxfZGV2IHsKKwlzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2OworCXN0 cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJc3RydWN0IG9wYWxfbG9ja191bmxv Y2sgbGt1bDsKKwljb25zdCBvcGFsX3N0ZXAgKmZ1bmNzOworCXN0cnVjdCB3b3JrX3N0cnVjdCBv cGFsX3NlbmRfd29yazsKKwlzdHJ1Y3Qgd29ya19zdHJ1Y3Qgb3BhbF9yZWN2X3dvcms7CisJdm9p ZCAqKmZ1bmNfZGF0YTsKKwlib29sIHJlc3VtZV9mcm9tX3N1c3BlbmQ7CisJc3RydWN0IG9wYWxf c3VzcGVuZF91bmxrICpyZXN1bWVfZGF0YTsKKwlzaXplX3QgbnVtX2Z1bmNfZGF0YTsKKwlhdG9t aWNfdCBpbl91c2U7CisJc2VjdG9yX3Qgc3RhcnQ7CisJc2VjdG9yX3QgbGVuZ3RoOworCXU4IGxy OworCXU4IGtleV90eXBlOworCXU4IGtleV9uYW1lW09QQUxfS0VZX01BWF07CisJc2l6ZV90IGtl eV9uYW1lX2xlbjsKKwl1OCBrZXlbT1BBTF9LRVlfTUFYXTsKKwlzaXplX3Qga2V5X2xlbjsKKwl1 MTYgY29tSUQ7CisJdTMyIEhTTjsKKwl1MzIgVFNOOworCXU2NCBhbGlnbjsKKwl1NjQgbG93ZXN0 X2xiYTsKKwlzdHJ1Y3QgbGlzdF9oZWFkIG5vZGU7CisJY2hhciBkaXNrX25hbWVbRElTS19OQU1F X0xFTl07CisJaW50IHN0YXRlOworCisJc3RydWN0IG9wYWxfY21kIGNtZDsKKwlzdHJ1Y3QgcGFy c2VkX3Jlc3AgcGFyc2VkOworCisJc2l6ZV90IHByZXZfZF9sZW47CisJdm9pZCAqcHJldl9kYXRh OworCisJc2VjX2NiICpmaW5hbF9jYjsKKwl2b2lkICpmaW5hbF9jYl9kYXRhOworCW9wYWxfc3Rl cCBlcnJvcl9jYjsKKwl2b2lkICplcnJvcl9jYl9kYXRhOworCW9wYWxfY2Igb3Blcl9jYjsKK307 CisKK0xJU1RfSEVBRChvcGFsX2xpc3QpOworREVGSU5FX1NQSU5MT0NLKGxpc3Rfc3BpbmxvY2sp OworCitzdGF0aWMgdm9pZCBwcmludF9idWZmZXIoY29uc3QgdTggKnB0ciwgdTMyIGxlbmd0aCkK K3sKKyNpZmRlZiBERUJVRworCXByaW50X2hleF9kdW1wX2J5dGVzKCJPUEFMOiAiLCBEVU1QX1BS RUZJWF9PRkZTRVQsIHB0ciwgbGVuZ3RoKTsKKwlwcl9kZWJ1ZygiXG4iKTsKKyNlbmRpZgorfQor CisjZGVmaW5lIFRQRVJfU1lOQ19TVVBQT1JURUQgQklUKDApCisKK3N0YXRpYyBib29sIGNoZWNr X3RwZXIoY29uc3Qgdm9pZCAqZGF0YSkKK3sKKwljb25zdCBzdHJ1Y3QgZDBfdHBlcl9mZWF0dXJl cyAqdHBlciA9IGRhdGE7CisJdTggZmxhZ3MgPSB0cGVyLT5zdXBwb3J0ZWRfZmVhdHVyZXM7CisK KwlpZiAoIShmbGFncyAmIFRQRVJfU1lOQ19TVVBQT1JURUQpKSB7CisJCXByX2VycigiVFBlciBz eW5jIG5vdCBzdXBwb3J0ZWQuIGZsYWdzID0gJWRcbiIsCisJCSAgICAgICB0cGVyLT5zdXBwb3J0 ZWRfZmVhdHVyZXMpOworCQlyZXR1cm4gZmFsc2U7CisJfQorCisJcmV0dXJuIHRydWU7Cit9CisK K3N0YXRpYyBib29sIGNoZWNrX1NVTShjb25zdCB2b2lkICpkYXRhKQoreworCWNvbnN0IHN0cnVj dCBkMF9zaW5nbGVfdXNlcl9tb2RlICpzdW0gPSBkYXRhOworCXUzMiBubG8gPSBiZTMyX3RvX2Nw dShzdW0tPm51bV9sb2NraW5nX29iamVjdHMpOworCisJaWYgKG5sbyA9PSAwKSB7CisJCXByX2Vy cigiTmVlZCBhdCBsZWFzdCBvbmUgbG9ja2luZyBvYmplY3QuXG4iKTsKKwkJcmV0dXJuIGZhbHNl OworCX0KKworCXByX2RlYnVnKCJOdW1iZXIgb2YgbG9ja2luZyBvYmplY3RzOiAlZFxuIiwgbmxv KTsKKworCXJldHVybiB0cnVlOworfQorCitzdGF0aWMgdTE2IGdldF9jb21JRF92MTAwKGNvbnN0 IHZvaWQgKmRhdGEpCit7CisJY29uc3Qgc3RydWN0IGQwX29wYWxfdjEwMCAqdjEwMCA9IGRhdGE7 CisKKwlyZXR1cm4gYmUxNl90b19jcHUodjEwMC0+YmFzZUNvbUlEKTsKK30KKworc3RhdGljIHUx NiBnZXRfY29tSURfdjIwMChjb25zdCB2b2lkICpkYXRhKQoreworCWNvbnN0IHN0cnVjdCBkMF9v cGFsX3YyMDAgKnYyMDAgPSBkYXRhOworCisJcmV0dXJuIGJlMTZfdG9fY3B1KHYyMDAtPmJhc2VD b21JRCk7Cit9CisKK3N0YXRpYyB2b2lkIG9wYWxfc2VuZF9jYl9jb250KGludCBlcnJvciwgdm9p ZCAqZGF0YSkKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJc2l6ZV90IGJ1Zmxl biA9IElPX0JVRkZFUl9MRU5HVEg7CisJdm9pZCAqYnVmZmVyID0gZGV2LT5jbWQucmVzcDsKKwlz dHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9IGJ1ZmZlcjsKKworCXByX2RlYnVnKCIlczogU2VudCBP UEFMIGNvbW1hbmQ6IGVycm9yPSVkLCBvdXRzdGFuZGluZz0lZCwgbWluVHJhbnNmZXI9JWRcbiIs CisJICAgICAgIGRldi0+ZGlza19uYW1lLCBlcnJvciwgaGRyLT5jcC5vdXRzdGFuZGluZ0RhdGEs CisJICAgICAgIGhkci0+Y3AubWluVHJhbnNmZXIpOworCisJaWYgKGVycm9yIHx8IGhkci0+Y3Au b3V0c3RhbmRpbmdEYXRhID09IDAgfHwKKwkgICAgaGRyLT5jcC5taW5UcmFuc2ZlciAhPSAwKSB7 CisJCWlmIChkZXYtPmNtZC5jYikKKwkJCWRldi0+Y21kLmNiKGVycm9yLCBkZXYtPmNtZC5jYl9k YXRhKTsKKwkJcmV0dXJuOworCX0KKworCW1lbXNldChidWZmZXIsIDAsIGJ1Zmxlbik7CisJc2No ZWR1bGVfd29yaygmZGV2LT5vcGFsX3JlY3Zfd29yayk7Cit9CisKK3N0YXRpYyB2b2lkIG9wYWxf c2VuZF9jYihpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYg PSBkYXRhOworCXNpemVfdCBidWZsZW4gPSBJT19CVUZGRVJfTEVOR1RIOworCXZvaWQgKmJ1ZmZl ciA9IGRldi0+Y21kLnJlc3A7CisKKwlpZiAoZXJyb3IpIHsKKwkJaWYgKGRldi0+Y21kLmNiKQor CQkJZGV2LT5jbWQuY2IoZXJyb3IsIGRldi0+Y21kLmNiX2RhdGEpOworCQlyZXR1cm47CisJfQor CisJbWVtc2V0KGJ1ZmZlciwgMCwgYnVmbGVuKTsKKwlzY2hlZHVsZV93b3JrKCZkZXYtPm9wYWxf cmVjdl93b3JrKTsKK30KKworc3RhdGljIGlubGluZSB2b2lkIGdldF9kYXRhX29wcyhzdHJ1Y3Qg b3BhbF9kZXYgKmRldiwgY29uc3Qgc3RydWN0IHNlY19vcHMgKipvcHMsCisJCQkJdm9pZCAqKmRh dGEpCit7CisJaWYgKGRldi0+cmVzdW1lX2Zyb21fc3VzcGVuZCkgeworCQkqb3BzID0gJmRldi0+ cmVzdW1lX2RhdGEtPm9wczsKKwkJKmRhdGEgPSBkZXYtPnJlc3VtZV9kYXRhLT5kYXRhOworCX0g ZWxzZSB7CisJCSpvcHMgPSBkZXYtPmJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHM7CisJCSpk YXRhID0gZGV2LT5iZGV2LT5iZF9kaXNrLT5wcml2YXRlX2RhdGE7CisJfQorfQorCitzdGF0aWMg dm9pZCBfb3BhbF9zZW5kX2NtZChzdHJ1Y3Qgd29ya19zdHJ1Y3QgKnNlbmRfd29yaykKK3sKKwlz dHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGNvbnRhaW5lcl9vZihzZW5kX3dvcmssIHN0cnVjdCBvcGFs X2RldiwKKwkJCQkJICAgIG9wYWxfc2VuZF93b3JrKTsKKwljb25zdCBzdHJ1Y3Qgc2VjX29wcyAq b3BzID0gTlVMTDsKKwl2b2lkICpkYXRhID0gTlVMTDsKKworCWdldF9kYXRhX29wcyhkZXYsICZv cHMsICZkYXRhKTsKKwlvcHMtPnNlbmQoZGF0YSwgZGV2LT5jb21JRCwgVENHX1NFQ1BfMDEsIGRl di0+Y21kLmNtZCwKKwkJICBJT19CVUZGRVJfTEVOR1RILCBvcGFsX3NlbmRfY2IsIGRldik7CisK K30KKworc3RhdGljIHZvaWQgX29wYWxfcmVjdl9jbWQoc3RydWN0IHdvcmtfc3RydWN0ICpyZWN2 X3dvcmspCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBjb250YWluZXJfb2YocmVjdl93b3Jr LCBzdHJ1Y3Qgb3BhbF9kZXYsCisJCQkJCSAgICBvcGFsX3JlY3Zfd29yayk7CisJY29uc3Qgc3Ry dWN0IHNlY19vcHMgKm9wczsKKwl2b2lkICpkYXRhOworCisJZ2V0X2RhdGFfb3BzKGRldiwgJm9w cywgJmRhdGEpOworCW9wcy0+cmVjdihkYXRhLCBkZXYtPmNvbUlELCBUQ0dfU0VDUF8wMSwgZGV2 LT5jbWQucmVzcCwKKwkJICBJT19CVUZGRVJfTEVOR1RILCBvcGFsX3NlbmRfY2JfY29udCwgZGV2 KTsKK30KKworc3RhdGljIHZvaWQgb3BhbF9zZW5kX3JlY3Yoc3RydWN0IG9wYWxfZGV2ICpkZXYs IHNlY19jYiAqY2IsIHZvaWQgKmNiX2RhdGEpCit7CisJZGV2LT5jbWQuY2IgPSBjYjsKKwlkZXYt PmNtZC5jYl9kYXRhID0gY2JfZGF0YTsKKwlzY2hlZHVsZV93b3JrKCZkZXYtPm9wYWxfc2VuZF93 b3JrKTsKK30KKworc3RhdGljIHZvaWQgY2hlY2tfZ2VvbWV0cnkoc3RydWN0IG9wYWxfZGV2ICpk ZXYsIGNvbnN0IHZvaWQgKmRhdGEpCit7CisJY29uc3Qgc3RydWN0IGQwX2dlb21ldHJ5X2ZlYXR1 cmVzICpnZW8gPSBkYXRhOworCisJZGV2LT5hbGlnbiA9IGdlby0+YWxpZ25tZW50X2dyYW51bGFy aXR5OworCWRldi0+bG93ZXN0X2xiYSA9IGdlby0+bG93ZXN0X2FsaWduZWRfbGJhOworfQorCitz dGF0aWMgdm9pZCBvcGFsX2Rpc2NvdmVyeTBfZW5kKGludCBlcnJvciwgdm9pZCAqZGF0YSkKK3sK Kwlib29sIGZvdW5kQ29tSUQgPSBmYWxzZSwgc3VwcG9ydGVkID0gdHJ1ZSwgc2luZ2xlX3VzZXIg PSBmYWxzZTsKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJY29uc3Qgc3RydWN0IGQw X2hlYWRlciAqaGRyOworCWNvbnN0IHU4ICplcG9zLCAqY3BvczsKKwl1MTYgY29tSUQgPSAwOwor CisJaWYgKGVycm9yKSB7CisJCXByX2VycigiJXM6IFNlbmRpbmcgZGlzY292ZXJ5MCBmYWlsZWRc biIsIGRldi0+ZGlza19uYW1lKTsKKwkJZ290byBlcnJfY2FsbGJhY2s7CisJfQorCisJZXBvcyA9 IGRldi0+Y21kLnJlc3A7CisJY3BvcyA9IGRldi0+Y21kLnJlc3A7CisJaGRyID0gKHN0cnVjdCBk MF9oZWFkZXIgKilkZXYtPmNtZC5yZXNwOworCisJcHJpbnRfYnVmZmVyKGRldi0+Y21kLnJlc3As IGJlMzJfdG9fY3B1KGhkci0+bGVuZ3RoKSk7CisKKwllcG9zICs9IGJlMzJfdG9fY3B1KGhkci0+ bGVuZ3RoKTsgLyogZW5kIG9mIGJ1ZmZlciAqLworCWNwb3MgKz0gc2l6ZW9mKCpoZHIpOyAvKiBj dXJyZW50IHBvc2l0aW9uIG9uIGJ1ZmZlciAqLworCisJd2hpbGUgKGNwb3MgPCBlcG9zICYmIHN1 cHBvcnRlZCkgeworCQljb25zdCBzdHJ1Y3QgZDBfZmVhdHVyZXMgKmJvZHkgPQorCQkJKGNvbnN0 IHN0cnVjdCBkMF9mZWF0dXJlcyAqKWNwb3M7CisKKwkJc3dpdGNoIChiZTE2X3RvX2NwdShib2R5 LT5jb2RlKSkgeworCQljYXNlIEZDX1RQRVI6CisJCQlzdXBwb3J0ZWQgPSBjaGVja190cGVyKGJv ZHktPmZlYXR1cmVzKTsKKwkJCWJyZWFrOworCQljYXNlIEZDX1NJTkdMRVVTRVI6CisJCQlzaW5n bGVfdXNlciA9IGNoZWNrX1NVTShib2R5LT5mZWF0dXJlcyk7CisJCQlicmVhazsKKwkJY2FzZSBG Q19HRU9NRVRSWToKKwkJCWNoZWNrX2dlb21ldHJ5KGRldiwgYm9keSk7CisJCQlicmVhazsKKwkJ Y2FzZSBGQ19MT0NLSU5HOgorCQljYXNlIEZDX0VOVEVSUFJJU0U6CisJCWNhc2UgRkNfREFUQVNU T1JFOgorCQkJLyogc29tZSBpZ25vcmVkIHByb3BlcnRpZXMgKi8KKwkJCXByX2RlYnVnKCIlczog Rm91bmQgT1BBTCBmZWF0dXJlIGRlc2NyaXB0aW9uOiAlZFxuIiwKKwkJCQkgZGV2LT5kaXNrX25h bWUsIGJlMTZfdG9fY3B1KGJvZHktPmNvZGUpKTsKKwkJCWJyZWFrOworCQljYXNlIEZDX09QQUxW MTAwOgorCQkJY29tSUQgPSBnZXRfY29tSURfdjEwMChib2R5LT5mZWF0dXJlcyk7CisJCQlmb3Vu ZENvbUlEID0gdHJ1ZTsKKwkJCWJyZWFrOworCQljYXNlIEZDX09QQUxWMjAwOgorCQkJY29tSUQg PSBnZXRfY29tSURfdjIwMChib2R5LT5mZWF0dXJlcyk7CisJCQlmb3VuZENvbUlEID0gdHJ1ZTsK KwkJCWJyZWFrOworCQljYXNlIDB4YmZmZiAuLi4gMHhmZmZmOgorCQkJLyogdmVuZG9yIHNwZWNp ZmljLCBqdXN0IGlnbm9yZSAqLworCQkJYnJlYWs7CisJCWRlZmF1bHQ6CisJCQlwcl93YXJuKCIl czogT1BBTCBVbmtub3duIGZlYXR1cmU6ICVkXG4iLAorCQkJCWRldi0+ZGlza19uYW1lLCBiZTE2 X3RvX2NwdShib2R5LT5jb2RlKSk7CisKKwkJfQorCQljcG9zICs9IGJvZHktPmxlbmd0aCArIDQ7 CisJfQorCisJaWYgKCFzdXBwb3J0ZWQpIHsKKwkJcHJfZXJyKCIlczogRGV2aWNlIG5vdCBzdXBw b3J0ZWRcbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJZ290byBlcnJfY2FsbGJhY2s7CisJfQorCisJ aWYgKCFzaW5nbGVfdXNlcikKKwkJcHJfd2FybigiJXM6IERldmljZSBkb2Vzbid0IHN1cHBvcnQg c2luZ2xlIHVzZXIgbW9kZVxuIiwKKwkJCWRldi0+ZGlza19uYW1lKTsKKworCWlmICghZm91bmRD b21JRCkgeworCQlwcl93YXJuKCIlczogQ291bGQgbm90IGZpbmQgT1BBTCBjb21JRCBmb3IgZGV2 aWNlLiBPUEFMIGtlcm5lbCB1bmxvY2tpbmcgd2lsbCBiZSBkaXNhYmxlZFxuIiwKKwkJCWRldi0+ ZGlza19uYW1lKTsKKwkJZ290byBlcnJfY2FsbGJhY2s7CisJfQorCisJZGV2LT5jb21JRCA9IGNv bUlEOworCitlcnJfY2FsbGJhY2s6CisJaWYgKGRldi0+b3Blcl9jYikKKwkJZGV2LT5vcGVyX2Ni KGVycm9yLCBkZXYpOworfQorCitzdGF0aWMgaW50IG9wYWxfZGlzY292ZXJ5MChzdHJ1Y3Qgb3Bh bF9kZXYgKmRldikKK3sKKwljb25zdCBzdHJ1Y3Qgc2VjX29wcyAqb3BzOworCXZvaWQgKmRhdGE7 CisKKwlnZXRfZGF0YV9vcHMoZGV2LCAmb3BzLCAmZGF0YSk7CisJbWVtc2V0KGRldi0+Y21kLnJl c3AsIDAsIElPX0JVRkZFUl9MRU5HVEgpOworCXJldHVybiBvcHMtPnJlY3YoZGF0YSwgMHgwMDAx LCBUQ0dfU0VDUF8wMSwgZGV2LT5jbWQucmVzcCwKKwkJCSBJT19CVUZGRVJfTEVOR1RILCBvcGFs X2Rpc2NvdmVyeTBfZW5kLCBkZXYpOworfQorCitzdGF0aWMgdm9pZCBhZGRfdG9rZW5fdTgoc3Ry dWN0IG9wYWxfY21kICpjbWQsIHU4IHRvaykKK3sKKwljbWQtPmNtZFtjbWQtPnBvcysrXSA9IHRv azsKK30KKworc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRkX3Rva2VuX3U4KHN0cnVjdCBvcGFs X2NtZCAqY21kLCB1OCB0b2spCit7CisJQlVJTERfQlVHX09OKElPX0JVRkZFUl9MRU5HVEggPj0g U0laRV9NQVgpOworCisJaWYgKGNtZC0+cG9zID49IElPX0JVRkZFUl9MRU5HVEggLSAxKSB7CisJ CXByX2VycigiRXJyb3IgYWRkaW5nIHU4OiBlbmQgb2YgYnVmZmVyLlxuIik7CisJCXJldHVybiAt RVJBTkdFOworCX0KKworCWFkZF90b2tlbl91OChjbWQsIHRvayk7CisKKwlyZXR1cm4gMTsKK30K KworI2RlZmluZSBUSU5ZX0FUT01fREFUQV9NQVNLIEdFTk1BU0soNSwgMCkKKyNkZWZpbmUgVElO WV9BVE9NX1NJR05FRCBCSVQoNikKKworI2RlZmluZSBTSE9SVF9BVE9NX0lEIEJJVCg3KQorI2Rl ZmluZSBTSE9SVF9BVE9NX0JZVEVTVFJJTkcgQklUKDUpCisjZGVmaW5lIFNIT1JUX0FUT01fU0lH TkVEIEJJVCg0KQorI2RlZmluZSBTSE9SVF9BVE9NX0xFTl9NQVNLIEdFTk1BU0soMywgMCkKKwor c3RhdGljIHZvaWQgYWRkX3Nob3J0X2F0b21faGVhZGVyKHN0cnVjdCBvcGFsX2NtZCAqY21kLCBi b29sIGJ5dGVzdHJpbmcsCisJCQkJICBib29sIGhhc19zaWduLCBpbnQgbGVuKQoreworCXU4IGF0 b207CisKKwlhdG9tID0gU0hPUlRfQVRPTV9JRDsKKwlhdG9tIHw9IGJ5dGVzdHJpbmcgPyBTSE9S VF9BVE9NX0JZVEVTVFJJTkcgOiAwOworCWF0b20gfD0gaGFzX3NpZ24gPyBTSE9SVF9BVE9NX1NJ R05FRCA6IDA7CisJYXRvbSB8PSBsZW4gJiBTSE9SVF9BVE9NX0xFTl9NQVNLOworCisJYWRkX3Rv a2VuX3U4KGNtZCwgYXRvbSk7Cit9CisKKyNkZWZpbmUgTUVESVVNX0FUT01fSUQgKEJJVCg3KSB8 IEJJVCg2KSkKKyNkZWZpbmUgTUVESVVNX0FUT01fQllURVNUUklORyBCSVQoNCkKKyNkZWZpbmUg TUVESVVNX0FUT01fU0lHTkVEIEJJVCgzKQorI2RlZmluZSBNRURJVU1fQVRPTV9MRU5fTUFTSyBH RU5NQVNLKDIsIDApCisKK3N0YXRpYyB2b2lkIGFkZF9tZWRpdW1fYXRvbV9oZWFkZXIoc3RydWN0 IG9wYWxfY21kICpjbWQsIGJvb2wgYnl0ZXN0cmluZywKKwkJCQkgICBib29sIGhhc19zaWduLCBp bnQgbGVuKQoreworCXU4IGhlYWRlcjA7CisKKwloZWFkZXIwID0gTUVESVVNX0FUT01fSUQ7CisJ aGVhZGVyMCB8PSBieXRlc3RyaW5nID8gTUVESVVNX0FUT01fQllURVNUUklORyA6IDA7CisJaGVh ZGVyMCB8PSBoYXNfc2lnbiA/IE1FRElVTV9BVE9NX1NJR05FRCA6IDA7CisJaGVhZGVyMCB8PSAo bGVuID4+IDgpICYgTUVESVVNX0FUT01fTEVOX01BU0s7CisJY21kLT5jbWRbY21kLT5wb3MrK10g PSBoZWFkZXIwOworCWNtZC0+Y21kW2NtZC0+cG9zKytdID0gbGVuOworfQorCitzdGF0aWMgdm9p ZCBhZGRfdG9rZW5fdTY0KHN0cnVjdCBvcGFsX2NtZCAqY21kLCB1NjQgbnVtYmVyLCBzaXplX3Qg bGVuKQoreworCWFkZF9zaG9ydF9hdG9tX2hlYWRlcihjbWQsIGZhbHNlLCBmYWxzZSwgbGVuKTsK KworCXdoaWxlIChsZW4tLSkgeworCQl1OCBuID0gbnVtYmVyID4+IChsZW4gKiA4KTsKKworCQlh ZGRfdG9rZW5fdTgoY21kLCBuKTsKKwl9Cit9CisKK3N0YXRpYyBzc2l6ZV90IHRlc3RfYW5kX2Fk ZF90b2tlbl91NjQoc3RydWN0IG9wYWxfY21kICpjbWQsIHU2NCBudW1iZXIpCit7CisJaW50IGxl bjsKKwlpbnQgbXNiOworCisJaWYgKCEobnVtYmVyICYgflRJTllfQVRPTV9EQVRBX01BU0spKQor CQlyZXR1cm4gdGVzdF9hbmRfYWRkX3Rva2VuX3U4KGNtZCwgbnVtYmVyKTsKKworCW1zYiA9IGZs cyhudW1iZXIpOworCWxlbiA9IERJVl9ST1VORF9VUChtc2IsIDQpOworCisJaWYgKGNtZC0+cG9z ID49IElPX0JVRkZFUl9MRU5HVEggLSBsZW4gLSAxKSB7CisJCXByX2VycigiRXJyb3IgYWRkaW5n IHU2NDogZW5kIG9mIGJ1ZmZlci5cbiIpOworCQlyZXR1cm4gLUVSQU5HRTsKKwl9CisKKwlhZGRf dG9rZW5fdTY0KGNtZCwgbnVtYmVyLCBsZW4pOworCisJLyogcmV0dXJuIGxlbmd0aCBvZiB0b2tl biBwbHVzIGF0b20gKi8KKwlyZXR1cm4gbGVuICsgMTsKK30KKworc3RhdGljIHZvaWQgYWRkX3Rv a2VuX2J5dGVzdHJpbmcoc3RydWN0IG9wYWxfY21kICpjbWQsCisJCQkJIGNvbnN0IHU4ICpieXRl c3RyaW5nLCBzaXplX3QgbGVuKQoreworCW1lbWNweSgmY21kLT5jbWRbY21kLT5wb3NdLCBieXRl c3RyaW5nLCBsZW4pOworCWNtZC0+cG9zICs9IGxlbjsKK30KKworc3RhdGljIHNzaXplX3QgdGVz dF9hbmRfYWRkX3Rva2VuX2J5dGVzdHJpbmcoc3RydWN0IG9wYWxfY21kICpjbWQsCisJCQkJCSAg ICAgY29uc3QgdTggKmJ5dGVzdHJpbmcsIHNpemVfdCBsZW4pCit7CisJc2l6ZV90IGhlYWRlcl9s ZW4gPSAxOworCWJvb2wgaXNfc2hvcnRfYXRvbSA9IHRydWU7CisKKwlpZiAobGVuICYgflNIT1JU X0FUT01fTEVOX01BU0spIHsKKwkJaGVhZGVyX2xlbiA9IDI7CisJCWlzX3Nob3J0X2F0b20gPSBm YWxzZTsKKwl9CisKKwlpZiAoY21kLT5wb3MgPj0gSU9fQlVGRkVSX0xFTkdUSCAtIGxlbiAtIGhl YWRlcl9sZW4pIHsKKwkJcHJfZXJyKCJFcnJvciBhZGRpbmcgYnl0ZXN0cmluZzogZW5kIG9mIGJ1 ZmZlci5cbiIpOworCQlyZXR1cm4gLUVSQU5HRTsKKwl9CisKKwlpZiAoaXNfc2hvcnRfYXRvbSkK KwkJYWRkX3Nob3J0X2F0b21faGVhZGVyKGNtZCwgdHJ1ZSwgZmFsc2UsIGxlbik7CisJZWxzZQor CQlhZGRfbWVkaXVtX2F0b21faGVhZGVyKGNtZCwgdHJ1ZSwgZmFsc2UsIGxlbik7CisKKwlhZGRf dG9rZW5fYnl0ZXN0cmluZyhjbWQsIGJ5dGVzdHJpbmcsIGxlbik7CisKKwlyZXR1cm4gaGVhZGVy X2xlbiArIGxlbjsKK30KKworI2RlZmluZSBMT0NLSU5HX1JBTkdFX05PTl9HTE9CQUwgMHgwMwor CitzdGF0aWMgaW50IGJ1aWxkX2xvY2tpbmdfcmFuZ2UodTggKmJ1ZmZlciwgc2l6ZV90IGxlbmd0 aCwgdTggbHIpCit7CisJaWYgKGxlbmd0aCA8IE9QQUxfVUlEX0xFTkdUSCkKKwkJcmV0dXJuIC1F UkFOR0U7CisKKwltZW1jcHkoYnVmZmVyLCBPUEFMVUlEW09QQUxfTE9DS0lOR1JBTkdFX0dMT0JB TF0sIE9QQUxfVUlEX0xFTkdUSCk7CisKKwlpZiAobHIgPT0gMCkKKwkJcmV0dXJuIDA7CisJYnVm ZmVyWzVdID0gTE9DS0lOR19SQU5HRV9OT05fR0xPQkFMOworCWJ1ZmZlcls3XSA9IGxyOworCisJ cmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgYnVpbGRfbG9ja2luZ191c2VyKHU4ICpidWZmZXIs IHNpemVfdCBsZW5ndGgsIHU4IGxyKQoreworCWlmIChsZW5ndGggPCBPUEFMX1VJRF9MRU5HVEgp CisJCXJldHVybiAtRVJBTkdFOworCisJbWVtY3B5KGJ1ZmZlciwgT1BBTFVJRFtPUEFMX1VTRVIx X1VJRF0sIE9QQUxfVUlEX0xFTkdUSCk7CisKKwlidWZmZXJbN10gPSBsciArIDE7CisKKwlyZXR1 cm4gMDsKK30KKworLyoKKyAqIE4gPSBudW1iZXIgb2YgZm9ybWF0IHNwZWNpZmllcnMgKDEtOTk5 KSB0byBiZSByZXBsaWNhdGVkCisgKiBjID0gdTgKKyAqIHUgPSB1NjQKKyAqIHMgPSBieXRlc3Ry aW5nLCBsZW5ndGgKKyAqCisgKiByZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYyIs CisgKgkJCSAgICAgICB1OF92YWwxKTsKKyAqCisgKiByZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5f dmEoY21kLCAiMmMydSIsCisgKgkJCSAgICAgICB1OF92YWwxLCB1OF92YWwyLCB1NjRfdmFsMSwg dTY0X3ZhbDIpOworICoKKyAqIHJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICIzcyIs CisgKgkJCSAgICAgICBieXRlc3RyaW5nMSwgbGVuZ3RoMSwKKyAqCQkJICAgICAgIGJ5dGVzdHJp bmcyLCBsZW5ndGgyLAorICoJCQkgICAgICAgYnl0ZXN0cmluZzMsIGxlbmd0aDMpOworICovCitz dGF0aWMgaW50IHRlc3RfYW5kX2FkZF90b2tlbl92YShzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwKKwkJ CQkgY29uc3QgY2hhciAqZm10LCAuLi4pCit7CisJY29uc3QgdTggKml0ID0gZm10LCAqdG1wOwor CWludCByZXQsIG51bSA9IDEsIHN1bSA9IDA7CisJdmFfbGlzdCBhcDsKKworCXZhX3N0YXJ0KGFw LCBmbXQpOworCisJd2hpbGUgKCppdCAhPSAnXDAnKSB7CisJCXU2NCB0b2s2NCA9IDA7CisJCXU4 IHRvaywgKmJzdHI7CisJCXNpemVfdCBsZW47CisKKwkJcmV0ID0gMDsKKworCQlzd2l0Y2ggKCpp dCkgeworCQljYXNlICcxJyAuLi4gJzknOgorCQkJdG1wID0gaXQ7CisJCQludW0gPSAwOworCQkJ d2hpbGUgKCp0bXAgPj0gJzAnICYmICp0bXAgPD0gJzknKQorCQkJCW51bSA9IG51bSAqIDEwICsg KCp0bXArKyAtICcwJyk7CisJCQlpdCA9IHRtcDsKKwkJCWNvbnRpbnVlOworCQljYXNlICdjJzoK KwkJCXdoaWxlIChudW0tLSkgeworCQkJCXRvayA9IHZhX2FyZyhhcCwgdW5zaWduZWQgaW50KTsK KwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdTgoY21kLCB0b2spOworCQkJCWlmIChyZXQg PCAwKQorCQkJCQlnb3RvIGVycjsKKwkJCX0KKwkJCW51bSA9IDE7CisJCQlicmVhazsKKwkJY2Fz ZSAndSc6CisJCQl3aGlsZSAobnVtLS0pIHsKKwkJCQl0b2s2NCA9IHZhX2FyZyhhcCwgdTY0KTsK KwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdTY0KGNtZCwgdG9rNjQpOworCQkJCWlmIChy ZXQgPCAwKQorCQkJCQlnb3RvIGVycjsKKwkJCX0KKwkJCW51bSA9IDE7CisJCQlicmVhazsKKwkJ Y2FzZSAncyc6CisJCQl3aGlsZSAobnVtLS0pIHsKKwkJCQlic3RyID0gdmFfYXJnKGFwLCB1OCAq KTsKKwkJCQlsZW4gPSB2YV9hcmcoYXAsIHNpemVfdCk7CisJCQkJcmV0ID0gdGVzdF9hbmRfYWRk X3Rva2VuX2J5dGVzdHJpbmcoY21kLCBic3RyLAorCQkJCQkJCQkgICAgbGVuKTsKKwkJCQlpZiAo cmV0IDwgMCkKKwkJCQkJZ290byBlcnI7CisJCQl9CisJCQludW0gPSAxOworCQkJYnJlYWs7CisJ CWNhc2UgJyAnOgorCQljYXNlICdcdCc6CisJCQkvKiBpZ25vcmVkICovCisJCQlicmVhazsKKwkJ ZGVmYXVsdDoKKwkJCXByX3dhcm4oIlVucmVjb2duaXplZCB0eXBlLlxuIik7CisJCX0KKworCQlp dCsrOworCQlzdW0gKz0gcmV0OworCX0KKworCXZhX2VuZChhcCk7CisKKwlyZXR1cm4gc3VtOwor CisgZXJyOgorCXByX2VycigiVG9rZW4gZmFpbGVkIHRvIGJlIGFkZGVkLlxuIik7CisJcmV0dXJu IHJldDsKK30KKworc3RhdGljIHZvaWQgc2V0X2NvbUlEKHN0cnVjdCBvcGFsX2NtZCAqY21kLCB1 MTYgY29tSUQpCit7CisJc3RydWN0IG9wYWxfaGVhZGVyICpoZHIgPSAoc3RydWN0IG9wYWxfaGVh ZGVyICopY21kLT5jbWQ7CisKKwloZHItPmNwLmV4dGVuZGVkQ29tSURbMF0gPSBjb21JRCA+PiA4 OworCWhkci0+Y3AuZXh0ZW5kZWRDb21JRFsxXSA9IGNvbUlEOworCWhkci0+Y3AuZXh0ZW5kZWRD b21JRFsyXSA9IDA7CisJaGRyLT5jcC5leHRlbmRlZENvbUlEWzNdID0gMDsKK30KKworc3RhdGlj IGludCBjbWRfZmluYWxpemUoc3RydWN0IG9wYWxfY21kICpjbWQsIHUzMiBoc24sIHUzMiB0c24p Cit7CisJc3RydWN0IG9wYWxfaGVhZGVyICpoZHI7CisJaW50IHJldDsKKworCXJldCA9IHRlc3Rf YW5kX2FkZF90b2tlbl92YShjbWQsICI2YyIsCisJCQkJICAgIE9QQUxfRU5ET0ZEQVRBLCBPUEFM X1NUQVJUTElTVCwKKwkJCQkgICAgMCwgMCwgMCwgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQg PCAwKSB7CisJCXByX2VycigiRXJyb3IgZmluYWxpemluZyBjb21tYW5kLlxuIik7CisJCXJldHVy biAtRUZBVUxUOworCX0KKworCWhkciA9IChzdHJ1Y3Qgb3BhbF9oZWFkZXIgKikgY21kLT5jbWQ7 CisKKwloZHItPnBrdC5UU04gPSBjcHVfdG9fYmUzMih0c24pOworCWhkci0+cGt0LkhTTiA9IGNw dV90b19iZTMyKGhzbik7CisKKwloZHItPnN1YnBrdC5sZW5ndGggPSBjcHVfdG9fYmUzMihjbWQt PnBvcyAtIHNpemVvZigqaGRyKSk7CisJd2hpbGUgKGNtZC0+cG9zICUgNCkgeworCQlpZiAoY21k LT5wb3MgPj0gSU9fQlVGRkVSX0xFTkdUSCkgeworCQkJcHJfZXJyKCJFcnJvcjogQnVmZmVyIG92 ZXJydW5cbiIpOworCQkJcmV0dXJuIC1FUkFOR0U7CisJCX0KKwkJY21kLT5jbWRbY21kLT5wb3Mr K10gPSAwOworCX0KKwloZHItPnBrdC5sZW5ndGggPSBjcHVfdG9fYmUzMihjbWQtPnBvcyAtIHNp emVvZihoZHItPmNwKSAtCisJCQkJICAgICAgc2l6ZW9mKGhkci0+cGt0KSk7CisJaGRyLT5jcC5s ZW5ndGggPSBjcHVfdG9fYmUzMihjbWQtPnBvcyAtIHNpemVvZihoZHItPmNwKSk7CisKKwlyZXR1 cm4gMDsKK30KKworc3RhdGljIGVudW0gT1BBTF9SRVNQT05TRV9UT0tFTiB0b2tlbl90eXBlKGNv bnN0IHN0cnVjdCBwYXJzZWRfcmVzcCAqcmVzcCwKKwkJCQkJICAgaW50IG4pCit7CisJY29uc3Qg c3RydWN0IG9wYWxfcmVzcF90b2sgKnRvazsKKworCWlmIChuID49IHJlc3AtPm51bSkgeworCQlw cl9lcnIoIlRva2VuIG51bWJlciBkb2Vzbid0IGV4aXN0OiAlZCwgcmVzcDogJWRcbiIsCisJCSAg ICAgICBuLCByZXNwLT5udW0pOworCQlyZXR1cm4gT1BBTF9EVEFfVE9LRU5JRF9JTlZBTElEOwor CX0KKworCXRvayA9ICZyZXNwLT50b2tzW25dOworCWlmICh0b2stPmxlbiA9PSAwKSB7CisJCXBy X2VycigiVG9rZW4gbGVuZ3RoIG11c3QgYmUgbm9uLXplcm9cbiIpOworCQlyZXR1cm4gT1BBTF9E VEFfVE9LRU5JRF9JTlZBTElEOworCX0KKworCXJldHVybiB0b2stPnR5cGU7Cit9CisKKy8qCisg KiBUaGlzIGZ1bmN0aW9uIHJldHVybnMgMCBpbiBjYXNlIG9mIGludmFsaWQgdG9rZW4uIE9uZSBz aG91bGQgY2FsbAorICogdG9rZW5fdHlwZSgpIGZpcnN0IHRvIGZpbmQgb3V0IGlmIHRoZSB0b2tl biBpcyB2YWxpZCBvciBub3QuCisgKi8KK3N0YXRpYyBlbnVtIE9QQUxfVE9LRU4gcmVzcG9uc2Vf Z2V0X3Rva2VuKGNvbnN0IHN0cnVjdCBwYXJzZWRfcmVzcCAqcmVzcCwKKwkJCQkJICBpbnQgbikK K3sKKwljb25zdCBzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rOworCisJaWYgKG4gPj0gcmVzcC0+ bnVtKSB7CisJCXByX2VycigiVG9rZW4gbnVtYmVyIGRvZXNuJ3QgZXhpc3Q6ICVkLCByZXNwOiAl ZFxuIiwKKwkJICAgICAgIG4sIHJlc3AtPm51bSk7CisJCXJldHVybiAwOworCX0KKworCXRvayA9 ICZyZXNwLT50b2tzW25dOworCWlmICh0b2stPmxlbiA9PSAwKSB7CisJCXByX2VycigiVG9rZW4g bGVuZ3RoIG11c3QgYmUgbm9uLXplcm9cbiIpOworCQlyZXR1cm4gMDsKKwl9CisKKwlyZXR1cm4g dG9rLT5wb3NbMF07Cit9CisKK3N0YXRpYyBzaXplX3QgcmVzcG9uc2VfcGFyc2VfdGlueShzdHJ1 Y3Qgb3BhbF9yZXNwX3RvayAqdG9rLAorCQkJCSAgY29uc3QgdTggKnBvcykKK3sKKwl0b2stPnBv cyA9IHBvczsKKwl0b2stPmxlbiA9IDE7CisJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhfVElOWTsK KworCWlmIChwb3NbMF0gJiBUSU5ZX0FUT01fU0lHTkVEKSB7CisJCXRvay0+dHlwZSA9IE9QQUxf RFRBX1RPS0VOSURfU0lOVDsKKwl9IGVsc2UgeworCQl0b2stPnR5cGUgPSBPUEFMX0RUQV9UT0tF TklEX1VJTlQ7CisJCXRvay0+c3RvcmVkLnUgPSBwb3NbMF0gJiAweDNmOworCX0KKworCXJldHVy biB0b2stPmxlbjsKK30KKworc3RhdGljIHNpemVfdCByZXNwb25zZV9wYXJzZV9zaG9ydChzdHJ1 Y3Qgb3BhbF9yZXNwX3RvayAqdG9rLAorCQkJCSAgIGNvbnN0IHU4ICpwb3MpCit7CisJdG9rLT5w b3MgPSBwb3M7CisJdG9rLT5sZW4gPSAocG9zWzBdICYgU0hPUlRfQVRPTV9MRU5fTUFTSykgKyAx OworCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX1NIT1JUOworCisJaWYgKHBvc1swXSAmIFNIT1JU X0FUT01fQllURVNUUklORykgeworCQl0b2stPnR5cGUgPSBPUEFMX0RUQV9UT0tFTklEX0JZVEVT VFJJTkc7CisJfSBlbHNlIGlmIChwb3NbMF0gJiBTSE9SVF9BVE9NX1NJR05FRCkgeworCQl0b2st PnR5cGUgPSBPUEFMX0RUQV9UT0tFTklEX1NJTlQ7CisJfSBlbHNlIHsKKwkJdTY0IHVfaW50ZWdl ciA9IDA7CisJCWludCBpLCBiID0gMDsKKworCQl0b2stPnR5cGUgPSBPUEFMX0RUQV9UT0tFTklE X1VJTlQ7CisJCWlmICh0b2stPmxlbiA+IDkpIHsKKwkJCXByX3dhcm4oInVpbnQ2NCB3aXRoIG1v cmUgdGhhbiA4IGJ5dGVzXG4iKTsKKwkJCXJldHVybiAtRUlOVkFMOworCQl9CisJCWZvciAoaSA9 IHRvay0+bGVuIC0gMTsgaSA+IDA7IGktLSkgeworCQkJdV9pbnRlZ2VyIHw9ICgodTY0KXBvc1tp XSA8PCAoOCAqIGIpKTsKKwkJCWIrKzsKKwkJfQorCQl0b2stPnN0b3JlZC51ID0gdV9pbnRlZ2Vy OworCX0KKworCXJldHVybiB0b2stPmxlbjsKK30KKworc3RhdGljIHNpemVfdCByZXNwb25zZV9w YXJzZV9tZWRpdW0oc3RydWN0IG9wYWxfcmVzcF90b2sgKnRvaywKKwkJCQkgICAgY29uc3QgdTgg KnBvcykKK3sKKwl0b2stPnBvcyA9IHBvczsKKwl0b2stPmxlbiA9ICgoKHBvc1swXSAmIE1FRElV TV9BVE9NX0xFTl9NQVNLKSA8PCA4KSB8IHBvc1sxXSkgKyAyOworCXRvay0+d2lkdGggPSBPUEFM X1dJRFRIX01FRElVTTsKKworCWlmIChwb3NbMF0gJiBNRURJVU1fQVRPTV9CWVRFU1RSSU5HKQor CQl0b2stPnR5cGUgPSBPUEFMX0RUQV9UT0tFTklEX0JZVEVTVFJJTkc7CisJZWxzZSBpZiAocG9z WzBdICYgTUVESVVNX0FUT01fU0lHTkVEKQorCQl0b2stPnR5cGUgPSBPUEFMX0RUQV9UT0tFTklE X1NJTlQ7CisJZWxzZQorCQl0b2stPnR5cGUgPSBPUEFMX0RUQV9UT0tFTklEX1VJTlQ7CisKKwly ZXR1cm4gdG9rLT5sZW47Cit9CisKKyNkZWZpbmUgTE9OR19BVE9NX0lEIChCSVQoNykgfCBCSVQo NikgfCBCSVQoNSkpCisjZGVmaW5lIExPTkdfQVRPTV9CWVRFU1RSSU5HIEJJVCgxKQorI2RlZmlu ZSBMT05HX0FUT01fU0lHTkVEIEJJVCgwKQorc3RhdGljIHNpemVfdCByZXNwb25zZV9wYXJzZV9s b25nKHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2ssCisJCQkJICBjb25zdCB1OCAqcG9zKQorewor CXRvay0+cG9zID0gcG9zOworCXRvay0+bGVuID0gKChwb3NbMV0gPDwgMTYpIHwgKHBvc1syXSA8 PCA4KSB8IHBvc1szXSkgKyA0OworCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX0xPTkc7CisKKwlp ZiAocG9zWzBdICYgTE9OR19BVE9NX0JZVEVTVFJJTkcpCisJCXRvay0+dHlwZSA9IE9QQUxfRFRB X1RPS0VOSURfQllURVNUUklORzsKKwllbHNlIGlmIChwb3NbMF0gJiBMT05HX0FUT01fU0lHTkVE KQorCQl0b2stPnR5cGUgPSBPUEFMX0RUQV9UT0tFTklEX1NJTlQ7CisJZWxzZQorCQl0b2stPnR5 cGUgPSBPUEFMX0RUQV9UT0tFTklEX1VJTlQ7CisKKwlyZXR1cm4gdG9rLT5sZW47Cit9CisKK3N0 YXRpYyBzaXplX3QgcmVzcG9uc2VfcGFyc2VfdG9rZW4oc3RydWN0IG9wYWxfcmVzcF90b2sgKnRv aywKKwkJCQkgICBjb25zdCB1OCAqcG9zKQoreworCXRvay0+cG9zID0gcG9zOworCXRvay0+bGVu ID0gMTsKKwl0b2stPnR5cGUgPSBPUEFMX0RUQV9UT0tFTklEX1RPS0VOOworCXRvay0+d2lkdGgg PSBPUEFMX1dJRFRIX1RPS0VOOworCisJcmV0dXJuIHRvay0+bGVuOworfQorCitzdGF0aWMgaW50 IHJlc3BvbnNlX3BhcnNlKGNvbnN0IHU4ICpidWYsIHNpemVfdCBsZW5ndGgsCisJCQkgIHN0cnVj dCBwYXJzZWRfcmVzcCAqcmVzcCkKK3sKKwljb25zdCBzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkcjsK KwlzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqaXRlcjsKKwlpbnQgcmV0LCBudW1fZW50cmllcyA9IDA7 CisJdTMyIGNwb3MgPSAwLCB0b3RhbDsKKwlzaXplX3QgdG9rZW5fbGVuZ3RoOworCWNvbnN0IHU4 ICpwb3M7CisKKwlpZiAoIWJ1ZikKKwkJcmV0dXJuIC1FRkFVTFQ7CisKKwlpZiAoIXJlc3ApCisJ CXJldHVybiAtRUZBVUxUOworCisJaGRyID0gKHN0cnVjdCBvcGFsX2hlYWRlciAqKWJ1ZjsKKwlw b3MgPSBidWY7CisJcG9zICs9IHNpemVvZigqaGRyKTsKKworCXByX2RlYnVnKCJSZXNwb25zZSBz aXplOiBjcDogJWQsIHBrdDogJWQsIHN1YnBrdDogJWRcbiIsCisJCSBiZTMyX3RvX2NwdShoZHIt PmNwLmxlbmd0aCksCisJCSBiZTMyX3RvX2NwdShoZHItPnBrdC5sZW5ndGgpLAorCQkgYmUzMl90 b19jcHUoaGRyLT5zdWJwa3QubGVuZ3RoKSk7CisKKwlpZiAoKGhkci0+Y3AubGVuZ3RoID09IDAp CisJICAgIHx8IChoZHItPnBrdC5sZW5ndGggPT0gMCkKKwkgICAgfHwgKGhkci0+c3VicGt0Lmxl bmd0aCA9PSAwKSkgeworCQlwcl9lcnIoIkJhZCBoZWFkZXIgbGVuZ3RoLiBjcDogJWQsIHBrdDog JWQsIHN1YnBrdDogJWRcbiIsCisJCSAgICAgICBiZTMyX3RvX2NwdShoZHItPmNwLmxlbmd0aCks CisJCSAgICAgICBiZTMyX3RvX2NwdShoZHItPnBrdC5sZW5ndGgpLAorCQkgICAgICAgYmUzMl90 b19jcHUoaGRyLT5zdWJwa3QubGVuZ3RoKSk7CisJCXByaW50X2J1ZmZlcihwb3MsIHNpemVvZigq aGRyKSk7CisJCXJldCA9IC1FSU5WQUw7CisJCWdvdG8gZXJyOworCX0KKworCWlmIChwb3MgPiBi dWYgKyBsZW5ndGgpIHsKKwkJcmV0ID0gLUVGQVVMVDsKKwkJZ290byBlcnI7CisJfQorCisJaXRl ciA9IHJlc3AtPnRva3M7CisJdG90YWwgPSBiZTMyX3RvX2NwdShoZHItPnN1YnBrdC5sZW5ndGgp OworCXByaW50X2J1ZmZlcihwb3MsIHRvdGFsKTsKKwl3aGlsZSAoY3BvcyA8IHRvdGFsKSB7CisJ CWlmICghKHBvc1swXSAmIDB4ODApKSAvKiB0aW55IGF0b20gKi8KKwkJCXRva2VuX2xlbmd0aCA9 IHJlc3BvbnNlX3BhcnNlX3RpbnkoaXRlciwgcG9zKTsKKwkJZWxzZSBpZiAoIShwb3NbMF0gJiAw eDQwKSkgLyogc2hvcnQgYXRvbSAqLworCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2Vf c2hvcnQoaXRlciwgcG9zKTsKKwkJZWxzZSBpZiAoIShwb3NbMF0gJiAweDIwKSkgLyogbWVkaXVt IGF0b20gKi8KKwkJCXRva2VuX2xlbmd0aCA9IHJlc3BvbnNlX3BhcnNlX21lZGl1bShpdGVyLCBw b3MpOworCQllbHNlIGlmICghKHBvc1swXSAmIDB4MTApKSAvKiBsb25nIGF0b20gKi8KKwkJCXRv a2VuX2xlbmd0aCA9IHJlc3BvbnNlX3BhcnNlX2xvbmcoaXRlciwgcG9zKTsKKwkJZWxzZSAvKiBU T0tFTiAqLworCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfdG9rZW4oaXRlciwgcG9z KTsKKworCQlpZiAodG9rZW5fbGVuZ3RoID09IC1FSU5WQUwpIHsKKwkJCXJldCA9IC1FSU5WQUw7 CisJCQlnb3RvIGVycjsKKwkJfQorCisJCXBvcyArPSB0b2tlbl9sZW5ndGg7CisJCWNwb3MgKz0g dG9rZW5fbGVuZ3RoOworCQlpdGVyKys7CisJCW51bV9lbnRyaWVzKys7CisJfQorCisJaWYgKG51 bV9lbnRyaWVzID09IDApIHsKKwkJcHJfZXJyKCJDb3VsZG4ndCBwYXJzZSByZXNwb25zZS5cbiIp OworCQlyZXQgPSAtRUlOVkFMOworCQlnb3RvIGVycjsKKwl9CisJcmVzcC0+bnVtID0gbnVtX2Vu dHJpZXM7CisKKwlyZXR1cm4gMDsKK2VycjoKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgc2l6 ZV90IHJlc3BvbnNlX2dldF9zdHJpbmcoY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLCBp bnQgbiwKKwkJCQkgIGNvbnN0IGNoYXIgKipzdG9yZSkKK3sKKwkqc3RvcmUgPSBOVUxMOworCWlm ICghcmVzcCkgeworCQlwcl9lcnIoIlJlc3BvbnNlIGlzIE5VTExcbiIpOworCQlyZXR1cm4gMDsK Kwl9CisKKwlpZiAobiA+IHJlc3AtPm51bSkgeworCQlwcl9lcnIoIlJlc3BvbnNlIGhhcyAlZCB0 b2tlbnMuIENhbid0IGFjY2VzcyAlZFxuIiwKKwkJICAgICAgIHJlc3AtPm51bSwgbik7CisJCXJl dHVybiAwOworCX0KKworCWlmIChyZXNwLT50b2tzW25dLnR5cGUgIT0gT1BBTF9EVEFfVE9LRU5J RF9CWVRFU1RSSU5HKSB7CisJCXByX2VycigiVG9rZW4gaXMgbm90IGEgYnl0ZSBzdHJpbmchXG4i KTsKKwkJcmV0dXJuIDA7CisJfQorCisJKnN0b3JlID0gcmVzcC0+dG9rc1tuXS5wb3MgKyAxOwor CXJldHVybiByZXNwLT50b2tzW25dLmxlbiAtIDE7Cit9CisKK3N0YXRpYyB1NjQgcmVzcG9uc2Vf Z2V0X3U2NChjb25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJlc3AsIGludCBuKQoreworCWlmICgh cmVzcCkgeworCQlwcl9lcnIoIlJlc3BvbnNlIGlzIE5VTExcbiIpOworCQlyZXR1cm4gMDsKKwl9 CisKKwlpZiAobiA+IHJlc3AtPm51bSkgeworCQlwcl9lcnIoIlJlc3BvbnNlIGhhcyAlZCB0b2tl bnMuIENhbid0IGFjY2VzcyAlZFxuIiwKKwkJICAgICAgIHJlc3AtPm51bSwgbik7CisJCXJldHVy biAwOworCX0KKworCWlmIChyZXNwLT50b2tzW25dLnR5cGUgIT0gT1BBTF9EVEFfVE9LRU5JRF9V SU5UKSB7CisJCXByX2VycigiVG9rZW4gaXMgbm90IHVuc2lnbmVkIGl0OiAlZFxuIiwKKwkJICAg ICAgIHJlc3AtPnRva3Nbbl0udHlwZSk7CisJCXJldHVybiAwOworCX0KKworCWlmICghKChyZXNw LT50b2tzW25dLndpZHRoID09IE9QQUxfV0lEVEhfVElOWSkgfHwKKwkgICAgICAocmVzcC0+dG9r c1tuXS53aWR0aCA9PSBPUEFMX1dJRFRIX1NIT1JUKSkpIHsKKwkJcHJfZXJyKCJBdG9tIGlzIG5v dCBzaG9ydCBvciB0aW55OiAlZFxuIiwKKwkJICAgICAgIHJlc3AtPnRva3Nbbl0ud2lkdGgpOwor CQlyZXR1cm4gMDsKKwl9CisKKwlyZXR1cm4gcmVzcC0+dG9rc1tuXS5zdG9yZWQudTsKK30KKwor c3RhdGljIHU4IHJlc3BvbnNlX3N0YXR1cyhjb25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJlc3Ap Cit7CisJaWYgKCh0b2tlbl90eXBlKHJlc3AsIDApID09IE9QQUxfRFRBX1RPS0VOSURfVE9LRU4p CisJICAgICYmIChyZXNwb25zZV9nZXRfdG9rZW4ocmVzcCwgMCkgPT0gT1BBTF9FTkRPRlNFU1NJ T04pKSB7CisJCXJldHVybiAwOworCX0KKworCWlmIChyZXNwLT5udW0gPCA1KQorCQlyZXR1cm4g RFRBRVJST1JfTk9fTUVUSE9EX1NUQVRVUzsKKworCWlmICgodG9rZW5fdHlwZShyZXNwLCByZXNw LT5udW0gLSAxKSAhPSBPUEFMX0RUQV9UT0tFTklEX1RPS0VOKSB8fAorCSAgICAodG9rZW5fdHlw ZShyZXNwLCByZXNwLT5udW0gLSA1KSAhPSBPUEFMX0RUQV9UT0tFTklEX1RPS0VOKSB8fAorCSAg ICAocmVzcG9uc2VfZ2V0X3Rva2VuKHJlc3AsIHJlc3AtPm51bSAtIDEpICE9IE9QQUxfRU5ETElT VCkgfHwKKwkgICAgKHJlc3BvbnNlX2dldF90b2tlbihyZXNwLCByZXNwLT5udW0gLSA1KSAhPSBP UEFMX1NUQVJUTElTVCkpCisJCXJldHVybiBEVEFFUlJPUl9OT19NRVRIT0RfU1RBVFVTOworCisJ cmV0dXJuIHJlc3BvbnNlX2dldF91NjQocmVzcCwgcmVzcC0+bnVtIC0gNCk7Cit9CisKKy8qIFBh cnNlcyBhbmQgY2hlY2tzIGZvciBlcnJvcnMgKi8KK3N0YXRpYyBpbnQgcGFyc2VfYW5kX2NoZWNr X3N0YXR1cyhzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsK KwlpbnQgZXJyb3I7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJcHJpbnRfYnVmZmVyKGNtZC0+Y21k LCBjbWQtPnBvcyk7CisKKwllcnJvciA9IHJlc3BvbnNlX3BhcnNlKGNtZC0+cmVzcCwgSU9fQlVG RkVSX0xFTkdUSCwgJmRldi0+cGFyc2VkKTsKKwlpZiAoZXJyb3IpIHsKKwkJcHJfZXJyKCIlczog Q291bGRuJ3QgcGFyc2UgcmVzcG9uc2UuXG4iLCBkZXYtPmRpc2tfbmFtZSk7CisJCWdvdG8gZXJy X3JldHVybjsKKwl9CisKKwllcnJvciA9IHJlc3BvbnNlX3N0YXR1cygmZGV2LT5wYXJzZWQpOwor CWlmIChlcnJvcikKKwkJcHJfZXJyKCIlczogUmVzcG9uc2UgU3RhdHVzOiAlZFxuIiwgZGV2LT5k aXNrX25hbWUsCisJCSAgICAgICBlcnJvcik7CisKKyBlcnJfcmV0dXJuOgorCXJldHVybiBlcnJv cjsKK30KKworc3RhdGljIHZvaWQgY2xlYXJfb3BhbF9jbWQoc3RydWN0IG9wYWxfY21kICpjbWQp Cit7CisJY21kLT5wb3MgPSBzaXplb2Yoc3RydWN0IG9wYWxfaGVhZGVyKTsKKwltZW1zZXQoY21k LT5jbWQsIDAsIElPX0JVRkZFUl9MRU5HVEgpOworCWNtZC0+Y2IgPSBOVUxMOworCWNtZC0+Y2Jf ZGF0YSA9IE5VTEw7Cit9CisKK3N0YXRpYyB2b2lkIHN0YXJ0X29wYWxfc2Vzc2lvbl9jb250KGlu dCBlcnJvciwgdm9pZCAqZGF0YSkKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJ dTMyIEhTTiwgVFNOOworCisJaWYgKGVycm9yKQorCQlnb3RvIGVycl9yZXR1cm47CisKKwllcnJv ciA9IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoZGV2KTsKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJy X3JldHVybjsKKworCUhTTiA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2VkLCA0KTsKKwlU U04gPSByZXNwb25zZV9nZXRfdTY0KCZkZXYtPnBhcnNlZCwgNSk7CisKKwlpZiAoSFNOID09IDAg JiYgVFNOID09IDApIHsKKwkJcHJfZXJyKCIlczogQ291bGRuJ3QgYXV0aGVudGljYXRlIHNlc3Np b25cbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJZXJyb3IgPSAtRVBFUk07CisJCWdvdG8gZXJyX3Jl dHVybjsKKwl9CisKKwlkZXYtPkhTTiA9IEhTTjsKKwlkZXYtPlRTTiA9IFRTTjsKKworZXJyX3Jl dHVybjoKKwlpZiAoZGV2LT5vcGVyX2NiKQorCQlkZXYtPm9wZXJfY2IoZXJyb3IsIGRldik7Cit9 CisKK3N0YXRpYyBpbnQgZ2V0X29wYWxfa2V5KHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXN0 cnVjdCBrZXkgKnVrZXkgPSBOVUxMOworCWNvbnN0IHU4ICp0bXBrZXkgPSBOVUxMOworCXNpemVf dCB0bXBsZW47CisJaW50IHJldCA9IDA7CisKKwlpZiAoZGV2LT5rZXlfdHlwZSA9PSBPUEFMX0tF WV9QTEFJTikgeworCQl0bXBrZXkgPSBkZXYtPmtleV9uYW1lOworCQl0bXBsZW4gPSBkZXYtPmtl eV9uYW1lX2xlbjsKKwl9IGVsc2UgaWYgKGRldi0+a2V5X3R5cGUgPT0gT1BBTF9LRVlfS0VZUklO RykgeworCQl1a2V5ID0gcmVxdWVzdF91c2VyX2tleShkZXYtPmtleV9uYW1lLCAmdG1wa2V5LCAm dG1wbGVuKTsKKwkJaWYgKElTX0VSUih1a2V5KSkgeworCQkJcHJfZXJyKCIlczogQ2FuJ3QgcmV0 cmlldmUga2V5OiAlbGRcbiIsIGRldi0+ZGlza19uYW1lLAorCQkJICAgICAgIFBUUl9FUlIodWtl eSkpOworCQkJcmV0dXJuIFBUUl9FUlIodWtleSk7CisJCX0KKwl9IGVsc2UgeworCQlwcl9lcnIo IlJlcXVlc3RlZCBpbnZhbGlkIGtleSB0eXBlOiAlZFxuIiwgZGV2LT5rZXlfdHlwZSk7CisJCXJl dHVybiAtRUlOVkFMOworCX0KKworCWlmICh0bXBsZW4gPiBPUEFMX0tFWV9NQVgpIHsKKwkJcHJf ZXJyKCJSZXF1ZXN0ZWQga2V5IHdpdGggaW52YWxpZCBzaXplOiAlemRcbiIsIHRtcGxlbik7CisJ CXJldCA9IC1FSU5WQUw7CisJCWdvdG8gZXJyX2V4aXQ7CisJfQorCisJZGV2LT5rZXlfbGVuID0g dG1wbGVuOworCWlmICghbWVtY3B5KGRldi0+a2V5LCB0bXBrZXksIHRtcGxlbikpIHsKKwkJcHJf ZXJyKCJFcnJvciB3aGVuIGNvcHlpbmcga2V5Iik7CisJCXJldCA9IC1FRkFVTFQ7CisJCWdvdG8g ZXJyX2V4aXQ7CisJfQorCitlcnJfZXhpdDoKKwlrZXlfcHV0KHVrZXkpOworCisJcmV0dXJuIDA7 Cit9CisKK3N0YXRpYyB2b2lkIGNsZWFuX29wYWxfa2V5KHN0cnVjdCBvcGFsX2RldiAqZGV2KQor eworCW1lbXNldChkZXYtPmtleSwgMCwgT1BBTF9LRVlfTUFYKTsKKwlkZXYtPmtleV9sZW4gPSAw OworfQorCitzdGF0aWMgaW5saW5lIHZvaWQgY2xlYW5fZnVuY3Rpb25fZGF0YShzdHJ1Y3Qgb3Bh bF9kZXYgKmRldikKK3sKKwkJZGV2LT5mdW5jX2RhdGEgPSBOVUxMOworCQlkZXYtPm51bV9mdW5j X2RhdGEgPSAwOworfQorCisvKiBUaGlzIGlzIGEgZ2VuZXJpYyBjb250aW51ZSBmbi4KKyAqIFdl IHVzZSB0aGlzIHdoZW4gd2UgZG9uJ3QgY2FyZSBhYm91dCB0aGUgcmVzcG9uc2UgZGF0YQorICog YW5kIHNpbXBseSB3YW50IHRvIGNoZWNrIHRoZSBzdGF0dXMgYW5kIGNvbnRpbnVlLgorICovCitz dGF0aWMgdm9pZCBnZW5lcmljX2NvbnQoaW50IGVycm9yLCB2b2lkICpkYXRhKQoreworCXN0cnVj dCBvcGFsX2RldiAqZGV2ID0gZGF0YTsKKworCWlmIChlcnJvcikKKwkJZ290byBlcnJfcmV0dXJu OworCisJZXJyb3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7CisKKyBlcnJfcmV0dXJu OgorCWlmIChkZXYtPm9wZXJfY2IpCisJCWRldi0+b3Blcl9jYihlcnJvciwgZGV2KTsKK30KKwor c3RhdGljIHZvaWQgZW5kX3Nlc3Npb25fY29udChpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCit7CisJ c3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOworCisJZGV2LT5IU04gPSAwOworCWRldi0+VFNO ID0gMDsKKwlnZW5lcmljX2NvbnQoZXJyb3IsIGRhdGEpOworfQorCitzdGF0aWMgaW50IGZpbmFs aXplX2FuZF9zZW5kKHN0cnVjdCBvcGFsX2RldiAqZGV2LCBzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwK KwkJCSAgICAgc2VjX2NiIGNvbnQpCit7CisJaW50IHJldDsKKworCXJldCA9IGNtZF9maW5hbGl6 ZShjbWQsIGRldi0+SFNOLCBkZXYtPlRTTik7CisJaWYgKHJldCkgeworCQlwcl9lcnIoIiVzOiBF cnJvciBmaW5hbGl6aW5nIGNvbW1hbmQgYnVmZmVyOiAlZFxuIiwKKwkJICAgICAgIGRldi0+ZGlz a19uYW1lLCByZXQpOworCQlyZXR1cm4gcmV0OworCX0KKworCXByaW50X2J1ZmZlcihjbWQtPmNt ZCwgY21kLT5wb3MpOworCisJb3BhbF9zZW5kX3JlY3YoZGV2LCBjb250LCBkZXYpOworCXJldHVy biByZXQ7Cit9CisKK3N0YXRpYyBpbnQgd2FpdF9mb3JfY21kX2NvbXBsZXRpb24oc3RydWN0IG9w YWxfY29tcGxldGlvbiAqY29tcGxldGlvbikKK3sKKwl3YWl0X2Zvcl9jb21wbGV0aW9uX2ludGVy cnVwdGlibGUoJmNvbXBsZXRpb24tPmNtZF9jb21wbGV0aW9uKTsKKwlyZXR1cm4gY29tcGxldGlv bi0+Y29tcGxldGlvbl9zdGF0dXM7Cit9CisKK3N0YXRpYyBpbnQgZ2VuX2tleShzdHJ1Y3Qgb3Bh bF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0aG9kOworCXU4IHVpZFtPUEFMX1VJRF9MRU5H VEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwljbWQgPSAmZGV2LT5j bWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsK KworCW1lbWNweSh1aWQsIGRldi0+cHJldl9kYXRhLCBtaW4oc2l6ZW9mKHVpZCksIGRldi0+cHJl dl9kX2xlbikpOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRU5LRVldOworCWtmcmVlKGRl di0+cHJldl9kYXRhKTsKKwlkZXYtPnByZXZfZGF0YSA9IE5VTEw7CisKKwlyZXQgPSB0ZXN0X2Fu ZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAg ICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5H VEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfRU5ETElTVCk7CisJ aWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgZ2VuIGtleSBjb21t YW5kXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKwor CXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKwor c3RhdGljIHZvaWQgZ2V0X2FjdGl2ZV9rZXlfY29udChpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCit7 CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOworCWNvbnN0IGNoYXIgKmFjdGl2ZWtleTsK KwlzaXplX3Qga2V5bGVuOworCisJaWYgKGVycm9yKQorCQlnb3RvIGVycl9yZXR1cm47CisKKwll cnJvciA9IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoZGV2KTsKKwlpZiAoZXJyb3IpCisJCWdvdG8g ZXJyX3JldHVybjsKKwlrZXlsZW4gPSByZXNwb25zZV9nZXRfc3RyaW5nKCZkZXYtPnBhcnNlZCwg NCwgJmFjdGl2ZWtleSk7CisJaWYgKCFhY3RpdmVrZXkpIHsKKwkJcHJfZXJyKCIlczogQ291bGRu J3QgZXh0cmFjdCB0aGUgQWN0aXZla2V5IGZyb20gdGhlIHJlc3BvbnNlXG4iLAorCQkgICAgICAg X19mdW5jX18pOworCQllcnJvciA9IDB4MEE7CisJCWdvdG8gZXJyX3JldHVybjsKKwl9CisJZGV2 LT5wcmV2X2RhdGEgPSBrbWVtZHVwKGFjdGl2ZWtleSwga2V5bGVuLCBHRlBfS0VSTkVMKTsKKwor CWlmICghZGV2LT5wcmV2X2RhdGEpCisJCWVycm9yID0gLUVOT01FTTsKKworCWRldi0+cHJldl9k X2xlbiA9IGtleWxlbjsKKworZXJyX3JldHVybjoKKwlpZiAoZGV2LT5vcGVyX2NiKQorCQlkZXYt Pm9wZXJfY2IoZXJyb3IsIGRldik7Cit9CisKK3N0YXRpYyBpbnQgZ2V0X2FjdGl2ZV9rZXkoc3Ry dWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29uc3QgdTggKm1ldGhvZDsKKwl1OCB1aWRbT1BBTF9V SURfTEVOR1RIXTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0OworCisJY21kID0g JmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5j b21JRCk7CisKKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfR0VUXTsKKworCXJldCA9IGJ1aWxk X2xvY2tpbmdfcmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5scik7CisJaWYgKHJldCA8IDAp IHsKKwkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9ja2luZyByYW5nZVxuIiwgZGV2LT5kaXNr X25hbWUpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9r ZW5fdmEoY21kLCAiYzJzIDZjIDRjIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICB1 aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgs CisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJ CSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIHN0YXJ0 Q2xvdW1uICovCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzEwLCAvKiBBY3RpdmVLZXkgKi8KKwkJ CQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBP UEFMX1RJTllfVUlOVF8wNCwgLyogZW5kQ29sdW1uICovCisJCQkJICAgIE9QQUxfVElOWV9VSU5U XzEwLCAvKiBBY3RpdmVLZXkgKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9Q QUxfRU5ETElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKwlpZiAocmV0IDwgMCkgeworCQlw cl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBnZXQgYWN0aXZlIGtleSBjb21tYW5kXG4iLAorCQkg ICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5h bGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2V0X2FjdGl2ZV9rZXlfY29udCk7Cit9CisKK3N0YXRp YyBpbmxpbmUgaW50IGVuYWJsZV9nbG9iYWxfbHIoc3RydWN0IG9wYWxfY21kICpjbWQsIHU4ICp1 aWQsCisJCQkJICAgc3RydWN0IG9wYWxfdXNlcl9scl9zZXR1cCAqc2V0dXApCit7CisJY29uc3Qg dTggKm1ldGhvZDsKKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU0VUXTsKKwlyZXR1cm4gdGVz dF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyA0YyAyY3VjIDJjdSA0YyIsCisJCQkJICAgICBP UEFMX0NBTEwsCisJCQkJICAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgIG1ldGhv ZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkg ICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICAgT1BBTF9WQUxVRVMsCisJCQkJICAgICBPUEFM X1NUQVJUTElTVCwKKworCQkJCSAgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgICBPUEFMX1RJ TllfVUlOVF8wNSwgLyogUmVhZExvY2tFbmFibGVkICovCisJCQkJICAgICAhIXNldHVwLT5STEUs CisJCQkJICAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgIE9QQUxfU1RBUlROQU1FLAorCQkJ CSAgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIFdyaXRlTG9ja0VuYWJsZWQgKi8KKwkJCQkgICAg ICEhc2V0dXAtPldMRSwKKworCQkJCSAgICAgT1BBTF9FTkROQU1FLAorCQkJCSAgICAgT1BBTF9F TkRMSVNULAorCQkJCSAgICAgT1BBTF9FTkROQU1FLAorCQkJCSAgICAgT1BBTF9FTkRMSVNUKTsK K30KKworc3RhdGljIGludCBzZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBvcGFsX2RldiAqZGV2 KQoreworCWNvbnN0IHU4ICptZXRob2Q7CisJdTggdWlkW09QQUxfVUlEX0xFTkdUSF07CisJc3Ry dWN0IG9wYWxfY21kICpjbWQ7CisJc3RydWN0IG9wYWxfdXNlcl9scl9zZXR1cCAqc2V0dXA7CisJ aW50IHJldDsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNl dF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NF VF07CisJcmV0ID0gYnVpbGRfbG9ja2luZ19yYW5nZSh1aWQsIHNpemVvZih1aWQpLCBkZXYtPmxy KTsKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHJh bmdlXG4iLCBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKwlzZXR1cCA9 IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKwlpZiAoZGV2LT5sciA9PSAwKQorCQly ZXQgPSBlbmFibGVfZ2xvYmFsX2xyKGNtZCwgdWlkLCBzZXR1cCk7CisJZWxzZQorCQlyZXQgPSB0 ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzICA0YyAyY3VjIDJjdWMgMmN1YyAyY3UgNGMi LAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIHVpZCwgT1BBTF9VSURfTEVOR1RILAorCQkJ CSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFMX1NUQVJUTElT VCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVkFMVUVTLAorCQkJCSAg ICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BB TF9USU5ZX1VJTlRfMDMsIC8qIFJhbmdlIFN0YXJ0ICovCisJCQkJICAgIHNldHVwLT5yYW5nZV9z dGFydCwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAor CQkJCSAgICBPUEFMX1RJTllfVUlOVF8wNCwgLyogUmFuZ2UgTGVuZ3RoICovCisJCQkJICAgIHNl dHVwLT5yYW5nZV9sZW5ndGgsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKworCQkJCSAgICBPUEFM X1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDUsIC8qIFJlYWRMb2NrRW5hYmxl ZCAqLworCQkJCSAgICAhIXNldHVwLT5STEUsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKworCQkJ CSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIFdyaXRl TG9ja0VuYWJsZWQgKi8KKwkJCQkgICAgISFzZXR1cC0+V0xFLAorCisJCQkJICAgIE9QQUxfRU5E TkFNRSwKKwkJCQkgICAgT1BBTF9FTkRMSVNULAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJ ICAgIE9QQUxfRU5ETElTVCk7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3Ig YnVpbGRpbmcgU2V0dXAgTG9ja2luZyByYW5nZSBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRf c2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBzdGFydF9hZG1p bnNwX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldiwKKwkJCQkgICAgICBlbnVtIE9Q QUxfVUlEIGF1dGgsCisJCQkJICAgICAgY29uc3QgY2hhciAqa2V5LAorCQkJCSAgICAgIHU4IGtl eV9sZW4pCit7CisJY29uc3QgdTggKm1ldGhvZCwgKnNtdWlkLCAqYWRtaW5fc3AsICpoc2E7CisJ c3RydWN0IG9wYWxfY21kICpjbWQ7CisJdTMyIEhTTjsKKwlpbnQgcmV0OworCisJaWYgKGtleSA9 PSBOVUxMICYmIGF1dGggIT0gT1BBTF9BTllCT0RZX1VJRCkgeworCQlwcl9lcnIoIiVzOiBBdHRl bXB0ZWQgdG8gb3BlbiBBRE1JTl9TUCBTZXNzaW9uIHdpdGhvdXQgYSBIb3N0IiBcCisJCSAgICAg ICAiQ2hhbGxlbmdlLCBhbmQgbm90IGFzIHRoZSBBbnlib2R5IFVJRFxuIiwgX19mdW5jX18pOwor CQlyZXR1cm4gMTsKKwl9CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21k KTsKKworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCUhTTiA9IEdFTkVSSUNfSE9TVF9T RVNTSU9OX05VTTsKKworCXNtdWlkID0gT1BBTFVJRFtPUEFMX1NNVUlEX1VJRF07CisJbWV0aG9k ID0gT1BBTE1FVEhPRFtPUEFMX1NUQVJUU0VTU0lPTl07CisJYWRtaW5fc3AgPSBPUEFMVUlEW09Q QUxfQURNSU5TUF9VSURdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMy cyBjdXNjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICBzbXVpZCwgT1BBTF9VSURfTEVO R1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKwkJCQkgICAgT1BBTF9T VEFSVExJU1QsCisJCQkJICAgIEhTTiwKKwkJCQkgICAgYWRtaW5fc3AsIE9QQUxfVUlEX0xFTkdU SCwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDEpOworCWlmIChyZXQgPCAwKSB7CisJCXByX2Vy cigiJXM6IEVycm9yIGJ1aWxkaW5nIHN0YXJ0IGFkbWluc3Agc2Vzc2lvbiBjb21tYW5kLlxuIiwK KwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwlzd2l0Y2gg KGF1dGgpIHsKKwljYXNlIE9QQUxfQU5ZQk9EWV9VSUQ6CisJCS8qIG5vdGhpbmcgbGVmdCB0byBk byBmb3IgYW55Ym9keSwganVzdCBlbmQgYW5kIGZpbmFsaXplICovCisJCXJldCA9IHRlc3RfYW5k X2FkZF90b2tlbl92YShjbWQsICJjIiwKKwkJCQkJICAgIE9QQUxfRU5ETElTVCk7CisJCWJyZWFr OworCWNhc2UgT1BBTF9TSURfVUlEOgorCQloc2EgPSBPUEFMVUlEW09QQUxfU0lEX1VJRF07CisJ CXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICIyYyBzIDNjIHMgMmMiLAorCQkJCQkg ICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMCwgLyogSG9zdENo YWxsZW5nZSAqLworCQkJCQkgICAga2V5LCBrZXlfbGVuLAorCQkJCQkgICAgT1BBTF9FTkROQU1F LAorCQkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywg LyogSG9zdFNpZ25BdXRoICovCisJCQkJCSAgICBoc2EsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkJ ICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkJICAgIE9QQUxfRU5ETElTVCk7CisJCWJyZWFrOworCWRl ZmF1bHQ6CisJCXByX2VycigiQ2Fubm90IHN0YXJ0IEFkbWluIFNQIHNlc3Npb24gd2l0aCBhdXRo ICVkXG4iLCBhdXRoKTsKKwkJcmV0dXJuIDE7CisJfQorCisJaWYgKHJldCA8IDApIHsKKwkJcHJf ZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgc3RhcnQgYWRtaW5zcCBzZXNzaW9uIGNvbW1hbmQuXG4i LAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVy biBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgc3RhcnRfb3BhbF9zZXNzaW9uX2NvbnQpOwor fQorCitzdGF0aWMgaW50IHN0YXJ0X2FueWJvZHlBU1Bfb3BhbF9zZXNzaW9uKHN0cnVjdCBvcGFs X2RldiAqZGV2KQoreworCXJldHVybiBzdGFydF9hZG1pbnNwX29wYWxfc2Vzc2lvbihkZXYsIE9Q QUxfQU5ZQk9EWV9VSUQsIE5VTEwsIDApOworfQorCitzdGF0aWMgaW50IHN0YXJ0X1NJREFTUF9v cGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJaW50IHJldDsKKwljb25zdCB1 OCAqa2V5ID0gZGV2LT5wcmV2X2RhdGE7CisKKwlpZiAoIWtleSkKKwkJcmV0ID0gc3RhcnRfYWRt aW5zcF9vcGFsX3Nlc3Npb24oZGV2LCBPUEFMX1NJRF9VSUQsIGRldi0+a2V5LAorCQkJCQkJIGRl di0+a2V5X2xlbik7CisJZWxzZSB7CisJCXJldCA9IHN0YXJ0X2FkbWluc3Bfb3BhbF9zZXNzaW9u KGRldiwgT1BBTF9TSURfVUlELCBrZXksCisJCQkJCQkgZGV2LT5wcmV2X2RfbGVuKTsKKwkJa2Zy ZWUoa2V5KTsKKwkJZGV2LT5wcmV2X2RhdGEgPSBOVUxMOworCX0KKwlyZXR1cm4gcmV0OworfQor CitzdGF0aWMgaW50IHN0YXJ0X2xvY2tpbmdzcF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2 ICpkZXYsCisJCQkJCWVudW0gT1BBTF9VSUQgYXV0aCwgY29uc3QgdTggKmtleSwKKwkJCQkJdTgg a2V5X2xlbikKK3sKKworCWNvbnN0IHU4ICptZXRob2QsICpzbXVpZCwgKmxvY2tpbmdfc3AsICpo c2E7CisJc3RydWN0IG9wYWxfY21kICpjbWQ7CisJc2l6ZV90IGtsZW4gPSBrZXlfbGVuOworCXUz MiBIU047CisJaW50IHJldDsKKworCWlmIChrZXkgPT0gTlVMTCkgeworCQlwcl9lcnIoIkNhbm5v dCBzdGFydCBMb2NraW5nIFNQIHNlc3Npb24gd2l0aG91dCBhIGtleVxuIik7CisJCXJldHVybiAt RUlOVkFMOworCX0KKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOwor CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisJSFNOID0gR0VORVJJQ19IT1NUX1NFU1NJ T05fTlVNOworCisJc211aWQgPSBPUEFMVUlEW09QQUxfU01VSURfVUlEXTsKKwltZXRob2QgPSBP UEFMTUVUSE9EW09QQUxfU1RBUlRTRVNTSU9OXTsKKwlsb2NraW5nX3NwID0gT1BBTFVJRFtPUEFM X0xPQ0tJTkdTUF9VSURdOworCWhzYSA9IE9QQUxVSURbYXV0aF07CisKKwlyZXQgPSB0ZXN0X2Fu ZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIGN1c2MgMmNzYyAyY3NjIGMiLAorCQkJCSAgICBPUEFM X0NBTEwsCisJCQkJICAgIHNtdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwg T1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBI U04sCisJCQkJICAgIGxvY2tpbmdfc3AsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgT1BBTF9U SU5ZX1VJTlRfMDEsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElO WV9VSU5UXzAwLCAvKiBIb3N0Q2hhbGxlbmdlICovCisJCQkJICAgIGtleSwga2xlbiwKKwkJCQkg ICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFM X1RJTllfVUlOVF8wMywgLyogSG9zdCBTaWduIEF1dGhvcml0eSAqLworCQkJCSAgICBoc2EsIE9Q QUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfRU5E TElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBz dGFydCBhZG1pbnNwIHNlc3Npb24gY29tbWFuZC5cbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFt ZSk7CisJCXJldHVybiByZXQ7CisJfQorCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNt ZCwgc3RhcnRfb3BhbF9zZXNzaW9uX2NvbnQpOworfQorCitzdGF0aWMgaW5saW5lIGludCBzdGFy dF9hZG1pbjFMU1Bfb3BhbF9zZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXJldHVy biBzdGFydF9sb2NraW5nc3Bfb3BhbF9zZXNzaW9uKGRldiwgT1BBTF9BRE1JTjFfVUlELAorCQkJ CQkgICAgZGV2LT5rZXksIGRldi0+a2V5X2xlbik7Cit9CisKK3N0YXRpYyBpbnQgc3RhcnRfYXV0 aF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29uc3QgdTggKm1ldGhv ZCwgKnNtdWlkLCAqbG9ja2luZ19zcDsKKwl1OCBsa191bF91c2VyW09QQUxfVUlEX0xFTkdUSF07 CisJc3RydWN0IG9wYWxfY21kICpjbWQ7CisJdTMyIEhTTjsKKwlpbnQgcmV0OworCXN0cnVjdCBv cGFsX3VzZXJfaW5mbyAqdWluZm87CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9j bWQoY21kKTsKKworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCisJSFNOID0gR0VORVJJ Q19IT1NUX1NFU1NJT05fTlVNOworCisJdWluZm8gPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRl IC0gMV07CisKKwlzbXVpZCA9IE9QQUxVSURbT1BBTF9TTVVJRF9VSURdOworCW1ldGhvZCA9IE9Q QUxNRVRIT0RbT1BBTF9TVEFSVFNFU1NJT05dOworCWxvY2tpbmdfc3AgPSBPUEFMVUlEW09QQUxf TE9DS0lOR1NQX1VJRF07CisKKwlpZiAodWluZm8tPlNVTSkgeworCQlyZXQgPSBidWlsZF9sb2Nr aW5nX3VzZXIobGtfdWxfdXNlciwgc2l6ZW9mKGxrX3VsX3VzZXIpLAorCQkJCQkgZGV2LT5scik7 CisJCWlmIChyZXQgPCAwKSB7CisJCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHVz ZXJcbiIsCisJCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQkJcmV0dXJuIHJldDsKKwkJfQor CX0gZWxzZSBpZiAodWluZm8tPndobyAhPSBPUEFMX0FETUlOMSAmJiAhdWluZm8tPlNVTSkgewor CQlyZXQgPSBidWlsZF9sb2NraW5nX3VzZXIobGtfdWxfdXNlciwgc2l6ZW9mKGxrX3VsX3VzZXIp LAorCQkJCQkgdWluZm8tPndobyAtIDEpOworCQlpZiAocmV0IDwgMCkgeworCQkJcHJfZXJyKCIl czogQ2FuJ3QgYnVpbGQgbG9ja2luZyB1c2VyXG4iLAorCQkJICAgICAgIGRldi0+ZGlza19uYW1l KTsKKwkJCXJldHVybiByZXQ7CisJCX0KKwl9IGVsc2UKKwkJbWVtY3B5KGxrX3VsX3VzZXIsIE9Q QUxVSURbT1BBTF9BRE1JTjFfVUlEXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCisJcmV0ID0gdGVz dF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyBjdXMzY3MzYyBzIDJjIiwKKwkJCQkgICAgT1BB TF9DQUxMLAorCQkJCSAgICBzbXVpZCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2Qs IE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAg SFNOLAorCQkJCSAgICBsb2NraW5nX3NwLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIE9QQUxf VElOWV9VSU5UXzAxLAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5Z X1VJTlRfMDAsCisJCQkJICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4sCisJCQkJICAgIE9QQUxf RU5ETkFNRSwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9VSU5U XzAzLAorCisJCQkJICAgIGxrX3VsX3VzZXIsIE9QQUxfVUlEX0xFTkdUSCwKKworCQkJCSAgICBP UEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgewor CQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBTVEFSVFNFU1NJT04gY29tbWFuZC5cbiIsCisJ CSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZp bmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBzdGFydF9vcGFsX3Nlc3Npb25fY29udCk7Cit9CisK K3N0YXRpYyBpbnQgcmV2ZXJ0X3RwZXIoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29uc3Qg dTggKm1ldGhvZCwgKnNtdWlkOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisK KwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKworCXNldF9jb21JRChj bWQsIGRldi0+Y29tSUQpOworCisJc211aWQgPSBPUEFMVUlEW09QQUxfQURNSU5TUF9VSURdOwor CW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9SRVZFUlRdOworCisJcmV0ID0gdGVzdF9hbmRfYWRk X3Rva2VuX3ZhKGNtZCwgImMycyAyYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgc211 aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgs CisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBPUEFMX0VORExJU1QpOworCWlmIChy ZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIFJFVkVSVCBUUEVSIGNvbW1h bmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKwor CXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKwor c3RhdGljIGludCBpbnRlcm5hbF9hY3RpdmF0ZV91c2VyKHN0cnVjdCBvcGFsX2RldiAqZGV2KQor eworCWNvbnN0IHU4ICptZXRob2Q7CisJdTggdWlkW09QQUxfVUlEX0xFTkdUSF07CisJc3RydWN0 IG9wYWxfY21kICpjbWQ7CisJaW50IHJldDsKKwlzdHJ1Y3Qgb3BhbF9hY3RpdmF0ZV91c2VyICph Y3Q7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29t SUQoY21kLCBkZXYtPmNvbUlEKTsKKworCWFjdCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUg LSAxXTsKKworCW1lbWNweSh1aWQsIE9QQUxVSURbT1BBTF9VU0VSMV9VSURdLCBPUEFMX1VJRF9M RU5HVEgpOworCXVpZFs3XSA9IGFjdC0+d2hvLndobzsKKworCW1ldGhvZCA9IE9QQUxNRVRIT0Rb T1BBTF9TRVRdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAzYyBj IDRjIDNjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdU SCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9T VEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlO VF8wMSwgLyogVmFsdWVzICovCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisKKwkJCQkgICAg T1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzA1LCAvKiBFbmFibGVkICov CisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLCAvKiBUcnVlICovCisJCQkJICAgIE9QQUxfRU5E TkFNRSwKKworCQkJCSAgICBPUEFMX0VORExJU1QsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJ CQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVy cm9yIGJ1aWxkaW5nIEFjdGl2YXRlIFVzZXJOIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5k aXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2Vu ZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBlcmFzZV9sb2NraW5n X3JhbmdlKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCWNvbnN0IHU4ICptZXRob2Q7CisJdTgg dWlkW09QQUxfVUlEX0xFTkdUSF07CisJc3RydWN0IG9wYWxfY21kICpjbWQ7CisJaW50IHJldDsK KworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChj bWQsIGRldi0+Y29tSUQpOworCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0VSQVNFXTsKKwor CWlmIChidWlsZF9sb2NraW5nX3JhbmdlKHVpZCwgc2l6ZW9mKHVpZCksIGRldi0+bHIpIDwgMCkg eworCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHJhbmdlXG4iLCBkZXYtPmRpc2tf bmFtZSk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCXJldCA9IHRlc3RfYW5kX2FkZF90b2tl bl92YShjbWQsICJjMnMgMmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIHVpZCwgT1BB TF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJ CSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQg PCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEVyYXNlIExvY2tpbmcgUmFuZ2Ug Q21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9 CisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOworfQor CitzdGF0aWMgaW50IHNldF9tYnJfZG9uZShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25z dCB1OCAqbWV0aG9kLCAqdWlkOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisK Kwl1OCBtYnJfZG9uZV90ZiA9ICoodTggKilkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07 CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQo Y21kLCBkZXYtPmNvbUlEKTsKKworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOworCXVp ZCA9IE9QQUxVSURbT1BBTF9NQlJDT05UUk9MXTsKKworCXJldCA9IHRlc3RfYW5kX2FkZF90b2tl bl92YShjbWQsICJjMnMgM2MgNmMgMmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIHVp ZCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwK KworCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJ ICAgIE9QQUxfVkFMVUVTLAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBPUEFM X1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDIsIC8qIERvbmUgKi8KKwkJCQkg ICAgbWJyX2RvbmVfdGYsICAgICAgIC8qIERvbmUgVCBvciBGICovCisJCQkJICAgIE9QQUxfRU5E TkFNRSwKKwkJCQkgICAgT1BBTF9FTkRMSVNULAorCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJ CQkgICAgT1BBTF9FTkRMSVNUKTsKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJv ciBCdWlsZGluZyBzZXQgTUJSIERvbmUgY29tbWFuZFxuIiwKKwkJICAgICAgIGRldi0+ZGlza19u YW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2 LCBjbWQsIGdlbmVyaWNfY29udCk7Cit9CisKK3N0YXRpYyBpbnQgc2V0X21icl9lbmFibGVfZGlz YWJsZShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0aG9kLCAqdWlkOwor CXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwl1OCBtYnJfZW5fZGlzID0gKih1 OCAqKWRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKworCWNtZCA9ICZkZXYtPmNtZDsK KwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCisJ bWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07CisJdWlkID0gT1BBTFVJRFtPUEFMX01CUkNP TlRST0xdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAzYyA2YyAy YyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJ CQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRM SVNULAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9WQUxVRVMsCisKKwkJ CQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBP UEFMX1RJTllfVUlOVF8wMSwgLyogRW5hYmxlICovCisJCQkJICAgIG1icl9lbl9kaXMsICAgICAg ICAvKiBFbmFibGUgb3IgRGlzYWJsZSAqLworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAg IE9QQUxfRU5ETElTVCwKKworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5E TElTVCk7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgc2V0 IE1CUiBkb25lIGNvbW1hbmRcbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVy biByZXQ7CisJfQorCisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmlj X2NvbnQpOworfQorCitzdGF0aWMgaW50IHNldF9uZXdfcHcoc3RydWN0IG9wYWxfZGV2ICpkZXYp Cit7CisJY29uc3QgdTggKm1ldGhvZDsKKwl1OCBjcGluX3VpZFtPUEFMX1VJRF9MRU5HVEhdOwor CXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisJc3RydWN0IG9wYWxfbmV3X3B3ICpw dzsKKwlzaXplX3Qga2V5X2xlbjsKKwl1OCAqa2V5OworCisJY21kID0gJmRldi0+Y21kOworCWNs ZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwlwdyA9 IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKwlrZXkgPSBwdy0+bmV3X3Bpbi5rZXk7 CisJa2V5X2xlbiA9IHB3LT5uZXdfcGluLmtleV9sZW47CisJbWVtY3B5KGNwaW5fdWlkLCBPUEFM VUlEW09QQUxfQ19QSU5fQURNSU4xXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCWlmIChwdy0+dXNl cl9mb3JfcHcgIT0gT1BBTF9BRE1JTjEpIHsKKwkJY3Bpbl91aWRbNV0gPSAweDAzOworCQlpZiAo cHctPndoby5TVU0pCisJCQljcGluX3VpZFs3XSA9IHB3LT5uZXdfcGluLmxyICsgMTsKKwkJZWxz ZQorCQkJY3Bpbl91aWRbN10gPSBwdy0+dXNlcl9mb3JfcHc7CisJfQorCisJbWV0aG9kID0gT1BB TE1FVEhPRFtPUEFMX1NFVF07CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAi YzJzIDNjIDNjczJjIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICBjcGluX3VpZCwg T1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKwor CQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAg IE9QQUxfVElOWV9VSU5UXzAxLCAvKiBWYWx1ZXMgKi8KKworCQkJCSAgICBPUEFMX1NUQVJUTElT VCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAv KiBQSU4gKi8KKwkJCQkgICAga2V5LCBrZXlfbGVuLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJ CQkJICAgIE9QQUxfRU5ETElTVCwKKworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9Q QUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWls ZGluZyBTRVQgQU1JTjEgUElOIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUp OworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNt ZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBzZXRfc2lkX2NwaW5fcGluKHN0cnVj dCBvcGFsX2RldiAqZGV2KQoreworCWNvbnN0IHU4ICptZXRob2QsICpjcGluX3VpZDsKKwlzdHJ1 Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0OworCisJY21kID0gJmRldi0+Y21kOworCWNsZWFy X29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwljcGluX3Vp ZCA9IE9QQUxVSURbT1BBTF9DX1BJTl9TSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9T RVRdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAyYyA0Y3MyYyAy YyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgY3Bpbl91aWQsIE9QQUxfVUlEX0xFTkdU SCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9T VEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCisJCQkJICAgIE9QQUxfVElOWV9V SU5UXzAxLCAvKiBWYWx1ZXMgKi8KKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9Q QUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElOICovCisJCQkJ ICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4sCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkg ICAgT1BBTF9FTkRMSVNULAorCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9F TkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5n IFNFVCBDUElOIFBJTiBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJ cmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdl bmVyaWNfY29udCk7Cit9CisKK3N0YXRpYyB2b2lkIHF1ZXJ5X2xvY2tpbmdfcmFuZ2VfY29udChp bnQgZXJyb3IsIHZvaWQgKmRhdGEpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwor CisJaWYgKGVycm9yKQorCQlnb3RvIGVycl9yZXR1cm47CisKKwllcnJvciA9IHBhcnNlX2FuZF9j aGVja19zdGF0dXMoZGV2KTsKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJyX3JldHVybjsKKworCWRl di0+c3RhcnQgPSByZXNwb25zZV9nZXRfdTY0KCZkZXYtPnBhcnNlZCwgNCk7CisJZGV2LT5sZW5n dGggPSByZXNwb25zZV9nZXRfdTY0KCZkZXYtPnBhcnNlZCwgOCk7CisKK2Vycl9yZXR1cm46CisJ aWYgKGRldi0+b3Blcl9jYikKKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYpOworfQorCitzdGF0 aWMgaW50IHF1ZXJ5X2xvY2tpbmdfcmFuZ2Uoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJdTgg bHJfYnVmZmVyW09QQUxfVUlEX0xFTkdUSF07CisJc3RydWN0IG9wYWxfY21kICpjbWQ7CisJY29u c3QgdTggKm1ldGhvZDsKKwlpbnQgcmV0OworCisJY21kID0gJmRldi0+Y21kOworCWNsZWFyX29w YWxfY21kKGNtZCk7CisKKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfR0VUXTsKKworCWlmIChi dWlsZF9sb2NraW5nX3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1ZmZlciksIGRldi0+bHIp IDwgMCkgeworCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHJhbmdlXG4iLCBkZXYt PmRpc2tfbmFtZSk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCXNldF9jb21JRChjbWQsIGRl di0+Y29tSUQpOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAxMmMi LAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVOR1RI LAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFMX1NU QVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1F LAorCQkJCSAgICBPUEFMX1NUQVJUQ09MVU1OLAorCQkJCSAgICBPUEFMX1JBTkdFU1RBUlQsCisJ CQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9Q QUxfRU5EQ09MVU1OLAorCQkJCSAgICBPUEFMX1JBTkdFTEVOR1RILAorCQkJCSAgICBPUEFMX0VO RE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKwor CWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEdFVCBMb2NraW5n IFJhbmdlIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4g cmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgcXVlcnlfbG9j a2luZ19yYW5nZV9jb250KTsKK30KKworc3RhdGljIGludCBhZGRfdXNlcl90b19scihzdHJ1Y3Qg b3BhbF9kZXYgKmRldikKK3sKKwl1OCBscl9idWZmZXJbT1BBTF9VSURfTEVOR1RIXTsKKwl1OCB1 c2VyX3VpZFtPUEFMX1VJRF9MRU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWNvbnN0 IHU4ICptZXRob2Q7CisJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrdWw7CisJaW50IHJldDsK KworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChj bWQsIGRldi0+Y29tSUQpOworCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07CisKKwls a3VsID0gZGV2LT5mdW5jX2RhdGFbZGV2LT5zdGF0ZSAtIDFdOworCisJbWVtY3B5KGxyX2J1ZmZl ciwgT1BBTFVJRFtPUEFMX0xPQ0tJTkdSQU5HRV9BQ0VfUkRMT0NLRURdLAorCSAgICAgICBPUEFM X1VJRF9MRU5HVEgpOworCisJaWYgKGxrdWwtPmxfc3RhdGUgPT0gT1BBTF9SVykKKwkJbWVtY3B5 KGxyX2J1ZmZlciwgT1BBTFVJRFtPUEFMX0xPQ0tJTkdSQU5HRV9BQ0VfV1JMT0NLRURdLAorCQkg ICAgICAgT1BBTF9VSURfTEVOR1RIKTsKKworCWxyX2J1ZmZlcls3XSA9IGRldi0+bHI7CisKKwlt ZW1jcHkodXNlcl91aWQsIE9QQUxVSURbT1BBTF9VU0VSMV9VSURdLCBPUEFMX1VJRF9MRU5HVEgp OworCXVzZXJfdWlkWzddID0gbGt1bC0+YXV0aG9yaXR5LndobzsKKworCXJldCA9IHRlc3RfYW5k X2FkZF90b2tlbl92YShjbWQsICJjMnMgM2MgM2MgMmMgMnNjIGMyc2MgY3MyYyA1YyIsCisJCQkJ ICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgbHJfYnVmZmVyLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJ ICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNU LAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDEsIC8q IFZhbHVlcyAqLworCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBPUEFMX1NUQVJU TkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIEJvb2xlYW5FeHByICovCisKKwkJ CQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCisJCQkJICAg IE9QQUxVSURbT1BBTF9IQUxGX1VJRF9BVVRIT1JJVFlfT0JKX1JFRl0sCisJCQkJICAgIE9QQUxf VUlEX0xFTkdUSF9IQUxGLAorCQkJCSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAorCQkJ CSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9Q QUxVSURbT1BBTF9IQUxGX1VJRF9BVVRIT1JJVFlfT0JKX1JFRl0sCisJCQkJICAgIE9QQUxfVUlE X0xFTkdUSF9IQUxGLAorCQkJCSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAg ICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxV SURbT1BBTF9IQUxGX1VJRF9CT09MRUFOX0FDRV0sCisJCQkJICAgIE9QQUxfVUlEX0xFTkdUSF9I QUxGLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAor CisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCQkJCSAgICBP UEFMX0VORExJU1QsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9FTkRMSVNU KTsKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBhZGQgdXNl ciB0byBsb2NraW5nIHJhbmdlIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUp OworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNt ZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBsb2NrX3VubG9ja19sb2NraW5nX3Jh bmdlKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXU4IGxyX2J1ZmZlcltPUEFMX1VJRF9MRU5H VEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWNvbnN0IHU4ICptZXRob2Q7CisJc3RydWN0 IG9wYWxfbG9ja191bmxvY2sgKmxrdWw7CisJaW50IHJldDsKKwl1OCByZWFkX2xvY2tlZCA9IDEs IHdyaXRlX2xvY2tlZCA9IDE7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQo Y21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKworCW1ldGhvZCA9IE9QQUxNRVRI T0RbT1BBTF9TRVRdOworCWxrdWwgPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07CisJ aWYgKGJ1aWxkX2xvY2tpbmdfcmFuZ2UobHJfYnVmZmVyLCBzaXplb2YobHJfYnVmZmVyKSwgZGV2 LT5scikgPCAwKSB7CisJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIs IGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJc3dpdGNoIChsa3Vs LT5sX3N0YXRlKSB7CisJY2FzZSBPUEFMX1JPOgorCQlyZWFkX2xvY2tlZCA9IDA7CisJCXdyaXRl X2xvY2tlZCA9IDE7CisJCWJyZWFrOworCWNhc2UgT1BBTF9SVzoKKwkJcmVhZF9sb2NrZWQgPSAw OworCQl3cml0ZV9sb2NrZWQgPSAwOworCQlicmVhazsKKwljYXNlIE9QQUxfTEs6CisJCS8qIHZh cnMgYXJlIGluaXRhbGl6ZWQgdG8gbG9ja2VkICovCisJCWJyZWFrOworCWRlZmF1bHQ6CisJCXBy X2VycigiVHJpZWQgdG8gc2V0IGFuIGludmFsaWQgbG9ja2luZyBzdGF0ZS4uLiByZXR1cm5pbmcg dG8gdWxhbmRcbiIpOworCQlyZXR1cm4gMTsKKwl9CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9r ZW5fdmEoY21kLCAiYzJzYyAzYyA0YyA0YyAzYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkg ICAgbHJfYnVmZmVyLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRI T0RfTEVOR1RILAorCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICBPUEFMX1NUQVJU TkFNRSwKKwkJCQkgICAgT1BBTF9WQUxVRVMsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCisJ CQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1JFQURMT0NLRUQsCisJCQkJICAg IHJlYWRfbG9ja2VkLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFS VE5BTUUsCisJCQkJICAgIE9QQUxfV1JJVEVMT0NLRUQsCisJCQkJICAgIHdyaXRlX2xvY2tlZCwK KwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAg T1BBTF9FTkROQU1FLAorCQkJCSAgICBPUEFMX0VORExJU1QpOworCisJaWYgKHJldCA8IDApIHsK KwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgU0VUIGNvbW1hbmQuXG4iLCBkZXYtPmRpc2tf bmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYs IGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworCitzdGF0aWMgaW50IGxvY2tfdW5sb2NrX2xvY2tp bmdfcmFuZ2VfU1VNKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXU4IGxyX2J1ZmZlcltPUEFM X1VJRF9MRU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWNvbnN0IHU4ICptZXRob2Q7 CisJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrdWw7CisJaW50IHJldDsKKwl1OCByZWFkX2xv Y2tlZCA9IDEsIHdyaXRlX2xvY2tlZCA9IDE7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJf b3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKworCW1ldGhvZCA9 IE9QQUxNRVRIT0RbT1BBTF9TRVRdOworCWxrdWwgPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRl IC0gMV07CisJaWYgKGJ1aWxkX2xvY2tpbmdfcmFuZ2UobHJfYnVmZmVyLCBzaXplb2YobHJfYnVm ZmVyKSwgZGV2LT5scikgPCAwKSB7CisJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcg cmFuZ2VcbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJc3dp dGNoIChsa3VsLT5sX3N0YXRlKSB7CisJY2FzZSBPUEFMX1JPOgorCQlyZWFkX2xvY2tlZCA9IDA7 CisJCXdyaXRlX2xvY2tlZCA9IDE7CisJCWJyZWFrOworCWNhc2UgT1BBTF9SVzoKKwkJcmVhZF9s b2NrZWQgPSAwOworCQl3cml0ZV9sb2NrZWQgPSAwOworCQlicmVhazsKKwljYXNlIE9QQUxfTEs6 CisJCS8qIHZhcnMgYXJlIGluaXRhbGl6ZWQgdG8gbG9ja2VkICovCisJCWJyZWFrOworCWRlZmF1 bHQ6CisJCXByX2VycigiVHJpZWQgdG8gc2V0IGFuIGludmFsaWQgbG9ja2luZyBzdGF0ZS5cbiIp OworCQlyZXR1cm4gMTsKKwl9CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAi YzJzYyAzYyA0YyA0YyA0YyA0YyAzYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgbHJf YnVmZmVyLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVO R1RILAorCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwK KwkJCQkgICAgT1BBTF9WQUxVRVMsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCisJCQkJICAg IE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1JFQURMT0NLRU5BQkxFRCwKKwkJCQkgICAg T1BBTF9UUlVFLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5B TUUsCisJCQkJICAgIE9QQUxfV1JJVEVMT0NLRU5BQkxFRCwKKwkJCQkgICAgT1BBTF9UUlVFLAor CQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAg IE9QQUxfUkVBRExPQ0tFRCwKKwkJCQkgICAgcmVhZF9sb2NrZWQsCisJCQkJICAgIE9QQUxfRU5E TkFNRSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9XUklURUxPQ0tF RCwKKwkJCQkgICAgd3JpdGVfbG9ja2VkLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkg ICAgT1BBTF9FTkRMSVNULAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5E TElTVCk7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgU0VU IGNvbW1hbmQuXG4iLCBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCXJldHVy biBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworaW50IGFj dGl2YXRlX2xzcChzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwl1OCB1c2VyX2xyW09QQUxfVUlE X0xFTkdUSF07CisJY29uc3QgdTggKm1ldGhvZCwgKnVpZDsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNt ZDsKKwlpbnQgcmV0OworCXNpemVfdCB1aW50XzMgPSAweDgzOworCisJY21kID0gJmRldi0+Y21k OworCisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsK KworCXVpZCA9IE9QQUxVSURbT1BBTF9MT0NLSU5HU1BfVUlEXTsKKwltZXRob2QgPSBPUEFMTUVU SE9EW09QQUxfQUNUSVZBVEVdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwg ImMycyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5HVEgs CisJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RIKTsKKwlpZiAocmV0IDwgMCkgewor CQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBBY3RpdmF0ZSBMb2NraW5nU1AgY29tbWFuZC5c biIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCS8qIEFj dGl2YXRpbmcgYXMgU1VNICovCisJaWYgKGRldi0+bHIgPiAwKSB7CisJCXJldCA9IGJ1aWxkX2xv Y2tpbmdfcmFuZ2UodXNlcl9sciwgc2l6ZW9mKHVzZXJfbHIpLCBkZXYtPmxyKTsKKwkJaWYgKHJl dCA8IDApIHsKKwkJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgdXNlclxuIiwKKwkJ CSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCQlyZXR1cm4gcmV0OworCQl9CisJCXRlc3RfYW5k X2FkZF90b2tlbl92YShjbWQsICIyYyA0YyBjc2MgMmMiLAorCQkJCSAgICAgIE9QQUxfU1RBUlRM SVNULAorCQkJCSAgICAgIE9QQUxfU1RBUlROQU1FLAorCisJCQkJICAgICAgdWludF8zLAorCQkJ CSAgICAgIE9QQUxfVElOWV9VSU5UXzA2LAorCQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzAwLAor CQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzAwLAorCisJCQkJICAgICAgT1BBTF9TVEFSVExJU1Qs CisJCQkJICAgICAgdXNlcl9sciwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICAgIE9QQUxfRU5E TElTVCwKKworCQkJCSAgICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgICBPUEFMX0VORExJU1Qp OworCX0gZWxzZSAvKiBBY3RpYXZlIE5vcm1hbCBNb2RlICovCisJCXJldCA9IHRlc3RfYW5kX2Fk ZF90b2tlbl92YShjbWQsICIyYyIsCisJCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkJICAg IE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBi dWlsZGluZyBBY3RpdmF0ZSBMb2NraW5nU1AgY29tbWFuZC5cbiIsCisJCSAgICAgICBkZXYtPmRp c2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5k KGRldiwgY21kLCBnZW5lcmljX2NvbnQpOworfQorCitzdGF0aWMgdm9pZCBnZXRfbHNwX2xpZmVj eWNsZV9jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKK3sKKworCXN0cnVjdCBvcGFsX2RldiAq ZGV2ID0gZGF0YTsKKwl1OCBsY19zdGF0dXM7CisKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJyX3Jl dHVybjsKKworCWVycm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhkZXYpOworCWlmIChlcnJv cikKKwkJZ290byBlcnJfcmV0dXJuOworCisJbGNfc3RhdHVzID0gcmVzcG9uc2VfZ2V0X3U2NCgm ZGV2LT5wYXJzZWQsIDQpOworCS8qIDB4MDggaXMgTWFudWZhY3VyZWQgSW5hY3RpdmUgKi8KKwkv KiAweDA5IGlzIE1hbnVmYWN0dXJlZCAqLworCWlmIChsY19zdGF0dXMgIT0gMHgwOCkgeworCQlw cl9lcnIoIiVzOiBDb3VsZG4ndCBkZXRlcm1pbmUgdGhlIHN0YXR1cyBvZiB0aGUgTGlmY3ljbGUg c3RhdGVcbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCWVycm9yID0gLUVOT0RFVjsK Kwl9CisKK2Vycl9yZXR1cm46CisJaWYgKGRldi0+b3Blcl9jYikKKwkJZGV2LT5vcGVyX2NiKGVy cm9yLCBkZXYpOworfQorCisvKiBEZXRlcm1pbmUgaWYgd2UncmUgaW4gdGhlIE1hbnVmYWN0dXJl ZCBJbmFjdGl2ZSBvciBBY3RpdmUgc3RhdGUgKi8KK2ludCBnZXRfbHNwX2xpZmVjeWNsZShzdHJ1 Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwljb25zdCB1OCAq bWV0aG9kLCAqdWlkOworCWludCByZXQ7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisKKwljbGVhcl9v cGFsX2NtZChjbWQpOworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCisJdWlkID0gT1BB TFVJRFtPUEFMX0xPQ0tJTkdTUF9VSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRVRd OworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAyYyA0YyA0YyAyYyIs CisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJ ICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNU LAorCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJ CQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIFN0YXJ0IENvbHVtbiAqLworCQkJCSAgICBPUEFM X1RJTllfVUlOVF8wNiwgLyogTGlmY3ljbGUgQ29sdW1uICovCisJCQkJICAgIE9QQUxfRU5ETkFN RSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDQs IC8qIEVuZCBDb2x1bW4gKi8KKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIExpZmVjeWNs ZSBDb2x1bW4gKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfRU5ETElT VCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2Vycigi JXM6IEVycm9yIEJ1aWxkaW5nIEdFVCBMaWZlY3ljbGUgU3RhdHVzIGNvbW1hbmRcbiIsCisJCSAg ICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZpbmFs aXplX2FuZF9zZW5kKGRldiwgY21kLCBnZXRfbHNwX2xpZmVjeWNsZV9jb250KTsKK30KKworc3Rh dGljIHZvaWQgZ2V0X21zaWRfY3Bpbl9waW5fY29udChpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCit7 CisJY29uc3QgY2hhciAqbXNpZF9waW47CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwor CXNpemVfdCBzdHJsZW47CisKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJyX3JldHVybjsKKworCWVy cm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhkZXYpOworCWlmIChlcnJvcikKKwkJZ290byBl cnJfcmV0dXJuOworCisJc3RybGVuID0gcmVzcG9uc2VfZ2V0X3N0cmluZygmZGV2LT5wYXJzZWQs IDQsICZtc2lkX3Bpbik7CisJaWYgKCFtc2lkX3BpbikgeworCQlwcl9lcnIoIiVzOiBDb3VsZG4n dCBleHRyYWN0IFBJTiBmcm9tIHJlc3BvbnNlXG4iLCBfX2Z1bmNfXyk7CisJCWVycm9yID0gMTsK KwkJZ290byBlcnJfcmV0dXJuOworCX0KKworCWRldi0+cHJldl9kYXRhID0ga21lbWR1cChtc2lk X3Bpbiwgc3RybGVuLCBHRlBfS0VSTkVMKTsKKwlpZiAoIWRldi0+cHJldl9kYXRhKQorCQllcnJv ciA9IC1FTk9NRU07CisKKwlkZXYtPnByZXZfZF9sZW4gPSBzdHJsZW47CisKKyBlcnJfcmV0dXJu OgorCWlmIChkZXYtPm9wZXJfY2IpCisJCWRldi0+b3Blcl9jYihlcnJvciwgZGV2KTsKK30KKwor c3RhdGljIGludCBnZXRfbXNpZF9jcGluX3BpbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlj b25zdCB1OCAqbWV0aG9kLCAqc211aWQ7CisJaW50IHJldDsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNt ZDsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9jb21J RChjbWQsIGRldi0+Y29tSUQpOworCisJc211aWQgPSBPUEFMVUlEW09QQUxfQ19QSU5fTVNJRF07 CisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0dFVF07CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRf dG9rZW5fdmEoY21kLCAiYyAycyAxMmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisKKwkJCQkgICAg c211aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5H VEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAor CQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIFNh cnQgQ29sdW1uICovCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAvKiBQSU4gKi8KKwkJCQkg ICAgT1BBTF9FTkROQU1FLAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9U SU5ZX1VJTlRfMDQsIC8qIEVuZCBDb2x1bW4gKi8KKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMs IC8qIFBJTiAqLworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElTVCwK KwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6 IEVycm9yIGJ1aWxkaW5nIEdldCBNU0lEIENQSU4gUElOIGNvbW1hbmQuXG4iLAorCQkgICAgICAg ZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9h bmRfc2VuZChkZXYsIGNtZCwgZ2V0X21zaWRfY3Bpbl9waW5fY29udCk7Cit9CisKK3N0YXRpYyB2 b2lkIHVubG9ja19zdXNwZW5kX2ZpbmFsKGludCBlcnJvciwgdm9pZCAqZGF0YSkKK3sKKwlzdHJ1 Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisKKwlkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQgPSBm YWxzZTsKKwlkZXYtPnJlc3VtZV9kYXRhID0gTlVMTDsKKwlkZXYtPmZ1bmNfZGF0YSA9IE5VTEw7 CisJZGV2LT5iZGV2ID0gTlVMTDsKK30KKworc3RhdGljIGludCBidWlsZF9lbmRfb3BhbF9zZXNz aW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCisJ Y21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNtZCk7CisKKwlzZXRfY29tSUQoY21k LCBkZXYtPmNvbUlEKTsKKwlyZXR1cm4gdGVzdF9hbmRfYWRkX3Rva2VuX3U4KGNtZCwgT1BBTF9F TkRPRlNFU1NJT04pOworfQorCitzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb24oc3RydWN0IG9w YWxfZGV2ICpkZXYpCit7CisJaW50IHJldCA9IGJ1aWxkX2VuZF9vcGFsX3Nlc3Npb24oZGV2KTsK KwlpZiAocmV0IDwgMCkKKwkJcmV0dXJuIHJldDsKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQo ZGV2LCAmZGV2LT5jbWQsIGVuZF9zZXNzaW9uX2NvbnQpOworfQorCitzdGF0aWMgc3RydWN0IG9w YWxfZGV2ICpmaW5kX29wYWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHU4IGxyKQor eworCXN0cnVjdCBvcGFsX2RldiAqaXRlciwgKm9wYWxfZGV2ID0gTlVMTDsKKworCWxpc3RfZm9y X2VhY2hfZW50cnkoaXRlciwgJm9wYWxfbGlzdCwgbm9kZSkgeworCQlpZiAoc3RybmNtcChpdGVy LT5kaXNrX25hbWUsIGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZSwKKwkJCSAgICBESVNLX05BTUVf TEVOKSkKKwkJCWNvbnRpbnVlOworCQlpZiAoaXRlci0+bHIgPT0gbHIpIHsKKwkJCW9wYWxfZGV2 ID0gaXRlcjsKKwkJCWJyZWFrOworCQl9CisJfQorCisJcmV0dXJuIG9wYWxfZGV2OworfQorCitz dGF0aWMgaW50IHVwZGF0ZV9vcGFsX2RldihzdHJ1Y3Qgb3BhbF9kZXYgKm9sZF9kZXYsIHN0cnVj dCBvcGFsX2RldiAqbmV3X2RldikKK3sKKwlpZiAoIWF0b21pY19hZGRfdW5sZXNzKCZvbGRfZGV2 LT5pbl91c2UsIDEsIDEpKSB7CisJCXByX2VycigiJXM6IGRldiB3YXMgaW4gdXNlXG4iLCBfX2Z1 bmNfXyk7CisJCXJldHVybiAtRUJVU1k7CisJfQorCisJb2xkX2Rldi0+a2V5X25hbWVfbGVuID0g bmV3X2Rldi0+a2V5X25hbWVfbGVuOworCWlmICghbWVtY3B5KG9sZF9kZXYtPmtleV9uYW1lLCBu ZXdfZGV2LT5rZXlfbmFtZSwgb2xkX2Rldi0+a2V5X25hbWVfbGVuKSkgeworCQlwcl9lcnIoIiVz OiBFcnJvciB1cGRhdGluZyBkZXZpY2U6XG4iLCBvbGRfZGV2LT5kaXNrX25hbWUpOworCQlyZXR1 cm4gLUVGQVVMVDsKKwl9CisKKwlpZiAoIXN0cm5jcHkob2xkX2Rldi0+ZGlza19uYW1lLCBuZXdf ZGV2LT5kaXNrX25hbWUsIERJU0tfTkFNRV9MRU4pKSB7CisJCXByX2VycigiJXM6IEVycm9yIHJl Z2lzdGVyaW5nIGRldmljZTogY29weWluZyBkaXNrIG5hbWVcbiIsCisJCSAgICAgICBvbGRfZGV2 LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVGQVVMVDsKKwl9CisKKwlvbGRfZGV2LT5jb21JRCA9 IG5ld19kZXYtPmNvbUlEOworCW9sZF9kZXYtPnN0YXJ0ID0gbmV3X2Rldi0+c3RhcnQ7CisJb2xk X2Rldi0+bGVuZ3RoID0gbmV3X2Rldi0+bGVuZ3RoOworCW9sZF9kZXYtPmFsaWduID0gbmV3X2Rl di0+YWxpZ247CisJb2xkX2Rldi0+bG93ZXN0X2xiYSA9IG5ld19kZXYtPmxvd2VzdF9sYmE7CisJ b2xkX2Rldi0+YmRldiA9IE5VTEw7CisJb2xkX2Rldi0+ZmluYWxfY2IgPSBuZXdfZGV2LT5maW5h bF9jYjsKKwlvbGRfZGV2LT5maW5hbF9jYl9kYXRhID0gbmV3X2Rldi0+ZmluYWxfY2JfZGF0YTsK KwlvbGRfZGV2LT5vcGVyX2NiID0gbmV3X2Rldi0+b3Blcl9jYjsKKwlvbGRfZGV2LT5zdGF0ZSA9 IG5ld19kZXYtPnN0YXRlOworCW9sZF9kZXYtPmZ1bmNzID0gbmV3X2Rldi0+ZnVuY3M7CisKKwlr ZnJlZShvbGRfZGV2LT5jb21wbGV0aW9uKTsKKwljbGVhbl9mdW5jdGlvbl9kYXRhKG9sZF9kZXYp OworCisJb2xkX2Rldi0+Y29tcGxldGlvbiA9IG5ld19kZXYtPmNvbXBsZXRpb247CisKKwkvKgor CSAqIFdvbid0IGJlIGFibGUgdG8gYXV0byB1bmxvY2sgdGhpcyBsb2NraW5nIHJhbmdlIGJhc2Vk IG9uIGJsb2NrCisJICogcmVxdWVzdGVzLgorCSAqLworCWlmIChvbGRfZGV2LT5sZW5ndGggPT0g MCkKKwkJcHJfd2FybigiJXM6IE1pc3NpbmcgYmxvY2sgaW5mb3JtYXRpb24gZm9yIGxvY2tpbmcg cmFuZ2UgJWRcbiIsCisJCQlvbGRfZGV2LT5kaXNrX25hbWUsIG9sZF9kZXYtPmxyKTsKKworCXJl dHVybiAwOworfQorCitpbnQgb3BhbF9yZWdpc3Rlcl9jb250KHN0cnVjdCBvcGFsX2RldiAqbmV3 X2RldikKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKm9sZF9kZXY7CisJdW5zaWduZWQgbG9uZyBmbGFn czsKKwlpbnQgZXJyb3IgPSAwOworCisJc3Bpbl9sb2NrX2lycXNhdmUoJmxpc3Rfc3BpbmxvY2ss IGZsYWdzKTsKKworCW9sZF9kZXYgPSBmaW5kX29wYWxfZGV2KG5ld19kZXYtPmJkZXYsIG5ld19k ZXYtPmxyKTsKKwlpZiAoIW9sZF9kZXYpIHsKKwkJbGlzdF9hZGRfdGFpbCgmbmV3X2Rldi0+bm9k ZSwgJm9wYWxfbGlzdCk7CisJCW9sZF9kZXYgPSBuZXdfZGV2OworCX0gZWxzZSB7CisJCWlmIChv bGRfZGV2ID09IG5ld19kZXYpCisJCQllcnJvciA9IDA7CisJCWVsc2UgeworCQkJZXJyb3IgPSB1 cGRhdGVfb3BhbF9kZXYob2xkX2RldiwgbmV3X2Rldik7CisJCQljbGVhbl9vcGFsX2tleShuZXdf ZGV2KTsKKwkJCWtmcmVlKG5ld19kZXYpOworCQl9CisJfQorCisJaWYgKGVycm9yKQorCQlsaXN0 X2RlbCgmb2xkX2Rldi0+bm9kZSk7CisKKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZsaXN0X3Nw aW5sb2NrLCBmbGFncyk7CisKKwlpZiAoIWVycm9yKQorCQlwcl9pbmZvKCIlczogUmVnaXN0ZXJl ZCBrZXkgZm9yIGxvY2tpbmcgcmFuZ2U6ICVkXG4iLAorCQkJb2xkX2Rldi0+ZGlza19uYW1lLCBv bGRfZGV2LT5scik7CisKKwlpZiAob2xkX2Rldi0+b3Blcl9jYikKKwkJb2xkX2Rldi0+b3Blcl9j YihlcnJvciwgb2xkX2Rldik7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHZvaWQgbmV4dChp bnQgZXJyb3IsIHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCW9wYWxfc3RlcCBmdW5jID0gZGV2 LT5mdW5jc1tkZXYtPnN0YXRlXTsKKwl2b2lkICpjYl9kYXRhID0gZGV2LT5maW5hbF9jYl9kYXRh OworCXNlY19jYiAqY2IgPSBkZXYtPmZpbmFsX2NiOworCWJvb2wgZG9uZSA9IGZhbHNlOworCisK KwlpZiAoZXJyb3IgfHwgIWZ1bmMpIHsKKwkJZG9uZSA9IHRydWU7CisJCWdvdG8gbmV4dF9leGl0 OworCX0KKwlkZXYtPnN0YXRlKys7CisJZGV2LT5vcGVyX2NiID0gbmV4dDsKKwllcnJvciA9IGZ1 bmMoZGV2KTsKKyBuZXh0X2V4aXQ6CisJaWYgKGVycm9yKSB7CisJCXByX2VycigiJXM6IEVycm9y IG9uIHN0ZXAgZnVuY3Rpb246ICVkIHdpdGggZXJyb3IgJWQ6ICVzXG4iLAorCQkgICAgICAgZGV2 LT5kaXNrX25hbWUsIGRldi0+c3RhdGUsIGVycm9yLAorCQkgICAgICAgb3BhbF9lcnJvcl90b19o dW1hbihlcnJvcikpOworCisKKwkJYXRvbWljX2RlYygmZGV2LT5pbl91c2UpOworCQlpZiAoZGV2 LT5lcnJvcl9jYikgeworCQkJZGV2LT5lcnJvcl9jYihkZXYtPmVycm9yX2NiX2RhdGEpOworCQkJ cmV0dXJuOworCQl9CisJCWlmIChjYikKKwkJCWNiKGVycm9yLCBjYl9kYXRhKTsKKworCQlkZXYt PmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVzID0gZXJyb3I7CisJCWNvbXBsZXRlKCZkZXYt PmNvbXBsZXRpb24tPmNtZF9jb21wbGV0aW9uKTsKKwl9IGVsc2UgaWYgKCFlcnJvciAmJiBkb25l KSB7CisJCWF0b21pY19kZWMoJmRldi0+aW5fdXNlKTsKKwkJaWYgKGNiKQorCQkJY2IoZXJyb3Is IGNiX2RhdGEpOworCQlkZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVzID0gZXJyb3I7 CisJCWNvbXBsZXRlKCZkZXYtPmNvbXBsZXRpb24tPmNtZF9jb21wbGV0aW9uKTsKKwl9Cit9CisK K2NvbnN0IG9wYWxfc3RlcCBlcnJvcl9lbmRfc2Vzc2lvbltdID0geworCWVuZF9vcGFsX3Nlc3Np b24sCisJTlVMTCwKK307CitzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb25fZXJyb3Ioc3RydWN0 IG9wYWxfZGV2ICpkZXYpCit7CisKKwlkZXYtPmZ1bmNzID0gZXJyb3JfZW5kX3Nlc3Npb247CisJ ZGV2LT5zdGF0ZSA9IDA7CisJZGV2LT5lcnJvcl9jYiA9IE5VTEw7CisJbmV4dCgwLCBkZXYpOwor CXJldHVybiAwOworfQorCitzdGF0aWMgc3RydWN0IG9wYWxfZGV2ICphbGxvY19vcGFsX2Rldihz dHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCB1OCBscikKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKm9w YWxfZGV2OworCXN0cnVjdCByZXF1ZXN0X3F1ZXVlICpxOworCXVuc2lnbmVkIGxvbmcgZG1hX2Fs aWduOworCWNvbnN0IGNoYXIgKmRpc2tfbmFtZTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlp bnQgcmV0OworCisJb3BhbF9kZXYgPSBremFsbG9jKHNpemVvZigqb3BhbF9kZXYpLCBHRlBfS0VS TkVMKTsKKwlpZiAoIW9wYWxfZGV2KQorCQlyZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKKworCW9w YWxfZGV2LT5iZGV2ID0gYmRldjsKKwlvcGFsX2Rldi0+bHIgPSBscjsKKwljbWQgPSAmb3BhbF9k ZXYtPmNtZDsKKwljbWQtPmNtZCA9IGNtZC0+Y21kX2J1ZjsKKwljbWQtPnJlc3AgPSBjbWQtPnJl c3BfYnVmOworCisJZGlza19uYW1lID0gYmRldi0+YmRfZGlzay0+ZGlza19uYW1lOworCWlmICgh c3RybmNweShvcGFsX2Rldi0+ZGlza19uYW1lLCBkaXNrX25hbWUsIERJU0tfTkFNRV9MRU4pKSB7 CisJCXByX2VycigiJXM6IEVycm9yIHJlZ2lzdGVyaW5nIGRldmljZTogY29weWluZyBkaXNrIG5h bWVcbiIsCisJCSAgICAgICBkaXNrX25hbWUpOworCQlyZXQgPSAtRUZBVUxUOworCQlnb3RvIGVy cl9mcmVlX2RldjsKKwl9CisKKwlxID0gYmRldi0+YmRfcXVldWU7CisJZG1hX2FsaWduID0gKHF1 ZXVlX2RtYV9hbGlnbm1lbnQocSkgfCBxLT5kbWFfcGFkX21hc2spICsgMTsKKwljbWQtPmNtZCA9 ICh1OCAqKXJvdW5kX3VwKCh1aW50cHRyX3QpY21kLT5jbWQsIGRtYV9hbGlnbik7CisJY21kLT5y ZXNwID0gKHU4ICopcm91bmRfdXAoKHVpbnRwdHJfdCljbWQtPnJlc3AsIGRtYV9hbGlnbik7CisK KwlJTklUX0xJU1RfSEVBRCgmb3BhbF9kZXYtPm5vZGUpOworCWF0b21pY19zZXQoJm9wYWxfZGV2 LT5pbl91c2UsIDEpOworCisJb3BhbF9kZXYtPmNvbXBsZXRpb24gPSBremFsbG9jKHNpemVvZigq b3BhbF9kZXYtPmNvbXBsZXRpb24pLAorCQkJCSAgICAgICBHRlBfS0VSTkVMKTsKKworCWlmICgh b3BhbF9kZXYtPmNvbXBsZXRpb24pCisJCWdvdG8gZXJyX2ZyZWVfZGV2OworCisJaW5pdF9jb21w bGV0aW9uKCZvcGFsX2Rldi0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24pOworCW9wYWxfZGV2 LT5jb21wbGV0aW9uLT5jb21wbGV0aW9uX3N0YXR1cyA9IDA7CisJb3BhbF9kZXYtPnN0YXRlID0g MDsKKwlJTklUX1dPUksoJm9wYWxfZGV2LT5vcGFsX3NlbmRfd29yaywgX29wYWxfc2VuZF9jbWQp OworCUlOSVRfV09SSygmb3BhbF9kZXYtPm9wYWxfcmVjdl93b3JrLCBfb3BhbF9yZWN2X2NtZCk7 CisKKworCXJldHVybiBvcGFsX2RldjsKKworZXJyX2ZyZWVfZGV2OgorCWtmcmVlKG9wYWxfZGV2 KTsKKwlyZXR1cm4gRVJSX1BUUihyZXQpOworfQorCitpbnQgb3BhbF9yZWdpc3RlcihzdHJ1Y3Qg YmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgb3BhbF9rZXkgKmtleV9jbWQsCisJCSAgY29uc3Qg b3BhbF9zdGVwICpmdW5jcykKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKm5ld19kZXYgPSBOVUxMOwor CXU4IGtleV9sZW4gPSBrZXlfY21kLT5rZXlfbGVuOworCXU4IGxyID0ga2V5X2NtZC0+bHI7CisJ c3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKKwlpbnQgcmV0OworCisJbmV3X2Rl diA9IGFsbG9jX29wYWxfZGV2KGJkZXYsIGxyKTsKKwlpZiAoSVNfRVJSKG5ld19kZXYpKSB7CisJ CXByX2VycigiJXM6IEVycm9yIHJlZ2lzdGVyaW5nIGRldmljZTogYWxsb2NhdGlvblxuIiwKKwkJ ICAgICAgIGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZSk7CisJCXJldHVybiBQVFJfRVJSKG5ld19k ZXYpOworCX0KKworCWlmICghbWVtY3B5KG5ld19kZXYtPmtleV9uYW1lLCBrZXlfY21kLT5rZXks IGtleV9sZW4pKSB7CisJCXByX2VycigiJXM6IEVycm9yIHJlZ2lzdGVyaW5nIGtleTogY291bGRu J3QgY29weSBrZXlcbiIsCisJCSAgICAgICBuZXdfZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4g LUVGQVVMVDsKKwl9CisKKwluZXdfZGV2LT5rZXlfbmFtZV9sZW4gPSBrZXlfbGVuOworCW5ld19k ZXYtPmtleV90eXBlID0ga2V5X2NtZC0+a2V5X3R5cGU7CisJcmV0ID0gZ2V0X29wYWxfa2V5KG5l d19kZXYpOworCWlmIChyZXQpIHsKKwkJcHJfZXJyKCIlczogQ291bGRuJ3QgZ2V0IGtleTogJWRc biIsIG5ld19kZXYtPmRpc2tfbmFtZSwgcmV0KTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwluZXdf ZGV2LT5mdW5jcyA9IGZ1bmNzOworCisJbmV3X2Rldi0+c3RhdGUgPSAwOworCWNvbXBsZXRpb24g PSBuZXdfZGV2LT5jb21wbGV0aW9uOworCW5leHQoMCwgbmV3X2Rldik7CisKKwlyZXR1cm4gd2Fp dF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxldGlvbik7Cit9CisKK3N0YXRpYyBzdHJ1Y3Qgb3Bh bF9kZXYgKmdldF9yZWdpc3RlcmVkX29wYWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYs CisJCQkJCQl1OCBscikKK3sKKwljb25zdCBjaGFyICpkaXNrbmFtZSA9IGJkZXYtPmJkX2Rpc2st PmRpc2tfbmFtZTsKKwlzdHJ1Y3Qgb3BhbF9kZXYgKml0ZXIsICpkZXYgPSBOVUxMOworCXVuc2ln bmVkIGxvbmcgZmxhZ3M7CisJYm9vbCBpbl91c2UgPSBmYWxzZTsKKworCXNwaW5fbG9ja19pcnFz YXZlKCZsaXN0X3NwaW5sb2NrLCBmbGFncyk7CisJbGlzdF9mb3JfZWFjaF9lbnRyeShpdGVyLCAm b3BhbF9saXN0LCBub2RlKSB7CisJCWlmIChzdHJuY21wKGl0ZXItPmRpc2tfbmFtZSwgZGlza25h bWUsIERJU0tfTkFNRV9MRU4pKQorCQkJY29udGludWU7CisJCWlmIChpdGVyLT5sciA9PSBscikg eworCQkJZGV2ID0gaXRlcjsKKwkJCWlmICghYXRvbWljX2FkZF91bmxlc3MoJml0ZXItPmluX3Vz ZSwgMSwgMSkpIHsKKwkJCQlkZXYgPSBOVUxMOworCQkJCWluX3VzZSA9IHRydWU7CisJCQl9CisJ CQlicmVhazsKKwkJfQorCX0KKworCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmxpc3Rfc3Bpbmxv Y2ssIGZsYWdzKTsKKworCWlmICghZGV2KQorCQlyZXR1cm4gTlVMTDsKKworCWRldi0+YmRldiA9 IGJkZXY7CisJcmV0dXJuIGRldjsKK30KKworLyogRnJlZSB1cCB0aGUgT3BhbCBkZXYgYW5kIGl0 cyBrZXlzIGR1cmluZyB0d28gc2NlbmFyaW9zOgorICoKKyAqIDEpIFdoZW4gYSBjb21tYW5kIGlz IGNvbXBsZXRlIHRoYXQgbm8gbG9uZ2VyIHJlcXVpcmVzCisgKiAgICB0aGUgb3BhbCBkZXYgdG8g YmUgYXJvdW5kLgorICogMikgV2hlbiBhIGNvbW1hbmQsIGluY2x1ZGluZyBPcGFsIFNhdmUgZmFp bHMgd2UgY2xlYW4KKyAqICAgIGFuZCBmcmVlIHRoZSBvcGFsIGRldi4KKyAqCisgKiAgICBJZiB3 ZSBmaW5kIHRoZSBvcGFsIGRldiBzdHJ1Y3R1cmUgaW4gdGhlIGxpc3Qgb2YKKyAqICAgIHNhdmVk IHBhc3N3b3JkcyB3ZSB3aWxsICpub3QqIHJlbW92ZSBpdC4KKyAqLworc3RhdGljIHZvaWQgcmVt b3ZlX2FuZF9jbGVhbl9vcGFsX2RldihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlzdHJ1Y3Qg b3BhbF9kZXYgKml0ZXI7CisJYm9vbCBmb3VuZCA9IGZhbHNlOworCisJc3Bpbl9sb2NrKCZsaXN0 X3NwaW5sb2NrKTsKKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGl0ZXIsICZvcGFsX2xpc3QsIG5vZGUp IHsKKwkJaWYgKGl0ZXIgPT0gZGV2KSB7CisJCQlmb3VuZCA9IHRydWU7CisJCQlicmVhazsKKwkJ fQorCX0KKworCXNwaW5fdW5sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKwlpZiAoIWZvdW5kKSB7CisJ CWNsZWFuX29wYWxfa2V5KGRldik7CisJCWNsZWFuX2Z1bmN0aW9uX2RhdGEoZGV2KTsKKwkJa2Zy ZWUoZGV2KTsKKwl9Cit9CisKK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9kZXYgKmdldF9vcl9jcmVhdGVf b3BhbF9kZXYoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCQkJICAgICAgIHU4IGxyLCBi b29sIHVzZV9uZXcpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBOVUxMOworCisJaWYgKCF1 c2VfbmV3KQorCQlkZXYgPSBnZXRfcmVnaXN0ZXJlZF9vcGFsX2RldihiZGV2LCBscik7CisKKwlp ZiAoIWRldikKKwkJZGV2ID0gYWxsb2Nfb3BhbF9kZXYoYmRldiwgbHIpOworCisJcmV0dXJuIGRl djsKK30KKworc3RhdGljIHN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKnNldHVwX29wYWxfZGV2KHN0 cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkJCSAgICAgIHN0cnVjdCBvcGFsX2RldiAqZGV2 LAorCQkJCQkgICAgICBjb25zdCBvcGFsX3N0ZXAgKmZ1bmNzLAorCQkJCQkgICAgICBzdHJ1Y3Qg b3BhbF9rZXkgKmtleSkKK3sKKwlpbnQgcmV0OworCisJZGV2LT5iZGV2ID0gYmRldjsKKwlkZXYt PnN0YXRlID0gMDsKKwlkZXYtPmZ1bmNzID0gZnVuY3M7CisJZGV2LT5UU04gPSAwOworCWRldi0+ SFNOID0gMDsKKwlkZXYtPmZpbmFsX2NiID0gTlVMTDsKKwlkZXYtPmZpbmFsX2NiX2RhdGEgPSBO VUxMOworCWRldi0+bHIgPSBrZXktPmxyOworCWRldi0+ZXJyb3JfY2IgPSBlbmRfb3BhbF9zZXNz aW9uX2Vycm9yOworCWRldi0+ZXJyb3JfY2JfZGF0YSA9IGRldjsKKworCWlmIChrZXkpIHsKKwkJ bWVtY3B5KGRldi0+a2V5X25hbWUsIGtleS0+a2V5LCBrZXktPmtleV9sZW4pOworCQlkZXYtPmtl eV9uYW1lX2xlbiA9IGtleS0+a2V5X2xlbjsKKwkJZGV2LT5rZXlfdHlwZSA9IGtleS0+a2V5X3R5 cGU7CisKKwkJcmV0ID0gZ2V0X29wYWxfa2V5KGRldik7CisJCWlmIChyZXQpIHsKKwkJCWtmcmVl KGRldi0+Y29tcGxldGlvbik7CisJCQlwcl9lcnIoIiVzOiBDb3VsZG4ndCBnZXQga2V5OiAlZFxu IiwKKwkJCSAgICAgICBkZXYtPmRpc2tfbmFtZSwgcmV0KTsKKwkJCXJldHVybiBFUlJfUFRSKHJl dCk7CisJCX0KKwl9CisJZGV2LT5mdW5jX2RhdGEgPSBOVUxMOworCWRldi0+Y29tcGxldGlvbi0+ Y29tcGxldGlvbl9zdGF0dXMgPSAwOworCXJldHVybiBkZXYtPmNvbXBsZXRpb247Cit9CisKK3N0 YXRpYyBpbnQgaW50ZXJuYWxfc2V0dXBfbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKKwkJ CSAgICAgc3RydWN0IG9wYWxfdXNlcl9scl9zZXR1cCAqc2V0dXApCit7CisJc3RydWN0IG9wYWxf ZGV2ICpkZXY7CisJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKKwl2b2lkICpk YXRhWzNdID0geyBOVUxMIH07CisJY29uc3Qgb3BhbF9zdGVwIGxyX2Z1bmNzW10gPSB7CisJCW9w YWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCisJCXNldHVwX2xvY2tp bmdfcmFuZ2UsCisJCWdldF9hY3RpdmVfa2V5LAorCQlnZW5fa2V5LAorCQllbmRfb3BhbF9zZXNz aW9uLAorCQlOVUxMLAorCX07CisJaW50IHJldDsKKworCWRldiA9IGdldF9vcl9jcmVhdGVfb3Bh bF9kZXYoYmRldiwgc2V0dXAtPmtleS5sciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJldHVybiAt RU5PTUVNOworCisJY29tcGxldGlvbiA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwgbHJfZnVu Y3MsICZzZXR1cC0+a2V5KTsKKwlpZiAoSVNfRVJSKGNvbXBsZXRpb24pKSB7CisJCXJldCA9IFBU Ul9FUlIoY29tcGxldGlvbik7CisJCWdvdG8gZXJyb3JfcmV0dXJuOworCX0KKworCWRldi0+ZnVu Y19kYXRhID0gZGF0YTsKKwlkZXYtPm51bV9mdW5jX2RhdGEgPSAzOworCWRldi0+ZnVuY19kYXRh WzFdID0gJnNldHVwLT53aG87CisJZGV2LT5mdW5jX2RhdGFbMl0gPSBzZXR1cDsKKworCW5leHQo MCwgZGV2KTsKKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsKKwor IGVycm9yX3JldHVybjoKKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7CisJcmV0dXJu IHJldDsKK30KKworaW50IG9wYWxfcmV2ZXJ0KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0 cnVjdCBvcGFsX2tleSAqa2V5KQoreworCWNvbnN0IG9wYWxfc3RlcCByZXZlcnRfZnVuY3NbXSA9 IHsKKwkJb3BhbF9kaXNjb3ZlcnkwLAorCQlzdGFydF9TSURBU1Bfb3BhbF9zZXNzaW9uLAorCQly ZXZlcnRfdHBlciwgLyogY29udHJvbGxlciB3aWxsIHRlcm1pbmF0ZSBzZXNzaW9uICovCisJCU5V TEwsCisJfTsKKworCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYsIGtleSwgcmV2ZXJ0X2Z1bmNz KTsKK30KKworaW50IGFjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3Ry dWN0IG9wYWxfYWN0aXZhdGVfdXNlciAqYWN0KQoreworCWNvbnN0IG9wYWxfc3RlcCBhY3RfZnVu Y3NbXSA9IHsKKwkJb3BhbF9kaXNjb3ZlcnkwLAorCQlzdGFydF9hZG1pbjFMU1Bfb3BhbF9zZXNz aW9uLAorCQlpbnRlcm5hbF9hY3RpdmF0ZV91c2VyLAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlO VUxMCisJfTsKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9u ICpjb21wbGV0aW9uOworCXZvaWQgKmRhdGFbM10gPSB7IE5VTEwgfTsKKwlpbnQgcmV0OworCisJ ZGV2ID0gZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihiZGV2LCBhY3QtPmtleS5sciwgdHJ1ZSk7CisJ aWYgKCFkZXYpCisJCXJldHVybiAtRU5PTUVNOworCisJY29tcGxldGlvbiA9IHNldHVwX29wYWxf ZGV2KGJkZXYsIGRldiwgYWN0X2Z1bmNzLCAmYWN0LT5rZXkpOworCWlmIChJU19FUlIoY29tcGxl dGlvbikpIHsKKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1 cm47CisJfQorCisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYtPmZ1bmNfZGF0YSA9IGRh dGE7CisJZGV2LT5mdW5jX2RhdGFbMV0gPSBhY3Q7CisJZGV2LT5mdW5jX2RhdGFbMl0gPSBhY3Q7 CisKKwluZXh0KDAsIGRldik7CisJcmV0ID0gd2FpdF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxl dGlvbik7CisKKyBlcnJvcl9yZXR1cm46CisJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2RldihkZXYp OworCXJldHVybiByZXQ7Cit9CisKK2ludCBvcGFsX3NldF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNl ICpiZGV2LCBzdHJ1Y3Qgb3BhbF9uZXdfcHcgKnB3KQorCit7CisJY29uc3Qgb3BhbF9zdGVwIHB3 X2Z1bmNzW10gPSB7CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Np b24sCisJCXNldF9uZXdfcHcsCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEwKKwl9OworCXN0 cnVjdCBvcGFsX2RldiAqZGV2OworCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247 CisJdm9pZCAqZGF0YVszXSA9IHsgTlVMTCB9OworCWludCByZXQ7CisKKwlkZXYgPSBnZXRfb3Jf Y3JlYXRlX29wYWxfZGV2KGJkZXYsIHB3LT5jdXJyZW50X3Bpbi5sciwgdHJ1ZSk7CisJaWYgKCFk ZXYpCisJCXJldHVybiAtRU5PTUVNOworCisJY29tcGxldGlvbiA9IHNldHVwX29wYWxfZGV2KGJk ZXYsIGRldiwgcHdfZnVuY3MsICZwdy0+Y3VycmVudF9waW4pOworCWlmIChJU19FUlIoY29tcGxl dGlvbikpIHsKKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1 cm47CisJfQorCisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYtPmZ1bmNfZGF0YSA9IGRh dGE7CisJZGV2LT5mdW5jX2RhdGFbMV0gPSAodm9pZCAqKSAmcHctPndobzsKKwlkZXYtPmZ1bmNf ZGF0YVsyXSA9ICh2b2lkICopIHB3OworCisJbmV4dCgwLCBkZXYpOworCXJldCA9IHdhaXRfZm9y X2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJyb3JfcmV0dXJuOgorCXJlbW92ZV9h bmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworfQorCitpbnQgb3BhbF9hY3Rf bHNwX2ludChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgb3BhbF9rZXkgKmtleSwK KwkJICAgICBjb25zdCBvcGFsX3N0ZXAgKmZ1bmNzKQoreworCXN0cnVjdCBvcGFsX2RldiAqZGV2 OworCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJaW50IHJldDsKKworCWRl diA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwga2V5LT5sciwgdHJ1ZSk7CisJaWYgKCFk ZXYpCisJCXJldHVybiAtRU5PTUVNOworCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2RldihiZGV2 LCBkZXYsIGZ1bmNzLCBrZXkpOworCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsKKwkJcmV0ID0g UFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1cm47CisJfQorCisJbmV4dCgw LCBkZXYpOworCXJldCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCisg ZXJyb3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4g cmV0OworfQorCisKK3N0YXRpYyBpbnQgb3BhbF9zYXZlX2ludGVybmFsKHN0cnVjdCBibG9ja19k ZXZpY2UgKmJkZXYsCisJCQkgICAgICBzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayAqbGspCit7CisJ dm9pZCAqZnVuY19kYXRhWzNdID0geyBOVUxMIH07CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7CisJ c3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKKwljb25zdCBvcGFsX3N0ZXAgX2F1 dGhfZnVuY3NbXSA9IHsKKwkJb3BhbF9kaXNjb3ZlcnkwLAorCQlzdGFydF9hdXRoX29wYWxfc2Vz c2lvbiwKKwkJcXVlcnlfbG9ja2luZ19yYW5nZSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJb3Bh bF9yZWdpc3Rlcl9jb250LAorCQlOVUxMCisJfTsKKwlpbnQgcmV0OworCisJZGV2ID0gZ2V0X29y X2NyZWF0ZV9vcGFsX2RldihiZGV2LCBsay0+a2V5LmxyLCBmYWxzZSk7CisJaWYgKCFkZXYpCisJ CXJldHVybiAtRU5PTUVNOworCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2RldihiZGV2LCBkZXYs IF9hdXRoX2Z1bmNzLCAmbGstPmtleSk7CisJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgeworCQly ZXQgPSBQVFJfRVJSKGNvbXBsZXRpb24pOworCQlnb3RvIGVycm9yX3JldHVybjsKKwl9CisKKwlk ZXYtPm51bV9mdW5jX2RhdGEgPSAzOworCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOworCWRl di0+ZnVuY19kYXRhWzFdID0gJmxrLT5hdXRob3JpdHk7CisJZGV2LT5sa3VsID0gKmxrOworCisJ bmV4dCgwLCBkZXYpOworCXJldCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24p OworCisgZXJyb3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwly ZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IGFkZF91c2VyX2xyX2ludGVybmFsKHN0cnVjdCBi bG9ja19kZXZpY2UgKmJkZXYsCisJCQkJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrKQorewor CXZvaWQgKmZ1bmNfZGF0YVszXSA9IHsgTlVMTCB9OworCXN0cnVjdCBvcGFsX2RldiAqZGV2Owor CXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJY29uc3Qgb3BhbF9zdGVwIGZ1 bmNzW10gPSB7CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxfc2Vz c2lvbiwKKwkJYWRkX3VzZXJfdG9fbHIsCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEwKKwl9 OworCWludCByZXQ7CisKKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJkZXYsIGxrLT5r ZXkubHIsIHRydWUpOworCWlmICghZGV2KQorCQlyZXR1cm4gLUVOT01FTTsKKwljb21wbGV0aW9u ID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBmdW5jcywgJmxrLT5rZXkpOworCWlmIChJU19F UlIoY29tcGxldGlvbikpIHsKKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBl cnJvcl9yZXR1cm47CisJfQorCisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYtPmZ1bmNf ZGF0YSA9IGZ1bmNfZGF0YTsKKwlkZXYtPmZ1bmNfZGF0YVsyXSA9IGxrOworCisJbmV4dCgwLCBk ZXYpOworCXJldCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJy b3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0 OworfQorCisvKiBUaGVzZSBhcmUgZ2xvYmFsJ2QgYmVjYXVzZSBib3RoIGxvY2tfdW5sb2NrX2lu dGVybmFsCisgKiBhbmQgb3BhbF91bmxvY2tfZnJvbV9zdXNwZW5kIG5lZWQgdGhlbS4KKyAqLwor Y29uc3Qgb3BhbF9zdGVwIHVsa19mdW5jc19TVU1bXSA9IHsKKwlvcGFsX2Rpc2NvdmVyeTAsCisJ c3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCisJbG9ja191bmxvY2tfbG9ja2luZ19yYW5nZV9TVU0s CisJZW5kX29wYWxfc2Vzc2lvbiwKKwlOVUxMCit9OworY29uc3Qgb3BhbF9zdGVwIF91bmxvY2tf ZnVuY3NbXSA9IHsKKwlvcGFsX2Rpc2NvdmVyeTAsCisJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24s CisJbG9ja191bmxvY2tfbG9ja2luZ19yYW5nZSwKKwllbmRfb3BhbF9zZXNzaW9uLAorCU5VTEwK K307CitzdGF0aWMgaW50IGxvY2tfdW5sb2NrX2ludGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2Ug KmJkZXYsCisJCQkJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrKQoreworCXZvaWQgKmZ1bmNf ZGF0YVszXSA9IHsgTlVMTCB9OworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXN0cnVjdCBvcGFs X2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisKKwlpbnQgcmV0OworCisJZGV2ID0gZ2V0X29yX2Ny ZWF0ZV9vcGFsX2RldihiZGV2LCBsay0+a2V5LmxyLCB0cnVlKTsKKwlpZiAoIWRldikKKwkJcmV0 dXJuIC1FTk9NRU07CisKKwlpZiAobGstPmF1dGhvcml0eS5TVU0pCisJCWNvbXBsZXRpb24gPSBz ZXR1cF9vcGFsX2RldihiZGV2LCBkZXYsIHVsa19mdW5jc19TVU0sICZsay0+a2V5KTsKKwllbHNl CisJCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2RldihiZGV2LCBkZXYsIF91bmxvY2tfZnVuY3Ms ICZsay0+a2V5KTsKKworCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsKKwkJcmV0ID0gUFRSX0VS Uihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1cm47CisJfQorCisJZGV2LT5udW1fZnVu Y19kYXRhID0gMzsKKwlkZXYtPmZ1bmNfZGF0YSA9IGZ1bmNfZGF0YTsKKwlkZXYtPmZ1bmNfZGF0 YVsxXSA9ICZsay0+YXV0aG9yaXR5OworCWRldi0+ZnVuY19kYXRhWzJdID0gbGs7CisKKwluZXh0 KDAsIGRldik7CisJcmV0ID0gd2FpdF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxldGlvbik7CisK KyBlcnJvcl9yZXR1cm46CisJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2RldihkZXYpOworCXJldHVy biByZXQ7Cit9CisKK2ludCBvcGFsX2VyYXNlX2xvY2tpbmdfcmFuZ2Uoc3RydWN0IGJsb2NrX2Rl dmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRl djsKKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpjb21wbGV0aW9uOworCXN0cnVjdCBvcGFsX2tl eSBrOworCWludCByZXQ7CisJY29uc3Qgb3BhbF9zdGVwIGVyYXNlX2Z1bmNzW10gPSB7CisJCW9w YWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxfc2Vzc2lvbiwKKwkJZXJhc2Vf bG9ja2luZ19yYW5nZSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJTlVMTCwKKwl9OworCisJaWYg KCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7CisJCXByX2VycigiQ2FuJ3Qgc2F2ZSBwYXNzd29y ZCBmb3IgTlVMTCBibG9jayBkZXZpY2UuXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJ aWYgKGNvcHlfZnJvbV91c2VyKCZrLCBrZXktPm9wYWwsIHNpemVvZigqa2V5LT5vcGFsKSkpCisJ CXJldHVybiAtRUZBVUxUOworCisJZGV2ID0gZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihiZGV2LCBr LmxyLCB0cnVlKTsKKwlpZiAoIWRldikKKwkJcmV0dXJuIC1FTk9NRU07CisKKwljb21wbGV0aW9u ID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBlcmFzZV9mdW5jcywgJmspOworCWlmIChJU19F UlIoY29tcGxldGlvbikpIHsKKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBl cnJvcl9yZXR1cm47CisJfQorCisJbmV4dCgwLCBkZXYpOworCXJldCA9IHdhaXRfZm9yX2NtZF9j b21wbGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJyb3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xl YW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworfQorRVhQT1JUX1NZTUJPTChvcGFsX2Vy YXNlX2xvY2tpbmdfcmFuZ2UpOworCitpbnQgb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFkb3dfbWJy KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkJICAgc3RydWN0IHNlZF9rZXkgKmtleSkK K3sKKwl2b2lkICpmdW5jX2RhdGFbNl0gPSB7IE5VTEwgfTsKKwlzdHJ1Y3Qgb3BhbF9tYnJfZGF0 YSBtYnI7CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7CisJc3RydWN0IG9wYWxfY29tcGxldGlvbiAq Y29tcGxldGlvbjsKKwljb25zdCBvcGFsX3N0ZXAgbWJyX2Z1bmNzW10gPSB7CisJCW9wYWxfZGlz Y292ZXJ5MCwKKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxfc2Vzc2lvbiwKKwkJc2V0X21icl9kb25l LAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlzdGFydF9hZG1pbjFMU1Bfb3BhbF9zZXNzaW9uLAor CQlzZXRfbWJyX2VuYWJsZV9kaXNhYmxlLAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlOVUxMLAor CX07CisJaW50IHJldDsKKworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzaykgeworCQlwcl9l cnIoIkNhbid0IHNhdmUgcGFzc3dvcmQgZm9yIE5VTEwgYmxvY2sgZGV2aWNlLlxuIik7CisJCXJl dHVybiAtRUlOVkFMOworCX0KKworCWlmIChjb3B5X2Zyb21fdXNlcigmbWJyLCBrZXktPm9wYWxf bWJyLCBzaXplb2YoKmtleS0+b3BhbF9tYnIpKSkKKwkJcmV0dXJuIC1FRkFVTFQ7CisKKwlpZiAo bWJyLmVuYWJsZV9kaXNhYmxlICE9IE9QQUxfTUJSX0VOQUJMRSAmJgorCSAgICBtYnIuZW5hYmxl X2Rpc2FibGUgIT0gT1BBTF9NQlJfRElTQUJMRSkKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwlkZXYg PSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJkZXYsIG1ici5rZXkubHIsIHRydWUpOworCWlmICgh ZGV2KQorCQlyZXR1cm4gLUVOT01FTTsKKworCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2Rldihi ZGV2LCBkZXYsIG1icl9mdW5jcywgJm1ici5rZXkpOworCWlmIChJU19FUlIoY29tcGxldGlvbikp IHsKKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1cm47CisJ fQorCisJZGV2LT5udW1fZnVuY19kYXRhID0gNjsKKwlkZXYtPmZ1bmNfZGF0YSA9IGZ1bmNfZGF0 YTsKKwlkZXYtPmZ1bmNfZGF0YVsyXSA9ICZtYnIuZW5hYmxlX2Rpc2FibGU7CisJZGV2LT5mdW5j X2RhdGFbNV0gPSAmbWJyLmVuYWJsZV9kaXNhYmxlOworCisJbmV4dCgwLCBkZXYpOworCXJldCA9 IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJyb3JfcmV0dXJuOgor CXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworCit9CitFWFBP UlRfU1lNQk9MKG9wYWxfZW5hYmxlX2Rpc2FibGVfc2hhZG93X21icik7CisKK2ludCBvcGFsX3Nh dmUoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlz dHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayBsa3VsOworCisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9k aXNrKSB7CisJCXByX2VycigiQ2FuJ3Qgc2F2ZSBwYXNzd29yZCBmb3IgTlVMTCBibG9jayBkZXZp Y2UuXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJaWYgKGNvcHlfZnJvbV91c2VyKCZs a3VsLCBrZXktPm9wYWxfbGtfdW5saywgc2l6ZW9mKCprZXktPm9wYWwpKSkKKwkJcmV0dXJuIC1F RkFVTFQ7CisKKwlyZXR1cm4gb3BhbF9zYXZlX2ludGVybmFsKGJkZXYsICZsa3VsKTsKK30KK0VY UE9SVF9TWU1CT0wob3BhbF9zYXZlKTsKKworaW50IG9wYWxfYWRkX3VzZXJfdG9fbHIoc3RydWN0 IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlzdHJ1Y3Qgb3Bh bF9sb2NrX3VubG9jayBsa3VsOworCisJaWYgKGNvcHlfZnJvbV91c2VyKCZsa3VsLCBrZXktPm9w YWxfbGtfdW5saywgc2l6ZW9mKGxrdWwpKSkKKwkJcmV0dXJuIC1FRkFVTFQ7CisKKwlpZiAoIWJk ZXYgfHwgIWJkZXYtPmJkX2Rpc2spIHsKKwkJcHJfZXJyKCJDYW4ndCBhc3NpZ24gdXNlciB0byBM UiB3aXRob3V0IGJhY2tpbmcgZGlza1xuIik7CisJCXJldHVybiAtRUZBVUxUOworCX0KKwlpZiAo bGt1bC5sX3N0YXRlICE9IE9QQUxfUk8gJiYgbGt1bC5sX3N0YXRlICE9IE9QQUxfUlcpIHsKKwkJ cHJfZXJyKCJMb2NraW5nIHN0YXRlIHdhcyBub3QgUk8gb3IgUldcbiIpOworCQlyZXR1cm4gLUVJ TlZBTDsKKwl9CisJaWYgKGxrdWwuYXV0aG9yaXR5LndobyA8IE9QQUxfVVNFUjEgJiYKKwkgICAg bGt1bC5hdXRob3JpdHkud2hvID4gT1BBTF9VU0VSOSkgeworCQlwcl9lcnIoIkF1dGhvcml0eSB3 YXMgbm90IHdpdGhpbiB0aGUgcmFuZ2Ugb2YgdXNlcnM6ICVkXG4iLAorCQkgICAgICAgbGt1bC5h dXRob3JpdHkud2hvKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCWlmIChsa3VsLmF1dGhvcml0 eS5TVU0pIHsKKwkJcHJfZXJyKCIlcyBub3Qgc3VwcG9ydGVkIGluIFNVTS4gVXNlIHNldHVwIGxv Y2tpbmcgcmFuZ2VcbiIsCisJCSAgICAgICBfX2Z1bmNfXyk7CisJCXJldHVybiAtRUlOVkFMOwor CX0KKworCXJldHVybiBhZGRfdXNlcl9scl9pbnRlcm5hbChiZGV2LCAmbGt1bCk7Cit9CitFWFBP UlRfU1lNQk9MKG9wYWxfYWRkX3VzZXJfdG9fbHIpOworCitpbnQgb3BhbF9yZXZlcnR0cGVyKHN0 cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisJc3RydWN0 IG9wYWxfa2V5IGs7CisKKwlpZiAoY29weV9mcm9tX3VzZXIoJmssIGtleS0+b3BhbCwgc2l6ZW9m KCprZXktPm9wYWwpKSkKKwkJcmV0dXJuIC1FRkFVTFQ7CisKKwlyZXR1cm4gb3BhbF9yZXZlcnQo YmRldiwgJmspOworfQorRVhQT1JUX1NZTUJPTChvcGFsX3JldmVydHRwZXIpOworCitpbnQgb3Bh bF9sb2NrX3VubG9jayhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAq a2V5KQoreworCXN0cnVjdCBvcGFsX2xvY2tfdW5sb2NrIGs7CisKKwlpZiAoY29weV9mcm9tX3Vz ZXIoJmssIGtleS0+b3BhbF9sa191bmxrLCBzaXplb2YoKmtleS0+b3BhbF9sa191bmxrKSkpCisJ CXJldHVybiAtRUZBVUxUOworCisJaWYgKGsuYXV0aG9yaXR5LndobyA8IE9QQUxfQURNSU4xIHx8 IGsuYXV0aG9yaXR5LndobyA+IE9QQUxfVVNFUjkpCisJCXJldHVybiAtRUlOVkFMOworCisJcmV0 dXJuIGxvY2tfdW5sb2NrX2ludGVybmFsKGJkZXYsICZrKTsKK30KK0VYUE9SVF9TWU1CT0wob3Bh bF9sb2NrX3VubG9jayk7CisKK2ludCBvcGFsX3Rha2Vfb3duZXJzaGlwKHN0cnVjdCBibG9ja19k ZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisJc3RydWN0IG9wYWxfa2V5IGs7 CisJY29uc3Qgb3BhbF9zdGVwIG93bmVyX2Z1bmNzW10gPSB7CisJCW9wYWxfZGlzY292ZXJ5MCwK KwkJc3RhcnRfYW55Ym9keUFTUF9vcGFsX3Nlc3Npb24sCisJCWdldF9tc2lkX2NwaW5fcGluLAor CQllbmRfb3BhbF9zZXNzaW9uLAorCQlzdGFydF9TSURBU1Bfb3BhbF9zZXNzaW9uLAorCQlzZXRf c2lkX2NwaW5fcGluLAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlOVUxMCisJfTsKKworCWlmICgh YmRldiB8fCAhYmRldi0+YmRfZGlzaykgeworCQlwcl9lcnIoIkNhbid0IHNhdmUgcGFzc3dvcmQg Zm9yIE5VTEwgYmxvY2sgZGV2aWNlLlxuIik7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWlm IChjb3B5X2Zyb21fdXNlcigmaywga2V5LT5vcGFsLCBzaXplb2YoKmtleS0+b3BhbCkpKQorCQly ZXR1cm4gLUVGQVVMVDsKKworCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYsICZrLCBvd25lcl9m dW5jcyk7Cit9CitFWFBPUlRfU1lNQk9MKG9wYWxfdGFrZV9vd25lcnNoaXApOworCitpbnQgb3Bh bF9hY3RpdmF0ZV9sc3Aoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkg KmtleSkKK3sKKwlzdHJ1Y3Qgb3BhbF9rZXkgazsKKwljb25zdCBvcGFsX3N0ZXAgYWN0aXZlX2Z1 bmNzW10gPSB7CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfU0lEQVNQX29wYWxfc2Vzc2lv biwgLyogT3BlbiBzZXNzaW9uIGFzIFNJRCBhdXRoICovCisJCWdldF9sc3BfbGlmZWN5Y2xlLAor CQlhY3RpdmF0ZV9sc3AsCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEwKKwl9OworCisJaWYg KCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7CisJCXByX2VycigiQ2FuJ3Qgc2F2ZSBwYXNzd29y ZCBmb3IgTlVMTCBibG9jayBkZXZpY2UuXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJ aWYgKGNvcHlfZnJvbV91c2VyKCZrLCBrZXktPm9wYWwsIHNpemVvZigqa2V5LT5vcGFsKSkpCisJ CXJldHVybiAtRUZBVUxUOworCisJcmV0dXJuIG9wYWxfYWN0X2xzcF9pbnQoYmRldiwgJmssIGFj dGl2ZV9mdW5jcyk7Cit9CitFWFBPUlRfU1lNQk9MKG9wYWxfYWN0aXZhdGVfbHNwKTsKKworaW50 IG9wYWxfc2V0dXBfbG9ja2luZ19yYW5nZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1 Y3Qgc2VkX2tleSAqcHcpCit7CisJc3RydWN0IG9wYWxfdXNlcl9scl9zZXR1cCBrOworCisJaWYg KCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7CisJCXByX2VycigiQ2FuJ3Qgc2F2ZSBwYXNzd29y ZCBmb3IgTlVMTCBibG9jayBkZXZpY2UuXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJ aWYgKGNvcHlfZnJvbV91c2VyKCZrLCBwdy0+b3BhbF9scnMsIHNpemVvZigqcHctPm9wYWxfbHJz KSkpCisJCXJldHVybiAtRUZBVUxUOworCisJcmV0dXJuIGludGVybmFsX3NldHVwX2xyKGJkZXYs ICZrKTsKK30KKworaW50IG9wYWxfc2V0X25ld19wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2 LCBzdHJ1Y3Qgc2VkX2tleSAqcHcpCit7CisJc3RydWN0IG9wYWxfbmV3X3B3IGs7CisKKwlpZiAo cHctPnNlZF90eXBlICE9IE9QQUxfUFcpCisJCXJldHVybiAtRUlOVkFMOworCisJaWYgKGNvcHlf ZnJvbV91c2VyKCZrLCBwdy0+b3BhbF9wdywgc2l6ZW9mKCpwdy0+b3BhbF9wdykpKQorCQlyZXR1 cm4gLUVGQVVMVDsKKworCWlmIChrLndoby53aG8gPCBPUEFMX0FETUlOMSB8fCBrLndoby53aG8g PiBPUEFMX1VTRVI5KQorCQlyZXR1cm4gLUVJTlZBTDsKKworCXJldHVybiBvcGFsX3NldF9wdyhi ZGV2LCAmayk7Cit9CitFWFBPUlRfU1lNQk9MKG9wYWxfc2V0X25ld19wdyk7CisKK2ludCBvcGFs X2FjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkg KnB3KQoreworCXN0cnVjdCBvcGFsX2FjdGl2YXRlX3VzZXIgazsKKworCWlmIChwdy0+c2VkX3R5 cGUgIT0gT1BBTF9BQ1RfVVNSKSB7CisJCXByX2VycigiU2VkIHR5cGUgd2FzIG5vdCBhY3QgdXNl clxuIik7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWlmIChjb3B5X2Zyb21fdXNlcigmaywg cHctPm9wYWxfYWN0LCBzaXplb2YoKnB3LT5vcGFsX2FjdCkpKSB7CisJCXByX2VycigiY29weSBm cm9tIHVzZXIgZXJyb3JcbiIpOworCQlyZXR1cm4gLUVGQVVMVDsKKwl9CisKKwkvKiBXZSBjYW4n dCBhY3RpdmF0ZSBBZG1pbjEgaXQncyBhY3RpdmUgYXMgbWFudWZhY3R1cmVkICovCisJaWYgKGsu d2hvLndobyA8IE9QQUxfVVNFUjEgJiYgay53aG8ud2hvID4gT1BBTF9VU0VSOSkgeworCQlwcl9l cnIoIldobyB3YXMgbm90IGEgdmFsaWQgdXNlcjogJWQgXG4iLCBrLndoby53aG8pOworCQlyZXR1 cm4gLUVJTlZBTDsKKwl9CisKKwlyZXR1cm4gYWN0aXZhdGVfdXNlcihiZGV2LCAmayk7CisKK30K K0VYUE9SVF9TWU1CT0wob3BhbF9hY3RpdmF0ZV91c2VyKTsKKworaW50IG9wYWxfdW5sb2NrX2Zy b21fc3VzcGVuZChzdHJ1Y3Qgb3BhbF9zdXNwZW5kX3VubGsgKmRhdGEpCit7CisJY29uc3QgY2hh ciAqZGlza25hbWUgPSBkYXRhLT5uYW1lOworCXN0cnVjdCBvcGFsX2RldiAqaXRlciwgKmRldiA9 IE5VTEw7CisJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKKwl2b2lkICpmdW5j X2RhdGFbM10gPSB7IE5VTEwgfTsKKworCXNwaW5fbG9jaygmbGlzdF9zcGlubG9jayk7CisJbGlz dF9mb3JfZWFjaF9lbnRyeShpdGVyLCAmb3BhbF9saXN0LCBub2RlKSB7CisJCWlmIChzdHJuY21w KGl0ZXItPmRpc2tfbmFtZSwgZGlza25hbWUsIERJU0tfTkFNRV9MRU4pKSB7CisJCQlwcl9lcnIo Iml0ZXJkaXNrIHdhcyAlcyBhbmQgZGlza25hbWUgaXMgJXNcbiIsCisJCQkgICAgICAgaXRlci0+ ZGlza19uYW1lLCBkaXNrbmFtZSk7CisJCQljb250aW51ZTsKKwkJfQorCQlpZiAoYXRvbWljX2Fk ZF91bmxlc3MoJml0ZXItPmluX3VzZSwgMSwgMSkpIHsKKwkJCWRldiA9IGl0ZXI7CisJCQlkZXYt PmZ1bmNfZGF0YSA9IGZ1bmNfZGF0YTsKKwkJCWRldi0+cmVzdW1lX2Zyb21fc3VzcGVuZCA9IHRy dWU7CisJCQlkZXYtPnJlc3VtZV9kYXRhID0gZGF0YTsKKwkJCWRldi0+ZmluYWxfY2IgPSB1bmxv Y2tfc3VzcGVuZF9maW5hbDsKKwkJCWRldi0+ZmluYWxfY2JfZGF0YSA9IGRldjsKKwkJCWRldi0+ ZXJyb3JfY2IgPSBlbmRfb3BhbF9zZXNzaW9uX2Vycm9yOworCQkJZGV2LT5lcnJvcl9jYl9kYXRh ID0gZGV2OworCQkJZGV2LT5zdGF0ZSA9IDA7CisJCQlpZiAoZGV2LT5sa3VsLmF1dGhvcml0eS5T VU0pCisJCQkJZGV2LT5mdW5jcyA9IHVsa19mdW5jc19TVU07CisJCQllbHNlCisJCQkJZGV2LT5m dW5jcyA9IF91bmxvY2tfZnVuY3M7CisJCQlkZXYtPlRTTiA9IDA7CisJCQlkZXYtPkhTTiA9IDA7 CisJCQlkZXYtPmZ1bmNfZGF0YVsyXSA9ICZkZXYtPmxrdWw7CisJCQlkZXYtPmZ1bmNfZGF0YVsx XSA9ICZkZXYtPmxrdWwuYXV0aG9yaXR5OworCQkJY29tcGxldGlvbiA9IGRldi0+Y29tcGxldGlv bjsKKwkJCW5leHQoMCwgZGV2KTsKKwkJCXdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRp b24pOworCQl9CisJfQorCXNwaW5fdW5sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKworCWlmICghZGV2 KQorCQlyZXR1cm4gLUVOT0RFVjsKKwlyZXR1cm4gMDsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF91 bmxvY2tfZnJvbV9zdXNwZW5kKTsKZGlmZiAtLWdpdCBhL2xpYi9zZWQtb3BhbF9pbnRlcm5hbC5o IGIvbGliL3NlZC1vcGFsX2ludGVybmFsLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAw MDAwMC4uNTQwNDFjYgotLS0gL2Rldi9udWxsCisrKyBiL2xpYi9zZWQtb3BhbF9pbnRlcm5hbC5o CkBAIC0wLDAgKzEsNTg3IEBACisvKgorICogQ29weXJpZ2h0IMKpIDIwMTYgSW50ZWwgQ29ycG9y YXRpb24KKyAqCisgKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJn ZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYQorICogY29weSBvZiB0aGlzIHNvZnR3YXJlIGFu ZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSAiU29mdHdhcmUiKSwKKyAqIHRv IGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRo b3V0IGxpbWl0YXRpb24KKyAqIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdl LCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLAorICogYW5kL29yIHNlbGwgY29waWVz IG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlCisgKiBT b2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBj b25kaXRpb25zOgorICoKKyAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBl cm1pc3Npb24gbm90aWNlIChpbmNsdWRpbmcgdGhlIG5leHQKKyAqIHBhcmFncmFwaCkgc2hhbGwg YmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUK KyAqIFNvZnR3YXJlLgorICoKKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBX SVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCisgKiBJTVBMSUVELCBJTkNM VURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElU WSwKKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1F TlQuICBJTiBOTyBFVkVOVCBTSEFMTAorICogVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERF UlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElU WSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBB UklTSU5HCisgKiBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FS RSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTCisgKiBJTiBUSEUgU09GVFdBUkUuCisgKgor ICogQXV0aG9yOgorICogICAgUmFmYWVsIEFudG9nbm9sbGkgPHJhZmFlbC5hbnRvZ25vbGxpQGlu dGVsLmNvbT4KKyAqICAgIFNjb3R0ICBCYXVlciAgICAgIDxzY290dC5iYXVlckBpbnRlbC5jb20+ CisgKi8KKworI2lmbmRlZiBfTlZNRV9PUEFMX0lOVEVSTkFMX0gKKyNkZWZpbmUgX05WTUVfT1BB TF9JTlRFUk5BTF9ICisKKyNpbmNsdWRlIDxsaW51eC9rZXktdHlwZS5oPgorI2luY2x1ZGUgPGtl eXMvdXNlci10eXBlLmg+CisKKyNkZWZpbmUgRFRBRVJST1JfTk9fTUVUSE9EX1NUQVRVUyAweDg5 CisjZGVmaW5lIEdFTkVSSUNfSE9TVF9TRVNTSU9OX05VTSAweDQxCisKK3N0YXRpYyBjb25zdCBj aGFyICpvcGFsX2Vycm9yc1tdID0geworCSJTdWNjZXNzIiwKKwkiTm90IEF1dGhvcml6ZWQiLAor CSJVbmtub3duIEVycm9yIiwKKwkiU1AgQnVzeSIsCisJIlNQIEZhaWxlZCIsCisJIlNQIERpc2Fi bGVkIiwKKwkiU1AgRnJvemVuIiwKKwkiTm8gU2Vzc2lvbnMgQXZhaWxhYmxlIiwKKwkiVW5pcXVl bmVzcyBDb25mbGljdCIsCisJIkluc3VmZmljaWVudCBTcGFjZSIsCisJIkluc3VmZmljaWVudCBS b3dzIiwKKwkiSW52YWxpZCBGdW5jdGlvbiIsCisJIkludmFsaWQgUGFyYW1ldGVyIiwKKwkiSW52 YWxpZCBSZWZlcmVuY2UiLAorCSJVbmtub3duIEVycm9yIiwKKwkiVFBFUiBNYWxmdW5jdGlvbiIs CisJIlRyYW5zYWN0aW9uIEZhaWx1cmUiLAorCSJSZXNwb25zZSBPdmVyZmxvdyIsCisJIkF1dGhv cml0eSBMb2NrZWQgT3V0IiwKK307CisKK3N0YXRpYyBjb25zdCBjaGFyICpvcGFsX2Vycm9yX3Rv X2h1bWFuKGludCBlcnJvcikKK3sKKwlpZiAoZXJyb3IgPT0gMHgzZikKKwkJcmV0dXJuICJGYWls ZWQiOworCisJaWYgKGVycm9yID49IEFSUkFZX1NJWkUob3BhbF9lcnJvcnMpIHx8IGVycm9yIDwg MCkKKwkJcmV0dXJuICJVbmtub3duIEVycm9yIjsKKworCXJldHVybiBvcGFsX2Vycm9yc1tlcnJv cl07Cit9CisKKy8qIFVzZXIgSURzIHVzZWQgaW4gdGhlIFRDRyBzdG9yYWdlIFNTQ3MgKi8KK3N0 YXRpYyBjb25zdCB1OCBPUEFMVUlEW11bOF0gPSB7CisJLyogdXNlcnMgKi8KKworCS8qIHNlc3Np b24gbWFuYWdlbWVudCAgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAs IDB4MDAsIDB4ZmZ9LAorCS8qIHNwZWNpYWwgInRoaXNTUCIgc3ludGF4ICovCisJeyAweDAwLCAw eDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAxIH0sCisJLyogQWRtaW5pc3Ry YXRpdmUgU1AgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDIsIDB4MDUsIDB4MDAsIDB4MDAsIDB4MDAs IDB4MDEgfSwKKwkvKiBMb2NraW5nIFNQICovCisJeyAweDAwLCAweDAwLCAweDAyLCAweDA1LCAw eDAwLCAweDAwLCAweDAwLCAweDAyIH0sCisJLyogRU5URVJQUklTRSBMb2NraW5nIFNQICAqLwor CXsgMHgwMCwgMHgwMCwgMHgwMiwgMHgwNSwgMHgwMCwgMHgwMSwgMHgwMCwgMHgwMSB9LAorCS8q IGFueWJvZHkgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDAsIDB4MDAs IDB4MDEgfSwKKwkvKiBTSUQgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4 MDAsIDB4MDAsIDB4MDYgfSwKKwkvKiBBRE1JTjEgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4 MDksIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDEgfSwKKwkvKiBVU0VSMSAqLworCXsgMHgwMCwgMHgw MCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMywgMHgwMCwgMHgwMSB9LAorCS8qIFVTRVIyICovCisJ eyAweDAwLCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAzLCAweDAwLCAweDAyIH0sCisJLyog UFNJRCB1c2VyICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAxLCAweGZm LCAweDAxIH0sCisJLyogQmFuZE1hc3RlciAwICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA5 LCAweDAwLCAweDAwLCAweDgwLCAweDAxIH0sCisJIC8qIEVyYXNlTWFzdGVyICovCisJeyAweDAw LCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAwLCAweDg0LCAweDAxIH0sCisKKwkvKiB0YWJs ZXMgKi8KKworCS8qIExvY2tpbmdfR2xvYmFsUmFuZ2UgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDgs IDB4MDIsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEgfSwKKwkvKiBBQ0VfTG9ja2luZ19SYW5nZV9T ZXRfUmRMb2NrZWQgVUlEICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA4LCAweDAwLCAweDAz LCAweEUwLCAweDAxIH0sCisJLyogQUNFX0xvY2tpbmdfUmFuZ2VfU2V0X1dyTG9ja2VkIFVJRCAq LworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOCwgMHgwMCwgMHgwMywgMHhFOCwgMHgwMSB9LAor CS8qIE1CUiBDb250cm9sICovCisJeyAweDAwLCAweDAwLCAweDA4LCAweDAzLCAweDAwLCAweDAw LCAweDAwLCAweDAxIH0sCisJLyogU2hhZG93IE1CUiAqLworCXsgMHgwMCwgMHgwMCwgMHgwOCwg MHgwNCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCB9LAorCS8qIEFVVEhPUklUWV9UQUJMRSAqLwor CXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMH0sCisJLyog Q19QSU5fVEFCTEUgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MEIsIDB4MDAsIDB4MDAsIDB4 MDAsIDB4MDB9LAorCS8qIE9QQUwgTG9ja2luZyBJbmZvICovCisJeyAweDAwLCAweDAwLCAweDA4 LCAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAxIH0sCisJLyogRW50ZXJwcmlzZSBMb2NraW5n IEluZm8gKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDgsIDB4MDEsIDB4MDAsIDB4MDAsIDB4MDAsIDB4 MDAgfSwKKworCS8qIENfUElOX1RBQkxFIG9iamVjdCBJRCdzICovCisKKwkvKiBDX1BJTl9NU0lE ICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDBCLCAweDAwLCAweDAwLCAweDg0LCAweDAyfSwK KwkvKiBDX1BJTl9TSUQgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MEIsIDB4MDAsIDB4MDAs IDB4MDAsIDB4MDF9LAorCSAvKiBDX1BJTl9BRE1JTjEgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAs IDB4MEIsIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDF9LAorCisJLyogaGFsZiBVSUQncyAob25seSBm aXJzdCA0IGJ5dGVzIHVzZWQpICovCisKKwkvKiBIYWxmLVVJRCDigJMgQXV0aG9yaXR5X29iamVj dF9yZWYgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MEMsIDB4MDUsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4 ZmYgfSwKKwkvKiBIYWxmLVVJRCDigJMgQm9vbGVhbiBBQ0UgKi8KKwl7IDB4MDAsIDB4MDAsIDB4 MDQsIDB4MEUsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYgfSwKKworCS8qIHNwZWNpYWwgdmFsdWUg Zm9yIG9taXR0ZWQgb3B0aW9uYWwgcGFyYW1ldGVyICovCisKKwkvKiBIRVhGRiBmb3Igb21pdHRl ZCAqLworCXsgMHhmZiwgMHhmZiwgMHhmZiwgMHhmZiwgMHhmZiwgMHhmZiwgMHhmZiwgMHhmZn0s Cit9Oworc3RhdGljIGNvbnN0IHNpemVfdCBPUEFMX1VJRF9MRU5HVEggPSA4Oworc3RhdGljIGNv bnN0IHNpemVfdCBPUEFMX01TSURfS0VZTEVOID0gMTU7CitzdGF0aWMgY29uc3Qgc2l6ZV90IE9Q QUxfVUlEX0xFTkdUSF9IQUxGID0gNDsKKworCisvKiBFbnVtIHRvIGluZGV4IE9QQUxVSUQgYXJy YXkgKi8KK2VudW0gT1BBTF9VSUQgeworCS8qIHVzZXJzICovCisJT1BBTF9TTVVJRF9VSUQsCisJ T1BBTF9USElTU1BfVUlELAorCU9QQUxfQURNSU5TUF9VSUQsCisJT1BBTF9MT0NLSU5HU1BfVUlE LAorCU9QQUxfRU5URVJQUklTRV9MT0NLSU5HU1BfVUlELAorCU9QQUxfQU5ZQk9EWV9VSUQsCisJ T1BBTF9TSURfVUlELAorCU9QQUxfQURNSU4xX1VJRCwKKwlPUEFMX1VTRVIxX1VJRCwKKwlPUEFM X1VTRVIyX1VJRCwKKwlPUEFMX1BTSURfVUlELAorCU9QQUxfRU5URVJQUklTRV9CQU5ETUFTVEVS MF9VSUQsCisJT1BBTF9FTlRFUlBSSVNFX0VSQVNFTUFTVEVSX1VJRCwKKwkvKiB0YWJsZXMgKi8K KwlPUEFMX0xPQ0tJTkdSQU5HRV9HTE9CQUwsCisJT1BBTF9MT0NLSU5HUkFOR0VfQUNFX1JETE9D S0VELAorCU9QQUxfTE9DS0lOR1JBTkdFX0FDRV9XUkxPQ0tFRCwKKwlPUEFMX01CUkNPTlRST0ws CisJT1BBTF9NQlIsCisJT1BBTF9BVVRIT1JJVFlfVEFCTEUsCisJT1BBTF9DX1BJTl9UQUJMRSwK KwlPUEFMX0xPQ0tJTkdfSU5GT19UQUJMRSwKKwlPUEFMX0VOVEVSUFJJU0VfTE9DS0lOR19JTkZP X1RBQkxFLAorCS8qIENfUElOX1RBQkxFIG9iamVjdCBJRCdzICovCisJT1BBTF9DX1BJTl9NU0lE LAorCU9QQUxfQ19QSU5fU0lELAorCU9QQUxfQ19QSU5fQURNSU4xLAorCS8qIGhhbGYgVUlEJ3Mg KG9ubHkgZmlyc3QgNCBieXRlcyB1c2VkKSAqLworCU9QQUxfSEFMRl9VSURfQVVUSE9SSVRZX09C Sl9SRUYsCisJT1BBTF9IQUxGX1VJRF9CT09MRUFOX0FDRSwKKwkvKiBvbWl0dGVkIG9wdGlvbmFs IHBhcmFtZXRlciAqLworCU9QQUxfVUlEX0hFWEZGLAorfTsKKworLyoKKyAqIFRDRyBTdG9yYWdl IFNTQyBNZXRob2RzLgorICovCitzdGF0aWMgY29uc3QgdTggT1BBTE1FVEhPRFtdWzhdID0gewor CS8qIFByb3BlcnRpZXMgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAs IDB4ZmYsIDB4MDEgfSwKKwkvKiBTVEFSVFNFU1NJT04gKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAs IDB4MDAsIDB4MDAsIDB4MDAsIDB4ZmYsIDB4MDIgfSwKKwkvKiBSZXZlcnQgKi8KKwl7IDB4MDAs IDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDIsIDB4MDIgfSwKKwkvKiBBY3RpdmF0 ZSAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMiwgMHgwMyB9 LAorCS8qIEVudGVycHJpc2UgR2V0ICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAw LCAweDAwLCAweDAwLCAweDA2IH0sCisJLyogRW50ZXJwcmlzZSBTZXQgKi8KKwl7IDB4MDAsIDB4 MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDcgfSwKKwkvKiBORVhUICovCisJ eyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDA4IH0sCisJLyog RW50ZXJwcmlzZSBBdXRoZW50aWNhdGUgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4 MDAsIDB4MDAsIDB4MDAsIDB4MGMgfSwKKwkvKiBHZXRBQ0wgKi8KKwl7IDB4MDAsIDB4MDAsIDB4 MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MGQgfSwKKwkvKiBHZW5LZXkgKi8KKwl7IDB4 MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MTAgfSwKKwkvKiByZXZl cnRTUCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgx MSB9LAorCS8qIEdldCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwg MHgwMCwgMHgxNiB9LAorCS8qIFNldCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgw MCwgMHgwMCwgMHgwMCwgMHgxNyB9LAorCS8qIEF1dGhlbnRpY2F0ZSAqLworCXsgMHgwMCwgMHgw MCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgxYyB9LAorCS8qIFJhbmRvbSAqLwor CXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMSB9LAorCS8q IEVyYXNlICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDA4LCAw eDAzIH0sCit9Oworc3RhdGljIGNvbnN0IHNpemVfdCBPUEFMX01FVEhPRF9MRU5HVEggPSA4Owor CisvKiBFbnVtIGZvciBpbmRleGluZyB0aGUgT1BBTE1FVEhPRCBhcnJheSAqLworZW51bSBPUEFM X01FVEhPRCB7CisJT1BBTF9QUk9QRVJUSUVTLAorCU9QQUxfU1RBUlRTRVNTSU9OLAorCU9QQUxf UkVWRVJULAorCU9QQUxfQUNUSVZBVEUsCisJT1BBTF9FR0VULAorCU9QQUxfRVNFVCwKKwlPUEFM X05FWFQsCisJT1BBTF9FQVVUSEVOVElDQVRFLAorCU9QQUxfR0VUQUNMLAorCU9QQUxfR0VOS0VZ LAorCU9QQUxfUkVWRVJUU1AsCisJT1BBTF9HRVQsCisJT1BBTF9TRVQsCisJT1BBTF9BVVRIRU5U SUNBVEUsCisJT1BBTF9SQU5ET00sCisJT1BBTF9FUkFTRSwKK307CisKK2VudW0gT1BBTF9SRVNQ T05TRV9UT0tFTiB7CisJT1BBTF9EVEFfVE9LRU5JRF9CWVRFU1RSSU5HID0gMHhlMCwKKwlPUEFM X0RUQV9UT0tFTklEX1NJTlQgPSAweGUxLAorCU9QQUxfRFRBX1RPS0VOSURfVUlOVCA9IDB4ZTIs CisJT1BBTF9EVEFfVE9LRU5JRF9UT0tFTiA9IDB4ZTMsIC8qIGFjdHVhbCB0b2tlbiBpcyByZXR1 cm5lZCAqLworCU9QQUxfRFRBX1RPS0VOSURfSU5WQUxJRCA9IDBYMAorfTsKKworZW51bSBPUEFM X1RPS0VOIHsKKwkvKiBCb29sZWFuICovCisJT1BBTF9UUlVFID0gMHgwMSwKKwlPUEFMX0ZBTFNF ID0gMHgwMCwKKwlPUEFMX0JPT0xFQU5fRVhQUiA9IDB4MDMsCisJLyogY2VsbGJsb2NrcyAqLwor CU9QQUxfVEFCTEUgPSAweDAwLAorCU9QQUxfU1RBUlRST1cgPSAweDAxLAorCU9QQUxfRU5EUk9X ID0gMHgwMiwKKwlPUEFMX1NUQVJUQ09MVU1OID0gMHgwMywKKwlPUEFMX0VORENPTFVNTiA9IDB4 MDQsCisJT1BBTF9WQUxVRVMgPSAweDAxLAorCS8qIGF1dGhvcml0eSB0YWJsZSAqLworCU9QQUxf UElOID0gMHgwMywKKwkvKiBsb2NraW5nIHRva2VucyAqLworCU9QQUxfUkFOR0VTVEFSVCA9IDB4 MDMsCisJT1BBTF9SQU5HRUxFTkdUSCA9IDB4MDQsCisJT1BBTF9SRUFETE9DS0VOQUJMRUQgPSAw eDA1LAorCU9QQUxfV1JJVEVMT0NLRU5BQkxFRCA9IDB4MDYsCisJT1BBTF9SRUFETE9DS0VEID0g MHgwNywKKwlPUEFMX1dSSVRFTE9DS0VEID0gMHgwOCwKKwlPUEFMX0FDVElWRUtFWSA9IDB4MEEs CisJLyogbG9ja2luZyBpbmZvIHRhYmxlICovCisJT1BBTF9NQVhSQU5HRVMgPSAweDA0LAorCSAv KiBtYnIgY29udHJvbCAqLworCU9QQUxfTUJSRU5BQkxFID0gMHgwMSwKKwlPUEFMX01CUkRPTkUg PSAweDAyLAorCS8qIHByb3BlcnRpZXMgKi8KKwlPUEFMX0hPU1RQUk9QRVJUSUVTID0gMHgwMCwK KwkvKiBhdG9tcyAqLworCU9QQUxfU1RBUlRMSVNUID0gMHhmMCwKKwlPUEFMX0VORExJU1QgPSAw eGYxLAorCU9QQUxfU1RBUlROQU1FID0gMHhmMiwKKwlPUEFMX0VORE5BTUUgPSAweGYzLAorCU9Q QUxfQ0FMTCA9IDB4ZjgsCisJT1BBTF9FTkRPRkRBVEEgPSAweGY5LAorCU9QQUxfRU5ET0ZTRVNT SU9OID0gMHhmYSwKKwlPUEFMX1NUQVJUVFJBTlNBQ1RPTiA9IDB4ZmIsCisJT1BBTF9FTkRUUkFO U0FDVE9OID0gMHhmQywKKwlPUEFMX0VNUFRZQVRPTSA9IDB4ZmYsCisJT1BBTF9XSEVSRSA9IDB4 MDAsCit9OworCisvKiBVc2VmdWwgdGlueSBhdG9tcy4KKyAqIFVzZWZ1bCBmb3IgdGFibGUgY29s dW1ucyBldGMKKyAqLworZW51bSBPUEFMX1RJTllfQVRPTSB7CisJT1BBTF9USU5ZX1VJTlRfMDAg PSAweDAwLAorCU9QQUxfVElOWV9VSU5UXzAxID0gMHgwMSwKKwlPUEFMX1RJTllfVUlOVF8wMiA9 IDB4MDIsCisJT1BBTF9USU5ZX1VJTlRfMDMgPSAweDAzLAorCU9QQUxfVElOWV9VSU5UXzA0ID0g MHgwNCwKKwlPUEFMX1RJTllfVUlOVF8wNSA9IDB4MDUsCisJT1BBTF9USU5ZX1VJTlRfMDYgPSAw eDA2LAorCU9QQUxfVElOWV9VSU5UXzA3ID0gMHgwNywKKwlPUEFMX1RJTllfVUlOVF8wOCA9IDB4 MDgsCisJT1BBTF9USU5ZX1VJTlRfMDkgPSAweDA5LAorCU9QQUxfVElOWV9VSU5UXzEwID0gMHgw YSwKKwlPUEFMX1RJTllfVUlOVF8xMSA9IDB4MGIsCisJT1BBTF9USU5ZX1VJTlRfMTIgPSAweDBj LAorCU9QQUxfVElOWV9VSU5UXzEzID0gMHgwZCwKKwlPUEFMX1RJTllfVUlOVF8xNCA9IDB4MGUs CisJT1BBTF9USU5ZX1VJTlRfMTUgPSAweDBmLAorfTsKKworZW51bSBPUEFMX0FUT01fV0lEVEgg eworCU9QQUxfV0lEVEhfVElOWSwKKwlPUEFMX1dJRFRIX1NIT1JULAorCU9QQUxfV0lEVEhfTUVE SVVNLAorCU9QQUxfV0lEVEhfTE9ORywKKwlPUEFMX1dJRFRIX1RPS0VOCit9OworCisvKiBMb2Nr aW5nIHN0YXRlIGZvciBhIGxvY2tpbmcgcmFuZ2UgKi8KK2VudW0gT1BBTF9MT0NLSU5HU1RBVEUg eworCU9QQUxfTE9DS0lOR19SRUFEV1JJVEUgPSAweDAxLAorCU9QQUxfTE9DS0lOR19SRUFET05M WSA9IDB4MDIsCisJT1BBTF9MT0NLSU5HX0xPQ0tFRCA9IDB4MDMsCit9OworCisvKgorICogU3Ry dWN0dXJlcyB0byBidWlsZCBhbmQgZGVjb2RlIHRoZSBPcGFsIFNTQyBtZXNzYWdlcworICogZmll bGRzIHRoYXQgYXJlIE5PVCByZWFsbHkgbnVtZXJpYyBhcmUgZGVmaW5lZCBhcyB1OFtdIHRvCisg KiBoZWxwIHJlZHVjZSB0aGUgZW5kaWFubmVzcyBpc3N1ZXMKKyAqLworCisvKiBDb21tIFBhY2tl dCAoaGVhZGVyKSBmb3IgdHJhbnNtaXNzaW9ucy4gKi8KK3N0cnVjdCBvcGFsX2NvbXBhY2tldCB7 CisJdTMyIHJlc2VydmVkMDsKKwl1OCBleHRlbmRlZENvbUlEWzRdOworCXUzMiBvdXRzdGFuZGlu Z0RhdGE7CisJdTMyIG1pblRyYW5zZmVyOworCXUzMiBsZW5ndGg7Cit9OworCisvKiBQYWNrZXQg c3RydWN0dXJlLiAqLworc3RydWN0IG9wYWxfcGFja2V0IHsKKwl1MzIgVFNOOworCXUzMiBIU047 CisJdTMyIHNlcV9udW1iZXI7CisJdTE2IHJlc2VydmVkMDsKKwl1MTYgYWNrX3R5cGU7CisJdTMy IGFja25vd2xlZGdtZW50OworCXUzMiBsZW5ndGg7Cit9OworCisvKiBEYXRhIHN1YiBwYWNrZXQg aGVhZGVyICovCitzdHJ1Y3Qgb3BhbF9kYXRhX3N1YnBhY2tldCB7CisJdTggcmVzZXJ2ZWQwWzZd OworCXUxNiBraW5kOworCXUzMiBsZW5ndGg7Cit9OworCisvKiBoZWFkZXIgb2YgYSByZXNwb25z ZSAqLworc3RydWN0IG9wYWxfaGVhZGVyIHsKKwlzdHJ1Y3Qgb3BhbF9jb21wYWNrZXQgY3A7CisJ c3RydWN0IG9wYWxfcGFja2V0IHBrdDsKKwlzdHJ1Y3Qgb3BhbF9kYXRhX3N1YnBhY2tldCBzdWJw a3Q7Cit9OworCisjZGVmaW5lIEZDX1RQRVIgICAgICAgMHgwMDAxCisjZGVmaW5lIEZDX0xPQ0tJ TkcgICAgMHgwMDAyCisjZGVmaW5lIEZDX0dFT01FVFJZICAgMHgwMDAzCisjZGVmaW5lIEZDX0VO VEVSUFJJU0UgMHgwMTAwCisjZGVmaW5lIEZDX0RBVEFTVE9SRSAgMHgwMjAyCisjZGVmaW5lIEZD X1NJTkdMRVVTRVIgMHgwMjAxCisjZGVmaW5lIEZDX09QQUxWMTAwICAgMHgwMjAwCisjZGVmaW5l IEZDX09QQUxWMjAwICAgMHgwMjAzCisKKy8qCisgKiBUaGUgRGlzY292ZXJ5IDAgSGVhZGVyLiBB cyBkZWZpbmVkIGluCisgKiBPcGFsIFNTQyBEb2N1bWVudGF0aW9uCisgKi8KK3N0cnVjdCBkMF9o ZWFkZXIgeworCXUzMiBsZW5ndGg7IC8qIHRoZSBsZW5ndGggb2YgdGhlIGhlYWRlciA0OCBpbiAy LjAwLjEwMCAqLworCXUzMiByZXZpc2lvbjsgLyoqPCByZXZpc2lvbiBvZiB0aGUgaGVhZGVyIDEg aW4gMi4wMC4xMDAgKi8KKwl1MzIgcmVzZXJ2ZWQwMTsKKwl1MzIgcmVzZXJ2ZWQwMjsKKwkvKgor CSAqIHRoZSByZW1haW5kZXIgb2YgdGhlIHN0cnVjdHVyZSBpcyB2ZW5kb3Igc3BlY2lmaWMgYW5k IHdpbGwgbm90IGJlCisJICogYWRkcmVzc2VkIG5vdworCSAqLworCXU4IGlnbm9yZWRbMzJdOwor fTsKKworLyoKKyAqIFRQZXIgRmVhdHVyZSBEZXNjcmlwdG9yLiBDb250YWlucyBmbGFncyBpbmRp Y2F0aW5nIHN1cHBvcnQgZm9yIHRoZQorICogVFBlciBmZWF0dXJlcyBkZXNjcmliZWQgaW4gdGhl IE9QQUwgc3BlY2lmaWNhdGlvbi4gVGhlIG5hbWVzIG1hdGNoIHRoZQorICogT1BBTCB0ZXJtaW5v bG9neQorICoKKyAqIGNvZGUgPT0gMHgwMDEgaW4gMi4wMC4xMDAKKyAqLworc3RydWN0IGQwX3Rw ZXJfZmVhdHVyZXMgeworCS8qCisJICogc3VwcG9ydGVkX2ZlYXR1cmVzIGJpdHM6CisJICogYml0 IDc6IHJlc2VydmVkCisJICogYml0IDY6IGNvbSBJRCBtYW5hZ2VtZW50CisJICogYml0IDU6IHJl c2VydmVkCisJICogYml0IDQ6IHN0cmVhbWluZyBzdXBwb3J0CisJICogYml0IDM6IGJ1ZmZlciBt YW5hZ2VtZW50CisJICogYml0IDI6IEFDSy9OQUNLCisJICogYml0IDE6IGFzeW5jCisJICogYml0 IDA6IHN5bmMKKwkgKi8KKwl1OCBzdXBwb3J0ZWRfZmVhdHVyZXM7CisJLyoKKwkgKiBieXRlcyA1 IHRocm91Z2ggMTUgYXJlIHJlc2VydmVkLCBidXQgd2UgcmVwcmVzZW50IHRoZSBmaXJzdCAzIGFz CisJICogdTggdG8ga2VlcCB0aGUgb3RoZXIgdHdvIDMyYml0cyBpbnRlZ2VycyBhbGlnbmVkLgor CSAqLworCXU4IHJlc2VydmVkMDFbM107CisJdTMyIHJlc2VydmVkMDI7CisJdTMyIHJlc2VydmVk MDM7Cit9OworCisvKgorICogTG9ja2luZyBGZWF0dXJlIERlc2NyaXB0b3IuIENvbnRhaW5zIGZs YWdzIGluZGljYXRpbmcgc3VwcG9ydCBmb3IgdGhlCisgKiBsb2NraW5nIGZlYXR1cmVzIGRlc2Ny aWJlZCBpbiB0aGUgT1BBTCBzcGVjaWZpY2F0aW9uLiBUaGUgbmFtZXMgbWF0Y2ggdGhlCisgKiBP UEFMIHRlcm1pbm9sb2d5CisgKgorICogY29kZSA9PSAweDAwMDIgaW4gMi4wMC4xMDAKKyAqLwor c3RydWN0IGQwX2xvY2tpbmdfZmVhdHVyZXMgeworCS8qCisJICogc3VwcG9ydGVkX2ZlYXR1cmVz IGJpdHM6CisJICogYml0cyA2LTc6IHJlc2VydmVkCisJICogYml0IDU6IE1CUiBkb25lCisJICog Yml0IDQ6IE1CUiBlbmFibGVkCisJICogYml0IDM6IG1lZGlhIGVuY3J5cHRpb24KKwkgKiBiaXQg MjogbG9ja2VkCisJICogYml0IDE6IGxvY2tpbmcgZW5hYmxlZAorCSAqIGJpdCAwOiBsb2NraW5n IHN1cHBvcnRlZAorCSAqLworCXU4IHN1cHBvcnRlZF9mZWF0dXJlczsKKwkvKgorCSAqIGJ5dGVz IDUgdGhyb3VnaCAxNSBhcmUgcmVzZXJ2ZWQsIGJ1dCB3ZSByZXByZXNlbnQgdGhlIGZpcnN0IDMg YXMKKwkgKiB1OCB0byBrZWVwIHRoZSBvdGhlciB0d28gMzJiaXRzIGludGVnZXJzIGFsaWduZWQu CisJICovCisJdTggcmVzZXJ2ZWQwMVszXTsKKwl1MzIgcmVzZXJ2ZWQwMjsKKwl1MzIgcmVzZXJ2 ZWQwMzsKK307CisKKy8qCisgKiBHZW9tZXRyeSBGZWF0dXJlIERlc2NyaXB0b3IuIENvbnRhaW5z IGZsYWdzIGluZGljYXRpbmcgc3VwcG9ydCBmb3IgdGhlCisgKiBnZW9tZXRyeSBmZWF0dXJlcyBk ZXNjcmliZWQgaW4gdGhlIE9QQUwgc3BlY2lmaWNhdGlvbi4gVGhlIG5hbWVzIG1hdGNoIHRoZQor ICogT1BBTCB0ZXJtaW5vbG9neQorICoKKyAqIGNvZGUgPT0gMHgwMDAzIGluIDIuMDAuMTAwCisg Ki8KK3N0cnVjdCBkMF9nZW9tZXRyeV9mZWF0dXJlcyB7CisJLyoKKwkgKiBza2lwIDMyIGJpdHMg ZnJvbSBoZWFkZXIsIG5lZWRlZCB0byBhbGlnbiB0aGUgc3RydWN0IHRvIDY0IGJpdHMuCisJICov CisJdTggaGVhZGVyWzRdOworCS8qCisJICogcmVzZXJ2ZWQwMToKKwkgKiBiaXRzIDEtNjogcmVz ZXJ2ZWQKKwkgKiBiaXQgMDogYWxpZ24KKwkgKi8KKwl1OCByZXNlcnZlZDAxOworCXU4IHJlc2Vy dmVkMDJbN107CisJdTMyIGxvZ2ljYWxfYmxvY2tfc2l6ZTsKKwl1NjQgYWxpZ25tZW50X2dyYW51 bGFyaXR5OworCXU2NCBsb3dlc3RfYWxpZ25lZF9sYmE7Cit9OworCisvKgorICogRW50ZXJwcmlz ZSBTU0MgRmVhdHVyZQorICoKKyAqIGNvZGUgPT0gMHgwMTAwCisgKi8KK3N0cnVjdCBkMF9lbnRl cnByaXNlX3NzYyB7CisJdTE2IGJhc2VDb21JRDsKKwl1MTYgbnVtQ29tSURzOworCS8qIHJhbmdl X2Nyb3NzaW5nOgorCSAqIGJpdHMgMS02OiByZXNlcnZlZAorCSAqIGJpdCAwOiByYW5nZSBjcm9z c2luZworCSAqLworCXU4IHJhbmdlX2Nyb3NzaW5nOworCXU4IHJlc2VydmVkMDE7CisJdTE2IHJl c2VydmVkMDI7CisJdTMyIHJlc2VydmVkMDM7CisJdTMyIHJlc2VydmVkMDQ7Cit9OworCisvKgor ICogT3BhbCBWMSBmZWF0dXJlCisgKgorICogY29kZSA9PSAweDAyMDAKKyAqLworc3RydWN0IGQw X29wYWxfdjEwMCB7CisJdTE2IGJhc2VDb21JRDsKKwl1MTYgbnVtQ29tSURzOworfTsKKworLyoK KyAqIFNpbmdsZSBVc2VyIE1vZGUgZmVhdHVyZQorICoKKyAqIGNvZGUgPT0gMHgwMjAxCisgKi8K K3N0cnVjdCBkMF9zaW5nbGVfdXNlcl9tb2RlIHsKKwl1MzIgbnVtX2xvY2tpbmdfb2JqZWN0czsK KwkvKiByZXNlcnZlZDAxOgorCSAqIGJpdCAwOiBhbnkKKwkgKiBiaXQgMTogYWxsCisJICogYml0 IDI6IHBvbGljeQorCSAqIGJpdHMgMy03OiByZXNlcnZlZAorCSAqLworCXU4IHJlc2VydmVkMDE7 CisJdTggcmVzZXJ2ZWQwMjsKKwl1MTYgcmVzZXJ2ZWQwMzsKKwl1MzIgcmVzZXJ2ZWQwNDsKK307 CisKKy8qCisgKiBBZGRpdG9uYWwgRGF0YXN0b3JlcyBmZWF0dXJlCisgKgorICogY29kZSA9PSAw eDAyMDIKKyAqLworc3RydWN0IGQwX2RhdGFzdG9yZV90YWJsZSB7CisJdTE2IHJlc2VydmVkMDE7 CisJdTE2IG1heF90YWJsZXM7CisJdTMyIG1heF9zaXplX3RhYmxlczsKKwl1MzIgdGFibGVfc2l6 ZV9hbGlnbm1lbnQ7Cit9OworCisvKgorICogT1BBTCAyLjAgZmVhdHVyZQorICoKKyAqIGNvZGUg PT0gMHgwMjAzCisgKi8KK3N0cnVjdCBkMF9vcGFsX3YyMDAgeworCXUxNiBiYXNlQ29tSUQ7CisJ dTE2IG51bUNvbUlEczsKKwkvKiByYW5nZV9jcm9zc2luZzoKKwkgKiBiaXRzIDEtNjogcmVzZXJ2 ZWQKKwkgKiBiaXQgMDogcmFuZ2UgY3Jvc3NpbmcKKwkgKi8KKwl1OCByYW5nZV9jcm9zc2luZzsK KwkvKiBudW1fbG9ja2luZ19hZG1pbl9hdXRoOgorCSAqIG5vdCBhbGlnbmVkIHRvIDE2IGJpdHMs IHNvIHVzZSB0d28gdTguCisJICogc3RvcmVkIGluIGJpZyBlbmRpYW46CisJICogMDogTVNCCisJ ICogMTogTFNCCisJICovCisJdTggbnVtX2xvY2tpbmdfYWRtaW5fYXV0aFsyXTsKKwkvKiBudW1f bG9ja2luZ191c2VyX2F1dGg6CisJICogbm90IGFsaWduZWQgdG8gMTYgYml0cywgc28gdXNlIHR3 byB1OC4KKwkgKiBzdG9yZWQgaW4gYmlnIGVuZGlhbjoKKwkgKiAwOiBNU0IKKwkgKiAxOiBMU0IK KwkgKi8KKwl1OCBudW1fbG9ja2luZ191c2VyX2F1dGhbMl07CisJdTggaW5pdGlhbFBJTjsKKwl1 OCByZXZlcnRlZFBJTjsKKwl1OCByZXNlcnZlZDAxOworCXUzMiByZXNlcnZlZDAyOworfTsKKwor LyogVW5pb24gb2YgZmVhdHVyZXMgdXNlZCB0byBwYXJzZSB0aGUgZGlzY292ZXJ5IDAgcmVzcG9u c2UgKi8KK3N0cnVjdCBkMF9mZWF0dXJlcyB7CisJdTE2IGNvZGU7CisJLyoKKwkgKiByX3ZlcnNp b24gYml0czoKKwkgKiBiaXRzIDQtNzogdmVyc2lvbgorCSAqIGJpdHMgMC0zOiByZXNlcnZlZAor CSAqLworCXU4IHJfdmVyc2lvbjsKKwl1OCBsZW5ndGg7CisJdTggZmVhdHVyZXNbXTsKK307CisK K3N0cnVjdCBrZXkgKnJlcXVlc3RfdXNlcl9rZXkoY29uc3QgY2hhciAqbWFzdGVyX2Rlc2MsIGNv bnN0IHU4ICoqbWFzdGVyX2tleSwKKwkJCSAgICAgc2l6ZV90ICptYXN0ZXJfa2V5bGVuKTsKKwor I2VuZGlmIC8qIF9OVk1FX09QQUxfSU5URVJOQUxfSCAqLwpkaWZmIC0tZ2l0IGEvbGliL3NlZC1v cGFsX2tleS5jIGIvbGliL3NlZC1vcGFsX2tleS5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4 IDAwMDAwMDAuLjBiNGRlMDEKLS0tIC9kZXYvbnVsbAorKysgYi9saWIvc2VkLW9wYWxfa2V5LmMK QEAgLTAsMCArMSw0NiBAQAorLyoKKyAqIENvcHlyaWdodCDCqSAyMDE2IEludGVsIENvcnBvcmF0 aW9uCisgKgorICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2Us IHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEKKyAqIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQg YXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCisgKiB0byBk ZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91 dCBsaW1pdGF0aW9uCisgKiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwg cHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwKKyAqIGFuZC9vciBzZWxsIGNvcGllcyBv ZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZQorICogU29m dHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29u ZGl0aW9uczoKKyAqCisgKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJt aXNzaW9uIG5vdGljZSAoaW5jbHVkaW5nIHRoZSBuZXh0CisgKiBwYXJhZ3JhcGgpIHNoYWxsIGJl IGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlCisg KiBTb2Z0d2FyZS4KKyAqCisgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lU SE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwgSU5DTFVE SU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFks CisgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5U LiAgSU4gTk8gRVZFTlQgU0hBTEwKKyAqIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJT IEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCisgKiBMSUFCSUxJVFks IFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJ U0lORworICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUg T1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUworICogSU4gVEhFIFNPRlRXQVJFLgorICoKKyAq IEF1dGhvcjoKKyAqICAgIFJhZmFlbCBBbnRvZ25vbGxpIDxyYWZhZWwuYW50b2dub2xsaUBpbnRl bC5jb20+CisgKi8KKworI2luY2x1ZGUgPGxpbnV4L2tleS5oPgorI2luY2x1ZGUgInNlZC1vcGFs X2ludGVybmFsLmgiCisKK3N0cnVjdCBrZXkgKnJlcXVlc3RfdXNlcl9rZXkoY29uc3QgY2hhciAq bWFzdGVyX2Rlc2MsIGNvbnN0IHU4ICoqbWFzdGVyX2tleSwKKwkJCSAgICAgc2l6ZV90ICptYXN0 ZXJfa2V5bGVuKQoreworCWNvbnN0IHN0cnVjdCB1c2VyX2tleV9wYXlsb2FkICp1cGF5bG9hZDsK KwlzdHJ1Y3Qga2V5ICp1a2V5OworCisJdWtleSA9IHJlcXVlc3Rfa2V5KCZrZXlfdHlwZV91c2Vy LCBtYXN0ZXJfZGVzYywgTlVMTCk7CisJaWYgKElTX0VSUih1a2V5KSkKKwkJZ290byBlcnJvcjsK KworCWRvd25fcmVhZCgmdWtleS0+c2VtKTsKKwl1cGF5bG9hZCA9IHVzZXJfa2V5X3BheWxvYWQo dWtleSk7CisJKm1hc3Rlcl9rZXkgPSB1cGF5bG9hZC0+ZGF0YTsKKwkqbWFzdGVyX2tleWxlbiA9 IHVwYXlsb2FkLT5kYXRhbGVuOworZXJyb3I6CisJcmV0dXJuIHVrZXk7Cit9CmRpZmYgLS1naXQg YS9saWIvc2VkLmMgYi9saWIvc2VkLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAw MC4uNzhmOGJhMwotLS0gL2Rldi9udWxsCisrKyBiL2xpYi9zZWQuYwpAQCAtMCwwICsxLDI1MCBA QAorI2luY2x1ZGUgPGxpbnV4L2Jsa2Rldi5oPgorI2luY2x1ZGUgPGxpbnV4L3NlZC5oPgorI2lu Y2x1ZGUgPGxpbnV4L3NlZC1vcGFsLmg+CisKKyNpZm5kZWYgQ09ORklHX1NFRF9PUEFMCitzdGF0 aWMgaW50IHNlZF9vcGFsX3NhdmUoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNl ZF9rZXkgKnNlZCkKKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQorc3RhdGljIGludCBzZWRfb3Bh bF9sb2NrX3VubG9jayhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAq a2V5KQorCXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9CitzdGF0aWMgaW50IHNlZF9vcGFsX3Rha2Vf b3duZXJzaGlwKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkp CisJeyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KK3N0YXRpYyBpbnQgc2VkX29wYWxfYWN0aXZhdGVf bHNwKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCisJeyBy ZXR1cm4gLUVPUE5PVFNVUFA7IH0KK3N0YXRpYyBpbnQgc2VkX29wYWxfc2V0X3B3KHN0cnVjdCBi bG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCisJeyByZXR1cm4gLUVPUE5P VFNVUFA7IH0KK3N0YXRpYyBpbnQgc2VkX29wYWxfYWN0aXZhdGVfdXNlcihzdHJ1Y3QgYmxvY2tf ZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorCXsgcmV0dXJuIC1FT1BOT1RTVVBQ OyB9CitzdGF0aWMgaW50IHNlZF9vcGFsX3JldmVydHRwZXIoc3RydWN0IGJsb2NrX2RldmljZSAq YmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQorc3Rh dGljIGludCBzZWRfb3BhbF9zZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2Ug KmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCisJeyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KK3N0 YXRpYyBpbnQgc2VkX29wYWxfYWRkdXNlcl90b19scihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2 LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorCXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9CitzdGF0aWMg aW50IHNlZF9vcGFsX2RvX21icihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk X2tleSAqa2V5KQorCXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9CitzdGF0aWMgaW50IHNlZF9vcGFs X2VyYXNlX2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkp CisJeyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KKworI2Vsc2UKKworc3RhdGljIGlubGluZSBpbnQg YmRldl9zZWNfY2FwYWJsZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2KQoreworCXJldHVybiAh KCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8CisJCSAh YmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcyk7CisKK30KKworc3RhdGljIGludCBzZWRfb3Bh bF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7 CisJaWYgKGJkZXZfc2VjX2NhcGFibGUoYmRldikpCisJICAgIHJldHVybiBvcGFsX3NhdmUoYmRl diwga2V5KTsKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisKK3N0YXRpYyBpbnQgc2VkX29wYWxf bG9ja191bmxvY2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtl eSkKK3sKKworCWlmIChiZGV2X3NlY19jYXBhYmxlKGJkZXYpKQorCQlyZXR1cm4gb3BhbF9sb2Nr X3VubG9jayhiZGV2LCBrZXkpOworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworc3RhdGljIGlu dCBzZWRfb3BhbF90YWtlX293bmVyc2hpcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LAorCQkJ CSAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlpZiAoYmRldl9zZWNfY2FwYWJsZShiZGV2 KSkKKwkJcmV0dXJuIG9wYWxfdGFrZV9vd25lcnNoaXAoYmRldiwga2V5KTsKKwlyZXR1cm4gLUVP UE5PVFNVUFA7Cit9CisKK3N0YXRpYyBpbnQgc2VkX29wYWxfYWN0aXZhdGVfbHNwKHN0cnVjdCBi bG9ja19kZXZpY2UgKmJkZXYsCisJCQkJIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlpZiAo YmRldl9zZWNfY2FwYWJsZShiZGV2KSkKKwkJcmV0dXJuIG9wYWxfYWN0aXZhdGVfbHNwKGJkZXYs IGtleSk7CisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQorCitzdGF0aWMgaW50IHNlZF9vcGFsX3Nl dF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LAorCQkJICAgc3RydWN0IHNlZF9rZXkgKmtl eSkKK3sKKwlpZiAoYmRldl9zZWNfY2FwYWJsZShiZGV2KSkKKwkJcmV0dXJuIG9wYWxfc2V0X25l d19wdyhiZGV2LCBrZXkpOworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworc3RhdGljIGludCBz ZWRfb3BhbF9hY3RpdmF0ZV91c2VyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkJICBz dHJ1Y3Qgc2VkX2tleSAqa2V5KQoreworCWlmIChiZGV2X3NlY19jYXBhYmxlKGJkZXYpKQorCQly ZXR1cm4gb3BhbF9hY3RpdmF0ZV91c2VyKGJkZXYsIGtleSk7CisJcmV0dXJuIC1FT1BOT1RTVVBQ OworfQorCitzdGF0aWMgaW50IHNlZF9vcGFsX3JldmVydHRwZXIoc3RydWN0IGJsb2NrX2Rldmlj ZSAqYmRldiwKKwkJCSAgICAgICBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQoreworCWlmIChiZGV2X3Nl Y19jYXBhYmxlKGJkZXYpKQorCQlyZXR1cm4gb3BhbF9yZXZlcnR0cGVyKGJkZXYsIGtleSk7CisJ cmV0dXJuIC1FT1BOT1RTVVBQOworfQorCitzdGF0aWMgaW50IHNlZF9vcGFsX3NldHVwX2xyKHN0 cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkgICAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7 CisKKwlpZiAoYmRldl9zZWNfY2FwYWJsZShiZGV2KSkKKwkJcmV0dXJuIG9wYWxfc2V0dXBfbG9j a2luZ19yYW5nZShiZGV2LCBrZXkpOworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworc3RhdGlj IGludCBzZWRfb3BhbF9hZGR1c2VyX3RvX2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJ CQkgICAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlpZiAoYmRldl9zZWNfY2FwYWJsZShi ZGV2KSkKKwkJcmV0dXJuIG9wYWxfYWRkX3VzZXJfdG9fbHIoYmRldiwga2V5KTsKKwlyZXR1cm4g LUVPUE5PVFNVUFA7Cit9CisKK3N0YXRpYyBpbnQgc2VkX29wYWxfZG9fbWJyKHN0cnVjdCBibG9j a19kZXZpY2UgKmJkZXYsCisJCQkgICBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQoreworCisJaWYgKGJk ZXZfc2VjX2NhcGFibGUoYmRldikpCisJCXJldHVybiBvcGFsX2VuYWJsZV9kaXNhYmxlX3NoYWRv d19tYnIoYmRldiwga2V5KTsKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisKK3N0YXRpYyBpbnQg c2VkX29wYWxfZXJhc2VfbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCSAgICAgc3Ry dWN0IHNlZF9rZXkgKmtleSkKK3sKKwlpZiAoYmRldl9zZWNfY2FwYWJsZShiZGV2KSkKKwkJcmV0 dXJuIG9wYWxfZXJhc2VfbG9ja2luZ19yYW5nZShiZGV2LCBrZXkpOworCXJldHVybiAtRU9QTk9U U1VQUDsKK30KKyNlbmRpZgorCitpbnQgc2VkX3NhdmUoc3RydWN0IGJsb2NrX2RldmljZSAqYmRl diwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgewor CWNhc2UgT1BBTF9MT0NLX1VOTE9DSzoKKwkJcmV0dXJuIHNlZF9vcGFsX3NhdmUoYmRldiwga2V5 KTsKKwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisKK2ludCBzZWRfbG9ja191bmxvY2so c3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKworCXN3 aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTF9MT0NLX1VOTE9DSzoKKwkJcmV0dXJu IHNlZF9vcGFsX2xvY2tfdW5sb2NrKGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1FT1BOT1RT VVBQOworfQorCitpbnQgc2VkX3Rha2Vfb3duZXJzaGlwKHN0cnVjdCBibG9ja19kZXZpY2UgKmJk ZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsK KwljYXNlIE9QQUw6CisJCXJldHVybiBzZWRfb3BhbF90YWtlX293bmVyc2hpcChiZGV2LCBrZXkp OworCX0KKworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworaW50IHNlZF9hY3RpdmF0ZV9sc3Ao c3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKworCXN3 aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTDoKKwkJcmV0dXJuIHNlZF9vcGFsX2Fj dGl2YXRlX2xzcChiZGV2LCBrZXkpOworCX0KKworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKwor aW50IHNlZF9zZXRfcHcoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkg KmtleSkKK3sKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTF9QVzoKKwkJ cmV0dXJuIHNlZF9vcGFsX3NldF9wdyhiZGV2LCBrZXkpOworCX0KKworCXJldHVybiAtRU9QTk9U U1VQUDsKK30KKworaW50IHNlZF9hY3RpdmF0ZV91c2VyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJk ZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsK KwljYXNlIE9QQUxfQUNUX1VTUjoKKwkJcmV0dXJuIHNlZF9vcGFsX2FjdGl2YXRlX3VzZXIoYmRl diwga2V5KTsKKwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisKK2ludCBzZWRfcmV2ZXJ0 dHBlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorewor CisJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBPUEFMOgorCQlyZXR1cm4gc2VkX29w YWxfcmV2ZXJ0dHBlcihiZGV2LCBrZXkpOworCX0KKworCXJldHVybiAtRU9QTk9UU1VQUDsKK30K KworaW50IHNlZF9zZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYs IHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsKKwlj YXNlIE9QQUxfTFJfU0VUVVA6CisJCXJldHVybiBzZWRfb3BhbF9zZXR1cF9scihiZGV2LCBrZXkp OworCX0KKworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworaW50IHNlZF9hZGR1c2VyX3RvX2xy KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlz d2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsKKwljYXNlIE9QQUxfTE9DS19VTkxPQ0s6CisJCXJldHVy biBzZWRfb3BhbF9hZGR1c2VyX3RvX2xyKGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1FT1BO T1RTVVBQOworfQorCitpbnQgc2VkX2RvX21icihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBz dHJ1Y3Qgc2VkX2tleSAqa2V5KQoreworCisJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2Fz ZSBPUEFMX01CUl9EQVRBOgorCQlyZXR1cm4gc2VkX29wYWxfZG9fbWJyKGJkZXYsIGtleSk7CisJ fQorCisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQorCitpbnQgc2VkX2VyYXNlX2xyKHN0cnVjdCBi bG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlzd2l0Y2ggKGtl eS0+c2VkX3R5cGUpIHsKKwljYXNlIE9QQUw6CisJCXJldHVybiBzZWRfb3BhbF9lcmFzZV9scihi ZGV2LCBrZXkpOworCX0KKworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KLS0gCjIuNy40CgoKX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGludXgtbnZtZSBt YWlsaW5nIGxpc3QKTGludXgtbnZtZUBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5p bmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtbnZtZQo= From mboxrd@z Thu Jan 1 00:00:00 1970 From: scott.bauer@intel.com (Scott Bauer) Date: Wed, 16 Nov 2016 16:17:27 -0700 Subject: [PATCH v1 2/7] lib: Add Sed-opal library In-Reply-To: <1479338252-8777-1-git-send-email-scott.bauer@intel.com> References: <1479338252-8777-1-git-send-email-scott.bauer@intel.com> Message-ID: <1479338252-8777-3-git-send-email-scott.bauer@intel.com> 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 | 3338 +++++++++++++++++++++++++++++++++++++++++++++++ lib/sed-opal_internal.h | 587 +++++++++ lib/sed-opal_key.c | 46 + lib/sed.c | 250 ++++ 4 files changed, 4221 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..3ce1126 --- /dev/null +++ b/lib/sed-opal.c @@ -0,0 +1,3338 @@ +/* + * 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; + struct work_struct opal_send_work; + struct work_struct opal_recv_work; + 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 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); + schedule_work(&dev->opal_recv_work); +} + +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); + schedule_work(&dev->opal_recv_work); +} + +static inline void get_data_ops(struct opal_dev *dev, const struct sec_ops **ops, + void **data) +{ + if (dev->resume_from_suspend) { + *ops = &dev->resume_data->ops; + *data = dev->resume_data->data; + } else { + *ops = dev->bdev->bd_disk->fops->sec_ops; + *data = dev->bdev->bd_disk->private_data; + } +} + +static void _opal_send_cmd(struct work_struct *send_work) +{ + struct opal_dev *dev = container_of(send_work, struct opal_dev, + opal_send_work); + const struct sec_ops *ops = NULL; + void *data = NULL; + + get_data_ops(dev, &ops, &data); + ops->send(data, dev->comID, TCG_SECP_01, dev->cmd.cmd, + IO_BUFFER_LENGTH, opal_send_cb, dev); + +} + +static void _opal_recv_cmd(struct work_struct *recv_work) +{ + struct opal_dev *dev = container_of(recv_work, struct opal_dev, + opal_recv_work); + const struct sec_ops *ops; + void *data; + + get_data_ops(dev, &ops, &data); + ops->recv(data, dev->comID, TCG_SECP_01, dev->cmd.resp, + IO_BUFFER_LENGTH, opal_send_cb_cont, dev); +} + +static void opal_send_recv(struct opal_dev *dev, sec_cb *cb, void *cb_data) +{ + dev->cmd.cb = cb; + dev->cmd.cb_data = cb_data; + schedule_work(&dev->opal_send_work); +} + +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; + case 0xbfff ... 0xffff: + /* vendor specific, just ignore */ + break; + default: + pr_warn("%s: OPAL Unknown feature: %d\n", + dev->disk_name, be16_to_cpu(body->code)); + + } + 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) +{ + const struct sec_ops *ops; + void *data; + + get_data_ops(dev, &ops, &data); + memset(dev->cmd.resp, 0, IO_BUFFER_LENGTH); + return ops->recv(data, 0x0001, TCG_SECP_01, 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) { + pr_warn("uint64 with more than 8 bytes\n"); + return -EINVAL; + } + for (i = tok->len - 1; i > 0; i--) { + u_integer |= ((u64)pos[i] << (8 * b)); + b++; + } + 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); + + if (token_length == -EINVAL) { + ret = -EINVAL; + goto err; + } + + 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); +} + +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); + + opal_send_recv(dev, cont, dev); + 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 inline int enable_global_lr(struct opal_cmd *cmd, u8 *uid, + struct opal_user_lr_setup *setup) +{ + const u8 *method; + method = OPALMETHOD[OPAL_SET]; + return test_and_add_token_va(cmd, "c2s 4c 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_05, /* ReadLockEnabled */ + !!setup->RLE, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_06, /* WriteLockEnabled */ + !!setup->WLE, + + OPAL_ENDNAME, + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); +} + +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]; + if (dev->lr == 0) + ret = enable_global_lr(cmd, uid, setup); + else + 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 = GENERIC_HOST_SESSION_NUM; + + 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 = GENERIC_HOST_SESSION_NUM; + + 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 = GENERIC_HOST_SESSION_NUM; + + 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 Done command\n", + 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 done command\n", + 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) +{ + int ret = build_end_opal_session(dev); + if (ret < 0) + return ret; + return finalize_and_send(dev, &dev->cmd, end_session_cont); +} + +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; + INIT_WORK(&opal_dev->opal_send_work, _opal_send_cmd); + INIT_WORK(&opal_dev->opal_recv_work, _opal_recv_cmd); + + + 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 = 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; +} + +/* These are global'd because both lock_unlock_internal + * and opal_unlock_from_suspend need them. + */ +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 +}; +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; + + 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) + 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 }; + + 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 = ulk_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..54041cb --- /dev/null +++ b/lib/sed-opal_internal.h @@ -0,0 +1,587 @@ +/* + * 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 +#define GENERIC_HOST_SESSION_NUM 0x41 + +static const char *opal_errors[] = { + "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 >= ARRAY_SIZE(opal_errors) || error < 0) + 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..78f8ba3 --- /dev/null +++ b/lib/sed.c @@ -0,0 +1,250 @@ +#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 inline int bdev_sec_capable(struct block_device *bdev) +{ + return !(!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops); + +} + +static int sed_opal_save(struct block_device *bdev, struct sed_key *key) +{ + if (bdev_sec_capable(bdev)) + return opal_save(bdev, key); + return -EOPNOTSUPP; +} + +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key) +{ + + if (bdev_sec_capable(bdev)) + return opal_lock_unlock(bdev, key); + return -EOPNOTSUPP; +} + +static int sed_opal_take_ownership(struct block_device *bdev, + struct sed_key *key) +{ + + if (bdev_sec_capable(bdev)) + return opal_take_ownership(bdev, key); + return -EOPNOTSUPP; +} + +static int sed_opal_activate_lsp(struct block_device *bdev, + struct sed_key *key) +{ + + if (bdev_sec_capable(bdev)) + return opal_activate_lsp(bdev, key); + return -EOPNOTSUPP; +} + +static int sed_opal_set_pw(struct block_device *bdev, + struct sed_key *key) +{ + if (bdev_sec_capable(bdev)) + return opal_set_new_pw(bdev, key); + return -EOPNOTSUPP; +} + +static int sed_opal_activate_user(struct block_device *bdev, + struct sed_key *key) +{ + if (bdev_sec_capable(bdev)) + return opal_activate_user(bdev, key); + return -EOPNOTSUPP; +} + +static int sed_opal_reverttper(struct block_device *bdev, + struct sed_key *key) +{ + if (bdev_sec_capable(bdev)) + return opal_reverttper(bdev, key); + return -EOPNOTSUPP; +} + +static int sed_opal_setup_lr(struct block_device *bdev, + struct sed_key *key) +{ + + if (bdev_sec_capable(bdev)) + return opal_setup_locking_range(bdev, key); + return -EOPNOTSUPP; +} + +static int sed_opal_adduser_to_lr(struct block_device *bdev, + struct sed_key *key) +{ + + if (bdev_sec_capable(bdev)) + return opal_add_user_to_lr(bdev, key); + return -EOPNOTSUPP; +} + +static int sed_opal_do_mbr(struct block_device *bdev, + struct sed_key *key) +{ + + if (bdev_sec_capable(bdev)) + return opal_enable_disable_shadow_mbr(bdev, key); + return -EOPNOTSUPP; +} + +static int sed_opal_erase_lr(struct block_device *bdev, + struct sed_key *key) +{ + if (bdev_sec_capable(bdev)) + return opal_erase_locking_range(bdev, key); + return -EOPNOTSUPP; +} +#endif + +int sed_save(struct block_device *bdev, struct sed_key *key) +{ + + 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) +{ + + 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) +{ + + 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) +{ + + 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) +{ + + 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) +{ + + 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) +{ + + 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) +{ + + 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) +{ + + 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) +{ + + 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) +{ + + switch (key->sed_type) { + case OPAL: + return sed_opal_erase_lr(bdev, key); + } + + return -EOPNOTSUPP; +} -- 2.7.4