From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Scott Bauer To: linux-nvme@lists.infradead.org Subject: [RFC PATCH 2/6] lib: Add Sed-opal library Date: Mon, 31 Oct 2016 15:58:15 -0600 Message-Id: <1477951099-3127-3-git-send-email-scott.bauer@intel.com> In-Reply-To: <1477951099-3127-1-git-send-email-scott.bauer@intel.com> References: <1477951099-3127-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, 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 dGVsLmNvbT4KLS0tCiBsaWIvc2VkLW9wYWwuYyAgICAgICAgICB8IDMzMzcgKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIGxpYi9zZWQtb3BhbF9pbnRlcm5h bC5oIHwgIDU4NiArKysrKysrKysKIGxpYi9zZWQtb3BhbF9rZXkuYyAgICAgIHwgICA0NiArCiBs aWIvc2VkLmMgICAgICAgICAgICAgICB8ICAzMDMgKysrKysKIDQgZmlsZXMgY2hhbmdlZCwgNDI3 MiBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL3NlZC1vcGFsLmMKIGNyZWF0 ZSBtb2RlIDEwMDY0NCBsaWIvc2VkLW9wYWxfaW50ZXJuYWwuaAogY3JlYXRlIG1vZGUgMTAwNjQ0 IGxpYi9zZWQtb3BhbF9rZXkuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGxpYi9zZWQuYwoKZGlmZiAt LWdpdCBhL2xpYi9zZWQtb3BhbC5jIGIvbGliL3NlZC1vcGFsLmMKbmV3IGZpbGUgbW9kZSAxMDA2 NDQKaW5kZXggMDAwMDAwMC4uMTBiMzM0OAotLS0gL2Rldi9udWxsCisrKyBiL2xpYi9zZWQtb3Bh bC5jCkBAIC0wLDAgKzEsMzMzNyBAQAorLyoKKyAqIENvcHlyaWdodCDCqSAyMDE2IEludGVsIENv cnBvcmF0aW9uCisgKgorICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBj aGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEKKyAqIGNvcHkgb2YgdGhpcyBzb2Z0d2Fy ZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCisg KiB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcg d2l0aG91dCBsaW1pdGF0aW9uCisgKiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBt ZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwKKyAqIGFuZC9vciBzZWxsIGNv cGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZQor ICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dp bmcgY29uZGl0aW9uczoKKyAqCisgKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhp cyBwZXJtaXNzaW9uIG5vdGljZSAoaW5jbHVkaW5nIHRoZSBuZXh0CisgKiBwYXJhZ3JhcGgpIHNo YWxsIGJlIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2Yg dGhlCisgKiBTb2Z0d2FyZS4KKyAqCisgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElT IiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwg SU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFC SUxJVFksCisgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklO R0VNRU5ULiAgSU4gTk8gRVZFTlQgU0hBTEwKKyAqIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBI T0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCisgKiBMSUFC SUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lT RSwgQVJJU0lORworICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09G VFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUworICogSU4gVEhFIFNPRlRXQVJFLgor ICoKKyAqIEF1dGhvcnM6CisgKiAgICBSYWZhZWwgQW50b2dub2xsaSA8cmFmYWVsLmFudG9nbm9s bGlAaW50ZWwuY29tPgorICogICAgU2NvdHQgIEJhdWVyICAgICAgPHNjb3R0LmJhdWVyQGludGVs LmNvbT4KKyAqLworCisjZGVmaW5lIHByX2ZtdChmbXQpIEtCVUlMRF9NT0ROQU1FICI6T1BBTDog IiBmbXQKKworI2luY2x1ZGUgPGxpbnV4L2RlbGF5Lmg+CisjaW5jbHVkZSA8bGludXgvZGV2aWNl Lmg+CisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvbGlzdC5oPgor I2luY2x1ZGUgPGxpbnV4L2dlbmhkLmg+CisjaW5jbHVkZSA8bGludXgvc2xhYi5oPgorI2luY2x1 ZGUgPGxpbnV4L3VhY2Nlc3MuaD4KKyNpbmNsdWRlIDx1YXBpL2xpbnV4L3NlZC1vcGFsLmg+Cisj aW5jbHVkZSA8bGludXgvc2VkLmg+CisjaW5jbHVkZSA8bGludXgvc2VkLW9wYWwuaD4KKyNpbmNs dWRlIDxsaW51eC9zdHJpbmcuaD4KKworI2luY2x1ZGUgInNlZC1vcGFsX2ludGVybmFsLmgiCisK KyNkZWZpbmUgSU9fQlVGRkVSX0xFTkdUSCAyMDQ4CisKKyNkZWZpbmUgTUFYX1RPS1MgNjQKKwor c3RydWN0IG9wYWxfY21kIHsKKwlzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2OworCXNlY19jYiAq Y2I7CisJdm9pZCAqY2JfZGF0YTsKKworCXNpemVfdCBwb3M7CisJdTggY21kX2J1ZltJT19CVUZG RVJfTEVOR1RIICogMl07CisJdTggcmVzcF9idWZbSU9fQlVGRkVSX0xFTkdUSCAqIDJdOworCXU4 ICpjbWQ7CisJdTggKnJlc3A7Cit9OworCisvKgorICogT24gdGhlIHBhcnNlZCByZXNwb25zZSwg d2UgZG9uJ3Qgc3RvcmUgYWdhaW4gdGhlIHRva3MgdGhhdCBhcmUgYWxyZWFkeQorICogc3RvcmVk IGluIHRoZSByZXNwb25zZSBidWZmZXIuIEluc3RlYWQsIGZvciBlYWNoIHRva2VuLCB3ZSBqdXN0 IHN0b3JlIGEKKyAqIHBvaW50ZXIgdG8gdGhlIHBvc2l0aW9uIGluIHRoZSBidWZmZXIgd2hlcmUg dGhlIHRva2VuIHN0YXJ0cywgYW5kIHRoZSBzaXplCisgKiBvZiB0aGUgdG9rZW4gaW4gYnl0ZXMu CisgKi8KK3N0cnVjdCBvcGFsX3Jlc3BfdG9rIHsKKwljb25zdCB1OCAqcG9zOworCXNpemVfdCBs ZW47CisJZW51bSBPUEFMX1JFU1BPTlNFX1RPS0VOIHR5cGU7CisJZW51bSBPUEFMX0FUT01fV0lE VEggd2lkdGg7CisJdW5pb24geworCQl1NjQgdTsKKwkJczY0IHM7CisJfSBzdG9yZWQ7Cit9Owor CisvKgorICogRnJvbSB0aGUgcmVzcG9uc2UgaGVhZGVyIGl0J3Mgbm90IHBvc3NpYmxlIHRvIGtu b3cgaG93IG1hbnkgdG9rZW5zIHRoZXJlIGFyZQorICogb24gdGhlIHBheWxvYWQuIFNvIHdlIGhh cmRjb2RlIHRoYXQgdGhlIG1heGltdW0gd2lsbCBiZSBNQVhfVE9LUywgYW5kIGxhdGVyCisgKiBp ZiB3ZSBzdGFydCBkZWFsaW5nIHdpdGggbWVzc2FnZXMgdGhhdCBoYXZlIG1vcmUgdGhhbiB0aGF0 LCB3ZSBjYW4gaW5jcmVhc2UKKyAqIHRoaXMgbnVtYmVyLiBUaGlzIGlzIGRvbmUgdG8gYXZvaWQg aGF2aW5nIHRvIG1ha2UgdHdvIHBhc3NlcyB0aHJvdWdoIHRoZQorICogcmVzcG9uc2UsIHRoZSBm aXJzdCBvbmUgY291bnRpbmcgaG93IG1hbnkgdG9rZW5zIHdlIGhhdmUgYW5kIHRoZSBzZWNvbmQg b25lCisgKiBhY3R1YWxseSBzdG9yaW5nIHRoZSBwb3NpdGlvbnMuCisgKi8KK3N0cnVjdCBwYXJz ZWRfcmVzcCB7CisJaW50IG51bTsKKwlzdHJ1Y3Qgb3BhbF9yZXNwX3RvayB0b2tzW01BWF9UT0tT XTsKK307CisKK3N0cnVjdCBvcGFsX2RldjsKKwordHlwZWRlZiB2b2lkICgqb3BhbF9jYikoaW50 IGVycm9yLCBzdHJ1Y3Qgb3BhbF9kZXYgKmRldik7CisKK3R5cGVkZWYgaW50ICgqb3BhbF9zdGVw KShzdHJ1Y3Qgb3BhbF9kZXYgKmRldik7CisKK3N0cnVjdCBvcGFsX2NvbXBsZXRpb24geworCXN0 cnVjdCBjb21wbGV0aW9uIGNtZF9jb21wbGV0aW9uOworCWludCBjb21wbGV0aW9uX3N0YXR1czsK K307CisKK3N0cnVjdCBvcGFsX2RldiB7CisJc3RydWN0IGJsb2NrX2RldmljZSAqYmRldjsKKwlz dHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpjb21wbGV0aW9uOworCXN0cnVjdCBvcGFsX2xvY2tfdW5s b2NrIGxrdWw7CisJY29uc3Qgb3BhbF9zdGVwICpmdW5jczsKKwl2b2lkICoqZnVuY19kYXRhOwor CWJvb2wgcmVzdW1lX2Zyb21fc3VzcGVuZDsKKwlzdHJ1Y3Qgb3BhbF9zdXNwZW5kX3VubGsgKnJl c3VtZV9kYXRhOworCXNpemVfdCBudW1fZnVuY19kYXRhOworCWF0b21pY190IGluX3VzZTsKKwlz ZWN0b3JfdCBzdGFydDsKKwlzZWN0b3JfdCBsZW5ndGg7CisJdTggbHI7CisJdTgga2V5X3R5cGU7 CisJdTgga2V5X25hbWVbT1BBTF9LRVlfTUFYXTsKKwlzaXplX3Qga2V5X25hbWVfbGVuOworCXU4 IGtleVtPUEFMX0tFWV9NQVhdOworCXNpemVfdCBrZXlfbGVuOworCXUxNiBjb21JRDsKKwl1MzIg SFNOOworCXUzMiBUU047CisJdTY0IGFsaWduOworCXU2NCBsb3dlc3RfbGJhOworCXN0cnVjdCBs aXN0X2hlYWQgbm9kZTsKKwljaGFyIGRpc2tfbmFtZVtESVNLX05BTUVfTEVOXTsKKwlpbnQgc3Rh dGU7CisKKwlzdHJ1Y3Qgb3BhbF9jbWQgY21kOworCXN0cnVjdCBwYXJzZWRfcmVzcCBwYXJzZWQ7 CisKKwlzaXplX3QgcHJldl9kX2xlbjsKKwl2b2lkICpwcmV2X2RhdGE7CisKKwlzZWNfY2IgKmZp bmFsX2NiOworCXZvaWQgKmZpbmFsX2NiX2RhdGE7CisJb3BhbF9zdGVwIGVycm9yX2NiOworCXZv aWQgKmVycm9yX2NiX2RhdGE7CisJb3BhbF9jYiBvcGVyX2NiOworfTsKKworTElTVF9IRUFEKG9w YWxfbGlzdCk7CitERUZJTkVfU1BJTkxPQ0sobGlzdF9zcGlubG9jayk7CisKK3N0YXRpYyB2b2lk IHByaW50X2J1ZmZlcihjb25zdCB1OCAqcHRyLCB1MzIgbGVuZ3RoKQoreworI2lmZGVmIERFQlVH CisJcHJpbnRfaGV4X2R1bXBfYnl0ZXMoIk9QQUw6ICIsIERVTVBfUFJFRklYX09GRlNFVCwgcHRy LCBsZW5ndGgpOworCXByX2RlYnVnKCJcbiIpOworI2VuZGlmCit9CisKKyNkZWZpbmUgVFBFUl9T WU5DX1NVUFBPUlRFRCBCSVQoMCkKKworc3RhdGljIGJvb2wgY2hlY2tfdHBlcihjb25zdCB2b2lk ICpkYXRhKQoreworCWNvbnN0IHN0cnVjdCBkMF90cGVyX2ZlYXR1cmVzICp0cGVyID0gZGF0YTsK Kwl1OCBmbGFncyA9IHRwZXItPnN1cHBvcnRlZF9mZWF0dXJlczsKKworCWlmICghKGZsYWdzICYg VFBFUl9TWU5DX1NVUFBPUlRFRCkpIHsKKwkJcHJfZXJyKCJUUGVyIHN5bmMgbm90IHN1cHBvcnRl ZC4gZmxhZ3MgPSAlZFxuIiwKKwkJICAgICAgIHRwZXItPnN1cHBvcnRlZF9mZWF0dXJlcyk7CisJ CXJldHVybiBmYWxzZTsKKwl9CisKKwlyZXR1cm4gdHJ1ZTsKK30KKworc3RhdGljIGJvb2wgY2hl Y2tfU1VNKGNvbnN0IHZvaWQgKmRhdGEpCit7CisJY29uc3Qgc3RydWN0IGQwX3NpbmdsZV91c2Vy X21vZGUgKnN1bSA9IGRhdGE7CisJdTMyIG5sbyA9IGJlMzJfdG9fY3B1KHN1bS0+bnVtX2xvY2tp bmdfb2JqZWN0cyk7CisKKwlpZiAobmxvID09IDApIHsKKwkJcHJfZXJyKCJOZWVkIGF0IGxlYXN0 IG9uZSBsb2NraW5nIG9iamVjdC5cbiIpOworCQlyZXR1cm4gZmFsc2U7CisJfQorCisJcHJfZGVi dWcoIk51bWJlciBvZiBsb2NraW5nIG9iamVjdHM6ICVkXG4iLCBubG8pOworCisJcmV0dXJuIHRy dWU7Cit9CisKK3N0YXRpYyB1MTYgZ2V0X2NvbUlEX3YxMDAoY29uc3Qgdm9pZCAqZGF0YSkKK3sK Kwljb25zdCBzdHJ1Y3QgZDBfb3BhbF92MTAwICp2MTAwID0gZGF0YTsKKworCXJldHVybiBiZTE2 X3RvX2NwdSh2MTAwLT5iYXNlQ29tSUQpOworfQorCitzdGF0aWMgdTE2IGdldF9jb21JRF92MjAw KGNvbnN0IHZvaWQgKmRhdGEpCit7CisJY29uc3Qgc3RydWN0IGQwX29wYWxfdjIwMCAqdjIwMCA9 IGRhdGE7CisKKwlyZXR1cm4gYmUxNl90b19jcHUodjIwMC0+YmFzZUNvbUlEKTsKK30KKworc3Rh dGljIGludCBfX29wYWxfc2VuZF9jbWQoc3RydWN0IG9wYWxfc3VzcGVuZF91bmxrICpkYXRhLCB1 MTYgY29tSUQsCisJCQkgICB2b2lkICpidWZmZXIsIHNpemVfdCBidWZsZW4sIHNlY19jYiAqY2Is CisJCQkgICB2b2lkICpjYl9kYXRhKQoreworCXJldHVybiBkYXRhLT5vcHMuc2VuZChkYXRhLT5k YXRhLCBjb21JRCwgVENHX1NFQ1BfMDEsIGJ1ZmZlciwgYnVmbGVuLAorCQkJICAgICBjYiwgY2Jf ZGF0YSk7Cit9CitzdGF0aWMgaW50IF9vcGFsX3NlbmRfY21kKHN0cnVjdCBibG9ja19kZXZpY2Ug KmJkZXYsIHUxNiBjb21JRCwKKwkJCSAgdm9pZCAqYnVmZmVyLCBzaXplX3QgYnVmbGVuLAorCQkJ ICBzZWNfY2IgKmNiLCB2b2lkICpjYl9kYXRhKQoreworCWNvbnN0IHN0cnVjdCBzZWNfb3BzICpv cHMgPSBiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzOworCisJcmV0dXJuIG9wcy0+c2VuZChi ZGV2LT5iZF9kaXNrLT5wcml2YXRlX2RhdGEsIGNvbUlELAorCQkJIFRDR19TRUNQXzAxLCBidWZm ZXIsIGJ1ZmxlbiwKKwkJCSBjYiwgY2JfZGF0YSk7Cit9CisKK3N0YXRpYyBpbnQgX19vcGFsX3Jl Y3ZfY21kKHN0cnVjdCBvcGFsX3N1c3BlbmRfdW5sayAqZGF0YSwgdTE2IGNvbUlELAorCQkJICAg dm9pZCAqYnVmZmVyLCBzaXplX3QgYnVmbGVuLCBzZWNfY2IgKmNiLAorCQkJICAgdm9pZCAqY2Jf ZGF0YSkKK3sKKwlyZXR1cm4gZGF0YS0+b3BzLnJlY3YoZGF0YS0+ZGF0YSwgY29tSUQsIFRDR19T RUNQXzAxLCBidWZmZXIsIGJ1ZmxlbiwKKwkJCSAgICAgY2IsIGNiX2RhdGEpOworfQorCitzdGF0 aWMgaW50IF9vcGFsX3JlY3ZfY21kKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHUxNiBjb21J RCwKKwkJCSAgdm9pZCAqYnVmZmVyLCBzaXplX3QgYnVmbGVuLAorCQkJICBzZWNfY2IgKmNiLCB2 b2lkICpjYl9kYXRhKQoreworCWNvbnN0IHN0cnVjdCBzZWNfb3BzICpvcHMgPSBiZGV2LT5iZF9k aXNrLT5mb3BzLT5zZWNfb3BzOworCisJcmV0dXJuIG9wcy0+cmVjdihiZGV2LT5iZF9kaXNrLT5w cml2YXRlX2RhdGEsIGNvbUlELAorCQkJIFRDR19TRUNQXzAxLCBidWZmZXIsIGJ1ZmxlbiwKKwkJ CSBjYiwgY2JfZGF0YSk7Cit9CisKK3N0YXRpYyB2b2lkIG9wYWxfc2VuZF9jYl9jb250KGludCBl cnJvciwgdm9pZCAqZGF0YSkKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJc2l6 ZV90IGJ1ZmxlbiA9IElPX0JVRkZFUl9MRU5HVEg7CisJdm9pZCAqYnVmZmVyID0gZGV2LT5jbWQu cmVzcDsKKwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9IGJ1ZmZlcjsKKworCXByX2RlYnVnKCIl czogU2VudCBPUEFMIGNvbW1hbmQ6IGVycm9yPSVkLCBvdXRzdGFuZGluZz0lZCwgbWluVHJhbnNm ZXI9JWRcbiIsCisJICAgICAgIGRldi0+ZGlza19uYW1lLCBlcnJvciwgaGRyLT5jcC5vdXRzdGFu ZGluZ0RhdGEsCisJICAgICAgIGhkci0+Y3AubWluVHJhbnNmZXIpOworCisJaWYgKGVycm9yIHx8 IGhkci0+Y3Aub3V0c3RhbmRpbmdEYXRhID09IDAgfHwKKwkgICAgaGRyLT5jcC5taW5UcmFuc2Zl ciAhPSAwKSB7CisJCWlmIChkZXYtPmNtZC5jYikKKwkJCWRldi0+Y21kLmNiKGVycm9yLCBkZXYt PmNtZC5jYl9kYXRhKTsKKwkJcmV0dXJuOworCX0KKworCW1lbXNldChidWZmZXIsIDAsIGJ1Zmxl bik7CisJaWYgKGRldi0+cmVzdW1lX2Zyb21fc3VzcGVuZCkKKwkJX19vcGFsX3JlY3ZfY21kKGRl di0+cmVzdW1lX2RhdGEsIGRldi0+Y29tSUQsCisJCQkJYnVmZmVyLCBidWZsZW4sIG9wYWxfc2Vu ZF9jYl9jb250LCBkZXYpOworCWVsc2UKKwkJX29wYWxfcmVjdl9jbWQoZGV2LT5iZGV2LCBkZXYt PmNvbUlELCBidWZmZXIsIGJ1ZmxlbiwKKwkJCSAgICAgICBvcGFsX3NlbmRfY2JfY29udCwgZGV2 KTsKK30KKworc3RhdGljIHZvaWQgb3BhbF9zZW5kX2NiKGludCBlcnJvciwgdm9pZCAqZGF0YSkK K3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJc2l6ZV90IGJ1ZmxlbiA9IElPX0JV RkZFUl9MRU5HVEg7CisJdm9pZCAqYnVmZmVyID0gZGV2LT5jbWQucmVzcDsKKworCWlmIChlcnJv cikgeworCQlpZiAoZGV2LT5jbWQuY2IpCisJCQlkZXYtPmNtZC5jYihlcnJvciwgZGV2LT5jbWQu Y2JfZGF0YSk7CisJCXJldHVybjsKKwl9CisKKwltZW1zZXQoYnVmZmVyLCAwLCBidWZsZW4pOwor CWlmIChkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQpCisJCV9fb3BhbF9yZWN2X2NtZChkZXYtPnJl c3VtZV9kYXRhLCBkZXYtPmNvbUlELAorCQkJCWJ1ZmZlciwgYnVmbGVuLCBvcGFsX3NlbmRfY2Jf Y29udCwgZGV2KTsKKwllbHNlCisJCV9vcGFsX3JlY3ZfY21kKGRldi0+YmRldiwgZGV2LT5jb21J RCwgYnVmZmVyLCBidWZsZW4sCisJCQkgICAgICAgb3BhbF9zZW5kX2NiX2NvbnQsIGRldik7Cit9 CisKK3N0YXRpYyBpbnQgb3BhbF9zZW5kX3JlY3Yoc3RydWN0IG9wYWxfZGV2ICpkZXYsIHNlY19j YiAqY2IsIHZvaWQgKmNiX2RhdGEpCit7CisJc2l6ZV90IGJ1ZmxlbiA9IElPX0JVRkZFUl9MRU5H VEg7CisJdm9pZCAqYnVmZmVyID0gZGV2LT5jbWQuY21kOworCWludCByZXQ7CisKKwlkZXYtPmNt ZC5jYiA9IGNiOworCWRldi0+Y21kLmNiX2RhdGEgPSBjYl9kYXRhOworCWlmIChkZXYtPnJlc3Vt ZV9mcm9tX3N1c3BlbmQpCisJCXJldCA9IF9fb3BhbF9zZW5kX2NtZChkZXYtPnJlc3VtZV9kYXRh LCBkZXYtPmNvbUlELCBidWZmZXIsCisJCQkJICAgICAgYnVmbGVuLCBvcGFsX3NlbmRfY2IsIGRl dik7CisJZWxzZQorCQlyZXQgPSBfb3BhbF9zZW5kX2NtZChkZXYtPmJkZXYsIGRldi0+Y29tSUQs IGJ1ZmZlciwgYnVmbGVuLAorCQkJCSAgICAgb3BhbF9zZW5kX2NiLCBkZXYpOworCisJcmV0dXJu IHJldDsKK30KKworc3RhdGljIHZvaWQgY2hlY2tfZ2VvbWV0cnkoc3RydWN0IG9wYWxfZGV2ICpk 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 KwkJCWJyZWFrOworCQlkZWZhdWx0OgorCQkJaWYgKGJlMTZfdG9fY3B1KGJvZHktPmNvZGUpID4g MHhiZmZmKSB7CisJCQkJLyogdmVuZG9yIHNwZWNpZmljLCBqdXN0IGlnbm9yZSAqLworCQkJfSBl bHNlIHsKKwkJCQlwcl93YXJuKCIlczogT1BBTCBVbmtub3duIGZlYXR1cmU6ICVkXG4iLAorCQkJ CQlkZXYtPmRpc2tfbmFtZSwgYmUxNl90b19jcHUoYm9keS0+Y29kZSkpOworCQkJfQorCQl9CisJ CWNwb3MgKz0gYm9keS0+bGVuZ3RoICsgNDsKKwl9CisKKwlpZiAoIXN1cHBvcnRlZCkgeworCQlw cl9lcnIoIiVzOiBEZXZpY2Ugbm90IHN1cHBvcnRlZFxuIiwgZGV2LT5kaXNrX25hbWUpOworCQln b3RvIGVycl9jYWxsYmFjazsKKwl9CisKKwlpZiAoIXNpbmdsZV91c2VyKQorCQlwcl93YXJuKCIl czogRGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCBzaW5nbGUgdXNlciBtb2RlXG4iLAorCQkJZGV2LT5k aXNrX25hbWUpOworCisJaWYgKCFmb3VuZENvbUlEKSB7CisJCXByX3dhcm4oIiVzOiBDb3VsZCBu b3QgZmluZCBPUEFMIGNvbUlEIGZvciBkZXZpY2UuIE9QQUwga2VybmVsIHVubG9ja2luZyB3aWxs IGJlIGRpc2FibGVkXG4iLAorCQkJZGV2LT5kaXNrX25hbWUpOworCQlnb3RvIGVycl9jYWxsYmFj azsKKwl9CisKKwlkZXYtPmNvbUlEID0gY29tSUQ7CisKK2Vycl9jYWxsYmFjazoKKwlpZiAoZGV2 LT5vcGVyX2NiKQorCQlkZXYtPm9wZXJfY2IoZXJyb3IsIGRldik7Cit9CisKK3N0YXRpYyBpbnQg b3BhbF9kaXNjb3ZlcnkwKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCW1lbXNldChkZXYtPmNt ZC5yZXNwLCAwLCBJT19CVUZGRVJfTEVOR1RIKTsKKworCWlmIChkZXYtPnJlc3VtZV9mcm9tX3N1 c3BlbmQpCisJCXJldHVybiBfX29wYWxfcmVjdl9jbWQoZGV2LT5yZXN1bWVfZGF0YSwgMHgwMDAx LAorCQkJCSAgICAgICBkZXYtPmNtZC5yZXNwLCBJT19CVUZGRVJfTEVOR1RILAorCQkJCSAgICAg ICBvcGFsX2Rpc2NvdmVyeTBfZW5kLCBkZXYpOworCisJcmV0dXJuIF9vcGFsX3JlY3ZfY21kKGRl di0+YmRldiwgMHgwMDAxLCBkZXYtPmNtZC5yZXNwLAorCQkJICAgICAgSU9fQlVGRkVSX0xFTkdU SCwgb3BhbF9kaXNjb3ZlcnkwX2VuZCwKKwkJCSAgICAgIGRldik7Cit9CisKK3N0YXRpYyB2b2lk IGFkZF90b2tlbl91OChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTggdG9rKQoreworCWNtZC0+Y21k W2NtZC0+cG9zKytdID0gdG9rOworfQorCitzdGF0aWMgc3NpemVfdCB0ZXN0X2FuZF9hZGRfdG9r ZW5fdTgoc3RydWN0IG9wYWxfY21kICpjbWQsIHU4IHRvaykKK3sKKwlCVUlMRF9CVUdfT04oSU9f QlVGRkVSX0xFTkdUSCA+PSBTSVpFX01BWCk7CisKKwlpZiAoY21kLT5wb3MgPj0gSU9fQlVGRkVS X0xFTkdUSCAtIDEpIHsKKwkJcHJfZXJyKCJFcnJvciBhZGRpbmcgdTg6IGVuZCBvZiBidWZmZXIu XG4iKTsKKwkJcmV0dXJuIC1FUkFOR0U7CisJfQorCisJYWRkX3Rva2VuX3U4KGNtZCwgdG9rKTsK KworCXJldHVybiAxOworfQorCisjZGVmaW5lIFRJTllfQVRPTV9EQVRBX01BU0sgR0VOTUFTSyg1 LCAwKQorI2RlZmluZSBUSU5ZX0FUT01fU0lHTkVEIEJJVCg2KQorCisjZGVmaW5lIFNIT1JUX0FU T01fSUQgQklUKDcpCisjZGVmaW5lIFNIT1JUX0FUT01fQllURVNUUklORyBCSVQoNSkKKyNkZWZp bmUgU0hPUlRfQVRPTV9TSUdORUQgQklUKDQpCisjZGVmaW5lIFNIT1JUX0FUT01fTEVOX01BU0sg R0VOTUFTSygzLCAwKQorCitzdGF0aWMgdm9pZCBhZGRfc2hvcnRfYXRvbV9oZWFkZXIoc3RydWN0 IG9wYWxfY21kICpjbWQsIGJvb2wgYnl0ZXN0cmluZywKKwkJCQkgIGJvb2wgaGFzX3NpZ24sIGlu dCBsZW4pCit7CisJdTggYXRvbTsKKworCWF0b20gPSBTSE9SVF9BVE9NX0lEOworCWF0b20gfD0g Ynl0ZXN0cmluZyA/IFNIT1JUX0FUT01fQllURVNUUklORyA6IDA7CisJYXRvbSB8PSBoYXNfc2ln biA/IFNIT1JUX0FUT01fU0lHTkVEIDogMDsKKwlhdG9tIHw9IGxlbiAmIFNIT1JUX0FUT01fTEVO X01BU0s7CisKKwlhZGRfdG9rZW5fdTgoY21kLCBhdG9tKTsKK30KKworI2RlZmluZSBNRURJVU1f QVRPTV9JRCAoQklUKDcpIHwgQklUKDYpKQorI2RlZmluZSBNRURJVU1fQVRPTV9CWVRFU1RSSU5H IEJJVCg0KQorI2RlZmluZSBNRURJVU1fQVRPTV9TSUdORUQgQklUKDMpCisjZGVmaW5lIE1FRElV TV9BVE9NX0xFTl9NQVNLIEdFTk1BU0soMiwgMCkKKworc3RhdGljIHZvaWQgYWRkX21lZGl1bV9h dG9tX2hlYWRlcihzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgYm9vbCBieXRlc3RyaW5nLAorCQkJCSAg IGJvb2wgaGFzX3NpZ24sIGludCBsZW4pCit7CisJdTggaGVhZGVyMDsKKworCWhlYWRlcjAgPSBN RURJVU1fQVRPTV9JRDsKKwloZWFkZXIwIHw9IGJ5dGVzdHJpbmcgPyBNRURJVU1fQVRPTV9CWVRF U1RSSU5HIDogMDsKKwloZWFkZXIwIHw9IGhhc19zaWduID8gTUVESVVNX0FUT01fU0lHTkVEIDog MDsKKwloZWFkZXIwIHw9IChsZW4gPj4gOCkgJiBNRURJVU1fQVRPTV9MRU5fTUFTSzsKKwljbWQt PmNtZFtjbWQtPnBvcysrXSA9IGhlYWRlcjA7CisJY21kLT5jbWRbY21kLT5wb3MrK10gPSBsZW47 Cit9CisKK3N0YXRpYyB2b2lkIGFkZF90b2tlbl91NjQoc3RydWN0IG9wYWxfY21kICpjbWQsIHU2 NCBudW1iZXIsIHNpemVfdCBsZW4pCit7CisJYWRkX3Nob3J0X2F0b21faGVhZGVyKGNtZCwgZmFs c2UsIGZhbHNlLCBsZW4pOworCisJd2hpbGUgKGxlbi0tKSB7CisJCXU4IG4gPSBudW1iZXIgPj4g KGxlbiAqIDgpOworCisJCWFkZF90b2tlbl91OChjbWQsIG4pOworCX0KK30KKworc3RhdGljIHNz aXplX3QgdGVzdF9hbmRfYWRkX3Rva2VuX3U2NChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTY0IG51 bWJlcikKK3sKKwlpbnQgbGVuOworCWludCBtc2I7CisKKwlpZiAoIShudW1iZXIgJiB+VElOWV9B VE9NX0RBVEFfTUFTSykpCisJCXJldHVybiB0ZXN0X2FuZF9hZGRfdG9rZW5fdTgoY21kLCBudW1i ZXIpOworCisJbXNiID0gZmxzKG51bWJlcik7CisJbGVuID0gRElWX1JPVU5EX1VQKG1zYiwgNCk7 CisKKwlpZiAoY21kLT5wb3MgPj0gSU9fQlVGRkVSX0xFTkdUSCAtIGxlbiAtIDEpIHsKKwkJcHJf ZXJyKCJFcnJvciBhZGRpbmcgdTY0OiBlbmQgb2YgYnVmZmVyLlxuIik7CisJCXJldHVybiAtRVJB TkdFOworCX0KKworCWFkZF90b2tlbl91NjQoY21kLCBudW1iZXIsIGxlbik7CisKKwkvKiByZXR1 cm4gbGVuZ3RoIG9mIHRva2VuIHBsdXMgYXRvbSAqLworCXJldHVybiBsZW4gKyAxOworfQorCitz dGF0aWMgdm9pZCBhZGRfdG9rZW5fYnl0ZXN0cmluZyhzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwKKwkJ CQkgY29uc3QgdTggKmJ5dGVzdHJpbmcsIHNpemVfdCBsZW4pCit7CisJbWVtY3B5KCZjbWQtPmNt ZFtjbWQtPnBvc10sIGJ5dGVzdHJpbmcsIGxlbik7CisJY21kLT5wb3MgKz0gbGVuOworfQorCitz dGF0aWMgc3NpemVfdCB0ZXN0X2FuZF9hZGRfdG9rZW5fYnl0ZXN0cmluZyhzdHJ1Y3Qgb3BhbF9j bWQgKmNtZCwKKwkJCQkJICAgICBjb25zdCB1OCAqYnl0ZXN0cmluZywgc2l6ZV90IGxlbikKK3sK KwlzaXplX3QgaGVhZGVyX2xlbiA9IDE7CisJYm9vbCBpc19zaG9ydF9hdG9tID0gdHJ1ZTsKKwor CWlmIChsZW4gJiB+U0hPUlRfQVRPTV9MRU5fTUFTSykgeworCQloZWFkZXJfbGVuID0gMjsKKwkJ aXNfc2hvcnRfYXRvbSA9IGZhbHNlOworCX0KKworCWlmIChjbWQtPnBvcyA+PSBJT19CVUZGRVJf TEVOR1RIIC0gbGVuIC0gaGVhZGVyX2xlbikgeworCQlwcl9lcnIoIkVycm9yIGFkZGluZyBieXRl c3RyaW5nOiBlbmQgb2YgYnVmZmVyLlxuIik7CisJCXJldHVybiAtRVJBTkdFOworCX0KKworCWlm IChpc19zaG9ydF9hdG9tKQorCQlhZGRfc2hvcnRfYXRvbV9oZWFkZXIoY21kLCB0cnVlLCBmYWxz ZSwgbGVuKTsKKwllbHNlCisJCWFkZF9tZWRpdW1fYXRvbV9oZWFkZXIoY21kLCB0cnVlLCBmYWxz ZSwgbGVuKTsKKworCWFkZF90b2tlbl9ieXRlc3RyaW5nKGNtZCwgYnl0ZXN0cmluZywgbGVuKTsK KworCXJldHVybiBoZWFkZXJfbGVuICsgbGVuOworfQorCisjZGVmaW5lIExPQ0tJTkdfUkFOR0Vf Tk9OX0dMT0JBTCAweDAzCisKK3N0YXRpYyBpbnQgYnVpbGRfbG9ja2luZ19yYW5nZSh1OCAqYnVm ZmVyLCBzaXplX3QgbGVuZ3RoLCB1OCBscikKK3sKKwlpZiAobGVuZ3RoIDwgT1BBTF9VSURfTEVO R1RIKQorCQlyZXR1cm4gLUVSQU5HRTsKKworCW1lbWNweShidWZmZXIsIE9QQUxVSURbT1BBTF9M T0NLSU5HUkFOR0VfR0xPQkFMXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCWlmIChsciA9PSAwKQor CQlyZXR1cm4gMDsKKwlidWZmZXJbNV0gPSBMT0NLSU5HX1JBTkdFX05PTl9HTE9CQUw7CisJYnVm ZmVyWzddID0gbHI7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBidWlsZF9sb2NraW5n X3VzZXIodTggKmJ1ZmZlciwgc2l6ZV90IGxlbmd0aCwgdTggbHIpCit7CisJaWYgKGxlbmd0aCA8 IE9QQUxfVUlEX0xFTkdUSCkKKwkJcmV0dXJuIC1FUkFOR0U7CisKKwltZW1jcHkoYnVmZmVyLCBP UEFMVUlEW09QQUxfVVNFUjFfVUlEXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCWJ1ZmZlcls3XSA9 IGxyICsgMTsKKworCXJldHVybiAwOworfQorCisvKgorICogTiA9IG51bWJlciBvZiBmb3JtYXQg c3BlY2lmaWVycyAoMS05OTkpIHRvIGJlIHJlcGxpY2F0ZWQKKyAqIGMgPSB1OAorICogdSA9IHU2 NAorICogcyA9IGJ5dGVzdHJpbmcsIGxlbmd0aAorICoKKyAqIHJldCA9IHRlc3RfYW5kX2FkZF90 b2tlbl92YShjbWQsICJjIiwKKyAqCQkJICAgICAgIHU4X3ZhbDEpOworICoKKyAqIHJldCA9IHRl c3RfYW5kX2FkZF90b2tlbl92YShjbWQsICIyYzJ1IiwKKyAqCQkJICAgICAgIHU4X3ZhbDEsIHU4 X3ZhbDIsIHU2NF92YWwxLCB1NjRfdmFsMik7CisgKgorICogcmV0ID0gdGVzdF9hbmRfYWRkX3Rv a2VuX3ZhKGNtZCwgIjNzIiwKKyAqCQkJICAgICAgIGJ5dGVzdHJpbmcxLCBsZW5ndGgxLAorICoJ CQkgICAgICAgYnl0ZXN0cmluZzIsIGxlbmd0aDIsCisgKgkJCSAgICAgICBieXRlc3RyaW5nMywg bGVuZ3RoMyk7CisgKi8KK3N0YXRpYyBpbnQgdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKHN0cnVjdCBv cGFsX2NtZCAqY21kLAorCQkJCSBjb25zdCBjaGFyICpmbXQsIC4uLikKK3sKKwljb25zdCB1OCAq aXQgPSBmbXQsICp0bXA7CisJaW50IHJldCwgbnVtID0gMSwgc3VtID0gMDsKKwl2YV9saXN0IGFw OworCisJdmFfc3RhcnQoYXAsIGZtdCk7CisKKwl3aGlsZSAoKml0ICE9ICdcMCcpIHsKKwkJdTY0 IHRvazY0ID0gMDsKKwkJdTggdG9rLCAqYnN0cjsKKwkJc2l6ZV90IGxlbjsKKworCQlyZXQgPSAw OworCisJCXN3aXRjaCAoKml0KSB7CisJCWNhc2UgJzEnIC4uLiAnOSc6CisJCQl0bXAgPSBpdDsK KwkJCW51bSA9IDA7CisJCQl3aGlsZSAoKnRtcCA+PSAnMCcgJiYgKnRtcCA8PSAnOScpCisJCQkJ bnVtID0gbnVtICogMTAgKyAoKnRtcCsrIC0gJzAnKTsKKwkJCWl0ID0gdG1wOworCQkJY29udGlu dWU7CisJCWNhc2UgJ2MnOgorCQkJd2hpbGUgKG51bS0tKSB7CisJCQkJdG9rID0gdmFfYXJnKGFw LCB1bnNpZ25lZCBpbnQpOworCQkJCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl91OChjbWQsIHRv ayk7CisJCQkJaWYgKHJldCA8IDApCisJCQkJCWdvdG8gZXJyOworCQkJfQorCQkJbnVtID0gMTsK KwkJCWJyZWFrOworCQljYXNlICd1JzoKKwkJCXdoaWxlIChudW0tLSkgeworCQkJCXRvazY0ID0g dmFfYXJnKGFwLCB1NjQpOworCQkJCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl91NjQoY21kLCB0 b2s2NCk7CisJCQkJaWYgKHJldCA8IDApCisJCQkJCWdvdG8gZXJyOworCQkJfQorCQkJbnVtID0g MTsKKwkJCWJyZWFrOworCQljYXNlICdzJzoKKwkJCXdoaWxlIChudW0tLSkgeworCQkJCWJzdHIg PSB2YV9hcmcoYXAsIHU4ICopOworCQkJCWxlbiA9IHZhX2FyZyhhcCwgc2l6ZV90KTsKKwkJCQly ZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fYnl0ZXN0cmluZyhjbWQsIGJzdHIsCisJCQkJCQkJCSAg ICBsZW4pOworCQkJCWlmIChyZXQgPCAwKQorCQkJCQlnb3RvIGVycjsKKwkJCX0KKwkJCW51bSA9 IDE7CisJCQlicmVhazsKKwkJY2FzZSAnICc6CisJCWNhc2UgJ1x0JzoKKwkJCS8qIGlnbm9yZWQg Ki8KKwkJCWJyZWFrOworCQlkZWZhdWx0OgorCQkJcHJfd2FybigiVW5yZWNvZ25pemVkIHR5cGUu XG4iKTsKKwkJfQorCisJCWl0Kys7CisJCXN1bSArPSByZXQ7CisJfQorCisJdmFfZW5kKGFwKTsK KworCXJldHVybiBzdW07CisKKyBlcnI6CisJcHJfZXJyKCJUb2tlbiBmYWlsZWQgdG8gYmUgYWRk ZWQuXG4iKTsKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgdm9pZCBzZXRfY29tSUQoc3RydWN0 IG9wYWxfY21kICpjbWQsIHUxNiBjb21JRCkKK3sKKwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9 IChzdHJ1Y3Qgb3BhbF9oZWFkZXIgKiljbWQtPmNtZDsKKworCWhkci0+Y3AuZXh0ZW5kZWRDb21J RFswXSA9IGNvbUlEID4+IDg7CisJaGRyLT5jcC5leHRlbmRlZENvbUlEWzFdID0gY29tSUQ7CisJ aGRyLT5jcC5leHRlbmRlZENvbUlEWzJdID0gMDsKKwloZHItPmNwLmV4dGVuZGVkQ29tSURbM10g PSAwOworfQorCitzdGF0aWMgaW50IGNtZF9maW5hbGl6ZShzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwg dTMyIGhzbiwgdTMyIHRzbikKK3sKKwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkcjsKKwlpbnQgcmV0 OworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgIjZjIiwKKwkJCQkgICAgT1BB TF9FTkRPRkRBVEEsIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICAwLCAwLCAwLCBPUEFMX0VORExJ U1QpOworCisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCJFcnJvciBmaW5hbGl6aW5nIGNvbW1h bmQuXG4iKTsKKwkJcmV0dXJuIC1FRkFVTFQ7CisJfQorCisJaGRyID0gKHN0cnVjdCBvcGFsX2hl YWRlciAqKSBjbWQtPmNtZDsKKworCWhkci0+cGt0LlRTTiA9IGNwdV90b19iZTMyKHRzbik7CisJ aGRyLT5wa3QuSFNOID0gY3B1X3RvX2JlMzIoaHNuKTsKKworCWhkci0+c3VicGt0Lmxlbmd0aCA9 IGNwdV90b19iZTMyKGNtZC0+cG9zIC0gc2l6ZW9mKCpoZHIpKTsKKwl3aGlsZSAoY21kLT5wb3Mg JSA0KSB7CisJCWlmIChjbWQtPnBvcyA+PSBJT19CVUZGRVJfTEVOR1RIKSB7CisJCQlwcl9lcnIo IkVycm9yOiBCdWZmZXIgb3ZlcnJ1blxuIik7CisJCQlyZXR1cm4gLUVSQU5HRTsKKwkJfQorCQlj bWQtPmNtZFtjbWQtPnBvcysrXSA9IDA7CisJfQorCWhkci0+cGt0Lmxlbmd0aCA9IGNwdV90b19i ZTMyKGNtZC0+cG9zIC0gc2l6ZW9mKGhkci0+Y3ApIC0KKwkJCQkgICAgICBzaXplb2YoaGRyLT5w a3QpKTsKKwloZHItPmNwLmxlbmd0aCA9IGNwdV90b19iZTMyKGNtZC0+cG9zIC0gc2l6ZW9mKGhk ci0+Y3ApKTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgZW51bSBPUEFMX1JFU1BPTlNFX1RP S0VOIHRva2VuX3R5cGUoY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLAorCQkJCQkgICBp bnQgbikKK3sKKwljb25zdCBzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rOworCisJaWYgKG4gPj0g cmVzcC0+bnVtKSB7CisJCXByX2VycigiVG9rZW4gbnVtYmVyIGRvZXNuJ3QgZXhpc3Q6ICVkLCBy ZXNwOiAlZFxuIiwKKwkJICAgICAgIG4sIHJlc3AtPm51bSk7CisJCXJldHVybiBPUEFMX0RUQV9U T0tFTklEX0lOVkFMSUQ7CisJfQorCisJdG9rID0gJnJlc3AtPnRva3Nbbl07CisJaWYgKHRvay0+ bGVuID09IDApIHsKKwkJcHJfZXJyKCJUb2tlbiBsZW5ndGggbXVzdCBiZSBub24temVyb1xuIik7 CisJCXJldHVybiBPUEFMX0RUQV9UT0tFTklEX0lOVkFMSUQ7CisJfQorCisJcmV0dXJuIHRvay0+ dHlwZTsKK30KKworLyoKKyAqIFRoaXMgZnVuY3Rpb24gcmV0dXJucyAwIGluIGNhc2Ugb2YgaW52 YWxpZCB0b2tlbi4gT25lIHNob3VsZCBjYWxsCisgKiB0b2tlbl90eXBlKCkgZmlyc3QgdG8gZmlu ZCBvdXQgaWYgdGhlIHRva2VuIGlzIHZhbGlkIG9yIG5vdC4KKyAqLworc3RhdGljIGVudW0gT1BB TF9UT0tFTiByZXNwb25zZV9nZXRfdG9rZW4oY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNw LAorCQkJCQkgIGludCBuKQoreworCWNvbnN0IHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2s7CisK KwlpZiAobiA+PSByZXNwLT5udW0pIHsKKwkJcHJfZXJyKCJUb2tlbiBudW1iZXIgZG9lc24ndCBl eGlzdDogJWQsIHJlc3A6ICVkXG4iLAorCQkgICAgICAgbiwgcmVzcC0+bnVtKTsKKwkJcmV0dXJu IDA7CisJfQorCisJdG9rID0gJnJlc3AtPnRva3Nbbl07CisJaWYgKHRvay0+bGVuID09IDApIHsK KwkJcHJfZXJyKCJUb2tlbiBsZW5ndGggbXVzdCBiZSBub24temVyb1xuIik7CisJCXJldHVybiAw OworCX0KKworCXJldHVybiB0b2stPnBvc1swXTsKK30KKworc3RhdGljIHNpemVfdCByZXNwb25z ZV9wYXJzZV90aW55KHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2ssCisJCQkJICBjb25zdCB1OCAq cG9zKQoreworCXRvay0+cG9zID0gcG9zOworCXRvay0+bGVuID0gMTsKKwl0b2stPndpZHRoID0g T1BBTF9XSURUSF9USU5ZOworCisJaWYgKHBvc1swXSAmIFRJTllfQVRPTV9TSUdORUQpIHsKKwkJ dG9rLT50eXBlID0gT1BBTF9EVEFfVE9LRU5JRF9TSU5UOworCX0gZWxzZSB7CisJCXRvay0+dHlw ZSA9IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKKwkJdG9rLT5zdG9yZWQudSA9IHBvc1swXSAmIDB4 M2Y7CisJfQorCisJcmV0dXJuIHRvay0+bGVuOworfQorCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNl X3BhcnNlX3Nob3J0KHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2ssCisJCQkJICAgY29uc3QgdTgg KnBvcykKK3sKKwl0b2stPnBvcyA9IHBvczsKKwl0b2stPmxlbiA9IChwb3NbMF0gJiBTSE9SVF9B VE9NX0xFTl9NQVNLKSArIDE7CisJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhfU0hPUlQ7CisKKwlp ZiAocG9zWzBdICYgU0hPUlRfQVRPTV9CWVRFU1RSSU5HKSB7CisJCXRvay0+dHlwZSA9IE9QQUxf RFRBX1RPS0VOSURfQllURVNUUklORzsKKwl9IGVsc2UgaWYgKHBvc1swXSAmIFNIT1JUX0FUT01f U0lHTkVEKSB7CisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfU0lOVDsKKwl9IGVsc2Ug eworCQl1NjQgdV9pbnRlZ2VyID0gMDsKKwkJaW50IGksIGIgPSAwOworCisJCXRvay0+dHlwZSA9 IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKKwkJaWYgKHRvay0+bGVuID4gOSkKKwkJCXByX3dhcm4o InVpbnQ2NCB3aXRoIG1vcmUgdGhhbiA4IGJ5dGVzXG4iKTsKKwkJZm9yIChpID0gdG9rLT5sZW4g LSAxOyBpID4gMDsgaS0tKSB7CisJCQl1X2ludGVnZXIgfD0gKCh1NjQpcG9zW2ldIDw8ICg4ICog YikpOworCQkJYisrOworCQl9CisJCXRvay0+c3RvcmVkLnUgPSB1X2ludGVnZXI7CisJfQorCisJ cmV0dXJuIHRvay0+bGVuOworfQorCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX3BhcnNlX21lZGl1 bShzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rLAorCQkJCSAgICBjb25zdCB1OCAqcG9zKQorewor CXRvay0+cG9zID0gcG9zOworCXRvay0+bGVuID0gKCgocG9zWzBdICYgTUVESVVNX0FUT01fTEVO X01BU0spIDw8IDgpIHwgcG9zWzFdKSArIDI7CisJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhfTUVE SVVNOworCisJaWYgKHBvc1swXSAmIE1FRElVTV9BVE9NX0JZVEVTVFJJTkcpCisJCXRvay0+dHlw ZSA9IE9QQUxfRFRBX1RPS0VOSURfQllURVNUUklORzsKKwllbHNlIGlmIChwb3NbMF0gJiBNRURJ VU1fQVRPTV9TSUdORUQpCisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfU0lOVDsKKwll bHNlCisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKKworCXJldHVybiB0b2st PmxlbjsKK30KKworI2RlZmluZSBMT05HX0FUT01fSUQgKEJJVCg3KSB8IEJJVCg2KSB8IEJJVCg1 KSkKKyNkZWZpbmUgTE9OR19BVE9NX0JZVEVTVFJJTkcgQklUKDEpCisjZGVmaW5lIExPTkdfQVRP TV9TSUdORUQgQklUKDApCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX3BhcnNlX2xvbmcoc3RydWN0 IG9wYWxfcmVzcF90b2sgKnRvaywKKwkJCQkgIGNvbnN0IHU4ICpwb3MpCit7CisJdG9rLT5wb3Mg PSBwb3M7CisJdG9rLT5sZW4gPSAoKHBvc1sxXSA8PCAxNikgfCAocG9zWzJdIDw8IDgpIHwgcG9z WzNdKSArIDQ7CisJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhfTE9ORzsKKworCWlmIChwb3NbMF0g JiBMT05HX0FUT01fQllURVNUUklORykKKwkJdG9rLT50eXBlID0gT1BBTF9EVEFfVE9LRU5JRF9C WVRFU1RSSU5HOworCWVsc2UgaWYgKHBvc1swXSAmIExPTkdfQVRPTV9TSUdORUQpCisJCXRvay0+ dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfU0lOVDsKKwllbHNlCisJCXRvay0+dHlwZSA9IE9QQUxf RFRBX1RPS0VOSURfVUlOVDsKKworCXJldHVybiB0b2stPmxlbjsKK30KKworc3RhdGljIHNpemVf dCByZXNwb25zZV9wYXJzZV90b2tlbihzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rLAorCQkJCSAg IGNvbnN0IHU4ICpwb3MpCit7CisJdG9rLT5wb3MgPSBwb3M7CisJdG9rLT5sZW4gPSAxOworCXRv ay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfVE9LRU47CisJdG9rLT53aWR0aCA9IE9QQUxfV0lE VEhfVE9LRU47CisKKwlyZXR1cm4gdG9rLT5sZW47Cit9CisKK3N0YXRpYyBpbnQgcmVzcG9uc2Vf cGFyc2UoY29uc3QgdTggKmJ1Ziwgc2l6ZV90IGxlbmd0aCwKKwkJCSAgc3RydWN0IHBhcnNlZF9y ZXNwICpyZXNwKQoreworCWNvbnN0IHN0cnVjdCBvcGFsX2hlYWRlciAqaGRyOworCXN0cnVjdCBv cGFsX3Jlc3BfdG9rICppdGVyOworCWludCByZXQsIG51bV9lbnRyaWVzID0gMDsKKwl1MzIgY3Bv cyA9IDAsIHRvdGFsOworCXNpemVfdCB0b2tlbl9sZW5ndGg7CisJY29uc3QgdTggKnBvczsKKwor CWlmICghYnVmKQorCQlyZXR1cm4gLUVGQVVMVDsKKworCWlmICghcmVzcCkKKwkJcmV0dXJuIC1F RkFVTFQ7CisKKwloZHIgPSAoc3RydWN0IG9wYWxfaGVhZGVyICopYnVmOworCXBvcyA9IGJ1ZjsK Kwlwb3MgKz0gc2l6ZW9mKCpoZHIpOworCisJcHJfZGVidWcoIlJlc3BvbnNlIHNpemU6IGNwOiAl ZCwgcGt0OiAlZCwgc3VicGt0OiAlZFxuIiwKKwkJIGJlMzJfdG9fY3B1KGhkci0+Y3AubGVuZ3Ro KSwKKwkJIGJlMzJfdG9fY3B1KGhkci0+cGt0Lmxlbmd0aCksCisJCSBiZTMyX3RvX2NwdShoZHIt PnN1YnBrdC5sZW5ndGgpKTsKKworCWlmICgoaGRyLT5jcC5sZW5ndGggPT0gMCkKKwkgICAgfHwg KGhkci0+cGt0Lmxlbmd0aCA9PSAwKQorCSAgICB8fCAoaGRyLT5zdWJwa3QubGVuZ3RoID09IDAp KSB7CisJCXByX2VycigiQmFkIGhlYWRlciBsZW5ndGguIGNwOiAlZCwgcGt0OiAlZCwgc3VicGt0 OiAlZFxuIiwKKwkJICAgICAgIGJlMzJfdG9fY3B1KGhkci0+Y3AubGVuZ3RoKSwKKwkJICAgICAg IGJlMzJfdG9fY3B1KGhkci0+cGt0Lmxlbmd0aCksCisJCSAgICAgICBiZTMyX3RvX2NwdShoZHIt PnN1YnBrdC5sZW5ndGgpKTsKKwkJcHJpbnRfYnVmZmVyKHBvcywgc2l6ZW9mKCpoZHIpKTsKKwkJ cmV0ID0gLUVJTlZBTDsKKwkJZ290byBlcnI7CisJfQorCisJaWYgKHBvcyA+IGJ1ZiArIGxlbmd0 aCkgeworCQlyZXQgPSAtRUZBVUxUOworCQlnb3RvIGVycjsKKwl9CisKKwlpdGVyID0gcmVzcC0+ dG9rczsKKwl0b3RhbCA9IGJlMzJfdG9fY3B1KGhkci0+c3VicGt0Lmxlbmd0aCk7CisJcHJpbnRf YnVmZmVyKHBvcywgdG90YWwpOworCXdoaWxlIChjcG9zIDwgdG90YWwpIHsKKwkJaWYgKCEocG9z WzBdICYgMHg4MCkpIC8qIHRpbnkgYXRvbSAqLworCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2Vf cGFyc2VfdGlueShpdGVyLCBwb3MpOworCQllbHNlIGlmICghKHBvc1swXSAmIDB4NDApKSAvKiBz aG9ydCBhdG9tICovCisJCQl0b2tlbl9sZW5ndGggPSByZXNwb25zZV9wYXJzZV9zaG9ydChpdGVy LCBwb3MpOworCQllbHNlIGlmICghKHBvc1swXSAmIDB4MjApKSAvKiBtZWRpdW0gYXRvbSAqLwor CQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfbWVkaXVtKGl0ZXIsIHBvcyk7CisJCWVs c2UgaWYgKCEocG9zWzBdICYgMHgxMCkpIC8qIGxvbmcgYXRvbSAqLworCQkJdG9rZW5fbGVuZ3Ro ID0gcmVzcG9uc2VfcGFyc2VfbG9uZyhpdGVyLCBwb3MpOworCQllbHNlIC8qIFRPS0VOICovCisJ CQl0b2tlbl9sZW5ndGggPSByZXNwb25zZV9wYXJzZV90b2tlbihpdGVyLCBwb3MpOworCisJCXBv cyArPSB0b2tlbl9sZW5ndGg7CisJCWNwb3MgKz0gdG9rZW5fbGVuZ3RoOworCQlpdGVyKys7CisJ CW51bV9lbnRyaWVzKys7CisJfQorCisJaWYgKG51bV9lbnRyaWVzID09IDApIHsKKwkJcHJfZXJy KCJDb3VsZG4ndCBwYXJzZSByZXNwb25zZS5cbiIpOworCQlyZXQgPSAtRUlOVkFMOworCQlnb3Rv IGVycjsKKwl9CisJcmVzcC0+bnVtID0gbnVtX2VudHJpZXM7CisKKwlyZXR1cm4gMDsKK2VycjoK KwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX2dldF9zdHJpbmcoY29u c3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLCBpbnQgbiwKKwkJCQkgIGNvbnN0IGNoYXIgKipz dG9yZSkKK3sKKwkqc3RvcmUgPSBOVUxMOworCWlmICghcmVzcCkgeworCQlwcl9lcnIoIlJlc3Bv bnNlIGlzIE5VTExcbiIpOworCQlyZXR1cm4gMDsKKwl9CisKKwlpZiAobiA+IHJlc3AtPm51bSkg eworCQlwcl9lcnIoIlJlc3BvbnNlIGhhcyAlZCB0b2tlbnMuIENhbid0IGFjY2VzcyAlZFxuIiwK KwkJICAgICAgIHJlc3AtPm51bSwgbik7CisJCXJldHVybiAwOworCX0KKworCWlmIChyZXNwLT50 b2tzW25dLnR5cGUgIT0gT1BBTF9EVEFfVE9LRU5JRF9CWVRFU1RSSU5HKSB7CisJCXByX2Vycigi VG9rZW4gaXMgbm90IGEgYnl0ZSBzdHJpbmchXG4iKTsKKwkJcmV0dXJuIDA7CisJfQorCisJKnN0 b3JlID0gcmVzcC0+dG9rc1tuXS5wb3MgKyAxOworCXJldHVybiByZXNwLT50b2tzW25dLmxlbiAt IDE7Cit9CisKK3N0YXRpYyB1NjQgcmVzcG9uc2VfZ2V0X3U2NChjb25zdCBzdHJ1Y3QgcGFyc2Vk X3Jlc3AgKnJlc3AsIGludCBuKQoreworCWlmICghcmVzcCkgeworCQlwcl9lcnIoIlJlc3BvbnNl IGlzIE5VTExcbiIpOworCQlyZXR1cm4gMDsKKwl9CisKKwlpZiAobiA+IHJlc3AtPm51bSkgewor CQlwcl9lcnIoIlJlc3BvbnNlIGhhcyAlZCB0b2tlbnMuIENhbid0IGFjY2VzcyAlZFxuIiwKKwkJ ICAgICAgIHJlc3AtPm51bSwgbik7CisJCXJldHVybiAwOworCX0KKworCWlmIChyZXNwLT50b2tz W25dLnR5cGUgIT0gT1BBTF9EVEFfVE9LRU5JRF9VSU5UKSB7CisJCXByX2VycigiVG9rZW4gaXMg bm90IHVuc2lnbmVkIGl0OiAlZFxuIiwKKwkJICAgICAgIHJlc3AtPnRva3Nbbl0udHlwZSk7CisJ CXJldHVybiAwOworCX0KKworCWlmICghKChyZXNwLT50b2tzW25dLndpZHRoID09IE9QQUxfV0lE VEhfVElOWSkgfHwKKwkgICAgICAocmVzcC0+dG9rc1tuXS53aWR0aCA9PSBPUEFMX1dJRFRIX1NI T1JUKSkpIHsKKwkJcHJfZXJyKCJBdG9tIGlzIG5vdCBzaG9ydCBvciB0aW55OiAlZFxuIiwKKwkJ ICAgICAgIHJlc3AtPnRva3Nbbl0ud2lkdGgpOworCQlyZXR1cm4gMDsKKwl9CisKKwlyZXR1cm4g cmVzcC0+dG9rc1tuXS5zdG9yZWQudTsKK30KKworc3RhdGljIHU4IHJlc3BvbnNlX3N0YXR1cyhj b25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJlc3ApCit7CisJaWYgKCh0b2tlbl90eXBlKHJlc3As IDApID09IE9QQUxfRFRBX1RPS0VOSURfVE9LRU4pCisJICAgICYmIChyZXNwb25zZV9nZXRfdG9r ZW4ocmVzcCwgMCkgPT0gT1BBTF9FTkRPRlNFU1NJT04pKSB7CisJCXJldHVybiAwOworCX0KKwor CWlmIChyZXNwLT5udW0gPCA1KQorCQlyZXR1cm4gRFRBRVJST1JfTk9fTUVUSE9EX1NUQVRVUzsK KworCWlmICgodG9rZW5fdHlwZShyZXNwLCByZXNwLT5udW0gLSAxKSAhPSBPUEFMX0RUQV9UT0tF TklEX1RPS0VOKSB8fAorCSAgICAodG9rZW5fdHlwZShyZXNwLCByZXNwLT5udW0gLSA1KSAhPSBP UEFMX0RUQV9UT0tFTklEX1RPS0VOKSB8fAorCSAgICAocmVzcG9uc2VfZ2V0X3Rva2VuKHJlc3As IHJlc3AtPm51bSAtIDEpICE9IE9QQUxfRU5ETElTVCkgfHwKKwkgICAgKHJlc3BvbnNlX2dldF90 b2tlbihyZXNwLCByZXNwLT5udW0gLSA1KSAhPSBPUEFMX1NUQVJUTElTVCkpCisJCXJldHVybiBE VEFFUlJPUl9OT19NRVRIT0RfU1RBVFVTOworCisJcmV0dXJuIHJlc3BvbnNlX2dldF91NjQocmVz cCwgcmVzcC0+bnVtIC0gNCk7Cit9CisKKy8qIFBhcnNlcyBhbmQgY2hlY2tzIGZvciBlcnJvcnMg Ki8KK3N0YXRpYyBpbnQgcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhzdHJ1Y3Qgb3BhbF9kZXYgKmRl dikKK3sKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgZXJyb3I7CisKKwljbWQgPSAmZGV2 LT5jbWQ7CisJcHJpbnRfYnVmZmVyKGNtZC0+Y21kLCBjbWQtPnBvcyk7CisKKwllcnJvciA9IHJl c3BvbnNlX3BhcnNlKGNtZC0+cmVzcCwgSU9fQlVGRkVSX0xFTkdUSCwgJmRldi0+cGFyc2VkKTsK KwlpZiAoZXJyb3IpIHsKKwkJcHJfZXJyKCIlczogQ291bGRuJ3QgcGFyc2UgcmVzcG9uc2UuXG4i LCBkZXYtPmRpc2tfbmFtZSk7CisJCWdvdG8gZXJyX3JldHVybjsKKwl9CisKKwllcnJvciA9IHJl c3BvbnNlX3N0YXR1cygmZGV2LT5wYXJzZWQpOworCWlmIChlcnJvcikKKwkJcHJfZXJyKCIlczog UmVzcG9uc2UgU3RhdHVzOiAlZFxuIiwgZGV2LT5kaXNrX25hbWUsCisJCSAgICAgICBlcnJvcik7 CisKKyBlcnJfcmV0dXJuOgorCXJldHVybiBlcnJvcjsKK30KKworc3RhdGljIHZvaWQgY2xlYXJf b3BhbF9jbWQoc3RydWN0IG9wYWxfY21kICpjbWQpCit7CisJY21kLT5wb3MgPSBzaXplb2Yoc3Ry dWN0IG9wYWxfaGVhZGVyKTsKKwltZW1zZXQoY21kLT5jbWQsIDAsIElPX0JVRkZFUl9MRU5HVEgp OworCWNtZC0+Y2IgPSBOVUxMOworCWNtZC0+Y2JfZGF0YSA9IE5VTEw7Cit9CisKK3N0YXRpYyB2 b2lkIHN0YXJ0X29wYWxfc2Vzc2lvbl9jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKK3sKKwlz dHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJdTMyIEhTTiwgVFNOOworCisJaWYgKGVycm9y KQorCQlnb3RvIGVycl9yZXR1cm47CisKKwllcnJvciA9IHBhcnNlX2FuZF9jaGVja19zdGF0dXMo ZGV2KTsKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJyX3JldHVybjsKKworCUhTTiA9IHJlc3BvbnNl X2dldF91NjQoJmRldi0+cGFyc2VkLCA0KTsKKwlUU04gPSByZXNwb25zZV9nZXRfdTY0KCZkZXYt PnBhcnNlZCwgNSk7CisKKwlpZiAoSFNOID09IDAgJiYgVFNOID09IDApIHsKKwkJcHJfZXJyKCIl czogQ291bGRuJ3QgYXV0aGVudGljYXRlIHNlc3Npb25cbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJ ZXJyb3IgPSAtRVBFUk07CisJCWdvdG8gZXJyX3JldHVybjsKKwl9CisKKwlkZXYtPkhTTiA9IEhT TjsKKwlkZXYtPlRTTiA9IFRTTjsKKworZXJyX3JldHVybjoKKwlpZiAoZGV2LT5vcGVyX2NiKQor CQlkZXYtPm9wZXJfY2IoZXJyb3IsIGRldik7Cit9CisKK3N0YXRpYyBpbnQgZ2V0X29wYWxfa2V5 KHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXN0cnVjdCBrZXkgKnVrZXkgPSBOVUxMOworCWNv bnN0IHU4ICp0bXBrZXkgPSBOVUxMOworCXNpemVfdCB0bXBsZW47CisJaW50IHJldCA9IDA7CisK KwlpZiAoZGV2LT5rZXlfdHlwZSA9PSBPUEFMX0tFWV9QTEFJTikgeworCQl0bXBrZXkgPSBkZXYt PmtleV9uYW1lOworCQl0bXBsZW4gPSBkZXYtPmtleV9uYW1lX2xlbjsKKwl9IGVsc2UgaWYgKGRl di0+a2V5X3R5cGUgPT0gT1BBTF9LRVlfS0VZUklORykgeworCQl1a2V5ID0gcmVxdWVzdF91c2Vy X2tleShkZXYtPmtleV9uYW1lLCAmdG1wa2V5LCAmdG1wbGVuKTsKKwkJaWYgKElTX0VSUih1a2V5 KSkgeworCQkJcHJfZXJyKCIlczogQ2FuJ3QgcmV0cmlldmUga2V5OiAlbGRcbiIsIGRldi0+ZGlz a19uYW1lLAorCQkJICAgICAgIFBUUl9FUlIodWtleSkpOworCQkJcmV0dXJuIFBUUl9FUlIodWtl eSk7CisJCX0KKwl9IGVsc2UgeworCQlwcl9lcnIoIlJlcXVlc3RlZCBpbnZhbGlkIGtleSB0eXBl OiAlZFxuIiwgZGV2LT5rZXlfdHlwZSk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWlmICh0 bXBsZW4gPiBPUEFMX0tFWV9NQVgpIHsKKwkJcHJfZXJyKCJSZXF1ZXN0ZWQga2V5IHdpdGggaW52 YWxpZCBzaXplOiAlemRcbiIsIHRtcGxlbik7CisJCXJldCA9IC1FSU5WQUw7CisJCWdvdG8gZXJy X2V4aXQ7CisJfQorCisJZGV2LT5rZXlfbGVuID0gdG1wbGVuOworCWlmICghbWVtY3B5KGRldi0+ a2V5LCB0bXBrZXksIHRtcGxlbikpIHsKKwkJcHJfZXJyKCJFcnJvciB3aGVuIGNvcHlpbmcga2V5 Iik7CisJCXJldCA9IC1FRkFVTFQ7CisJCWdvdG8gZXJyX2V4aXQ7CisJfQorCitlcnJfZXhpdDoK KwlrZXlfcHV0KHVrZXkpOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyB2b2lkIGNsZWFuX29w YWxfa2V5KHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCW1lbXNldChkZXYtPmtleSwgMCwgT1BB TF9LRVlfTUFYKTsKKwlkZXYtPmtleV9sZW4gPSAwOworfQorCitzdGF0aWMgaW5saW5lIHZvaWQg Y2xlYW5fZnVuY3Rpb25fZGF0YShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwkJZGV2LT5mdW5j X2RhdGEgPSBOVUxMOworCQlkZXYtPm51bV9mdW5jX2RhdGEgPSAwOworfQorCisvKiBUaGlzIGlz IGEgZ2VuZXJpYyBjb250aW51ZSBmbi4KKyAqIFdlIHVzZSB0aGlzIHdoZW4gd2UgZG9uJ3QgY2Fy ZSBhYm91dCB0aGUgcmVzcG9uc2UgZGF0YQorICogYW5kIHNpbXBseSB3YW50IHRvIGNoZWNrIHRo ZSBzdGF0dXMgYW5kIGNvbnRpbnVlLgorICovCitzdGF0aWMgdm9pZCBnZW5lcmljX2NvbnQoaW50 IGVycm9yLCB2b2lkICpkYXRhKQoreworCXN0cnVjdCBvcGFsX2RldiAqZGV2ID0gZGF0YTsKKwor CWlmIChlcnJvcikKKwkJZ290byBlcnJfcmV0dXJuOworCisJZXJyb3IgPSBwYXJzZV9hbmRfY2hl Y2tfc3RhdHVzKGRldik7CisKKyBlcnJfcmV0dXJuOgorCWlmIChkZXYtPm9wZXJfY2IpCisJCWRl di0+b3Blcl9jYihlcnJvciwgZGV2KTsKK30KKworc3RhdGljIHZvaWQgZW5kX3Nlc3Npb25fY29u dChpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRh OworCisJZGV2LT5IU04gPSAwOworCWRldi0+VFNOID0gMDsKKwlnZW5lcmljX2NvbnQoZXJyb3Is IGRhdGEpOworfQorCitzdGF0aWMgaW50IGZpbmFsaXplX2FuZF9zZW5kKHN0cnVjdCBvcGFsX2Rl diAqZGV2LCBzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwKKwkJCSAgICAgc2VjX2NiIGNvbnQpCit7CisJ aW50IHJldDsKKworCXJldCA9IGNtZF9maW5hbGl6ZShjbWQsIGRldi0+SFNOLCBkZXYtPlRTTik7 CisJaWYgKHJldCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBmaW5hbGl6aW5nIGNvbW1hbmQgYnVm ZmVyOiAlZFxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lLCByZXQpOworCQlyZXR1cm4gcmV0 OworCX0KKworCXByaW50X2J1ZmZlcihjbWQtPmNtZCwgY21kLT5wb3MpOworCisJcmV0ID0gb3Bh bF9zZW5kX3JlY3YoZGV2LCBjb250LCBkZXYpOworCWlmIChyZXQpCisJCXByX2VycigiJXM6IEVy cm9yIHJ1bm5pbmcgY29tbWFuZDogJWRcbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSwgcmV0 KTsKKworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgd2FpdF9mb3JfY21kX2NvbXBsZXRp b24oc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbikKK3sKKwl3YWl0X2Zvcl9jb21w bGV0aW9uX2ludGVycnVwdGlibGUoJmNvbXBsZXRpb24tPmNtZF9jb21wbGV0aW9uKTsKKwlyZXR1 cm4gY29tcGxldGlvbi0+Y29tcGxldGlvbl9zdGF0dXM7Cit9CisKK3N0YXRpYyBpbnQgZ2VuX2tl eShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0aG9kOworCXU4IHVpZFtP UEFMX1VJRF9MRU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwlj bWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBk ZXYtPmNvbUlEKTsKKworCW1lbWNweSh1aWQsIGRldi0+cHJldl9kYXRhLCBtaW4oc2l6ZW9mKHVp ZCksIGRldi0+cHJldl9kX2xlbikpOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRU5LRVld OworCWtmcmVlKGRldi0+cHJldl9kYXRhKTsKKwlkZXYtPnByZXZfZGF0YSA9IE5VTEw7CisKKwly ZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDJjIiwKKwkJCQkgICAgT1BBTF9D QUxMLAorCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFM X01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxf RU5ETElTVCk7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcg Z2VuIGtleSBjb21tYW5kXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4g cmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19j b250KTsKK30KKworc3RhdGljIHZvaWQgZ2V0X2FjdGl2ZV9rZXlfY29udChpbnQgZXJyb3IsIHZv aWQgKmRhdGEpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOworCWNvbnN0IGNoYXIg KmFjdGl2ZWtleTsKKwlzaXplX3Qga2V5bGVuOworCisJaWYgKGVycm9yKQorCQlnb3RvIGVycl9y ZXR1cm47CisKKwllcnJvciA9IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoZGV2KTsKKwlpZiAoZXJy b3IpCisJCWdvdG8gZXJyX3JldHVybjsKKwlrZXlsZW4gPSByZXNwb25zZV9nZXRfc3RyaW5nKCZk ZXYtPnBhcnNlZCwgNCwgJmFjdGl2ZWtleSk7CisJaWYgKCFhY3RpdmVrZXkpIHsKKwkJcHJfZXJy KCIlczogQ291bGRuJ3QgZXh0cmFjdCB0aGUgQWN0aXZla2V5IGZyb20gdGhlIHJlc3BvbnNlXG4i LAorCQkgICAgICAgX19mdW5jX18pOworCQllcnJvciA9IDB4MEE7CisJCWdvdG8gZXJyX3JldHVy bjsKKwl9CisJZGV2LT5wcmV2X2RhdGEgPSBrbWVtZHVwKGFjdGl2ZWtleSwga2V5bGVuLCBHRlBf S0VSTkVMKTsKKworCWlmICghZGV2LT5wcmV2X2RhdGEpCisJCWVycm9yID0gLUVOT01FTTsKKwor CWRldi0+cHJldl9kX2xlbiA9IGtleWxlbjsKKworZXJyX3JldHVybjoKKwlpZiAoZGV2LT5vcGVy X2NiKQorCQlkZXYtPm9wZXJfY2IoZXJyb3IsIGRldik7Cit9CisKK3N0YXRpYyBpbnQgZ2V0X2Fj dGl2ZV9rZXkoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29uc3QgdTggKm1ldGhvZDsKKwl1 OCB1aWRbT1BBTF9VSURfTEVOR1RIXTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0 OworCisJY21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlE KGNtZCwgZGV2LT5jb21JRCk7CisKKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfR0VUXTsKKwor CXJldCA9IGJ1aWxkX2xvY2tpbmdfcmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5scik7CisJ aWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9ja2luZyByYW5nZVxu IiwgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlyZXQgPSB0ZXN0 X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDZjIDRjIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxM LAorCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01F VEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RB UlRMSVNULAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRf MDMsIC8qIHN0YXJ0Q2xvdW1uICovCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzEwLCAvKiBBY3Rp dmVLZXkgKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1F LAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wNCwgLyogZW5kQ29sdW1uICovCisJCQkJICAgIE9Q QUxfVElOWV9VSU5UXzEwLCAvKiBBY3RpdmVLZXkgKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAor CisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKwlpZiAocmV0 IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBnZXQgYWN0aXZlIGtleSBjb21t YW5kXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKwor CXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2V0X2FjdGl2ZV9rZXlfY29udCk7 Cit9CisKK3N0YXRpYyBpbnQgc2V0dXBfbG9ja2luZ19yYW5nZShzdHJ1Y3Qgb3BhbF9kZXYgKmRl dikKK3sKKwljb25zdCB1OCAqbWV0aG9kOworCXU4IHVpZFtPUEFMX1VJRF9MRU5HVEhdOworCXN0 cnVjdCBvcGFsX2NtZCAqY21kOworCXN0cnVjdCBvcGFsX3VzZXJfbHJfc2V0dXAgKnNldHVwOwor CWludCByZXQ7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlz ZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9T RVRdOworCXJldCA9IGJ1aWxkX2xvY2tpbmdfcmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5s cik7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9ja2luZyBy YW5nZVxuIiwgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisJc2V0dXAg PSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRf dG9rZW5fdmEoY21kLCAiYzJzICA0YyAyY3VjIDJjdWMgMmN1YyAyY3UgNGMiLAorCQkJCSAgICBP UEFMX0NBTEwsCisJCQkJICAgIHVpZCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2Qs IE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAg T1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVkFMVUVTLAorCQkJCSAgICBPUEFMX1NUQVJU TElTVCwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRf MDMsIC8qIFJhbmdlIFN0YXJ0ICovCisJCQkJICAgIHNldHVwLT5yYW5nZV9zdGFydCwKKwkJCQkg ICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFM X1RJTllfVUlOVF8wNCwgLyogUmFuZ2UgTGVuZ3RoICovCisJCQkJICAgIHNldHVwLT5yYW5nZV9s ZW5ndGgsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwK KwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDUsIC8qIFJlYWRMb2NrRW5hYmxlZCAqLworCQkJCSAg ICAhIXNldHVwLT5STEUsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKworCQkJCSAgICBPUEFMX1NU QVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIFdyaXRlTG9ja0VuYWJsZWQg Ki8KKwkJCQkgICAgISFzZXR1cC0+V0xFLAorCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkg ICAgT1BBTF9FTkRMSVNULAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5E TElTVCk7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgU2V0 dXAgTG9ja2luZyByYW5nZSBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsK KwkJcmV0dXJuIHJldDsKKworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNt ZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBzdGFydF9hZG1pbnNwX29wYWxfc2Vz c2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldiwKKwkJCQkgICAgICBlbnVtIE9QQUxfVUlEIGF1dGgs CisJCQkJICAgICAgY29uc3QgY2hhciAqa2V5LAorCQkJCSAgICAgIHU4IGtleV9sZW4pCit7CisJ Y29uc3QgdTggKm1ldGhvZCwgKnNtdWlkLCAqYWRtaW5fc3AsICpoc2E7CisJc3RydWN0IG9wYWxf Y21kICpjbWQ7CisJdTMyIEhTTjsKKwlpbnQgcmV0OworCisJaWYgKGtleSA9PSBOVUxMICYmIGF1 dGggIT0gT1BBTF9BTllCT0RZX1VJRCkgeworCQlwcl9lcnIoIiVzOiBBdHRlbXB0ZWQgdG8gb3Bl biBBRE1JTl9TUCBTZXNzaW9uIHdpdGhvdXQgYSBIb3N0IiBcCisJCSAgICAgICAiQ2hhbGxlbmdl LCBhbmQgbm90IGFzIHRoZSBBbnlib2R5IFVJRFxuIiwgX19mdW5jX18pOworCQlyZXR1cm4gMTsK Kwl9CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKworCXNldF9j b21JRChjbWQsIGRldi0+Y29tSUQpOworCUhTTiA9IDB4NDE7CisKKwlzbXVpZCA9IE9QQUxVSURb T1BBTF9TTVVJRF9VSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TVEFSVFNFU1NJT05d OworCWFkbWluX3NwID0gT1BBTFVJRFtPUEFMX0FETUlOU1BfVUlEXTsKKworCXJldCA9IHRlc3Rf YW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgY3VzYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJ CQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhP RF9MRU5HVEgsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBIU04sCisJCQkJICAg IGFkbWluX3NwLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxKTsK KwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBzdGFydCBhZG1p bnNwIHNlc3Npb24gY29tbWFuZC5cbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJl dHVybiByZXQ7CisJfQorCisJc3dpdGNoIChhdXRoKSB7CisJY2FzZSBPUEFMX0FOWUJPRFlfVUlE OgorCQkvKiBub3RoaW5nIGxlZnQgdG8gZG8gZm9yIGFueWJvZHksIGp1c3QgZW5kIGFuZCBmaW5h bGl6ZSAqLworCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYyIsCisJCQkJCSAg ICBPUEFMX0VORExJU1QpOworCQlicmVhazsKKwljYXNlIE9QQUxfU0lEX1VJRDoKKwkJaHNhID0g T1BBTFVJRFtPUEFMX1NJRF9VSURdOworCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21k LCAiMmMgcyAzYyBzIDJjIiwKKwkJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCQkgICAgT1BB TF9USU5ZX1VJTlRfMDAsIC8qIEhvc3RDaGFsbGVuZ2UgKi8KKwkJCQkJICAgIGtleSwga2V5X2xl biwKKwkJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJ CQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIEhvc3RTaWduQXV0aCAqLworCQkJCQkgICAgaHNh LCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJCSAgICBPUEFM X0VORExJU1QpOworCQlicmVhazsKKwlkZWZhdWx0OgorCQlwcl9lcnIoIkNhbm5vdCBzdGFydCBB ZG1pbiBTUCBzZXNzaW9uIHdpdGggYXV0aCAlZFxuIiwgYXV0aCk7CisJCXJldHVybiAxOworCX0K KworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIHN0YXJ0IGFk bWluc3Agc2Vzc2lvbiBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJ cmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0 YXJ0X29wYWxfc2Vzc2lvbl9jb250KTsKK30KKworc3RhdGljIGludCBzdGFydF9hbnlib2R5QVNQ X29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlyZXR1cm4gc3RhcnRfYWRt aW5zcF9vcGFsX3Nlc3Npb24oZGV2LCBPUEFMX0FOWUJPRFlfVUlELCBOVUxMLCAwKTsKK30KKwor c3RhdGljIGludCBzdGFydF9TSURBU1Bfb3BhbF9zZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2 KQoreworCWludCByZXQ7CisJY29uc3QgdTggKmtleSA9IGRldi0+cHJldl9kYXRhOworCisJaWYg KCFrZXkpCisJCXJldCA9IHN0YXJ0X2FkbWluc3Bfb3BhbF9zZXNzaW9uKGRldiwgT1BBTF9TSURf VUlELCBkZXYtPmtleSwKKwkJCQkJCSBkZXYtPmtleV9sZW4pOworCWVsc2UgeworCQlyZXQgPSBz dGFydF9hZG1pbnNwX29wYWxfc2Vzc2lvbihkZXYsIE9QQUxfU0lEX1VJRCwga2V5LAorCQkJCQkJ IGRldi0+cHJldl9kX2xlbik7CisJCWtmcmVlKGtleSk7CisJCWRldi0+cHJldl9kYXRhID0gTlVM TDsKKwl9CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBzdGFydF9sb2NraW5nc3Bfb3Bh bF9zZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2LAorCQkJCQllbnVtIE9QQUxfVUlEIGF1dGgs IGNvbnN0IHU4ICprZXksCisJCQkJCXU4IGtleV9sZW4pCit7CisKKwljb25zdCB1OCAqbWV0aG9k LCAqc211aWQsICpsb2NraW5nX3NwLCAqaHNhOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCXNp emVfdCBrbGVuID0ga2V5X2xlbjsKKwl1MzIgSFNOOworCWludCByZXQ7CisKKwlpZiAoa2V5ID09 IE5VTEwpIHsKKwkJcHJfZXJyKCJDYW5ub3Qgc3RhcnQgTG9ja2luZyBTUCBzZXNzaW9uIHdpdGhv dXQgYSBrZXlcbiIpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwljbWQgPSAmZGV2LT5jbWQ7 CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwor CUhTTiA9IDB4NDE7CisKKwlzbXVpZCA9IE9QQUxVSURbT1BBTF9TTVVJRF9VSURdOworCW1ldGhv ZCA9IE9QQUxNRVRIT0RbT1BBTF9TVEFSVFNFU1NJT05dOworCWxvY2tpbmdfc3AgPSBPUEFMVUlE W09QQUxfTE9DS0lOR1NQX1VJRF07CisJaHNhID0gT1BBTFVJRFthdXRoXTsKKworCXJldCA9IHRl c3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgY3VzYyAyY3NjIDJjc2MgYyIsCisJCQkJICAg IE9QQUxfQ0FMTCwKKwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0 aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJ ICAgIEhTTiwKKwkJCQkgICAgbG9ja2luZ19zcCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBP UEFMX1RJTllfVUlOVF8wMSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BB TF9USU5ZX1VJTlRfMDAsIC8qIEhvc3RDaGFsbGVuZ2UgKi8KKwkJCQkgICAga2V5LCBrbGVuLAor CQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAg IE9QQUxfVElOWV9VSU5UXzAzLCAvKiBIb3N0IFNpZ24gQXV0aG9yaXR5ICovCisJCQkJICAgIGhz YSwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BB TF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxk aW5nIHN0YXJ0IGFkbWluc3Agc2Vzc2lvbiBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlz a19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRl diwgY21kLCBzdGFydF9vcGFsX3Nlc3Npb25fY29udCk7Cit9CisKK3N0YXRpYyBpbmxpbmUgaW50 IHN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJ cmV0dXJuIHN0YXJ0X2xvY2tpbmdzcF9vcGFsX3Nlc3Npb24oZGV2LCBPUEFMX0FETUlOMV9VSUQs CisJCQkJCSAgICBkZXYtPmtleSwgZGV2LT5rZXlfbGVuKTsKK30KKworc3RhdGljIGludCBzdGFy dF9hdXRoX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAq bWV0aG9kLCAqc211aWQsICpsb2NraW5nX3NwOworCXU4IGxrX3VsX3VzZXJbT1BBTF9VSURfTEVO R1RIXTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwl1MzIgSFNOOworCWludCByZXQ7CisJc3Ry dWN0IG9wYWxfdXNlcl9pbmZvICp1aW5mbzsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9v cGFsX2NtZChjbWQpOworCisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwlIU04gPSAw eDQxOworCisJdWluZm8gPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07CisKKwlzbXVp ZCA9IE9QQUxVSURbT1BBTF9TTVVJRF9VSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9T VEFSVFNFU1NJT05dOworCWxvY2tpbmdfc3AgPSBPUEFMVUlEW09QQUxfTE9DS0lOR1NQX1VJRF07 CisKKwlpZiAodWluZm8tPlNVTSkgeworCQlyZXQgPSBidWlsZF9sb2NraW5nX3VzZXIobGtfdWxf dXNlciwgc2l6ZW9mKGxrX3VsX3VzZXIpLAorCQkJCQkgZGV2LT5scik7CisJCWlmIChyZXQgPCAw KSB7CisJCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHVzZXJcbiIsCisJCQkgICAg ICAgZGV2LT5kaXNrX25hbWUpOworCQkJcmV0dXJuIHJldDsKKwkJfQorCX0gZWxzZSBpZiAodWlu Zm8tPndobyAhPSBPUEFMX0FETUlOMSAmJiAhdWluZm8tPlNVTSkgeworCQlyZXQgPSBidWlsZF9s b2NraW5nX3VzZXIobGtfdWxfdXNlciwgc2l6ZW9mKGxrX3VsX3VzZXIpLAorCQkJCQkgdWluZm8t PndobyAtIDEpOworCQlpZiAocmV0IDwgMCkgeworCQkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQg bG9ja2luZyB1c2VyXG4iLAorCQkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJCXJldHVybiBy ZXQ7CisJCX0KKwl9IGVsc2UKKwkJbWVtY3B5KGxrX3VsX3VzZXIsIE9QQUxVSURbT1BBTF9BRE1J TjFfVUlEXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2Vu X3ZhKGNtZCwgImMycyBjdXMzY3MzYyBzIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAg ICBzbXVpZCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xF TkdUSCwKKworCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAgSFNOLAorCQkJCSAgICBs b2NraW5nX3NwLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLAor CQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDAsCisJCQkJ ICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4sCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkg ICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLAorCisJCQkJICAg IGxrX3VsX3VzZXIsIE9QQUxfVUlEX0xFTkdUSCwKKworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJ CQkJICAgIE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBF cnJvciBidWlsZGluZyBTVEFSVFNFU1NJT04gY29tbWFuZC5cbiIsCisJCSAgICAgICBkZXYtPmRp c2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5k KGRldiwgY21kLCBzdGFydF9vcGFsX3Nlc3Npb25fY29udCk7Cit9CisKK3N0YXRpYyBpbnQgcmV2 ZXJ0X3RwZXIoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29uc3QgdTggKm1ldGhvZCwgKnNt dWlkOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwljbWQgPSAmZGV2LT5j bWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQp OworCisJc211aWQgPSBPUEFMVUlEW09QQUxfQURNSU5TUF9VSURdOworCW1ldGhvZCA9IE9QQUxN RVRIT0RbT1BBTF9SRVZFUlRdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwg ImMycyAyYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xF TkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisJCQkJICAgIE9QQUxf U1RBUlRMSVNULAorCQkJCSAgICBPUEFMX0VORExJU1QpOworCWlmIChyZXQgPCAwKSB7CisJCXBy X2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIFJFVkVSVCBUUEVSIGNvbW1hbmQuXG4iLAorCQkgICAg ICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6 ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBpbnRl cm5hbF9hY3RpdmF0ZV91c2VyKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCWNvbnN0IHU4ICpt ZXRob2Q7CisJdTggdWlkW09QQUxfVUlEX0xFTkdUSF07CisJc3RydWN0IG9wYWxfY21kICpjbWQ7 CisJaW50IHJldDsKKwlzdHJ1Y3Qgb3BhbF9hY3RpdmF0ZV91c2VyICphY3Q7CisKKwljbWQgPSAm ZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNv bUlEKTsKKworCWFjdCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKworCW1lbWNw eSh1aWQsIE9QQUxVSURbT1BBTF9VU0VSMV9VSURdLCBPUEFMX1VJRF9MRU5HVEgpOworCXVpZFs3 XSA9IGFjdC0+d2hvLndobzsKKworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOworCisJ cmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAzYyBjIDRjIDNjIiwKKwkJCQkg ICAgT1BBTF9DQUxMLAorCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0 aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJ ICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSwgLyogVmFsdWVz ICovCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUs CisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzA1LCAvKiBFbmFibGVkICovCisJCQkJICAgIE9QQUxf VElOWV9VSU5UXzAxLCAvKiBUcnVlICovCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKworCQkJCSAg ICBPUEFMX0VORExJU1QsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9FTkRM SVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEFj dGl2YXRlIFVzZXJOIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQly ZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2Vu ZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBlcmFzZV9sb2NraW5nX3JhbmdlKHN0cnVjdCBv cGFsX2RldiAqZGV2KQoreworCWNvbnN0IHU4ICptZXRob2Q7CisJdTggdWlkW09QQUxfVUlEX0xF TkdUSF07CisJc3RydWN0IG9wYWxfY21kICpjbWQ7CisJaW50IHJldDsKKworCWNtZCA9ICZkZXYt PmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQp OworCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0VSQVNFXTsKKworCWlmIChidWlsZF9sb2Nr aW5nX3JhbmdlKHVpZCwgc2l6ZW9mKHVpZCksIGRldi0+bHIpIDwgMCkgeworCQlwcl9lcnIoIiVz OiBDYW4ndCBidWlsZCBsb2NraW5nIHJhbmdlXG4iLCBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVy biAtRUlOVkFMOworCX0KKworCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMg MmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIHVpZCwgT1BBTF9VSURfTEVOR1RILAor CQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFMX1NUQVJU TElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2Vy cigiJXM6IEVycm9yIGJ1aWxkaW5nIEVyYXNlIExvY2tpbmcgUmFuZ2UgQ21tYW5kLlxuIiwKKwkJ ICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisJcmV0dXJuIGZpbmFs aXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOworfQorCitzdGF0aWMgaW50IHNl dF9tYnJfZG9uZShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0aG9kLCAq dWlkOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwl1OCBtYnJfZG9uZV90 ZiA9ICoodTggKilkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07CisKKwljbWQgPSAmZGV2 LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlE KTsKKworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOworCXVpZCA9IE9QQUxVSURbT1BB TF9NQlJDT05UUk9MXTsKKworCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMg M2MgNmMgMmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIHVpZCwgT1BBTF9VSURfTEVO R1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFM X1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVkFMVUVT LAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJ CQkgICAgT1BBTF9USU5ZX1VJTlRfMDIsIC8qIERvbmUgKi8KKwkJCQkgICAgbWJyX2RvbmVfdGYs ICAgICAgIC8qIERvbmUgVCBvciBGICovCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAg T1BBTF9FTkRMSVNULAorCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9FTkRM SVNUKTsKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBCdWlsZGluZyBzZXQg TUJSIERvbnQvTm90IGRvbmUgY29tbWFuZFxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsK KwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQs IGdlbmVyaWNfY29udCk7Cit9CisKK3N0YXRpYyBpbnQgc2V0X21icl9lbmFibGVfZGlzYWJsZShz dHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0aG9kLCAqdWlkOworCXN0cnVj dCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwl1OCBtYnJfZW5fZGlzID0gKih1OCAqKWRl di0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVh cl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCisJbWV0aG9k ID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07CisJdWlkID0gT1BBTFVJRFtPUEFMX01CUkNPTlRST0xd OworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAzYyA2YyAyYyIsCisJ CQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAg IG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAor CQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9WQUxVRVMsCisKKwkJCQkgICAg T1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJ TllfVUlOVF8wMSwgLyogRW5hYmxlICovCisJCQkJICAgIG1icl9lbl9kaXMsICAgICAgICAvKiBF bmFibGUgb3IgRGlzYWJsZSAqLworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxf RU5ETElTVCwKKworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElTVCk7 CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgc2V0IE1CUiBE b250L05vdCBkb25lIGNvbW1hbmRcbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJl dHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5l cmljX2NvbnQpOworfQorCitzdGF0aWMgaW50IHNldF9uZXdfcHcoc3RydWN0IG9wYWxfZGV2ICpk ZXYpCit7CisJY29uc3QgdTggKm1ldGhvZDsKKwl1OCBjcGluX3VpZFtPUEFMX1VJRF9MRU5HVEhd OworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisJc3RydWN0IG9wYWxfbmV3X3B3 ICpwdzsKKwlzaXplX3Qga2V5X2xlbjsKKwl1OCAqa2V5OworCisJY21kID0gJmRldi0+Y21kOwor CWNsZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwlw dyA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKwlrZXkgPSBwdy0+bmV3X3Bpbi5r ZXk7CisJa2V5X2xlbiA9IHB3LT5uZXdfcGluLmtleV9sZW47CisJbWVtY3B5KGNwaW5fdWlkLCBP UEFMVUlEW09QQUxfQ19QSU5fQURNSU4xXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCWlmIChwdy0+ dXNlcl9mb3JfcHcgIT0gT1BBTF9BRE1JTjEpIHsKKwkJY3Bpbl91aWRbNV0gPSAweDAzOworCQlp ZiAocHctPndoby5TVU0pCisJCQljcGluX3VpZFs3XSA9IHB3LT5uZXdfcGluLmxyICsgMTsKKwkJ ZWxzZQorCQkJY3Bpbl91aWRbN10gPSBwdy0+dXNlcl9mb3JfcHc7CisJfQorCisJbWV0aG9kID0g T1BBTE1FVEhPRFtPUEFMX1NFVF07CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21k LCAiYzJzIDNjIDNjczJjIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICBjcGluX3Vp ZCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwK KworCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJ ICAgIE9QQUxfVElOWV9VSU5UXzAxLCAvKiBWYWx1ZXMgKi8KKworCQkJCSAgICBPUEFMX1NUQVJU TElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAz LCAvKiBQSU4gKi8KKwkJCQkgICAga2V5LCBrZXlfbGVuLAorCQkJCSAgICBPUEFMX0VORE5BTUUs CisJCQkJICAgIE9QQUxfRU5ETElTVCwKKworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAg IE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBi dWlsZGluZyBTRVQgQU1JTjEgUElOIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25h bWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYs IGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBzZXRfc2lkX2NwaW5fcGluKHN0 cnVjdCBvcGFsX2RldiAqZGV2KQoreworCWNvbnN0IHU4ICptZXRob2QsICpjcGluX3VpZDsKKwlz dHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0OworCisJY21kID0gJmRldi0+Y21kOworCWNs ZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwljcGlu X3VpZCA9IE9QQUxVSURbT1BBTF9DX1BJTl9TSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BB TF9TRVRdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAyYyA0Y3My YyAyYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgY3Bpbl91aWQsIE9QQUxfVUlEX0xF TkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BB TF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCisJCQkJICAgIE9QQUxfVElO WV9VSU5UXzAxLCAvKiBWYWx1ZXMgKi8KKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAg IE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElOICovCisJ CQkJICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4sCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJ CQkgICAgT1BBTF9FTkRMSVNULAorCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BB TF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxk aW5nIFNFVCBDUElOIFBJTiBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsK KwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQs IGdlbmVyaWNfY29udCk7Cit9CisKK3N0YXRpYyB2b2lkIHF1ZXJ5X2xvY2tpbmdfcmFuZ2VfY29u dChpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRh OworCisJaWYgKGVycm9yKQorCQlnb3RvIGVycl9yZXR1cm47CisKKwllcnJvciA9IHBhcnNlX2Fu ZF9jaGVja19zdGF0dXMoZGV2KTsKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJyX3JldHVybjsKKwor CWRldi0+c3RhcnQgPSByZXNwb25zZV9nZXRfdTY0KCZkZXYtPnBhcnNlZCwgNCk7CisJZGV2LT5s ZW5ndGggPSByZXNwb25zZV9nZXRfdTY0KCZkZXYtPnBhcnNlZCwgOCk7CisKK2Vycl9yZXR1cm46 CisJaWYgKGRldi0+b3Blcl9jYikKKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYpOworfQorCitz dGF0aWMgaW50IHF1ZXJ5X2xvY2tpbmdfcmFuZ2Uoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJ dTggbHJfYnVmZmVyW09QQUxfVUlEX0xFTkdUSF07CisJc3RydWN0IG9wYWxfY21kICpjbWQ7CisJ Y29uc3QgdTggKm1ldGhvZDsKKwlpbnQgcmV0OworCisJY21kID0gJmRldi0+Y21kOworCWNsZWFy X29wYWxfY21kKGNtZCk7CisKKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfR0VUXTsKKworCWlm IChidWlsZF9sb2NraW5nX3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1ZmZlciksIGRldi0+ bHIpIDwgMCkgeworCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHJhbmdlXG4iLCBk ZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCXNldF9jb21JRChjbWQs IGRldi0+Y29tSUQpOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAx MmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVO R1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFM X1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlRO QU1FLAorCQkJCSAgICBPUEFMX1NUQVJUQ09MVU1OLAorCQkJCSAgICBPUEFMX1JBTkdFU1RBUlQs CisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAg IE9QQUxfRU5EQ09MVU1OLAorCQkJCSAgICBPUEFMX1JBTkdFTEVOR1RILAorCQkJCSAgICBPUEFM X0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsK KworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEdFVCBMb2Nr aW5nIFJhbmdlIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1 cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgcXVlcnlf bG9ja2luZ19yYW5nZV9jb250KTsKK30KKworc3RhdGljIGludCBhZGRfdXNlcl90b19scihzdHJ1 Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwl1OCBscl9idWZmZXJbT1BBTF9VSURfTEVOR1RIXTsKKwl1 OCB1c2VyX3VpZFtPUEFMX1VJRF9MRU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWNv bnN0IHU4ICptZXRob2Q7CisJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrdWw7CisJaW50IHJl dDsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9jb21J RChjbWQsIGRldi0+Y29tSUQpOworCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07CisK Kwlsa3VsID0gZGV2LT5mdW5jX2RhdGFbZGV2LT5zdGF0ZSAtIDFdOworCisJbWVtY3B5KGxyX2J1 ZmZlciwgT1BBTFVJRFtPUEFMX0xPQ0tJTkdSQU5HRV9BQ0VfUkRMT0NLRURdLAorCSAgICAgICBP UEFMX1VJRF9MRU5HVEgpOworCisJaWYgKGxrdWwtPmxfc3RhdGUgPT0gT1BBTF9SVykKKwkJbWVt Y3B5KGxyX2J1ZmZlciwgT1BBTFVJRFtPUEFMX0xPQ0tJTkdSQU5HRV9BQ0VfV1JMT0NLRURdLAor CQkgICAgICAgT1BBTF9VSURfTEVOR1RIKTsKKworCWxyX2J1ZmZlcls3XSA9IGRldi0+bHI7CisK KwltZW1jcHkodXNlcl91aWQsIE9QQUxVSURbT1BBTF9VU0VSMV9VSURdLCBPUEFMX1VJRF9MRU5H VEgpOworCXVzZXJfdWlkWzddID0gbGt1bC0+YXV0aG9yaXR5LndobzsKKworCXJldCA9IHRlc3Rf YW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgM2MgM2MgMmMgMnNjIGMyc2MgY3MyYyA1YyIsCisJ CQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgbHJfYnVmZmVyLCBPUEFMX1VJRF9MRU5HVEgsCisJ CQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRM SVNULAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDEs IC8qIFZhbHVlcyAqLworCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBPUEFMX1NU QVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIEJvb2xlYW5FeHByICovCisK KwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCisJCQkJ ICAgIE9QQUxVSURbT1BBTF9IQUxGX1VJRF9BVVRIT1JJVFlfT0JKX1JFRl0sCisJCQkJICAgIE9Q QUxfVUlEX0xFTkdUSF9IQUxGLAorCQkJCSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAor CQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAg IE9QQUxVSURbT1BBTF9IQUxGX1VJRF9BVVRIT1JJVFlfT0JKX1JFRl0sCisJCQkJICAgIE9QQUxf VUlEX0xFTkdUSF9IQUxGLAorCQkJCSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAorCQkJ CSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9Q QUxVSURbT1BBTF9IQUxGX1VJRF9CT09MRUFOX0FDRV0sCisJCQkJICAgIE9QQUxfVUlEX0xFTkdU SF9IQUxGLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSwKKwkJCQkgICAgT1BBTF9FTkROQU1F LAorCisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCQkJCSAg ICBPUEFMX0VORExJU1QsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9FTkRM SVNUKTsKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBhZGQg dXNlciB0byBsb2NraW5nIHJhbmdlIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25h bWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYs IGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBsb2NrX3VubG9ja19sb2NraW5n X3JhbmdlKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXU4IGxyX2J1ZmZlcltPUEFMX1VJRF9M RU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWNvbnN0IHU4ICptZXRob2Q7CisJc3Ry dWN0IG9wYWxfbG9ja191bmxvY2sgKmxrdWw7CisJaW50IHJldDsKKwl1OCByZWFkX2xvY2tlZCA9 IDEsIHdyaXRlX2xvY2tlZCA9IDE7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9j bWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKworCW1ldGhvZCA9IE9QQUxN RVRIT0RbT1BBTF9TRVRdOworCWxrdWwgPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07 CisJaWYgKGJ1aWxkX2xvY2tpbmdfcmFuZ2UobHJfYnVmZmVyLCBzaXplb2YobHJfYnVmZmVyKSwg ZGV2LT5scikgPCAwKSB7CisJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2Vc biIsIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJc3dpdGNoIChs a3VsLT5sX3N0YXRlKSB7CisJY2FzZSBPUEFMX1JPOgorCQlyZWFkX2xvY2tlZCA9IDA7CisJCXdy aXRlX2xvY2tlZCA9IDE7CisJCWJyZWFrOworCWNhc2UgT1BBTF9SVzoKKwkJcmVhZF9sb2NrZWQg PSAwOworCQl3cml0ZV9sb2NrZWQgPSAwOworCQlicmVhazsKKwljYXNlIE9QQUxfTEs6CisJCS8q IHZhcnMgYXJlIGluaXRhbGl6ZWQgdG8gbG9ja2VkICovCisJCWJyZWFrOworCWRlZmF1bHQ6CisJ CXByX2VycigiVHJpZWQgdG8gc2V0IGFuIGludmFsaWQgbG9ja2luZyBzdGF0ZS4uLiByZXR1cm5p bmcgdG8gdWxhbmRcbiIpOworCQlyZXR1cm4gMTsKKwl9CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRf dG9rZW5fdmEoY21kLCAiYzJzYyAzYyA0YyA0YyAzYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJ CQkgICAgbHJfYnVmZmVyLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9N RVRIT0RfTEVOR1RILAorCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICBPUEFMX1NU QVJUTkFNRSwKKwkJCQkgICAgT1BBTF9WQUxVRVMsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAor CisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1JFQURMT0NLRUQsCisJCQkJ ICAgIHJlYWRfbG9ja2VkLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9T VEFSVE5BTUUsCisJCQkJICAgIE9QQUxfV1JJVEVMT0NLRUQsCisJCQkJICAgIHdyaXRlX2xvY2tl ZCwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkg ICAgT1BBTF9FTkROQU1FLAorCQkJCSAgICBPUEFMX0VORExJU1QpOworCisJaWYgKHJldCA8IDAp IHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgU0VUIGNvbW1hbmQuXG4iLCBkZXYtPmRp c2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChk ZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworCitzdGF0aWMgaW50IGxvY2tfdW5sb2NrX2xv Y2tpbmdfcmFuZ2VfU1VNKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXU4IGxyX2J1ZmZlcltP UEFMX1VJRF9MRU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWNvbnN0IHU4ICptZXRo b2Q7CisJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrdWw7CisJaW50IHJldDsKKwl1OCByZWFk X2xvY2tlZCA9IDEsIHdyaXRlX2xvY2tlZCA9IDE7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xl YXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKworCW1ldGhv ZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOworCWxrdWwgPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0 YXRlIC0gMV07CisJaWYgKGJ1aWxkX2xvY2tpbmdfcmFuZ2UobHJfYnVmZmVyLCBzaXplb2YobHJf YnVmZmVyKSwgZGV2LT5scikgPCAwKSB7CisJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tp bmcgcmFuZ2VcbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJ c3dpdGNoIChsa3VsLT5sX3N0YXRlKSB7CisJY2FzZSBPUEFMX1JPOgorCQlyZWFkX2xvY2tlZCA9 IDA7CisJCXdyaXRlX2xvY2tlZCA9IDE7CisJCWJyZWFrOworCWNhc2UgT1BBTF9SVzoKKwkJcmVh ZF9sb2NrZWQgPSAwOworCQl3cml0ZV9sb2NrZWQgPSAwOworCQlicmVhazsKKwljYXNlIE9QQUxf TEs6CisJCS8qIHZhcnMgYXJlIGluaXRhbGl6ZWQgdG8gbG9ja2VkICovCisJCWJyZWFrOworCWRl ZmF1bHQ6CisJCXByX2VycigiVHJpZWQgdG8gc2V0IGFuIGludmFsaWQgbG9ja2luZyBzdGF0ZS5c biIpOworCQlyZXR1cm4gMTsKKwl9CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21k LCAiYzJzYyAzYyA0YyA0YyA0YyA0YyAzYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAg bHJfYnVmZmVyLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0Rf TEVOR1RILAorCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFN RSwKKwkJCQkgICAgT1BBTF9WQUxVRVMsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCisJCQkJ ICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1JFQURMT0NLRU5BQkxFRCwKKwkJCQkg ICAgT1BBTF9UUlVFLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFS VE5BTUUsCisJCQkJICAgIE9QQUxfV1JJVEVMT0NLRU5BQkxFRCwKKwkJCQkgICAgT1BBTF9UUlVF LAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJ ICAgIE9QQUxfUkVBRExPQ0tFRCwKKwkJCQkgICAgcmVhZF9sb2NrZWQsCisJCQkJICAgIE9QQUxf RU5ETkFNRSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9XUklURUxP Q0tFRCwKKwkJCQkgICAgd3JpdGVfbG9ja2VkLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJ CQkgICAgT1BBTF9FTkRMSVNULAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxf RU5ETElTVCk7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcg U0VUIGNvbW1hbmQuXG4iLCBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCXJl dHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworaW50 IGFjdGl2YXRlX2xzcChzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwl1OCB1c2VyX2xyW09QQUxf VUlEX0xFTkdUSF07CisJY29uc3QgdTggKm1ldGhvZCwgKnVpZDsKKwlzdHJ1Y3Qgb3BhbF9jbWQg KmNtZDsKKwlpbnQgcmV0OworCXNpemVfdCB1aW50XzMgPSAweDgzOworCisJY21kID0gJmRldi0+ Y21kOworCisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlE KTsKKworCXVpZCA9IE9QQUxVSURbT1BBTF9MT0NLSU5HU1BfVUlEXTsKKwltZXRob2QgPSBPUEFM TUVUSE9EW09QQUxfQUNUSVZBVEVdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNt ZCwgImMycyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5H VEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RIKTsKKwlpZiAocmV0IDwgMCkg eworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBBY3RpdmF0ZSBMb2NraW5nU1AgY29tbWFu ZC5cbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCS8q IEFjdGl2YXRpbmcgYXMgU1VNICovCisJaWYgKGRldi0+bHIgPiAwKSB7CisJCXJldCA9IGJ1aWxk X2xvY2tpbmdfcmFuZ2UodXNlcl9sciwgc2l6ZW9mKHVzZXJfbHIpLCBkZXYtPmxyKTsKKwkJaWYg KHJldCA8IDApIHsKKwkJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgdXNlclxuIiwK KwkJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCQlyZXR1cm4gcmV0OworCQl9CisJCXRlc3Rf YW5kX2FkZF90b2tlbl92YShjbWQsICIyYyA0YyBjc2MgMmMiLAorCQkJCSAgICAgIE9QQUxfU1RB UlRMSVNULAorCQkJCSAgICAgIE9QQUxfU1RBUlROQU1FLAorCisJCQkJICAgICAgdWludF8zLAor CQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzA2LAorCQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzAw LAorCQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzAwLAorCisJCQkJICAgICAgT1BBTF9TVEFSVExJ U1QsCisJCQkJICAgICAgdXNlcl9sciwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICAgIE9QQUxf RU5ETElTVCwKKworCQkJCSAgICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgICBPUEFMX0VORExJ U1QpOworCX0gZWxzZSAvKiBBY3RpYXZlIE5vcm1hbCBNb2RlICovCisJCXJldCA9IHRlc3RfYW5k X2FkZF90b2tlbl92YShjbWQsICIyYyIsCisJCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkJ ICAgIE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJv ciBidWlsZGluZyBBY3RpdmF0ZSBMb2NraW5nU1AgY29tbWFuZC5cbiIsCisJCSAgICAgICBkZXYt PmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZpbmFsaXplX2FuZF9z ZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOworfQorCitzdGF0aWMgdm9pZCBnZXRfbHNwX2xp ZmVjeWNsZV9jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKK3sKKworCXN0cnVjdCBvcGFsX2Rl diAqZGV2ID0gZGF0YTsKKwl1OCBsY19zdGF0dXM7CisKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJy X3JldHVybjsKKworCWVycm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhkZXYpOworCWlmIChl cnJvcikKKwkJZ290byBlcnJfcmV0dXJuOworCisJbGNfc3RhdHVzID0gcmVzcG9uc2VfZ2V0X3U2 NCgmZGV2LT5wYXJzZWQsIDQpOworCS8qIDB4MDggaXMgTWFudWZhY3VyZWQgSW5hY3RpdmUgKi8K KwkvKiAweDA5IGlzIE1hbnVmYWN0dXJlZCAqLworCWlmIChsY19zdGF0dXMgIT0gMHgwOCkgewor CQlwcl9lcnIoIiVzOiBDb3VsZG4ndCBkZXRlcm1pbmUgdGhlIHN0YXR1cyBvZiB0aGUgTGlmY3lj bGUgc3RhdGVcbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCWVycm9yID0gLUVOT0RF VjsKKwl9CisKK2Vycl9yZXR1cm46CisJaWYgKGRldi0+b3Blcl9jYikKKwkJZGV2LT5vcGVyX2Ni KGVycm9yLCBkZXYpOworfQorCisvKiBEZXRlcm1pbmUgaWYgd2UncmUgaW4gdGhlIE1hbnVmYWN0 dXJlZCBJbmFjdGl2ZSBvciBBY3RpdmUgc3RhdGUgKi8KK2ludCBnZXRfbHNwX2xpZmVjeWNsZShz dHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwljb25zdCB1 OCAqbWV0aG9kLCAqdWlkOworCWludCByZXQ7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisKKwljbGVh cl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCisJdWlkID0g T1BBTFVJRFtPUEFMX0xPQ0tJTkdTUF9VSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9H RVRdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAyYyA0YyA0YyAy YyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJ CQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRM SVNULAorCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwK KwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIFN0YXJ0IENvbHVtbiAqLworCQkJCSAgICBP UEFMX1RJTllfVUlOVF8wNiwgLyogTGlmY3ljbGUgQ29sdW1uICovCisJCQkJICAgIE9QQUxfRU5E TkFNRSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRf MDQsIC8qIEVuZCBDb2x1bW4gKi8KKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIExpZmVj eWNsZSBDb2x1bW4gKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfRU5E TElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2Vy cigiJXM6IEVycm9yIEJ1aWxkaW5nIEdFVCBMaWZlY3ljbGUgU3RhdHVzIGNvbW1hbmRcbiIsCisJ CSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZp bmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZXRfbHNwX2xpZmVjeWNsZV9jb250KTsKK30KKwor c3RhdGljIHZvaWQgZ2V0X21zaWRfY3Bpbl9waW5fY29udChpbnQgZXJyb3IsIHZvaWQgKmRhdGEp Cit7CisJY29uc3QgY2hhciAqbXNpZF9waW47CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRh OworCXNpemVfdCBzdHJsZW47CisKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJyX3JldHVybjsKKwor CWVycm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhkZXYpOworCWlmIChlcnJvcikKKwkJZ290 byBlcnJfcmV0dXJuOworCisJc3RybGVuID0gcmVzcG9uc2VfZ2V0X3N0cmluZygmZGV2LT5wYXJz ZWQsIDQsICZtc2lkX3Bpbik7CisJaWYgKCFtc2lkX3BpbikgeworCQlwcl9lcnIoIiVzOiBDb3Vs ZG4ndCBleHRyYWN0IFBJTiBmcm9tIHJlc3BvbnNlXG4iLCBfX2Z1bmNfXyk7CisJCWVycm9yID0g MTsKKwkJZ290byBlcnJfcmV0dXJuOworCX0KKworCWRldi0+cHJldl9kYXRhID0ga21lbWR1cCht c2lkX3Bpbiwgc3RybGVuLCBHRlBfS0VSTkVMKTsKKwlpZiAoIWRldi0+cHJldl9kYXRhKQorCQll cnJvciA9IC1FTk9NRU07CisKKwlkZXYtPnByZXZfZF9sZW4gPSBzdHJsZW47CisKKyBlcnJfcmV0 dXJuOgorCWlmIChkZXYtPm9wZXJfY2IpCisJCWRldi0+b3Blcl9jYihlcnJvciwgZGV2KTsKK30K Kworc3RhdGljIGludCBnZXRfbXNpZF9jcGluX3BpbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sK Kwljb25zdCB1OCAqbWV0aG9kLCAqc211aWQ7CisJaW50IHJldDsKKwlzdHJ1Y3Qgb3BhbF9jbWQg KmNtZDsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9j b21JRChjbWQsIGRldi0+Y29tSUQpOworCisJc211aWQgPSBPUEFMVUlEW09QQUxfQ19QSU5fTVNJ RF07CisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0dFVF07CisKKwlyZXQgPSB0ZXN0X2FuZF9h ZGRfdG9rZW5fdmEoY21kLCAiYyAycyAxMmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisKKwkJCQkg ICAgc211aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9M RU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNU LAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8q IFNhcnQgQ29sdW1uICovCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAvKiBQSU4gKi8KKwkJ CQkgICAgT1BBTF9FTkROQU1FLAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BB TF9USU5ZX1VJTlRfMDQsIC8qIEVuZCBDb2x1bW4gKi8KKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRf MDMsIC8qIFBJTiAqLworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElT VCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2Vycigi JXM6IEVycm9yIGJ1aWxkaW5nIEdldCBNU0lEIENQSU4gUElOIGNvbW1hbmQuXG4iLAorCQkgICAg ICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6 ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2V0X21zaWRfY3Bpbl9waW5fY29udCk7Cit9CisKK3N0YXRp YyB2b2lkIHVubG9ja19zdXNwZW5kX2ZpbmFsKGludCBlcnJvciwgdm9pZCAqZGF0YSkKK3sKKwlz dHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisKKwlkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQg PSBmYWxzZTsKKwlkZXYtPnJlc3VtZV9kYXRhID0gTlVMTDsKKwlkZXYtPmZ1bmNfZGF0YSA9IE5V TEw7CisJZGV2LT5iZGV2ID0gTlVMTDsKK30KKworc3RhdGljIGludCBidWlsZF9lbmRfb3BhbF9z ZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXN0cnVjdCBvcGFsX2NtZCAqY21kOwor CisJY21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNtZCk7CisKKwlzZXRfY29tSUQo Y21kLCBkZXYtPmNvbUlEKTsKKwlyZXR1cm4gdGVzdF9hbmRfYWRkX3Rva2VuX3U4KGNtZCwgT1BB TF9FTkRPRlNFU1NJT04pOworfQorCitzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb24oc3RydWN0 IG9wYWxfZGV2ICpkZXYpCit7CisJaWYgKGJ1aWxkX2VuZF9vcGFsX3Nlc3Npb24oZGV2KSA8IDAp CisJCXJldHVybiAtMTsKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCAmZGV2LT5jbWQs IGVuZF9zZXNzaW9uX2NvbnQpOworfQorCitzdGF0aWMgc3RydWN0IG9wYWxfZGV2ICpmaW5kX29w YWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHU4IGxyKQoreworCXN0cnVjdCBvcGFs X2RldiAqaXRlciwgKm9wYWxfZGV2ID0gTlVMTDsKKworCWxpc3RfZm9yX2VhY2hfZW50cnkoaXRl ciwgJm9wYWxfbGlzdCwgbm9kZSkgeworCQlpZiAoc3RybmNtcChpdGVyLT5kaXNrX25hbWUsIGJk ZXYtPmJkX2Rpc2stPmRpc2tfbmFtZSwKKwkJCSAgICBESVNLX05BTUVfTEVOKSkKKwkJCWNvbnRp bnVlOworCQlpZiAoaXRlci0+bHIgPT0gbHIpIHsKKwkJCW9wYWxfZGV2ID0gaXRlcjsKKwkJCWJy ZWFrOworCQl9CisJfQorCisJcmV0dXJuIG9wYWxfZGV2OworfQorCitzdGF0aWMgaW50IHVwZGF0 ZV9vcGFsX2RldihzdHJ1Y3Qgb3BhbF9kZXYgKm9sZF9kZXYsIHN0cnVjdCBvcGFsX2RldiAqbmV3 X2RldikKK3sKKwlpZiAoIWF0b21pY19hZGRfdW5sZXNzKCZvbGRfZGV2LT5pbl91c2UsIDEsIDEp KSB7CisJCXByX2VycigiJXM6IGRldiB3YXMgaW4gdXNlXG4iLCBfX2Z1bmNfXyk7CisJCXJldHVy biAtRUJVU1k7CisJfQorCisJb2xkX2Rldi0+a2V5X25hbWVfbGVuID0gbmV3X2Rldi0+a2V5X25h bWVfbGVuOworCWlmICghbWVtY3B5KG9sZF9kZXYtPmtleV9uYW1lLCBuZXdfZGV2LT5rZXlfbmFt ZSwgb2xkX2Rldi0+a2V5X25hbWVfbGVuKSkgeworCQlwcl9lcnIoIiVzOiBFcnJvciB1cGRhdGlu ZyBkZXZpY2U6XG4iLCBvbGRfZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVGQVVMVDsKKwl9 CisKKwlpZiAoIXN0cm5jcHkob2xkX2Rldi0+ZGlza19uYW1lLCBuZXdfZGV2LT5kaXNrX25hbWUs IERJU0tfTkFNRV9MRU4pKSB7CisJCXByX2VycigiJXM6IEVycm9yIHJlZ2lzdGVyaW5nIGRldmlj ZTogY29weWluZyBkaXNrIG5hbWVcbiIsCisJCSAgICAgICBvbGRfZGV2LT5kaXNrX25hbWUpOwor CQlyZXR1cm4gLUVGQVVMVDsKKwl9CisKKwlvbGRfZGV2LT5jb21JRCA9IG5ld19kZXYtPmNvbUlE OworCW9sZF9kZXYtPnN0YXJ0ID0gbmV3X2Rldi0+c3RhcnQ7CisJb2xkX2Rldi0+bGVuZ3RoID0g bmV3X2Rldi0+bGVuZ3RoOworCW9sZF9kZXYtPmFsaWduID0gbmV3X2Rldi0+YWxpZ247CisJb2xk X2Rldi0+bG93ZXN0X2xiYSA9IG5ld19kZXYtPmxvd2VzdF9sYmE7CisJb2xkX2Rldi0+YmRldiA9 IE5VTEw7CisJb2xkX2Rldi0+ZmluYWxfY2IgPSBuZXdfZGV2LT5maW5hbF9jYjsKKwlvbGRfZGV2 LT5maW5hbF9jYl9kYXRhID0gbmV3X2Rldi0+ZmluYWxfY2JfZGF0YTsKKwlvbGRfZGV2LT5vcGVy X2NiID0gbmV3X2Rldi0+b3Blcl9jYjsKKwlvbGRfZGV2LT5zdGF0ZSA9IG5ld19kZXYtPnN0YXRl OworCW9sZF9kZXYtPmZ1bmNzID0gbmV3X2Rldi0+ZnVuY3M7CisKKwlrZnJlZShvbGRfZGV2LT5j b21wbGV0aW9uKTsKKwljbGVhbl9mdW5jdGlvbl9kYXRhKG9sZF9kZXYpOworCisJb2xkX2Rldi0+ Y29tcGxldGlvbiA9IG5ld19kZXYtPmNvbXBsZXRpb247CisKKwkvKgorCSAqIFdvbid0IGJlIGFi bGUgdG8gYXV0byB1bmxvY2sgdGhpcyBsb2NraW5nIHJhbmdlIGJhc2VkIG9uIGJsb2NrCisJICog cmVxdWVzdGVzLgorCSAqLworCWlmIChvbGRfZGV2LT5sZW5ndGggPT0gMCkKKwkJcHJfd2Fybigi JXM6IE1pc3NpbmcgYmxvY2sgaW5mb3JtYXRpb24gZm9yIGxvY2tpbmcgcmFuZ2UgJWRcbiIsCisJ CQlvbGRfZGV2LT5kaXNrX25hbWUsIG9sZF9kZXYtPmxyKTsKKworCXJldHVybiAwOworfQorCitp bnQgb3BhbF9yZWdpc3Rlcl9jb250KHN0cnVjdCBvcGFsX2RldiAqbmV3X2RldikKK3sKKwlzdHJ1 Y3Qgb3BhbF9kZXYgKm9sZF9kZXY7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKwlpbnQgZXJyb3Ig PSAwOworCisJc3Bpbl9sb2NrX2lycXNhdmUoJmxpc3Rfc3BpbmxvY2ssIGZsYWdzKTsKKworCW9s ZF9kZXYgPSBmaW5kX29wYWxfZGV2KG5ld19kZXYtPmJkZXYsIG5ld19kZXYtPmxyKTsKKwlpZiAo IW9sZF9kZXYpIHsKKwkJbGlzdF9hZGRfdGFpbCgmbmV3X2Rldi0+bm9kZSwgJm9wYWxfbGlzdCk7 CisJCW9sZF9kZXYgPSBuZXdfZGV2OworCX0gZWxzZSB7CisJCWlmIChvbGRfZGV2ID09IG5ld19k ZXYpCisJCQllcnJvciA9IDA7CisJCWVsc2UgeworCQkJZXJyb3IgPSB1cGRhdGVfb3BhbF9kZXYo b2xkX2RldiwgbmV3X2Rldik7CisJCQljbGVhbl9vcGFsX2tleShuZXdfZGV2KTsKKwkJCWtmcmVl KG5ld19kZXYpOworCQl9CisJfQorCisJaWYgKGVycm9yKQorCQlsaXN0X2RlbCgmb2xkX2Rldi0+ bm9kZSk7CisKKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZsaXN0X3NwaW5sb2NrLCBmbGFncyk7 CisKKwlpZiAoIWVycm9yKQorCQlwcl9pbmZvKCIlczogUmVnaXN0ZXJlZCBrZXkgZm9yIGxvY2tp bmcgcmFuZ2U6ICVkXG4iLAorCQkJb2xkX2Rldi0+ZGlza19uYW1lLCBvbGRfZGV2LT5scik7CisK KwlpZiAob2xkX2Rldi0+b3Blcl9jYikKKwkJb2xkX2Rldi0+b3Blcl9jYihlcnJvciwgb2xkX2Rl dik7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHZvaWQgbmV4dChpbnQgZXJyb3IsIHN0cnVj dCBvcGFsX2RldiAqZGV2KQoreworCW9wYWxfc3RlcCBmdW5jID0gZGV2LT5mdW5jc1tkZXYtPnN0 YXRlXTsKKwl2b2lkICpjYl9kYXRhID0gZGV2LT5maW5hbF9jYl9kYXRhOworCXNlY19jYiAqY2Ig PSBkZXYtPmZpbmFsX2NiOworCWJvb2wgZG9uZSA9IGZhbHNlOworCisKKwlpZiAoZXJyb3IgfHwg IWZ1bmMpIHsKKwkJZG9uZSA9IHRydWU7CisJCWdvdG8gbmV4dF9leGl0OworCX0KKwlkZXYtPnN0 YXRlKys7CisJZGV2LT5vcGVyX2NiID0gbmV4dDsKKwllcnJvciA9IGZ1bmMoZGV2KTsKKyBuZXh0 X2V4aXQ6CisJaWYgKGVycm9yKSB7CisJCXByX2VycigiJXM6IEVycm9yIG9uIHN0ZXAgZnVuY3Rp b246ICVkIHdpdGggZXJyb3IgJWQ6ICVzXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUsIGRl di0+c3RhdGUsIGVycm9yLAorCQkgICAgICAgb3BhbF9lcnJvcl90b19odW1hbihlcnJvcikpOwor CisKKwkJYXRvbWljX2RlYygmZGV2LT5pbl91c2UpOworCQlpZiAoZGV2LT5lcnJvcl9jYikgewor CQkJZGV2LT5lcnJvcl9jYihkZXYtPmVycm9yX2NiX2RhdGEpOworCQkJcmV0dXJuOworCQl9CisJ CWlmIChjYikKKwkJCWNiKGVycm9yLCBjYl9kYXRhKTsKKworCQlkZXYtPmNvbXBsZXRpb24tPmNv bXBsZXRpb25fc3RhdHVzID0gZXJyb3I7CisJCWNvbXBsZXRlKCZkZXYtPmNvbXBsZXRpb24tPmNt ZF9jb21wbGV0aW9uKTsKKwl9IGVsc2UgaWYgKCFlcnJvciAmJiBkb25lKSB7CisJCWF0b21pY19k ZWMoJmRldi0+aW5fdXNlKTsKKwkJaWYgKGNiKQorCQkJY2IoZXJyb3IsIGNiX2RhdGEpOworCQlk ZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVzID0gZXJyb3I7CisJCWNvbXBsZXRlKCZk ZXYtPmNvbXBsZXRpb24tPmNtZF9jb21wbGV0aW9uKTsKKwl9Cit9CisKK2NvbnN0IG9wYWxfc3Rl cCBlcnJvcl9lbmRfc2Vzc2lvbltdID0geworCWVuZF9vcGFsX3Nlc3Npb24sCisJTlVMTCwKK307 CitzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb25fZXJyb3Ioc3RydWN0IG9wYWxfZGV2ICpkZXYp Cit7CisKKwlkZXYtPmZ1bmNzID0gZXJyb3JfZW5kX3Nlc3Npb247CisJZGV2LT5zdGF0ZSA9IDA7 CisJZGV2LT5lcnJvcl9jYiA9IE5VTEw7CisJbmV4dCgwLCBkZXYpOworCXJldHVybiAwOworfQor CitzdGF0aWMgc3RydWN0IG9wYWxfZGV2ICphbGxvY19vcGFsX2RldihzdHJ1Y3QgYmxvY2tfZGV2 aWNlICpiZGV2LCB1OCBscikKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKm9wYWxfZGV2OworCXN0cnVj dCByZXF1ZXN0X3F1ZXVlICpxOworCXVuc2lnbmVkIGxvbmcgZG1hX2FsaWduOworCWNvbnN0IGNo YXIgKmRpc2tfbmFtZTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0OworCisJb3Bh bF9kZXYgPSBremFsbG9jKHNpemVvZigqb3BhbF9kZXYpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIW9w YWxfZGV2KQorCQlyZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKKworCW9wYWxfZGV2LT5iZGV2ID0g YmRldjsKKwlvcGFsX2Rldi0+bHIgPSBscjsKKwljbWQgPSAmb3BhbF9kZXYtPmNtZDsKKwljbWQt PmNtZCA9IGNtZC0+Y21kX2J1ZjsKKwljbWQtPnJlc3AgPSBjbWQtPnJlc3BfYnVmOworCisJZGlz a19uYW1lID0gYmRldi0+YmRfZGlzay0+ZGlza19uYW1lOworCWlmICghc3RybmNweShvcGFsX2Rl di0+ZGlza19uYW1lLCBkaXNrX25hbWUsIERJU0tfTkFNRV9MRU4pKSB7CisJCXByX2VycigiJXM6 IEVycm9yIHJlZ2lzdGVyaW5nIGRldmljZTogY29weWluZyBkaXNrIG5hbWVcbiIsCisJCSAgICAg ICBkaXNrX25hbWUpOworCQlyZXQgPSAtRUZBVUxUOworCQlnb3RvIGVycl9mcmVlX2RldjsKKwl9 CisKKwlxID0gYmRldi0+YmRfcXVldWU7CisJZG1hX2FsaWduID0gKHF1ZXVlX2RtYV9hbGlnbm1l bnQocSkgfCBxLT5kbWFfcGFkX21hc2spICsgMTsKKwljbWQtPmNtZCA9ICh1OCAqKXJvdW5kX3Vw KCh1aW50cHRyX3QpY21kLT5jbWQsIGRtYV9hbGlnbik7CisJY21kLT5yZXNwID0gKHU4ICopcm91 bmRfdXAoKHVpbnRwdHJfdCljbWQtPnJlc3AsIGRtYV9hbGlnbik7CisKKwlJTklUX0xJU1RfSEVB RCgmb3BhbF9kZXYtPm5vZGUpOworCWF0b21pY19zZXQoJm9wYWxfZGV2LT5pbl91c2UsIDEpOwor CisJb3BhbF9kZXYtPmNvbXBsZXRpb24gPSBremFsbG9jKHNpemVvZigqb3BhbF9kZXYtPmNvbXBs ZXRpb24pLAorCQkJCSAgICAgICBHRlBfS0VSTkVMKTsKKworCWlmICghb3BhbF9kZXYtPmNvbXBs ZXRpb24pCisJCWdvdG8gZXJyX2ZyZWVfZGV2OworCisJaW5pdF9jb21wbGV0aW9uKCZvcGFsX2Rl di0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24pOworCW9wYWxfZGV2LT5jb21wbGV0aW9uLT5j b21wbGV0aW9uX3N0YXR1cyA9IDA7CisJb3BhbF9kZXYtPnN0YXRlID0gMDsKKworCXJldHVybiBv cGFsX2RldjsKKworZXJyX2ZyZWVfZGV2OgorCWtmcmVlKG9wYWxfZGV2KTsKKwlyZXR1cm4gRVJS X1BUUihyZXQpOworfQorCitpbnQgb3BhbF9yZWdpc3RlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpi ZGV2LCBzdHJ1Y3Qgb3BhbF9rZXkgKmtleV9jbWQsCisJCSAgY29uc3Qgb3BhbF9zdGVwICpmdW5j cykKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKm5ld19kZXYgPSBOVUxMOworCXU4IGtleV9sZW4gPSBr ZXlfY21kLT5rZXlfbGVuOworCXU4IGxyID0ga2V5X2NtZC0+bHI7CisJc3RydWN0IG9wYWxfY29t cGxldGlvbiAqY29tcGxldGlvbjsKKwlpbnQgcmV0OworCisJbmV3X2RldiA9IGFsbG9jX29wYWxf ZGV2KGJkZXYsIGxyKTsKKwlpZiAoSVNfRVJSKG5ld19kZXYpKSB7CisJCXByX2VycigiJXM6IEVy cm9yIHJlZ2lzdGVyaW5nIGRldmljZTogYWxsb2NhdGlvblxuIiwKKwkJICAgICAgIGJkZXYtPmJk X2Rpc2stPmRpc2tfbmFtZSk7CisJCXJldHVybiBQVFJfRVJSKG5ld19kZXYpOworCX0KKworCWlm ICghbWVtY3B5KG5ld19kZXYtPmtleV9uYW1lLCBrZXlfY21kLT5rZXksIGtleV9sZW4pKSB7CisJ CXByX2VycigiJXM6IEVycm9yIHJlZ2lzdGVyaW5nIGtleTogY291bGRuJ3QgY29weSBrZXlcbiIs CisJCSAgICAgICBuZXdfZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVGQVVMVDsKKwl9CisK KwluZXdfZGV2LT5rZXlfbmFtZV9sZW4gPSBrZXlfbGVuOworCW5ld19kZXYtPmtleV90eXBlID0g a2V5X2NtZC0+a2V5X3R5cGU7CisJcmV0ID0gZ2V0X29wYWxfa2V5KG5ld19kZXYpOworCWlmIChy ZXQpIHsKKwkJcHJfZXJyKCIlczogQ291bGRuJ3QgZ2V0IGtleTogJWRcbiIsIG5ld19kZXYtPmRp c2tfbmFtZSwgcmV0KTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwluZXdfZGV2LT5mdW5jcyA9IGZ1 bmNzOworCisJbmV3X2Rldi0+c3RhdGUgPSAwOworCWNvbXBsZXRpb24gPSBuZXdfZGV2LT5jb21w bGV0aW9uOworCW5leHQoMCwgbmV3X2Rldik7CisKKwlyZXR1cm4gd2FpdF9mb3JfY21kX2NvbXBs ZXRpb24oY29tcGxldGlvbik7Cit9CisKK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9kZXYgKmdldF9yZWdp c3RlcmVkX29wYWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkJCQl1OCBscikK K3sKKwljb25zdCBjaGFyICpkaXNrbmFtZSA9IGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZTsKKwlz dHJ1Y3Qgb3BhbF9kZXYgKml0ZXIsICpkZXYgPSBOVUxMOworCXVuc2lnbmVkIGxvbmcgZmxhZ3M7 CisJYm9vbCBpbl91c2UgPSBmYWxzZTsKKworCXNwaW5fbG9ja19pcnFzYXZlKCZsaXN0X3NwaW5s b2NrLCBmbGFncyk7CisJbGlzdF9mb3JfZWFjaF9lbnRyeShpdGVyLCAmb3BhbF9saXN0LCBub2Rl KSB7CisJCWlmIChzdHJuY21wKGl0ZXItPmRpc2tfbmFtZSwgZGlza25hbWUsIERJU0tfTkFNRV9M RU4pKQorCQkJY29udGludWU7CisJCWlmIChpdGVyLT5sciA9PSBscikgeworCQkJZGV2ID0gaXRl cjsKKwkJCWlmICghYXRvbWljX2FkZF91bmxlc3MoJml0ZXItPmluX3VzZSwgMSwgMSkpIHsKKwkJ CQlkZXYgPSBOVUxMOworCQkJCWluX3VzZSA9IHRydWU7CisJCQl9CisJCQlicmVhazsKKwkJfQor CX0KKworCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmxpc3Rfc3BpbmxvY2ssIGZsYWdzKTsKKwor CWlmICghZGV2KQorCQlyZXR1cm4gTlVMTDsKKworCWRldi0+YmRldiA9IGJkZXY7CisJcmV0dXJu IGRldjsKK30KKworLyogRnJlZSB1cCB0aGUgT3BhbCBkZXYgYW5kIGl0cyBrZXlzIGR1cmluZyB0 d28gc2NlbmFyaW9zOgorICoKKyAqIDEpIFdoZW4gYSBjb21tYW5kIGlzIGNvbXBsZXRlIHRoYXQg bm8gbG9uZ2VyIHJlcXVpcmVzCisgKiAgICB0aGUgb3BhbCBkZXYgdG8gYmUgYXJvdW5kLgorICog MikgV2hlbiBhIGNvbW1hbmQsIGluY2x1ZGluZyBPcGFsIFNhdmUgZmFpbHMgd2UgY2xlYW4KKyAq ICAgIGFuZCBmcmVlIHRoZSBvcGFsIGRldi4KKyAqCisgKiAgICBJZiB3ZSBmaW5kIHRoZSBvcGFs IGRldiBzdHJ1Y3R1cmUgaW4gdGhlIGxpc3Qgb2YKKyAqICAgIHNhdmVkIHBhc3N3b3JkcyB3ZSB3 aWxsICpub3QqIHJlbW92ZSBpdC4KKyAqLworc3RhdGljIHZvaWQgcmVtb3ZlX2FuZF9jbGVhbl9v cGFsX2RldihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKml0ZXI7 CisJYm9vbCBmb3VuZCA9IGZhbHNlOworCisJc3Bpbl9sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKwls aXN0X2Zvcl9lYWNoX2VudHJ5KGl0ZXIsICZvcGFsX2xpc3QsIG5vZGUpIHsKKwkJaWYgKGl0ZXIg PT0gZGV2KSB7CisJCQlmb3VuZCA9IHRydWU7CisJCQlicmVhazsKKwkJfQorCX0KKworCXNwaW5f dW5sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKwlpZiAoIWZvdW5kKSB7CisJCWNsZWFuX29wYWxfa2V5 KGRldik7CisJCWNsZWFuX2Z1bmN0aW9uX2RhdGEoZGV2KTsKKwkJa2ZyZWUoZGV2KTsKKwl9Cit9 CisKK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9kZXYgKmdldF9vcl9jcmVhdGVfb3BhbF9kZXYoc3RydWN0 IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCQkJICAgICAgIHU4IGxyLCBib29sIHVzZV9uZXcpCit7 CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7CisKKwlpZiAodXNlX25ldykKKwkJcmV0dXJuIGFsbG9j X29wYWxfZGV2KGJkZXYsIGxyKTsKKworCWRldiA9IGdldF9yZWdpc3RlcmVkX29wYWxfZGV2KGJk ZXYsIGxyKTsKKwlpZiAoIWRldikgeworCQlkZXYgPSBhbGxvY19vcGFsX2RldihiZGV2LCBscik7 CisJCWlmICghZGV2KQorCQkJcmV0dXJuIE5VTEw7CisJfQorCXJldHVybiBkZXY7Cit9CisKK3N0 YXRpYyBzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpzZXR1cF9vcGFsX2RldihzdHJ1Y3QgYmxvY2tf ZGV2aWNlICpiZGV2LAorCQkJCQkgICAgICBzdHJ1Y3Qgb3BhbF9kZXYgKmRldiwKKwkJCQkJICAg ICAgY29uc3Qgb3BhbF9zdGVwICpmdW5jcywKKwkJCQkJICAgICAgc3RydWN0IG9wYWxfa2V5ICpr ZXkpCit7CisJaW50IHJldDsKKworCWRldi0+YmRldiA9IGJkZXY7CisJZGV2LT5zdGF0ZSA9IDA7 CisJZGV2LT5mdW5jcyA9IGZ1bmNzOworCWRldi0+VFNOID0gMDsKKwlkZXYtPkhTTiA9IDA7CisJ ZGV2LT5maW5hbF9jYiA9IE5VTEw7CisJZGV2LT5maW5hbF9jYl9kYXRhID0gTlVMTDsKKwlkZXYt PmxyID0ga2V5LT5scjsKKwlkZXYtPmVycm9yX2NiID0gZW5kX29wYWxfc2Vzc2lvbl9lcnJvcjsK KwlkZXYtPmVycm9yX2NiX2RhdGEgPSBkZXY7CisKKwlpZiAoa2V5KSB7CisJCW1lbWNweShkZXYt PmtleV9uYW1lLCBrZXktPmtleSwga2V5LT5rZXlfbGVuKTsKKwkJZGV2LT5rZXlfbmFtZV9sZW4g PSBrZXktPmtleV9sZW47CisJCWRldi0+a2V5X3R5cGUgPSBrZXktPmtleV90eXBlOworCisJCXJl dCA9IGdldF9vcGFsX2tleShkZXYpOworCQlpZiAocmV0KSB7CisJCQlrZnJlZShkZXYtPmNvbXBs ZXRpb24pOworCQkJcHJfZXJyKCIlczogQ291bGRuJ3QgZ2V0IGtleTogJWRcbiIsCisJCQkgICAg ICAgZGV2LT5kaXNrX25hbWUsIHJldCk7CisJCQlyZXR1cm4gRVJSX1BUUihyZXQpOworCQl9CisJ fQorCWRldi0+ZnVuY19kYXRhID0gTlVMTDsKKwlkZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25f c3RhdHVzID0gMDsKKworCXJldHVybiBkZXYtPmNvbXBsZXRpb247Cit9CisKK3N0YXRpYyBpbnQg aW50ZXJuYWxfc2V0dXBfbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCSAgICAgc3Ry dWN0IG9wYWxfdXNlcl9scl9zZXR1cCAqc2V0dXApCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7 CisJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKKwl2b2lkICpkYXRhWzNdID0g eyBOVUxMIH07CisJY29uc3Qgb3BhbF9zdGVwIGxyX2Z1bmNzW10gPSB7CisJCW9wYWxfZGlzY292 ZXJ5MCwKKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCisJCXNldHVwX2xvY2tpbmdfcmFuZ2Us CisJCWdldF9hY3RpdmVfa2V5LAorCQlnZW5fa2V5LAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlO VUxMLAorCX07CisJaW50IHJldDsKKworCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRl diwgc2V0dXAtPmtleS5sciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJldHVybiAtRU5PTUVNOwor CisJY29tcGxldGlvbiA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwgbHJfZnVuY3MsICZzZXR1 cC0+a2V5KTsKKwlpZiAoSVNfRVJSKGNvbXBsZXRpb24pKSB7CisJCXJldCA9IFBUUl9FUlIoY29t cGxldGlvbik7CisJCWdvdG8gZXJyb3JfcmV0dXJuOworCX0KKworCWRldi0+ZnVuY19kYXRhID0g ZGF0YTsKKwlkZXYtPm51bV9mdW5jX2RhdGEgPSAzOworCWRldi0+ZnVuY19kYXRhWzFdID0gJnNl dHVwLT53aG87CisJZGV2LT5mdW5jX2RhdGFbMl0gPSBzZXR1cDsKKworCW5leHQoMCwgZGV2KTsK KwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsKKworIGVycm9yX3Jl dHVybjoKKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7CisJcmV0dXJuIHJldDsKK30K KworaW50IG9wYWxfcmV2ZXJ0KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBvcGFs X2tleSAqa2V5KQoreworCWNvbnN0IG9wYWxfc3RlcCByZXZlcnRfZnVuY3NbXSA9IHsKKwkJb3Bh bF9kaXNjb3ZlcnkwLAorCQlzdGFydF9TSURBU1Bfb3BhbF9zZXNzaW9uLAorCQlyZXZlcnRfdHBl ciwgLyogY29udHJvbGxlciB3aWxsIHRlcm1pbmF0ZSBzZXNzaW9uICovCisJCU5VTEwsCisJfTsK KworCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYsIGtleSwgcmV2ZXJ0X2Z1bmNzKTsKK30KKwor aW50IGFjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IG9wYWxf YWN0aXZhdGVfdXNlciAqYWN0KQoreworCWNvbnN0IG9wYWxfc3RlcCBhY3RfZnVuY3NbXSA9IHsK KwkJb3BhbF9kaXNjb3ZlcnkwLAorCQlzdGFydF9hZG1pbjFMU1Bfb3BhbF9zZXNzaW9uLAorCQlp bnRlcm5hbF9hY3RpdmF0ZV91c2VyLAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlOVUxMCisJfTsK KwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpjb21wbGV0 aW9uOworCXZvaWQgKmRhdGFbM10gPSB7IE5VTEwgfTsKKwlpbnQgcmV0OworCisJZGV2ID0gZ2V0 X29yX2NyZWF0ZV9vcGFsX2RldihiZGV2LCBhY3QtPmtleS5sciwgdHJ1ZSk7CisJaWYgKCFkZXYp CisJCXJldHVybiAtRU5PTUVNOworCisJY29tcGxldGlvbiA9IHNldHVwX29wYWxfZGV2KGJkZXYs IGRldiwgYWN0X2Z1bmNzLCAmYWN0LT5rZXkpOworCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsK KwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1cm47CisJfQor CisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7CisJZGV2 LT5mdW5jX2RhdGFbMV0gPSBhY3Q7CisJZGV2LT5mdW5jX2RhdGFbMl0gPSBhY3Q7CisKKwluZXh0 KDAsIGRldik7CisJcmV0ID0gd2FpdF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxldGlvbik7CisK KyBlcnJvcl9yZXR1cm46CisJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2RldihkZXYpOworCXJldHVy biByZXQ7Cit9CisKK2ludCBvcGFsX3NldF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBz dHJ1Y3Qgb3BhbF9uZXdfcHcgKnB3KQorCit7CisJY29uc3Qgb3BhbF9zdGVwIHB3X2Z1bmNzW10g PSB7CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCisJCXNl dF9uZXdfcHcsCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEwKKwl9OworCXN0cnVjdCBvcGFs X2RldiAqZGV2OworCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJdm9pZCAq ZGF0YVszXSA9IHsgTlVMTCB9OworCWludCByZXQ7CisKKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29w YWxfZGV2KGJkZXYsIHB3LT5jdXJyZW50X3Bpbi5sciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJl dHVybiAtRU5PTUVNOworCisJY29tcGxldGlvbiA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwg cHdfZnVuY3MsICZwdy0+Y3VycmVudF9waW4pOworCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsK KwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1cm47CisJfQor CisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7CisJZGV2 LT5mdW5jX2RhdGFbMV0gPSAodm9pZCAqKSAmcHctPndobzsKKwlkZXYtPmZ1bmNfZGF0YVsyXSA9 ICh2b2lkICopIHB3OworCisJbmV4dCgwLCBkZXYpOworCXJldCA9IHdhaXRfZm9yX2NtZF9jb21w bGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJyb3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5f b3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworfQorCitpbnQgb3BhbF9hY3RfbHNwX2ludChz dHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgb3BhbF9rZXkgKmtleSwKKwkJICAgICBj b25zdCBvcGFsX3N0ZXAgKmZ1bmNzKQoreworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXN0cnVj dCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJaW50IHJldDsKKworCWRldiA9IGdldF9v cl9jcmVhdGVfb3BhbF9kZXYoYmRldiwga2V5LT5sciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJl dHVybiAtRU5PTUVNOworCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2RldihiZGV2LCBkZXYsIGZ1 bmNzLCBrZXkpOworCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsKKwkJcmV0ID0gUFRSX0VSUihj b21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1cm47CisJfQorCisJbmV4dCgwLCBkZXYpOwor CXJldCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJyb3JfcmV0 dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworfQor CisKK3N0YXRpYyBpbnQgb3BhbF9zYXZlX2ludGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2UgKmJk ZXYsCisJCQkgICAgICBzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayAqbGspCit7CisJdm9pZCAqZnVu Y19kYXRhWzNdID0geyBOVUxMIH07CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7CisJc3RydWN0IG9w YWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKKwljb25zdCBvcGFsX3N0ZXAgX2F1dGhfZnVuY3Nb XSA9IHsKKwkJb3BhbF9kaXNjb3ZlcnkwLAorCQlzdGFydF9hdXRoX29wYWxfc2Vzc2lvbiwKKwkJ cXVlcnlfbG9ja2luZ19yYW5nZSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJb3BhbF9yZWdpc3Rl cl9jb250LAorCQlOVUxMCisJfTsKKwlpbnQgcmV0OworCisJZGV2ID0gZ2V0X29yX2NyZWF0ZV9v cGFsX2RldihiZGV2LCBsay0+a2V5LmxyLCBmYWxzZSk7CisJaWYgKCFkZXYpCisJCXJldHVybiAt RU5PTUVNOworCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2RldihiZGV2LCBkZXYsIF9hdXRoX2Z1 bmNzLCAmbGstPmtleSk7CisJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgeworCQlyZXQgPSBQVFJf RVJSKGNvbXBsZXRpb24pOworCQlnb3RvIGVycm9yX3JldHVybjsKKwl9CisKKwlkZXYtPm51bV9m dW5jX2RhdGEgPSAzOworCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOworCWRldi0+ZnVuY19k YXRhWzFdID0gJmxrLT5hdXRob3JpdHk7CisJZGV2LT5sa3VsID0gKmxrOworCisJbmV4dCgwLCBk ZXYpOworCXJldCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJy b3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0 OworfQorCitzdGF0aWMgaW50IGFkZF91c2VyX2xyX2ludGVybmFsKHN0cnVjdCBibG9ja19kZXZp Y2UgKmJkZXYsCisJCQkJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrKQoreworCXZvaWQgKmZ1 bmNfZGF0YVszXSA9IHsgTlVMTCB9OworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXN0cnVjdCBv cGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJY29uc3Qgb3BhbF9zdGVwIGZ1bmNzW10gPSB7 CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxfc2Vzc2lvbiwKKwkJ YWRkX3VzZXJfdG9fbHIsCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEwKKwl9OworCWludCBy ZXQ7CisKKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJkZXYsIGxrLT5rZXkubHIsIHRy dWUpOworCWlmICghZGV2KQorCQlyZXR1cm4gLUVOT01FTTsKKwljb21wbGV0aW9uID0gc2V0dXBf b3BhbF9kZXYoYmRldiwgZGV2LCBmdW5jcywgJmxrLT5rZXkpOworCWlmIChJU19FUlIoY29tcGxl dGlvbikpIHsKKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1 cm47CisJfQorCisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYtPmZ1bmNfZGF0YSA9IGZ1 bmNfZGF0YTsKKwlkZXYtPmZ1bmNfZGF0YVsyXSA9IGxrOworCisJbmV4dCgwLCBkZXYpOworCXJl dCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJyb3JfcmV0dXJu OgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworfQorCitz dGF0aWMgaW50IGxvY2tfdW5sb2NrX2ludGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYs CisJCQkJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrKQoreworCXZvaWQgKmZ1bmNfZGF0YVsz XSA9IHsgTlVMTCB9OworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXN0cnVjdCBvcGFsX2NvbXBs ZXRpb24gKmNvbXBsZXRpb247CisKKwljb25zdCBvcGFsX3N0ZXAgdWxrX2Z1bmNzX1NVTVtdID0g eworCQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAorCQlsb2Nr X3VubG9ja19sb2NraW5nX3JhbmdlX1NVTSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJTlVMTAor CX07CisJY29uc3Qgb3BhbF9zdGVwIF91bmxvY2tfZnVuY3NbXSA9IHsKKwkJb3BhbF9kaXNjb3Zl cnkwLAorCQlzdGFydF9hdXRoX29wYWxfc2Vzc2lvbiwKKwkJbG9ja191bmxvY2tfbG9ja2luZ19y YW5nZSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJTlVMTAorCX07CisJaW50IHJldDsKKworCWRl diA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgbGstPmtleS5sciwgdHJ1ZSk7CisJaWYg KCFkZXYpCisJCXJldHVybiAtRU5PTUVNOworCisJaWYgKGxrLT5hdXRob3JpdHkuU1VNKQorCQlj b21wbGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCB1bGtfZnVuY3NfU1VNLCAmbGst PmtleSk7CisJZWxzZQorCQljb21wbGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBf dW5sb2NrX2Z1bmNzLCAmbGstPmtleSk7CisKKwlpZiAoSVNfRVJSKGNvbXBsZXRpb24pKSB7CisJ CXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7CisJCWdvdG8gZXJyb3JfcmV0dXJuOworCX0KKwor CWRldi0+bnVtX2Z1bmNfZGF0YSA9IDM7CisJZGV2LT5mdW5jX2RhdGEgPSBmdW5jX2RhdGE7CisJ ZGV2LT5mdW5jX2RhdGFbMV0gPSAmbGstPmF1dGhvcml0eTsKKwlkZXYtPmZ1bmNfZGF0YVsyXSA9 IGxrOworCisJbmV4dCgwLCBkZXYpOworCXJldCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNv bXBsZXRpb24pOworCisgZXJyb3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYo ZGV2KTsKKwlyZXR1cm4gcmV0OworfQorCitpbnQgb3BhbF9lcmFzZV9sb2NraW5nX3JhbmdlKHN0 cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisJc3RydWN0 IG9wYWxfZGV2ICpkZXY7CisJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKKwlz dHJ1Y3Qgb3BhbF9rZXkgazsKKwlpbnQgcmV0OworCWNvbnN0IG9wYWxfc3RlcCBlcmFzZV9mdW5j c1tdID0geworCQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Np b24sCisJCWVyYXNlX2xvY2tpbmdfcmFuZ2UsCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEws CisJfTsKKworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzaykgeworCQlwcl9lcnIoIkNhbid0 IHNhdmUgcGFzc3dvcmQgZm9yIE5VTEwgYmxvY2sgZGV2aWNlLlxuIik7CisJCXJldHVybiAtRUlO VkFMOworCX0KKworCWlmIChjb3B5X2Zyb21fdXNlcigmaywga2V5LT5vcGFsLCBzaXplb2YoKmtl eS0+b3BhbCkpKQorCQlyZXR1cm4gLUVGQVVMVDsKKworCWRldiA9IGdldF9vcl9jcmVhdGVfb3Bh bF9kZXYoYmRldiwgay5sciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJldHVybiAtRU5PTUVNOwor CisJY29tcGxldGlvbiA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwgZXJhc2VfZnVuY3MsICZr KTsKKwlpZiAoSVNfRVJSKGNvbXBsZXRpb24pKSB7CisJCXJldCA9IFBUUl9FUlIoY29tcGxldGlv bik7CisJCWdvdG8gZXJyb3JfcmV0dXJuOworCX0KKworCW5leHQoMCwgZGV2KTsKKwlyZXQgPSB3 YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsKKworIGVycm9yX3JldHVybjoKKwly ZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7CisJcmV0dXJuIHJldDsKK30KK0VYUE9SVF9T WU1CT0wob3BhbF9lcmFzZV9sb2NraW5nX3JhbmdlKTsKKworaW50IG9wYWxfZW5hYmxlX2Rpc2Fi bGVfc2hhZG93X21icihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LAorCQkJCSAgIHN0cnVjdCBz ZWRfa2V5ICprZXkpCit7CisJdm9pZCAqZnVuY19kYXRhWzZdID0geyBOVUxMIH07CisJc3RydWN0 IG9wYWxfbWJyX2RhdGEgbWJyOworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXN0cnVjdCBvcGFs X2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJY29uc3Qgb3BhbF9zdGVwIG1icl9mdW5jc1tdID0g eworCQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24sCisJ CXNldF9tYnJfZG9uZSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJc3RhcnRfYWRtaW4xTFNQX29w YWxfc2Vzc2lvbiwKKwkJc2V0X21icl9lbmFibGVfZGlzYWJsZSwKKwkJZW5kX29wYWxfc2Vzc2lv biwKKwkJTlVMTCwKKwl9OworCWludCByZXQ7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rp c2spIHsKKwkJcHJfZXJyKCJDYW4ndCBzYXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmlj ZS5cbiIpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlpZiAoY29weV9mcm9tX3VzZXIoJm1i ciwga2V5LT5vcGFsX21iciwgc2l6ZW9mKCprZXktPm9wYWxfbWJyKSkpCisJCXJldHVybiAtRUZB VUxUOworCisJaWYgKG1ici5lbmFibGVfZGlzYWJsZSAhPSBPUEFMX01CUl9FTkFCTEUgJiYKKwkg ICAgbWJyLmVuYWJsZV9kaXNhYmxlICE9IE9QQUxfTUJSX0RJU0FCTEUpCisJCXJldHVybiAtRUlO VkFMOworCisJZGV2ID0gZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihiZGV2LCBtYnIua2V5LmxyLCB0 cnVlKTsKKwlpZiAoIWRldikKKwkJcmV0dXJuIC1FTk9NRU07CisKKwljb21wbGV0aW9uID0gc2V0 dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBtYnJfZnVuY3MsICZtYnIua2V5KTsKKwlpZiAoSVNfRVJS KGNvbXBsZXRpb24pKSB7CisJCXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7CisJCWdvdG8gZXJy b3JfcmV0dXJuOworCX0KKworCWRldi0+bnVtX2Z1bmNfZGF0YSA9IDY7CisJZGV2LT5mdW5jX2Rh dGEgPSBmdW5jX2RhdGE7CisJZGV2LT5mdW5jX2RhdGFbMl0gPSAmbWJyLmVuYWJsZV9kaXNhYmxl OworCWRldi0+ZnVuY19kYXRhWzVdID0gJm1ici5lbmFibGVfZGlzYWJsZTsKKworCW5leHQoMCwg ZGV2KTsKKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsKKworIGVy cm9yX3JldHVybjoKKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7CisJcmV0dXJuIHJl dDsKKworfQorRVhQT1JUX1NZTUJPTChvcGFsX2VuYWJsZV9kaXNhYmxlX3NoYWRvd19tYnIpOwor CitpbnQgb3BhbF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5 ICprZXkpCit7CisJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgbGt1bDsKKworCWlmICghYmRldiB8 fCAhYmRldi0+YmRfZGlzaykgeworCQlwcl9lcnIoIkNhbid0IHNhdmUgcGFzc3dvcmQgZm9yIE5V TEwgYmxvY2sgZGV2aWNlLlxuIik7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWlmIChjb3B5 X2Zyb21fdXNlcigmbGt1bCwga2V5LT5vcGFsX2xrX3VubGssIHNpemVvZigqa2V5LT5vcGFsKSkp CisJCXJldHVybiAtRUZBVUxUOworCisJcmV0dXJuIG9wYWxfc2F2ZV9pbnRlcm5hbChiZGV2LCAm bGt1bCk7Cit9CitFWFBPUlRfU1lNQk9MKG9wYWxfc2F2ZSk7CisKK2ludCBvcGFsX2FkZF91c2Vy X3RvX2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7 CisJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgbGt1bDsKKworCWlmIChjb3B5X2Zyb21fdXNlcigm bGt1bCwga2V5LT5vcGFsX2xrX3VubGssIHNpemVvZihsa3VsKSkpCisJCXJldHVybiAtRUZBVUxU OworCisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7CisJCXByX2VycigiQ2FuJ3QgYXNz aWduIHVzZXIgdG8gTFIgd2l0aG91dCBiYWNraW5nIGRpc2tcbiIpOworCQlyZXR1cm4gLUVGQVVM VDsKKwl9CisJaWYgKGxrdWwubF9zdGF0ZSAhPSBPUEFMX1JPICYmIGxrdWwubF9zdGF0ZSAhPSBP UEFMX1JXKSB7CisJCXByX2VycigiTG9ja2luZyBzdGF0ZSB3YXMgbm90IFJPIG9yIFJXXG4iKTsK KwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCWlmIChsa3VsLmF1dGhvcml0eS53aG8gPCBPUEFMX1VT RVIxICYmCisJICAgIGxrdWwuYXV0aG9yaXR5LndobyA+IE9QQUxfVVNFUjkpIHsKKwkJcHJfZXJy KCJBdXRob3JpdHkgd2FzIG5vdCB3aXRoaW4gdGhlIHJhbmdlIG9mIHVzZXJzOiAlZFxuIiwKKwkJ ICAgICAgIGxrdWwuYXV0aG9yaXR5Lndobyk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKwlpZiAo bGt1bC5hdXRob3JpdHkuU1VNKSB7CisJCXByX2VycigiJXMgbm90IHN1cHBvcnRlZCBpbiBTVU0u IFVzZSBzZXR1cCBsb2NraW5nIHJhbmdlXG4iLAorCQkgICAgICAgX19mdW5jX18pOworCQlyZXR1 cm4gLUVJTlZBTDsKKwl9CisKKwlyZXR1cm4gYWRkX3VzZXJfbHJfaW50ZXJuYWwoYmRldiwgJmxr dWwpOworfQorRVhQT1JUX1NZTUJPTChvcGFsX2FkZF91c2VyX3RvX2xyKTsKKworaW50IG9wYWxf cmV2ZXJ0dHBlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5 KQoreworCXN0cnVjdCBvcGFsX2tleSBrOworCisJaWYgKGNvcHlfZnJvbV91c2VyKCZrLCBrZXkt Pm9wYWwsIHNpemVvZigqa2V5LT5vcGFsKSkpCisJCXJldHVybiAtRUZBVUxUOworCisJcmV0dXJu IG9wYWxfcmV2ZXJ0KGJkZXYsICZrKTsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF9yZXZlcnR0cGVy KTsKKworaW50IG9wYWxfbG9ja191bmxvY2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3Ry dWN0IHNlZF9rZXkgKmtleSkKK3sKKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayBrOworCisJaWYg KGNvcHlfZnJvbV91c2VyKCZrLCBrZXktPm9wYWxfbGtfdW5saywgc2l6ZW9mKCprZXktPm9wYWxf bGtfdW5saykpKQorCQlyZXR1cm4gLUVGQVVMVDsKKworCWlmIChrLmF1dGhvcml0eS53aG8gPCBP UEFMX0FETUlOMSB8fCBrLmF1dGhvcml0eS53aG8gPj0gT1BBTF9VU0VSOSkKKwkJcmV0dXJuIC1F SU5WQUw7CisKKwlyZXR1cm4gbG9ja191bmxvY2tfaW50ZXJuYWwoYmRldiwgJmspOworfQorRVhQ T1JUX1NZTUJPTChvcGFsX2xvY2tfdW5sb2NrKTsKKworaW50IG9wYWxfdGFrZV9vd25lcnNoaXAo c3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlzdHJ1 Y3Qgb3BhbF9rZXkgazsKKwljb25zdCBvcGFsX3N0ZXAgb3duZXJfZnVuY3NbXSA9IHsKKwkJb3Bh bF9kaXNjb3ZlcnkwLAorCQlzdGFydF9hbnlib2R5QVNQX29wYWxfc2Vzc2lvbiwKKwkJZ2V0X21z aWRfY3Bpbl9waW4sCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCXN0YXJ0X1NJREFTUF9vcGFsX3Nl c3Npb24sCisJCXNldF9zaWRfY3Bpbl9waW4sCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEwK Kwl9OworCisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7CisJCXByX2VycigiQ2FuJ3Qg c2F2ZSBwYXNzd29yZCBmb3IgTlVMTCBibG9jayBkZXZpY2UuXG4iKTsKKwkJcmV0dXJuIC1FSU5W QUw7CisJfQorCisJaWYgKGNvcHlfZnJvbV91c2VyKCZrLCBrZXktPm9wYWwsIHNpemVvZigqa2V5 LT5vcGFsKSkpCisJCXJldHVybiAtRUZBVUxUOworCisJcmV0dXJuIG9wYWxfcmVnaXN0ZXIoYmRl diwgJmssIG93bmVyX2Z1bmNzKTsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF90YWtlX293bmVyc2hp cCk7CisKK2ludCBvcGFsX2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBz dHJ1Y3Qgc2VkX2tleSAqa2V5KQoreworCXN0cnVjdCBvcGFsX2tleSBrOworCWNvbnN0IG9wYWxf c3RlcCBhY3RpdmVfZnVuY3NbXSA9IHsKKwkJb3BhbF9kaXNjb3ZlcnkwLAorCQlzdGFydF9TSURB U1Bfb3BhbF9zZXNzaW9uLCAvKiBPcGVuIHNlc3Npb24gYXMgU0lEIGF1dGggKi8KKwkJZ2V0X2xz cF9saWZlY3ljbGUsCisJCWFjdGl2YXRlX2xzcCwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJTlVM TAorCX07CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2spIHsKKwkJcHJfZXJyKCJDYW4n dCBzYXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmljZS5cbiIpOworCQlyZXR1cm4gLUVJ TlZBTDsKKwl9CisKKwlpZiAoY29weV9mcm9tX3VzZXIoJmssIGtleS0+b3BhbCwgc2l6ZW9mKCpr ZXktPm9wYWwpKSkKKwkJcmV0dXJuIC1FRkFVTFQ7CisKKwlyZXR1cm4gb3BhbF9hY3RfbHNwX2lu dChiZGV2LCAmaywgYWN0aXZlX2Z1bmNzKTsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF9hY3RpdmF0 ZV9sc3ApOworCitpbnQgb3BhbF9zZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZp Y2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICpwdykKK3sKKwlzdHJ1Y3Qgb3BhbF91c2VyX2xyX3Nl dHVwIGs7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2spIHsKKwkJcHJfZXJyKCJDYW4n dCBzYXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmljZS5cbiIpOworCQlyZXR1cm4gLUVJ TlZBTDsKKwl9CisKKwlpZiAoY29weV9mcm9tX3VzZXIoJmssIHB3LT5vcGFsX2xycywgc2l6ZW9m KCpwdy0+b3BhbF9scnMpKSkKKwkJcmV0dXJuIC1FRkFVTFQ7CisKKwlyZXR1cm4gaW50ZXJuYWxf c2V0dXBfbHIoYmRldiwgJmspOworfQorCitpbnQgb3BhbF9zZXRfbmV3X3B3KHN0cnVjdCBibG9j a19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICpwdykKK3sKKwlzdHJ1Y3Qgb3BhbF9uZXdf cHcgazsKKworCWlmIChwdy0+c2VkX3R5cGUgIT0gT1BBTF9QVykKKwkJcmV0dXJuIC1FSU5WQUw7 CisKKwlpZiAoY29weV9mcm9tX3VzZXIoJmssIHB3LT5vcGFsX3B3LCBzaXplb2YoKnB3LT5vcGFs X3B3KSkpCisJCXJldHVybiAtRUZBVUxUOworCisJaWYgKGsud2hvLndobyA8IE9QQUxfQURNSU4x IHx8IGsud2hvLndobyA+IE9QQUxfVVNFUjkpCisJCXJldHVybiAtRUlOVkFMOworCisJcmV0dXJu IG9wYWxfc2V0X3B3KGJkZXYsICZrKTsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF9zZXRfbmV3X3B3 KTsKKworaW50IG9wYWxfYWN0aXZhdGVfdXNlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBz dHJ1Y3Qgc2VkX2tleSAqcHcpCit7CisJc3RydWN0IG9wYWxfYWN0aXZhdGVfdXNlciBrOworCisJ aWYgKHB3LT5zZWRfdHlwZSAhPSBPUEFMX0FDVF9VU1IpIHsKKwkJcHJfZXJyKCJTZWQgdHlwZSB3 YXMgbm90IGFjdCB1c2VyXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJaWYgKGNvcHlf ZnJvbV91c2VyKCZrLCBwdy0+b3BhbF9hY3QsIHNpemVvZigqcHctPm9wYWxfYWN0KSkpIHsKKwkJ cHJfZXJyKCJjb3B5IGZyb20gdXNlciBlcnJvclxuIik7CisJCXJldHVybiAtRUZBVUxUOworCX0K KworCS8qIFdlIGNhbid0IGFjdGl2YXRlIEFkbWluMSBpdCdzIGFjdGl2ZSBhcyBtYW51ZmFjdHVy ZWQgKi8KKwlpZiAoay53aG8ud2hvIDwgT1BBTF9VU0VSMSAmJiBrLndoby53aG8gPiBPUEFMX1VT RVI5KSB7CisJCXByX2VycigiV2hvIHdhcyBub3QgYSB2YWxpZCB1c2VyOiAlZCBcbiIsIGsud2hv Lndobyk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCXJldHVybiBhY3RpdmF0ZV91c2VyKGJk ZXYsICZrKTsKKworfQorRVhQT1JUX1NZTUJPTChvcGFsX2FjdGl2YXRlX3VzZXIpOworCitpbnQg b3BhbF91bmxvY2tfZnJvbV9zdXNwZW5kKHN0cnVjdCBvcGFsX3N1c3BlbmRfdW5sayAqZGF0YSkK K3sKKwljb25zdCBjaGFyICpkaXNrbmFtZSA9IGRhdGEtPm5hbWU7CisJc3RydWN0IG9wYWxfZGV2 ICppdGVyLCAqZGV2ID0gTlVMTDsKKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpjb21wbGV0aW9u OworCXZvaWQgKmZ1bmNfZGF0YVszXSA9IHsgTlVMTCB9OworCWNvbnN0IG9wYWxfc3RlcCBfdW5s b2NrX2Z1bmNzX1NVTVtdID0geworCQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2F1dGhfb3Bh bF9zZXNzaW9uLAorCQlsb2NrX3VubG9ja19sb2NraW5nX3JhbmdlLAorCQllbmRfb3BhbF9zZXNz aW9uLAorCQlOVUxMCisJfTsKKwljb25zdCBvcGFsX3N0ZXAgX3VubG9ja19mdW5jc1tdID0gewor CQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAorCQlsb2NrX3Vu bG9ja19sb2NraW5nX3JhbmdlLAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlOVUxMCisJfTsKKwor CisJc3Bpbl9sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGl0ZXIs ICZvcGFsX2xpc3QsIG5vZGUpIHsKKwkJaWYgKHN0cm5jbXAoaXRlci0+ZGlza19uYW1lLCBkaXNr bmFtZSwgRElTS19OQU1FX0xFTikpIHsKKwkJCXByX2VycigiaXRlcmRpc2sgd2FzICVzIGFuZCBk aXNrbmFtZSBpcyAlc1xuIiwKKwkJCSAgICAgICBpdGVyLT5kaXNrX25hbWUsIGRpc2tuYW1lKTsK KwkJCWNvbnRpbnVlOworCQl9CisJCWlmIChhdG9taWNfYWRkX3VubGVzcygmaXRlci0+aW5fdXNl LCAxLCAxKSkgeworCQkJZGV2ID0gaXRlcjsKKwkJCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRh OworCQkJZGV2LT5yZXN1bWVfZnJvbV9zdXNwZW5kID0gdHJ1ZTsKKwkJCWRldi0+cmVzdW1lX2Rh dGEgPSBkYXRhOworCQkJZGV2LT5maW5hbF9jYiA9IHVubG9ja19zdXNwZW5kX2ZpbmFsOworCQkJ ZGV2LT5maW5hbF9jYl9kYXRhID0gZGV2OworCQkJZGV2LT5lcnJvcl9jYiA9IGVuZF9vcGFsX3Nl c3Npb25fZXJyb3I7CisJCQlkZXYtPmVycm9yX2NiX2RhdGEgPSBkZXY7CisJCQlkZXYtPnN0YXRl ID0gMDsKKwkJCWlmIChkZXYtPmxrdWwuYXV0aG9yaXR5LlNVTSkKKwkJCQlkZXYtPmZ1bmNzID0g X3VubG9ja19mdW5jc19TVU07CisJCQllbHNlCisJCQkJZGV2LT5mdW5jcyA9IF91bmxvY2tfZnVu Y3M7CisJCQlkZXYtPlRTTiA9IDA7CisJCQlkZXYtPkhTTiA9IDA7CisJCQlkZXYtPmZ1bmNfZGF0 YVsyXSA9ICZkZXYtPmxrdWw7CisJCQlkZXYtPmZ1bmNfZGF0YVsxXSA9ICZkZXYtPmxrdWwuYXV0 aG9yaXR5OworCQkJY29tcGxldGlvbiA9IGRldi0+Y29tcGxldGlvbjsKKwkJCW5leHQoMCwgZGV2 KTsKKwkJCXdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCQl9CisJfQorCXNw aW5fdW5sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKworCWlmICghZGV2KQorCQlyZXR1cm4gLUVOT0RF VjsKKwlyZXR1cm4gMDsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF91bmxvY2tfZnJvbV9zdXNwZW5k KTsKZGlmZiAtLWdpdCBhL2xpYi9zZWQtb3BhbF9pbnRlcm5hbC5oIGIvbGliL3NlZC1vcGFsX2lu dGVybmFsLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uYzlkMzg4MwotLS0g L2Rldi9udWxsCisrKyBiL2xpYi9zZWQtb3BhbF9pbnRlcm5hbC5oCkBAIC0wLDAgKzEsNTg2IEBA CisvKgorICogQ29weXJpZ2h0IMKpIDIwMTYgSW50ZWwgQ29ycG9yYXRpb24KKyAqCisgKiBQZXJt aXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBv YnRhaW5pbmcgYQorICogY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3Vt ZW50YXRpb24gZmlsZXMgKHRoZSAiU29mdHdhcmUiKSwKKyAqIHRvIGRlYWwgaW4gdGhlIFNvZnR3 YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24KKyAq IHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmli dXRlLCBzdWJsaWNlbnNlLAorICogYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwg YW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlCisgKiBTb2Z0d2FyZSBpcyBmdXJuaXNo ZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgorICoKKyAq IFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIChp bmNsdWRpbmcgdGhlIG5leHQKKyAqIHBhcmFncmFwaCkgc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxs IGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUKKyAqIFNvZnR3YXJlLgorICoK KyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9G IEFOWSBLSU5ELCBFWFBSRVNTIE9SCisgKiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1J VEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKKyAqIEZJVE5FU1MgRk9S IEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuICBJTiBOTyBFVkVOVCBT SEFMTAorICogVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBB TlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBB Q1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HCisgKiBGUk9NLCBP VVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9U SEVSIERFQUxJTkdTCisgKiBJTiBUSEUgU09GVFdBUkUuCisgKgorICogQXV0aG9yOgorICogICAg UmFmYWVsIEFudG9nbm9sbGkgPHJhZmFlbC5hbnRvZ25vbGxpQGludGVsLmNvbT4KKyAqICAgIFNj b3R0ICBCYXVlciAgICAgIDxzY290dC5iYXVlckBpbnRlbC5jb20+CisgKi8KKworI2lmbmRlZiBf TlZNRV9PUEFMX0lOVEVSTkFMX0gKKyNkZWZpbmUgX05WTUVfT1BBTF9JTlRFUk5BTF9ICisKKyNp bmNsdWRlIDxsaW51eC9rZXktdHlwZS5oPgorI2luY2x1ZGUgPGtleXMvdXNlci10eXBlLmg+CisK KyNkZWZpbmUgRFRBRVJST1JfTk9fTUVUSE9EX1NUQVRVUyAweDg5CisKK3N0YXRpYyBjb25zdCBj aGFyICpvcGFsX2Vycm9yc1sxOV0gPSB7CisJIlN1Y2Nlc3MiLAorCSJOb3QgQXV0aG9yaXplZCIs CisJIlVua25vd24gRXJyb3IiLAorCSJTUCBCdXN5IiwKKwkiU1AgRmFpbGVkIiwKKwkiU1AgRGlz YWJsZWQiLAorCSJTUCBGcm96ZW4iLAorCSJObyBTZXNzaW9ucyBBdmFpbGFibGUiLAorCSJVbmlx dWVuZXNzIENvbmZsaWN0IiwKKwkiSW5zdWZmaWNpZW50IFNwYWNlIiwKKwkiSW5zdWZmaWNpZW50 IFJvd3MiLAorCSJJbnZhbGlkIEZ1bmN0aW9uIiwKKwkiSW52YWxpZCBQYXJhbWV0ZXIiLAorCSJJ bnZhbGlkIFJlZmVyZW5jZSIsCisJIlVua25vd24gRXJyb3IiLAorCSJUUEVSIE1hbGZ1bmN0aW9u IiwKKwkiVHJhbnNhY3Rpb24gRmFpbHVyZSIsCisJIlJlc3BvbnNlIE92ZXJmbG93IiwKKwkiQXV0 aG9yaXR5IExvY2tlZCBPdXQiLAorfTsKKworc3RhdGljIGNvbnN0IGNoYXIgKm9wYWxfZXJyb3Jf dG9faHVtYW4oaW50IGVycm9yKQoreworCWlmIChlcnJvciA9PSAweDNmKQorCQlyZXR1cm4gIkZh aWxlZCI7CisKKwlpZiAoZXJyb3IgPj0gc2l6ZW9mKG9wYWxfZXJyb3JzKSB8fCBlcnJvciA8IDAp CisJCXJldHVybiAiVW5rbm93biBFcnJvciI7CisKKwlyZXR1cm4gb3BhbF9lcnJvcnNbZXJyb3Jd OworfQorCisvKiBVc2VyIElEcyB1c2VkIGluIHRoZSBUQ0cgc3RvcmFnZSBTU0NzICovCitzdGF0 aWMgY29uc3QgdTggT1BBTFVJRFtdWzhdID0geworCS8qIHVzZXJzICovCisKKwkvKiBzZXNzaW9u IG1hbmFnZW1lbnQgICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw eDAwLCAweGZmfSwKKwkvKiBzcGVjaWFsICJ0aGlzU1AiIHN5bnRheCAqLworCXsgMHgwMCwgMHgw MCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMSB9LAorCS8qIEFkbWluaXN0cmF0 aXZlIFNQICovCisJeyAweDAwLCAweDAwLCAweDAyLCAweDA1LCAweDAwLCAweDAwLCAweDAwLCAw eDAxIH0sCisJLyogTG9ja2luZyBTUCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMiwgMHgwNSwgMHgw MCwgMHgwMCwgMHgwMCwgMHgwMiB9LAorCS8qIEVOVEVSUFJJU0UgTG9ja2luZyBTUCAgKi8KKwl7 IDB4MDAsIDB4MDAsIDB4MDIsIDB4MDUsIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDEgfSwKKwkvKiBh bnlib2R5ICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAwLCAweDAwLCAw eDAxIH0sCisJLyogU0lEICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAw LCAweDAwLCAweDA2IH0sCisJLyogQURNSU4xICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA5 LCAweDAwLCAweDAxLCAweDAwLCAweDAxIH0sCisJLyogVVNFUjEgKi8KKwl7IDB4MDAsIDB4MDAs IDB4MDAsIDB4MDksIDB4MDAsIDB4MDMsIDB4MDAsIDB4MDEgfSwKKwkvKiBVU0VSMiAqLworCXsg MHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMywgMHgwMCwgMHgwMiB9LAorCS8qIFBT SUQgdXNlciAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMSwgMHhmZiwg MHgwMSB9LAorCS8qIEJhbmRNYXN0ZXIgMCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwg MHgwMCwgMHgwMCwgMHg4MCwgMHgwMSB9LAorCSAvKiBFcmFzZU1hc3RlciAqLworCXsgMHgwMCwg MHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMCwgMHg4NCwgMHgwMSB9LAorCisJLyogdGFibGVz ICovCisKKwkvKiBMb2NraW5nX0dsb2JhbFJhbmdlICovCisJeyAweDAwLCAweDAwLCAweDA4LCAw eDAyLCAweDAwLCAweDAwLCAweDAwLCAweDAxIH0sCisJLyogQUNFX0xvY2tpbmdfUmFuZ2VfU2V0 X1JkTG9ja2VkIFVJRCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOCwgMHgwMCwgMHgwMywg MHhFMCwgMHgwMSB9LAorCS8qIEFDRV9Mb2NraW5nX1JhbmdlX1NldF9XckxvY2tlZCBVSUQgKi8K Kwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDgsIDB4MDAsIDB4MDMsIDB4RTgsIDB4MDEgfSwKKwkv KiBNQlIgQ29udHJvbCAqLworCXsgMHgwMCwgMHgwMCwgMHgwOCwgMHgwMywgMHgwMCwgMHgwMCwg MHgwMCwgMHgwMSB9LAorCS8qIFNoYWRvdyBNQlIgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDgsIDB4 MDQsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAgfSwKKwkvKiBBVVRIT1JJVFlfVEFCTEUgKi8KKwl7 IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDB9LAorCS8qIENf UElOX1RBQkxFICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDBCLCAweDAwLCAweDAwLCAweDAw LCAweDAwfSwKKwkvKiBPUEFMIExvY2tpbmcgSW5mbyAqLworCXsgMHgwMCwgMHgwMCwgMHgwOCwg MHgwMSwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMSB9LAorCS8qIEVudGVycHJpc2UgTG9ja2luZyBJ bmZvICovCisJeyAweDAwLCAweDAwLCAweDA4LCAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAw IH0sCisKKwkvKiBDX1BJTl9UQUJMRSBvYmplY3QgSUQncyAqLworCisJLyogQ19QSU5fTVNJRCAq LworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwQiwgMHgwMCwgMHgwMCwgMHg4NCwgMHgwMn0sCisJ LyogQ19QSU5fU0lEICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDBCLCAweDAwLCAweDAwLCAw eDAwLCAweDAxfSwKKwkgLyogQ19QSU5fQURNSU4xICovCisJeyAweDAwLCAweDAwLCAweDAwLCAw eDBCLCAweDAwLCAweDAxLCAweDAwLCAweDAxfSwKKworCS8qIGhhbGYgVUlEJ3MgKG9ubHkgZmly c3QgNCBieXRlcyB1c2VkKSAqLworCisJLyogSGFsZi1VSUQg4oCTIEF1dGhvcml0eV9vYmplY3Rf cmVmICovCisJeyAweDAwLCAweDAwLCAweDBDLCAweDA1LCAweGZmLCAweGZmLCAweGZmLCAweGZm IH0sCisJLyogSGFsZi1VSUQg4oCTIEJvb2xlYW4gQUNFICovCisJeyAweDAwLCAweDAwLCAweDA0 LCAweDBFLCAweGZmLCAweGZmLCAweGZmLCAweGZmIH0sCisKKwkvKiBzcGVjaWFsIHZhbHVlIGZv ciBvbWl0dGVkIG9wdGlvbmFsIHBhcmFtZXRlciAqLworCisJLyogSEVYRkYgZm9yIG9taXR0ZWQg Ki8KKwl7IDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmZ9LAor fTsKK3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9VSURfTEVOR1RIID0gODsKK3N0YXRpYyBjb25z dCBzaXplX3QgT1BBTF9NU0lEX0tFWUxFTiA9IDE1Oworc3RhdGljIGNvbnN0IHNpemVfdCBPUEFM X1VJRF9MRU5HVEhfSEFMRiA9IDQ7CisKKworLyogRW51bSB0byBpbmRleCBPUEFMVUlEIGFycmF5 ICovCitlbnVtIE9QQUxfVUlEIHsKKwkvKiB1c2VycyAqLworCU9QQUxfU01VSURfVUlELAorCU9Q QUxfVEhJU1NQX1VJRCwKKwlPUEFMX0FETUlOU1BfVUlELAorCU9QQUxfTE9DS0lOR1NQX1VJRCwK KwlPUEFMX0VOVEVSUFJJU0VfTE9DS0lOR1NQX1VJRCwKKwlPUEFMX0FOWUJPRFlfVUlELAorCU9Q QUxfU0lEX1VJRCwKKwlPUEFMX0FETUlOMV9VSUQsCisJT1BBTF9VU0VSMV9VSUQsCisJT1BBTF9V U0VSMl9VSUQsCisJT1BBTF9QU0lEX1VJRCwKKwlPUEFMX0VOVEVSUFJJU0VfQkFORE1BU1RFUjBf VUlELAorCU9QQUxfRU5URVJQUklTRV9FUkFTRU1BU1RFUl9VSUQsCisJLyogdGFibGVzICovCisJ T1BBTF9MT0NLSU5HUkFOR0VfR0xPQkFMLAorCU9QQUxfTE9DS0lOR1JBTkdFX0FDRV9SRExPQ0tF RCwKKwlPUEFMX0xPQ0tJTkdSQU5HRV9BQ0VfV1JMT0NLRUQsCisJT1BBTF9NQlJDT05UUk9MLAor CU9QQUxfTUJSLAorCU9QQUxfQVVUSE9SSVRZX1RBQkxFLAorCU9QQUxfQ19QSU5fVEFCTEUsCisJ T1BBTF9MT0NLSU5HX0lORk9fVEFCTEUsCisJT1BBTF9FTlRFUlBSSVNFX0xPQ0tJTkdfSU5GT19U QUJMRSwKKwkvKiBDX1BJTl9UQUJMRSBvYmplY3QgSUQncyAqLworCU9QQUxfQ19QSU5fTVNJRCwK KwlPUEFMX0NfUElOX1NJRCwKKwlPUEFMX0NfUElOX0FETUlOMSwKKwkvKiBoYWxmIFVJRCdzIChv bmx5IGZpcnN0IDQgYnl0ZXMgdXNlZCkgKi8KKwlPUEFMX0hBTEZfVUlEX0FVVEhPUklUWV9PQkpf UkVGLAorCU9QQUxfSEFMRl9VSURfQk9PTEVBTl9BQ0UsCisJLyogb21pdHRlZCBvcHRpb25hbCBw YXJhbWV0ZXIgKi8KKwlPUEFMX1VJRF9IRVhGRiwKK307CisKKy8qCisgKiBUQ0cgU3RvcmFnZSBT U0MgTWV0aG9kcy4KKyAqLworc3RhdGljIGNvbnN0IHU4IE9QQUxNRVRIT0RbXVs4XSA9IHsKKwkv KiBQcm9wZXJ0aWVzICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw eGZmLCAweDAxIH0sCisJLyogU1RBUlRTRVNTSU9OICovCisJeyAweDAwLCAweDAwLCAweDAwLCAw eDAwLCAweDAwLCAweDAwLCAweGZmLCAweDAyIH0sCisJLyogUmV2ZXJ0ICovCisJeyAweDAwLCAw eDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAyLCAweDAyIH0sCisJLyogQWN0aXZhdGUg Ki8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDIsIDB4MDMgfSwK KwkvKiBFbnRlcnByaXNlIEdldCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwg MHgwMCwgMHgwMCwgMHgwNiB9LAorCS8qIEVudGVycHJpc2UgU2V0ICovCisJeyAweDAwLCAweDAw LCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDA3IH0sCisJLyogTkVYVCAqLworCXsg MHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOCB9LAorCS8qIEVu dGVycHJpc2UgQXV0aGVudGljYXRlICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAw LCAweDAwLCAweDAwLCAweDBjIH0sCisJLyogR2V0QUNMICovCisJeyAweDAwLCAweDAwLCAweDAw LCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDBkIH0sCisJLyogR2VuS2V5ICovCisJeyAweDAw LCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDEwIH0sCisJLyogcmV2ZXJ0 U1AgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MTEg fSwKKwkvKiBHZXQgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4 MDAsIDB4MTYgfSwKKwkvKiBTZXQgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAs IDB4MDAsIDB4MDAsIDB4MTcgfSwKKwkvKiBBdXRoZW50aWNhdGUgKi8KKwl7IDB4MDAsIDB4MDAs IDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MWMgfSwKKwkvKiBSYW5kb20gKi8KKwl7 IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDEgfSwKKwkvKiBF cmFzZSAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwOCwgMHgw MyB9LAorfTsKK3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9NRVRIT0RfTEVOR1RIID0gODsKKwor LyogRW51bSBmb3IgaW5kZXhpbmcgdGhlIE9QQUxNRVRIT0QgYXJyYXkgKi8KK2VudW0gT1BBTF9N RVRIT0QgeworCU9QQUxfUFJPUEVSVElFUywKKwlPUEFMX1NUQVJUU0VTU0lPTiwKKwlPUEFMX1JF VkVSVCwKKwlPUEFMX0FDVElWQVRFLAorCU9QQUxfRUdFVCwKKwlPUEFMX0VTRVQsCisJT1BBTF9O RVhULAorCU9QQUxfRUFVVEhFTlRJQ0FURSwKKwlPUEFMX0dFVEFDTCwKKwlPUEFMX0dFTktFWSwK KwlPUEFMX1JFVkVSVFNQLAorCU9QQUxfR0VULAorCU9QQUxfU0VULAorCU9QQUxfQVVUSEVOVElD QVRFLAorCU9QQUxfUkFORE9NLAorCU9QQUxfRVJBU0UsCit9OworCitlbnVtIE9QQUxfUkVTUE9O U0VfVE9LRU4geworCU9QQUxfRFRBX1RPS0VOSURfQllURVNUUklORyA9IDB4ZTAsCisJT1BBTF9E VEFfVE9LRU5JRF9TSU5UID0gMHhlMSwKKwlPUEFMX0RUQV9UT0tFTklEX1VJTlQgPSAweGUyLAor CU9QQUxfRFRBX1RPS0VOSURfVE9LRU4gPSAweGUzLCAvKiBhY3R1YWwgdG9rZW4gaXMgcmV0dXJu ZWQgKi8KKwlPUEFMX0RUQV9UT0tFTklEX0lOVkFMSUQgPSAwWDAKK307CisKK2VudW0gT1BBTF9U T0tFTiB7CisJLyogQm9vbGVhbiAqLworCU9QQUxfVFJVRSA9IDB4MDEsCisJT1BBTF9GQUxTRSA9 IDB4MDAsCisJT1BBTF9CT09MRUFOX0VYUFIgPSAweDAzLAorCS8qIGNlbGxibG9ja3MgKi8KKwlP UEFMX1RBQkxFID0gMHgwMCwKKwlPUEFMX1NUQVJUUk9XID0gMHgwMSwKKwlPUEFMX0VORFJPVyA9 IDB4MDIsCisJT1BBTF9TVEFSVENPTFVNTiA9IDB4MDMsCisJT1BBTF9FTkRDT0xVTU4gPSAweDA0 LAorCU9QQUxfVkFMVUVTID0gMHgwMSwKKwkvKiBhdXRob3JpdHkgdGFibGUgKi8KKwlPUEFMX1BJ TiA9IDB4MDMsCisJLyogbG9ja2luZyB0b2tlbnMgKi8KKwlPUEFMX1JBTkdFU1RBUlQgPSAweDAz LAorCU9QQUxfUkFOR0VMRU5HVEggPSAweDA0LAorCU9QQUxfUkVBRExPQ0tFTkFCTEVEID0gMHgw NSwKKwlPUEFMX1dSSVRFTE9DS0VOQUJMRUQgPSAweDA2LAorCU9QQUxfUkVBRExPQ0tFRCA9IDB4 MDcsCisJT1BBTF9XUklURUxPQ0tFRCA9IDB4MDgsCisJT1BBTF9BQ1RJVkVLRVkgPSAweDBBLAor CS8qIGxvY2tpbmcgaW5mbyB0YWJsZSAqLworCU9QQUxfTUFYUkFOR0VTID0gMHgwNCwKKwkgLyog bWJyIGNvbnRyb2wgKi8KKwlPUEFMX01CUkVOQUJMRSA9IDB4MDEsCisJT1BBTF9NQlJET05FID0g MHgwMiwKKwkvKiBwcm9wZXJ0aWVzICovCisJT1BBTF9IT1NUUFJPUEVSVElFUyA9IDB4MDAsCisJ LyogYXRvbXMgKi8KKwlPUEFMX1NUQVJUTElTVCA9IDB4ZjAsCisJT1BBTF9FTkRMSVNUID0gMHhm MSwKKwlPUEFMX1NUQVJUTkFNRSA9IDB4ZjIsCisJT1BBTF9FTkROQU1FID0gMHhmMywKKwlPUEFM X0NBTEwgPSAweGY4LAorCU9QQUxfRU5ET0ZEQVRBID0gMHhmOSwKKwlPUEFMX0VORE9GU0VTU0lP TiA9IDB4ZmEsCisJT1BBTF9TVEFSVFRSQU5TQUNUT04gPSAweGZiLAorCU9QQUxfRU5EVFJBTlNB Q1RPTiA9IDB4ZkMsCisJT1BBTF9FTVBUWUFUT00gPSAweGZmLAorCU9QQUxfV0hFUkUgPSAweDAw LAorfTsKKworLyogVXNlZnVsIHRpbnkgYXRvbXMuCisgKiBVc2VmdWwgZm9yIHRhYmxlIGNvbHVt bnMgZXRjCisgKi8KK2VudW0gT1BBTF9USU5ZX0FUT00geworCU9QQUxfVElOWV9VSU5UXzAwID0g MHgwMCwKKwlPUEFMX1RJTllfVUlOVF8wMSA9IDB4MDEsCisJT1BBTF9USU5ZX1VJTlRfMDIgPSAw eDAyLAorCU9QQUxfVElOWV9VSU5UXzAzID0gMHgwMywKKwlPUEFMX1RJTllfVUlOVF8wNCA9IDB4 MDQsCisJT1BBTF9USU5ZX1VJTlRfMDUgPSAweDA1LAorCU9QQUxfVElOWV9VSU5UXzA2ID0gMHgw NiwKKwlPUEFMX1RJTllfVUlOVF8wNyA9IDB4MDcsCisJT1BBTF9USU5ZX1VJTlRfMDggPSAweDA4 LAorCU9QQUxfVElOWV9VSU5UXzA5ID0gMHgwOSwKKwlPUEFMX1RJTllfVUlOVF8xMCA9IDB4MGEs CisJT1BBTF9USU5ZX1VJTlRfMTEgPSAweDBiLAorCU9QQUxfVElOWV9VSU5UXzEyID0gMHgwYywK KwlPUEFMX1RJTllfVUlOVF8xMyA9IDB4MGQsCisJT1BBTF9USU5ZX1VJTlRfMTQgPSAweDBlLAor CU9QQUxfVElOWV9VSU5UXzE1ID0gMHgwZiwKK307CisKK2VudW0gT1BBTF9BVE9NX1dJRFRIIHsK KwlPUEFMX1dJRFRIX1RJTlksCisJT1BBTF9XSURUSF9TSE9SVCwKKwlPUEFMX1dJRFRIX01FRElV TSwKKwlPUEFMX1dJRFRIX0xPTkcsCisJT1BBTF9XSURUSF9UT0tFTgorfTsKKworLyogTG9ja2lu ZyBzdGF0ZSBmb3IgYSBsb2NraW5nIHJhbmdlICovCitlbnVtIE9QQUxfTE9DS0lOR1NUQVRFIHsK KwlPUEFMX0xPQ0tJTkdfUkVBRFdSSVRFID0gMHgwMSwKKwlPUEFMX0xPQ0tJTkdfUkVBRE9OTFkg PSAweDAyLAorCU9QQUxfTE9DS0lOR19MT0NLRUQgPSAweDAzLAorfTsKKworLyoKKyAqIFN0cnVj dHVyZXMgdG8gYnVpbGQgYW5kIGRlY29kZSB0aGUgT3BhbCBTU0MgbWVzc2FnZXMKKyAqIGZpZWxk cyB0aGF0IGFyZSBOT1QgcmVhbGx5IG51bWVyaWMgYXJlIGRlZmluZWQgYXMgdThbXSB0bworICog aGVscCByZWR1Y2UgdGhlIGVuZGlhbm5lc3MgaXNzdWVzCisgKi8KKworLyogQ29tbSBQYWNrZXQg KGhlYWRlcikgZm9yIHRyYW5zbWlzc2lvbnMuICovCitzdHJ1Y3Qgb3BhbF9jb21wYWNrZXQgewor CXUzMiByZXNlcnZlZDA7CisJdTggZXh0ZW5kZWRDb21JRFs0XTsKKwl1MzIgb3V0c3RhbmRpbmdE YXRhOworCXUzMiBtaW5UcmFuc2ZlcjsKKwl1MzIgbGVuZ3RoOworfTsKKworLyogUGFja2V0IHN0 cnVjdHVyZS4gKi8KK3N0cnVjdCBvcGFsX3BhY2tldCB7CisJdTMyIFRTTjsKKwl1MzIgSFNOOwor CXUzMiBzZXFfbnVtYmVyOworCXUxNiByZXNlcnZlZDA7CisJdTE2IGFja190eXBlOworCXUzMiBh Y2tub3dsZWRnbWVudDsKKwl1MzIgbGVuZ3RoOworfTsKKworLyogRGF0YSBzdWIgcGFja2V0IGhl YWRlciAqLworc3RydWN0IG9wYWxfZGF0YV9zdWJwYWNrZXQgeworCXU4IHJlc2VydmVkMFs2XTsK Kwl1MTYga2luZDsKKwl1MzIgbGVuZ3RoOworfTsKKworLyogaGVhZGVyIG9mIGEgcmVzcG9uc2Ug Ki8KK3N0cnVjdCBvcGFsX2hlYWRlciB7CisJc3RydWN0IG9wYWxfY29tcGFja2V0IGNwOworCXN0 cnVjdCBvcGFsX3BhY2tldCBwa3Q7CisJc3RydWN0IG9wYWxfZGF0YV9zdWJwYWNrZXQgc3VicGt0 OworfTsKKworI2RlZmluZSBGQ19UUEVSICAgICAgIDB4MDAwMQorI2RlZmluZSBGQ19MT0NLSU5H ICAgIDB4MDAwMgorI2RlZmluZSBGQ19HRU9NRVRSWSAgIDB4MDAwMworI2RlZmluZSBGQ19FTlRF UlBSSVNFIDB4MDEwMAorI2RlZmluZSBGQ19EQVRBU1RPUkUgIDB4MDIwMgorI2RlZmluZSBGQ19T SU5HTEVVU0VSIDB4MDIwMQorI2RlZmluZSBGQ19PUEFMVjEwMCAgIDB4MDIwMAorI2RlZmluZSBG Q19PUEFMVjIwMCAgIDB4MDIwMworCisvKgorICogVGhlIERpc2NvdmVyeSAwIEhlYWRlci4gQXMg ZGVmaW5lZCBpbgorICogT3BhbCBTU0MgRG9jdW1lbnRhdGlvbgorICovCitzdHJ1Y3QgZDBfaGVh ZGVyIHsKKwl1MzIgbGVuZ3RoOyAvKiB0aGUgbGVuZ3RoIG9mIHRoZSBoZWFkZXIgNDggaW4gMi4w MC4xMDAgKi8KKwl1MzIgcmV2aXNpb247IC8qKjwgcmV2aXNpb24gb2YgdGhlIGhlYWRlciAxIGlu IDIuMDAuMTAwICovCisJdTMyIHJlc2VydmVkMDE7CisJdTMyIHJlc2VydmVkMDI7CisJLyoKKwkg KiB0aGUgcmVtYWluZGVyIG9mIHRoZSBzdHJ1Y3R1cmUgaXMgdmVuZG9yIHNwZWNpZmljIGFuZCB3 aWxsIG5vdCBiZQorCSAqIGFkZHJlc3NlZCBub3cKKwkgKi8KKwl1OCBpZ25vcmVkWzMyXTsKK307 CisKKy8qCisgKiBUUGVyIEZlYXR1cmUgRGVzY3JpcHRvci4gQ29udGFpbnMgZmxhZ3MgaW5kaWNh dGluZyBzdXBwb3J0IGZvciB0aGUKKyAqIFRQZXIgZmVhdHVyZXMgZGVzY3JpYmVkIGluIHRoZSBP UEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRjaCB0aGUKKyAqIE9QQUwgdGVybWlub2xv Z3kKKyAqCisgKiBjb2RlID09IDB4MDAxIGluIDIuMDAuMTAwCisgKi8KK3N0cnVjdCBkMF90cGVy X2ZlYXR1cmVzIHsKKwkvKgorCSAqIHN1cHBvcnRlZF9mZWF0dXJlcyBiaXRzOgorCSAqIGJpdCA3 OiByZXNlcnZlZAorCSAqIGJpdCA2OiBjb20gSUQgbWFuYWdlbWVudAorCSAqIGJpdCA1OiByZXNl cnZlZAorCSAqIGJpdCA0OiBzdHJlYW1pbmcgc3VwcG9ydAorCSAqIGJpdCAzOiBidWZmZXIgbWFu YWdlbWVudAorCSAqIGJpdCAyOiBBQ0svTkFDSworCSAqIGJpdCAxOiBhc3luYworCSAqIGJpdCAw OiBzeW5jCisJICovCisJdTggc3VwcG9ydGVkX2ZlYXR1cmVzOworCS8qCisJICogYnl0ZXMgNSB0 aHJvdWdoIDE1IGFyZSByZXNlcnZlZCwgYnV0IHdlIHJlcHJlc2VudCB0aGUgZmlyc3QgMyBhcwor CSAqIHU4IHRvIGtlZXAgdGhlIG90aGVyIHR3byAzMmJpdHMgaW50ZWdlcnMgYWxpZ25lZC4KKwkg Ki8KKwl1OCByZXNlcnZlZDAxWzNdOworCXUzMiByZXNlcnZlZDAyOworCXUzMiByZXNlcnZlZDAz OworfTsKKworLyoKKyAqIExvY2tpbmcgRmVhdHVyZSBEZXNjcmlwdG9yLiBDb250YWlucyBmbGFn cyBpbmRpY2F0aW5nIHN1cHBvcnQgZm9yIHRoZQorICogbG9ja2luZyBmZWF0dXJlcyBkZXNjcmli ZWQgaW4gdGhlIE9QQUwgc3BlY2lmaWNhdGlvbi4gVGhlIG5hbWVzIG1hdGNoIHRoZQorICogT1BB TCB0ZXJtaW5vbG9neQorICoKKyAqIGNvZGUgPT0gMHgwMDAyIGluIDIuMDAuMTAwCisgKi8KK3N0 cnVjdCBkMF9sb2NraW5nX2ZlYXR1cmVzIHsKKwkvKgorCSAqIHN1cHBvcnRlZF9mZWF0dXJlcyBi aXRzOgorCSAqIGJpdHMgNi03OiByZXNlcnZlZAorCSAqIGJpdCA1OiBNQlIgZG9uZQorCSAqIGJp dCA0OiBNQlIgZW5hYmxlZAorCSAqIGJpdCAzOiBtZWRpYSBlbmNyeXB0aW9uCisJICogYml0IDI6 IGxvY2tlZAorCSAqIGJpdCAxOiBsb2NraW5nIGVuYWJsZWQKKwkgKiBiaXQgMDogbG9ja2luZyBz dXBwb3J0ZWQKKwkgKi8KKwl1OCBzdXBwb3J0ZWRfZmVhdHVyZXM7CisJLyoKKwkgKiBieXRlcyA1 IHRocm91Z2ggMTUgYXJlIHJlc2VydmVkLCBidXQgd2UgcmVwcmVzZW50IHRoZSBmaXJzdCAzIGFz CisJICogdTggdG8ga2VlcCB0aGUgb3RoZXIgdHdvIDMyYml0cyBpbnRlZ2VycyBhbGlnbmVkLgor CSAqLworCXU4IHJlc2VydmVkMDFbM107CisJdTMyIHJlc2VydmVkMDI7CisJdTMyIHJlc2VydmVk MDM7Cit9OworCisvKgorICogR2VvbWV0cnkgRmVhdHVyZSBEZXNjcmlwdG9yLiBDb250YWlucyBm bGFncyBpbmRpY2F0aW5nIHN1cHBvcnQgZm9yIHRoZQorICogZ2VvbWV0cnkgZmVhdHVyZXMgZGVz Y3JpYmVkIGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRjaCB0aGUKKyAq IE9QQUwgdGVybWlub2xvZ3kKKyAqCisgKiBjb2RlID09IDB4MDAwMyBpbiAyLjAwLjEwMAorICov CitzdHJ1Y3QgZDBfZ2VvbWV0cnlfZmVhdHVyZXMgeworCS8qCisJICogc2tpcCAzMiBiaXRzIGZy b20gaGVhZGVyLCBuZWVkZWQgdG8gYWxpZ24gdGhlIHN0cnVjdCB0byA2NCBiaXRzLgorCSAqLwor CXU4IGhlYWRlcls0XTsKKwkvKgorCSAqIHJlc2VydmVkMDE6CisJICogYml0cyAxLTY6IHJlc2Vy dmVkCisJICogYml0IDA6IGFsaWduCisJICovCisJdTggcmVzZXJ2ZWQwMTsKKwl1OCByZXNlcnZl ZDAyWzddOworCXUzMiBsb2dpY2FsX2Jsb2NrX3NpemU7CisJdTY0IGFsaWdubWVudF9ncmFudWxh cml0eTsKKwl1NjQgbG93ZXN0X2FsaWduZWRfbGJhOworfTsKKworLyoKKyAqIEVudGVycHJpc2Ug U1NDIEZlYXR1cmUKKyAqCisgKiBjb2RlID09IDB4MDEwMAorICovCitzdHJ1Y3QgZDBfZW50ZXJw cmlzZV9zc2MgeworCXUxNiBiYXNlQ29tSUQ7CisJdTE2IG51bUNvbUlEczsKKwkvKiByYW5nZV9j cm9zc2luZzoKKwkgKiBiaXRzIDEtNjogcmVzZXJ2ZWQKKwkgKiBiaXQgMDogcmFuZ2UgY3Jvc3Np bmcKKwkgKi8KKwl1OCByYW5nZV9jcm9zc2luZzsKKwl1OCByZXNlcnZlZDAxOworCXUxNiByZXNl cnZlZDAyOworCXUzMiByZXNlcnZlZDAzOworCXUzMiByZXNlcnZlZDA0OworfTsKKworLyoKKyAq IE9wYWwgVjEgZmVhdHVyZQorICoKKyAqIGNvZGUgPT0gMHgwMjAwCisgKi8KK3N0cnVjdCBkMF9v cGFsX3YxMDAgeworCXUxNiBiYXNlQ29tSUQ7CisJdTE2IG51bUNvbUlEczsKK307CisKKy8qCisg KiBTaW5nbGUgVXNlciBNb2RlIGZlYXR1cmUKKyAqCisgKiBjb2RlID09IDB4MDIwMQorICovCitz dHJ1Y3QgZDBfc2luZ2xlX3VzZXJfbW9kZSB7CisJdTMyIG51bV9sb2NraW5nX29iamVjdHM7CisJ LyogcmVzZXJ2ZWQwMToKKwkgKiBiaXQgMDogYW55CisJICogYml0IDE6IGFsbAorCSAqIGJpdCAy OiBwb2xpY3kKKwkgKiBiaXRzIDMtNzogcmVzZXJ2ZWQKKwkgKi8KKwl1OCByZXNlcnZlZDAxOwor CXU4IHJlc2VydmVkMDI7CisJdTE2IHJlc2VydmVkMDM7CisJdTMyIHJlc2VydmVkMDQ7Cit9Owor CisvKgorICogQWRkaXRvbmFsIERhdGFzdG9yZXMgZmVhdHVyZQorICoKKyAqIGNvZGUgPT0gMHgw MjAyCisgKi8KK3N0cnVjdCBkMF9kYXRhc3RvcmVfdGFibGUgeworCXUxNiByZXNlcnZlZDAxOwor CXUxNiBtYXhfdGFibGVzOworCXUzMiBtYXhfc2l6ZV90YWJsZXM7CisJdTMyIHRhYmxlX3NpemVf YWxpZ25tZW50OworfTsKKworLyoKKyAqIE9QQUwgMi4wIGZlYXR1cmUKKyAqCisgKiBjb2RlID09 IDB4MDIwMworICovCitzdHJ1Y3QgZDBfb3BhbF92MjAwIHsKKwl1MTYgYmFzZUNvbUlEOworCXUx NiBudW1Db21JRHM7CisJLyogcmFuZ2VfY3Jvc3Npbmc6CisJICogYml0cyAxLTY6IHJlc2VydmVk CisJICogYml0IDA6IHJhbmdlIGNyb3NzaW5nCisJICovCisJdTggcmFuZ2VfY3Jvc3Npbmc7CisJ LyogbnVtX2xvY2tpbmdfYWRtaW5fYXV0aDoKKwkgKiBub3QgYWxpZ25lZCB0byAxNiBiaXRzLCBz byB1c2UgdHdvIHU4LgorCSAqIHN0b3JlZCBpbiBiaWcgZW5kaWFuOgorCSAqIDA6IE1TQgorCSAq IDE6IExTQgorCSAqLworCXU4IG51bV9sb2NraW5nX2FkbWluX2F1dGhbMl07CisJLyogbnVtX2xv Y2tpbmdfdXNlcl9hdXRoOgorCSAqIG5vdCBhbGlnbmVkIHRvIDE2IGJpdHMsIHNvIHVzZSB0d28g dTguCisJICogc3RvcmVkIGluIGJpZyBlbmRpYW46CisJICogMDogTVNCCisJICogMTogTFNCCisJ ICovCisJdTggbnVtX2xvY2tpbmdfdXNlcl9hdXRoWzJdOworCXU4IGluaXRpYWxQSU47CisJdTgg cmV2ZXJ0ZWRQSU47CisJdTggcmVzZXJ2ZWQwMTsKKwl1MzIgcmVzZXJ2ZWQwMjsKK307CisKKy8q IFVuaW9uIG9mIGZlYXR1cmVzIHVzZWQgdG8gcGFyc2UgdGhlIGRpc2NvdmVyeSAwIHJlc3BvbnNl ICovCitzdHJ1Y3QgZDBfZmVhdHVyZXMgeworCXUxNiBjb2RlOworCS8qCisJICogcl92ZXJzaW9u IGJpdHM6CisJICogYml0cyA0LTc6IHZlcnNpb24KKwkgKiBiaXRzIDAtMzogcmVzZXJ2ZWQKKwkg Ki8KKwl1OCByX3ZlcnNpb247CisJdTggbGVuZ3RoOworCXU4IGZlYXR1cmVzW107Cit9OworCitz dHJ1Y3Qga2V5ICpyZXF1ZXN0X3VzZXJfa2V5KGNvbnN0IGNoYXIgKm1hc3Rlcl9kZXNjLCBjb25z dCB1OCAqKm1hc3Rlcl9rZXksCisJCQkgICAgIHNpemVfdCAqbWFzdGVyX2tleWxlbik7CisKKyNl bmRpZiAvKiBfTlZNRV9PUEFMX0lOVEVSTkFMX0ggKi8KZGlmZiAtLWdpdCBhL2xpYi9zZWQtb3Bh bF9rZXkuYyBiL2xpYi9zZWQtb3BhbF9rZXkuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAw MDAwMDAwLi4wYjRkZTAxCi0tLSAvZGV2L251bGwKKysrIGIvbGliL3NlZC1vcGFsX2tleS5jCkBA IC0wLDAgKzEsNDYgQEAKKy8qCisgKiBDb3B5cmlnaHQgwqkgMjAxNiBJbnRlbCBDb3Jwb3JhdGlv bgorICoKKyAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0 byBhbnkgcGVyc29uIG9idGFpbmluZyBhCisgKiBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFz c29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLAorICogdG8gZGVh bCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQg bGltaXRhdGlvbgorICogdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1 Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsCisgKiBhbmQvb3Igc2VsbCBjb3BpZXMgb2Yg dGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUKKyAqIFNvZnR3 YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRp dGlvbnM6CisgKgorICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlz c2lvbiBub3RpY2UgKGluY2x1ZGluZyB0aGUgbmV4dAorICogcGFyYWdyYXBoKSBzaGFsbCBiZSBp bmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZQorICog U29mdHdhcmUuCisgKgorICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhP VVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1IKKyAqIElNUExJRUQsIElOQ0xVRElO RyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAor ICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4g IElOIE5PIEVWRU5UIFNIQUxMCisgKiBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBC RSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUgorICogTElBQklMSVRZLCBX SEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJ TkcKKyAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9S IFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MKKyAqIElOIFRIRSBTT0ZUV0FSRS4KKyAqCisgKiBB dXRob3I6CisgKiAgICBSYWZhZWwgQW50b2dub2xsaSA8cmFmYWVsLmFudG9nbm9sbGlAaW50ZWwu Y29tPgorICovCisKKyNpbmNsdWRlIDxsaW51eC9rZXkuaD4KKyNpbmNsdWRlICJzZWQtb3BhbF9p bnRlcm5hbC5oIgorCitzdHJ1Y3Qga2V5ICpyZXF1ZXN0X3VzZXJfa2V5KGNvbnN0IGNoYXIgKm1h c3Rlcl9kZXNjLCBjb25zdCB1OCAqKm1hc3Rlcl9rZXksCisJCQkgICAgIHNpemVfdCAqbWFzdGVy X2tleWxlbikKK3sKKwljb25zdCBzdHJ1Y3QgdXNlcl9rZXlfcGF5bG9hZCAqdXBheWxvYWQ7CisJ c3RydWN0IGtleSAqdWtleTsKKworCXVrZXkgPSByZXF1ZXN0X2tleSgma2V5X3R5cGVfdXNlciwg bWFzdGVyX2Rlc2MsIE5VTEwpOworCWlmIChJU19FUlIodWtleSkpCisJCWdvdG8gZXJyb3I7CisK Kwlkb3duX3JlYWQoJnVrZXktPnNlbSk7CisJdXBheWxvYWQgPSB1c2VyX2tleV9wYXlsb2FkKHVr ZXkpOworCSptYXN0ZXJfa2V5ID0gdXBheWxvYWQtPmRhdGE7CisJKm1hc3Rlcl9rZXlsZW4gPSB1 cGF5bG9hZC0+ZGF0YWxlbjsKK2Vycm9yOgorCXJldHVybiB1a2V5OworfQpkaWZmIC0tZ2l0IGEv bGliL3NlZC5jIGIvbGliL3NlZC5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAu LjA2Y2FjZDkKLS0tIC9kZXYvbnVsbAorKysgYi9saWIvc2VkLmMKQEAgLTAsMCArMSwzMDMgQEAK KyNpbmNsdWRlIDxsaW51eC9ibGtkZXYuaD4KKyNpbmNsdWRlIDxsaW51eC9zZWQuaD4KKyNpbmNs dWRlIDxsaW51eC9zZWQtb3BhbC5oPgorCisjaWZuZGVmIENPTkZJR19TRURfT1BBTAorc3RhdGlj IGludCBzZWRfb3BhbF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf a2V5ICpzZWQpCisJeyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KK3N0YXRpYyBpbnQgc2VkX29wYWxf bG9ja191bmxvY2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtl eSkKKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQorc3RhdGljIGludCBzZWRfb3BhbF90YWtlX293 bmVyc2hpcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQor CXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9CitzdGF0aWMgaW50IHNlZF9vcGFsX2FjdGl2YXRlX2xz cChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorCXsgcmV0 dXJuIC1FT1BOT1RTVVBQOyB9CitzdGF0aWMgaW50IHNlZF9vcGFsX3NldF9wdyhzdHJ1Y3QgYmxv Y2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorCXsgcmV0dXJuIC1FT1BOT1RT VVBQOyB9CitzdGF0aWMgaW50IHNlZF9vcGFsX2FjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2Rl dmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKKwl7IHJldHVybiAtRU9QTk9UU1VQUDsg fQorc3RhdGljIGludCBzZWRfb3BhbF9yZXZlcnR0cGVyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJk ZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCisJeyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KK3N0YXRp YyBpbnQgc2VkX29wYWxfc2V0dXBfbG9ja2luZ19yYW5nZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpi ZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorCXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9CitzdGF0 aWMgaW50IHNlZF9vcGFsX2FkZHVzZXJfdG9fbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg c3RydWN0IHNlZF9rZXkgKmtleSkKKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQorc3RhdGljIGlu dCBzZWRfb3BhbF9kb19tYnIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9r ZXkgKmtleSkKKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQorc3RhdGljIGludCBzZWRfb3BhbF9l cmFzZV9scihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQor CXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9CisKKyNlbHNlCisKK3N0YXRpYyBpbnQgc2VkX29wYWxf c2F2ZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorewor CisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8 CisJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQorCQlyZXR1cm4gLUVPUE5PVFNV UFA7CisKKwlyZXR1cm4gb3BhbF9zYXZlKGJkZXYsIGtleSk7Cit9CisKK3N0YXRpYyBpbnQgc2Vk X29wYWxfbG9ja191bmxvY2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9r ZXkgKmtleSkKK3sKKworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRf ZGlzay0+Zm9wcyB8fAorCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0 dXJuIC1FT1BOT1RTVVBQOworCisJcmV0dXJuIG9wYWxfbG9ja191bmxvY2soYmRldiwga2V5KTsK K30KKworc3RhdGljIGludCBzZWRfb3BhbF90YWtlX293bmVyc2hpcChzdHJ1Y3QgYmxvY2tfZGV2 aWNlICpiZGV2LAorCQkJCSAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlpZiAoIWJkZXYg fHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKKwkgICAgIWJkZXYt PmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVybiAtRU9QTk9UU1VQUDsKKworCXJldHVy biBvcGFsX3Rha2Vfb3duZXJzaGlwKGJkZXYsIGtleSk7Cit9CisKK3N0YXRpYyBpbnQgc2VkX29w YWxfYWN0aXZhdGVfbHNwKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkJIHN0cnVjdCBz ZWRfa2V5ICprZXkpCit7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYt PmJkX2Rpc2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJ CXJldHVybiAtRU9QTk9UU1VQUDsKKworCXJldHVybiBvcGFsX2FjdGl2YXRlX2xzcChiZGV2LCBr ZXkpOworfQorCitzdGF0aWMgaW50IHNlZF9vcGFsX3NldF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNl ICpiZGV2LAorCQkJICAgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKworCWlmICghYmRldiB8fCAh YmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAorCSAgICAhYmRldi0+YmRf ZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJuIC1FT1BOT1RTVVBQOworCisJcmV0dXJuIG9w YWxfc2V0X25ld19wdyhiZGV2LCBrZXkpOworfQorCitzdGF0aWMgaW50IHNlZF9vcGFsX2FjdGl2 YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCQkgIHN0cnVjdCBzZWRfa2V5 ICprZXkpCit7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rp c2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVy biAtRU9QTk9UU1VQUDsKKworCXJldHVybiBvcGFsX2FjdGl2YXRlX3VzZXIoYmRldiwga2V5KTsK K30KKworc3RhdGljIGludCBzZWRfb3BhbF9yZXZlcnR0cGVyKHN0cnVjdCBibG9ja19kZXZpY2Ug KmJkZXYsCisJCQkgICAgICAgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKworCWlmICghYmRldiB8 fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAorCSAgICAhYmRldi0+ YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJuIC1FT1BOT1RTVVBQOworCisJcmV0dXJu IG9wYWxfcmV2ZXJ0dHBlcihiZGV2LCBrZXkpOworfQorCitzdGF0aWMgaW50IHNlZF9vcGFsX3Nl dHVwX2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkgICAgIHN0cnVjdCBzZWRfa2V5 ICprZXkpCit7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rp c2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVy biAtRU9QTk9UU1VQUDsKKworCXJldHVybiBvcGFsX3NldHVwX2xvY2tpbmdfcmFuZ2UoYmRldiwg a2V5KTsKK30KKworc3RhdGljIGludCBzZWRfb3BhbF9hZGR1c2VyX3RvX2xyKHN0cnVjdCBibG9j a19kZXZpY2UgKmJkZXYsCisJCQkgICAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlpZiAo IWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKKwkgICAg IWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVybiAtRU9QTk9UU1VQUDsKKwor CXJldHVybiBvcGFsX2FkZF91c2VyX3RvX2xyKGJkZXYsIGtleSk7Cit9CisKK3N0YXRpYyBpbnQg c2VkX29wYWxfZG9fbWJyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkgICBzdHJ1Y3Qg c2VkX2tleSAqa2V5KQoreworCisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2 LT5iZF9kaXNrLT5mb3BzIHx8CisJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQor CQlyZXR1cm4gLUVPUE5PVFNVUFA7CisKKwlyZXR1cm4gb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFk b3dfbWJyKGJkZXYsIGtleSk7Cit9CisKK3N0YXRpYyBpbnQgc2VkX29wYWxfZXJhc2VfbHIoc3Ry dWN0IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCSAgICAgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sK KworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8 fAorCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJuIC1FT1BOT1RT VVBQOworCisJcmV0dXJuIG9wYWxfZXJhc2VfbG9ja2luZ19yYW5nZShiZGV2LCBrZXkpOworfQor I2VuZGlmCisKK2ludCBzZWRfc2F2ZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qg c2VkX2tleSAqa2V5KQoreworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+ YmRfZGlzay0+Zm9wcyB8fAorCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJ cmV0dXJuIC1FT1BOT1RTVVBQOworCisJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBP UEFMX0xPQ0tfVU5MT0NLOgorCQlyZXR1cm4gc2VkX29wYWxfc2F2ZShiZGV2LCBrZXkpOworCX0K KworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworaW50IHNlZF9sb2NrX3VubG9jayhzdHJ1Y3Qg YmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQoreworCWlmICghYmRldiB8 fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAorCSAgICAhYmRldi0+ YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJuIC1FT1BOT1RTVVBQOworCisJc3dpdGNo IChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBPUEFMX0xPQ0tfVU5MT0NLOgorCQlyZXR1cm4gc2Vk X29wYWxfbG9ja191bmxvY2soYmRldiwga2V5KTsKKwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7 Cit9CisKK2ludCBzZWRfdGFrZV9vd25lcnNoaXAoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg c3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwg IWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19v cHMpCisJCXJldHVybiAtRU9QTk9UU1VQUDsKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgewor CWNhc2UgT1BBTDoKKwkJcmV0dXJuIHNlZF9vcGFsX3Rha2Vfb3duZXJzaGlwKGJkZXYsIGtleSk7 CisJfQorCisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQorCitpbnQgc2VkX2FjdGl2YXRlX2xzcChz dHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQoreworCWlmICgh YmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAorCSAgICAh YmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJuIC1FT1BOT1RTVVBQOworCisJ c3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBPUEFMOgorCQlyZXR1cm4gc2VkX29wYWxf YWN0aXZhdGVfbHNwKGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQor CitpbnQgc2VkX3NldF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tl eSAqa2V5KQoreworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlz ay0+Zm9wcyB8fAorCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJu IC1FT1BOT1RTVVBQOworCisJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBPUEFMX1BX OgorCQlyZXR1cm4gc2VkX29wYWxfc2V0X3B3KGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1F T1BOT1RTVVBQOworfQorCitpbnQgc2VkX2FjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2Rldmlj ZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJk X2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZv cHMtPnNlY19vcHMpCisJCXJldHVybiAtRU9QTk9UU1VQUDsKKworCXN3aXRjaCAoa2V5LT5zZWRf dHlwZSkgeworCWNhc2UgT1BBTF9BQ1RfVVNSOgorCQlyZXR1cm4gc2VkX29wYWxfYWN0aXZhdGVf dXNlcihiZGV2LCBrZXkpOworCX0KKworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworaW50IHNl ZF9yZXZlcnR0cGVyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICpr ZXkpCit7CisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5m b3BzIHx8CisJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQorCQlyZXR1cm4gLUVP UE5PVFNVUFA7CisKKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsKKwljYXNlIE9QQUw6CisJCXJl dHVybiBzZWRfb3BhbF9yZXZlcnR0cGVyKGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1FT1BO T1RTVVBQOworfQorCitpbnQgc2VkX3NldHVwX2xvY2tpbmdfcmFuZ2Uoc3RydWN0IGJsb2NrX2Rl dmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlpZiAoIWJkZXYgfHwgIWJkZXYt PmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2st PmZvcHMtPnNlY19vcHMpCisJCXJldHVybiAtRU9QTk9UU1VQUDsKKworCXN3aXRjaCAoa2V5LT5z ZWRfdHlwZSkgeworCWNhc2UgT1BBTF9MUl9TRVRVUDoKKwkJcmV0dXJuIHNlZF9vcGFsX3NldHVw X2xyKGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQorCitpbnQgc2Vk X2FkZHVzZXJfdG9fbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkg KmtleSkKK3sKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2st PmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVybiAt RU9QTk9UU1VQUDsKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTF9MT0NL X1VOTE9DSzoKKwkJcmV0dXJuIHNlZF9vcGFsX2FkZHVzZXJfdG9fbHIoYmRldiwga2V5KTsKKwl9 CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisKK2ludCBzZWRfZG9fbWJyKHN0cnVjdCBibG9j a19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisJaWYgKCFiZGV2IHx8ICFi ZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8CisJICAgICFiZGV2LT5iZF9k aXNrLT5mb3BzLT5zZWNfb3BzKQorCQlyZXR1cm4gLUVPUE5PVFNVUFA7CisKKwlzd2l0Y2ggKGtl eS0+c2VkX3R5cGUpIHsKKwljYXNlIE9QQUxfTUJSX0RBVEE6CisJCXJldHVybiBzZWRfb3BhbF9k b19tYnIoYmRldiwga2V5KTsKKwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisKK2ludCBz ZWRfZXJhc2VfbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtl eSkKK3sKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZv cHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVybiAtRU9Q Tk9UU1VQUDsKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTDoKKwkJcmV0 dXJuIHNlZF9vcGFsX2VyYXNlX2xyKGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1FT1BOT1RT VVBQOworfQotLSAKMi43LjQKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fXwpMaW51eC1udm1lIG1haWxpbmcgbGlzdApMaW51eC1udm1lQGxpc3RzLmluZnJh ZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51 eC1udm1lCg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: scott.bauer@intel.com (Scott Bauer) Date: Mon, 31 Oct 2016 15:58:15 -0600 Subject: [RFC PATCH 2/6] lib: Add Sed-opal library In-Reply-To: <1477951099-3127-1-git-send-email-scott.bauer@intel.com> References: <1477951099-3127-1-git-send-email-scott.bauer@intel.com> Message-ID: <1477951099-3127-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 | 3337 +++++++++++++++++++++++++++++++++++++++++++++++ lib/sed-opal_internal.h | 586 +++++++++ lib/sed-opal_key.c | 46 + lib/sed.c | 303 +++++ 4 files changed, 4272 insertions(+) create mode 100644 lib/sed-opal.c create mode 100644 lib/sed-opal_internal.h create mode 100644 lib/sed-opal_key.c create mode 100644 lib/sed.c diff --git a/lib/sed-opal.c b/lib/sed-opal.c new file mode 100644 index 0000000..10b3348 --- /dev/null +++ b/lib/sed-opal.c @@ -0,0 +1,3337 @@ +/* + * Copyright ? 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Rafael Antognolli + * Scott Bauer + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ":OPAL: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sed-opal_internal.h" + +#define IO_BUFFER_LENGTH 2048 + +#define MAX_TOKS 64 + +struct opal_cmd { + struct block_device *bdev; + sec_cb *cb; + void *cb_data; + + size_t pos; + u8 cmd_buf[IO_BUFFER_LENGTH * 2]; + u8 resp_buf[IO_BUFFER_LENGTH * 2]; + u8 *cmd; + u8 *resp; +}; + +/* + * On the parsed response, we don't store again the toks that are already + * stored in the response buffer. Instead, for each token, we just store a + * pointer to the position in the buffer where the token starts, and the size + * of the token in bytes. + */ +struct opal_resp_tok { + const u8 *pos; + size_t len; + enum OPAL_RESPONSE_TOKEN type; + enum OPAL_ATOM_WIDTH width; + union { + u64 u; + s64 s; + } stored; +}; + +/* + * From the response header it's not possible to know how many tokens there are + * on the payload. So we hardcode that the maximum will be MAX_TOKS, and later + * if we start dealing with messages that have more than that, we can increase + * this number. This is done to avoid having to make two passes through the + * response, the first one counting how many tokens we have and the second one + * actually storing the positions. + */ +struct parsed_resp { + int num; + struct opal_resp_tok toks[MAX_TOKS]; +}; + +struct opal_dev; + +typedef void (*opal_cb)(int error, struct opal_dev *dev); + +typedef int (*opal_step)(struct opal_dev *dev); + +struct opal_completion { + struct completion cmd_completion; + int completion_status; +}; + +struct opal_dev { + struct block_device *bdev; + struct opal_completion *completion; + struct opal_lock_unlock lkul; + const opal_step *funcs; + void **func_data; + bool resume_from_suspend; + struct opal_suspend_unlk *resume_data; + size_t num_func_data; + atomic_t in_use; + sector_t start; + sector_t length; + u8 lr; + u8 key_type; + u8 key_name[OPAL_KEY_MAX]; + size_t key_name_len; + u8 key[OPAL_KEY_MAX]; + size_t key_len; + u16 comID; + u32 HSN; + u32 TSN; + u64 align; + u64 lowest_lba; + struct list_head node; + char disk_name[DISK_NAME_LEN]; + int state; + + struct opal_cmd cmd; + struct parsed_resp parsed; + + size_t prev_d_len; + void *prev_data; + + sec_cb *final_cb; + void *final_cb_data; + opal_step error_cb; + void *error_cb_data; + opal_cb oper_cb; +}; + +LIST_HEAD(opal_list); +DEFINE_SPINLOCK(list_spinlock); + +static void print_buffer(const u8 *ptr, u32 length) +{ +#ifdef DEBUG + print_hex_dump_bytes("OPAL: ", DUMP_PREFIX_OFFSET, ptr, length); + pr_debug("\n"); +#endif +} + +#define TPER_SYNC_SUPPORTED BIT(0) + +static bool check_tper(const void *data) +{ + const struct d0_tper_features *tper = data; + u8 flags = tper->supported_features; + + if (!(flags & TPER_SYNC_SUPPORTED)) { + pr_err("TPer sync not supported. flags = %d\n", + tper->supported_features); + return false; + } + + return true; +} + +static bool check_SUM(const void *data) +{ + const struct d0_single_user_mode *sum = data; + u32 nlo = be32_to_cpu(sum->num_locking_objects); + + if (nlo == 0) { + pr_err("Need at least one locking object.\n"); + return false; + } + + pr_debug("Number of locking objects: %d\n", nlo); + + return true; +} + +static u16 get_comID_v100(const void *data) +{ + const struct d0_opal_v100 *v100 = data; + + return be16_to_cpu(v100->baseComID); +} + +static u16 get_comID_v200(const void *data) +{ + const struct d0_opal_v200 *v200 = data; + + return be16_to_cpu(v200->baseComID); +} + +static int __opal_send_cmd(struct opal_suspend_unlk *data, u16 comID, + void *buffer, size_t buflen, sec_cb *cb, + void *cb_data) +{ + return data->ops.send(data->data, comID, TCG_SECP_01, buffer, buflen, + cb, cb_data); +} +static int _opal_send_cmd(struct block_device *bdev, u16 comID, + void *buffer, size_t buflen, + sec_cb *cb, void *cb_data) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + + return ops->send(bdev->bd_disk->private_data, comID, + TCG_SECP_01, buffer, buflen, + cb, cb_data); +} + +static int __opal_recv_cmd(struct opal_suspend_unlk *data, u16 comID, + void *buffer, size_t buflen, sec_cb *cb, + void *cb_data) +{ + return data->ops.recv(data->data, comID, TCG_SECP_01, buffer, buflen, + cb, cb_data); +} + +static int _opal_recv_cmd(struct block_device *bdev, u16 comID, + void *buffer, size_t buflen, + sec_cb *cb, void *cb_data) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + + return ops->recv(bdev->bd_disk->private_data, comID, + TCG_SECP_01, buffer, buflen, + cb, cb_data); +} + +static void opal_send_cb_cont(int error, void *data) +{ + struct opal_dev *dev = data; + size_t buflen = IO_BUFFER_LENGTH; + void *buffer = dev->cmd.resp; + struct opal_header *hdr = buffer; + + pr_debug("%s: Sent OPAL command: error=%d, outstanding=%d, minTransfer=%d\n", + dev->disk_name, error, hdr->cp.outstandingData, + hdr->cp.minTransfer); + + if (error || hdr->cp.outstandingData == 0 || + hdr->cp.minTransfer != 0) { + if (dev->cmd.cb) + dev->cmd.cb(error, dev->cmd.cb_data); + return; + } + + memset(buffer, 0, buflen); + if (dev->resume_from_suspend) + __opal_recv_cmd(dev->resume_data, dev->comID, + buffer, buflen, opal_send_cb_cont, dev); + else + _opal_recv_cmd(dev->bdev, dev->comID, buffer, buflen, + opal_send_cb_cont, dev); +} + +static void opal_send_cb(int error, void *data) +{ + struct opal_dev *dev = data; + size_t buflen = IO_BUFFER_LENGTH; + void *buffer = dev->cmd.resp; + + if (error) { + if (dev->cmd.cb) + dev->cmd.cb(error, dev->cmd.cb_data); + return; + } + + memset(buffer, 0, buflen); + if (dev->resume_from_suspend) + __opal_recv_cmd(dev->resume_data, dev->comID, + buffer, buflen, opal_send_cb_cont, dev); + else + _opal_recv_cmd(dev->bdev, dev->comID, buffer, buflen, + opal_send_cb_cont, dev); +} + +static int opal_send_recv(struct opal_dev *dev, sec_cb *cb, void *cb_data) +{ + size_t buflen = IO_BUFFER_LENGTH; + void *buffer = dev->cmd.cmd; + int ret; + + dev->cmd.cb = cb; + dev->cmd.cb_data = cb_data; + if (dev->resume_from_suspend) + ret = __opal_send_cmd(dev->resume_data, dev->comID, buffer, + buflen, opal_send_cb, dev); + else + ret = _opal_send_cmd(dev->bdev, dev->comID, buffer, buflen, + opal_send_cb, dev); + + return ret; +} + +static void check_geometry(struct opal_dev *dev, const void *data) +{ + const struct d0_geometry_features *geo = data; + + dev->align = geo->alignment_granularity; + dev->lowest_lba = geo->lowest_aligned_lba; +} + +static void opal_discovery0_end(int error, void *data) +{ + bool foundComID = false, supported = true, single_user = false; + struct opal_dev *dev = data; + const struct d0_header *hdr; + const u8 *epos, *cpos; + u16 comID = 0; + + if (error) { + pr_err("%s: Sending discovery0 failed\n", dev->disk_name); + goto err_callback; + } + + epos = dev->cmd.resp; + cpos = dev->cmd.resp; + hdr = (struct d0_header *)dev->cmd.resp; + + print_buffer(dev->cmd.resp, be32_to_cpu(hdr->length)); + + epos += be32_to_cpu(hdr->length); /* end of buffer */ + cpos += sizeof(*hdr); /* current position on buffer */ + + while (cpos < epos && supported) { + const struct d0_features *body = + (const struct d0_features *)cpos; + + switch (be16_to_cpu(body->code)) { + case FC_TPER: + supported = check_tper(body->features); + break; + case FC_SINGLEUSER: + single_user = check_SUM(body->features); + break; + case FC_GEOMETRY: + check_geometry(dev, body); + break; + case FC_LOCKING: + case FC_ENTERPRISE: + case FC_DATASTORE: + /* some ignored properties */ + pr_debug("%s: Found OPAL feature description: %d\n", + dev->disk_name, be16_to_cpu(body->code)); + break; + case FC_OPALV100: + comID = get_comID_v100(body->features); + foundComID = true; + break; + case FC_OPALV200: + comID = get_comID_v200(body->features); + foundComID = true; + break; + default: + if (be16_to_cpu(body->code) > 0xbfff) { + /* vendor specific, just ignore */ + } else { + pr_warn("%s: OPAL Unknown feature: %d\n", + dev->disk_name, be16_to_cpu(body->code)); + } + } + cpos += body->length + 4; + } + + if (!supported) { + pr_err("%s: Device not supported\n", dev->disk_name); + goto err_callback; + } + + if (!single_user) + pr_warn("%s: Device doesn't support single user mode\n", + dev->disk_name); + + if (!foundComID) { + pr_warn("%s: Could not find OPAL comID for device. OPAL kernel unlocking will be disabled\n", + dev->disk_name); + goto err_callback; + } + + dev->comID = comID; + +err_callback: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static int opal_discovery0(struct opal_dev *dev) +{ + memset(dev->cmd.resp, 0, IO_BUFFER_LENGTH); + + if (dev->resume_from_suspend) + return __opal_recv_cmd(dev->resume_data, 0x0001, + dev->cmd.resp, IO_BUFFER_LENGTH, + opal_discovery0_end, dev); + + return _opal_recv_cmd(dev->bdev, 0x0001, dev->cmd.resp, + IO_BUFFER_LENGTH, opal_discovery0_end, + dev); +} + +static void add_token_u8(struct opal_cmd *cmd, u8 tok) +{ + cmd->cmd[cmd->pos++] = tok; +} + +static ssize_t test_and_add_token_u8(struct opal_cmd *cmd, u8 tok) +{ + BUILD_BUG_ON(IO_BUFFER_LENGTH >= SIZE_MAX); + + if (cmd->pos >= IO_BUFFER_LENGTH - 1) { + pr_err("Error adding u8: end of buffer.\n"); + return -ERANGE; + } + + add_token_u8(cmd, tok); + + return 1; +} + +#define TINY_ATOM_DATA_MASK GENMASK(5, 0) +#define TINY_ATOM_SIGNED BIT(6) + +#define SHORT_ATOM_ID BIT(7) +#define SHORT_ATOM_BYTESTRING BIT(5) +#define SHORT_ATOM_SIGNED BIT(4) +#define SHORT_ATOM_LEN_MASK GENMASK(3, 0) + +static void add_short_atom_header(struct opal_cmd *cmd, bool bytestring, + bool has_sign, int len) +{ + u8 atom; + + atom = SHORT_ATOM_ID; + atom |= bytestring ? SHORT_ATOM_BYTESTRING : 0; + atom |= has_sign ? SHORT_ATOM_SIGNED : 0; + atom |= len & SHORT_ATOM_LEN_MASK; + + add_token_u8(cmd, atom); +} + +#define MEDIUM_ATOM_ID (BIT(7) | BIT(6)) +#define MEDIUM_ATOM_BYTESTRING BIT(4) +#define MEDIUM_ATOM_SIGNED BIT(3) +#define MEDIUM_ATOM_LEN_MASK GENMASK(2, 0) + +static void add_medium_atom_header(struct opal_cmd *cmd, bool bytestring, + bool has_sign, int len) +{ + u8 header0; + + header0 = MEDIUM_ATOM_ID; + header0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0; + header0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0; + header0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK; + cmd->cmd[cmd->pos++] = header0; + cmd->cmd[cmd->pos++] = len; +} + +static void add_token_u64(struct opal_cmd *cmd, u64 number, size_t len) +{ + add_short_atom_header(cmd, false, false, len); + + while (len--) { + u8 n = number >> (len * 8); + + add_token_u8(cmd, n); + } +} + +static ssize_t test_and_add_token_u64(struct opal_cmd *cmd, u64 number) +{ + int len; + int msb; + + if (!(number & ~TINY_ATOM_DATA_MASK)) + return test_and_add_token_u8(cmd, number); + + msb = fls(number); + len = DIV_ROUND_UP(msb, 4); + + if (cmd->pos >= IO_BUFFER_LENGTH - len - 1) { + pr_err("Error adding u64: end of buffer.\n"); + return -ERANGE; + } + + add_token_u64(cmd, number, len); + + /* return length of token plus atom */ + return len + 1; +} + +static void add_token_bytestring(struct opal_cmd *cmd, + const u8 *bytestring, size_t len) +{ + memcpy(&cmd->cmd[cmd->pos], bytestring, len); + cmd->pos += len; +} + +static ssize_t test_and_add_token_bytestring(struct opal_cmd *cmd, + const u8 *bytestring, size_t len) +{ + size_t header_len = 1; + bool is_short_atom = true; + + if (len & ~SHORT_ATOM_LEN_MASK) { + header_len = 2; + is_short_atom = false; + } + + if (cmd->pos >= IO_BUFFER_LENGTH - len - header_len) { + pr_err("Error adding bytestring: end of buffer.\n"); + return -ERANGE; + } + + if (is_short_atom) + add_short_atom_header(cmd, true, false, len); + else + add_medium_atom_header(cmd, true, false, len); + + add_token_bytestring(cmd, bytestring, len); + + return header_len + len; +} + +#define LOCKING_RANGE_NON_GLOBAL 0x03 + +static int build_locking_range(u8 *buffer, size_t length, u8 lr) +{ + if (length < OPAL_UID_LENGTH) + return -ERANGE; + + memcpy(buffer, OPALUID[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH); + + if (lr == 0) + return 0; + buffer[5] = LOCKING_RANGE_NON_GLOBAL; + buffer[7] = lr; + + return 0; +} + +static int build_locking_user(u8 *buffer, size_t length, u8 lr) +{ + if (length < OPAL_UID_LENGTH) + return -ERANGE; + + memcpy(buffer, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH); + + buffer[7] = lr + 1; + + return 0; +} + +/* + * N = number of format specifiers (1-999) to be replicated + * c = u8 + * u = u64 + * s = bytestring, length + * + * ret = test_and_add_token_va(cmd, "c", + * u8_val1); + * + * ret = test_and_add_token_va(cmd, "2c2u", + * u8_val1, u8_val2, u64_val1, u64_val2); + * + * ret = test_and_add_token_va(cmd, "3s", + * bytestring1, length1, + * bytestring2, length2, + * bytestring3, length3); + */ +static int test_and_add_token_va(struct opal_cmd *cmd, + const char *fmt, ...) +{ + const u8 *it = fmt, *tmp; + int ret, num = 1, sum = 0; + va_list ap; + + va_start(ap, fmt); + + while (*it != '\0') { + u64 tok64 = 0; + u8 tok, *bstr; + size_t len; + + ret = 0; + + switch (*it) { + case '1' ... '9': + tmp = it; + num = 0; + while (*tmp >= '0' && *tmp <= '9') + num = num * 10 + (*tmp++ - '0'); + it = tmp; + continue; + case 'c': + while (num--) { + tok = va_arg(ap, unsigned int); + ret = test_and_add_token_u8(cmd, tok); + if (ret < 0) + goto err; + } + num = 1; + break; + case 'u': + while (num--) { + tok64 = va_arg(ap, u64); + ret = test_and_add_token_u64(cmd, tok64); + if (ret < 0) + goto err; + } + num = 1; + break; + case 's': + while (num--) { + bstr = va_arg(ap, u8 *); + len = va_arg(ap, size_t); + ret = test_and_add_token_bytestring(cmd, bstr, + len); + if (ret < 0) + goto err; + } + num = 1; + break; + case ' ': + case '\t': + /* ignored */ + break; + default: + pr_warn("Unrecognized type.\n"); + } + + it++; + sum += ret; + } + + va_end(ap); + + return sum; + + err: + pr_err("Token failed to be added.\n"); + return ret; +} + +static void set_comID(struct opal_cmd *cmd, u16 comID) +{ + struct opal_header *hdr = (struct opal_header *)cmd->cmd; + + hdr->cp.extendedComID[0] = comID >> 8; + hdr->cp.extendedComID[1] = comID; + hdr->cp.extendedComID[2] = 0; + hdr->cp.extendedComID[3] = 0; +} + +static int cmd_finalize(struct opal_cmd *cmd, u32 hsn, u32 tsn) +{ + struct opal_header *hdr; + int ret; + + ret = test_and_add_token_va(cmd, "6c", + OPAL_ENDOFDATA, OPAL_STARTLIST, + 0, 0, 0, OPAL_ENDLIST); + + if (ret < 0) { + pr_err("Error finalizing command.\n"); + return -EFAULT; + } + + hdr = (struct opal_header *) cmd->cmd; + + hdr->pkt.TSN = cpu_to_be32(tsn); + hdr->pkt.HSN = cpu_to_be32(hsn); + + hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr)); + while (cmd->pos % 4) { + if (cmd->pos >= IO_BUFFER_LENGTH) { + pr_err("Error: Buffer overrun\n"); + return -ERANGE; + } + cmd->cmd[cmd->pos++] = 0; + } + hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) - + sizeof(hdr->pkt)); + hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp)); + + return 0; +} + +static enum OPAL_RESPONSE_TOKEN token_type(const struct parsed_resp *resp, + int n) +{ + const struct opal_resp_tok *tok; + + if (n >= resp->num) { + pr_err("Token number doesn't exist: %d, resp: %d\n", + n, resp->num); + return OPAL_DTA_TOKENID_INVALID; + } + + tok = &resp->toks[n]; + if (tok->len == 0) { + pr_err("Token length must be non-zero\n"); + return OPAL_DTA_TOKENID_INVALID; + } + + return tok->type; +} + +/* + * This function returns 0 in case of invalid token. One should call + * token_type() first to find out if the token is valid or not. + */ +static enum OPAL_TOKEN response_get_token(const struct parsed_resp *resp, + int n) +{ + const struct opal_resp_tok *tok; + + if (n >= resp->num) { + pr_err("Token number doesn't exist: %d, resp: %d\n", + n, resp->num); + return 0; + } + + tok = &resp->toks[n]; + if (tok->len == 0) { + pr_err("Token length must be non-zero\n"); + return 0; + } + + return tok->pos[0]; +} + +static size_t response_parse_tiny(struct opal_resp_tok *tok, + const u8 *pos) +{ + tok->pos = pos; + tok->len = 1; + tok->width = OPAL_WIDTH_TINY; + + if (pos[0] & TINY_ATOM_SIGNED) { + tok->type = OPAL_DTA_TOKENID_SINT; + } else { + tok->type = OPAL_DTA_TOKENID_UINT; + tok->stored.u = pos[0] & 0x3f; + } + + return tok->len; +} + +static size_t response_parse_short(struct opal_resp_tok *tok, + const u8 *pos) +{ + tok->pos = pos; + tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1; + tok->width = OPAL_WIDTH_SHORT; + + if (pos[0] & SHORT_ATOM_BYTESTRING) { + tok->type = OPAL_DTA_TOKENID_BYTESTRING; + } else if (pos[0] & SHORT_ATOM_SIGNED) { + tok->type = OPAL_DTA_TOKENID_SINT; + } else { + u64 u_integer = 0; + int i, b = 0; + + tok->type = OPAL_DTA_TOKENID_UINT; + if (tok->len > 9) + pr_warn("uint64 with more than 8 bytes\n"); + for (i = tok->len - 1; i > 0; i--) { + u_integer |= ((u64)pos[i] << (8 * b)); + b++; + } + tok->stored.u = u_integer; + } + + return tok->len; +} + +static size_t response_parse_medium(struct opal_resp_tok *tok, + const u8 *pos) +{ + tok->pos = pos; + tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2; + tok->width = OPAL_WIDTH_MEDIUM; + + if (pos[0] & MEDIUM_ATOM_BYTESTRING) + tok->type = OPAL_DTA_TOKENID_BYTESTRING; + else if (pos[0] & MEDIUM_ATOM_SIGNED) + tok->type = OPAL_DTA_TOKENID_SINT; + else + tok->type = OPAL_DTA_TOKENID_UINT; + + return tok->len; +} + +#define LONG_ATOM_ID (BIT(7) | BIT(6) | BIT(5)) +#define LONG_ATOM_BYTESTRING BIT(1) +#define LONG_ATOM_SIGNED BIT(0) +static size_t response_parse_long(struct opal_resp_tok *tok, + const u8 *pos) +{ + tok->pos = pos; + tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4; + tok->width = OPAL_WIDTH_LONG; + + if (pos[0] & LONG_ATOM_BYTESTRING) + tok->type = OPAL_DTA_TOKENID_BYTESTRING; + else if (pos[0] & LONG_ATOM_SIGNED) + tok->type = OPAL_DTA_TOKENID_SINT; + else + tok->type = OPAL_DTA_TOKENID_UINT; + + return tok->len; +} + +static size_t response_parse_token(struct opal_resp_tok *tok, + const u8 *pos) +{ + tok->pos = pos; + tok->len = 1; + tok->type = OPAL_DTA_TOKENID_TOKEN; + tok->width = OPAL_WIDTH_TOKEN; + + return tok->len; +} + +static int response_parse(const u8 *buf, size_t length, + struct parsed_resp *resp) +{ + const struct opal_header *hdr; + struct opal_resp_tok *iter; + int ret, num_entries = 0; + u32 cpos = 0, total; + size_t token_length; + const u8 *pos; + + if (!buf) + return -EFAULT; + + if (!resp) + return -EFAULT; + + hdr = (struct opal_header *)buf; + pos = buf; + pos += sizeof(*hdr); + + pr_debug("Response size: cp: %d, pkt: %d, subpkt: %d\n", + be32_to_cpu(hdr->cp.length), + be32_to_cpu(hdr->pkt.length), + be32_to_cpu(hdr->subpkt.length)); + + if ((hdr->cp.length == 0) + || (hdr->pkt.length == 0) + || (hdr->subpkt.length == 0)) { + pr_err("Bad header length. cp: %d, pkt: %d, subpkt: %d\n", + be32_to_cpu(hdr->cp.length), + be32_to_cpu(hdr->pkt.length), + be32_to_cpu(hdr->subpkt.length)); + print_buffer(pos, sizeof(*hdr)); + ret = -EINVAL; + goto err; + } + + if (pos > buf + length) { + ret = -EFAULT; + goto err; + } + + iter = resp->toks; + total = be32_to_cpu(hdr->subpkt.length); + print_buffer(pos, total); + while (cpos < total) { + if (!(pos[0] & 0x80)) /* tiny atom */ + token_length = response_parse_tiny(iter, pos); + else if (!(pos[0] & 0x40)) /* short atom */ + token_length = response_parse_short(iter, pos); + else if (!(pos[0] & 0x20)) /* medium atom */ + token_length = response_parse_medium(iter, pos); + else if (!(pos[0] & 0x10)) /* long atom */ + token_length = response_parse_long(iter, pos); + else /* TOKEN */ + token_length = response_parse_token(iter, pos); + + pos += token_length; + cpos += token_length; + iter++; + num_entries++; + } + + if (num_entries == 0) { + pr_err("Couldn't parse response.\n"); + ret = -EINVAL; + goto err; + } + resp->num = num_entries; + + return 0; +err: + return ret; +} + +static size_t response_get_string(const struct parsed_resp *resp, int n, + const char **store) +{ + *store = NULL; + if (!resp) { + pr_err("Response is NULL\n"); + return 0; + } + + if (n > resp->num) { + pr_err("Response has %d tokens. Can't access %d\n", + resp->num, n); + return 0; + } + + if (resp->toks[n].type != OPAL_DTA_TOKENID_BYTESTRING) { + pr_err("Token is not a byte string!\n"); + return 0; + } + + *store = resp->toks[n].pos + 1; + return resp->toks[n].len - 1; +} + +static u64 response_get_u64(const struct parsed_resp *resp, int n) +{ + if (!resp) { + pr_err("Response is NULL\n"); + return 0; + } + + if (n > resp->num) { + pr_err("Response has %d tokens. Can't access %d\n", + resp->num, n); + return 0; + } + + if (resp->toks[n].type != OPAL_DTA_TOKENID_UINT) { + pr_err("Token is not unsigned it: %d\n", + resp->toks[n].type); + return 0; + } + + if (!((resp->toks[n].width == OPAL_WIDTH_TINY) || + (resp->toks[n].width == OPAL_WIDTH_SHORT))) { + pr_err("Atom is not short or tiny: %d\n", + resp->toks[n].width); + return 0; + } + + return resp->toks[n].stored.u; +} + +static u8 response_status(const struct parsed_resp *resp) +{ + if ((token_type(resp, 0) == OPAL_DTA_TOKENID_TOKEN) + && (response_get_token(resp, 0) == OPAL_ENDOFSESSION)) { + return 0; + } + + if (resp->num < 5) + return DTAERROR_NO_METHOD_STATUS; + + if ((token_type(resp, resp->num - 1) != OPAL_DTA_TOKENID_TOKEN) || + (token_type(resp, resp->num - 5) != OPAL_DTA_TOKENID_TOKEN) || + (response_get_token(resp, resp->num - 1) != OPAL_ENDLIST) || + (response_get_token(resp, resp->num - 5) != OPAL_STARTLIST)) + return DTAERROR_NO_METHOD_STATUS; + + return response_get_u64(resp, resp->num - 4); +} + +/* Parses and checks for errors */ +static int parse_and_check_status(struct opal_dev *dev) +{ + struct opal_cmd *cmd; + int error; + + cmd = &dev->cmd; + print_buffer(cmd->cmd, cmd->pos); + + error = response_parse(cmd->resp, IO_BUFFER_LENGTH, &dev->parsed); + if (error) { + pr_err("%s: Couldn't parse response.\n", dev->disk_name); + goto err_return; + } + + error = response_status(&dev->parsed); + if (error) + pr_err("%s: Response Status: %d\n", dev->disk_name, + error); + + err_return: + return error; +} + +static void clear_opal_cmd(struct opal_cmd *cmd) +{ + cmd->pos = sizeof(struct opal_header); + memset(cmd->cmd, 0, IO_BUFFER_LENGTH); + cmd->cb = NULL; + cmd->cb_data = NULL; +} + +static void start_opal_session_cont(int error, void *data) +{ + struct opal_dev *dev = data; + u32 HSN, TSN; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + if (error) + goto err_return; + + HSN = response_get_u64(&dev->parsed, 4); + TSN = response_get_u64(&dev->parsed, 5); + + if (HSN == 0 && TSN == 0) { + pr_err("%s: Couldn't authenticate session\n", dev->disk_name); + error = -EPERM; + goto err_return; + } + + dev->HSN = HSN; + dev->TSN = TSN; + +err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static int get_opal_key(struct opal_dev *dev) +{ + struct key *ukey = NULL; + const u8 *tmpkey = NULL; + size_t tmplen; + int ret = 0; + + if (dev->key_type == OPAL_KEY_PLAIN) { + tmpkey = dev->key_name; + tmplen = dev->key_name_len; + } else if (dev->key_type == OPAL_KEY_KEYRING) { + ukey = request_user_key(dev->key_name, &tmpkey, &tmplen); + if (IS_ERR(ukey)) { + pr_err("%s: Can't retrieve key: %ld\n", dev->disk_name, + PTR_ERR(ukey)); + return PTR_ERR(ukey); + } + } else { + pr_err("Requested invalid key type: %d\n", dev->key_type); + return -EINVAL; + } + + if (tmplen > OPAL_KEY_MAX) { + pr_err("Requested key with invalid size: %zd\n", tmplen); + ret = -EINVAL; + goto err_exit; + } + + dev->key_len = tmplen; + if (!memcpy(dev->key, tmpkey, tmplen)) { + pr_err("Error when copying key"); + ret = -EFAULT; + goto err_exit; + } + +err_exit: + key_put(ukey); + + return 0; +} + +static void clean_opal_key(struct opal_dev *dev) +{ + memset(dev->key, 0, OPAL_KEY_MAX); + dev->key_len = 0; +} + +static inline void clean_function_data(struct opal_dev *dev) +{ + dev->func_data = NULL; + dev->num_func_data = 0; +} + +/* This is a generic continue fn. + * We use this when we don't care about the response data + * and simply want to check the status and continue. + */ +static void generic_cont(int error, void *data) +{ + struct opal_dev *dev = data; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + + err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static void end_session_cont(int error, void *data) +{ + struct opal_dev *dev = data; + + dev->HSN = 0; + dev->TSN = 0; + generic_cont(error, data); +} + +static int finalize_and_send(struct opal_dev *dev, struct opal_cmd *cmd, + sec_cb cont) +{ + int ret; + + ret = cmd_finalize(cmd, dev->HSN, dev->TSN); + if (ret) { + pr_err("%s: Error finalizing command buffer: %d\n", + dev->disk_name, ret); + return ret; + } + + print_buffer(cmd->cmd, cmd->pos); + + ret = opal_send_recv(dev, cont, dev); + if (ret) + pr_err("%s: Error running command: %d\n", + dev->disk_name, ret); + + return ret; +} + +static int wait_for_cmd_completion(struct opal_completion *completion) +{ + wait_for_completion_interruptible(&completion->cmd_completion); + return completion->completion_status; +} + +static int gen_key(struct opal_dev *dev) +{ + const u8 *method; + u8 uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len)); + method = OPALMETHOD[OPAL_GENKEY]; + kfree(dev->prev_data); + dev->prev_data = NULL; + + ret = test_and_add_token_va(cmd, "c2s 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building gen key command\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static void get_active_key_cont(int error, void *data) +{ + struct opal_dev *dev = data; + const char *activekey; + size_t keylen; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + if (error) + goto err_return; + keylen = response_get_string(&dev->parsed, 4, &activekey); + if (!activekey) { + pr_err("%s: Couldn't extract the Activekey from the response\n", + __func__); + error = 0x0A; + goto err_return; + } + dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL); + + if (!dev->prev_data) + error = -ENOMEM; + + dev->prev_d_len = keylen; + +err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static int get_active_key(struct opal_dev *dev) +{ + const u8 *method; + u8 uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_GET]; + + ret = build_locking_range(uid, sizeof(uid), dev->lr); + if (ret < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + + ret = test_and_add_token_va(cmd, "c2s 6c 4c 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* startCloumn */ + OPAL_TINY_UINT_10, /* ActiveKey */ + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_04, /* endColumn */ + OPAL_TINY_UINT_10, /* ActiveKey */ + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building get active key command\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, get_active_key_cont); +} + +static int setup_locking_range(struct opal_dev *dev) +{ + const u8 *method; + u8 uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + struct opal_user_lr_setup *setup; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + ret = build_locking_range(uid, sizeof(uid), dev->lr); + if (ret < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + setup = dev->func_data[dev->state - 1]; + + ret = test_and_add_token_va(cmd, "c2s 4c 2cuc 2cuc 2cuc 2cu 4c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_VALUES, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* Range Start */ + setup->range_start, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_04, /* Range Length */ + setup->range_length, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_05, /* ReadLockEnabled */ + !!setup->RLE, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_06, /* WriteLockEnabled */ + !!setup->WLE, + + OPAL_ENDNAME, + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building Setup Locking range command.\n", + dev->disk_name); + return ret; + + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int start_adminsp_opal_session(struct opal_dev *dev, + enum OPAL_UID auth, + const char *key, + u8 key_len) +{ + const u8 *method, *smuid, *admin_sp, *hsa; + struct opal_cmd *cmd; + u32 HSN; + int ret; + + if (key == NULL && auth != OPAL_ANYBODY_UID) { + pr_err("%s: Attempted to open ADMIN_SP Session without a Host" \ + "Challenge, and not as the Anybody UID\n", __func__); + return 1; + } + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + set_comID(cmd, dev->comID); + HSN = 0x41; + + smuid = OPALUID[OPAL_SMUID_UID]; + method = OPALMETHOD[OPAL_STARTSESSION]; + admin_sp = OPALUID[OPAL_ADMINSP_UID]; + + ret = test_and_add_token_va(cmd, "c2s cusc", + OPAL_CALL, + smuid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + OPAL_STARTLIST, + HSN, + admin_sp, OPAL_UID_LENGTH, + OPAL_TINY_UINT_01); + if (ret < 0) { + pr_err("%s: Error building start adminsp session command.\n", + dev->disk_name); + return ret; + } + + switch (auth) { + case OPAL_ANYBODY_UID: + /* nothing left to do for anybody, just end and finalize */ + ret = test_and_add_token_va(cmd, "c", + OPAL_ENDLIST); + break; + case OPAL_SID_UID: + hsa = OPALUID[OPAL_SID_UID]; + ret = test_and_add_token_va(cmd, "2c s 3c s 2c", + OPAL_STARTNAME, + OPAL_TINY_UINT_00, /* HostChallenge */ + key, key_len, + OPAL_ENDNAME, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* HostSignAuth */ + hsa, OPAL_UID_LENGTH, + OPAL_ENDNAME, + OPAL_ENDLIST); + break; + default: + pr_err("Cannot start Admin SP session with auth %d\n", auth); + return 1; + } + + if (ret < 0) { + pr_err("%s: Error building start adminsp session command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, start_opal_session_cont); +} + +static int start_anybodyASP_opal_session(struct opal_dev *dev) +{ + return start_adminsp_opal_session(dev, OPAL_ANYBODY_UID, NULL, 0); +} + +static int start_SIDASP_opal_session(struct opal_dev *dev) +{ + int ret; + const u8 *key = dev->prev_data; + + if (!key) + ret = start_adminsp_opal_session(dev, OPAL_SID_UID, dev->key, + dev->key_len); + else { + ret = start_adminsp_opal_session(dev, OPAL_SID_UID, key, + dev->prev_d_len); + kfree(key); + dev->prev_data = NULL; + } + return ret; +} + +static int start_lockingsp_opal_session(struct opal_dev *dev, + enum OPAL_UID auth, const u8 *key, + u8 key_len) +{ + + const u8 *method, *smuid, *locking_sp, *hsa; + struct opal_cmd *cmd; + size_t klen = key_len; + u32 HSN; + int ret; + + if (key == NULL) { + pr_err("Cannot start Locking SP session without a key\n"); + return -EINVAL; + } + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + set_comID(cmd, dev->comID); + HSN = 0x41; + + smuid = OPALUID[OPAL_SMUID_UID]; + method = OPALMETHOD[OPAL_STARTSESSION]; + locking_sp = OPALUID[OPAL_LOCKINGSP_UID]; + hsa = OPALUID[auth]; + + ret = test_and_add_token_va(cmd, "c2s cusc 2csc 2csc c", + OPAL_CALL, + smuid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + HSN, + locking_sp, OPAL_UID_LENGTH, + OPAL_TINY_UINT_01, + + OPAL_STARTNAME, + OPAL_TINY_UINT_00, /* HostChallenge */ + key, klen, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* Host Sign Authority */ + hsa, OPAL_UID_LENGTH, + OPAL_ENDNAME, + + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building start adminsp session command.\n", + dev->disk_name); + return ret; + } + return finalize_and_send(dev, cmd, start_opal_session_cont); +} + +static inline int start_admin1LSP_opal_session(struct opal_dev *dev) +{ + return start_lockingsp_opal_session(dev, OPAL_ADMIN1_UID, + dev->key, dev->key_len); +} + +static int start_auth_opal_session(struct opal_dev *dev) +{ + const u8 *method, *smuid, *locking_sp; + u8 lk_ul_user[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + u32 HSN; + int ret; + struct opal_user_info *uinfo; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + set_comID(cmd, dev->comID); + + HSN = 0x41; + + uinfo = dev->func_data[dev->state - 1]; + + smuid = OPALUID[OPAL_SMUID_UID]; + method = OPALMETHOD[OPAL_STARTSESSION]; + locking_sp = OPALUID[OPAL_LOCKINGSP_UID]; + + if (uinfo->SUM) { + ret = build_locking_user(lk_ul_user, sizeof(lk_ul_user), + dev->lr); + if (ret < 0) { + pr_err("%s: Can't build locking user\n", + dev->disk_name); + return ret; + } + } else if (uinfo->who != OPAL_ADMIN1 && !uinfo->SUM) { + ret = build_locking_user(lk_ul_user, sizeof(lk_ul_user), + uinfo->who - 1); + if (ret < 0) { + pr_err("%s: Can't build locking user\n", + dev->disk_name); + return ret; + } + } else + memcpy(lk_ul_user, OPALUID[OPAL_ADMIN1_UID], OPAL_UID_LENGTH); + + + ret = test_and_add_token_va(cmd, "c2s cus3cs3c s 2c", + OPAL_CALL, + smuid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + HSN, + locking_sp, OPAL_UID_LENGTH, + OPAL_TINY_UINT_01, + OPAL_STARTNAME, + OPAL_TINY_UINT_00, + dev->key, dev->key_len, + OPAL_ENDNAME, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, + + lk_ul_user, OPAL_UID_LENGTH, + + OPAL_ENDNAME, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building STARTSESSION command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, start_opal_session_cont); +} + +static int revert_tper(struct opal_dev *dev) +{ + const u8 *method, *smuid; + struct opal_cmd *cmd; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + set_comID(cmd, dev->comID); + + smuid = OPALUID[OPAL_ADMINSP_UID]; + method = OPALMETHOD[OPAL_REVERT]; + + ret = test_and_add_token_va(cmd, "c2s 2c", + OPAL_CALL, + smuid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + OPAL_STARTLIST, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building REVERT TPER command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int internal_activate_user(struct opal_dev *dev) +{ + const u8 *method; + u8 uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + int ret; + struct opal_activate_user *act; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + act = dev->func_data[dev->state - 1]; + + memcpy(uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH); + uid[7] = act->who.who; + + method = OPALMETHOD[OPAL_SET]; + + ret = test_and_add_token_va(cmd, "c2s 3c c 4c 3c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_01, /* Values */ + + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_TINY_UINT_05, /* Enabled */ + OPAL_TINY_UINT_01, /* True */ + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building Activate UserN command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int erase_locking_range(struct opal_dev *dev) +{ + const u8 *method; + u8 uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_ERASE]; + + if (build_locking_range(uid, sizeof(uid), dev->lr) < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + + ret = test_and_add_token_va(cmd, "c2s 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building Erase Locking Range Cmmand.\n", + dev->disk_name); + return ret; + } + return finalize_and_send(dev, cmd, generic_cont); +} + +static int set_mbr_done(struct opal_dev *dev) +{ + const u8 *method, *uid; + struct opal_cmd *cmd; + int ret; + + u8 mbr_done_tf = *(u8 *)dev->func_data[dev->state - 1]; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + uid = OPALUID[OPAL_MBRCONTROL]; + + ret = test_and_add_token_va(cmd, "c2s 3c 6c 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_VALUES, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_02, /* Done */ + mbr_done_tf, /* Done T or F */ + OPAL_ENDNAME, + OPAL_ENDLIST, + + OPAL_ENDNAME, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error Building set MBR Dont/Not done command\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int set_mbr_enable_disable(struct opal_dev *dev) +{ + const u8 *method, *uid; + struct opal_cmd *cmd; + int ret; + + u8 mbr_en_dis = *(u8 *)dev->func_data[dev->state - 1]; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + uid = OPALUID[OPAL_MBRCONTROL]; + + ret = test_and_add_token_va(cmd, "c2s 3c 6c 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_VALUES, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_01, /* Enable */ + mbr_en_dis, /* Enable or Disable */ + OPAL_ENDNAME, + OPAL_ENDLIST, + + OPAL_ENDNAME, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error Building set MBR Dont/Not done command\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int set_new_pw(struct opal_dev *dev) +{ + const u8 *method; + u8 cpin_uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + int ret; + struct opal_new_pw *pw; + size_t key_len; + u8 *key; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + pw = dev->func_data[dev->state - 1]; + key = pw->new_pin.key; + key_len = pw->new_pin.key_len; + memcpy(cpin_uid, OPALUID[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH); + + if (pw->user_for_pw != OPAL_ADMIN1) { + cpin_uid[5] = 0x03; + if (pw->who.SUM) + cpin_uid[7] = pw->new_pin.lr + 1; + else + cpin_uid[7] = pw->user_for_pw; + } + + method = OPALMETHOD[OPAL_SET]; + + ret = test_and_add_token_va(cmd, "c2s 3c 3cs2c 2c", + OPAL_CALL, + cpin_uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_01, /* Values */ + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* PIN */ + key, key_len, + OPAL_ENDNAME, + OPAL_ENDLIST, + + OPAL_ENDNAME, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building SET AMIN1 PIN command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int set_sid_cpin_pin(struct opal_dev *dev) +{ + const u8 *method, *cpin_uid; + struct opal_cmd *cmd; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + cpin_uid = OPALUID[OPAL_C_PIN_SID]; + method = OPALMETHOD[OPAL_SET]; + + ret = test_and_add_token_va(cmd, "c2s 2c 4cs2c 2c", + OPAL_CALL, + cpin_uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + + OPAL_TINY_UINT_01, /* Values */ + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* PIN */ + dev->key, dev->key_len, + OPAL_ENDNAME, + OPAL_ENDLIST, + + OPAL_ENDNAME, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building SET CPIN PIN command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static void query_locking_range_cont(int error, void *data) +{ + struct opal_dev *dev = data; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + if (error) + goto err_return; + + dev->start = response_get_u64(&dev->parsed, 4); + dev->length = response_get_u64(&dev->parsed, 8); + +err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static int query_locking_range(struct opal_dev *dev) +{ + u8 lr_buffer[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + const u8 *method; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + method = OPALMETHOD[OPAL_GET]; + + if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + + set_comID(cmd, dev->comID); + + ret = test_and_add_token_va(cmd, "c2s 12c", + OPAL_CALL, + lr_buffer, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_STARTCOLUMN, + OPAL_RANGESTART, + OPAL_ENDNAME, + OPAL_STARTNAME, + OPAL_ENDCOLUMN, + OPAL_RANGELENGTH, + OPAL_ENDNAME, + OPAL_ENDLIST, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building GET Locking Range command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, query_locking_range_cont); +} + +static int add_user_to_lr(struct opal_dev *dev) +{ + u8 lr_buffer[OPAL_UID_LENGTH]; + u8 user_uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + const u8 *method; + struct opal_lock_unlock *lkul; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + + lkul = dev->func_data[dev->state - 1]; + + memcpy(lr_buffer, OPALUID[OPAL_LOCKINGRANGE_ACE_RDLOCKED], + OPAL_UID_LENGTH); + + if (lkul->l_state == OPAL_RW) + memcpy(lr_buffer, OPALUID[OPAL_LOCKINGRANGE_ACE_WRLOCKED], + OPAL_UID_LENGTH); + + lr_buffer[7] = dev->lr; + + memcpy(user_uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH); + user_uid[7] = lkul->authority.who; + + ret = test_and_add_token_va(cmd, "c2s 3c 3c 2c 2sc c2sc cs2c 5c", + OPAL_CALL, + lr_buffer, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_01, /* Values */ + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* BooleanExpr */ + + OPAL_STARTLIST, + OPAL_STARTNAME, + + OPALUID[OPAL_HALF_UID_AUTHORITY_OBJ_REF], + OPAL_UID_LENGTH_HALF, + user_uid, OPAL_UID_LENGTH, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPALUID[OPAL_HALF_UID_AUTHORITY_OBJ_REF], + OPAL_UID_LENGTH_HALF, + user_uid, OPAL_UID_LENGTH, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPALUID[OPAL_HALF_UID_BOOLEAN_ACE], + OPAL_UID_LENGTH_HALF, + OPAL_TINY_UINT_01, + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building add user to locking range command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int lock_unlock_locking_range(struct opal_dev *dev) +{ + u8 lr_buffer[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + const u8 *method; + struct opal_lock_unlock *lkul; + int ret; + u8 read_locked = 1, write_locked = 1; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + lkul = dev->func_data[dev->state - 1]; + if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + + switch (lkul->l_state) { + case OPAL_RO: + read_locked = 0; + write_locked = 1; + break; + case OPAL_RW: + read_locked = 0; + write_locked = 0; + break; + case OPAL_LK: + /* vars are initalized to locked */ + break; + default: + pr_err("Tried to set an invalid locking state... returning to uland\n"); + return 1; + } + + ret = test_and_add_token_va(cmd, "c2sc 3c 4c 4c 3c", + OPAL_CALL, + lr_buffer, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_VALUES, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_READLOCKED, + read_locked, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_WRITELOCKED, + write_locked, + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building SET command.\n", dev->disk_name); + return ret; + } + return finalize_and_send(dev, cmd, generic_cont); +} + + +static int lock_unlock_locking_range_SUM(struct opal_dev *dev) +{ + u8 lr_buffer[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + const u8 *method; + struct opal_lock_unlock *lkul; + int ret; + u8 read_locked = 1, write_locked = 1; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + lkul = dev->func_data[dev->state - 1]; + if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + + switch (lkul->l_state) { + case OPAL_RO: + read_locked = 0; + write_locked = 1; + break; + case OPAL_RW: + read_locked = 0; + write_locked = 0; + break; + case OPAL_LK: + /* vars are initalized to locked */ + break; + default: + pr_err("Tried to set an invalid locking state.\n"); + return 1; + } + + ret = test_and_add_token_va(cmd, "c2sc 3c 4c 4c 4c 4c 3c", + OPAL_CALL, + lr_buffer, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_VALUES, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_READLOCKENABLED, + OPAL_TRUE, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_WRITELOCKENABLED, + OPAL_TRUE, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_READLOCKED, + read_locked, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_WRITELOCKED, + write_locked, + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building SET command.\n", dev->disk_name); + return ret; + } + return finalize_and_send(dev, cmd, generic_cont); +} + +int activate_lsp(struct opal_dev *dev) +{ + u8 user_lr[OPAL_UID_LENGTH]; + const u8 *method, *uid; + struct opal_cmd *cmd; + int ret; + size_t uint_3 = 0x83; + + cmd = &dev->cmd; + + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + uid = OPALUID[OPAL_LOCKINGSP_UID]; + method = OPALMETHOD[OPAL_ACTIVATE]; + + ret = test_and_add_token_va(cmd, "c2s", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH); + if (ret < 0) { + pr_err("%s: Error building Activate LockingSP command.\n", + dev->disk_name); + return ret; + } + /* Activating as SUM */ + if (dev->lr > 0) { + ret = build_locking_range(user_lr, sizeof(user_lr), dev->lr); + if (ret < 0) { + pr_err("%s: Can't build locking user\n", + dev->disk_name); + return ret; + } + test_and_add_token_va(cmd, "2c 4c csc 2c", + OPAL_STARTLIST, + OPAL_STARTNAME, + + uint_3, + OPAL_TINY_UINT_06, + OPAL_TINY_UINT_00, + OPAL_TINY_UINT_00, + + OPAL_STARTLIST, + user_lr, OPAL_UID_LENGTH, + OPAL_ENDLIST, + + OPAL_ENDNAME, + OPAL_ENDLIST); + } else /* Actiave Normal Mode */ + ret = test_and_add_token_va(cmd, "2c", + OPAL_STARTLIST, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building Activate LockingSP command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static void get_lsp_lifecycle_cont(int error, void *data) +{ + + struct opal_dev *dev = data; + u8 lc_status; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + if (error) + goto err_return; + + lc_status = response_get_u64(&dev->parsed, 4); + /* 0x08 is Manufacured Inactive */ + /* 0x09 is Manufactured */ + if (lc_status != 0x08) { + pr_err("%s: Couldn't determine the status of the Lifcycle state\n", + dev->disk_name); + error = -ENODEV; + } + +err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +/* Determine if we're in the Manufactured Inactive or Active state */ +int get_lsp_lifecycle(struct opal_dev *dev) +{ + struct opal_cmd *cmd; + const u8 *method, *uid; + int ret; + + cmd = &dev->cmd; + + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + uid = OPALUID[OPAL_LOCKINGSP_UID]; + method = OPALMETHOD[OPAL_GET]; + + ret = test_and_add_token_va(cmd, "c2s 2c 4c 4c 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* Start Column */ + OPAL_TINY_UINT_06, /* Lifcycle Column */ + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_04, /* End Column */ + OPAL_TINY_UINT_06, /* Lifecycle Column */ + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error Building GET Lifecycle Status command\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, get_lsp_lifecycle_cont); +} + +static void get_msid_cpin_pin_cont(int error, void *data) +{ + const char *msid_pin; + struct opal_dev *dev = data; + size_t strlen; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + if (error) + goto err_return; + + strlen = response_get_string(&dev->parsed, 4, &msid_pin); + if (!msid_pin) { + pr_err("%s: Couldn't extract PIN from response\n", __func__); + error = 1; + goto err_return; + } + + dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL); + if (!dev->prev_data) + error = -ENOMEM; + + dev->prev_d_len = strlen; + + err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static int get_msid_cpin_pin(struct opal_dev *dev) +{ + const u8 *method, *smuid; + int ret; + struct opal_cmd *cmd; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + smuid = OPALUID[OPAL_C_PIN_MSID]; + method = OPALMETHOD[OPAL_GET]; + + ret = test_and_add_token_va(cmd, "c 2s 12c", + OPAL_CALL, + + smuid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* Sart Column */ + OPAL_TINY_UINT_03, /* PIN */ + OPAL_ENDNAME, + OPAL_STARTNAME, + OPAL_TINY_UINT_04, /* End Column */ + OPAL_TINY_UINT_03, /* PIN */ + OPAL_ENDNAME, + OPAL_ENDLIST, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building Get MSID CPIN PIN command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, get_msid_cpin_pin_cont); +} + +static void unlock_suspend_final(int error, void *data) +{ + struct opal_dev *dev = data; + + dev->resume_from_suspend = false; + dev->resume_data = NULL; + dev->func_data = NULL; + dev->bdev = NULL; +} + +static int build_end_opal_session(struct opal_dev *dev) +{ + struct opal_cmd *cmd; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + set_comID(cmd, dev->comID); + return test_and_add_token_u8(cmd, OPAL_ENDOFSESSION); +} + +static int end_opal_session(struct opal_dev *dev) +{ + if (build_end_opal_session(dev) < 0) + return -1; + return finalize_and_send(dev, &dev->cmd, end_session_cont); +} + +static struct opal_dev *find_opal_dev(struct block_device *bdev, u8 lr) +{ + struct opal_dev *iter, *opal_dev = NULL; + + list_for_each_entry(iter, &opal_list, node) { + if (strncmp(iter->disk_name, bdev->bd_disk->disk_name, + DISK_NAME_LEN)) + continue; + if (iter->lr == lr) { + opal_dev = iter; + break; + } + } + + return opal_dev; +} + +static int update_opal_dev(struct opal_dev *old_dev, struct opal_dev *new_dev) +{ + if (!atomic_add_unless(&old_dev->in_use, 1, 1)) { + pr_err("%s: dev was in use\n", __func__); + return -EBUSY; + } + + old_dev->key_name_len = new_dev->key_name_len; + if (!memcpy(old_dev->key_name, new_dev->key_name, old_dev->key_name_len)) { + pr_err("%s: Error updating device:\n", old_dev->disk_name); + return -EFAULT; + } + + if (!strncpy(old_dev->disk_name, new_dev->disk_name, DISK_NAME_LEN)) { + pr_err("%s: Error registering device: copying disk name\n", + old_dev->disk_name); + return -EFAULT; + } + + old_dev->comID = new_dev->comID; + old_dev->start = new_dev->start; + old_dev->length = new_dev->length; + old_dev->align = new_dev->align; + old_dev->lowest_lba = new_dev->lowest_lba; + old_dev->bdev = NULL; + old_dev->final_cb = new_dev->final_cb; + old_dev->final_cb_data = new_dev->final_cb_data; + old_dev->oper_cb = new_dev->oper_cb; + old_dev->state = new_dev->state; + old_dev->funcs = new_dev->funcs; + + kfree(old_dev->completion); + clean_function_data(old_dev); + + old_dev->completion = new_dev->completion; + + /* + * Won't be able to auto unlock this locking range based on block + * requestes. + */ + if (old_dev->length == 0) + pr_warn("%s: Missing block information for locking range %d\n", + old_dev->disk_name, old_dev->lr); + + return 0; +} + +int opal_register_cont(struct opal_dev *new_dev) +{ + struct opal_dev *old_dev; + unsigned long flags; + int error = 0; + + spin_lock_irqsave(&list_spinlock, flags); + + old_dev = find_opal_dev(new_dev->bdev, new_dev->lr); + if (!old_dev) { + list_add_tail(&new_dev->node, &opal_list); + old_dev = new_dev; + } else { + if (old_dev == new_dev) + error = 0; + else { + error = update_opal_dev(old_dev, new_dev); + clean_opal_key(new_dev); + kfree(new_dev); + } + } + + if (error) + list_del(&old_dev->node); + + spin_unlock_irqrestore(&list_spinlock, flags); + + if (!error) + pr_info("%s: Registered key for locking range: %d\n", + old_dev->disk_name, old_dev->lr); + + if (old_dev->oper_cb) + old_dev->oper_cb(error, old_dev); + + return 0; +} + +static void next(int error, struct opal_dev *dev) +{ + opal_step func = dev->funcs[dev->state]; + void *cb_data = dev->final_cb_data; + sec_cb *cb = dev->final_cb; + bool done = false; + + + if (error || !func) { + done = true; + goto next_exit; + } + dev->state++; + dev->oper_cb = next; + error = func(dev); + next_exit: + if (error) { + pr_err("%s: Error on step function: %d with error %d: %s\n", + dev->disk_name, dev->state, error, + opal_error_to_human(error)); + + + atomic_dec(&dev->in_use); + if (dev->error_cb) { + dev->error_cb(dev->error_cb_data); + return; + } + if (cb) + cb(error, cb_data); + + dev->completion->completion_status = error; + complete(&dev->completion->cmd_completion); + } else if (!error && done) { + atomic_dec(&dev->in_use); + if (cb) + cb(error, cb_data); + dev->completion->completion_status = error; + complete(&dev->completion->cmd_completion); + } +} + +const opal_step error_end_session[] = { + end_opal_session, + NULL, +}; +static int end_opal_session_error(struct opal_dev *dev) +{ + + dev->funcs = error_end_session; + dev->state = 0; + dev->error_cb = NULL; + next(0, dev); + return 0; +} + +static struct opal_dev *alloc_opal_dev(struct block_device *bdev, u8 lr) +{ + struct opal_dev *opal_dev; + struct request_queue *q; + unsigned long dma_align; + const char *disk_name; + struct opal_cmd *cmd; + int ret; + + opal_dev = kzalloc(sizeof(*opal_dev), GFP_KERNEL); + if (!opal_dev) + return ERR_PTR(-ENOMEM); + + opal_dev->bdev = bdev; + opal_dev->lr = lr; + cmd = &opal_dev->cmd; + cmd->cmd = cmd->cmd_buf; + cmd->resp = cmd->resp_buf; + + disk_name = bdev->bd_disk->disk_name; + if (!strncpy(opal_dev->disk_name, disk_name, DISK_NAME_LEN)) { + pr_err("%s: Error registering device: copying disk name\n", + disk_name); + ret = -EFAULT; + goto err_free_dev; + } + + q = bdev->bd_queue; + dma_align = (queue_dma_alignment(q) | q->dma_pad_mask) + 1; + cmd->cmd = (u8 *)round_up((uintptr_t)cmd->cmd, dma_align); + cmd->resp = (u8 *)round_up((uintptr_t)cmd->resp, dma_align); + + INIT_LIST_HEAD(&opal_dev->node); + atomic_set(&opal_dev->in_use, 1); + + opal_dev->completion = kzalloc(sizeof(*opal_dev->completion), + GFP_KERNEL); + + if (!opal_dev->completion) + goto err_free_dev; + + init_completion(&opal_dev->completion->cmd_completion); + opal_dev->completion->completion_status = 0; + opal_dev->state = 0; + + return opal_dev; + +err_free_dev: + kfree(opal_dev); + return ERR_PTR(ret); +} + +int opal_register(struct block_device *bdev, struct opal_key *key_cmd, + const opal_step *funcs) +{ + struct opal_dev *new_dev = NULL; + u8 key_len = key_cmd->key_len; + u8 lr = key_cmd->lr; + struct opal_completion *completion; + int ret; + + new_dev = alloc_opal_dev(bdev, lr); + if (IS_ERR(new_dev)) { + pr_err("%s: Error registering device: allocation\n", + bdev->bd_disk->disk_name); + return PTR_ERR(new_dev); + } + + if (!memcpy(new_dev->key_name, key_cmd->key, key_len)) { + pr_err("%s: Error registering key: couldn't copy key\n", + new_dev->disk_name); + return -EFAULT; + } + + new_dev->key_name_len = key_len; + new_dev->key_type = key_cmd->key_type; + ret = get_opal_key(new_dev); + if (ret) { + pr_err("%s: Couldn't get key: %d\n", new_dev->disk_name, ret); + return ret; + } + + new_dev->funcs = funcs; + + new_dev->state = 0; + completion = new_dev->completion; + next(0, new_dev); + + return wait_for_cmd_completion(completion); +} + +static struct opal_dev *get_registered_opal_dev(struct block_device *bdev, + u8 lr) +{ + const char *diskname = bdev->bd_disk->disk_name; + struct opal_dev *iter, *dev = NULL; + unsigned long flags; + bool in_use = false; + + spin_lock_irqsave(&list_spinlock, flags); + list_for_each_entry(iter, &opal_list, node) { + if (strncmp(iter->disk_name, diskname, DISK_NAME_LEN)) + continue; + if (iter->lr == lr) { + dev = iter; + if (!atomic_add_unless(&iter->in_use, 1, 1)) { + dev = NULL; + in_use = true; + } + break; + } + } + + spin_unlock_irqrestore(&list_spinlock, flags); + + if (!dev) + return NULL; + + dev->bdev = bdev; + return dev; +} + +/* Free up the Opal dev and its keys during two scenarios: + * + * 1) When a command is complete that no longer requires + * the opal dev to be around. + * 2) When a command, including Opal Save fails we clean + * and free the opal dev. + * + * If we find the opal dev structure in the list of + * saved passwords we will *not* remove it. + */ +static void remove_and_clean_opal_dev(struct opal_dev *dev) +{ + struct opal_dev *iter; + bool found = false; + + spin_lock(&list_spinlock); + list_for_each_entry(iter, &opal_list, node) { + if (iter == dev) { + found = true; + break; + } + } + + spin_unlock(&list_spinlock); + if (!found) { + clean_opal_key(dev); + clean_function_data(dev); + kfree(dev); + } +} + +static struct opal_dev *get_or_create_opal_dev(struct block_device *bdev, + u8 lr, bool use_new) +{ + struct opal_dev *dev; + + if (use_new) + return alloc_opal_dev(bdev, lr); + + dev = get_registered_opal_dev(bdev, lr); + if (!dev) { + dev = alloc_opal_dev(bdev, lr); + if (!dev) + return NULL; + } + return dev; +} + +static struct opal_completion *setup_opal_dev(struct block_device *bdev, + struct opal_dev *dev, + const opal_step *funcs, + struct opal_key *key) +{ + int ret; + + dev->bdev = bdev; + dev->state = 0; + dev->funcs = funcs; + dev->TSN = 0; + dev->HSN = 0; + dev->final_cb = NULL; + dev->final_cb_data = NULL; + dev->lr = key->lr; + dev->error_cb = end_opal_session_error; + dev->error_cb_data = dev; + + if (key) { + memcpy(dev->key_name, key->key, key->key_len); + dev->key_name_len = key->key_len; + dev->key_type = key->key_type; + + ret = get_opal_key(dev); + if (ret) { + kfree(dev->completion); + pr_err("%s: Couldn't get key: %d\n", + dev->disk_name, ret); + return ERR_PTR(ret); + } + } + dev->func_data = NULL; + dev->completion->completion_status = 0; + + return dev->completion; +} + +static int internal_setup_lr(struct block_device *bdev, + struct opal_user_lr_setup *setup) +{ + struct opal_dev *dev; + struct opal_completion *completion; + void *data[3] = { NULL }; + const opal_step lr_funcs[] = { + opal_discovery0, + start_auth_opal_session, + setup_locking_range, + get_active_key, + gen_key, + end_opal_session, + NULL, + }; + int ret; + + dev = get_or_create_opal_dev(bdev, setup->key.lr, true); + if (!dev) + return -ENOMEM; + + completion = setup_opal_dev(bdev, dev, lr_funcs, &setup->key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->func_data = data; + dev->num_func_data = 3; + dev->func_data[1] = &setup->who; + dev->func_data[2] = setup; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +int opal_revert(struct block_device *bdev, struct opal_key *key) +{ + const opal_step revert_funcs[] = { + opal_discovery0, + start_SIDASP_opal_session, + revert_tper, /* controller will terminate session */ + NULL, + }; + + return opal_register(bdev, key, revert_funcs); +} + +int activate_user(struct block_device *bdev, struct opal_activate_user *act) +{ + const opal_step act_funcs[] = { + opal_discovery0, + start_admin1LSP_opal_session, + internal_activate_user, + end_opal_session, + NULL + }; + struct opal_dev *dev; + struct opal_completion *completion; + void *data[3] = { NULL }; + int ret; + + dev = get_or_create_opal_dev(bdev, act->key.lr, true); + if (!dev) + return -ENOMEM; + + completion = setup_opal_dev(bdev, dev, act_funcs, &act->key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 3; + dev->func_data = data; + dev->func_data[1] = act; + dev->func_data[2] = act; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +int opal_set_pw(struct block_device *bdev, struct opal_new_pw *pw) + +{ + const opal_step pw_funcs[] = { + opal_discovery0, + start_auth_opal_session, + set_new_pw, + end_opal_session, + NULL + }; + struct opal_dev *dev; + struct opal_completion *completion; + void *data[3] = { NULL }; + int ret; + + dev = get_or_create_opal_dev(bdev, pw->current_pin.lr, true); + if (!dev) + return -ENOMEM; + + completion = setup_opal_dev(bdev, dev, pw_funcs, &pw->current_pin); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 3; + dev->func_data = data; + dev->func_data[1] = (void *) &pw->who; + dev->func_data[2] = (void *) pw; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +int opal_act_lsp_int(struct block_device *bdev, struct opal_key *key, + const opal_step *funcs) +{ + struct opal_dev *dev; + struct opal_completion *completion; + int ret; + + dev = get_or_create_opal_dev(bdev, key->lr, true); + if (!dev) + return -ENOMEM; + completion = setup_opal_dev(bdev, dev, funcs, key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + + +static int opal_save_internal(struct block_device *bdev, + struct opal_lock_unlock *lk) +{ + void *func_data[3] = { NULL }; + struct opal_dev *dev; + struct opal_completion *completion; + const opal_step _auth_funcs[] = { + opal_discovery0, + start_auth_opal_session, + query_locking_range, + end_opal_session, + opal_register_cont, + NULL + }; + int ret; + + dev = get_or_create_opal_dev(bdev, lk->key.lr, false); + if (!dev) + return -ENOMEM; + completion = setup_opal_dev(bdev, dev, _auth_funcs, &lk->key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 3; + dev->func_data = func_data; + dev->func_data[1] = &lk->authority; + dev->lkul = *lk; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +static int add_user_lr_internal(struct block_device *bdev, + struct opal_lock_unlock *lk) +{ + void *func_data[3] = { NULL }; + struct opal_dev *dev; + struct opal_completion *completion; + const opal_step funcs[] = { + opal_discovery0, + start_admin1LSP_opal_session, + add_user_to_lr, + end_opal_session, + NULL + }; + int ret; + + dev = get_or_create_opal_dev(bdev, lk->key.lr, true); + if (!dev) + return -ENOMEM; + completion = setup_opal_dev(bdev, dev, funcs, &lk->key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 3; + dev->func_data = func_data; + dev->func_data[2] = lk; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +static int lock_unlock_internal(struct block_device *bdev, + struct opal_lock_unlock *lk) +{ + void *func_data[3] = { NULL }; + struct opal_dev *dev; + struct opal_completion *completion; + + const opal_step ulk_funcs_SUM[] = { + opal_discovery0, + start_auth_opal_session, + lock_unlock_locking_range_SUM, + end_opal_session, + NULL + }; + const opal_step _unlock_funcs[] = { + opal_discovery0, + start_auth_opal_session, + lock_unlock_locking_range, + end_opal_session, + NULL + }; + int ret; + + dev = get_or_create_opal_dev(bdev, lk->key.lr, true); + if (!dev) + return -ENOMEM; + + if (lk->authority.SUM) + completion = setup_opal_dev(bdev, dev, ulk_funcs_SUM, &lk->key); + else + completion = setup_opal_dev(bdev, dev, _unlock_funcs, &lk->key); + + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 3; + dev->func_data = func_data; + dev->func_data[1] = &lk->authority; + dev->func_data[2] = lk; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +int opal_erase_locking_range(struct block_device *bdev, struct sed_key *key) +{ + struct opal_dev *dev; + struct opal_completion *completion; + struct opal_key k; + int ret; + const opal_step erase_funcs[] = { + opal_discovery0, + start_admin1LSP_opal_session, + erase_locking_range, + end_opal_session, + NULL, + }; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) + return -EFAULT; + + dev = get_or_create_opal_dev(bdev, k.lr, true); + if (!dev) + return -ENOMEM; + + completion = setup_opal_dev(bdev, dev, erase_funcs, &k); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} +EXPORT_SYMBOL(opal_erase_locking_range); + +int opal_enable_disable_shadow_mbr(struct block_device *bdev, + struct sed_key *key) +{ + void *func_data[6] = { NULL }; + struct opal_mbr_data mbr; + struct opal_dev *dev; + struct opal_completion *completion; + const opal_step mbr_funcs[] = { + opal_discovery0, + start_admin1LSP_opal_session, + set_mbr_done, + end_opal_session, + start_admin1LSP_opal_session, + set_mbr_enable_disable, + end_opal_session, + NULL, + }; + int ret; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&mbr, key->opal_mbr, sizeof(*key->opal_mbr))) + return -EFAULT; + + if (mbr.enable_disable != OPAL_MBR_ENABLE && + mbr.enable_disable != OPAL_MBR_DISABLE) + return -EINVAL; + + dev = get_or_create_opal_dev(bdev, mbr.key.lr, true); + if (!dev) + return -ENOMEM; + + completion = setup_opal_dev(bdev, dev, mbr_funcs, &mbr.key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 6; + dev->func_data = func_data; + dev->func_data[2] = &mbr.enable_disable; + dev->func_data[5] = &mbr.enable_disable; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; + +} +EXPORT_SYMBOL(opal_enable_disable_shadow_mbr); + +int opal_save(struct block_device *bdev, struct sed_key *key) +{ + struct opal_lock_unlock lkul; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&lkul, key->opal_lk_unlk, sizeof(*key->opal))) + return -EFAULT; + + return opal_save_internal(bdev, &lkul); +} +EXPORT_SYMBOL(opal_save); + +int opal_add_user_to_lr(struct block_device *bdev, struct sed_key *key) +{ + struct opal_lock_unlock lkul; + + if (copy_from_user(&lkul, key->opal_lk_unlk, sizeof(lkul))) + return -EFAULT; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't assign user to LR without backing disk\n"); + return -EFAULT; + } + if (lkul.l_state != OPAL_RO && lkul.l_state != OPAL_RW) { + pr_err("Locking state was not RO or RW\n"); + return -EINVAL; + } + if (lkul.authority.who < OPAL_USER1 && + lkul.authority.who > OPAL_USER9) { + pr_err("Authority was not within the range of users: %d\n", + lkul.authority.who); + return -EINVAL; + } + if (lkul.authority.SUM) { + pr_err("%s not supported in SUM. Use setup locking range\n", + __func__); + return -EINVAL; + } + + return add_user_lr_internal(bdev, &lkul); +} +EXPORT_SYMBOL(opal_add_user_to_lr); + +int opal_reverttper(struct block_device *bdev, struct sed_key *key) +{ + struct opal_key k; + + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) + return -EFAULT; + + return opal_revert(bdev, &k); +} +EXPORT_SYMBOL(opal_reverttper); + +int opal_lock_unlock(struct block_device *bdev, struct sed_key *key) +{ + struct opal_lock_unlock k; + + if (copy_from_user(&k, key->opal_lk_unlk, sizeof(*key->opal_lk_unlk))) + return -EFAULT; + + if (k.authority.who < OPAL_ADMIN1 || k.authority.who >= OPAL_USER9) + return -EINVAL; + + return lock_unlock_internal(bdev, &k); +} +EXPORT_SYMBOL(opal_lock_unlock); + +int opal_take_ownership(struct block_device *bdev, struct sed_key *key) +{ + struct opal_key k; + const opal_step owner_funcs[] = { + opal_discovery0, + start_anybodyASP_opal_session, + get_msid_cpin_pin, + end_opal_session, + start_SIDASP_opal_session, + set_sid_cpin_pin, + end_opal_session, + NULL + }; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) + return -EFAULT; + + return opal_register(bdev, &k, owner_funcs); +} +EXPORT_SYMBOL(opal_take_ownership); + +int opal_activate_lsp(struct block_device *bdev, struct sed_key *key) +{ + struct opal_key k; + const opal_step active_funcs[] = { + opal_discovery0, + start_SIDASP_opal_session, /* Open session as SID auth */ + get_lsp_lifecycle, + activate_lsp, + end_opal_session, + NULL + }; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) + return -EFAULT; + + return opal_act_lsp_int(bdev, &k, active_funcs); +} +EXPORT_SYMBOL(opal_activate_lsp); + +int opal_setup_locking_range(struct block_device *bdev, struct sed_key *pw) +{ + struct opal_user_lr_setup k; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&k, pw->opal_lrs, sizeof(*pw->opal_lrs))) + return -EFAULT; + + return internal_setup_lr(bdev, &k); +} + +int opal_set_new_pw(struct block_device *bdev, struct sed_key *pw) +{ + struct opal_new_pw k; + + if (pw->sed_type != OPAL_PW) + return -EINVAL; + + if (copy_from_user(&k, pw->opal_pw, sizeof(*pw->opal_pw))) + return -EFAULT; + + if (k.who.who < OPAL_ADMIN1 || k.who.who > OPAL_USER9) + return -EINVAL; + + return opal_set_pw(bdev, &k); +} +EXPORT_SYMBOL(opal_set_new_pw); + +int opal_activate_user(struct block_device *bdev, struct sed_key *pw) +{ + struct opal_activate_user k; + + if (pw->sed_type != OPAL_ACT_USR) { + pr_err("Sed type was not act user\n"); + return -EINVAL; + } + + if (copy_from_user(&k, pw->opal_act, sizeof(*pw->opal_act))) { + pr_err("copy from user error\n"); + return -EFAULT; + } + + /* We can't activate Admin1 it's active as manufactured */ + if (k.who.who < OPAL_USER1 && k.who.who > OPAL_USER9) { + pr_err("Who was not a valid user: %d \n", k.who.who); + return -EINVAL; + } + + return activate_user(bdev, &k); + +} +EXPORT_SYMBOL(opal_activate_user); + +int opal_unlock_from_suspend(struct opal_suspend_unlk *data) +{ + const char *diskname = data->name; + struct opal_dev *iter, *dev = NULL; + struct opal_completion *completion; + void *func_data[3] = { NULL }; + const opal_step _unlock_funcs_SUM[] = { + opal_discovery0, + start_auth_opal_session, + lock_unlock_locking_range, + end_opal_session, + NULL + }; + const opal_step _unlock_funcs[] = { + opal_discovery0, + start_auth_opal_session, + lock_unlock_locking_range, + end_opal_session, + NULL + }; + + + spin_lock(&list_spinlock); + list_for_each_entry(iter, &opal_list, node) { + if (strncmp(iter->disk_name, diskname, DISK_NAME_LEN)) { + pr_err("iterdisk was %s and diskname is %s\n", + iter->disk_name, diskname); + continue; + } + if (atomic_add_unless(&iter->in_use, 1, 1)) { + dev = iter; + dev->func_data = func_data; + dev->resume_from_suspend = true; + dev->resume_data = data; + dev->final_cb = unlock_suspend_final; + dev->final_cb_data = dev; + dev->error_cb = end_opal_session_error; + dev->error_cb_data = dev; + dev->state = 0; + if (dev->lkul.authority.SUM) + dev->funcs = _unlock_funcs_SUM; + else + dev->funcs = _unlock_funcs; + dev->TSN = 0; + dev->HSN = 0; + dev->func_data[2] = &dev->lkul; + dev->func_data[1] = &dev->lkul.authority; + completion = dev->completion; + next(0, dev); + wait_for_cmd_completion(completion); + } + } + spin_unlock(&list_spinlock); + + if (!dev) + return -ENODEV; + return 0; +} +EXPORT_SYMBOL(opal_unlock_from_suspend); diff --git a/lib/sed-opal_internal.h b/lib/sed-opal_internal.h new file mode 100644 index 0000000..c9d3883 --- /dev/null +++ b/lib/sed-opal_internal.h @@ -0,0 +1,586 @@ +/* + * Copyright ? 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Author: + * Rafael Antognolli + * Scott Bauer + */ + +#ifndef _NVME_OPAL_INTERNAL_H +#define _NVME_OPAL_INTERNAL_H + +#include +#include + +#define DTAERROR_NO_METHOD_STATUS 0x89 + +static const char *opal_errors[19] = { + "Success", + "Not Authorized", + "Unknown Error", + "SP Busy", + "SP Failed", + "SP Disabled", + "SP Frozen", + "No Sessions Available", + "Uniqueness Conflict", + "Insufficient Space", + "Insufficient Rows", + "Invalid Function", + "Invalid Parameter", + "Invalid Reference", + "Unknown Error", + "TPER Malfunction", + "Transaction Failure", + "Response Overflow", + "Authority Locked Out", +}; + +static const char *opal_error_to_human(int error) +{ + if (error == 0x3f) + return "Failed"; + + if (error >= sizeof(opal_errors) || error < 0) + return "Unknown Error"; + + return opal_errors[error]; +} + +/* User IDs used in the TCG storage SSCs */ +static const u8 OPALUID[][8] = { + /* users */ + + /* session management */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, + /* special "thisSP" syntax */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* Administrative SP */ + { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 }, + /* Locking SP */ + { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 }, + /* ENTERPRISE Locking SP */ + { 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, 0x01 }, + /* anybody */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 }, + /* SID */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 }, + /* ADMIN1 */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 }, + /* USER1 */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 }, + /* USER2 */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 }, + /* PSID user */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 }, + /* BandMaster 0 */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x01 }, + /* EraseMaster */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x84, 0x01 }, + + /* tables */ + + /* Locking_GlobalRange */ + { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 }, + /* ACE_Locking_Range_Set_RdLocked UID */ + { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x01 }, + /* ACE_Locking_Range_Set_WrLocked UID */ + { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x01 }, + /* MBR Control */ + { 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01 }, + /* Shadow MBR */ + { 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 }, + /* AUTHORITY_TABLE */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00}, + /* C_PIN_TABLE */ + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00}, + /* OPAL Locking Info */ + { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 }, + /* Enterprise Locking Info */ + { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 }, + + /* C_PIN_TABLE object ID's */ + + /* C_PIN_MSID */ + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02}, + /* C_PIN_SID */ + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01}, + /* C_PIN_ADMIN1 */ + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01}, + + /* half UID's (only first 4 bytes used) */ + + /* Half-UID ? Authority_object_ref */ + { 0x00, 0x00, 0x0C, 0x05, 0xff, 0xff, 0xff, 0xff }, + /* Half-UID ? Boolean ACE */ + { 0x00, 0x00, 0x04, 0x0E, 0xff, 0xff, 0xff, 0xff }, + + /* special value for omitted optional parameter */ + + /* HEXFF for omitted */ + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, +}; +static const size_t OPAL_UID_LENGTH = 8; +static const size_t OPAL_MSID_KEYLEN = 15; +static const size_t OPAL_UID_LENGTH_HALF = 4; + + +/* Enum to index OPALUID array */ +enum OPAL_UID { + /* users */ + OPAL_SMUID_UID, + OPAL_THISSP_UID, + OPAL_ADMINSP_UID, + OPAL_LOCKINGSP_UID, + OPAL_ENTERPRISE_LOCKINGSP_UID, + OPAL_ANYBODY_UID, + OPAL_SID_UID, + OPAL_ADMIN1_UID, + OPAL_USER1_UID, + OPAL_USER2_UID, + OPAL_PSID_UID, + OPAL_ENTERPRISE_BANDMASTER0_UID, + OPAL_ENTERPRISE_ERASEMASTER_UID, + /* tables */ + OPAL_LOCKINGRANGE_GLOBAL, + OPAL_LOCKINGRANGE_ACE_RDLOCKED, + OPAL_LOCKINGRANGE_ACE_WRLOCKED, + OPAL_MBRCONTROL, + OPAL_MBR, + OPAL_AUTHORITY_TABLE, + OPAL_C_PIN_TABLE, + OPAL_LOCKING_INFO_TABLE, + OPAL_ENTERPRISE_LOCKING_INFO_TABLE, + /* C_PIN_TABLE object ID's */ + OPAL_C_PIN_MSID, + OPAL_C_PIN_SID, + OPAL_C_PIN_ADMIN1, + /* half UID's (only first 4 bytes used) */ + OPAL_HALF_UID_AUTHORITY_OBJ_REF, + OPAL_HALF_UID_BOOLEAN_ACE, + /* omitted optional parameter */ + OPAL_UID_HEXFF, +}; + +/* + * TCG Storage SSC Methods. + */ +static const u8 OPALMETHOD[][8] = { + /* Properties */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01 }, + /* STARTSESSION */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02 }, + /* Revert */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02 }, + /* Activate */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03 }, + /* Enterprise Get */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06 }, + /* Enterprise Set */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07 }, + /* NEXT */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08 }, + /* Enterprise Authenticate */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c }, + /* GetACL */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d }, + /* GenKey */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10 }, + /* revertSP */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11 }, + /* Get */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16 }, + /* Set */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17 }, + /* Authenticate */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c }, + /* Random */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 }, + /* Erase */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 }, +}; +static const size_t OPAL_METHOD_LENGTH = 8; + +/* Enum for indexing the OPALMETHOD array */ +enum OPAL_METHOD { + OPAL_PROPERTIES, + OPAL_STARTSESSION, + OPAL_REVERT, + OPAL_ACTIVATE, + OPAL_EGET, + OPAL_ESET, + OPAL_NEXT, + OPAL_EAUTHENTICATE, + OPAL_GETACL, + OPAL_GENKEY, + OPAL_REVERTSP, + OPAL_GET, + OPAL_SET, + OPAL_AUTHENTICATE, + OPAL_RANDOM, + OPAL_ERASE, +}; + +enum OPAL_RESPONSE_TOKEN { + OPAL_DTA_TOKENID_BYTESTRING = 0xe0, + OPAL_DTA_TOKENID_SINT = 0xe1, + OPAL_DTA_TOKENID_UINT = 0xe2, + OPAL_DTA_TOKENID_TOKEN = 0xe3, /* actual token is returned */ + OPAL_DTA_TOKENID_INVALID = 0X0 +}; + +enum OPAL_TOKEN { + /* Boolean */ + OPAL_TRUE = 0x01, + OPAL_FALSE = 0x00, + OPAL_BOOLEAN_EXPR = 0x03, + /* cellblocks */ + OPAL_TABLE = 0x00, + OPAL_STARTROW = 0x01, + OPAL_ENDROW = 0x02, + OPAL_STARTCOLUMN = 0x03, + OPAL_ENDCOLUMN = 0x04, + OPAL_VALUES = 0x01, + /* authority table */ + OPAL_PIN = 0x03, + /* locking tokens */ + OPAL_RANGESTART = 0x03, + OPAL_RANGELENGTH = 0x04, + OPAL_READLOCKENABLED = 0x05, + OPAL_WRITELOCKENABLED = 0x06, + OPAL_READLOCKED = 0x07, + OPAL_WRITELOCKED = 0x08, + OPAL_ACTIVEKEY = 0x0A, + /* locking info table */ + OPAL_MAXRANGES = 0x04, + /* mbr control */ + OPAL_MBRENABLE = 0x01, + OPAL_MBRDONE = 0x02, + /* properties */ + OPAL_HOSTPROPERTIES = 0x00, + /* atoms */ + OPAL_STARTLIST = 0xf0, + OPAL_ENDLIST = 0xf1, + OPAL_STARTNAME = 0xf2, + OPAL_ENDNAME = 0xf3, + OPAL_CALL = 0xf8, + OPAL_ENDOFDATA = 0xf9, + OPAL_ENDOFSESSION = 0xfa, + OPAL_STARTTRANSACTON = 0xfb, + OPAL_ENDTRANSACTON = 0xfC, + OPAL_EMPTYATOM = 0xff, + OPAL_WHERE = 0x00, +}; + +/* Useful tiny atoms. + * Useful for table columns etc + */ +enum OPAL_TINY_ATOM { + OPAL_TINY_UINT_00 = 0x00, + OPAL_TINY_UINT_01 = 0x01, + OPAL_TINY_UINT_02 = 0x02, + OPAL_TINY_UINT_03 = 0x03, + OPAL_TINY_UINT_04 = 0x04, + OPAL_TINY_UINT_05 = 0x05, + OPAL_TINY_UINT_06 = 0x06, + OPAL_TINY_UINT_07 = 0x07, + OPAL_TINY_UINT_08 = 0x08, + OPAL_TINY_UINT_09 = 0x09, + OPAL_TINY_UINT_10 = 0x0a, + OPAL_TINY_UINT_11 = 0x0b, + OPAL_TINY_UINT_12 = 0x0c, + OPAL_TINY_UINT_13 = 0x0d, + OPAL_TINY_UINT_14 = 0x0e, + OPAL_TINY_UINT_15 = 0x0f, +}; + +enum OPAL_ATOM_WIDTH { + OPAL_WIDTH_TINY, + OPAL_WIDTH_SHORT, + OPAL_WIDTH_MEDIUM, + OPAL_WIDTH_LONG, + OPAL_WIDTH_TOKEN +}; + +/* Locking state for a locking range */ +enum OPAL_LOCKINGSTATE { + OPAL_LOCKING_READWRITE = 0x01, + OPAL_LOCKING_READONLY = 0x02, + OPAL_LOCKING_LOCKED = 0x03, +}; + +/* + * Structures to build and decode the Opal SSC messages + * fields that are NOT really numeric are defined as u8[] to + * help reduce the endianness issues + */ + +/* Comm Packet (header) for transmissions. */ +struct opal_compacket { + u32 reserved0; + u8 extendedComID[4]; + u32 outstandingData; + u32 minTransfer; + u32 length; +}; + +/* Packet structure. */ +struct opal_packet { + u32 TSN; + u32 HSN; + u32 seq_number; + u16 reserved0; + u16 ack_type; + u32 acknowledgment; + u32 length; +}; + +/* Data sub packet header */ +struct opal_data_subpacket { + u8 reserved0[6]; + u16 kind; + u32 length; +}; + +/* header of a response */ +struct opal_header { + struct opal_compacket cp; + struct opal_packet pkt; + struct opal_data_subpacket subpkt; +}; + +#define FC_TPER 0x0001 +#define FC_LOCKING 0x0002 +#define FC_GEOMETRY 0x0003 +#define FC_ENTERPRISE 0x0100 +#define FC_DATASTORE 0x0202 +#define FC_SINGLEUSER 0x0201 +#define FC_OPALV100 0x0200 +#define FC_OPALV200 0x0203 + +/* + * The Discovery 0 Header. As defined in + * Opal SSC Documentation + */ +struct d0_header { + u32 length; /* the length of the header 48 in 2.00.100 */ + u32 revision; /**< revision of the header 1 in 2.00.100 */ + u32 reserved01; + u32 reserved02; + /* + * the remainder of the structure is vendor specific and will not be + * addressed now + */ + u8 ignored[32]; +}; + +/* + * TPer Feature Descriptor. Contains flags indicating support for the + * TPer features described in the OPAL specification. The names match the + * OPAL terminology + * + * code == 0x001 in 2.00.100 + */ +struct d0_tper_features { + /* + * supported_features bits: + * bit 7: reserved + * bit 6: com ID management + * bit 5: reserved + * bit 4: streaming support + * bit 3: buffer management + * bit 2: ACK/NACK + * bit 1: async + * bit 0: sync + */ + u8 supported_features; + /* + * bytes 5 through 15 are reserved, but we represent the first 3 as + * u8 to keep the other two 32bits integers aligned. + */ + u8 reserved01[3]; + u32 reserved02; + u32 reserved03; +}; + +/* + * Locking Feature Descriptor. Contains flags indicating support for the + * locking features described in the OPAL specification. The names match the + * OPAL terminology + * + * code == 0x0002 in 2.00.100 + */ +struct d0_locking_features { + /* + * supported_features bits: + * bits 6-7: reserved + * bit 5: MBR done + * bit 4: MBR enabled + * bit 3: media encryption + * bit 2: locked + * bit 1: locking enabled + * bit 0: locking supported + */ + u8 supported_features; + /* + * bytes 5 through 15 are reserved, but we represent the first 3 as + * u8 to keep the other two 32bits integers aligned. + */ + u8 reserved01[3]; + u32 reserved02; + u32 reserved03; +}; + +/* + * Geometry Feature Descriptor. Contains flags indicating support for the + * geometry features described in the OPAL specification. The names match the + * OPAL terminology + * + * code == 0x0003 in 2.00.100 + */ +struct d0_geometry_features { + /* + * skip 32 bits from header, needed to align the struct to 64 bits. + */ + u8 header[4]; + /* + * reserved01: + * bits 1-6: reserved + * bit 0: align + */ + u8 reserved01; + u8 reserved02[7]; + u32 logical_block_size; + u64 alignment_granularity; + u64 lowest_aligned_lba; +}; + +/* + * Enterprise SSC Feature + * + * code == 0x0100 + */ +struct d0_enterprise_ssc { + u16 baseComID; + u16 numComIDs; + /* range_crossing: + * bits 1-6: reserved + * bit 0: range crossing + */ + u8 range_crossing; + u8 reserved01; + u16 reserved02; + u32 reserved03; + u32 reserved04; +}; + +/* + * Opal V1 feature + * + * code == 0x0200 + */ +struct d0_opal_v100 { + u16 baseComID; + u16 numComIDs; +}; + +/* + * Single User Mode feature + * + * code == 0x0201 + */ +struct d0_single_user_mode { + u32 num_locking_objects; + /* reserved01: + * bit 0: any + * bit 1: all + * bit 2: policy + * bits 3-7: reserved + */ + u8 reserved01; + u8 reserved02; + u16 reserved03; + u32 reserved04; +}; + +/* + * Additonal Datastores feature + * + * code == 0x0202 + */ +struct d0_datastore_table { + u16 reserved01; + u16 max_tables; + u32 max_size_tables; + u32 table_size_alignment; +}; + +/* + * OPAL 2.0 feature + * + * code == 0x0203 + */ +struct d0_opal_v200 { + u16 baseComID; + u16 numComIDs; + /* range_crossing: + * bits 1-6: reserved + * bit 0: range crossing + */ + u8 range_crossing; + /* num_locking_admin_auth: + * not aligned to 16 bits, so use two u8. + * stored in big endian: + * 0: MSB + * 1: LSB + */ + u8 num_locking_admin_auth[2]; + /* num_locking_user_auth: + * not aligned to 16 bits, so use two u8. + * stored in big endian: + * 0: MSB + * 1: LSB + */ + u8 num_locking_user_auth[2]; + u8 initialPIN; + u8 revertedPIN; + u8 reserved01; + u32 reserved02; +}; + +/* Union of features used to parse the discovery 0 response */ +struct d0_features { + u16 code; + /* + * r_version bits: + * bits 4-7: version + * bits 0-3: reserved + */ + u8 r_version; + u8 length; + u8 features[]; +}; + +struct key *request_user_key(const char *master_desc, const u8 **master_key, + size_t *master_keylen); + +#endif /* _NVME_OPAL_INTERNAL_H */ diff --git a/lib/sed-opal_key.c b/lib/sed-opal_key.c new file mode 100644 index 0000000..0b4de01 --- /dev/null +++ b/lib/sed-opal_key.c @@ -0,0 +1,46 @@ +/* + * Copyright ? 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Author: + * Rafael Antognolli + */ + +#include +#include "sed-opal_internal.h" + +struct key *request_user_key(const char *master_desc, const u8 **master_key, + size_t *master_keylen) +{ + const struct user_key_payload *upayload; + struct key *ukey; + + ukey = request_key(&key_type_user, master_desc, NULL); + if (IS_ERR(ukey)) + goto error; + + down_read(&ukey->sem); + upayload = user_key_payload(ukey); + *master_key = upayload->data; + *master_keylen = upayload->datalen; +error: + return ukey; +} diff --git a/lib/sed.c b/lib/sed.c new file mode 100644 index 0000000..06cacd9 --- /dev/null +++ b/lib/sed.c @@ -0,0 +1,303 @@ +#include +#include +#include + +#ifndef CONFIG_SED_OPAL +static int sed_opal_save(struct block_device *bdev, struct sed_key *sed) + { return -EOPNOTSUPP; } +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_take_ownership(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_activate_lsp(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_set_pw(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_activate_user(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_reverttper(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_setup_locking_range(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_adduser_to_lr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_do_mbr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_erase_lr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } + +#else + +static int sed_opal_save(struct block_device *bdev, struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_save(bdev, key); +} + +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_lock_unlock(bdev, key); +} + +static int sed_opal_take_ownership(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_take_ownership(bdev, key); +} + +static int sed_opal_activate_lsp(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_activate_lsp(bdev, key); +} + +static int sed_opal_set_pw(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_set_new_pw(bdev, key); +} + +static int sed_opal_activate_user(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_activate_user(bdev, key); +} + +static int sed_opal_reverttper(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_reverttper(bdev, key); +} + +static int sed_opal_setup_lr(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_setup_locking_range(bdev, key); +} + +static int sed_opal_adduser_to_lr(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_add_user_to_lr(bdev, key); +} + +static int sed_opal_do_mbr(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_enable_disable_shadow_mbr(bdev, key); +} + +static int sed_opal_erase_lr(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_erase_locking_range(bdev, key); +} +#endif + +int sed_save(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_LOCK_UNLOCK: + return sed_opal_save(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_lock_unlock(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_LOCK_UNLOCK: + return sed_opal_lock_unlock(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_take_ownership(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL: + return sed_opal_take_ownership(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_activate_lsp(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL: + return sed_opal_activate_lsp(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_set_pw(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_PW: + return sed_opal_set_pw(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_activate_user(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_ACT_USR: + return sed_opal_activate_user(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_reverttper(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL: + return sed_opal_reverttper(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_LR_SETUP: + return sed_opal_setup_lr(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_LOCK_UNLOCK: + return sed_opal_adduser_to_lr(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_do_mbr(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_MBR_DATA: + return sed_opal_do_mbr(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_erase_lr(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL: + return sed_opal_erase_lr(bdev, key); + } + + return -EOPNOTSUPP; +} -- 2.7.4