All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] SED OPAL Library
@ 2016-11-29 21:51 ` Scott Bauer
  0 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-29 21:51 UTC (permalink / raw)
  To: linux-nvme
  Cc: keith.busch, sagi, hch, Rafael.Antognolli, axboe, linux-block,
	jonathan.derrick, j.naumann

Changes from v1->v2
1) Removed work queues and call backs. The code now operates in
   in a normal call chain fashion. Each opal command provides a
   series of commands it needs to run. next() iterates through
   the functions only calling the subsequent function once the
   current has finished and if no error has occured.

2) Refactored the ioctl handling. A driver that wants to
   support SED now sets up a block ioctl handler and forwards
   the request into the sed library.

3) The implementing ioctl handler in the driver now passes a
   combined send/recv function pointer and a pointer to "data"
   that may be necessary for sending data to the controller.
   In the case of nvme we send the "nvme_sec_submit" fn pointer
   as well as a nvme_ns sturcutre as the "data".

   When the sed library wants to send the opal packet to the
   controller it calls the fn pointer. In this case it calls
   nvme_sec_submit, and passes the nvme_ns. The nvme driver
   handles the actual submission to the controller.

4) Instead of passing around strings we now pass around major
   and minor numbers.

5) Removed the user-land pointer indirection.

6) Moved sed* from lib/ to block/

7) Removed the manditory secure erase when setting up a locking
   range. Instead made a new secure erase function.

9) Added a kref_get and nvme_ns_put in the unlock_from_suspend.

8) Added addition to MAINTAINERS
--------------------------------------------------------------------

This Patch series implements a large portion of the Opal protocol for
self encrypting devices. The driver has the capability of storing a
locking range's password. It either stores directly in the driver,
or in the Kernel's key managment. The password can then be replayed
during a resume from previous suspend-to-RAM.

The driver also supports logic to bring the device out of a factory
default-inactive state into a functional Opal state.

The following logic is supported in order to bring the tper into a
working state:

1) Taking Ownership of the drive (Setting the Admin CPIN).
2) Activating the Locking SP (In Single User Mode or Normal Mode).
3) Setting up Locking Ranges (Single User or Normal Mode).
4) Adding users to Locking Ranges (Normal Mode Only).
5) Locking or Unlocking Locking Rangs (Single User Mode or Normal Mode).
6) Reverting the TPer (Restore to factory default).
7) Setting LR/User passwords (Single User Mode or Normal Mode).
8) Eabling/disabling Shadow MBR.
9) Enabling Users in the LockingSP (Normal Mode Only).
10) Saving Password for resume from suspend.


Each command above is exported through an ioctl in the block layer.

Scott Bauer (4):
  include: Add definitions for sed
  block: Add Sed-opal library
  nvme: Implement resume_from_suspend and sed block ioctl
  Maintainers: Add Information for SED Opal library

 MAINTAINERS                   |   10 +
 block/Makefile                |    2 +-
 block/sed-opal.c              | 3157 +++++++++++++++++++++++++++++++++++++++++
 block/sed-opal_internal.h     |  601 ++++++++
 block/sed.c                   |  207 +++
 drivers/nvme/host/core.c      |   76 +
 drivers/nvme/host/nvme.h      |    4 +-
 drivers/nvme/host/pci.c       |    7 +-
 include/linux/sed-opal.h      |   57 +
 include/linux/sed.h           |   85 ++
 include/uapi/linux/sed-opal.h |  108 ++
 include/uapi/linux/sed.h      |   64 +
 12 files changed, 4375 insertions(+), 3 deletions(-)
 create mode 100644 block/sed-opal.c
 create mode 100644 block/sed-opal_internal.h
 create mode 100644 block/sed.c
 create mode 100644 include/linux/sed-opal.h
 create mode 100644 include/linux/sed.h
 create mode 100644 include/uapi/linux/sed-opal.h
 create mode 100644 include/uapi/linux/sed.h



_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 0/4] SED OPAL Library
@ 2016-11-29 21:51 ` Scott Bauer
  0 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-29 21:51 UTC (permalink / raw)


Changes from v1->v2
1) Removed work queues and call backs. The code now operates in
   in a normal call chain fashion. Each opal command provides a
   series of commands it needs to run. next() iterates through
   the functions only calling the subsequent function once the
   current has finished and if no error has occured.

2) Refactored the ioctl handling. A driver that wants to
   support SED now sets up a block ioctl handler and forwards
   the request into the sed library.

3) The implementing ioctl handler in the driver now passes a
   combined send/recv function pointer and a pointer to "data"
   that may be necessary for sending data to the controller.
   In the case of nvme we send the "nvme_sec_submit" fn pointer
   as well as a nvme_ns sturcutre as the "data".

   When the sed library wants to send the opal packet to the
   controller it calls the fn pointer. In this case it calls
   nvme_sec_submit, and passes the nvme_ns. The nvme driver
   handles the actual submission to the controller.

4) Instead of passing around strings we now pass around major
   and minor numbers.

5) Removed the user-land pointer indirection.

6) Moved sed* from lib/ to block/

7) Removed the manditory secure erase when setting up a locking
   range. Instead made a new secure erase function.

9) Added a kref_get and nvme_ns_put in the unlock_from_suspend.

8) Added addition to MAINTAINERS
--------------------------------------------------------------------

This Patch series implements a large portion of the Opal protocol for
self encrypting devices. The driver has the capability of storing a
locking range's password. It either stores directly in the driver,
or in the Kernel's key managment. The password can then be replayed
during a resume from previous suspend-to-RAM.

The driver also supports logic to bring the device out of a factory
default-inactive state into a functional Opal state.

The following logic is supported in order to bring the tper into a
working state:

1) Taking Ownership of the drive (Setting the Admin CPIN).
2) Activating the Locking SP (In Single User Mode or Normal Mode).
3) Setting up Locking Ranges (Single User or Normal Mode).
4) Adding users to Locking Ranges (Normal Mode Only).
5) Locking or Unlocking Locking Rangs (Single User Mode or Normal Mode).
6) Reverting the TPer (Restore to factory default).
7) Setting LR/User passwords (Single User Mode or Normal Mode).
8) Eabling/disabling Shadow MBR.
9) Enabling Users in the LockingSP (Normal Mode Only).
10) Saving Password for resume from suspend.


Each command above is exported through an ioctl in the block layer.

Scott Bauer (4):
  include: Add definitions for sed
  block: Add Sed-opal library
  nvme: Implement resume_from_suspend and sed block ioctl
  Maintainers: Add Information for SED Opal library

 MAINTAINERS                   |   10 +
 block/Makefile                |    2 +-
 block/sed-opal.c              | 3157 +++++++++++++++++++++++++++++++++++++++++
 block/sed-opal_internal.h     |  601 ++++++++
 block/sed.c                   |  207 +++
 drivers/nvme/host/core.c      |   76 +
 drivers/nvme/host/nvme.h      |    4 +-
 drivers/nvme/host/pci.c       |    7 +-
 include/linux/sed-opal.h      |   57 +
 include/linux/sed.h           |   85 ++
 include/uapi/linux/sed-opal.h |  108 ++
 include/uapi/linux/sed.h      |   64 +
 12 files changed, 4375 insertions(+), 3 deletions(-)
 create mode 100644 block/sed-opal.c
 create mode 100644 block/sed-opal_internal.h
 create mode 100644 block/sed.c
 create mode 100644 include/linux/sed-opal.h
 create mode 100644 include/linux/sed.h
 create mode 100644 include/uapi/linux/sed-opal.h
 create mode 100644 include/uapi/linux/sed.h

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 1/4] include: Add definitions for sed
  2016-11-29 21:51 ` Scott Bauer
@ 2016-11-29 21:51   ` Scott Bauer
  -1 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-29 21:51 UTC (permalink / raw)
  To: linux-nvme
  Cc: keith.busch, sagi, hch, Rafael.Antognolli, axboe, linux-block,
	Scott Bauer, jonathan.derrick, j.naumann

VGhpcyBwYXRjaCBhZGRzIHRoZSBkZWZpbml0aW9ucyBhbmQgc3RydWN0dXJlcyBmb3IgdGhlIFNF
RApPcGFsIGNvZGUuCgpTaWduZWQtb2ZmLWJ5OiBTY290dCBCYXVlciA8c2NvdHQuYmF1ZXJAaW50
ZWwuY29tPgpTaWduZWQtb2ZmLWJ5OiBSYWZhZWwgQW50b2dub2xsaSA8UmFmYWVsLkFudG9nbm9s
bGlAaW50ZWwuY29tPgotLS0KIGluY2x1ZGUvbGludXgvc2VkLW9wYWwuaCAgICAgIHwgIDU3ICsr
KysrKysrKysrKysrKysrKysrKysKIGluY2x1ZGUvbGludXgvc2VkLmggICAgICAgICAgIHwgIDg1
ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogaW5jbHVkZS91YXBpL2xpbnV4L3Nl
ZC1vcGFsLmggfCAxMDggKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
CiBpbmNsdWRlL3VhcGkvbGludXgvc2VkLmggICAgICB8ICA2NCArKysrKysrKysrKysrKysrKysr
KysrKysrCiA0IGZpbGVzIGNoYW5nZWQsIDMxNCBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAx
MDA2NDQgaW5jbHVkZS9saW51eC9zZWQtb3BhbC5oCiBjcmVhdGUgbW9kZSAxMDA2NDQgaW5jbHVk
ZS9saW51eC9zZWQuaAogY3JlYXRlIG1vZGUgMTAwNjQ0IGluY2x1ZGUvdWFwaS9saW51eC9zZWQt
b3BhbC5oCiBjcmVhdGUgbW9kZSAxMDA2NDQgaW5jbHVkZS91YXBpL2xpbnV4L3NlZC5oCgpkaWZm
IC0tZ2l0IGEvaW5jbHVkZS9saW51eC9zZWQtb3BhbC5oIGIvaW5jbHVkZS9saW51eC9zZWQtb3Bh
bC5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjljNmQ4NDkKLS0tIC9kZXYv
bnVsbAorKysgYi9pbmNsdWRlL2xpbnV4L3NlZC1vcGFsLmgKQEAgLTAsMCArMSw1NyBAQAorLyoK
KyAqIENvcHlyaWdodCDCqSAyMDE2IEludGVsIENvcnBvcmF0aW9uCisgKgorICogQXV0aG9yczoK
KyAqICAgIFJhZmFlbCBBbnRvZ25vbGxpIDxyYWZhZWwuYW50b2dub2xsaUBpbnRlbC5jb20+Cisg
KiAgICBTY290dCAgQmF1ZXIgICAgICA8c2NvdHQuYmF1ZXJAaW50ZWwuY29tPgorICoKKyAqIFRo
aXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQv
b3IgbW9kaWZ5IGl0CisgKiB1bmRlciB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdGhlIEdO
VSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlLAorICogdmVyc2lvbiAyLCBhcyBwdWJsaXNoZWQgYnkg
dGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZGlz
dHJpYnV0ZWQgaW4gdGhlIGhvcGUgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUCisgKiBB
TlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFO
VEFCSUxJVFkgb3IKKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRo
ZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IKKyAqIG1vcmUgZGV0YWlscy4KKyAqLwor
CisjaWZuZGVmIExJTlVYX09QQUxfSAorI2RlZmluZSBMSU5VWF9PUEFMX0gKKworI2luY2x1ZGUg
PGxpbnV4L3NlZC5oPgorI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgorCitzdHJ1Y3Qgb3BhbF9z
dXNwZW5kX3VubGsgeworCXZvaWQgKnN1Ym1pdF9kYXRhOworCWRldl90IGRldjsKKwlzZWRfc2Vj
X3N1Ym1pdCAqc3VibWl0X2ZuOworfTsKKworaW50IG9wYWxfc2F2ZShzdHJ1Y3QgYmxvY2tfZGV2
aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorCSAgICAgIHZvaWQgKnNibXRfZGF0YSwg
c2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbik7CitpbnQgb3BhbF9sb2NrX3VubG9jayhzdHJ1Y3Qg
YmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorCQkgICAgIHZvaWQgKnNi
bXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbik7CitpbnQgb3BhbF90YWtlX293bmVy
c2hpcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorCQkJ
dm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKTsKK2ludCBvcGFsX2Fj
dGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5
LAorCQkgICAgICB2b2lkICpzYm10X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pOwor
aW50IG9wYWxfc2V0X25ld19wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk
X2tleSAqa2V5LAorCQkgICAgdm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0
X2ZuKTsKK2ludCBvcGFsX2FjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg
c3RydWN0IHNlZF9rZXkgKmtleSwKKwkJICAgICAgIHZvaWQgKnNibXRfZGF0YSwgc2VkX3NlY19z
dWJtaXQgKnN1Ym1pdF9mbik7CitpbnQgb3BhbF9yZXZlcnR0cGVyKHN0cnVjdCBibG9ja19kZXZp
Y2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXksCisJCSAgICB2b2lkICpzYm10X2RhdGEsIHNl
ZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pOworaW50IG9wYWxfc2V0dXBfbG9ja2luZ19yYW5nZShz
dHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorCQkJICAgICB2
b2lkICpzYm10X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pOworaW50IG9wYWxfYWRk
X3VzZXJfdG9fbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtl
eSwKKwkJCXZvaWQgKnNibXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbik7CitpbnQg
b3BhbF9lbmFibGVfZGlzYWJsZV9zaGFkb3dfbWJyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYs
IHN0cnVjdCBzZWRfa2V5ICprZXksCisJCQkJICAgdm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1
Ym1pdCAqc3VibWl0X2ZuKTsKK2ludCBvcGFsX2VyYXNlX2xvY2tpbmdfcmFuZ2Uoc3RydWN0IGJs
b2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSwKKwkJCSAgICAgdm9pZCAqc2Jt
dF9kYXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKTsKK2ludCBvcGFsX3NlY3VyZV9lcmFz
ZV9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkJICAgIHN0cnVj
dCBzZWRfa2V5ICprZXksIHZvaWQgKnNibXRfZGF0YSwKKwkJCQkgICAgc2VkX3NlY19zdWJtaXQg
KnN1Ym1pdF9mbik7CitpbnQgb3BhbF91bmxvY2tfZnJvbV9zdXNwZW5kKHN0cnVjdCBvcGFsX3N1
c3BlbmRfdW5sayAqZGF0YSk7CisKKyNlbmRpZiAvKiBMSU5VWF9PUEFMX0ggKi8KZGlmZiAtLWdp
dCBhL2luY2x1ZGUvbGludXgvc2VkLmggYi9pbmNsdWRlL2xpbnV4L3NlZC5oCm5ldyBmaWxlIG1v
ZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjdjM2I2OWIKLS0tIC9kZXYvbnVsbAorKysgYi9pbmNs
dWRlL2xpbnV4L3NlZC5oCkBAIC0wLDAgKzEsODUgQEAKKy8qCisgKiBTZWxmLUVuY3J5cHRpbmcg
RHJpdmUgaW50ZXJmYWNlIC0gc2VkLmgKKyAqCisgKiBDb3B5cmlnaHQgwqkgMjAxNiBJbnRlbCBD
b3Jwb3JhdGlvbgorICoKKyAqIEF1dGhvcnM6CisgKiAgICBSYWZhZWwgQW50b2dub2xsaSA8cmFm
YWVsLmFudG9nbm9sbGlAaW50ZWwuY29tPgorICogICAgU2NvdHQgIEJhdWVyICAgICAgPHNjb3R0
LmJhdWVyQGludGVsLmNvbT4KKyAqICAgIEpvbmF0aGFuIERlcnJpY2sgIDxqb25hdGhhbi5kZXJy
aWNrQGludGVsLmNvbT4KKyAqCisgKiBUaGlzIGNvZGUgaXMgdGhlIGdlbmVyaWMgbGF5ZXIgdG8g
aW50ZXJmYWNlIHdpdGggc2VsZi1lbmNyeXB0aW5nCisgKiBkcml2ZXMuIFNwZWNpZmljIGNvbW1h
bmQgc2V0cyBzaG91bGQgYWR2ZXJ0aXNlIHN1cHBvcnQgdG8gc2VkIHVhcGkKKyAqCisgKiBUaGlz
IHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29y
IG1vZGlmeSBpdAorICogdW5kZXIgdGhlIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHRoZSBHTlUg
R2VuZXJhbCBQdWJsaWMgTGljZW5zZSwKKyAqIHZlcnNpb24gMiwgYXMgcHVibGlzaGVkIGJ5IHRo
ZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24uCisgKgorICogVGhpcyBwcm9ncmFtIGlzIGRpc3Ry
aWJ1dGVkIGluIHRoZSBob3BlIGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVAorICogQU5Z
IFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRB
QklMSVRZIG9yCisgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUg
R05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yCisgKiBtb3JlIGRldGFpbHMuCisgKgorICov
CisKKyNpZm5kZWYgTElOVVhfU0VEX0gKKyNkZWZpbmUgTElOVVhfU0VEX0gKKworI2luY2x1ZGUg
PGxpbnV4L2Jsa2Rldi5oPgorI2luY2x1ZGUgPHVhcGkvbGludXgvc2VkLmg+CisKKworLyoKKyAq
IFRoZXNlIGNvbnN0YW50IHZhbHVlcyBjb21lIGZyb206CisgKiBUQ0cgU3RvcmFnZSBBcmNoaXRl
Y3R1cmUgQ29yZSBTcGVjIHYyLjAxIHIxCisgKiBTZWN0aW9uOiAzLjMgSW50ZXJmYWNlIENvbW11
bmljYXRpb25zCisgKi8KK2VudW0geworCVRDR19TRUNQXzAwID0gMCwKKwlUQ0dfU0VDUF8wMSwK
K307CisKKy8qCisgKiBzZWRfc2VjX3N1Ym1pdCAtIHRyYW5zcG9ydCBzcGVjaWZpYyBUcnVzdGVk
IFNlbmQvUmVjZWl2ZSBmdW5jdGlvbnMKKyAqIFNlZSBTUEMtNCBmb3Igc3BlY2lmaWMgZGVmaW5p
dGlvbnMKKyAqCisgKiBAc2VjX3NlY19zdWJtaXQ6IHNlbmRzIG9yIHJlY2lldmVzIHRoZSBwYXls
b2FkIHRvIHRoZSB0cnVzdGVkIHBlcmlwaGVyYWwKKyAqCVNQU1A6IFNlY3VyaXR5IFByb3RvY29s
IFNwZWNpZmljCisgKglTRUNQOiBTZWN1cml0eSBQcm90b2NvbAorICoJYnVmZmVyOiBQYXlsb2Fk
CisgKglsZW46IFBheWxvYWQgbGVuZ3RoCisgKiAgICAgIGJvb2w6IFdldGhlciB0byBzZW5kKHRy
dWUpIG9yIHRvIHJlY2lldmUoZmFsc2UpCisgKi8KKwordHlwZWRlZiBpbnQgKHNlZF9zZWNfc3Vi
bWl0KSh2b2lkICpkYXRhLCB1MTYgc3BzcCwgdTggc2VjcCwKKwkJCSAgICAgdm9pZCAqYnVmZmVy
LCBzaXplX3QgbGVuLCBib29sIHNlbmQpOworCitpbnQgc2VkX3NhdmUoc3RydWN0IGJsb2NrX2Rl
dmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSwKKyAgICAgICAgICAgICAgICAgdm9pZCAq
c2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKTsKK2ludCBzZWRfbG9ja191bmxv
Y2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSwKKyAgICAg
ICAgICAgICAgICAgdm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKTsK
K2ludCBzZWRfdGFrZV9vd25lcnNoaXAoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0
IHNlZF9rZXkgKmtleSwKKyAgICAgICAgICAgICAgICAgdm9pZCAqc2JtdF9kYXRhLCBzZWRfc2Vj
X3N1Ym1pdCAqc3VibWl0X2ZuKTsKK2ludCBzZWRfYWN0aXZhdGVfbHNwKHN0cnVjdCBibG9ja19k
ZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXksCisgICAgICAgICAgICAgICAgIHZvaWQg
KnNibXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbik7CitpbnQgc2VkX3NldF9wdyhz
dHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorICAgICAgICAg
ICAgICAgICB2b2lkICpzYm10X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pOworaW50
IHNlZF9hY3RpdmF0ZV91c2VyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf
a2V5ICprZXksCisgICAgICAgICAgICAgICAgIHZvaWQgKnNibXRfZGF0YSwgc2VkX3NlY19zdWJt
aXQgKnN1Ym1pdF9mbik7CitpbnQgc2VkX3JldmVydHRwZXIoc3RydWN0IGJsb2NrX2RldmljZSAq
YmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSwKKyAgICAgICAgICAgICAgICAgdm9pZCAqc2JtdF9k
YXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKTsKK2ludCBzZWRfc2V0dXBfbG9ja2luZ19y
YW5nZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorICAg
ICAgICAgICAgICAgICB2b2lkICpzYm10X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4p
OworaW50IHNlZF9hZGR1c2VyX3RvX2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVj
dCBzZWRfa2V5ICprZXksCisgICAgICAgICAgICAgICAgIHZvaWQgKnNibXRfZGF0YSwgc2VkX3Nl
Y19zdWJtaXQgKnN1Ym1pdF9mbik7CitpbnQgc2VkX2RvX21icihzdHJ1Y3QgYmxvY2tfZGV2aWNl
ICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorICAgICAgICAgICAgICAgICB2b2lkICpzYm10
X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pOworaW50IHNlZF9lcmFzZV9scihzdHJ1
Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorICAgICAgICAgICAg
ICAgICB2b2lkICpzYm10X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pOworaW50IHNl
ZF9zZWN1cmVfZXJhc2VfbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9r
ZXkgKmtleSwKKwkJCXZvaWQgKnNibXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbik7
CitpbnQgYmxrZGV2X3NlZF9pb2N0bChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBmbW9kZV90
IGZtb2RlLCB1bnNpZ25lZCBpbnQgY21kLAorCQkgICAgIHVuc2lnbmVkIGxvbmcgYXJnLCB2b2lk
ICpzYm10X2N0cmxfZGF0YSwKKwkJICAgICBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKTsKKwor
I2VuZGlmIC8qIExJTlVYX1NFRF9IICovCmRpZmYgLS1naXQgYS9pbmNsdWRlL3VhcGkvbGludXgv
c2VkLW9wYWwuaCBiL2luY2x1ZGUvdWFwaS9saW51eC9zZWQtb3BhbC5oCm5ldyBmaWxlIG1vZGUg
MTAwNjQ0CmluZGV4IDAwMDAwMDAuLjM0Njg5YTkKLS0tIC9kZXYvbnVsbAorKysgYi9pbmNsdWRl
L3VhcGkvbGludXgvc2VkLW9wYWwuaApAQCAtMCwwICsxLDEwOCBAQAorLyoKKyAqIENvcHlyaWdo
dCDCqSAyMDE2IEludGVsIENvcnBvcmF0aW9uCisgKgorICogQXV0aG9yczoKKyAqICAgIFJhZmFl
bCBBbnRvZ25vbGxpIDxyYWZhZWwuYW50b2dub2xsaUBpbnRlbC5jb20+CisgKiAgICBTY290dCAg
QmF1ZXIgICAgICA8c2NvdHQuYmF1ZXJAaW50ZWwuY29tPgorICoKKyAqIFRoaXMgcHJvZ3JhbSBp
cyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0
CisgKiB1bmRlciB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1
YmxpYyBMaWNlbnNlLAorICogdmVyc2lvbiAyLCBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29m
dHdhcmUgRm91bmRhdGlvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4g
dGhlIGhvcGUgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUCisgKiBBTlkgV0FSUkFOVFk7
IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFkgb3IK
KyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUgR2VuZXJh
bCBQdWJsaWMgTGljZW5zZSBmb3IKKyAqIG1vcmUgZGV0YWlscy4KKyAqLworCisjaWZuZGVmIF9V
QVBJX09QQUxfSAorI2RlZmluZSBfVUFQSV9PUEFMX0gKKworI2luY2x1ZGUgPGxpbnV4L3R5cGVz
Lmg+CisKKyNkZWZpbmUgT1BBTF9LRVlfTUFYIDI1NgorCitlbnVtIG9wYWxfbWJyIHsKKwlPUEFM
X01CUl9FTkFCTEUsCisJT1BBTF9NQlJfRElTQUJMRSwKK307CisKK2VudW0gb3BhbF91c2VyIHsK
KwlPUEFMX0FETUlOMSwKKwlPUEFMX1VTRVIxLAorCU9QQUxfVVNFUjIsCisJT1BBTF9VU0VSMywK
KwlPUEFMX1VTRVI0LAorCU9QQUxfVVNFUjUsCisJT1BBTF9VU0VSNiwKKwlPUEFMX1VTRVI3LAor
CU9QQUxfVVNFUjgsCisJT1BBTF9VU0VSOSwKK307CisKK3N0cnVjdCBvcGFsX3VzZXJfaW5mbyB7
CisJYm9vbCBTVU07CisJZW51bSBvcGFsX3VzZXIgd2hvOworfTsKKworZW51bSBvcGFsX2tleV90
eXBlIHsKKwlPUEFMX0tFWV9QTEFJTiwKKwlPUEFMX0tFWV9LRVlSSU5HLAorfTsKKworZW51bSBv
cGFsX2xvY2tfc3RhdGUgeworCU9QQUxfUk8gPSAweDAxLCAvKiAwMDAxICovCisJT1BBTF9SVyA9
IDB4MDIsIC8qIDAwMTAgKi8KKwlPUEFMX0xLID0gMHgwNCwgLyogMDEwMCAqLworfTsKKworc3Ry
dWN0IG9wYWxfa2V5IHsKKwlfX3U4CWxyOworCV9fdTgJa2V5X3R5cGU7CisJX191OAlrZXlfbGVu
OworCV9fdTgJa2V5W09QQUxfS0VZX01BWF07Cit9OworCitzdHJ1Y3Qgb3BhbF9rZXlfYW5kX3Vz
ZXIgeworCXN0cnVjdCBvcGFsX3VzZXJfaW5mbyB3aG87CisJc3RydWN0IG9wYWxfa2V5IGtleTsK
K307CisKK3N0cnVjdCBvcGFsX3VzZXJfbHJfc2V0dXAgeworCXN0cnVjdCBvcGFsX3VzZXJfaW5m
byB3aG87CisJc3RydWN0IG9wYWxfa2V5IGtleTsKKwlzaXplX3QgcmFuZ2Vfc3RhcnQ7CisJc2l6
ZV90IHJhbmdlX2xlbmd0aDsKKwlpbnQgICAgUkxFOyAvKiBSZWFkIExvY2sgZW5hYmxlZCAqLwor
CWludCAgICBXTEU7IC8qIFdyaXRlIExvY2sgRW5hYmxlZCAqLworfTsKKworc3RydWN0IG9wYWxf
bG9ja191bmxvY2sgeworCXN0cnVjdCBvcGFsX3VzZXJfaW5mbyBhdXRob3JpdHk7CisJZW51bSBv
cGFsX2xvY2tfc3RhdGUgbF9zdGF0ZTsKKwlzdHJ1Y3Qgb3BhbF9rZXkga2V5OworfTsKKworc3Ry
dWN0IG9wYWxfbmV3X3B3IHsKKwlzdHJ1Y3Qgb3BhbF91c2VyX2luZm8gd2hvOworCisJLyogV2hl
biB3ZSdyZSBub3Qgb3BlcmF0aW5nIGluIFNVTSwgYW5kIHdlIGZpcnN0IHNldAorCSAqIHBhc3N3
b3JkcyB3ZSBuZWVkIHRvIHNldCB0aGVtIHZpYSBBRE1JTiBhdXRob3JpdHkuCisJICogQWZ0ZXIg
cGFzc3dvcmRzIGFyZSBjaGFuZ2VkLCB3ZSBjYW4gc2V0IHRoZW0gdmlhLAorCSAqIFVzZXIgYXV0
aG9yaXRpZXMuCisJICogQmVjYXVzZSBvZiB0aGlzIHJlc3RyaWN0aW9uIHdlIG5lZWQgdG8ga25v
dyBhYm91dAorCSAqIFR3byBkaWZmZXJlbnQgdXNlcnMuIE9uZSBpbiAnd2hvJyB3aGljaCB3ZSB3
aWxsIHVzZQorCSAqIHRvIHN0YXJ0IHRoZSBzZXNzaW9uIGFuZCB1c2VyX2Zvcl9wdyBhcyB0aGUg
dXNlciB3ZSdyZQorCSAqIGNoYW5pbmcgdGhlIHB3IGZvci4KKwkgKi8KKwllbnVtIG9wYWxfdXNl
ciB1c2VyX2Zvcl9wdzsKKwlzdHJ1Y3Qgb3BhbF9rZXkgY3VycmVudF9waW47CisJc3RydWN0IG9w
YWxfa2V5IG5ld19waW47Cit9OworCitzdHJ1Y3Qgb3BhbF9tYnJfZGF0YSB7CisJdTggZW5hYmxl
X2Rpc2FibGU7CisJc3RydWN0IG9wYWxfa2V5IGtleTsKK307CisKKyNlbmRpZiAvKiBfVUFQSV9T
RURfSCAqLwpkaWZmIC0tZ2l0IGEvaW5jbHVkZS91YXBpL2xpbnV4L3NlZC5oIGIvaW5jbHVkZS91
YXBpL2xpbnV4L3NlZC5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmE5YWFj
ZDEKLS0tIC9kZXYvbnVsbAorKysgYi9pbmNsdWRlL3VhcGkvbGludXgvc2VkLmgKQEAgLTAsMCAr
MSw2NCBAQAorLyoKKyAqIERlZmluaXRpb25zIGZvciB0aGUgc2VsZi1lbmNyeXB0aW5nIGRyaXZl
IGludGVyZmFjZQorICogQ29weXJpZ2h0IMKpIDIwMTYgSW50ZWwgQ29ycG9yYXRpb24KKyAqCisg
KiBBdXRob3JzOgorICogICAgUmFmYWVsIEFudG9nbm9sbGkgPHJhZmFlbC5hbnRvZ25vbGxpQGlu
dGVsLmNvbT4KKyAqICAgIFNjb3R0ICBCYXVlciAgICAgIDxzY290dC5iYXVlckBpbnRlbC5jb20+
CisgKgorICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmli
dXRlIGl0IGFuZC9vciBtb2RpZnkgaXQKKyAqIHVuZGVyIHRoZSB0ZXJtcyBhbmQgY29uZGl0aW9u
cyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UsCisgKiB2ZXJzaW9uIDIsIGFzIHB1
Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgorICoKKyAqIFRoaXMgcHJv
Z3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJ
VEhPVVQKKyAqIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5
IG9mIE1FUkNIQU5UQUJJTElUWSBvcgorICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBP
U0UuICBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvcgorICogbW9yZSBkZXRh
aWxzLgorICovCisKKyNpZm5kZWYgX1VBUElfU0VEX0gKKyNkZWZpbmUgX1VBUElfU0VEX0gKKwor
I2luY2x1ZGUgPGxpbnV4L3R5cGVzLmg+CisjaW5jbHVkZSAic2VkLW9wYWwuaCIKKworZW51bSBz
ZWRfa2V5X3R5cGUgeworCU9QQUwsCisJT1BBTF9QVywKKwlPUEFMX0FDVF9VU1IsCisJT1BBTF9M
Ul9TRVRVUCwKKwlPUEFMX0xPQ0tfVU5MT0NLLAorCU9QQUxfTUJSX0RBVEEsCit9OworCitzdHJ1
Y3Qgc2VkX2tleSB7CisJX191MzIgc2VkX3R5cGU7CisJdW5pb24geworCQlzdHJ1Y3Qgb3BhbF9r
ZXkgICAgICAgICAgICBvcGFsOworCQlzdHJ1Y3Qgb3BhbF9uZXdfcHcgICAgICAgICBvcGFsX3B3
OworCQlzdHJ1Y3Qgb3BhbF9rZXlfYW5kX3VzZXIgICBvcGFsX2FjdDsKKwkJc3RydWN0IG9wYWxf
dXNlcl9scl9zZXR1cCAgb3BhbF9scnM7CisJCXN0cnVjdCBvcGFsX2xvY2tfdW5sb2NrICAgIG9w
YWxfbGtfdW5sazsKKwkJc3RydWN0IG9wYWxfbWJyX2RhdGEgICAgICAgb3BhbF9tYnI7CisJCS8q
IGFkZGl0aW9uYWwgY29tbWFuZCBzZXQga2V5IHR5cGVzICovCisJfTsKK307CisKKyNkZWZpbmUg
SU9DX1NFRF9TQVZFCQkgICBfSU9XKCdwJywgMjIwLCBzdHJ1Y3Qgc2VkX2tleSkKKyNkZWZpbmUg
SU9DX1NFRF9MT0NLX1VOTE9DSwkgICBfSU9XKCdwJywgMjIxLCBzdHJ1Y3Qgc2VkX2tleSkKKyNk
ZWZpbmUgSU9DX1NFRF9UQUtFX09XTkVSU0hJUAkgICBfSU9XKCdwJywgMjIyLCBzdHJ1Y3Qgc2Vk
X2tleSkKKyNkZWZpbmUgSU9DX1NFRF9BQ1RJVkFURV9MU1AgICAgICAgX0lPVygncCcsIDIyMywg
c3RydWN0IHNlZF9rZXkpCisjZGVmaW5lIElPQ19TRURfU0VUX1BXICAgICAgICAgICAgIF9JT1co
J3AnLCAyMjQsIHN0cnVjdCBzZWRfa2V5KQorI2RlZmluZSBJT0NfU0VEX0FDVElWQVRFX1VTUiAg
ICAgICBfSU9XKCdwJywgMjI1LCBzdHJ1Y3Qgc2VkX2tleSkKKyNkZWZpbmUgSU9DX1NFRF9SRVZF
UlRfVFBSICAgICAgICAgX0lPVygncCcsIDIyNiwgc3RydWN0IHNlZF9rZXkpCisjZGVmaW5lIElP
Q19TRURfTFJfU0VUVVAgICAgICAgICAgIF9JT1coJ3AnLCAyMjcsIHN0cnVjdCBzZWRfa2V5KQor
I2RlZmluZSBJT0NfU0VEX0FERF9VU1JfVE9fTFIgICAgICBfSU9XKCdwJywgMjI4LCBzdHJ1Y3Qg
c2VkX2tleSkKKyNkZWZpbmUgSU9DX1NFRF9FTkFCTEVfRElTQUJMRV9NQlIgX0lPVygncCcsIDIy
OSwgc3RydWN0IHNlZF9rZXkpCisjZGVmaW5lIElPQ19TRURfRVJBU0VfTFIgICAgICAgICAgIF9J
T1coJ3AnLCAyMzAsIHN0cnVjdCBzZWRfa2V5KQorI2RlZmluZSBJT0NfU0VEX1NFQ1VSRV9FUkFT
RV9MUiAgICBfSU9XKCdwJywgMjMxLCBzdHJ1Y3Qgc2VkX2tleSkKKworc3RhdGljIGlubGluZSBp
bnQgaXNfc2VkX2lvY3RsKHVuc2lnbmVkIGludCBjbWQpCit7CisJcmV0dXJuIChjbWQgPj0gSU9D
X1NFRF9TQVZFICYmIGNtZCA8PSBJT0NfU0VEX1NFQ1VSRV9FUkFTRV9MUik7Cit9CisjZW5kaWYg
LyogX1VBUElfU0VEX0ggKi8KLS0gCjIuNy40CgoKX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX18KTGludXgtbnZtZSBtYWlsaW5nIGxpc3QKTGludXgtbnZtZUBs
aXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlz
dGluZm8vbGludXgtbnZtZQo=

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 1/4] include: Add definitions for sed
@ 2016-11-29 21:51   ` Scott Bauer
  0 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-29 21:51 UTC (permalink / raw)


This patch adds the definitions and structures for the SED
Opal code.

Signed-off-by: Scott Bauer <scott.bauer at intel.com>
Signed-off-by: Rafael Antognolli <Rafael.Antognolli at intel.com>
---
 include/linux/sed-opal.h      |  57 ++++++++++++++++++++++
 include/linux/sed.h           |  85 +++++++++++++++++++++++++++++++++
 include/uapi/linux/sed-opal.h | 108 ++++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/sed.h      |  64 +++++++++++++++++++++++++
 4 files changed, 314 insertions(+)
 create mode 100644 include/linux/sed-opal.h
 create mode 100644 include/linux/sed.h
 create mode 100644 include/uapi/linux/sed-opal.h
 create mode 100644 include/uapi/linux/sed.h

diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
new file mode 100644
index 0000000..9c6d849
--- /dev/null
+++ b/include/linux/sed-opal.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright ? 2016 Intel Corporation
+ *
+ * Authors:
+ *    Rafael Antognolli <rafael.antognolli at intel.com>
+ *    Scott  Bauer      <scott.bauer at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef LINUX_OPAL_H
+#define LINUX_OPAL_H
+
+#include <linux/sed.h>
+#include <linux/kernel.h>
+
+struct opal_suspend_unlk {
+	void *submit_data;
+	dev_t dev;
+	sed_sec_submit *submit_fn;
+};
+
+int opal_save(struct block_device *bdev, struct sed_key *key,
+	      void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_lock_unlock(struct block_device *bdev, struct sed_key *key,
+		     void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_take_ownership(struct block_device *bdev, struct sed_key *key,
+			void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_activate_lsp(struct block_device *bdev, struct sed_key *key,
+		      void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_set_new_pw(struct block_device *bdev, struct sed_key *key,
+		    void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_activate_user(struct block_device *bdev, struct sed_key *key,
+		       void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_reverttper(struct block_device *bdev, struct sed_key *key,
+		    void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_setup_locking_range(struct block_device *bdev, struct sed_key *key,
+			     void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_add_user_to_lr(struct block_device *bdev, struct sed_key *key,
+			void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_enable_disable_shadow_mbr(struct block_device *bdev, struct sed_key *key,
+				   void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_erase_locking_range(struct block_device *bdev, struct sed_key *key,
+			     void *sbmt_data, sed_sec_submit *submit_fn);
+int opal_secure_erase_locking_range(struct block_device *bdev,
+				    struct sed_key *key, void *sbmt_data,
+				    sed_sec_submit *submit_fn);
+int opal_unlock_from_suspend(struct opal_suspend_unlk *data);
+
+#endif /* LINUX_OPAL_H */
diff --git a/include/linux/sed.h b/include/linux/sed.h
new file mode 100644
index 0000000..7c3b69b
--- /dev/null
+++ b/include/linux/sed.h
@@ -0,0 +1,85 @@
+/*
+ * Self-Encrypting Drive interface - sed.h
+ *
+ * Copyright ? 2016 Intel Corporation
+ *
+ * Authors:
+ *    Rafael Antognolli <rafael.antognolli at intel.com>
+ *    Scott  Bauer      <scott.bauer at intel.com>
+ *    Jonathan Derrick  <jonathan.derrick at intel.com>
+ *
+ * This code is the generic layer to interface with self-encrypting
+ * drives. Specific command sets should advertise support to sed uapi
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef LINUX_SED_H
+#define LINUX_SED_H
+
+#include <linux/blkdev.h>
+#include <uapi/linux/sed.h>
+
+
+/*
+ * These constant values come from:
+ * TCG Storage Architecture Core Spec v2.01 r1
+ * Section: 3.3 Interface Communications
+ */
+enum {
+	TCG_SECP_00 = 0,
+	TCG_SECP_01,
+};
+
+/*
+ * sed_sec_submit - transport specific Trusted Send/Receive functions
+ * See SPC-4 for specific definitions
+ *
+ * @sec_sec_submit: sends or recieves the payload to the trusted peripheral
+ *	SPSP: Security Protocol Specific
+ *	SECP: Security Protocol
+ *	buffer: Payload
+ *	len: Payload length
+ *      bool: Wether to send(true) or to recieve(false)
+ */
+
+typedef int (sed_sec_submit)(void *data, u16 spsp, u8 secp,
+			     void *buffer, size_t len, bool send);
+
+int sed_save(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_lock_unlock(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_take_ownership(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_activate_lsp(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_set_pw(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_activate_user(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_reverttper(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_do_mbr(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_erase_lr(struct block_device *bdev, struct sed_key *key,
+                 void *sbmt_data, sed_sec_submit *submit_fn);
+int sed_secure_erase_lr(struct block_device *bdev, struct sed_key *key,
+			void *sbmt_data, sed_sec_submit *submit_fn);
+int blkdev_sed_ioctl(struct block_device *bdev, fmode_t fmode, unsigned int cmd,
+		     unsigned long arg, void *sbmt_ctrl_data,
+		     sed_sec_submit *submit_fn);
+
+#endif /* LINUX_SED_H */
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
new file mode 100644
index 0000000..34689a9
--- /dev/null
+++ b/include/uapi/linux/sed-opal.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright ? 2016 Intel Corporation
+ *
+ * Authors:
+ *    Rafael Antognolli <rafael.antognolli at intel.com>
+ *    Scott  Bauer      <scott.bauer at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _UAPI_OPAL_H
+#define _UAPI_OPAL_H
+
+#include <linux/types.h>
+
+#define OPAL_KEY_MAX 256
+
+enum opal_mbr {
+	OPAL_MBR_ENABLE,
+	OPAL_MBR_DISABLE,
+};
+
+enum opal_user {
+	OPAL_ADMIN1,
+	OPAL_USER1,
+	OPAL_USER2,
+	OPAL_USER3,
+	OPAL_USER4,
+	OPAL_USER5,
+	OPAL_USER6,
+	OPAL_USER7,
+	OPAL_USER8,
+	OPAL_USER9,
+};
+
+struct opal_user_info {
+	bool SUM;
+	enum opal_user who;
+};
+
+enum opal_key_type {
+	OPAL_KEY_PLAIN,
+	OPAL_KEY_KEYRING,
+};
+
+enum opal_lock_state {
+	OPAL_RO = 0x01, /* 0001 */
+	OPAL_RW = 0x02, /* 0010 */
+	OPAL_LK = 0x04, /* 0100 */
+};
+
+struct opal_key {
+	__u8	lr;
+	__u8	key_type;
+	__u8	key_len;
+	__u8	key[OPAL_KEY_MAX];
+};
+
+struct opal_key_and_user {
+	struct opal_user_info who;
+	struct opal_key key;
+};
+
+struct opal_user_lr_setup {
+	struct opal_user_info who;
+	struct opal_key key;
+	size_t range_start;
+	size_t range_length;
+	int    RLE; /* Read Lock enabled */
+	int    WLE; /* Write Lock Enabled */
+};
+
+struct opal_lock_unlock {
+	struct opal_user_info authority;
+	enum opal_lock_state l_state;
+	struct opal_key key;
+};
+
+struct opal_new_pw {
+	struct opal_user_info who;
+
+	/* When we're not operating in SUM, and we first set
+	 * passwords we need to set them via ADMIN authority.
+	 * After passwords are changed, we can set them via,
+	 * User authorities.
+	 * Because of this restriction we need to know about
+	 * Two different users. One in 'who' which we will use
+	 * to start the session and user_for_pw as the user we're
+	 * chaning the pw for.
+	 */
+	enum opal_user user_for_pw;
+	struct opal_key current_pin;
+	struct opal_key new_pin;
+};
+
+struct opal_mbr_data {
+	u8 enable_disable;
+	struct opal_key key;
+};
+
+#endif /* _UAPI_SED_H */
diff --git a/include/uapi/linux/sed.h b/include/uapi/linux/sed.h
new file mode 100644
index 0000000..a9aacd1
--- /dev/null
+++ b/include/uapi/linux/sed.h
@@ -0,0 +1,64 @@
+/*
+ * Definitions for the self-encrypting drive interface
+ * Copyright ? 2016 Intel Corporation
+ *
+ * Authors:
+ *    Rafael Antognolli <rafael.antognolli at intel.com>
+ *    Scott  Bauer      <scott.bauer at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _UAPI_SED_H
+#define _UAPI_SED_H
+
+#include <linux/types.h>
+#include "sed-opal.h"
+
+enum sed_key_type {
+	OPAL,
+	OPAL_PW,
+	OPAL_ACT_USR,
+	OPAL_LR_SETUP,
+	OPAL_LOCK_UNLOCK,
+	OPAL_MBR_DATA,
+};
+
+struct sed_key {
+	__u32 sed_type;
+	union {
+		struct opal_key            opal;
+		struct opal_new_pw         opal_pw;
+		struct opal_key_and_user   opal_act;
+		struct opal_user_lr_setup  opal_lrs;
+		struct opal_lock_unlock    opal_lk_unlk;
+		struct opal_mbr_data       opal_mbr;
+		/* additional command set key types */
+	};
+};
+
+#define IOC_SED_SAVE		   _IOW('p', 220, struct sed_key)
+#define IOC_SED_LOCK_UNLOCK	   _IOW('p', 221, struct sed_key)
+#define IOC_SED_TAKE_OWNERSHIP	   _IOW('p', 222, struct sed_key)
+#define IOC_SED_ACTIVATE_LSP       _IOW('p', 223, struct sed_key)
+#define IOC_SED_SET_PW             _IOW('p', 224, struct sed_key)
+#define IOC_SED_ACTIVATE_USR       _IOW('p', 225, struct sed_key)
+#define IOC_SED_REVERT_TPR         _IOW('p', 226, struct sed_key)
+#define IOC_SED_LR_SETUP           _IOW('p', 227, struct sed_key)
+#define IOC_SED_ADD_USR_TO_LR      _IOW('p', 228, struct sed_key)
+#define IOC_SED_ENABLE_DISABLE_MBR _IOW('p', 229, struct sed_key)
+#define IOC_SED_ERASE_LR           _IOW('p', 230, struct sed_key)
+#define IOC_SED_SECURE_ERASE_LR    _IOW('p', 231, struct sed_key)
+
+static inline int is_sed_ioctl(unsigned int cmd)
+{
+	return (cmd >= IOC_SED_SAVE && cmd <= IOC_SED_SECURE_ERASE_LR);
+}
+#endif /* _UAPI_SED_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
  2016-11-29 21:51 ` Scott Bauer
@ 2016-11-29 21:52   ` Scott Bauer
  -1 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-29 21:52 UTC (permalink / raw)
  To: linux-nvme
  Cc: keith.busch, sagi, hch, Rafael.Antognolli, axboe, linux-block,
	Scott Bauer, jonathan.derrick, j.naumann

VGhpcyBwYXRjaCBpbXBsZW1lbnRzIHRoZSBuZWNlc3NhcnkgbG9naWMgdG8gYnJpbmcgYW4gT3Bh
bAplbmFibGVkIGRyaXZlIG91dCBvZiBhIGZhY3RvcnktZW5hYmxlZCBpbnRvIGEgd29ya2luZwpP
cGFsIHN0YXRlLgoKVGhpcyBwYXRjaCBzZXQgYWxzbyBlbmFibGVzIGxvZ2ljIHRvIHNhdmUgYSBw
YXNzd29yZCB0bwpiZSByZXBsYXllZCBkdXJpbmcgYSByZXN1bWUgZnJvbSBzdXNwZW5kLiBUaGUg
a2V5IGNhbiBiZQpzYXZlZCBpbiB0aGUgZHJpdmVyIG9yIGluIHRoZSBLZXJuZWwncyBLZXkgbWFu
YWdtZW50LgoKU2lnbmVkLW9mZi1ieTogU2NvdHQgQmF1ZXIgPHNjb3R0LmJhdWVyQGludGVsLmNv
bT4KU2lnbmVkLW9mZi1ieTogUmFmYWVsIEFudG9nbm9sbGkgPFJhZmFlbC5BbnRvZ25vbGxpQGlu
dGVsLmNvbT4KLS0tCiBibG9jay9NYWtlZmlsZSAgICAgICAgICAgIHwgICAgMiArLQogYmxvY2sv
c2VkLW9wYWwuYyAgICAgICAgICB8IDMxNTcgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrCiBibG9jay9zZWQtb3BhbF9pbnRlcm5hbC5oIHwgIDYwMSArKysrKysr
KysKIGJsb2NrL3NlZC5jICAgICAgICAgICAgICAgfCAgMjA3ICsrKwogNCBmaWxlcyBjaGFuZ2Vk
LCAzOTY2IGluc2VydGlvbnMoKyksIDEgZGVsZXRpb24oLSkKIGNyZWF0ZSBtb2RlIDEwMDY0NCBi
bG9jay9zZWQtb3BhbC5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgYmxvY2svc2VkLW9wYWxfaW50ZXJu
YWwuaAogY3JlYXRlIG1vZGUgMTAwNjQ0IGJsb2NrL3NlZC5jCgpkaWZmIC0tZ2l0IGEvYmxvY2sv
TWFrZWZpbGUgYi9ibG9jay9NYWtlZmlsZQppbmRleCAzNmFjZGQ3Li42NjMyZDQyIDEwMDY0NAot
LS0gYS9ibG9jay9NYWtlZmlsZQorKysgYi9ibG9jay9NYWtlZmlsZQpAQCAtOCw3ICs4LDcgQEAg
b2JqLSQoQ09ORklHX0JMT0NLKSA6PSBiaW8ubyBlbGV2YXRvci5vIGJsay1jb3JlLm8gYmxrLXRh
Zy5vIGJsay1zeXNmcy5vIFwKIAkJCWJsay1saWIubyBibGstbXEubyBibGstbXEtdGFnLm8gXAog
CQkJYmxrLW1xLXN5c2ZzLm8gYmxrLW1xLWNwdW1hcC5vIGlvY3RsLm8gXAogCQkJZ2VuaGQubyBz
Y3NpX2lvY3RsLm8gcGFydGl0aW9uLWdlbmVyaWMubyBpb3ByaW8ubyBcCi0JCQliYWRibG9ja3Mu
byBwYXJ0aXRpb25zLworCQkJYmFkYmxvY2tzLm8gc2VkLm8gc2VkLW9wYWwubyBwYXJ0aXRpb25z
LwogCiBvYmotJChDT05GSUdfQk9VTkNFKQkrPSBib3VuY2Uubwogb2JqLSQoQ09ORklHX0JMS19E
RVZfQlNHKQkrPSBic2cubwpkaWZmIC0tZ2l0IGEvYmxvY2svc2VkLW9wYWwuYyBiL2Jsb2NrL3Nl
ZC1vcGFsLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNTM2MDJhYQotLS0g
L2Rldi9udWxsCisrKyBiL2Jsb2NrL3NlZC1vcGFsLmMKQEAgLTAsMCArMSwzMTU3IEBACisvKgor
ICogQ29weXJpZ2h0IMKpIDIwMTYgSW50ZWwgQ29ycG9yYXRpb24KKyAqCisgKiBBdXRob3JzOgor
ICogICAgUmFmYWVsIEFudG9nbm9sbGkgPHJhZmFlbC5hbnRvZ25vbGxpQGludGVsLmNvbT4KKyAq
ICAgIFNjb3R0ICBCYXVlciAgICAgIDxzY290dC5iYXVlckBpbnRlbC5jb20+CisgKgorICogVGhp
cyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9v
ciBtb2RpZnkgaXQKKyAqIHVuZGVyIHRoZSB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB0aGUgR05V
IEdlbmVyYWwgUHVibGljIExpY2Vuc2UsCisgKiB2ZXJzaW9uIDIsIGFzIHB1Ymxpc2hlZCBieSB0
aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgorICoKKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0
cmlidXRlZCBpbiB0aGUgaG9wZSBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVQKKyAqIEFO
WSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5U
QUJJTElUWSBvcgorICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhl
IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvcgorICogbW9yZSBkZXRhaWxzLgorICovCisK
KyNkZWZpbmUgcHJfZm10KGZtdCkgS0JVSUxEX01PRE5BTUUgIjpPUEFMOiAiIGZtdAorCisjaW5j
bHVkZSA8bGludXgvZGVsYXkuaD4KKyNpbmNsdWRlIDxsaW51eC9kZXZpY2UuaD4KKyNpbmNsdWRl
IDxsaW51eC9rZXJuZWwuaD4KKyNpbmNsdWRlIDxsaW51eC9saXN0Lmg+CisjaW5jbHVkZSA8bGlu
dXgvZ2VuaGQuaD4KKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CisjaW5jbHVkZSA8bGludXgvdWFj
Y2Vzcy5oPgorI2luY2x1ZGUgPHVhcGkvbGludXgvc2VkLW9wYWwuaD4KKyNpbmNsdWRlIDxsaW51
eC9zZWQuaD4KKyNpbmNsdWRlIDxsaW51eC9zZWQtb3BhbC5oPgorI2luY2x1ZGUgPGxpbnV4L3N0
cmluZy5oPgorI2luY2x1ZGUgPGxpbnV4L2tkZXZfdC5oPgorI2luY2x1ZGUgPGxpbnV4L2tleS5o
PgorCisjaW5jbHVkZSAic2VkLW9wYWxfaW50ZXJuYWwuaCIKKworI2RlZmluZSBJT19CVUZGRVJf
TEVOR1RIIDIwNDgKKworI2RlZmluZSBNQVhfVE9LUyA2NAorCit0eXBlZGVmIGludCAoY29udF9m
bikodm9pZCAqZGF0YSk7CisKK3N0cnVjdCBvcGFsX2NtZCB7CisJc3RydWN0IGJsb2NrX2Rldmlj
ZSAqYmRldjsKKwljb250X2ZuICpjYjsKKwl2b2lkICpjYl9kYXRhOworCisJc2l6ZV90IHBvczsK
Kwl1OCBjbWRfYnVmW0lPX0JVRkZFUl9MRU5HVEggKiAyXTsKKwl1OCByZXNwX2J1ZltJT19CVUZG
RVJfTEVOR1RIICogMl07CisJdTggKmNtZDsKKwl1OCAqcmVzcDsKK307CisKKy8qCisgKiBPbiB0
aGUgcGFyc2VkIHJlc3BvbnNlLCB3ZSBkb24ndCBzdG9yZSBhZ2FpbiB0aGUgdG9rcyB0aGF0IGFy
ZSBhbHJlYWR5CisgKiBzdG9yZWQgaW4gdGhlIHJlc3BvbnNlIGJ1ZmZlci4gSW5zdGVhZCwgZm9y
IGVhY2ggdG9rZW4sIHdlIGp1c3Qgc3RvcmUgYQorICogcG9pbnRlciB0byB0aGUgcG9zaXRpb24g
aW4gdGhlIGJ1ZmZlciB3aGVyZSB0aGUgdG9rZW4gc3RhcnRzLCBhbmQgdGhlIHNpemUKKyAqIG9m
IHRoZSB0b2tlbiBpbiBieXRlcy4KKyAqLworc3RydWN0IG9wYWxfcmVzcF90b2sgeworCWNvbnN0
IHU4ICpwb3M7CisJc2l6ZV90IGxlbjsKKwllbnVtIE9QQUxfUkVTUE9OU0VfVE9LRU4gdHlwZTsK
KwllbnVtIE9QQUxfQVRPTV9XSURUSCB3aWR0aDsKKwl1bmlvbiB7CisJCXU2NCB1OworCQlzNjQg
czsKKwl9IHN0b3JlZDsKK307CisKKy8qCisgKiBGcm9tIHRoZSByZXNwb25zZSBoZWFkZXIgaXQn
cyBub3QgcG9zc2libGUgdG8ga25vdyBob3cgbWFueSB0b2tlbnMgdGhlcmUgYXJlCisgKiBvbiB0
aGUgcGF5bG9hZC4gU28gd2UgaGFyZGNvZGUgdGhhdCB0aGUgbWF4aW11bSB3aWxsIGJlIE1BWF9U
T0tTLCBhbmQgbGF0ZXIKKyAqIGlmIHdlIHN0YXJ0IGRlYWxpbmcgd2l0aCBtZXNzYWdlcyB0aGF0
IGhhdmUgbW9yZSB0aGFuIHRoYXQsIHdlIGNhbiBpbmNyZWFzZQorICogdGhpcyBudW1iZXIuIFRo
aXMgaXMgZG9uZSB0byBhdm9pZCBoYXZpbmcgdG8gbWFrZSB0d28gcGFzc2VzIHRocm91Z2ggdGhl
CisgKiByZXNwb25zZSwgdGhlIGZpcnN0IG9uZSBjb3VudGluZyBob3cgbWFueSB0b2tlbnMgd2Ug
aGF2ZSBhbmQgdGhlIHNlY29uZCBvbmUKKyAqIGFjdHVhbGx5IHN0b3JpbmcgdGhlIHBvc2l0aW9u
cy4KKyAqLworc3RydWN0IHBhcnNlZF9yZXNwIHsKKwlpbnQgbnVtOworCXN0cnVjdCBvcGFsX3Jl
c3BfdG9rIHRva3NbTUFYX1RPS1NdOworfTsKKworc3RydWN0IG9wYWxfZGV2OworCit0eXBlZGVm
IGludCAoKm9wYWxfc3RlcCkoc3RydWN0IG9wYWxfZGV2ICpkZXYpOworCitzdHJ1Y3Qgb3BhbF9k
ZXYgeworCWRldl90IG1ham1pbjsKKwlzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuOworCXZvaWQg
KnN1Ym1pdF9kYXRhOworCXN0cnVjdCBvcGFsX2xvY2tfdW5sb2NrIGxrdWw7CisJY29uc3Qgb3Bh
bF9zdGVwICpmdW5jczsKKwl2b2lkICoqZnVuY19kYXRhOworCWJvb2wgcmVzdW1lX2Zyb21fc3Vz
cGVuZDsKKwlzdHJ1Y3Qgb3BhbF9zdXNwZW5kX3VubGsgKnJlc3VtZV9kYXRhOworCXNpemVfdCBu
dW1fZnVuY19kYXRhOworCWF0b21pY190IGluX3VzZTsKKwlzZWN0b3JfdCBzdGFydDsKKwlzZWN0
b3JfdCBsZW5ndGg7CisJdTggbHI7CisJdTgga2V5X3R5cGU7CisJdTgga2V5X25hbWVbT1BBTF9L
RVlfTUFYXTsKKwlzaXplX3Qga2V5X25hbWVfbGVuOworCXU4IGtleVtPUEFMX0tFWV9NQVhdOwor
CXNpemVfdCBrZXlfbGVuOworCXUxNiBjb21JRDsKKwl1MzIgSFNOOworCXUzMiBUU047CisJdTY0
IGFsaWduOworCXU2NCBsb3dlc3RfbGJhOworCXN0cnVjdCBsaXN0X2hlYWQgbm9kZTsKKwljaGFy
IGRpc2tfbmFtZVtESVNLX05BTUVfTEVOXTsKKwlpbnQgc3RhdGU7CisKKwlzdHJ1Y3Qgb3BhbF9j
bWQgY21kOworCXN0cnVjdCBwYXJzZWRfcmVzcCBwYXJzZWQ7CisKKwlzaXplX3QgcHJldl9kX2xl
bjsKKwl2b2lkICpwcmV2X2RhdGE7CisKKwlvcGFsX3N0ZXAgZXJyb3JfY2I7CisJdm9pZCAqZXJy
b3JfY2JfZGF0YTsKK307CisKK0xJU1RfSEVBRChvcGFsX2xpc3QpOworREVGSU5FX1NQSU5MT0NL
KGxpc3Rfc3BpbmxvY2spOworCitzdGF0aWMgdm9pZCBwcmludF9idWZmZXIoY29uc3QgdTggKnB0
ciwgdTMyIGxlbmd0aCkKK3sKKyNpZmRlZiBERUJVRworCXByaW50X2hleF9kdW1wX2J5dGVzKCJP
UEFMOiAiLCBEVU1QX1BSRUZJWF9PRkZTRVQsIHB0ciwgbGVuZ3RoKTsKKwlwcl9kZWJ1ZygiXG4i
KTsKKyNlbmRpZgorfQorCisjZGVmaW5lIFRQRVJfU1lOQ19TVVBQT1JURUQgQklUKDApCisKK3N0
YXRpYyBib29sIGNoZWNrX3RwZXIoY29uc3Qgdm9pZCAqZGF0YSkKK3sKKwljb25zdCBzdHJ1Y3Qg
ZDBfdHBlcl9mZWF0dXJlcyAqdHBlciA9IGRhdGE7CisJdTggZmxhZ3MgPSB0cGVyLT5zdXBwb3J0
ZWRfZmVhdHVyZXM7CisKKwlpZiAoIShmbGFncyAmIFRQRVJfU1lOQ19TVVBQT1JURUQpKSB7CisJ
CXByX2VycigiVFBlciBzeW5jIG5vdCBzdXBwb3J0ZWQuIGZsYWdzID0gJWRcbiIsCisJCSAgICAg
ICB0cGVyLT5zdXBwb3J0ZWRfZmVhdHVyZXMpOworCQlyZXR1cm4gZmFsc2U7CisJfQorCisJcmV0
dXJuIHRydWU7Cit9CisKK3N0YXRpYyBib29sIGNoZWNrX1NVTShjb25zdCB2b2lkICpkYXRhKQor
eworCWNvbnN0IHN0cnVjdCBkMF9zaW5nbGVfdXNlcl9tb2RlICpzdW0gPSBkYXRhOworCXUzMiBu
bG8gPSBiZTMyX3RvX2NwdShzdW0tPm51bV9sb2NraW5nX29iamVjdHMpOworCisJaWYgKG5sbyA9
PSAwKSB7CisJCXByX2VycigiTmVlZCBhdCBsZWFzdCBvbmUgbG9ja2luZyBvYmplY3QuXG4iKTsK
KwkJcmV0dXJuIGZhbHNlOworCX0KKworCXByX2RlYnVnKCJOdW1iZXIgb2YgbG9ja2luZyBvYmpl
Y3RzOiAlZFxuIiwgbmxvKTsKKworCXJldHVybiB0cnVlOworfQorCitzdGF0aWMgdTE2IGdldF9j
b21JRF92MTAwKGNvbnN0IHZvaWQgKmRhdGEpCit7CisJY29uc3Qgc3RydWN0IGQwX29wYWxfdjEw
MCAqdjEwMCA9IGRhdGE7CisKKwlyZXR1cm4gYmUxNl90b19jcHUodjEwMC0+YmFzZUNvbUlEKTsK
K30KKworc3RhdGljIHUxNiBnZXRfY29tSURfdjIwMChjb25zdCB2b2lkICpkYXRhKQoreworCWNv
bnN0IHN0cnVjdCBkMF9vcGFsX3YyMDAgKnYyMDAgPSBkYXRhOworCisJcmV0dXJuIGJlMTZfdG9f
Y3B1KHYyMDAtPmJhc2VDb21JRCk7Cit9CisKK3N0YXRpYyBpbnQgb3BhbF9zZW5kX2NtZChzdHJ1
Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlyZXR1cm4gZGV2LT5zdWJtaXRfZm4oZGV2LT5zdWJtaXRf
ZGF0YSwgZGV2LT5jb21JRCwgVENHX1NFQ1BfMDEsCisJCQkgICAgICBkZXYtPmNtZC5jbWQsIElP
X0JVRkZFUl9MRU5HVEgsIHRydWUpOworfQorCitzdGF0aWMgaW50IG9wYWxfcmVjdl9jbWQoc3Ry
dWN0IG9wYWxfZGV2ICpkZXYpCit7CisJcmV0dXJuIGRldi0+c3VibWl0X2ZuKGRldi0+c3VibWl0
X2RhdGEsIGRldi0+Y29tSUQsIFRDR19TRUNQXzAxLAorCQkJICAgICAgZGV2LT5jbWQucmVzcCwg
SU9fQlVGRkVSX0xFTkdUSCwgZmFsc2UpOworfQorCitzdGF0aWMgaW50IG9wYWxfcmVjdl9jaGVj
ayhzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlzaXplX3QgYnVmbGVuID0gSU9fQlVGRkVSX0xF
TkdUSDsKKwl2b2lkICpidWZmZXIgPSBkZXYtPmNtZC5yZXNwOworCXN0cnVjdCBvcGFsX2hlYWRl
ciAqaGRyID0gYnVmZmVyOworCWludCByZXQ7CisKKwlkbyB7CisJCXByX2RlYnVnKCIlczogU2Vu
dCBPUEFMIGNvbW1hbmQ6IG91dHN0YW5kaW5nPSVkLCBtaW5UcmFuc2Zlcj0lZFxuIiwKKwkJCSBk
ZXYtPmRpc2tfbmFtZSwgaGRyLT5jcC5vdXRzdGFuZGluZ0RhdGEsCisJCQkgaGRyLT5jcC5taW5U
cmFuc2Zlcik7CisKKwkJaWYgKGhkci0+Y3Aub3V0c3RhbmRpbmdEYXRhID09IDAgfHwKKwkJICAg
IGhkci0+Y3AubWluVHJhbnNmZXIgIT0gMCkKKwkJCXJldHVybiAwOworCisJCW1lbXNldChidWZm
ZXIsIDAsIGJ1Zmxlbik7CisJCXJldCA9IG9wYWxfcmVjdl9jbWQoZGV2KTsKKwl9IHdoaWxlICgh
cmV0KTsKKworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgb3BhbF9zZW5kX3JlY3Yoc3Ry
dWN0IG9wYWxfZGV2ICpkZXYsIGNvbnRfZm4gKmNvbnQpCit7CisJaW50IHJldDsKKworCXJldCA9
IG9wYWxfc2VuZF9jbWQoZGV2KTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCXJldCA9IG9w
YWxfcmVjdl9jbWQoZGV2KTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCXJldCA9IG9wYWxf
cmVjdl9jaGVjayhkZXYpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwlyZXR1cm4gY29u
dChkZXYpOworfQorCitzdGF0aWMgdm9pZCBjaGVja19nZW9tZXRyeShzdHJ1Y3Qgb3BhbF9kZXYg
KmRldiwgY29uc3Qgdm9pZCAqZGF0YSkKK3sKKwljb25zdCBzdHJ1Y3QgZDBfZ2VvbWV0cnlfZmVh
dHVyZXMgKmdlbyA9IGRhdGE7CisKKwlkZXYtPmFsaWduID0gZ2VvLT5hbGlnbm1lbnRfZ3JhbnVs
YXJpdHk7CisJZGV2LT5sb3dlc3RfbGJhID0gZ2VvLT5sb3dlc3RfYWxpZ25lZF9sYmE7Cit9CisK
K3N0YXRpYyBpbnQgbmV4dChzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlvcGFsX3N0ZXAgZnVu
YzsKKwlpbnQgZXJyb3IgPSAwOworCisJZG8geworCisJCWZ1bmMgPSBkZXYtPmZ1bmNzW2Rldi0+
c3RhdGVdOworCQlpZiAoIWZ1bmMpCisJCQlicmVhazsKKworCQlkZXYtPnN0YXRlKys7CisJCWVy
cm9yID0gZnVuYyhkZXYpOworCisJCWlmIChlcnJvcikgeworCQkJcHJfZXJyKCIlczogRXJyb3Ig
b24gc3RlcCBmdW5jdGlvbjogJWQgd2l0aCBlcnJvciAlZDogJXNcbiIsCisJCQkgICAgICAgZGV2
LT5kaXNrX25hbWUsIGRldi0+c3RhdGUsIGVycm9yLAorCQkJICAgICAgIG9wYWxfZXJyb3JfdG9f
aHVtYW4oZXJyb3IpKTsKKworCQkJLyoKKwkJCSAqIFdlIGNoZWNrIGZvciBzdGF0ZSA+IDIgYmVj
YXVzZSBlcnJvcl9jYiBpcworCQkJICogYW4gZW5kIHNlc3Npb24gY2FsbC4gV2UgbmV2ZXIgc3Rh
cnQgYSBzZXNzaW9uIHVudGlsCisJCQkgKiBhZnRlciBzdGF0ZSAyLiBTbyBJZiB3ZSBmYWlsZWQg
b24gc3RhdGUgMiBvciBsb3dlcgorCQkJICogdGhhdCBtZWFucyB3ZSBmYWlsZWQgdG8gc3RhcnQg
YSBzZXNzaW9uCisJCQkgKiBkdWUgdG8gYSBiYWQgcHcgb3Igc29tZXRoaW5nLiBUaGVyZWZvcmUg
aXMgbm8gcmVhc29uCisJCQkgKiB0byBlbmQgYSBub24gZXhpc3RhbnQgc2Vzc2lvbi4KKwkJCSAq
LworCQkJaWYgKGRldi0+ZXJyb3JfY2IgJiYgZGV2LT5zdGF0ZSA+IDIpCisJCQkJZGV2LT5lcnJv
cl9jYihkZXYtPmVycm9yX2NiX2RhdGEpOworCQl9CisJfSB3aGlsZSAoIWVycm9yKTsKKworCXJl
dHVybiBlcnJvcjsKK30KKworc3RhdGljIGludCBvcGFsX2Rpc2NvdmVyeTBfZW5kKHN0cnVjdCBv
cGFsX2RldiAqZGV2KQoreworCWJvb2wgZm91bmRDb21JRCA9IGZhbHNlLCBzdXBwb3J0ZWQgPSB0
cnVlLCBzaW5nbGVfdXNlciA9IGZhbHNlOworCWNvbnN0IHN0cnVjdCBkMF9oZWFkZXIgKmhkcjsK
Kwljb25zdCB1OCAqZXBvcywgKmNwb3M7CisJdTE2IGNvbUlEID0gMDsKKwlpbnQgZXJyb3IgPSAw
OworCisJZXBvcyA9IGRldi0+Y21kLnJlc3A7CisJY3BvcyA9IGRldi0+Y21kLnJlc3A7CisJaGRy
ID0gKHN0cnVjdCBkMF9oZWFkZXIgKilkZXYtPmNtZC5yZXNwOworCisJcHJpbnRfYnVmZmVyKGRl
di0+Y21kLnJlc3AsIGJlMzJfdG9fY3B1KGhkci0+bGVuZ3RoKSk7CisKKwllcG9zICs9IGJlMzJf
dG9fY3B1KGhkci0+bGVuZ3RoKTsgLyogZW5kIG9mIGJ1ZmZlciAqLworCWNwb3MgKz0gc2l6ZW9m
KCpoZHIpOyAvKiBjdXJyZW50IHBvc2l0aW9uIG9uIGJ1ZmZlciAqLworCisJd2hpbGUgKGNwb3Mg
PCBlcG9zICYmIHN1cHBvcnRlZCkgeworCQljb25zdCBzdHJ1Y3QgZDBfZmVhdHVyZXMgKmJvZHkg
PQorCQkJKGNvbnN0IHN0cnVjdCBkMF9mZWF0dXJlcyAqKWNwb3M7CisKKwkJc3dpdGNoIChiZTE2
X3RvX2NwdShib2R5LT5jb2RlKSkgeworCQljYXNlIEZDX1RQRVI6CisJCQlzdXBwb3J0ZWQgPSBj
aGVja190cGVyKGJvZHktPmZlYXR1cmVzKTsKKwkJCWJyZWFrOworCQljYXNlIEZDX1NJTkdMRVVT
RVI6CisJCQlzaW5nbGVfdXNlciA9IGNoZWNrX1NVTShib2R5LT5mZWF0dXJlcyk7CisJCQlicmVh
azsKKwkJY2FzZSBGQ19HRU9NRVRSWToKKwkJCWNoZWNrX2dlb21ldHJ5KGRldiwgYm9keSk7CisJ
CQlicmVhazsKKwkJY2FzZSBGQ19MT0NLSU5HOgorCQljYXNlIEZDX0VOVEVSUFJJU0U6CisJCWNh
c2UgRkNfREFUQVNUT1JFOgorCQkJLyogc29tZSBpZ25vcmVkIHByb3BlcnRpZXMgKi8KKwkJCXBy
X2RlYnVnKCIlczogRm91bmQgT1BBTCBmZWF0dXJlIGRlc2NyaXB0aW9uOiAlZFxuIiwKKwkJCQkg
ZGV2LT5kaXNrX25hbWUsIGJlMTZfdG9fY3B1KGJvZHktPmNvZGUpKTsKKwkJCWJyZWFrOworCQlj
YXNlIEZDX09QQUxWMTAwOgorCQkJY29tSUQgPSBnZXRfY29tSURfdjEwMChib2R5LT5mZWF0dXJl
cyk7CisJCQlmb3VuZENvbUlEID0gdHJ1ZTsKKwkJCWJyZWFrOworCQljYXNlIEZDX09QQUxWMjAw
OgorCQkJY29tSUQgPSBnZXRfY29tSURfdjIwMChib2R5LT5mZWF0dXJlcyk7CisJCQlmb3VuZENv
bUlEID0gdHJ1ZTsKKwkJCWJyZWFrOworCQljYXNlIDB4YmZmZiAuLi4gMHhmZmZmOgorCQkJLyog
dmVuZG9yIHNwZWNpZmljLCBqdXN0IGlnbm9yZSAqLworCQkJYnJlYWs7CisJCWRlZmF1bHQ6CisJ
CQlwcl93YXJuKCIlczogT1BBTCBVbmtub3duIGZlYXR1cmU6ICVkXG4iLAorCQkJCWRldi0+ZGlz
a19uYW1lLCBiZTE2X3RvX2NwdShib2R5LT5jb2RlKSk7CisKKwkJfQorCQljcG9zICs9IGJvZHkt
Pmxlbmd0aCArIDQ7CisJfQorCisJaWYgKCFzdXBwb3J0ZWQpIHsKKwkJcHJfZXJyKCIlczogRGV2
aWNlIG5vdCBzdXBwb3J0ZWRcbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJZXJyb3IgPSAxOworCQln
b3RvIGVycl9jYWxsYmFjazsKKwl9CisKKwlpZiAoIXNpbmdsZV91c2VyKQorCQlwcl93YXJuKCIl
czogRGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCBzaW5nbGUgdXNlciBtb2RlXG4iLAorCQkJZGV2LT5k
aXNrX25hbWUpOworCisJaWYgKCFmb3VuZENvbUlEKSB7CisJCXByX3dhcm4oIiVzOiBDb3VsZCBu
b3QgZmluZCBPUEFMIGNvbUlEIGZvciBkZXZpY2UuIE9QQUwga2VybmVsIHVubG9ja2luZyB3aWxs
IGJlIGRpc2FibGVkXG4iLAorCQkJZGV2LT5kaXNrX25hbWUpOworCQllcnJvciA9IDE7CisJCWdv
dG8gZXJyX2NhbGxiYWNrOworCX0KKworCWRldi0+Y29tSUQgPSBjb21JRDsKKworZXJyX2NhbGxi
YWNrOgorCXJldHVybiBlcnJvcjsKK30KKworc3RhdGljIGludCBvcGFsX2Rpc2NvdmVyeTAoc3Ry
dWN0IG9wYWxfZGV2ICpkZXYpCit7CisJaW50IHJldDsKKworCW1lbXNldChkZXYtPmNtZC5yZXNw
LCAwLCBJT19CVUZGRVJfTEVOR1RIKTsKKwlkZXYtPmNvbUlEID0gMHgwMDAxOworCXJldCA9IG9w
YWxfcmVjdl9jbWQoZGV2KTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCXJldHVybiBvcGFs
X2Rpc2NvdmVyeTBfZW5kKGRldik7Cit9CisKK3N0YXRpYyB2b2lkIGFkZF90b2tlbl91OChzdHJ1
Y3Qgb3BhbF9jbWQgKmNtZCwgdTggdG9rKQoreworCWNtZC0+Y21kW2NtZC0+cG9zKytdID0gdG9r
OworfQorCitzdGF0aWMgc3NpemVfdCB0ZXN0X2FuZF9hZGRfdG9rZW5fdTgoc3RydWN0IG9wYWxf
Y21kICpjbWQsIHU4IHRvaykKK3sKKwlCVUlMRF9CVUdfT04oSU9fQlVGRkVSX0xFTkdUSCA+PSBT
SVpFX01BWCk7CisKKwlpZiAoY21kLT5wb3MgPj0gSU9fQlVGRkVSX0xFTkdUSCAtIDEpIHsKKwkJ
cHJfZXJyKCJFcnJvciBhZGRpbmcgdTg6IGVuZCBvZiBidWZmZXIuXG4iKTsKKwkJcmV0dXJuIC1F
UkFOR0U7CisJfQorCisJYWRkX3Rva2VuX3U4KGNtZCwgdG9rKTsKKworCXJldHVybiAxOworfQor
CisjZGVmaW5lIFRJTllfQVRPTV9EQVRBX01BU0sgR0VOTUFTSyg1LCAwKQorI2RlZmluZSBUSU5Z
X0FUT01fU0lHTkVEIEJJVCg2KQorCisjZGVmaW5lIFNIT1JUX0FUT01fSUQgQklUKDcpCisjZGVm
aW5lIFNIT1JUX0FUT01fQllURVNUUklORyBCSVQoNSkKKyNkZWZpbmUgU0hPUlRfQVRPTV9TSUdO
RUQgQklUKDQpCisjZGVmaW5lIFNIT1JUX0FUT01fTEVOX01BU0sgR0VOTUFTSygzLCAwKQorCitz
dGF0aWMgdm9pZCBhZGRfc2hvcnRfYXRvbV9oZWFkZXIoc3RydWN0IG9wYWxfY21kICpjbWQsIGJv
b2wgYnl0ZXN0cmluZywKKwkJCQkgIGJvb2wgaGFzX3NpZ24sIGludCBsZW4pCit7CisJdTggYXRv
bTsKKworCWF0b20gPSBTSE9SVF9BVE9NX0lEOworCWF0b20gfD0gYnl0ZXN0cmluZyA/IFNIT1JU
X0FUT01fQllURVNUUklORyA6IDA7CisJYXRvbSB8PSBoYXNfc2lnbiA/IFNIT1JUX0FUT01fU0lH
TkVEIDogMDsKKwlhdG9tIHw9IGxlbiAmIFNIT1JUX0FUT01fTEVOX01BU0s7CisKKwlhZGRfdG9r
ZW5fdTgoY21kLCBhdG9tKTsKK30KKworI2RlZmluZSBNRURJVU1fQVRPTV9JRCAoQklUKDcpIHwg
QklUKDYpKQorI2RlZmluZSBNRURJVU1fQVRPTV9CWVRFU1RSSU5HIEJJVCg0KQorI2RlZmluZSBN
RURJVU1fQVRPTV9TSUdORUQgQklUKDMpCisjZGVmaW5lIE1FRElVTV9BVE9NX0xFTl9NQVNLIEdF
Tk1BU0soMiwgMCkKKworc3RhdGljIHZvaWQgYWRkX21lZGl1bV9hdG9tX2hlYWRlcihzdHJ1Y3Qg
b3BhbF9jbWQgKmNtZCwgYm9vbCBieXRlc3RyaW5nLAorCQkJCSAgIGJvb2wgaGFzX3NpZ24sIGlu
dCBsZW4pCit7CisJdTggaGVhZGVyMDsKKworCWhlYWRlcjAgPSBNRURJVU1fQVRPTV9JRDsKKwlo
ZWFkZXIwIHw9IGJ5dGVzdHJpbmcgPyBNRURJVU1fQVRPTV9CWVRFU1RSSU5HIDogMDsKKwloZWFk
ZXIwIHw9IGhhc19zaWduID8gTUVESVVNX0FUT01fU0lHTkVEIDogMDsKKwloZWFkZXIwIHw9IChs
ZW4gPj4gOCkgJiBNRURJVU1fQVRPTV9MRU5fTUFTSzsKKwljbWQtPmNtZFtjbWQtPnBvcysrXSA9
IGhlYWRlcjA7CisJY21kLT5jbWRbY21kLT5wb3MrK10gPSBsZW47Cit9CisKK3N0YXRpYyB2b2lk
IGFkZF90b2tlbl91NjQoc3RydWN0IG9wYWxfY21kICpjbWQsIHU2NCBudW1iZXIsIHNpemVfdCBs
ZW4pCit7CisJYWRkX3Nob3J0X2F0b21faGVhZGVyKGNtZCwgZmFsc2UsIGZhbHNlLCBsZW4pOwor
CisJd2hpbGUgKGxlbi0tKSB7CisJCXU4IG4gPSBudW1iZXIgPj4gKGxlbiAqIDgpOworCisJCWFk
ZF90b2tlbl91OChjbWQsIG4pOworCX0KK30KKworc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRk
X3Rva2VuX3U2NChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTY0IG51bWJlcikKK3sKKwlpbnQgbGVu
OworCWludCBtc2I7CisKKwlpZiAoIShudW1iZXIgJiB+VElOWV9BVE9NX0RBVEFfTUFTSykpCisJ
CXJldHVybiB0ZXN0X2FuZF9hZGRfdG9rZW5fdTgoY21kLCBudW1iZXIpOworCisJbXNiID0gZmxz
KG51bWJlcik7CisJbGVuID0gRElWX1JPVU5EX1VQKG1zYiwgNCk7CisKKwlpZiAoY21kLT5wb3Mg
Pj0gSU9fQlVGRkVSX0xFTkdUSCAtIGxlbiAtIDEpIHsKKwkJcHJfZXJyKCJFcnJvciBhZGRpbmcg
dTY0OiBlbmQgb2YgYnVmZmVyLlxuIik7CisJCXJldHVybiAtRVJBTkdFOworCX0KKworCWFkZF90
b2tlbl91NjQoY21kLCBudW1iZXIsIGxlbik7CisKKwkvKiByZXR1cm4gbGVuZ3RoIG9mIHRva2Vu
IHBsdXMgYXRvbSAqLworCXJldHVybiBsZW4gKyAxOworfQorCitzdGF0aWMgdm9pZCBhZGRfdG9r
ZW5fYnl0ZXN0cmluZyhzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwKKwkJCQkgY29uc3QgdTggKmJ5dGVz
dHJpbmcsIHNpemVfdCBsZW4pCit7CisJbWVtY3B5KCZjbWQtPmNtZFtjbWQtPnBvc10sIGJ5dGVz
dHJpbmcsIGxlbik7CisJY21kLT5wb3MgKz0gbGVuOworfQorCitzdGF0aWMgc3NpemVfdCB0ZXN0
X2FuZF9hZGRfdG9rZW5fYnl0ZXN0cmluZyhzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwKKwkJCQkJICAg
ICBjb25zdCB1OCAqYnl0ZXN0cmluZywgc2l6ZV90IGxlbikKK3sKKwlzaXplX3QgaGVhZGVyX2xl
biA9IDE7CisJYm9vbCBpc19zaG9ydF9hdG9tID0gdHJ1ZTsKKworCWlmIChsZW4gJiB+U0hPUlRf
QVRPTV9MRU5fTUFTSykgeworCQloZWFkZXJfbGVuID0gMjsKKwkJaXNfc2hvcnRfYXRvbSA9IGZh
bHNlOworCX0KKworCWlmIChjbWQtPnBvcyA+PSBJT19CVUZGRVJfTEVOR1RIIC0gbGVuIC0gaGVh
ZGVyX2xlbikgeworCQlwcl9lcnIoIkVycm9yIGFkZGluZyBieXRlc3RyaW5nOiBlbmQgb2YgYnVm
ZmVyLlxuIik7CisJCXJldHVybiAtRVJBTkdFOworCX0KKworCWlmIChpc19zaG9ydF9hdG9tKQor
CQlhZGRfc2hvcnRfYXRvbV9oZWFkZXIoY21kLCB0cnVlLCBmYWxzZSwgbGVuKTsKKwllbHNlCisJ
CWFkZF9tZWRpdW1fYXRvbV9oZWFkZXIoY21kLCB0cnVlLCBmYWxzZSwgbGVuKTsKKworCWFkZF90
b2tlbl9ieXRlc3RyaW5nKGNtZCwgYnl0ZXN0cmluZywgbGVuKTsKKworCXJldHVybiBoZWFkZXJf
bGVuICsgbGVuOworfQorCisjZGVmaW5lIExPQ0tJTkdfUkFOR0VfTk9OX0dMT0JBTCAweDAzCisK
K3N0YXRpYyBpbnQgYnVpbGRfbG9ja2luZ19yYW5nZSh1OCAqYnVmZmVyLCBzaXplX3QgbGVuZ3Ro
LCB1OCBscikKK3sKKwlpZiAobGVuZ3RoIDwgT1BBTF9VSURfTEVOR1RIKQorCQlyZXR1cm4gLUVS
QU5HRTsKKworCW1lbWNweShidWZmZXIsIE9QQUxVSURbT1BBTF9MT0NLSU5HUkFOR0VfR0xPQkFM
XSwgT1BBTF9VSURfTEVOR1RIKTsKKworCWlmIChsciA9PSAwKQorCQlyZXR1cm4gMDsKKwlidWZm
ZXJbNV0gPSBMT0NLSU5HX1JBTkdFX05PTl9HTE9CQUw7CisJYnVmZmVyWzddID0gbHI7CisKKwly
ZXR1cm4gMDsKK30KKworc3RhdGljIGludCBidWlsZF9sb2NraW5nX3VzZXIodTggKmJ1ZmZlciwg
c2l6ZV90IGxlbmd0aCwgdTggbHIpCit7CisJaWYgKGxlbmd0aCA8IE9QQUxfVUlEX0xFTkdUSCkK
KwkJcmV0dXJuIC1FUkFOR0U7CisKKwltZW1jcHkoYnVmZmVyLCBPUEFMVUlEW09QQUxfVVNFUjFf
VUlEXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCWJ1ZmZlcls3XSA9IGxyICsgMTsKKworCXJldHVy
biAwOworfQorCisvKgorICogTiA9IG51bWJlciBvZiBmb3JtYXQgc3BlY2lmaWVycyAoMS05OTkp
IHRvIGJlIHJlcGxpY2F0ZWQKKyAqIGMgPSB1OAorICogdSA9IHU2NAorICogcyA9IGJ5dGVzdHJp
bmcsIGxlbmd0aAorICoKKyAqIHJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjIiwK
KyAqCQkJICAgICAgIHU4X3ZhbDEpOworICoKKyAqIHJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92
YShjbWQsICIyYzJ1IiwKKyAqCQkJICAgICAgIHU4X3ZhbDEsIHU4X3ZhbDIsIHU2NF92YWwxLCB1
NjRfdmFsMik7CisgKgorICogcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgIjNzIiwK
KyAqCQkJICAgICAgIGJ5dGVzdHJpbmcxLCBsZW5ndGgxLAorICoJCQkgICAgICAgYnl0ZXN0cmlu
ZzIsIGxlbmd0aDIsCisgKgkJCSAgICAgICBieXRlc3RyaW5nMywgbGVuZ3RoMyk7CisgKi8KK3N0
YXRpYyBpbnQgdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKHN0cnVjdCBvcGFsX2NtZCAqY21kLAorCQkJ
CSBjb25zdCBjaGFyICpmbXQsIC4uLikKK3sKKwljb25zdCB1OCAqaXQgPSBmbXQsICp0bXA7CisJ
aW50IHJldCwgbnVtID0gMSwgc3VtID0gMDsKKwl2YV9saXN0IGFwOworCisJdmFfc3RhcnQoYXAs
IGZtdCk7CisKKwl3aGlsZSAoKml0ICE9ICdcMCcpIHsKKwkJdTY0IHRvazY0ID0gMDsKKwkJdTgg
dG9rLCAqYnN0cjsKKwkJc2l6ZV90IGxlbjsKKworCQlyZXQgPSAwOworCisJCXN3aXRjaCAoKml0
KSB7CisJCWNhc2UgJzEnIC4uLiAnOSc6CisJCQl0bXAgPSBpdDsKKwkJCW51bSA9IDA7CisJCQl3
aGlsZSAoKnRtcCA+PSAnMCcgJiYgKnRtcCA8PSAnOScpCisJCQkJbnVtID0gbnVtICogMTAgKyAo
KnRtcCsrIC0gJzAnKTsKKwkJCWl0ID0gdG1wOworCQkJY29udGludWU7CisJCWNhc2UgJ2MnOgor
CQkJd2hpbGUgKG51bS0tKSB7CisJCQkJdG9rID0gdmFfYXJnKGFwLCB1bnNpZ25lZCBpbnQpOwor
CQkJCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl91OChjbWQsIHRvayk7CisJCQkJaWYgKHJldCA8
IDApCisJCQkJCWdvdG8gZXJyOworCQkJfQorCQkJbnVtID0gMTsKKwkJCWJyZWFrOworCQljYXNl
ICd1JzoKKwkJCXdoaWxlIChudW0tLSkgeworCQkJCXRvazY0ID0gdmFfYXJnKGFwLCB1NjQpOwor
CQkJCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl91NjQoY21kLCB0b2s2NCk7CisJCQkJaWYgKHJl
dCA8IDApCisJCQkJCWdvdG8gZXJyOworCQkJfQorCQkJbnVtID0gMTsKKwkJCWJyZWFrOworCQlj
YXNlICdzJzoKKwkJCXdoaWxlIChudW0tLSkgeworCQkJCWJzdHIgPSB2YV9hcmcoYXAsIHU4ICop
OworCQkJCWxlbiA9IHZhX2FyZyhhcCwgc2l6ZV90KTsKKwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRf
dG9rZW5fYnl0ZXN0cmluZyhjbWQsIGJzdHIsCisJCQkJCQkJCSAgICBsZW4pOworCQkJCWlmIChy
ZXQgPCAwKQorCQkJCQlnb3RvIGVycjsKKwkJCX0KKwkJCW51bSA9IDE7CisJCQlicmVhazsKKwkJ
Y2FzZSAnICc6CisJCWNhc2UgJ1x0JzoKKwkJCS8qIGlnbm9yZWQgKi8KKwkJCWJyZWFrOworCQlk
ZWZhdWx0OgorCQkJcHJfd2FybigiVW5yZWNvZ25pemVkIHR5cGUuXG4iKTsKKwkJfQorCisJCWl0
Kys7CisJCXN1bSArPSByZXQ7CisJfQorCisJdmFfZW5kKGFwKTsKKworCXJldHVybiBzdW07CisK
KyBlcnI6CisJcHJfZXJyKCJUb2tlbiBmYWlsZWQgdG8gYmUgYWRkZWQuXG4iKTsKKwlyZXR1cm4g
cmV0OworfQorCitzdGF0aWMgdm9pZCBzZXRfY29tSUQoc3RydWN0IG9wYWxfY21kICpjbWQsIHUx
NiBjb21JRCkKK3sKKwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9IChzdHJ1Y3Qgb3BhbF9oZWFk
ZXIgKiljbWQtPmNtZDsKKworCWhkci0+Y3AuZXh0ZW5kZWRDb21JRFswXSA9IGNvbUlEID4+IDg7
CisJaGRyLT5jcC5leHRlbmRlZENvbUlEWzFdID0gY29tSUQ7CisJaGRyLT5jcC5leHRlbmRlZENv
bUlEWzJdID0gMDsKKwloZHItPmNwLmV4dGVuZGVkQ29tSURbM10gPSAwOworfQorCitzdGF0aWMg
aW50IGNtZF9maW5hbGl6ZShzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTMyIGhzbiwgdTMyIHRzbikK
K3sKKwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkcjsKKwlpbnQgcmV0OworCisJcmV0ID0gdGVzdF9h
bmRfYWRkX3Rva2VuX3ZhKGNtZCwgIjZjIiwKKwkJCQkgICAgT1BBTF9FTkRPRkRBVEEsIE9QQUxf
U1RBUlRMSVNULAorCQkJCSAgICAwLCAwLCAwLCBPUEFMX0VORExJU1QpOworCisJaWYgKHJldCA8
IDApIHsKKwkJcHJfZXJyKCJFcnJvciBmaW5hbGl6aW5nIGNvbW1hbmQuXG4iKTsKKwkJcmV0dXJu
IC1FRkFVTFQ7CisJfQorCisJaGRyID0gKHN0cnVjdCBvcGFsX2hlYWRlciAqKSBjbWQtPmNtZDsK
KworCWhkci0+cGt0LlRTTiA9IGNwdV90b19iZTMyKHRzbik7CisJaGRyLT5wa3QuSFNOID0gY3B1
X3RvX2JlMzIoaHNuKTsKKworCWhkci0+c3VicGt0Lmxlbmd0aCA9IGNwdV90b19iZTMyKGNtZC0+
cG9zIC0gc2l6ZW9mKCpoZHIpKTsKKwl3aGlsZSAoY21kLT5wb3MgJSA0KSB7CisJCWlmIChjbWQt
PnBvcyA+PSBJT19CVUZGRVJfTEVOR1RIKSB7CisJCQlwcl9lcnIoIkVycm9yOiBCdWZmZXIgb3Zl
cnJ1blxuIik7CisJCQlyZXR1cm4gLUVSQU5HRTsKKwkJfQorCQljbWQtPmNtZFtjbWQtPnBvcysr
XSA9IDA7CisJfQorCWhkci0+cGt0Lmxlbmd0aCA9IGNwdV90b19iZTMyKGNtZC0+cG9zIC0gc2l6
ZW9mKGhkci0+Y3ApIC0KKwkJCQkgICAgICBzaXplb2YoaGRyLT5wa3QpKTsKKwloZHItPmNwLmxl
bmd0aCA9IGNwdV90b19iZTMyKGNtZC0+cG9zIC0gc2l6ZW9mKGhkci0+Y3ApKTsKKworCXJldHVy
biAwOworfQorCitzdGF0aWMgZW51bSBPUEFMX1JFU1BPTlNFX1RPS0VOIHRva2VuX3R5cGUoY29u
c3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLAorCQkJCQkgICBpbnQgbikKK3sKKwljb25zdCBz
dHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rOworCisJaWYgKG4gPj0gcmVzcC0+bnVtKSB7CisJCXBy
X2VycigiVG9rZW4gbnVtYmVyIGRvZXNuJ3QgZXhpc3Q6ICVkLCByZXNwOiAlZFxuIiwKKwkJICAg
ICAgIG4sIHJlc3AtPm51bSk7CisJCXJldHVybiBPUEFMX0RUQV9UT0tFTklEX0lOVkFMSUQ7CisJ
fQorCisJdG9rID0gJnJlc3AtPnRva3Nbbl07CisJaWYgKHRvay0+bGVuID09IDApIHsKKwkJcHJf
ZXJyKCJUb2tlbiBsZW5ndGggbXVzdCBiZSBub24temVyb1xuIik7CisJCXJldHVybiBPUEFMX0RU
QV9UT0tFTklEX0lOVkFMSUQ7CisJfQorCisJcmV0dXJuIHRvay0+dHlwZTsKK30KKworLyoKKyAq
IFRoaXMgZnVuY3Rpb24gcmV0dXJucyAwIGluIGNhc2Ugb2YgaW52YWxpZCB0b2tlbi4gT25lIHNo
b3VsZCBjYWxsCisgKiB0b2tlbl90eXBlKCkgZmlyc3QgdG8gZmluZCBvdXQgaWYgdGhlIHRva2Vu
IGlzIHZhbGlkIG9yIG5vdC4KKyAqLworc3RhdGljIGVudW0gT1BBTF9UT0tFTiByZXNwb25zZV9n
ZXRfdG9rZW4oY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLAorCQkJCQkgIGludCBuKQor
eworCWNvbnN0IHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2s7CisKKwlpZiAobiA+PSByZXNwLT5u
dW0pIHsKKwkJcHJfZXJyKCJUb2tlbiBudW1iZXIgZG9lc24ndCBleGlzdDogJWQsIHJlc3A6ICVk
XG4iLAorCQkgICAgICAgbiwgcmVzcC0+bnVtKTsKKwkJcmV0dXJuIDA7CisJfQorCisJdG9rID0g
JnJlc3AtPnRva3Nbbl07CisJaWYgKHRvay0+bGVuID09IDApIHsKKwkJcHJfZXJyKCJUb2tlbiBs
ZW5ndGggbXVzdCBiZSBub24temVyb1xuIik7CisJCXJldHVybiAwOworCX0KKworCXJldHVybiB0
b2stPnBvc1swXTsKK30KKworc3RhdGljIHNpemVfdCByZXNwb25zZV9wYXJzZV90aW55KHN0cnVj
dCBvcGFsX3Jlc3BfdG9rICp0b2ssCisJCQkJICBjb25zdCB1OCAqcG9zKQoreworCXRvay0+cG9z
ID0gcG9zOworCXRvay0+bGVuID0gMTsKKwl0b2stPndpZHRoID0gT1BBTF9XSURUSF9USU5ZOwor
CisJaWYgKHBvc1swXSAmIFRJTllfQVRPTV9TSUdORUQpIHsKKwkJdG9rLT50eXBlID0gT1BBTF9E
VEFfVE9LRU5JRF9TSU5UOworCX0gZWxzZSB7CisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VO
SURfVUlOVDsKKwkJdG9rLT5zdG9yZWQudSA9IHBvc1swXSAmIDB4M2Y7CisJfQorCisJcmV0dXJu
IHRvay0+bGVuOworfQorCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX3BhcnNlX3Nob3J0KHN0cnVj
dCBvcGFsX3Jlc3BfdG9rICp0b2ssCisJCQkJICAgY29uc3QgdTggKnBvcykKK3sKKwl0b2stPnBv
cyA9IHBvczsKKwl0b2stPmxlbiA9IChwb3NbMF0gJiBTSE9SVF9BVE9NX0xFTl9NQVNLKSArIDE7
CisJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhfU0hPUlQ7CisKKwlpZiAocG9zWzBdICYgU0hPUlRf
QVRPTV9CWVRFU1RSSU5HKSB7CisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfQllURVNU
UklORzsKKwl9IGVsc2UgaWYgKHBvc1swXSAmIFNIT1JUX0FUT01fU0lHTkVEKSB7CisJCXRvay0+
dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfU0lOVDsKKwl9IGVsc2UgeworCQl1NjQgdV9pbnRlZ2Vy
ID0gMDsKKwkJaW50IGksIGIgPSAwOworCisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURf
VUlOVDsKKwkJaWYgKHRvay0+bGVuID4gOSkgeworCQkJcHJfd2FybigidWludDY0IHdpdGggbW9y
ZSB0aGFuIDggYnl0ZXNcbiIpOworCQkJcmV0dXJuIC1FSU5WQUw7CisJCX0KKwkJZm9yIChpID0g
dG9rLT5sZW4gLSAxOyBpID4gMDsgaS0tKSB7CisJCQl1X2ludGVnZXIgfD0gKCh1NjQpcG9zW2ld
IDw8ICg4ICogYikpOworCQkJYisrOworCQl9CisJCXRvay0+c3RvcmVkLnUgPSB1X2ludGVnZXI7
CisJfQorCisJcmV0dXJuIHRvay0+bGVuOworfQorCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX3Bh
cnNlX21lZGl1bShzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rLAorCQkJCSAgICBjb25zdCB1OCAq
cG9zKQoreworCXRvay0+cG9zID0gcG9zOworCXRvay0+bGVuID0gKCgocG9zWzBdICYgTUVESVVN
X0FUT01fTEVOX01BU0spIDw8IDgpIHwgcG9zWzFdKSArIDI7CisJdG9rLT53aWR0aCA9IE9QQUxf
V0lEVEhfTUVESVVNOworCisJaWYgKHBvc1swXSAmIE1FRElVTV9BVE9NX0JZVEVTVFJJTkcpCisJ
CXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfQllURVNUUklORzsKKwllbHNlIGlmIChwb3Nb
MF0gJiBNRURJVU1fQVRPTV9TSUdORUQpCisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURf
U0lOVDsKKwllbHNlCisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKKworCXJl
dHVybiB0b2stPmxlbjsKK30KKworI2RlZmluZSBMT05HX0FUT01fSUQgKEJJVCg3KSB8IEJJVCg2
KSB8IEJJVCg1KSkKKyNkZWZpbmUgTE9OR19BVE9NX0JZVEVTVFJJTkcgQklUKDEpCisjZGVmaW5l
IExPTkdfQVRPTV9TSUdORUQgQklUKDApCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX3BhcnNlX2xv
bmcoc3RydWN0IG9wYWxfcmVzcF90b2sgKnRvaywKKwkJCQkgIGNvbnN0IHU4ICpwb3MpCit7CisJ
dG9rLT5wb3MgPSBwb3M7CisJdG9rLT5sZW4gPSAoKHBvc1sxXSA8PCAxNikgfCAocG9zWzJdIDw8
IDgpIHwgcG9zWzNdKSArIDQ7CisJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhfTE9ORzsKKworCWlm
IChwb3NbMF0gJiBMT05HX0FUT01fQllURVNUUklORykKKwkJdG9rLT50eXBlID0gT1BBTF9EVEFf
VE9LRU5JRF9CWVRFU1RSSU5HOworCWVsc2UgaWYgKHBvc1swXSAmIExPTkdfQVRPTV9TSUdORUQp
CisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfU0lOVDsKKwllbHNlCisJCXRvay0+dHlw
ZSA9IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKKworCXJldHVybiB0b2stPmxlbjsKK30KKworc3Rh
dGljIHNpemVfdCByZXNwb25zZV9wYXJzZV90b2tlbihzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9r
LAorCQkJCSAgIGNvbnN0IHU4ICpwb3MpCit7CisJdG9rLT5wb3MgPSBwb3M7CisJdG9rLT5sZW4g
PSAxOworCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfVE9LRU47CisJdG9rLT53aWR0aCA9
IE9QQUxfV0lEVEhfVE9LRU47CisKKwlyZXR1cm4gdG9rLT5sZW47Cit9CisKK3N0YXRpYyBpbnQg
cmVzcG9uc2VfcGFyc2UoY29uc3QgdTggKmJ1Ziwgc2l6ZV90IGxlbmd0aCwKKwkJCSAgc3RydWN0
IHBhcnNlZF9yZXNwICpyZXNwKQoreworCWNvbnN0IHN0cnVjdCBvcGFsX2hlYWRlciAqaGRyOwor
CXN0cnVjdCBvcGFsX3Jlc3BfdG9rICppdGVyOworCWludCByZXQsIG51bV9lbnRyaWVzID0gMDsK
Kwl1MzIgY3BvcyA9IDAsIHRvdGFsOworCXNpemVfdCB0b2tlbl9sZW5ndGg7CisJY29uc3QgdTgg
KnBvczsKKworCWlmICghYnVmKQorCQlyZXR1cm4gLUVGQVVMVDsKKworCWlmICghcmVzcCkKKwkJ
cmV0dXJuIC1FRkFVTFQ7CisKKwloZHIgPSAoc3RydWN0IG9wYWxfaGVhZGVyICopYnVmOworCXBv
cyA9IGJ1ZjsKKwlwb3MgKz0gc2l6ZW9mKCpoZHIpOworCisJcHJfZGVidWcoIlJlc3BvbnNlIHNp
emU6IGNwOiAlZCwgcGt0OiAlZCwgc3VicGt0OiAlZFxuIiwKKwkJIGJlMzJfdG9fY3B1KGhkci0+
Y3AubGVuZ3RoKSwKKwkJIGJlMzJfdG9fY3B1KGhkci0+cGt0Lmxlbmd0aCksCisJCSBiZTMyX3Rv
X2NwdShoZHItPnN1YnBrdC5sZW5ndGgpKTsKKworCWlmICgoaGRyLT5jcC5sZW5ndGggPT0gMCkK
KwkgICAgfHwgKGhkci0+cGt0Lmxlbmd0aCA9PSAwKQorCSAgICB8fCAoaGRyLT5zdWJwa3QubGVu
Z3RoID09IDApKSB7CisJCXByX2VycigiQmFkIGhlYWRlciBsZW5ndGguIGNwOiAlZCwgcGt0OiAl
ZCwgc3VicGt0OiAlZFxuIiwKKwkJICAgICAgIGJlMzJfdG9fY3B1KGhkci0+Y3AubGVuZ3RoKSwK
KwkJICAgICAgIGJlMzJfdG9fY3B1KGhkci0+cGt0Lmxlbmd0aCksCisJCSAgICAgICBiZTMyX3Rv
X2NwdShoZHItPnN1YnBrdC5sZW5ndGgpKTsKKwkJcHJpbnRfYnVmZmVyKHBvcywgc2l6ZW9mKCpo
ZHIpKTsKKwkJcmV0ID0gLUVJTlZBTDsKKwkJZ290byBlcnI7CisJfQorCisJaWYgKHBvcyA+IGJ1
ZiArIGxlbmd0aCkgeworCQlyZXQgPSAtRUZBVUxUOworCQlnb3RvIGVycjsKKwl9CisKKwlpdGVy
ID0gcmVzcC0+dG9rczsKKwl0b3RhbCA9IGJlMzJfdG9fY3B1KGhkci0+c3VicGt0Lmxlbmd0aCk7
CisJcHJpbnRfYnVmZmVyKHBvcywgdG90YWwpOworCXdoaWxlIChjcG9zIDwgdG90YWwpIHsKKwkJ
aWYgKCEocG9zWzBdICYgMHg4MCkpIC8qIHRpbnkgYXRvbSAqLworCQkJdG9rZW5fbGVuZ3RoID0g
cmVzcG9uc2VfcGFyc2VfdGlueShpdGVyLCBwb3MpOworCQllbHNlIGlmICghKHBvc1swXSAmIDB4
NDApKSAvKiBzaG9ydCBhdG9tICovCisJCQl0b2tlbl9sZW5ndGggPSByZXNwb25zZV9wYXJzZV9z
aG9ydChpdGVyLCBwb3MpOworCQllbHNlIGlmICghKHBvc1swXSAmIDB4MjApKSAvKiBtZWRpdW0g
YXRvbSAqLworCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfbWVkaXVtKGl0ZXIsIHBv
cyk7CisJCWVsc2UgaWYgKCEocG9zWzBdICYgMHgxMCkpIC8qIGxvbmcgYXRvbSAqLworCQkJdG9r
ZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfbG9uZyhpdGVyLCBwb3MpOworCQllbHNlIC8qIFRP
S0VOICovCisJCQl0b2tlbl9sZW5ndGggPSByZXNwb25zZV9wYXJzZV90b2tlbihpdGVyLCBwb3Mp
OworCisJCWlmICh0b2tlbl9sZW5ndGggPT0gLUVJTlZBTCkgeworCQkJcmV0ID0gLUVJTlZBTDsK
KwkJCWdvdG8gZXJyOworCQl9CisKKwkJcG9zICs9IHRva2VuX2xlbmd0aDsKKwkJY3BvcyArPSB0
b2tlbl9sZW5ndGg7CisJCWl0ZXIrKzsKKwkJbnVtX2VudHJpZXMrKzsKKwl9CisKKwlpZiAobnVt
X2VudHJpZXMgPT0gMCkgeworCQlwcl9lcnIoIkNvdWxkbid0IHBhcnNlIHJlc3BvbnNlLlxuIik7
CisJCXJldCA9IC1FSU5WQUw7CisJCWdvdG8gZXJyOworCX0KKwlyZXNwLT5udW0gPSBudW1fZW50
cmllczsKKworCXJldHVybiAwOworZXJyOgorCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBzaXpl
X3QgcmVzcG9uc2VfZ2V0X3N0cmluZyhjb25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJlc3AsIGlu
dCBuLAorCQkJCSAgY29uc3QgY2hhciAqKnN0b3JlKQoreworCSpzdG9yZSA9IE5VTEw7CisJaWYg
KCFyZXNwKSB7CisJCXByX2VycigiUmVzcG9uc2UgaXMgTlVMTFxuIik7CisJCXJldHVybiAwOwor
CX0KKworCWlmIChuID4gcmVzcC0+bnVtKSB7CisJCXByX2VycigiUmVzcG9uc2UgaGFzICVkIHRv
a2Vucy4gQ2FuJ3QgYWNjZXNzICVkXG4iLAorCQkgICAgICAgcmVzcC0+bnVtLCBuKTsKKwkJcmV0
dXJuIDA7CisJfQorCisJaWYgKHJlc3AtPnRva3Nbbl0udHlwZSAhPSBPUEFMX0RUQV9UT0tFTklE
X0JZVEVTVFJJTkcpIHsKKwkJcHJfZXJyKCJUb2tlbiBpcyBub3QgYSBieXRlIHN0cmluZyFcbiIp
OworCQlyZXR1cm4gMDsKKwl9CisKKwkqc3RvcmUgPSByZXNwLT50b2tzW25dLnBvcyArIDE7CisJ
cmV0dXJuIHJlc3AtPnRva3Nbbl0ubGVuIC0gMTsKK30KKworc3RhdGljIHU2NCByZXNwb25zZV9n
ZXRfdTY0KGNvbnN0IHN0cnVjdCBwYXJzZWRfcmVzcCAqcmVzcCwgaW50IG4pCit7CisJaWYgKCFy
ZXNwKSB7CisJCXByX2VycigiUmVzcG9uc2UgaXMgTlVMTFxuIik7CisJCXJldHVybiAwOworCX0K
KworCWlmIChuID4gcmVzcC0+bnVtKSB7CisJCXByX2VycigiUmVzcG9uc2UgaGFzICVkIHRva2Vu
cy4gQ2FuJ3QgYWNjZXNzICVkXG4iLAorCQkgICAgICAgcmVzcC0+bnVtLCBuKTsKKwkJcmV0dXJu
IDA7CisJfQorCisJaWYgKHJlc3AtPnRva3Nbbl0udHlwZSAhPSBPUEFMX0RUQV9UT0tFTklEX1VJ
TlQpIHsKKwkJcHJfZXJyKCJUb2tlbiBpcyBub3QgdW5zaWduZWQgaXQ6ICVkXG4iLAorCQkgICAg
ICAgcmVzcC0+dG9rc1tuXS50eXBlKTsKKwkJcmV0dXJuIDA7CisJfQorCisJaWYgKCEoKHJlc3At
PnRva3Nbbl0ud2lkdGggPT0gT1BBTF9XSURUSF9USU5ZKSB8fAorCSAgICAgIChyZXNwLT50b2tz
W25dLndpZHRoID09IE9QQUxfV0lEVEhfU0hPUlQpKSkgeworCQlwcl9lcnIoIkF0b20gaXMgbm90
IHNob3J0IG9yIHRpbnk6ICVkXG4iLAorCQkgICAgICAgcmVzcC0+dG9rc1tuXS53aWR0aCk7CisJ
CXJldHVybiAwOworCX0KKworCXJldHVybiByZXNwLT50b2tzW25dLnN0b3JlZC51OworfQorCitz
dGF0aWMgdTggcmVzcG9uc2Vfc3RhdHVzKGNvbnN0IHN0cnVjdCBwYXJzZWRfcmVzcCAqcmVzcCkK
K3sKKwlpZiAoKHRva2VuX3R5cGUocmVzcCwgMCkgPT0gT1BBTF9EVEFfVE9LRU5JRF9UT0tFTikK
KwkgICAgJiYgKHJlc3BvbnNlX2dldF90b2tlbihyZXNwLCAwKSA9PSBPUEFMX0VORE9GU0VTU0lP
TikpIHsKKwkJcmV0dXJuIDA7CisJfQorCisJaWYgKHJlc3AtPm51bSA8IDUpCisJCXJldHVybiBE
VEFFUlJPUl9OT19NRVRIT0RfU1RBVFVTOworCisJaWYgKCh0b2tlbl90eXBlKHJlc3AsIHJlc3At
Pm51bSAtIDEpICE9IE9QQUxfRFRBX1RPS0VOSURfVE9LRU4pIHx8CisJICAgICh0b2tlbl90eXBl
KHJlc3AsIHJlc3AtPm51bSAtIDUpICE9IE9QQUxfRFRBX1RPS0VOSURfVE9LRU4pIHx8CisJICAg
IChyZXNwb25zZV9nZXRfdG9rZW4ocmVzcCwgcmVzcC0+bnVtIC0gMSkgIT0gT1BBTF9FTkRMSVNU
KSB8fAorCSAgICAocmVzcG9uc2VfZ2V0X3Rva2VuKHJlc3AsIHJlc3AtPm51bSAtIDUpICE9IE9Q
QUxfU1RBUlRMSVNUKSkKKwkJcmV0dXJuIERUQUVSUk9SX05PX01FVEhPRF9TVEFUVVM7CisKKwly
ZXR1cm4gcmVzcG9uc2VfZ2V0X3U2NChyZXNwLCByZXNwLT5udW0gLSA0KTsKK30KKworLyogUGFy
c2VzIGFuZCBjaGVja3MgZm9yIGVycm9ycyAqLworc3RhdGljIGludCBwYXJzZV9hbmRfY2hlY2tf
c3RhdHVzKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXN0cnVjdCBvcGFsX2NtZCAqY21kOwor
CWludCBlcnJvcjsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwlwcmludF9idWZmZXIoY21kLT5jbWQs
IGNtZC0+cG9zKTsKKworCWVycm9yID0gcmVzcG9uc2VfcGFyc2UoY21kLT5yZXNwLCBJT19CVUZG
RVJfTEVOR1RILCAmZGV2LT5wYXJzZWQpOworCWlmIChlcnJvcikgeworCQlwcl9lcnIoIiVzOiBD
b3VsZG4ndCBwYXJzZSByZXNwb25zZS5cbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJZ290byBlcnJf
cmV0dXJuOworCX0KKworCWVycm9yID0gcmVzcG9uc2Vfc3RhdHVzKCZkZXYtPnBhcnNlZCk7CisJ
aWYgKGVycm9yKQorCQlwcl9lcnIoIiVzOiBSZXNwb25zZSBTdGF0dXM6ICVkXG4iLCBkZXYtPmRp
c2tfbmFtZSwKKwkJICAgICAgIGVycm9yKTsKKworIGVycl9yZXR1cm46CisJcmV0dXJuIGVycm9y
OworfQorCitzdGF0aWMgdm9pZCBjbGVhcl9vcGFsX2NtZChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCkK
K3sKKwljbWQtPnBvcyA9IHNpemVvZihzdHJ1Y3Qgb3BhbF9oZWFkZXIpOworCW1lbXNldChjbWQt
PmNtZCwgMCwgSU9fQlVGRkVSX0xFTkdUSCk7CisJY21kLT5jYiA9IE5VTEw7CisJY21kLT5jYl9k
YXRhID0gTlVMTDsKK30KKworc3RhdGljIGludCBzdGFydF9vcGFsX3Nlc3Npb25fY29udCh2b2lk
ICpkYXRhKQoreworCXN0cnVjdCBvcGFsX2RldiAqZGV2ID0gZGF0YTsKKwl1MzIgSFNOLCBUU047
CisJaW50IGVycm9yID0gMDsKKworCWVycm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhkZXYp
OworCWlmIChlcnJvcikKKwkJZ290byBlcnJfcmV0dXJuOworCisJSFNOID0gcmVzcG9uc2VfZ2V0
X3U2NCgmZGV2LT5wYXJzZWQsIDQpOworCVRTTiA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFy
c2VkLCA1KTsKKworCWlmIChIU04gPT0gMCAmJiBUU04gPT0gMCkgeworCQlwcl9lcnIoIiVzOiBD
b3VsZG4ndCBhdXRoZW50aWNhdGUgc2Vzc2lvblxuIiwgZGV2LT5kaXNrX25hbWUpOworCQllcnJv
ciA9IC1FUEVSTTsKKwkJZ290byBlcnJfcmV0dXJuOworCX0KKworCWRldi0+SFNOID0gSFNOOwor
CWRldi0+VFNOID0gVFNOOworCitlcnJfcmV0dXJuOgorCXJldHVybiBlcnJvcjsKK30KKworc3Ry
dWN0IGtleSAqcmVxdWVzdF91c2VyX2tleShjb25zdCBjaGFyICptYXN0ZXJfZGVzYywgY29uc3Qg
dTggKiptYXN0ZXJfa2V5LAorCQkJICAgICBzaXplX3QgKm1hc3Rlcl9rZXlsZW4pCit7CisJY29u
c3Qgc3RydWN0IHVzZXJfa2V5X3BheWxvYWQgKnVwYXlsb2FkOworCXN0cnVjdCBrZXkgKnVrZXk7
CisKKwl1a2V5ID0gcmVxdWVzdF9rZXkoJmtleV90eXBlX3VzZXIsIG1hc3Rlcl9kZXNjLCBOVUxM
KTsKKwlpZiAoSVNfRVJSKHVrZXkpKQorCQlnb3RvIGVycm9yOworCisJZG93bl9yZWFkKCZ1a2V5
LT5zZW0pOworCXVwYXlsb2FkID0gdXNlcl9rZXlfcGF5bG9hZCh1a2V5KTsKKwkqbWFzdGVyX2tl
eSA9IHVwYXlsb2FkLT5kYXRhOworCSptYXN0ZXJfa2V5bGVuID0gdXBheWxvYWQtPmRhdGFsZW47
CitlcnJvcjoKKwlyZXR1cm4gdWtleTsKK30KKworc3RhdGljIGludCBnZXRfb3BhbF9rZXkoc3Ry
dWN0IG9wYWxfZGV2ICpkZXYpCit7CisJc3RydWN0IGtleSAqdWtleSA9IE5VTEw7CisJY29uc3Qg
dTggKnRtcGtleSA9IE5VTEw7CisJc2l6ZV90IHRtcGxlbjsKKwlpbnQgcmV0ID0gMDsKKworCWlm
IChkZXYtPmtleV90eXBlID09IE9QQUxfS0VZX1BMQUlOKSB7CisJCXRtcGtleSA9IGRldi0+a2V5
X25hbWU7CisJCXRtcGxlbiA9IGRldi0+a2V5X25hbWVfbGVuOworCX0gZWxzZSBpZiAoZGV2LT5r
ZXlfdHlwZSA9PSBPUEFMX0tFWV9LRVlSSU5HKSB7CisJCXVrZXkgPSByZXF1ZXN0X3VzZXJfa2V5
KGRldi0+a2V5X25hbWUsICZ0bXBrZXksICZ0bXBsZW4pOworCQlpZiAoSVNfRVJSKHVrZXkpKSB7
CisJCQlwcl9lcnIoIiVzOiBDYW4ndCByZXRyaWV2ZSBrZXk6ICVsZFxuIiwgZGV2LT5kaXNrX25h
bWUsCisJCQkgICAgICAgUFRSX0VSUih1a2V5KSk7CisJCQlyZXR1cm4gUFRSX0VSUih1a2V5KTsK
KwkJfQorCX0gZWxzZSB7CisJCXByX2VycigiUmVxdWVzdGVkIGludmFsaWQga2V5IHR5cGU6ICVk
XG4iLCBkZXYtPmtleV90eXBlKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJaWYgKHRtcGxl
biA+IE9QQUxfS0VZX01BWCkgeworCQlwcl9lcnIoIlJlcXVlc3RlZCBrZXkgd2l0aCBpbnZhbGlk
IHNpemU6ICV6ZFxuIiwgdG1wbGVuKTsKKwkJcmV0ID0gLUVJTlZBTDsKKwkJZ290byBlcnJfZXhp
dDsKKwl9CisKKwlkZXYtPmtleV9sZW4gPSB0bXBsZW47CisJaWYgKCFtZW1jcHkoZGV2LT5rZXks
IHRtcGtleSwgdG1wbGVuKSkgeworCQlwcl9lcnIoIkVycm9yIHdoZW4gY29weWluZyBrZXkiKTsK
KwkJcmV0ID0gLUVGQVVMVDsKKwkJZ290byBlcnJfZXhpdDsKKwl9CisKK2Vycl9leGl0OgorCWtl
eV9wdXQodWtleSk7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHZvaWQgY2xlYW5fb3BhbF9r
ZXkoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJbWVtc2V0KGRldi0+a2V5LCAwLCBPUEFMX0tF
WV9NQVgpOworCWRldi0+a2V5X2xlbiA9IDA7Cit9CisKK3N0YXRpYyBpbmxpbmUgdm9pZCBjbGVh
bl9mdW5jdGlvbl9kYXRhKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCWRldi0+ZnVuY19kYXRh
ID0gTlVMTDsKKwlkZXYtPm51bV9mdW5jX2RhdGEgPSAwOworfQorCisvKiBUaGlzIGlzIGEgZ2Vu
ZXJpYyBjb250aW51YXRpb24uCisgKiBXZSB1c2UgdGhpcyB3aGVuIHdlIGRvbid0IGNhcmUgYWJv
dXQgdGhlIHJlc3BvbnNlIGRhdGEKKyAqIGFuZCBzaW1wbHkgd2FudCB0byBjaGVjayB0aGUgc3Rh
dHVzIGFuZCBjb250aW51ZS4KKyAqLworc3RhdGljIGludCBnZW5lcmljX2NvbnQodm9pZCAqZGF0
YSkKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisKKwlyZXR1cm4gcGFyc2VfYW5k
X2NoZWNrX3N0YXR1cyhkZXYpOworfQorCitzdGF0aWMgaW50IGVuZF9zZXNzaW9uX2NvbnQodm9p
ZCAqZGF0YSkKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisKKwlkZXYtPkhTTiA9
IDA7CisJZGV2LT5UU04gPSAwOworCXJldHVybiBnZW5lcmljX2NvbnQoZGF0YSk7Cit9CisKK3N0
YXRpYyBpbnQgZmluYWxpemVfYW5kX3NlbmQoc3RydWN0IG9wYWxfZGV2ICpkZXYsIHN0cnVjdCBv
cGFsX2NtZCAqY21kLAorCQkJICAgICBjb250X2ZuIGNvbnQpCit7CisJaW50IHJldDsKKworCXJl
dCA9IGNtZF9maW5hbGl6ZShjbWQsIGRldi0+SFNOLCBkZXYtPlRTTik7CisJaWYgKHJldCkgewor
CQlwcl9lcnIoIiVzOiBFcnJvciBmaW5hbGl6aW5nIGNvbW1hbmQgYnVmZmVyOiAlZFxuIiwKKwkJ
ICAgICAgIGRldi0+ZGlza19uYW1lLCByZXQpOworCQlyZXR1cm4gcmV0OworCX0KKworCXByaW50
X2J1ZmZlcihjbWQtPmNtZCwgY21kLT5wb3MpOworCisJcmV0dXJuIG9wYWxfc2VuZF9yZWN2KGRl
diwgY29udCk7Cit9CisKK3N0YXRpYyBpbnQgZ2VuX2tleShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikK
K3sKKwljb25zdCB1OCAqbWV0aG9kOworCXU4IHVpZFtPUEFMX1VJRF9MRU5HVEhdOworCXN0cnVj
dCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJf
b3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKworCW1lbWNweSh1
aWQsIGRldi0+cHJldl9kYXRhLCBtaW4oc2l6ZW9mKHVpZCksIGRldi0+cHJldl9kX2xlbikpOwor
CW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRU5LRVldOworCWtmcmVlKGRldi0+cHJldl9kYXRh
KTsKKwlkZXYtPnByZXZfZGF0YSA9IE5VTEw7CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5f
dmEoY21kLCAiYzJzIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICB1aWQsIE9QQUxf
VUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkg
ICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfRU5ETElTVCk7CisJaWYgKHJldCA8IDAp
IHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgZ2VuIGtleSBjb21tYW5kXG4iLAorCQkg
ICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5h
bGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBn
ZXRfYWN0aXZlX2tleV9jb250KHZvaWQgKmRhdGEpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYg
PSBkYXRhOworCWNvbnN0IGNoYXIgKmFjdGl2ZWtleTsKKwlzaXplX3Qga2V5bGVuOworCWludCBl
cnJvciA9IDA7CisKKwllcnJvciA9IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoZGV2KTsKKwlpZiAo
ZXJyb3IpCisJCWdvdG8gZXJyX3JldHVybjsKKwlrZXlsZW4gPSByZXNwb25zZV9nZXRfc3RyaW5n
KCZkZXYtPnBhcnNlZCwgNCwgJmFjdGl2ZWtleSk7CisJaWYgKCFhY3RpdmVrZXkpIHsKKwkJcHJf
ZXJyKCIlczogQ291bGRuJ3QgZXh0cmFjdCB0aGUgQWN0aXZla2V5IGZyb20gdGhlIHJlc3BvbnNl
XG4iLAorCQkgICAgICAgX19mdW5jX18pOworCQllcnJvciA9IDB4MEE7CisJCWdvdG8gZXJyX3Jl
dHVybjsKKwl9CisJZGV2LT5wcmV2X2RhdGEgPSBrbWVtZHVwKGFjdGl2ZWtleSwga2V5bGVuLCBH
RlBfS0VSTkVMKTsKKworCWlmICghZGV2LT5wcmV2X2RhdGEpIHsKKwkJZXJyb3IgPSAtRU5PTUVN
OworCQlnb3RvIGVycl9yZXR1cm47CisJfQorCisJZGV2LT5wcmV2X2RfbGVuID0ga2V5bGVuOwor
CisgZXJyX3JldHVybjoKKwlyZXR1cm4gZXJyb3I7Cit9CisKK3N0YXRpYyBpbnQgZ2V0X2FjdGl2
ZV9rZXkoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29uc3QgdTggKm1ldGhvZDsKKwl1OCB1
aWRbT1BBTF9VSURfTEVOR1RIXTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0Owor
CisJY21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlEKGNt
ZCwgZGV2LT5jb21JRCk7CisKKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfR0VUXTsKKworCXJl
dCA9IGJ1aWxkX2xvY2tpbmdfcmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5scik7CisJaWYg
KHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9ja2luZyByYW5nZVxuIiwg
ZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlyZXQgPSB0ZXN0X2Fu
ZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDZjIDRjIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAor
CQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhP
RF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlRM
SVNULAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMs
IC8qIHN0YXJ0Q2xvdW1uICovCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzEwLCAvKiBBY3RpdmVL
ZXkgKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAor
CQkJCSAgICBPUEFMX1RJTllfVUlOVF8wNCwgLyogZW5kQ29sdW1uICovCisJCQkJICAgIE9QQUxf
VElOWV9VSU5UXzEwLCAvKiBBY3RpdmVLZXkgKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJ
CQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKwlpZiAocmV0IDwg
MCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBnZXQgYWN0aXZlIGtleSBjb21tYW5k
XG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJl
dHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2V0X2FjdGl2ZV9rZXlfY29udCk7Cit9
CisKK3N0YXRpYyBpbmxpbmUgaW50IGVuYWJsZV9nbG9iYWxfbHIoc3RydWN0IG9wYWxfY21kICpj
bWQsIHU4ICp1aWQsCisJCQkJICAgc3RydWN0IG9wYWxfdXNlcl9scl9zZXR1cCAqc2V0dXApCit7
CisJY29uc3QgdTggKm1ldGhvZDsKKworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOwor
CXJldHVybiB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDRjIDJjdWMgMmN1YyA0YyA0
YyAzYyIsCisJCQkJICAgICBPUEFMX0NBTEwsCisJCQkJICAgICB1aWQsIE9QQUxfVUlEX0xFTkdU
SCwKKwkJCQkgICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgICBPUEFM
X1NUQVJUTElTVCwKKwkJCQkgICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICAgT1BBTF9WQUxV
RVMsCisJCQkJICAgICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICAgT1BBTF9TVEFSVE5BTUUs
CisJCQkJICAgICBPUEFMX1RJTllfVUlOVF8wNSwgLyogUmVhZExvY2tFbmFibGVkICovCisJCQkJ
ICAgICAhIXNldHVwLT5STEUsCisJCQkJICAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgIE9Q
QUxfU1RBUlROQU1FLAorCQkJCSAgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIFdyaXRlTG9ja0Vu
YWJsZWQgKi8KKwkJCQkgICAgICEhc2V0dXAtPldMRSwKKwkJCQkgICAgIE9QQUxfRU5ETkFNRSwK
KworCQkJCSAgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgICBPUEFMX1JFQURMT0NLRUQsCisJ
CQkJICAgICBPUEFMX0ZBTFNFLAorCQkJCSAgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgICBP
UEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgIE9QQUxfV1JJVEVMT0NLRUQsCisJCQkJICAgICBPUEFM
X0ZBTFNFLAorCQkJCSAgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgICBPUEFMX0VORExJU1Qs
CisJCQkJICAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgICBPUEFMX0VORExJU1QpOworfQorCitz
dGF0aWMgaW50IHNldHVwX2xvY2tpbmdfcmFuZ2Uoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJ
Y29uc3QgdTggKm1ldGhvZDsKKwl1OCB1aWRbT1BBTF9VSURfTEVOR1RIXTsKKwlzdHJ1Y3Qgb3Bh
bF9jbWQgKmNtZDsKKwlzdHJ1Y3Qgb3BhbF91c2VyX2xyX3NldHVwICpzZXR1cDsKKwlpbnQgcmV0
OworCisJY21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlE
KGNtZCwgZGV2LT5jb21JRCk7CisKKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU0VUXTsKKwly
ZXQgPSBidWlsZF9sb2NraW5nX3JhbmdlKHVpZCwgc2l6ZW9mKHVpZCksIGRldi0+bHIpOworCWlm
IChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIs
IGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCXNldHVwID0gZGV2LT5m
dW5jX2RhdGFbZGV2LT5zdGF0ZSAtIDFdOworCWlmIChkZXYtPmxyID09IDApCisJCXJldCA9IGVu
YWJsZV9nbG9iYWxfbHIoY21kLCB1aWQsIHNldHVwKTsKKwllbHNlCisJCXJldCA9IHRlc3RfYW5k
X2FkZF90b2tlbl92YShjbWQsICJjMnMgIDRjIDJjdWMgMmN1YyAyY3VjIDJjdSA0YyIsCisJCQkJ
ICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1l
dGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJ
CSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9WQUxVRVMsCisJCQkJICAgIE9QQUxf
U1RBUlRMSVNULAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllf
VUlOVF8wMywgLyogUmFuZ2UgU3RhcnQgKi8KKwkJCQkgICAgc2V0dXAtPnJhbmdlX3N0YXJ0LAor
CQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAg
IE9QQUxfVElOWV9VSU5UXzA0LCAvKiBSYW5nZSBMZW5ndGggKi8KKwkJCQkgICAgc2V0dXAtPnJh
bmdlX2xlbmd0aCwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfU1RBUlRO
QU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wNSwgLyogUmVhZExvY2tFbmFibGVkICovCisJ
CQkJICAgICEhc2V0dXAtPlJMRSwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9Q
QUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wNiwgLyogV3JpdGVMb2NrRW5h
YmxlZCAqLworCQkJCSAgICAhIXNldHVwLT5XTEUsCisKKwkJCQkgICAgT1BBTF9FTkROQU1FLAor
CQkJCSAgICBPUEFMX0VORExJU1QsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BB
TF9FTkRMSVNUKTsKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGlu
ZyBTZXR1cCBMb2NraW5nIHJhbmdlIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25h
bWUpOworCQlyZXR1cm4gcmV0OworCisJfQorCisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRl
diwgY21kLCBnZW5lcmljX2NvbnQpOworfQorCitzdGF0aWMgaW50IHN0YXJ0X2FkbWluc3Bfb3Bh
bF9zZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2LAorCQkJCSAgICAgIGVudW0gT1BBTF9VSUQg
YXV0aCwKKwkJCQkgICAgICBjb25zdCBjaGFyICprZXksCisJCQkJICAgICAgdTgga2V5X2xlbikK
K3sKKwljb25zdCB1OCAqbWV0aG9kLCAqc211aWQsICphZG1pbl9zcCwgKmhzYTsKKwlzdHJ1Y3Qg
b3BhbF9jbWQgKmNtZDsKKwl1MzIgSFNOOworCWludCByZXQ7CisKKwlpZiAoa2V5ID09IE5VTEwg
JiYgYXV0aCAhPSBPUEFMX0FOWUJPRFlfVUlEKSB7CisJCXByX2VycigiJXM6IEF0dGVtcHRlZCB0
byBvcGVuIEFETUlOX1NQIFNlc3Npb24gd2l0aG91dCBhIEhvc3QiIFwKKwkJICAgICAgICJDaGFs
bGVuZ2UsIGFuZCBub3QgYXMgdGhlIEFueWJvZHkgVUlEXG4iLCBfX2Z1bmNfXyk7CisJCXJldHVy
biAxOworCX0KKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCisJ
c2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisJSFNOID0gR0VORVJJQ19IT1NUX1NFU1NJT05f
TlVNOworCisJc211aWQgPSBPUEFMVUlEW09QQUxfU01VSURfVUlEXTsKKwltZXRob2QgPSBPUEFM
TUVUSE9EW09QQUxfU1RBUlRTRVNTSU9OXTsKKwlhZG1pbl9zcCA9IE9QQUxVSURbT1BBTF9BRE1J
TlNQX1VJRF07CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIGN1c2Mi
LAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIHNtdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJ
CQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCQkJCSAgICBPUEFMX1NUQVJUTElT
VCwKKwkJCQkgICAgSFNOLAorCQkJCSAgICBhZG1pbl9zcCwgT1BBTF9VSURfTEVOR1RILAorCQkJ
CSAgICBPUEFMX1RJTllfVUlOVF8wMSk7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczog
RXJyb3IgYnVpbGRpbmcgc3RhcnQgYWRtaW5zcCBzZXNzaW9uIGNvbW1hbmQuXG4iLAorCQkgICAg
ICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXN3aXRjaCAoYXV0aCkg
eworCWNhc2UgT1BBTF9BTllCT0RZX1VJRDoKKwkJLyogbm90aGluZyBsZWZ0IHRvIGRvIGZvciBh
bnlib2R5LCBqdXN0IGVuZCBhbmQgZmluYWxpemUgKi8KKwkJcmV0ID0gdGVzdF9hbmRfYWRkX3Rv
a2VuX3ZhKGNtZCwgImMiLAorCQkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKwkJYnJlYWs7CisJY2Fz
ZSBPUEFMX1NJRF9VSUQ6CisJCWhzYSA9IE9QQUxVSURbT1BBTF9TSURfVUlEXTsKKwkJcmV0ID0g
dGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgIjJjIHMgM2MgcyAyYyIsCisJCQkJCSAgICBPUEFM
X1NUQVJUTkFNRSwKKwkJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAwLCAvKiBIb3N0Q2hhbGxlbmdl
ICovCisJCQkJCSAgICBrZXksIGtleV9sZW4sCisJCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJ
CSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAvKiBIb3N0
U2lnbkF1dGggKi8KKwkJCQkJICAgIGhzYSwgT1BBTF9VSURfTEVOR1RILAorCQkJCQkgICAgT1BB
TF9FTkROQU1FLAorCQkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKwkJYnJlYWs7CisJZGVmYXVsdDoK
KwkJcHJfZXJyKCJDYW5ub3Qgc3RhcnQgQWRtaW4gU1Agc2Vzc2lvbiB3aXRoIGF1dGggJWRcbiIs
IGF1dGgpOworCQlyZXR1cm4gMTsKKwl9CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVz
OiBFcnJvciBidWlsZGluZyBzdGFydCBhZG1pbnNwIHNlc3Npb24gY29tbWFuZC5cbiIsCisJCSAg
ICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZpbmFs
aXplX2FuZF9zZW5kKGRldiwgY21kLCBzdGFydF9vcGFsX3Nlc3Npb25fY29udCk7Cit9CisKK3N0
YXRpYyBpbnQgc3RhcnRfYW55Ym9keUFTUF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpk
ZXYpCit7CisJcmV0dXJuIHN0YXJ0X2FkbWluc3Bfb3BhbF9zZXNzaW9uKGRldiwgT1BBTF9BTllC
T0RZX1VJRCwgTlVMTCwgMCk7Cit9CisKK3N0YXRpYyBpbnQgc3RhcnRfU0lEQVNQX29wYWxfc2Vz
c2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlpbnQgcmV0OworCWNvbnN0IHU4ICprZXkg
PSBkZXYtPnByZXZfZGF0YTsKKworCWlmICgha2V5KQorCQlyZXQgPSBzdGFydF9hZG1pbnNwX29w
YWxfc2Vzc2lvbihkZXYsIE9QQUxfU0lEX1VJRCwgZGV2LT5rZXksCisJCQkJCQkgZGV2LT5rZXlf
bGVuKTsKKwllbHNlIHsKKwkJcmV0ID0gc3RhcnRfYWRtaW5zcF9vcGFsX3Nlc3Npb24oZGV2LCBP
UEFMX1NJRF9VSUQsIGtleSwKKwkJCQkJCSBkZXYtPnByZXZfZF9sZW4pOworCQlrZnJlZShrZXkp
OworCQlkZXYtPnByZXZfZGF0YSA9IE5VTEw7CisJfQorCXJldHVybiByZXQ7Cit9CisKK3N0YXRp
YyBpbnQgc3RhcnRfbG9ja2luZ3NwX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldiwK
KwkJCQkJZW51bSBPUEFMX1VJRCBhdXRoLCBjb25zdCB1OCAqa2V5LAorCQkJCQl1OCBrZXlfbGVu
KQoreworCisJY29uc3QgdTggKm1ldGhvZCwgKnNtdWlkLCAqbG9ja2luZ19zcCwgKmhzYTsKKwlz
dHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlzaXplX3Qga2xlbiA9IGtleV9sZW47CisJdTMyIEhTTjsK
KwlpbnQgcmV0OworCisJaWYgKGtleSA9PSBOVUxMKSB7CisJCXByX2VycigiQ2Fubm90IHN0YXJ0
IExvY2tpbmcgU1Agc2Vzc2lvbiB3aXRob3V0IGEga2V5XG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7
CisJfQorCisJY21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNtZCk7CisKKwlzZXRf
Y29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKwlIU04gPSBHRU5FUklDX0hPU1RfU0VTU0lPTl9OVU07
CisKKwlzbXVpZCA9IE9QQUxVSURbT1BBTF9TTVVJRF9VSURdOworCW1ldGhvZCA9IE9QQUxNRVRI
T0RbT1BBTF9TVEFSVFNFU1NJT05dOworCWxvY2tpbmdfc3AgPSBPUEFMVUlEW09QQUxfTE9DS0lO
R1NQX1VJRF07CisJaHNhID0gT1BBTFVJRFthdXRoXTsKKworCXJldCA9IHRlc3RfYW5kX2FkZF90
b2tlbl92YShjbWQsICJjMnMgY3VzYyAyY3NjIDJjc2MgYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwK
KwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01F
VEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIEhTTiwKKwkJ
CQkgICAgbG9ja2luZ19zcCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBPUEFMX1RJTllfVUlO
VF8wMSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRf
MDAsIC8qIEhvc3RDaGFsbGVuZ2UgKi8KKwkJCQkgICAga2V5LCBrbGVuLAorCQkJCSAgICBPUEFM
X0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9V
SU5UXzAzLCAvKiBIb3N0IFNpZ24gQXV0aG9yaXR5ICovCisJCQkJICAgIGhzYSwgT1BBTF9VSURf
TEVOR1RILAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsK
KworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIHN0YXJ0IGFk
bWluc3Agc2Vzc2lvbiBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJ
cmV0dXJuIHJldDsKKwl9CisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBzdGFy
dF9vcGFsX3Nlc3Npb25fY29udCk7Cit9CisKK3N0YXRpYyBpbmxpbmUgaW50IHN0YXJ0X2FkbWlu
MUxTUF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJcmV0dXJuIHN0YXJ0
X2xvY2tpbmdzcF9vcGFsX3Nlc3Npb24oZGV2LCBPUEFMX0FETUlOMV9VSUQsCisJCQkJCSAgICBk
ZXYtPmtleSwgZGV2LT5rZXlfbGVuKTsKK30KKworc3RhdGljIGludCBzdGFydF9hdXRoX29wYWxf
c2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0aG9kLCAqc211
aWQsICpsb2NraW5nX3NwOworCXU4IGxrX3VsX3VzZXJbT1BBTF9VSURfTEVOR1RIXTsKKwlzdHJ1
Y3Qgb3BhbF9jbWQgKmNtZDsKKwl1MzIgSFNOOworCWludCByZXQ7CisJc3RydWN0IG9wYWxfdXNl
cl9pbmZvICp1aW5mbzsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQp
OworCisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwlIU04gPSBHRU5FUklDX0hPU1Rf
U0VTU0lPTl9OVU07CisKKwl1aW5mbyA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsK
KworCXNtdWlkID0gT1BBTFVJRFtPUEFMX1NNVUlEX1VJRF07CisJbWV0aG9kID0gT1BBTE1FVEhP
RFtPUEFMX1NUQVJUU0VTU0lPTl07CisJbG9ja2luZ19zcCA9IE9QQUxVSURbT1BBTF9MT0NLSU5H
U1BfVUlEXTsKKworCWlmICh1aW5mby0+U1VNKSB7CisJCXJldCA9IGJ1aWxkX2xvY2tpbmdfdXNl
cihsa191bF91c2VyLCBzaXplb2YobGtfdWxfdXNlciksCisJCQkJCSBkZXYtPmxyKTsKKwkJaWYg
KHJldCA8IDApIHsKKwkJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgdXNlclxuIiwK
KwkJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCQlyZXR1cm4gcmV0OworCQl9CisJfSBlbHNl
IGlmICh1aW5mby0+d2hvICE9IE9QQUxfQURNSU4xICYmICF1aW5mby0+U1VNKSB7CisJCXJldCA9
IGJ1aWxkX2xvY2tpbmdfdXNlcihsa191bF91c2VyLCBzaXplb2YobGtfdWxfdXNlciksCisJCQkJ
CSB1aW5mby0+d2hvIC0gMSk7CisJCWlmIChyZXQgPCAwKSB7CisJCQlwcl9lcnIoIiVzOiBDYW4n
dCBidWlsZCBsb2NraW5nIHVzZXJcbiIsCisJCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQkJ
cmV0dXJuIHJldDsKKwkJfQorCX0gZWxzZQorCQltZW1jcHkobGtfdWxfdXNlciwgT1BBTFVJRFtP
UEFMX0FETUlOMV9VSURdLCBPUEFMX1VJRF9MRU5HVEgpOworCisKKwlyZXQgPSB0ZXN0X2FuZF9h
ZGRfdG9rZW5fdmEoY21kLCAiYzJzIGN1czNjczNjIHMgMmMiLAorCQkJCSAgICBPUEFMX0NBTEws
CisJCQkJICAgIHNtdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9N
RVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBIU04sCisJ
CQkJICAgIGxvY2tpbmdfc3AsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgT1BBTF9USU5ZX1VJ
TlRfMDEsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8w
MCwKKwkJCQkgICAgZGV2LT5rZXksIGRldi0+a2V5X2xlbiwKKwkJCQkgICAgT1BBTF9FTkROQU1F
LAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsCisK
KwkJCQkgICAgbGtfdWxfdXNlciwgT1BBTF9VSURfTEVOR1RILAorCisJCQkJICAgIE9QQUxfRU5E
TkFNRSwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2Vy
cigiJXM6IEVycm9yIGJ1aWxkaW5nIFNUQVJUU0VTU0lPTiBjb21tYW5kLlxuIiwKKwkJICAgICAg
IGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVf
YW5kX3NlbmQoZGV2LCBjbWQsIHN0YXJ0X29wYWxfc2Vzc2lvbl9jb250KTsKK30KKworc3RhdGlj
IGludCByZXZlcnRfdHBlcihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0
aG9kLCAqc211aWQ7CisJc3RydWN0IG9wYWxfY21kICpjbWQ7CisJaW50IHJldDsKKworCWNtZCA9
ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCisJc2V0X2NvbUlEKGNtZCwgZGV2
LT5jb21JRCk7CisKKwlzbXVpZCA9IE9QQUxVSURbT1BBTF9BRE1JTlNQX1VJRF07CisJbWV0aG9k
ID0gT1BBTE1FVEhPRFtPUEFMX1JFVkVSVF07CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5f
dmEoY21kLCAiYzJzIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICBzbXVpZCwgT1BB
TF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKwkJCQkg
ICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfRU5ETElTVCk7CisJaWYgKHJldCA8IDAp
IHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgUkVWRVJUIFRQRVIgY29tbWFuZC5cbiIs
CisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJu
IGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOworfQorCitzdGF0aWMg
aW50IGludGVybmFsX2FjdGl2YXRlX3VzZXIoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29u
c3QgdTggKm1ldGhvZDsKKwl1OCB1aWRbT1BBTF9VSURfTEVOR1RIXTsKKwlzdHJ1Y3Qgb3BhbF9j
bWQgKmNtZDsKKwlpbnQgcmV0OworCXN0cnVjdCBvcGFsX2tleV9hbmRfdXNlciAqYWN0OworCisJ
Y21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlEKGNtZCwg
ZGV2LT5jb21JRCk7CisKKwlhY3QgPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07CisK
KwltZW1jcHkodWlkLCBPUEFMVUlEW09QQUxfVVNFUjFfVUlEXSwgT1BBTF9VSURfTEVOR1RIKTsK
Kwl1aWRbN10gPSBhY3QtPndoby53aG87CisKKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU0VU
XTsKKworCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgM2MgYyA0YyAzYyIs
CisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJ
ICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNU
LAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDEsIC8q
IFZhbHVlcyAqLworCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCisJCQkJICAgIE9QQUxfU1RB
UlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wNSwgLyogRW5hYmxlZCAqLworCQkJCSAg
ICBPUEFMX1RJTllfVUlOVF8wMSwgLyogVHJ1ZSAqLworCQkJCSAgICBPUEFMX0VORE5BTUUsCisK
KwkJCQkgICAgT1BBTF9FTkRMSVNULAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9Q
QUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWls
ZGluZyBBY3RpdmF0ZSBVc2VyTiBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1l
KTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBj
bWQsIGdlbmVyaWNfY29udCk7Cit9CisKK3N0YXRpYyBpbnQgZXJhc2VfbG9ja2luZ19yYW5nZShz
dHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0aG9kOworCXU4IHVpZFtPUEFM
X1VJRF9MRU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwljbWQg
PSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYt
PmNvbUlEKTsKKworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9FUkFTRV07CisKKwlpZiAoYnVp
bGRfbG9ja2luZ19yYW5nZSh1aWQsIHNpemVvZih1aWQpLCBkZXYtPmxyKSA8IDApIHsKKwkJcHJf
ZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9ja2luZyByYW5nZVxuIiwgZGV2LT5kaXNrX25hbWUpOwor
CQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21k
LCAiYzJzIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xF
TkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BB
TF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgewor
CQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBFcmFzZSBMb2NraW5nIFJhbmdlIENtbWFuZC5c
biIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCXJldHVy
biBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGlj
IGludCBzZXRfbWJyX2RvbmUoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29uc3QgdTggKm1l
dGhvZCwgKnVpZDsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0OworCXU4IG1icl9k
b25lX3RmID0gKih1OCAqKWRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKworCWNtZCA9
ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChjbWQsIGRldi0+
Y29tSUQpOworCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07CisJdWlkID0gT1BBTFVJ
RFtPUEFMX01CUkNPTlRST0xdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwg
ImMycyAzYyA2YyAyYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJ
RF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAg
IE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9W
QUxVRVMsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1F
LAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMiwgLyogRG9uZSAqLworCQkJCSAgICBtYnJfZG9u
ZV90ZiwgICAgICAgLyogRG9uZSBUIG9yIEYgKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCQkJ
CSAgICBPUEFMX0VORExJU1QsCisKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCQkJCSAgICBPUEFM
X0VORExJU1QpOworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIEJ1aWxkaW5n
IHNldCBNQlIgRG9uZSBjb21tYW5kXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQly
ZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2Vu
ZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBzZXRfbWJyX2VuYWJsZV9kaXNhYmxlKHN0cnVj
dCBvcGFsX2RldiAqZGV2KQoreworCWNvbnN0IHU4ICptZXRob2QsICp1aWQ7CisJc3RydWN0IG9w
YWxfY21kICpjbWQ7CisJaW50IHJldDsKKwl1OCBtYnJfZW5fZGlzID0gKih1OCAqKWRldi0+ZnVu
Y19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFs
X2NtZChjbWQpOworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCisJbWV0aG9kID0gT1BB
TE1FVEhPRFtPUEFMX1NFVF07CisJdWlkID0gT1BBTFVJRFtPUEFMX01CUkNPTlRST0xdOworCisJ
cmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAzYyA2YyAyYyIsCisJCQkJICAg
IE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhv
ZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAg
ICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9WQUxVRVMsCisKKwkJCQkgICAgT1BBTF9T
VEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlO
VF8wMSwgLyogRW5hYmxlICovCisJCQkJICAgIG1icl9lbl9kaXMsICAgICAgICAvKiBFbmFibGUg
b3IgRGlzYWJsZSAqLworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElT
VCwKKworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElTVCk7CisJaWYg
KHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgc2V0IE1CUiBkb25lIGNv
bW1hbmRcbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQor
CisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOworfQor
CitzdGF0aWMgaW50IHNldF9uZXdfcHcoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29uc3Qg
dTggKm1ldGhvZDsKKwl1OCBjcGluX3VpZFtPUEFMX1VJRF9MRU5HVEhdOworCXN0cnVjdCBvcGFs
X2NtZCAqY21kOworCWludCByZXQ7CisJc3RydWN0IG9wYWxfbmV3X3B3ICpwdzsKKwlzaXplX3Qg
a2V5X2xlbjsKKwl1OCAqa2V5OworCisJY21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21k
KGNtZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwlwdyA9IGRldi0+ZnVuY19k
YXRhW2Rldi0+c3RhdGUgLSAxXTsKKwlrZXkgPSBwdy0+bmV3X3Bpbi5rZXk7CisJa2V5X2xlbiA9
IHB3LT5uZXdfcGluLmtleV9sZW47CisJbWVtY3B5KGNwaW5fdWlkLCBPUEFMVUlEW09QQUxfQ19Q
SU5fQURNSU4xXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCWlmIChwdy0+dXNlcl9mb3JfcHcgIT0g
T1BBTF9BRE1JTjEpIHsKKwkJY3Bpbl91aWRbNV0gPSAweDAzOworCQlpZiAocHctPndoby5TVU0p
CisJCQljcGluX3VpZFs3XSA9IHB3LT5uZXdfcGluLmxyICsgMTsKKwkJZWxzZQorCQkJY3Bpbl91
aWRbN10gPSBwdy0+dXNlcl9mb3JfcHc7CisJfQorCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFM
X1NFVF07CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDNjIDNjczJj
IDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICBjcGluX3VpZCwgT1BBTF9VSURfTEVO
R1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFM
X1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9V
SU5UXzAxLCAvKiBWYWx1ZXMgKi8KKworCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAg
T1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAvKiBQSU4gKi8KKwkJ
CQkgICAga2V5LCBrZXlfbGVuLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxf
RU5ETElTVCwKKworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElTVCk7
CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBTRVQgQU1J
TjEgUElOIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4g
cmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19j
b250KTsKK30KKworc3RhdGljIGludCBzZXRfc2lkX2NwaW5fcGluKHN0cnVjdCBvcGFsX2RldiAq
ZGV2KQoreworCWNvbnN0IHU4ICptZXRob2QsICpjcGluX3VpZDsKKwlzdHJ1Y3Qgb3BhbF9jbWQg
KmNtZDsKKwlpbnQgcmV0OworCisJY21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNt
ZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwljcGluX3VpZCA9IE9QQUxVSURb
T1BBTF9DX1BJTl9TSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOworCisJcmV0
ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAyYyA0Y3MyYyAyYyIsCisJCQkJICAg
IE9QQUxfQ0FMTCwKKwkJCQkgICAgY3Bpbl91aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAg
bWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJ
CQkJICAgIE9QQUxfU1RBUlROQU1FLAorCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLCAvKiBW
YWx1ZXMgKi8KKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1F
LAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElOICovCisJCQkJICAgIGRldi0+a2V5
LCBkZXYtPmtleV9sZW4sCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9FTkRM
SVNULAorCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKwor
CWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIFNFVCBDUElOIFBJ
TiBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJldDsK
Kwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29udCk7
Cit9CisKK3N0YXRpYyBpbnQgcXVlcnlfbG9ja2luZ19yYW5nZV9jb250KHZvaWQgKmRhdGEpCit7
CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOworCWludCBlcnJvcjsKKworCWVycm9yID0g
cGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhkZXYpOworCWlmIChlcnJvcikKKwkJZ290byBlcnJfcmV0
dXJuOworCisJZGV2LT5zdGFydCA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2VkLCA0KTsK
KwlkZXYtPmxlbmd0aCA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2VkLCA4KTsKKworZXJy
X3JldHVybjoKKwlyZXR1cm4gZXJyb3I7Cit9CisKK3N0YXRpYyBpbnQgcXVlcnlfbG9ja2luZ19y
YW5nZShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwl1OCBscl9idWZmZXJbT1BBTF9VSURfTEVO
R1RIXTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwljb25zdCB1OCAqbWV0aG9kOworCWludCBy
ZXQ7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKworCW1ldGhv
ZCA9IE9QQUxNRVRIT0RbT1BBTF9HRVRdOworCisJaWYgKGJ1aWxkX2xvY2tpbmdfcmFuZ2UobHJf
YnVmZmVyLCBzaXplb2YobHJfYnVmZmVyKSwgZGV2LT5scikgPCAwKSB7CisJCXByX2VycigiJXM6
IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJu
IC1FSU5WQUw7CisJfQorCisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwlyZXQgPSB0
ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDEyYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwK
KwkJCQkgICAgbHJfYnVmZmVyLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwgT1BB
TF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBPUEFM
X1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfU1RBUlRD
T0xVTU4sCisJCQkJICAgIE9QQUxfUkFOR0VTVEFSVCwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAor
CQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9FTkRDT0xVTU4sCisJCQkJICAg
IE9QQUxfUkFOR0VMRU5HVEgsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9F
TkRMSVNULAorCQkJCSAgICBPUEFMX0VORExJU1QpOworCisJaWYgKHJldCA8IDApIHsKKwkJcHJf
ZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgR0VUIExvY2tpbmcgUmFuZ2UgY29tbWFuZC5cbiIsCisJ
CSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZp
bmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBxdWVyeV9sb2NraW5nX3JhbmdlX2NvbnQpOworfQor
CitzdGF0aWMgaW50IGFkZF91c2VyX3RvX2xyKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXU4
IGxyX2J1ZmZlcltPUEFMX1VJRF9MRU5HVEhdOworCXU4IHVzZXJfdWlkW09QQUxfVUlEX0xFTkdU
SF07CisJc3RydWN0IG9wYWxfY21kICpjbWQ7CisJY29uc3QgdTggKm1ldGhvZDsKKwlzdHJ1Y3Qg
b3BhbF9sb2NrX3VubG9jayAqbGt1bDsKKwlpbnQgcmV0OworCisJY21kID0gJmRldi0+Y21kOwor
CWNsZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwlt
ZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU0VUXTsKKworCWxrdWwgPSBkZXYtPmZ1bmNfZGF0YVtk
ZXYtPnN0YXRlIC0gMV07CisKKwltZW1jcHkobHJfYnVmZmVyLCBPUEFMVUlEW09QQUxfTE9DS0lO
R1JBTkdFX0FDRV9SRExPQ0tFRF0sCisJICAgICAgIE9QQUxfVUlEX0xFTkdUSCk7CisKKwlpZiAo
bGt1bC0+bF9zdGF0ZSA9PSBPUEFMX1JXKQorCQltZW1jcHkobHJfYnVmZmVyLCBPUEFMVUlEW09Q
QUxfTE9DS0lOR1JBTkdFX0FDRV9XUkxPQ0tFRF0sCisJCSAgICAgICBPUEFMX1VJRF9MRU5HVEgp
OworCisJbHJfYnVmZmVyWzddID0gZGV2LT5scjsKKworCW1lbWNweSh1c2VyX3VpZCwgT1BBTFVJ
RFtPUEFMX1VTRVIxX1VJRF0sIE9QQUxfVUlEX0xFTkdUSCk7CisJdXNlcl91aWRbN10gPSBsa3Vs
LT5hdXRob3JpdHkud2hvOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMy
cyAzYyAzYyAyYyAyc2MgYzJzYyBjczJjIDVjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAg
ICBscl9idWZmZXIsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhP
RF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlRO
QU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSwgLyogVmFsdWVzICovCisKKwkJCQkgICAg
T1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJ
TllfVUlOVF8wMywgLyogQm9vbGVhbkV4cHIgKi8KKworCQkJCSAgICBPUEFMX1NUQVJUTElTVCwK
KwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisKKwkJCQkgICAgT1BBTFVJRFtPUEFMX0hBTEZfVUlE
X0FVVEhPUklUWV9PQkpfUkVGXSwKKwkJCQkgICAgT1BBTF9VSURfTEVOR1RIX0hBTEYsCisJCQkJ
ICAgIHVzZXJfdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwor
CQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTFVJRFtPUEFMX0hBTEZfVUlEX0FV
VEhPUklUWV9PQkpfUkVGXSwKKwkJCQkgICAgT1BBTF9VSURfTEVOR1RIX0hBTEYsCisJCQkJICAg
IHVzZXJfdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKworCQkJ
CSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTFVJRFtPUEFMX0hBTEZfVUlEX0JPT0xF
QU5fQUNFXSwKKwkJCQkgICAgT1BBTF9VSURfTEVOR1RIX0hBTEYsCisJCQkJICAgIE9QQUxfVElO
WV9VSU5UXzAxLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9FTkRMSVNU
LAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAg
T1BBTF9FTkROQU1FLAorCQkJCSAgICBPUEFMX0VORExJU1QpOworCWlmIChyZXQgPCAwKSB7CisJ
CXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIGFkZCB1c2VyIHRvIGxvY2tpbmcgcmFuZ2UgY29t
bWFuZC5cbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQor
CisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOworfQor
CitzdGF0aWMgaW50IGxvY2tfdW5sb2NrX2xvY2tpbmdfcmFuZ2Uoc3RydWN0IG9wYWxfZGV2ICpk
ZXYpCit7CisJdTggbHJfYnVmZmVyW09QQUxfVUlEX0xFTkdUSF07CisJc3RydWN0IG9wYWxfY21k
ICpjbWQ7CisJY29uc3QgdTggKm1ldGhvZDsKKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayAqbGt1
bDsKKwlpbnQgcmV0OworCXU4IHJlYWRfbG9ja2VkID0gMSwgd3JpdGVfbG9ja2VkID0gMTsKKwor
CWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChjbWQs
IGRldi0+Y29tSUQpOworCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07CisJbGt1bCA9
IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKwlpZiAoYnVpbGRfbG9ja2luZ19yYW5n
ZShscl9idWZmZXIsIHNpemVvZihscl9idWZmZXIpLCBkZXYtPmxyKSA8IDApIHsKKwkJcHJfZXJy
KCIlczogQ2FuJ3QgYnVpbGQgbG9ja2luZyByYW5nZVxuIiwgZGV2LT5kaXNrX25hbWUpOworCQly
ZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlzd2l0Y2ggKGxrdWwtPmxfc3RhdGUpIHsKKwljYXNlIE9Q
QUxfUk86CisJCXJlYWRfbG9ja2VkID0gMDsKKwkJd3JpdGVfbG9ja2VkID0gMTsKKwkJYnJlYWs7
CisJY2FzZSBPUEFMX1JXOgorCQlyZWFkX2xvY2tlZCA9IDA7CisJCXdyaXRlX2xvY2tlZCA9IDA7
CisJCWJyZWFrOworCWNhc2UgT1BBTF9MSzoKKwkJLyogdmFycyBhcmUgaW5pdGFsaXplZCB0byBs
b2NrZWQgKi8KKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJcHJfZXJyKCJUcmllZCB0byBzZXQgYW4g
aW52YWxpZCBsb2NraW5nIHN0YXRlLi4uIHJldHVybmluZyB0byB1bGFuZFxuIik7CisJCXJldHVy
biAxOworCX0KKworCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnNjIDNjIDRj
IDRjIDNjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICBscl9idWZmZXIsIE9QQUxfVUlE
X0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisJCQkJICAgIE9Q
QUxfU1RBUlRMSVNULAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1ZB
TFVFUywKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUs
CisJCQkJICAgIE9QQUxfUkVBRExPQ0tFRCwKKwkJCQkgICAgcmVhZF9sb2NrZWQsCisJCQkJICAg
IE9QQUxfRU5ETkFNRSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9X
UklURUxPQ0tFRCwKKwkJCQkgICAgd3JpdGVfbG9ja2VkLAorCQkJCSAgICBPUEFMX0VORE5BTUUs
CisKKwkJCQkgICAgT1BBTF9FTkRMSVNULAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAg
IE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBi
dWlsZGluZyBTRVQgY29tbWFuZC5cbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJldDsK
Kwl9CisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOwor
fQorCisKK3N0YXRpYyBpbnQgbG9ja191bmxvY2tfbG9ja2luZ19yYW5nZV9TVU0oc3RydWN0IG9w
YWxfZGV2ICpkZXYpCit7CisJdTggbHJfYnVmZmVyW09QQUxfVUlEX0xFTkdUSF07CisJc3RydWN0
IG9wYWxfY21kICpjbWQ7CisJY29uc3QgdTggKm1ldGhvZDsKKwlzdHJ1Y3Qgb3BhbF9sb2NrX3Vu
bG9jayAqbGt1bDsKKwlpbnQgcmV0OworCXU4IHJlYWRfbG9ja2VkID0gMSwgd3JpdGVfbG9ja2Vk
ID0gMTsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9j
b21JRChjbWQsIGRldi0+Y29tSUQpOworCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07
CisJbGt1bCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKwlpZiAoYnVpbGRfbG9j
a2luZ19yYW5nZShscl9idWZmZXIsIHNpemVvZihscl9idWZmZXIpLCBkZXYtPmxyKSA8IDApIHsK
KwkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9ja2luZyByYW5nZVxuIiwgZGV2LT5kaXNrX25h
bWUpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlzd2l0Y2ggKGxrdWwtPmxfc3RhdGUpIHsK
KwljYXNlIE9QQUxfUk86CisJCXJlYWRfbG9ja2VkID0gMDsKKwkJd3JpdGVfbG9ja2VkID0gMTsK
KwkJYnJlYWs7CisJY2FzZSBPUEFMX1JXOgorCQlyZWFkX2xvY2tlZCA9IDA7CisJCXdyaXRlX2xv
Y2tlZCA9IDA7CisJCWJyZWFrOworCWNhc2UgT1BBTF9MSzoKKwkJLyogdmFycyBhcmUgaW5pdGFs
aXplZCB0byBsb2NrZWQgKi8KKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJcHJfZXJyKCJUcmllZCB0
byBzZXQgYW4gaW52YWxpZCBsb2NraW5nIHN0YXRlLlxuIik7CisJCXJldHVybiAxOworCX0KKwor
CXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnNjIDNjIDRjIDRjIDRjIDRjIDNj
IiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICBscl9idWZmZXIsIE9QQUxfVUlEX0xFTkdU
SCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisJCQkJICAgIE9QQUxfU1RB
UlRMSVNULAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1ZBTFVFUywK
KwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJ
ICAgIE9QQUxfUkVBRExPQ0tFTkFCTEVELAorCQkJCSAgICBPUEFMX1RSVUUsCisJCQkJICAgIE9Q
QUxfRU5ETkFNRSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9XUklU
RUxPQ0tFTkFCTEVELAorCQkJCSAgICBPUEFMX1RSVUUsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwK
KworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9SRUFETE9DS0VELAorCQkJ
CSAgICByZWFkX2xvY2tlZCwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxf
U1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1dSSVRFTE9DS0VELAorCQkJCSAgICB3cml0ZV9sb2Nr
ZWQsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKworCQkJCSAgICBPUEFMX0VORExJU1QsCisJCQkJ
ICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKwlpZiAocmV0IDwgMCkg
eworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBTRVQgY29tbWFuZC5cbiIsIGRldi0+ZGlz
a19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRl
diwgY21kLCBnZW5lcmljX2NvbnQpOworfQorCitpbnQgYWN0aXZhdGVfbHNwKHN0cnVjdCBvcGFs
X2RldiAqZGV2KQoreworCXU4IHVzZXJfbHJbT1BBTF9VSURfTEVOR1RIXTsKKwljb25zdCB1OCAq
bWV0aG9kLCAqdWlkOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisJc2l6ZV90
IHVpbnRfMyA9IDB4ODM7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisKKwljbGVhcl9vcGFsX2NtZChj
bWQpOworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCisJdWlkID0gT1BBTFVJRFtPUEFM
X0xPQ0tJTkdTUF9VSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9BQ1RJVkFURV07CisK
KwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIiwKKwkJCQkgICAgT1BBTF9D
QUxMLAorCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFM
X01FVEhPRF9MRU5HVEgpOworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1
aWxkaW5nIEFjdGl2YXRlIExvY2tpbmdTUCBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlz
a19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisJLyogQWN0aXZhdGluZyBhcyBTVU0gKi8KKwlp
ZiAoZGV2LT5sciA+IDApIHsKKwkJcmV0ID0gYnVpbGRfbG9ja2luZ19yYW5nZSh1c2VyX2xyLCBz
aXplb2YodXNlcl9sciksIGRldi0+bHIpOworCQlpZiAocmV0IDwgMCkgeworCQkJcHJfZXJyKCIl
czogQ2FuJ3QgYnVpbGQgbG9ja2luZyB1c2VyXG4iLAorCQkJICAgICAgIGRldi0+ZGlza19uYW1l
KTsKKwkJCXJldHVybiByZXQ7CisJCX0KKwkJdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgIjJj
IDRjIGNzYyAyYyIsCisJCQkJICAgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgICAgT1BBTF9T
VEFSVE5BTUUsCisKKwkJCQkgICAgICB1aW50XzMsCisJCQkJICAgICAgT1BBTF9USU5ZX1VJTlRf
MDYsCisJCQkJICAgICAgT1BBTF9USU5ZX1VJTlRfMDAsCisJCQkJICAgICAgT1BBTF9USU5ZX1VJ
TlRfMDAsCisKKwkJCQkgICAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAgICB1c2VyX2xyLCBP
UEFMX1VJRF9MRU5HVEgsCisJCQkJICAgICAgT1BBTF9FTkRMSVNULAorCisJCQkJICAgICAgT1BB
TF9FTkROQU1FLAorCQkJCSAgICAgIE9QQUxfRU5ETElTVCk7CisJfSBlbHNlIC8qIEFjdGlhdmUg
Tm9ybWFsIE1vZGUgKi8KKwkJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgIjJjIiwK
KwkJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlm
IChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEFjdGl2YXRlIExvY2tp
bmdTUCBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJl
dDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29u
dCk7Cit9CisKK3N0YXRpYyBpbnQgZ2V0X2xzcF9saWZlY3ljbGVfY29udCh2b2lkICpkYXRhKQor
eworCXN0cnVjdCBvcGFsX2RldiAqZGV2ID0gZGF0YTsKKwl1OCBsY19zdGF0dXM7CisJaW50IGVy
cm9yID0gMDsKKworCWVycm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhkZXYpOworCWlmIChl
cnJvcikKKwkJZ290byBlcnJfcmV0dXJuOworCisJbGNfc3RhdHVzID0gcmVzcG9uc2VfZ2V0X3U2
NCgmZGV2LT5wYXJzZWQsIDQpOworCS8qIDB4MDggaXMgTWFudWZhY3VyZWQgSW5hY3RpdmUgKi8K
KwkvKiAweDA5IGlzIE1hbnVmYWN0dXJlZCAqLworCWlmIChsY19zdGF0dXMgIT0gMHgwOCkgewor
CQlwcl9lcnIoIiVzOiBDb3VsZG4ndCBkZXRlcm1pbmUgdGhlIHN0YXR1cyBvZiB0aGUgTGlmY3lj
bGUgc3RhdGVcbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCWVycm9yID0gLUVOT0RF
VjsKKwkJZ290byBlcnJfcmV0dXJuOworCX0KKworZXJyX3JldHVybjoKKwlyZXR1cm4gZXJyb3I7
Cit9CisKKy8qIERldGVybWluZSBpZiB3ZSdyZSBpbiB0aGUgTWFudWZhY3R1cmVkIEluYWN0aXZl
IG9yIEFjdGl2ZSBzdGF0ZSAqLworaW50IGdldF9sc3BfbGlmZWN5Y2xlKHN0cnVjdCBvcGFsX2Rl
diAqZGV2KQoreworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWNvbnN0IHU4ICptZXRob2QsICp1
aWQ7CisJaW50IHJldDsKKworCWNtZCA9ICZkZXYtPmNtZDsKKworCWNsZWFyX29wYWxfY21kKGNt
ZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwl1aWQgPSBPUEFMVUlEW09QQUxf
TE9DS0lOR1NQX1VJRF07CisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0dFVF07CisKKwlyZXQg
PSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDJjIDRjIDRjIDJjIiwKKwkJCQkgICAg
T1BBTF9DQUxMLAorCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9k
LCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAg
IE9QQUxfU1RBUlRMSVNULAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFM
X1RJTllfVUlOVF8wMywgLyogU3RhcnQgQ29sdW1uICovCisJCQkJICAgIE9QQUxfVElOWV9VSU5U
XzA2LCAvKiBMaWZjeWNsZSBDb2x1bW4gKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJ
ICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wNCwgLyogRW5kIENv
bHVtbiAqLworCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wNiwgLyogTGlmZWN5Y2xlIENvbHVtbiAq
LworCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9FTkRMSVNULAorCQkJCSAg
ICBPUEFMX0VORExJU1QpOworCisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3Ig
QnVpbGRpbmcgR0VUIExpZmVjeWNsZSBTdGF0dXMgY29tbWFuZFxuIiwKKwkJICAgICAgIGRldi0+
ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3Nl
bmQoZGV2LCBjbWQsIGdldF9sc3BfbGlmZWN5Y2xlX2NvbnQpOworfQorCitzdGF0aWMgaW50IGdl
dF9tc2lkX2NwaW5fcGluX2NvbnQodm9pZCAqZGF0YSkKK3sKKwljb25zdCBjaGFyICptc2lkX3Bp
bjsKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJc2l6ZV90IHN0cmxlbjsKKwlpbnQg
ZXJyb3IgPSAwOworCisJZXJyb3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7CisJaWYg
KGVycm9yKQorCQlnb3RvIGVycl9yZXR1cm47CisKKwlzdHJsZW4gPSByZXNwb25zZV9nZXRfc3Ry
aW5nKCZkZXYtPnBhcnNlZCwgNCwgJm1zaWRfcGluKTsKKwlpZiAoIW1zaWRfcGluKSB7CisJCXBy
X2VycigiJXM6IENvdWxkbid0IGV4dHJhY3QgUElOIGZyb20gcmVzcG9uc2VcbiIsIF9fZnVuY19f
KTsKKwkJZXJyb3IgPSAxOworCQlnb3RvIGVycl9yZXR1cm47CisJfQorCisJZGV2LT5wcmV2X2Rh
dGEgPSBrbWVtZHVwKG1zaWRfcGluLCBzdHJsZW4sIEdGUF9LRVJORUwpOworCWlmICghZGV2LT5w
cmV2X2RhdGEpIHsKKwkJZXJyb3IgPSAtRU5PTUVNOworCQlnb3RvIGVycl9yZXR1cm47CisJfQor
CisJZGV2LT5wcmV2X2RfbGVuID0gc3RybGVuOworCisgZXJyX3JldHVybjoKKwlyZXR1cm4gZXJy
b3I7Cit9CisKK3N0YXRpYyBpbnQgZ2V0X21zaWRfY3Bpbl9waW4oc3RydWN0IG9wYWxfZGV2ICpk
ZXYpCit7CisJY29uc3QgdTggKm1ldGhvZCwgKnNtdWlkOworCWludCByZXQ7CisJc3RydWN0IG9w
YWxfY21kICpjbWQ7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsK
KwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKworCXNtdWlkID0gT1BBTFVJRFtPUEFMX0Nf
UElOX01TSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRVRdOworCisJcmV0ID0gdGVz
dF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMgMnMgMTJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAor
CisJCQkJICAgIHNtdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9N
RVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBPUEFMX1NU
QVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9VSU5U
XzAzLCAvKiBTYXJ0IENvbHVtbiAqLworCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElO
ICovCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJ
ICAgIE9QQUxfVElOWV9VSU5UXzA0LCAvKiBFbmQgQ29sdW1uICovCisJCQkJICAgIE9QQUxfVElO
WV9VSU5UXzAzLCAvKiBQSU4gKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCQkJCSAgICBPUEFM
X0VORExJU1QsCisJCQkJICAgIE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlw
cl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBHZXQgTVNJRCBDUElOIFBJTiBjb21tYW5kLlxuIiwK
KwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4g
ZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdldF9tc2lkX2NwaW5fcGluX2NvbnQpOworfQor
CitzdGF0aWMgdm9pZCB1bmxvY2tfc3VzcGVuZF9maW5hbChzdHJ1Y3Qgb3BhbF9kZXYgKmRldikK
K3sKKwlkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQgPSBmYWxzZTsKKwlkZXYtPnJlc3VtZV9kYXRh
ID0gTlVMTDsKKwlkZXYtPmZ1bmNfZGF0YSA9IE5VTEw7Cit9CisKK3N0YXRpYyBpbnQgYnVpbGRf
ZW5kX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlzdHJ1Y3Qgb3BhbF9j
bWQgKmNtZDsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCisJ
c2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisJcmV0dXJuIHRlc3RfYW5kX2FkZF90b2tlbl91
OChjbWQsIE9QQUxfRU5ET0ZTRVNTSU9OKTsKK30KKworc3RhdGljIGludCBlbmRfb3BhbF9zZXNz
aW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCWludCByZXQgPSBidWlsZF9lbmRfb3BhbF9z
ZXNzaW9uKGRldik7CisKKwlpZiAocmV0IDwgMCkKKwkJcmV0dXJuIHJldDsKKwlyZXR1cm4gZmlu
YWxpemVfYW5kX3NlbmQoZGV2LCAmZGV2LT5jbWQsIGVuZF9zZXNzaW9uX2NvbnQpOworfQorCitz
dGF0aWMgc3RydWN0IG9wYWxfZGV2ICpmaW5kX29wYWxfZGV2KGRldl90IG1ham1pbiwgdTggbHIp
Cit7CisJc3RydWN0IG9wYWxfZGV2ICppdGVyLCAqb3BhbF9kZXYgPSBOVUxMOworCisJbGlzdF9m
b3JfZWFjaF9lbnRyeShpdGVyLCAmb3BhbF9saXN0LCBub2RlKSB7CisJCWlmIChNQUpPUihpdGVy
LT5tYWptaW4pICE9IE1BSk9SKG1ham1pbikgfHwKKwkJICAgIE1JTk9SKGl0ZXItPm1ham1pbikg
IT0gTUlOT1IobWFqbWluKSkKKwkJCWNvbnRpbnVlOworCisJCWlmIChpdGVyLT5sciA9PSBscikg
eworCQkJb3BhbF9kZXYgPSBpdGVyOworCQkJYnJlYWs7CisJCX0KKwl9CisJcmV0dXJuIG9wYWxf
ZGV2OworfQorCitzdGF0aWMgaW50IHVwZGF0ZV9vcGFsX2RldihzdHJ1Y3Qgb3BhbF9kZXYgKm9s
ZF9kZXYsIHN0cnVjdCBvcGFsX2RldiAqbmV3X2RldikKK3sKKwlpZiAoIWF0b21pY19hZGRfdW5s
ZXNzKCZvbGRfZGV2LT5pbl91c2UsIDEsIDEpKSB7CisJCXByX2VycigiJXM6IGRldiB3YXMgaW4g
dXNlXG4iLCBfX2Z1bmNfXyk7CisJCXJldHVybiAtRUJVU1k7CisJfQorCisJb2xkX2Rldi0+a2V5
X25hbWVfbGVuID0gbmV3X2Rldi0+a2V5X25hbWVfbGVuOworCWlmICghbWVtY3B5KG9sZF9kZXYt
PmtleV9uYW1lLCBuZXdfZGV2LT5rZXlfbmFtZSwgb2xkX2Rldi0+a2V5X25hbWVfbGVuKSkgewor
CQlwcl9lcnIoIiVzOiBFcnJvciB1cGRhdGluZyBkZXZpY2U6XG4iLCBvbGRfZGV2LT5kaXNrX25h
bWUpOworCQlyZXR1cm4gLUVGQVVMVDsKKwl9CisKKwlpZiAoIXN0cm5jcHkob2xkX2Rldi0+ZGlz
a19uYW1lLCBuZXdfZGV2LT5kaXNrX25hbWUsIERJU0tfTkFNRV9MRU4pKSB7CisJCXByX2Vycigi
JXM6IEVycm9yIHJlZ2lzdGVyaW5nIGRldmljZTogY29weWluZyBkaXNrIG5hbWVcbiIsCisJCSAg
ICAgICBvbGRfZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVGQVVMVDsKKwl9CisKKwlvbGRf
ZGV2LT5jb21JRCA9IG5ld19kZXYtPmNvbUlEOworCW9sZF9kZXYtPnN0YXJ0ID0gbmV3X2Rldi0+
c3RhcnQ7CisJb2xkX2Rldi0+bGVuZ3RoID0gbmV3X2Rldi0+bGVuZ3RoOworCW9sZF9kZXYtPmFs
aWduID0gbmV3X2Rldi0+YWxpZ247CisJb2xkX2Rldi0+bG93ZXN0X2xiYSA9IG5ld19kZXYtPmxv
d2VzdF9sYmE7CisJb2xkX2Rldi0+c3RhdGUgPSBuZXdfZGV2LT5zdGF0ZTsKKwlvbGRfZGV2LT5m
dW5jcyA9IG5ld19kZXYtPmZ1bmNzOworCW9sZF9kZXYtPm1ham1pbiA9IG5ld19kZXYtPm1ham1p
bjsKKwlvbGRfZGV2LT5zdWJtaXRfZm4gPSBuZXdfZGV2LT5zdWJtaXRfZm47CisJb2xkX2Rldi0+
c3VibWl0X2RhdGEgPSBuZXdfZGV2LT5zdWJtaXRfZGF0YTsKKworCWNsZWFuX2Z1bmN0aW9uX2Rh
dGEob2xkX2Rldik7CisKKwkvKgorCSAqIFdvbid0IGJlIGFibGUgdG8gYXV0byB1bmxvY2sgdGhp
cyBsb2NraW5nIHJhbmdlIGJhc2VkIG9uIGJsb2NrCisJICogcmVxdWVzdGVzLgorCSAqLworCWlm
IChvbGRfZGV2LT5sZW5ndGggPT0gMCkKKwkJcHJfd2FybigiJXM6IE1pc3NpbmcgYmxvY2sgaW5m
b3JtYXRpb24gZm9yIGxvY2tpbmcgcmFuZ2UgJWRcbiIsCisJCQlvbGRfZGV2LT5kaXNrX25hbWUs
IG9sZF9kZXYtPmxyKTsKKworCXJldHVybiAwOworfQorCitpbnQgb3BhbF9yZWdpc3Rlcl9jb250
KHN0cnVjdCBvcGFsX2RldiAqbmV3X2RldikKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKm9sZF9kZXY7
CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKwlpbnQgZXJyb3IgPSAwOworCisJc3Bpbl9sb2NrX2ly
cXNhdmUoJmxpc3Rfc3BpbmxvY2ssIGZsYWdzKTsKKworCW9sZF9kZXYgPSBmaW5kX29wYWxfZGV2
KG5ld19kZXYtPm1ham1pbiwgbmV3X2Rldi0+bHIpOworCWlmICghb2xkX2RldikgeworCQlsaXN0
X2FkZF90YWlsKCZuZXdfZGV2LT5ub2RlLCAmb3BhbF9saXN0KTsKKwkJb2xkX2RldiA9IG5ld19k
ZXY7CisJfSBlbHNlIHsKKwkJaWYgKG9sZF9kZXYgPT0gbmV3X2RldikKKwkJCWVycm9yID0gMDsK
KwkJZWxzZSB7CisJCQllcnJvciA9IHVwZGF0ZV9vcGFsX2RldihvbGRfZGV2LCBuZXdfZGV2KTsK
KwkJCWNsZWFuX29wYWxfa2V5KG5ld19kZXYpOworCQkJa2ZyZWUobmV3X2Rldik7CisJCX0KKwl9
CisKKwlpZiAoZXJyb3IpCisJCWxpc3RfZGVsKCZvbGRfZGV2LT5ub2RlKTsKKworCXNwaW5fdW5s
b2NrX2lycXJlc3RvcmUoJmxpc3Rfc3BpbmxvY2ssIGZsYWdzKTsKKworCWlmICghZXJyb3IpCisJ
CXByX2luZm8oIiVzOiBSZWdpc3RlcmVkIGtleSBmb3IgbG9ja2luZyByYW5nZTogJWRcbiIsCisJ
CQlvbGRfZGV2LT5kaXNrX25hbWUsIG9sZF9kZXYtPmxyKTsKKworCXJldHVybiBlcnJvcjsKK30K
KworY29uc3Qgb3BhbF9zdGVwIGVycm9yX2VuZF9zZXNzaW9uW10gPSB7CisJZW5kX29wYWxfc2Vz
c2lvbiwKKwlOVUxMLAorfTsKK3N0YXRpYyBpbnQgZW5kX29wYWxfc2Vzc2lvbl9lcnJvcihzdHJ1
Y3Qgb3BhbF9kZXYgKmRldikKK3sKKworCWRldi0+ZnVuY3MgPSBlcnJvcl9lbmRfc2Vzc2lvbjsK
KwlkZXYtPnN0YXRlID0gMDsKKwlkZXYtPmVycm9yX2NiID0gTlVMTDsKKwlyZXR1cm4gbmV4dChk
ZXYpOworfQorCitzdGF0aWMgc3RydWN0IG9wYWxfZGV2ICphbGxvY19vcGFsX2RldihzdHJ1Y3Qg
YmxvY2tfZGV2aWNlICpiZGV2LCB1OCBscikKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKm9wYWxfZGV2
OworCXN0cnVjdCByZXF1ZXN0X3F1ZXVlICpxOworCXVuc2lnbmVkIGxvbmcgZG1hX2FsaWduOwor
CWNvbnN0IGNoYXIgKmRpc2tfbmFtZTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0
OworCisJb3BhbF9kZXYgPSBremFsbG9jKHNpemVvZigqb3BhbF9kZXYpLCBHRlBfS0VSTkVMKTsK
KwlpZiAoIW9wYWxfZGV2KQorCQlyZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKKworCW9wYWxfZGV2
LT5tYWptaW4gPSBiZGV2LT5iZF9kZXY7CisJb3BhbF9kZXYtPmxyID0gbHI7CisJY21kID0gJm9w
YWxfZGV2LT5jbWQ7CisJY21kLT5jbWQgPSBjbWQtPmNtZF9idWY7CisJY21kLT5yZXNwID0gY21k
LT5yZXNwX2J1ZjsKKworCWRpc2tfbmFtZSA9IGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZTsKKwlp
ZiAoIXN0cm5jcHkob3BhbF9kZXYtPmRpc2tfbmFtZSwgZGlza19uYW1lLCBESVNLX05BTUVfTEVO
KSkgeworCQlwcl9lcnIoIiVzOiBFcnJvciByZWdpc3RlcmluZyBkZXZpY2U6IGNvcHlpbmcgZGlz
ayBuYW1lXG4iLAorCQkgICAgICAgZGlza19uYW1lKTsKKwkJcmV0ID0gLUVGQVVMVDsKKwkJZ290
byBlcnJfZnJlZV9kZXY7CisJfQorCisJcSA9IGJkZXYtPmJkX3F1ZXVlOworCWRtYV9hbGlnbiA9
IChxdWV1ZV9kbWFfYWxpZ25tZW50KHEpIHwgcS0+ZG1hX3BhZF9tYXNrKSArIDE7CisJY21kLT5j
bWQgPSAodTggKilyb3VuZF91cCgodWludHB0cl90KWNtZC0+Y21kLCBkbWFfYWxpZ24pOworCWNt
ZC0+cmVzcCA9ICh1OCAqKXJvdW5kX3VwKCh1aW50cHRyX3QpY21kLT5yZXNwLCBkbWFfYWxpZ24p
OworCisJSU5JVF9MSVNUX0hFQUQoJm9wYWxfZGV2LT5ub2RlKTsKKwlhdG9taWNfc2V0KCZvcGFs
X2Rldi0+aW5fdXNlLCAxKTsKKworCW9wYWxfZGV2LT5zdGF0ZSA9IDA7CisKKwlyZXR1cm4gb3Bh
bF9kZXY7CisKK2Vycl9mcmVlX2RldjoKKwlrZnJlZShvcGFsX2Rldik7CisJcmV0dXJuIEVSUl9Q
VFIocmV0KTsKK30KKworaW50IG9wYWxfcmVnaXN0ZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRl
diwgc3RydWN0IG9wYWxfa2V5ICprZXlfY21kLAorCQkgIGNvbnN0IG9wYWxfc3RlcCAqZnVuY3Ms
IHZvaWQgKnNibXRfZGF0YSwKKwkJICBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKQoreworCXN0
cnVjdCBvcGFsX2RldiAqbmV3X2RldiA9IE5VTEw7CisJdTgga2V5X2xlbiA9IGtleV9jbWQtPmtl
eV9sZW47CisJdTggbHIgPSBrZXlfY21kLT5scjsKKwlpbnQgcmV0OworCisJbmV3X2RldiA9IGFs
bG9jX29wYWxfZGV2KGJkZXYsIGxyKTsKKwlpZiAoSVNfRVJSKG5ld19kZXYpKSB7CisJCXByX2Vy
cigiJXM6IEVycm9yIHJlZ2lzdGVyaW5nIGRldmljZTogYWxsb2NhdGlvblxuIiwKKwkJICAgICAg
IGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZSk7CisJCXJldHVybiBQVFJfRVJSKG5ld19kZXYpOwor
CX0KKworCWlmICghbWVtY3B5KG5ld19kZXYtPmtleV9uYW1lLCBrZXlfY21kLT5rZXksIGtleV9s
ZW4pKSB7CisJCXByX2VycigiJXM6IEVycm9yIHJlZ2lzdGVyaW5nIGtleTogY291bGRuJ3QgY29w
eSBrZXlcbiIsCisJCSAgICAgICBuZXdfZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVGQVVM
VDsKKwl9CisKKwluZXdfZGV2LT5rZXlfbmFtZV9sZW4gPSBrZXlfbGVuOworCW5ld19kZXYtPmtl
eV90eXBlID0ga2V5X2NtZC0+a2V5X3R5cGU7CisJcmV0ID0gZ2V0X29wYWxfa2V5KG5ld19kZXYp
OworCWlmIChyZXQpIHsKKwkJcHJfZXJyKCIlczogQ291bGRuJ3QgZ2V0IGtleTogJWRcbiIsIG5l
d19kZXYtPmRpc2tfbmFtZSwgcmV0KTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwluZXdfZGV2LT5m
dW5jcyA9IGZ1bmNzOworCW5ld19kZXYtPnN1Ym1pdF9kYXRhID0gc2JtdF9kYXRhOworCW5ld19k
ZXYtPnN1Ym1pdF9mbiA9IHN1Ym1pdF9mbjsKKworCW5ld19kZXYtPnN0YXRlID0gMDsKKwlyZXR1
cm4gbmV4dChuZXdfZGV2KTsKK30KKworc3RhdGljIHN0cnVjdCBvcGFsX2RldiAqZ2V0X3JlZ2lz
dGVyZWRfb3BhbF9kZXYoZGV2X3QgbWFqbWluLCB1OCBscikKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYg
Kml0ZXIsICpkZXYgPSBOVUxMOworCXVuc2lnbmVkIGxvbmcgZmxhZ3M7CisJYm9vbCBpbl91c2Ug
PSBmYWxzZTsKKworCXNwaW5fbG9ja19pcnFzYXZlKCZsaXN0X3NwaW5sb2NrLCBmbGFncyk7CisJ
bGlzdF9mb3JfZWFjaF9lbnRyeShpdGVyLCAmb3BhbF9saXN0LCBub2RlKSB7CisJCWlmIChNQUpP
UihpdGVyLT5tYWptaW4pICE9IE1BSk9SKG1ham1pbikgfHwKKwkJICAgIE1JTk9SKGl0ZXItPm1h
am1pbikgIT0gTUlOT1IobWFqbWluKSkKKwkJCWNvbnRpbnVlOworCQlpZiAoaXRlci0+bHIgPT0g
bHIpIHsKKwkJCWRldiA9IGl0ZXI7CisJCQlpZiAoIWF0b21pY19hZGRfdW5sZXNzKCZpdGVyLT5p
bl91c2UsIDEsIDEpKSB7CisJCQkJZGV2ID0gTlVMTDsKKwkJCQlpbl91c2UgPSB0cnVlOworCQkJ
fQorCQkJYnJlYWs7CisJCX0KKwl9CisKKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZsaXN0X3Nw
aW5sb2NrLCBmbGFncyk7CisKKwlpZiAoIWRldikKKwkJcmV0dXJuIE5VTEw7CisKKwlyZXR1cm4g
ZGV2OworfQorCisvKiBGcmVlIHVwIHRoZSBPcGFsIGRldiBhbmQgaXRzIGtleXMgZHVyaW5nIHR3
byBzY2VuYXJpb3M6CisgKgorICogMSkgV2hlbiBhIGNvbW1hbmQgaXMgY29tcGxldGUgdGhhdCBu
byBsb25nZXIgcmVxdWlyZXMKKyAqICAgIHRoZSBvcGFsIGRldiB0byBiZSBhcm91bmQuCisgKiAy
KSBXaGVuIGEgY29tbWFuZCwgaW5jbHVkaW5nIE9wYWwgU2F2ZSBmYWlscyB3ZSBjbGVhbgorICog
ICAgYW5kIGZyZWUgdGhlIG9wYWwgZGV2LgorICoKKyAqICAgIElmIHdlIGZpbmQgdGhlIG9wYWwg
ZGV2IHN0cnVjdHVyZSBpbiB0aGUgbGlzdCBvZgorICogICAgc2F2ZWQgcGFzc3dvcmRzIHdlIHdp
bGwgKm5vdCogcmVtb3ZlIGl0LgorICovCitzdGF0aWMgdm9pZCByZW1vdmVfYW5kX2NsZWFuX29w
YWxfZGV2KHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXN0cnVjdCBvcGFsX2RldiAqaXRlcjsK
Kwlib29sIGZvdW5kID0gZmFsc2U7CisKKwlhdG9taWNfZGVjKCZkZXYtPmluX3VzZSk7CisJc3Bp
bl9sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGl0ZXIsICZvcGFs
X2xpc3QsIG5vZGUpIHsKKwkJaWYgKGl0ZXIgPT0gZGV2KSB7CisJCQlmb3VuZCA9IHRydWU7CisJ
CQlicmVhazsKKwkJfQorCX0KKworCXNwaW5fdW5sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKwlpZiAo
IWZvdW5kKSB7CisJCWNsZWFuX29wYWxfa2V5KGRldik7CisJCWNsZWFuX2Z1bmN0aW9uX2RhdGEo
ZGV2KTsKKwkJa2ZyZWUoZGV2KTsKKwl9Cit9CisKK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9kZXYgKmdl
dF9vcl9jcmVhdGVfb3BhbF9kZXYoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCQkJICAg
ICAgIHU4IGxyLCBib29sIHVzZV9uZXcpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBOVUxM
OworCisJaWYgKCF1c2VfbmV3KQorCQlkZXYgPSBnZXRfcmVnaXN0ZXJlZF9vcGFsX2RldihiZGV2
LT5iZF9kZXYsIGxyKTsKKworCWlmICghZGV2KQorCQlkZXYgPSBhbGxvY19vcGFsX2RldihiZGV2
LCBscik7CisKKwlyZXR1cm4gZGV2OworfQorCitzdGF0aWMgaW50IHNldHVwX29wYWxfZGV2KHN0
cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsICBzdHJ1Y3Qgb3BhbF9kZXYgKmRldiwKKwkJCSAgY29u
c3Qgb3BhbF9zdGVwICpmdW5jcywgIHN0cnVjdCBvcGFsX2tleSAqa2V5LAorCQkJICB2b2lkICpz
Ym10X2RhdGEsICBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKQoreworCWludCByZXQ7CisKKwlk
ZXYtPnN0YXRlID0gMDsKKwlkZXYtPmZ1bmNzID0gZnVuY3M7CisJZGV2LT5UU04gPSAwOworCWRl
di0+SFNOID0gMDsKKwlkZXYtPmxyID0ga2V5LT5scjsKKwlkZXYtPmVycm9yX2NiID0gZW5kX29w
YWxfc2Vzc2lvbl9lcnJvcjsKKwlkZXYtPmVycm9yX2NiX2RhdGEgPSBkZXY7CisJZGV2LT5zdWJt
aXRfZm4gPSBzdWJtaXRfZm47CisJZGV2LT5zdWJtaXRfZGF0YSA9IHNibXRfZGF0YTsKKworCWlm
IChrZXkpIHsKKwkJbWVtY3B5KGRldi0+a2V5X25hbWUsIGtleS0+a2V5LCBrZXktPmtleV9sZW4p
OworCQlkZXYtPmtleV9uYW1lX2xlbiA9IGtleS0+a2V5X2xlbjsKKwkJZGV2LT5rZXlfdHlwZSA9
IGtleS0+a2V5X3R5cGU7CisKKwkJcmV0ID0gZ2V0X29wYWxfa2V5KGRldik7CisJCWlmIChyZXQp
IHsKKwkJCXByX2VycigiJXM6IENvdWxkbid0IGdldCBrZXk6ICVkXG4iLAorCQkJICAgICAgIGRl
di0+ZGlza19uYW1lLCByZXQpOworCQkJcmV0dXJuIHJldDsKKwkJfQorCX0KKwlkZXYtPmZ1bmNf
ZGF0YSA9IE5VTEw7CisJcmV0dXJuIDA7Cit9CisKK2ludCBvcGFsX3NlY3VyZV9lcmFzZV9sb2Nr
aW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXks
CisJCQkJICAgIHZvaWQgKnNibXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbikKK3sK
KwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKKwl2b2lkICpkYXRhWzNdID0geyBOVUxMIH07CisJY29u
c3Qgb3BhbF9zdGVwIGVyYXNlX2Z1bmNzW10gPSB7CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3Rh
cnRfYXV0aF9vcGFsX3Nlc3Npb24sCisJCWdldF9hY3RpdmVfa2V5LAorCQlnZW5fa2V5LAorCQll
bmRfb3BhbF9zZXNzaW9uLAorCQlOVUxMLAorCX07CisJaW50IHJldDsKKworCWRldiA9IGdldF9v
cl9jcmVhdGVfb3BhbF9kZXYoYmRldiwga2V5LT5vcGFsX2FjdC5rZXkubHIsIHRydWUpOworCWlm
ICghZGV2KQorCQlyZXR1cm4gLUVOT01FTTsKKworCXJldCA9IHNldHVwX29wYWxfZGV2KGJkZXYs
IGRldiwgZXJhc2VfZnVuY3MsICZrZXktPm9wYWxfYWN0LmtleSwKKwkJCSAgICAgc2JtdF9kYXRh
LCBzdWJtaXRfZm4pOworCWRldi0+ZnVuY19kYXRhID0gZGF0YTsKKwlkZXYtPmZ1bmNfZGF0YVsx
XSA9ICZrZXktPm9wYWxfYWN0LndobzsKKwlpZiAocmV0KQorCQlnb3RvIGVycm9yX3JldHVybjsK
KworCXJldCA9IG5leHQoZGV2KTsKKworIGVycm9yX3JldHVybjoKKwlyZW1vdmVfYW5kX2NsZWFu
X29wYWxfZGV2KGRldik7CisJcmV0dXJuIHJldDsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF9zZWN1
cmVfZXJhc2VfbG9ja2luZ19yYW5nZSk7CisKK2ludCBvcGFsX2VyYXNlX2xvY2tpbmdfcmFuZ2Uo
c3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSwKKwkJCSAgICAg
dm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKQoreworCXN0cnVjdCBv
cGFsX2RldiAqZGV2OworCWNvbnN0IG9wYWxfc3RlcCBlcmFzZV9mdW5jc1tdID0geworCQlvcGFs
X2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAorCQllcmFzZV9sb2NraW5n
X3JhbmdlLAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlOVUxMLAorCX07CisJaW50IHJldDsKKwor
CWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwga2V5LT5vcGFsX2xycy5rZXkubHIs
IHRydWUpOworCWlmICghZGV2KQorCQlyZXR1cm4gLUVOT01FTTsKKworCXJldCA9IHNldHVwX29w
YWxfZGV2KGJkZXYsIGRldiwgZXJhc2VfZnVuY3MsICZrZXktPm9wYWxfbHJzLmtleSwKKwkJCSAg
ICAgc2JtdF9kYXRhLCBzdWJtaXRfZm4pOworCWlmIChyZXQpCisJCWdvdG8gZXJyb3JfcmV0dXJu
OworCisJcmV0ID0gbmV4dChkZXYpOworCisgZXJyb3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xl
YW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworfQorRVhQT1JUX1NZTUJPTChvcGFsX2Vy
YXNlX2xvY2tpbmdfcmFuZ2UpOworCitpbnQgb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFkb3dfbWJy
KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkJICAgc3RydWN0IHNlZF9rZXkgKmtleSwg
dm9pZCAqc2JtdF9kYXRhLAorCQkJCSAgIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pCit7CisJ
dm9pZCAqZnVuY19kYXRhWzZdID0geyBOVUxMIH07CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7CisJ
Y29uc3Qgb3BhbF9zdGVwIG1icl9mdW5jc1tdID0geworCQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0
YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24sCisJCXNldF9tYnJfZG9uZSwKKwkJZW5kX29wYWxf
c2Vzc2lvbiwKKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxfc2Vzc2lvbiwKKwkJc2V0X21icl9lbmFi
bGVfZGlzYWJsZSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJTlVMTCwKKwl9OworCWludCByZXQ7
CisKKwlpZiAoa2V5LT5vcGFsX21ici5lbmFibGVfZGlzYWJsZSAhPSBPUEFMX01CUl9FTkFCTEUg
JiYKKwkgICAga2V5LT5vcGFsX21ici5lbmFibGVfZGlzYWJsZSAhPSBPUEFMX01CUl9ESVNBQkxF
KQorCQlyZXR1cm4gLUVJTlZBTDsKKworCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRl
diwga2V5LT5vcGFsX21ici5rZXkubHIsIHRydWUpOworCWlmICghZGV2KQorCQlyZXR1cm4gLUVO
T01FTTsKKworCXJldCA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwgbWJyX2Z1bmNzLCAma2V5
LT5vcGFsX21ici5rZXksCisJCQkgICAgIHNibXRfZGF0YSwgc3VibWl0X2ZuKTsKKwlpZiAocmV0
KQorCQlnb3RvIGVycm9yX3JldHVybjsKKworCWRldi0+bnVtX2Z1bmNfZGF0YSA9IDY7CisJZGV2
LT5mdW5jX2RhdGEgPSBmdW5jX2RhdGE7CisJZGV2LT5mdW5jX2RhdGFbMl0gPSAma2V5LT5vcGFs
X21ici5lbmFibGVfZGlzYWJsZTsKKwlkZXYtPmZ1bmNfZGF0YVs1XSA9ICZrZXktPm9wYWxfbWJy
LmVuYWJsZV9kaXNhYmxlOworCisJcmV0ID0gbmV4dChkZXYpOworCisgZXJyb3JfcmV0dXJuOgor
CXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworCit9CitFWFBP
UlRfU1lNQk9MKG9wYWxfZW5hYmxlX2Rpc2FibGVfc2hhZG93X21icik7CisKK2ludCBvcGFsX3Nh
dmUoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSwKKwkgICAg
ICB2b2lkICpzYm10X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pCit7CisJdm9pZCAq
ZnVuY19kYXRhWzNdID0geyBOVUxMIH07CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7CisJCWNvbnN0
IG9wYWxfc3RlcCBfYXV0aF9mdW5jc1tdID0geworCQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0
X2F1dGhfb3BhbF9zZXNzaW9uLAorCQlxdWVyeV9sb2NraW5nX3JhbmdlLAorCQllbmRfb3BhbF9z
ZXNzaW9uLAorCQlvcGFsX3JlZ2lzdGVyX2NvbnQsCisJCU5VTEwKKwl9OworCWludCByZXQ7CisK
KwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJkZXYsIGtleS0+b3BhbF9sa191bmxrLmtl
eS5sciwgZmFsc2UpOworCWlmICghZGV2KQorCQlyZXR1cm4gLUVOT01FTTsKKwlyZXQgPSBzZXR1
cF9vcGFsX2RldihiZGV2LCBkZXYsIF9hdXRoX2Z1bmNzLCAma2V5LT5vcGFsX2xrX3VubGsua2V5
LAorCQkJICAgICBzYm10X2RhdGEsIHN1Ym1pdF9mbik7CisJaWYgKHJldCkKKwkJZ290byBlcnJv
cl9yZXR1cm47CisKKwlkZXYtPm51bV9mdW5jX2RhdGEgPSAzOworCWRldi0+ZnVuY19kYXRhID0g
ZnVuY19kYXRhOworCWRldi0+ZnVuY19kYXRhWzFdID0gJmtleS0+b3BhbF9sa191bmxrLmF1dGhv
cml0eTsKKwlkZXYtPmxrdWwgPSBrZXktPm9wYWxfbGtfdW5sazsKKworCXJldCA9IG5leHQoZGV2
KTsKKworIGVycm9yX3JldHVybjoKKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7CisJ
cmV0dXJuIHJldDsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF9zYXZlKTsKKworaW50IG9wYWxfYWRk
X3VzZXJfdG9fbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtl
eSwKKwkJCXZvaWQgKnNibXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbikKK3sKKwl2
b2lkICpmdW5jX2RhdGFbM10gPSB7IE5VTEwgfTsKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKKwkJ
Y29uc3Qgb3BhbF9zdGVwIGZ1bmNzW10gPSB7CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRf
YWRtaW4xTFNQX29wYWxfc2Vzc2lvbiwKKwkJYWRkX3VzZXJfdG9fbHIsCisJCWVuZF9vcGFsX3Nl
c3Npb24sCisJCU5VTEwKKwl9OworCWludCByZXQ7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJk
X2Rpc2spIHsKKwkJcHJfZXJyKCJDYW4ndCBhc3NpZ24gdXNlciB0byBMUiB3aXRob3V0IGJhY2tp
bmcgZGlza1xuIik7CisJCXJldHVybiAtRUZBVUxUOworCX0KKwlpZiAoa2V5LT5vcGFsX2xrX3Vu
bGsubF9zdGF0ZSAhPSBPUEFMX1JPICYmCisJICAgIGtleS0+b3BhbF9sa191bmxrLmxfc3RhdGUg
IT0gT1BBTF9SVykgeworCQlwcl9lcnIoIkxvY2tpbmcgc3RhdGUgd2FzIG5vdCBSTyBvciBSV1xu
Iik7CisJCXJldHVybiAtRUlOVkFMOworCX0KKwlpZiAoa2V5LT5vcGFsX2xrX3VubGsuYXV0aG9y
aXR5LndobyA8IE9QQUxfVVNFUjEgJiYKKwkgICAga2V5LT5vcGFsX2xrX3VubGsuYXV0aG9yaXR5
LndobyA+IE9QQUxfVVNFUjkpIHsKKwkJcHJfZXJyKCJBdXRob3JpdHkgd2FzIG5vdCB3aXRoaW4g
dGhlIHJhbmdlIG9mIHVzZXJzOiAlZFxuIiwKKwkJICAgICAgIGtleS0+b3BhbF9sa191bmxrLmF1
dGhvcml0eS53aG8pOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisJaWYgKGtleS0+b3BhbF9sa191
bmxrLmF1dGhvcml0eS5TVU0pIHsKKwkJcHJfZXJyKCIlcyBub3Qgc3VwcG9ydGVkIGluIFNVTS4g
VXNlIHNldHVwIGxvY2tpbmcgcmFuZ2VcbiIsCisJCSAgICAgICBfX2Z1bmNfXyk7CisJCXJldHVy
biAtRUlOVkFMOworCX0KKworCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwga2V5
LT5vcGFsX2xrX3VubGsua2V5LmxyLCB0cnVlKTsKKwlpZiAoIWRldikKKwkJcmV0dXJuIC1FTk9N
RU07CisJcmV0ID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBmdW5jcywgJmtleS0+b3BhbF9s
a191bmxrLmtleSwKKwkJCQkgICAgc2JtdF9kYXRhLCBzdWJtaXRfZm4pOworCWlmIChyZXQpCisJ
CWdvdG8gZXJyb3JfcmV0dXJuOworCisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYtPmZ1
bmNfZGF0YSA9IGZ1bmNfZGF0YTsKKwlkZXYtPmZ1bmNfZGF0YVsyXSA9ICZrZXktPm9wYWxfbGtf
dW5sazsKKworCXJldCA9IG5leHQoZGV2KTsKKworIGVycm9yX3JldHVybjoKKwlyZW1vdmVfYW5k
X2NsZWFuX29wYWxfZGV2KGRldik7CisJcmV0dXJuIHJldDsKKworfQorRVhQT1JUX1NZTUJPTChv
cGFsX2FkZF91c2VyX3RvX2xyKTsKKworaW50IG9wYWxfcmV2ZXJ0dHBlcihzdHJ1Y3QgYmxvY2tf
ZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorCQkgICAgdm9pZCAqc2JtdF9kYXRh
LCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKQoreworCWNvbnN0IG9wYWxfc3RlcCByZXZlcnRf
ZnVuY3NbXSA9IHsKKwkJb3BhbF9kaXNjb3ZlcnkwLAorCQlzdGFydF9TSURBU1Bfb3BhbF9zZXNz
aW9uLAorCQlyZXZlcnRfdHBlciwgLyogY29udHJvbGxlciB3aWxsIHRlcm1pbmF0ZSBzZXNzaW9u
ICovCisJCU5VTEwsCisJfTsKKworCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYsICZrZXktPm9w
YWwsIHJldmVydF9mdW5jcywKKwkJCSAgICAgc2JtdF9kYXRhLCBzdWJtaXRfZm4pOworfQorRVhQ
T1JUX1NZTUJPTChvcGFsX3JldmVydHRwZXIpOworCisvKiBUaGVzZSBhcmUgZ2xvYmFsJ2QgYmVj
YXVzZSBib3RoIGxvY2tfdW5sb2NrX2ludGVybmFsCisgKiBhbmQgb3BhbF91bmxvY2tfZnJvbV9z
dXNwZW5kIG5lZWQgdGhlbS4KKyAqLworY29uc3Qgb3BhbF9zdGVwIHVsa19mdW5jc19TVU1bXSA9
IHsKKwlvcGFsX2Rpc2NvdmVyeTAsCisJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCisJbG9ja191
bmxvY2tfbG9ja2luZ19yYW5nZV9TVU0sCisJZW5kX29wYWxfc2Vzc2lvbiwKKwlOVUxMCit9Owor
Y29uc3Qgb3BhbF9zdGVwIF91bmxvY2tfZnVuY3NbXSA9IHsKKwlvcGFsX2Rpc2NvdmVyeTAsCisJ
c3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCisJbG9ja191bmxvY2tfbG9ja2luZ19yYW5nZSwKKwll
bmRfb3BhbF9zZXNzaW9uLAorCU5VTEwKK307CitpbnQgb3BhbF9sb2NrX3VubG9jayhzdHJ1Y3Qg
YmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorICAgICAgICAgICAgICAg
ICAgICAgdm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKQoreworCXZv
aWQgKmZ1bmNfZGF0YVszXSA9IHsgTlVMTCB9OworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCWlu
dCByZXQ7CisKKwlpZiAoa2V5LT5vcGFsX2xrX3VubGsuYXV0aG9yaXR5LndobyA8IE9QQUxfQURN
SU4xIHx8CisJICAgIGtleS0+b3BhbF9sa191bmxrLmF1dGhvcml0eS53aG8gPiBPUEFMX1VTRVI5
KQorCQlyZXR1cm4gLUVJTlZBTDsKKworCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRl
diwga2V5LT5vcGFsX2xrX3VubGsua2V5LmxyLCB0cnVlKTsKKwlpZiAoIWRldikKKwkJcmV0dXJu
IC1FTk9NRU07CisKKwlpZiAoa2V5LT5vcGFsX2xrX3VubGsuYXV0aG9yaXR5LlNVTSkKKwkJcmV0
ID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCB1bGtfZnVuY3NfU1VNLAorCQkJCSAgICAgJmtl
eS0+b3BhbF9sa191bmxrLmtleSwKKwkJCQkgICAgIHNibXRfZGF0YSwgc3VibWl0X2ZuKTsKKwll
bHNlCisJCXJldCA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwgX3VubG9ja19mdW5jcywKKwkJ
CQkgICAgICZrZXktPm9wYWxfbGtfdW5say5rZXksCisJCQkJICAgICBzYm10X2RhdGEsIHN1Ym1p
dF9mbik7CisJaWYgKHJldCkKKwkJZ290byBlcnJvcl9yZXR1cm47CisKKwlkZXYtPm51bV9mdW5j
X2RhdGEgPSAzOworCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOworCWRldi0+ZnVuY19kYXRh
WzFdID0gJmtleS0+b3BhbF9sa191bmxrLmF1dGhvcml0eTsKKwlkZXYtPmZ1bmNfZGF0YVsyXSA9
ICZrZXktPm9wYWxfbGtfdW5sazsKKworCXJldCA9IG5leHQoZGV2KTsKKworIGVycm9yX3JldHVy
bjoKKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7CisJcmV0dXJuIHJldDsKK30KK0VY
UE9SVF9TWU1CT0wob3BhbF9sb2NrX3VubG9jayk7CisKK2ludCBvcGFsX3Rha2Vfb3duZXJzaGlw
KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXksCisJCQl2b2lk
ICpzYm10X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pCit7CisJY29uc3Qgb3BhbF9z
dGVwIG93bmVyX2Z1bmNzW10gPSB7CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfYW55Ym9k
eUFTUF9vcGFsX3Nlc3Npb24sCisJCWdldF9tc2lkX2NwaW5fcGluLAorCQllbmRfb3BhbF9zZXNz
aW9uLAorCQlzdGFydF9TSURBU1Bfb3BhbF9zZXNzaW9uLAorCQlzZXRfc2lkX2NwaW5fcGluLAor
CQllbmRfb3BhbF9zZXNzaW9uLAorCQlOVUxMCisJfTsKKworCXJldHVybiBvcGFsX3JlZ2lzdGVy
KGJkZXYsICZrZXktPm9wYWwsIG93bmVyX2Z1bmNzLCBzYm10X2RhdGEsCisJCQkgICAgIHN1Ym1p
dF9mbik7Cit9CitFWFBPUlRfU1lNQk9MKG9wYWxfdGFrZV9vd25lcnNoaXApOworCitpbnQgb3Bh
bF9hY3RpdmF0ZV9sc3Aoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkg
KmtleSwKKwkJICAgICAgdm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2Zu
KQoreworCWNvbnN0IG9wYWxfc3RlcCBhY3RpdmVfZnVuY3NbXSA9IHsKKwkJb3BhbF9kaXNjb3Zl
cnkwLAorCQlzdGFydF9TSURBU1Bfb3BhbF9zZXNzaW9uLCAvKiBPcGVuIHNlc3Npb24gYXMgU0lE
IGF1dGggKi8KKwkJZ2V0X2xzcF9saWZlY3ljbGUsCisJCWFjdGl2YXRlX2xzcCwKKwkJZW5kX29w
YWxfc2Vzc2lvbiwKKwkJTlVMTAorCX07CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7CisJaW50IHJl
dDsKKworCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwga2V5LT5vcGFsLmxyLCB0
cnVlKTsKKwlpZiAoIWRldikKKwkJcmV0dXJuIC1FTk9NRU07CisJcmV0ID0gc2V0dXBfb3BhbF9k
ZXYoYmRldiwgZGV2LCBhY3RpdmVfZnVuY3MsICZrZXktPm9wYWwsCisJCQkgICAgIHNibXRfZGF0
YSwgc3VibWl0X2ZuKTsKKwlpZiAocmV0KQorCQlnb3RvIGVycm9yX3JldHVybjsKKworCXJldCA9
IG5leHQoZGV2KTsKKworIGVycm9yX3JldHVybjoKKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2
KGRldik7CisJcmV0dXJuIHJldDsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF9hY3RpdmF0ZV9sc3Ap
OworCitpbnQgb3BhbF9zZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJk
ZXYsIHN0cnVjdCBzZWRfa2V5ICpwdywKKwkJCSAgICAgdm9pZCAqc2JtdF9kYXRhLCBzZWRfc2Vj
X3N1Ym1pdCAqc3VibWl0X2ZuKQoreworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXZvaWQgKmRh
dGFbM10gPSB7IE5VTEwgfTsKKwljb25zdCBvcGFsX3N0ZXAgbHJfZnVuY3NbXSA9IHsKKwkJb3Bh
bF9kaXNjb3ZlcnkwLAorCQlzdGFydF9hdXRoX29wYWxfc2Vzc2lvbiwKKwkJc2V0dXBfbG9ja2lu
Z19yYW5nZSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJTlVMTCwKKwl9OworCWludCByZXQ7CisK
KwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJkZXYsIHB3LT5vcGFsX2xycy5rZXkubHIs
IHRydWUpOworCWlmICghZGV2KQorCQlyZXR1cm4gLUVOT01FTTsKKworCXJldCA9IHNldHVwX29w
YWxfZGV2KGJkZXYsIGRldiwgbHJfZnVuY3MsICZwdy0+b3BhbF9scnMua2V5LAorCQkJICAgICBz
Ym10X2RhdGEsIHN1Ym1pdF9mbik7CisJaWYgKHJldCkKKwkJZ290byBlcnJvcl9yZXR1cm47CisK
KwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7CisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYt
PmZ1bmNfZGF0YVsxXSA9ICZwdy0+b3BhbF9scnMud2hvOworCWRldi0+ZnVuY19kYXRhWzJdID0g
JnB3LT5vcGFsX2xyczsKKworCXJldCA9IG5leHQoZGV2KTsKKworIGVycm9yX3JldHVybjoKKwly
ZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7CisJcmV0dXJuIHJldDsKK30KK0VYUE9SVF9T
WU1CT0wob3BhbF9zZXR1cF9sb2NraW5nX3JhbmdlKTsKKworaW50IG9wYWxfc2V0X25ld19wdyhz
dHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqcHcsCisJCSAgICB2b2lk
ICpzYm10X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pCit7CisJY29uc3Qgb3BhbF9z
dGVwIHB3X2Z1bmNzW10gPSB7CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfYXV0aF9vcGFs
X3Nlc3Npb24sCisJCXNldF9uZXdfcHcsCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEwKKwl9
OworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXZvaWQgKmRhdGFbM10gPSB7IE5VTEwgfTsKKwlp
bnQgcmV0OworCisJaWYgKHB3LT5zZWRfdHlwZSAhPSBPUEFMX1BXKQorCQlyZXR1cm4gLUVJTlZB
TDsKKworCWlmIChwdy0+b3BhbF9wdy53aG8ud2hvIDwgT1BBTF9BRE1JTjEgfHwKKwkgICAgcHct
Pm9wYWxfcHcud2hvLndobyA+IE9QQUxfVVNFUjkpCisJCXJldHVybiAtRUlOVkFMOworCisJZGV2
ID0gZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihiZGV2LCBwdy0+b3BhbF9wdy5jdXJyZW50X3Bpbi5s
ciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJldHVybiAtRU5PTUVNOworCisJcmV0ID0gc2V0dXBf
b3BhbF9kZXYoYmRldiwgZGV2LCBwd19mdW5jcywKKwkJCSAgICAgJnB3LT5vcGFsX3B3LmN1cnJl
bnRfcGluLAorCQkJICAgICBzYm10X2RhdGEsIHN1Ym1pdF9mbik7CisJaWYgKHJldCkKKwkJZ290
byBlcnJvcl9yZXR1cm47CisKKwlkZXYtPm51bV9mdW5jX2RhdGEgPSAzOworCWRldi0+ZnVuY19k
YXRhID0gZGF0YTsKKwlkZXYtPmZ1bmNfZGF0YVsxXSA9ICh2b2lkICopICZwdy0+b3BhbF9wdy53
aG87CisJZGV2LT5mdW5jX2RhdGFbMl0gPSAodm9pZCAqKSAmcHctPm9wYWxfcHc7CisKKwlyZXQg
PSBuZXh0KGRldik7CisKKyBlcnJvcl9yZXR1cm46CisJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2Rl
dihkZXYpOworCXJldHVybiByZXQ7Cit9CitFWFBPUlRfU1lNQk9MKG9wYWxfc2V0X25ld19wdyk7
CisKK2ludCBvcGFsX2FjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3Ry
dWN0IHNlZF9rZXkgKnB3LAorCQkgICAgICAgdm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1p
dCAqc3VibWl0X2ZuKQoreworCWNvbnN0IG9wYWxfc3RlcCBhY3RfZnVuY3NbXSA9IHsKKwkJb3Bh
bF9kaXNjb3ZlcnkwLAorCQlzdGFydF9hZG1pbjFMU1Bfb3BhbF9zZXNzaW9uLAorCQlpbnRlcm5h
bF9hY3RpdmF0ZV91c2VyLAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlOVUxMCisJfTsKKwlzdHJ1
Y3Qgb3BhbF9kZXYgKmRldjsKKwl2b2lkICpkYXRhWzNdID0geyBOVUxMIH07CisJaW50IHJldDsK
KworCWlmIChwdy0+c2VkX3R5cGUgIT0gT1BBTF9BQ1RfVVNSKSB7CisJCXByX2VycigiU2VkIHR5
cGUgd2FzIG5vdCBhY3QgdXNlclxuIik7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCS8qIFdl
IGNhbid0IGFjdGl2YXRlIEFkbWluMSBpdCdzIGFjdGl2ZSBhcyBtYW51ZmFjdHVyZWQgKi8KKwlp
ZiAocHctPm9wYWxfYWN0Lndoby53aG8gPCBPUEFMX1VTRVIxICYmCisJICAgIHB3LT5vcGFsX2Fj
dC53aG8ud2hvID4gT1BBTF9VU0VSOSkgeworCQlwcl9lcnIoIldobyB3YXMgbm90IGEgdmFsaWQg
dXNlcjogJWQgXG4iLCBwdy0+b3BhbF9hY3Qud2hvLndobyk7CisJCXJldHVybiAtRUlOVkFMOwor
CX0KKworCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgcHctPm9wYWxfYWN0Lmtl
eS5sciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJldHVybiAtRU5PTUVNOworCisJcmV0ID0gc2V0
dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBhY3RfZnVuY3MsICZwdy0+b3BhbF9hY3Qua2V5LAorCQkJ
ICAgICBzYm10X2RhdGEsIHN1Ym1pdF9mbik7CisJaWYgKHJldCkKKwkJZ290byBlcnJvcl9yZXR1
cm47CisKKwlkZXYtPm51bV9mdW5jX2RhdGEgPSAzOworCWRldi0+ZnVuY19kYXRhID0gZGF0YTsK
KwlkZXYtPmZ1bmNfZGF0YVsxXSA9ICZwdy0+b3BhbF9hY3Q7CisJZGV2LT5mdW5jX2RhdGFbMl0g
PSAmcHctPm9wYWxfYWN0OworCisJcmV0ID0gbmV4dChkZXYpOworCisgZXJyb3JfcmV0dXJuOgor
CXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworCit9CitFWFBP
UlRfU1lNQk9MKG9wYWxfYWN0aXZhdGVfdXNlcik7CisKK2ludCBvcGFsX3VubG9ja19mcm9tX3N1
c3BlbmQoc3RydWN0IG9wYWxfc3VzcGVuZF91bmxrICpkYXRhKQoreworCWludCBtYWptaW4gPSBk
YXRhLT5kZXY7CisJc3RydWN0IG9wYWxfZGV2ICppdGVyLCAqZGV2ID0gTlVMTDsKKwl2b2lkICpm
dW5jX2RhdGFbM10gPSB7IE5VTEwgfTsKKwl1OCBjb3VudCA9IDA7CisJc3RydWN0IG9wYWxfZGV2
ICp0b2RvWzY0XSA9IHsgTlVMTCB9OworCWludCByZXQgPSAwOworCWJvb2wgd2FzX2ZhaWx1cmUg
PSBmYWxzZTsKKworCXNwaW5fbG9jaygmbGlzdF9zcGlubG9jayk7CisJbGlzdF9mb3JfZWFjaF9l
bnRyeShpdGVyLCAmb3BhbF9saXN0LCBub2RlKSB7CisJCWlmIChNQUpPUihpdGVyLT5tYWptaW4p
ICE9IE1BSk9SKG1ham1pbikgfHwKKwkJICAgIE1JTk9SKGl0ZXItPm1ham1pbikgIT0gTUlOT1Io
bWFqbWluKSkKKwkJCWNvbnRpbnVlOworCisJCWlmIChhdG9taWNfYWRkX3VubGVzcygmaXRlci0+
aW5fdXNlLCAxLCAxKSkgeworCQkJaWYgKGNvdW50IDwgNjQpCisJCQkJdG9kb1tjb3VudCsrXSA9
IGl0ZXI7CisJCQllbHNlCisJCQkJYnJlYWs7CisJCX0KKwl9CisJc3Bpbl91bmxvY2soJmxpc3Rf
c3BpbmxvY2spOworCisJd2hpbGUgKGNvdW50KSB7CisJCWRldiA9IHRvZG9bLS1jb3VudF07CisJ
CWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOworCQlkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQg
PSB0cnVlOworCQlkZXYtPnJlc3VtZV9kYXRhID0gZGF0YTsKKwkJZGV2LT5lcnJvcl9jYiA9IGVu
ZF9vcGFsX3Nlc3Npb25fZXJyb3I7CisJCWRldi0+ZXJyb3JfY2JfZGF0YSA9IGRldjsKKwkJZGV2
LT5zdGF0ZSA9IDA7CisJCWlmIChkZXYtPmxrdWwuYXV0aG9yaXR5LlNVTSkKKwkJCWRldi0+ZnVu
Y3MgPSB1bGtfZnVuY3NfU1VNOworCQllbHNlCisJCQlkZXYtPmZ1bmNzID0gX3VubG9ja19mdW5j
czsKKwkJZGV2LT5UU04gPSAwOworCQlkZXYtPkhTTiA9IDA7CisJCWRldi0+ZnVuY19kYXRhWzJd
ID0gJmRldi0+bGt1bDsKKwkJZGV2LT5mdW5jX2RhdGFbMV0gPSAmZGV2LT5sa3VsLmF1dGhvcml0
eTsKKwkJcmV0ID0gbmV4dChkZXYpOworCQlpZiAocmV0KQorCQkJd2FzX2ZhaWx1cmUgPSB0cnVl
OworCQl1bmxvY2tfc3VzcGVuZF9maW5hbChkZXYpOworCX0KKwlyZXR1cm4gd2FzX2ZhaWx1cmUg
PyAxIDogMDsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF91bmxvY2tfZnJvbV9zdXNwZW5kKTsKZGlm
ZiAtLWdpdCBhL2Jsb2NrL3NlZC1vcGFsX2ludGVybmFsLmggYi9ibG9jay9zZWQtb3BhbF9pbnRl
cm5hbC5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjEyMzY5ZWIKLS0tIC9k
ZXYvbnVsbAorKysgYi9ibG9jay9zZWQtb3BhbF9pbnRlcm5hbC5oCkBAIC0wLDAgKzEsNjAxIEBA
CisvKgorICogQ29weXJpZ2h0IMKpIDIwMTYgSW50ZWwgQ29ycG9yYXRpb24KKyAqCisgKiBBdXRo
b3JzOgorICogICAgUmFmYWVsIEFudG9nbm9sbGkgPHJhZmFlbC5hbnRvZ25vbGxpQGludGVsLmNv
bT4KKyAqICAgIFNjb3R0ICBCYXVlciAgICAgIDxzY290dC5iYXVlckBpbnRlbC5jb20+CisgKgor
ICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0
IGFuZC9vciBtb2RpZnkgaXQKKyAqIHVuZGVyIHRoZSB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB0
aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UsCisgKiB2ZXJzaW9uIDIsIGFzIHB1Ymxpc2hl
ZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgorICoKKyAqIFRoaXMgcHJvZ3JhbSBp
cyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVQK
KyAqIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1F
UkNIQU5UQUJJTElUWSBvcgorICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBT
ZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvcgorICogbW9yZSBkZXRhaWxzLgor
ICovCisKKyNpZm5kZWYgX05WTUVfT1BBTF9JTlRFUk5BTF9ICisjZGVmaW5lIF9OVk1FX09QQUxf
SU5URVJOQUxfSAorCisjaW5jbHVkZSA8bGludXgva2V5LXR5cGUuaD4KKyNpbmNsdWRlIDxrZXlz
L3VzZXItdHlwZS5oPgorCisjZGVmaW5lIERUQUVSUk9SX05PX01FVEhPRF9TVEFUVVMgMHg4OQor
I2RlZmluZSBHRU5FUklDX0hPU1RfU0VTU0lPTl9OVU0gMHg0MQorCisKKworLyoKKyAqIERlcml2
ZWQgZnJvbToKKyAqIFRDR19TdG9yYWdlX0FyY2hpdGVjdHVyZV9Db3JlX1NwZWNfdjIuMDFfcjEu
MDAKKyAqIFNlY3Rpb246IDUuMS41IE1ldGhvZCBTdGF0dXMgQ29kZXMKKyAqLworc3RhdGljIGNv
bnN0IGNoYXIgKm9wYWxfZXJyb3JzW10gPSB7CisJIlN1Y2Nlc3MiLAorCSJOb3QgQXV0aG9yaXpl
ZCIsCisJIlVua25vd24gRXJyb3IiLAorCSJTUCBCdXN5IiwKKwkiU1AgRmFpbGVkIiwKKwkiU1Ag
RGlzYWJsZWQiLAorCSJTUCBGcm96ZW4iLAorCSJObyBTZXNzaW9ucyBBdmFpbGFibGUiLAorCSJV
bmlxdWVuZXNzIENvbmZsaWN0IiwKKwkiSW5zdWZmaWNpZW50IFNwYWNlIiwKKwkiSW5zdWZmaWNp
ZW50IFJvd3MiLAorCSJJbnZhbGlkIEZ1bmN0aW9uIiwKKwkiSW52YWxpZCBQYXJhbWV0ZXIiLAor
CSJJbnZhbGlkIFJlZmVyZW5jZSIsCisJIlVua25vd24gRXJyb3IiLAorCSJUUEVSIE1hbGZ1bmN0
aW9uIiwKKwkiVHJhbnNhY3Rpb24gRmFpbHVyZSIsCisJIlJlc3BvbnNlIE92ZXJmbG93IiwKKwki
QXV0aG9yaXR5IExvY2tlZCBPdXQiLAorfTsKKworc3RhdGljIGNvbnN0IGNoYXIgKm9wYWxfZXJy
b3JfdG9faHVtYW4oaW50IGVycm9yKQoreworCWlmIChlcnJvciA9PSAweDNmKQorCQlyZXR1cm4g
IkZhaWxlZCI7CisKKwlpZiAoZXJyb3IgPj0gQVJSQVlfU0laRShvcGFsX2Vycm9ycykgfHwgZXJy
b3IgPCAwKQorCQlyZXR1cm4gIlVua25vd24gRXJyb3IiOworCisJcmV0dXJuIG9wYWxfZXJyb3Jz
W2Vycm9yXTsKK30KKworLyoKKyAqIFVzZXIgSURzIHVzZWQgaW4gdGhlIFRDRyBzdG9yYWdlIFNT
Q3MKKyAqIERlcml2ZWQgZnJvbTogVENHX1N0b3JhZ2VfQXJjaGl0ZWN0dXJlX0NvcmVfU3BlY192
Mi4wMV9yMS4wMAorICogU2VjdGlvbjogNi4zIEFzc2lnbmVkIFVJRHMKKyAqLworc3RhdGljIGNv
bnN0IHU4IE9QQUxVSURbXVs4XSA9IHsKKwkvKiB1c2VycyAqLworCisJLyogc2Vzc2lvbiBtYW5h
Z2VtZW50ICAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwg
MHhmZn0sCisJLyogc3BlY2lhbCAidGhpc1NQIiBzeW50YXggKi8KKwl7IDB4MDAsIDB4MDAsIDB4
MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEgfSwKKwkvKiBBZG1pbmlzdHJhdGl2ZSBT
UCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMiwgMHgwNSwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMSB9
LAorCS8qIExvY2tpbmcgU1AgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDIsIDB4MDUsIDB4MDAsIDB4
MDAsIDB4MDAsIDB4MDIgfSwKKwkvKiBFTlRFUlBSSVNFIExvY2tpbmcgU1AgICovCisJeyAweDAw
LCAweDAwLCAweDAyLCAweDA1LCAweDAwLCAweDAxLCAweDAwLCAweDAxIH0sCisJLyogYW55Ym9k
eSAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMSB9
LAorCS8qIFNJRCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMCwgMHgw
MCwgMHgwNiB9LAorCS8qIEFETUlOMSAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgw
MCwgMHgwMSwgMHgwMCwgMHgwMSB9LAorCS8qIFVTRVIxICovCisJeyAweDAwLCAweDAwLCAweDAw
LCAweDA5LCAweDAwLCAweDAzLCAweDAwLCAweDAxIH0sCisJLyogVVNFUjIgKi8KKwl7IDB4MDAs
IDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDMsIDB4MDAsIDB4MDIgfSwKKwkvKiBQU0lEIHVz
ZXIgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDEsIDB4ZmYsIDB4MDEg
fSwKKwkvKiBCYW5kTWFzdGVyIDAgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAs
IDB4MDAsIDB4ODAsIDB4MDEgfSwKKwkgLyogRXJhc2VNYXN0ZXIgKi8KKwl7IDB4MDAsIDB4MDAs
IDB4MDAsIDB4MDksIDB4MDAsIDB4MDAsIDB4ODQsIDB4MDEgfSwKKworCS8qIHRhYmxlcyAqLwor
CisJLyogTG9ja2luZ19HbG9iYWxSYW5nZSAqLworCXsgMHgwMCwgMHgwMCwgMHgwOCwgMHgwMiwg
MHgwMCwgMHgwMCwgMHgwMCwgMHgwMSB9LAorCS8qIEFDRV9Mb2NraW5nX1JhbmdlX1NldF9SZExv
Y2tlZCBVSUQgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDgsIDB4MDAsIDB4MDMsIDB4RTAs
IDB4MDEgfSwKKwkvKiBBQ0VfTG9ja2luZ19SYW5nZV9TZXRfV3JMb2NrZWQgVUlEICovCisJeyAw
eDAwLCAweDAwLCAweDAwLCAweDA4LCAweDAwLCAweDAzLCAweEU4LCAweDAxIH0sCisJLyogTUJS
IENvbnRyb2wgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDgsIDB4MDMsIDB4MDAsIDB4MDAsIDB4MDAs
IDB4MDEgfSwKKwkvKiBTaGFkb3cgTUJSICovCisJeyAweDAwLCAweDAwLCAweDA4LCAweDA0LCAw
eDAwLCAweDAwLCAweDAwLCAweDAwIH0sCisJLyogQVVUSE9SSVRZX1RBQkxFICovCisJeyAweDAw
LCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAwLCAweDAwLCAweDAwfSwKKwkvKiBDX1BJTl9U
QUJMRSAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwQiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgw
MH0sCisJLyogT1BBTCBMb2NraW5nIEluZm8gKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDgsIDB4MDEs
IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEgfSwKKwkvKiBFbnRlcnByaXNlIExvY2tpbmcgSW5mbyAq
LworCXsgMHgwMCwgMHgwMCwgMHgwOCwgMHgwMSwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCB9LAor
CisJLyogQ19QSU5fVEFCTEUgb2JqZWN0IElEJ3MgKi8KKworCS8qIENfUElOX01TSUQgKi8KKwl7
IDB4MDAsIDB4MDAsIDB4MDAsIDB4MEIsIDB4MDAsIDB4MDAsIDB4ODQsIDB4MDJ9LAorCS8qIENf
UElOX1NJRCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwQiwgMHgwMCwgMHgwMCwgMHgwMCwg
MHgwMX0sCisJIC8qIENfUElOX0FETUlOMSAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwQiwg
MHgwMCwgMHgwMSwgMHgwMCwgMHgwMX0sCisKKwkvKiBoYWxmIFVJRCdzIChvbmx5IGZpcnN0IDQg
Ynl0ZXMgdXNlZCkgKi8KKworCS8qIEhhbGYtVUlEIOKAkyBBdXRob3JpdHlfb2JqZWN0X3JlZiAq
LworCXsgMHgwMCwgMHgwMCwgMHgwQywgMHgwNSwgMHhmZiwgMHhmZiwgMHhmZiwgMHhmZiB9LAor
CS8qIEhhbGYtVUlEIOKAkyBCb29sZWFuIEFDRSAqLworCXsgMHgwMCwgMHgwMCwgMHgwNCwgMHgw
RSwgMHhmZiwgMHhmZiwgMHhmZiwgMHhmZiB9LAorCisJLyogc3BlY2lhbCB2YWx1ZSBmb3Igb21p
dHRlZCBvcHRpb25hbCBwYXJhbWV0ZXIgKi8KKworCS8qIEhFWEZGIGZvciBvbWl0dGVkICovCisJ
eyAweGZmLCAweGZmLCAweGZmLCAweGZmLCAweGZmLCAweGZmLCAweGZmLCAweGZmfSwKK307Citz
dGF0aWMgY29uc3Qgc2l6ZV90IE9QQUxfVUlEX0xFTkdUSCA9IDg7CitzdGF0aWMgY29uc3Qgc2l6
ZV90IE9QQUxfTVNJRF9LRVlMRU4gPSAxNTsKK3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9VSURf
TEVOR1RIX0hBTEYgPSA0OworCisKKy8qIEVudW0gdG8gaW5kZXggT1BBTFVJRCBhcnJheSAqLwor
ZW51bSBPUEFMX1VJRCB7CisJLyogdXNlcnMgKi8KKwlPUEFMX1NNVUlEX1VJRCwKKwlPUEFMX1RI
SVNTUF9VSUQsCisJT1BBTF9BRE1JTlNQX1VJRCwKKwlPUEFMX0xPQ0tJTkdTUF9VSUQsCisJT1BB
TF9FTlRFUlBSSVNFX0xPQ0tJTkdTUF9VSUQsCisJT1BBTF9BTllCT0RZX1VJRCwKKwlPUEFMX1NJ
RF9VSUQsCisJT1BBTF9BRE1JTjFfVUlELAorCU9QQUxfVVNFUjFfVUlELAorCU9QQUxfVVNFUjJf
VUlELAorCU9QQUxfUFNJRF9VSUQsCisJT1BBTF9FTlRFUlBSSVNFX0JBTkRNQVNURVIwX1VJRCwK
KwlPUEFMX0VOVEVSUFJJU0VfRVJBU0VNQVNURVJfVUlELAorCS8qIHRhYmxlcyAqLworCU9QQUxf
TE9DS0lOR1JBTkdFX0dMT0JBTCwKKwlPUEFMX0xPQ0tJTkdSQU5HRV9BQ0VfUkRMT0NLRUQsCisJ
T1BBTF9MT0NLSU5HUkFOR0VfQUNFX1dSTE9DS0VELAorCU9QQUxfTUJSQ09OVFJPTCwKKwlPUEFM
X01CUiwKKwlPUEFMX0FVVEhPUklUWV9UQUJMRSwKKwlPUEFMX0NfUElOX1RBQkxFLAorCU9QQUxf
TE9DS0lOR19JTkZPX1RBQkxFLAorCU9QQUxfRU5URVJQUklTRV9MT0NLSU5HX0lORk9fVEFCTEUs
CisJLyogQ19QSU5fVEFCTEUgb2JqZWN0IElEJ3MgKi8KKwlPUEFMX0NfUElOX01TSUQsCisJT1BB
TF9DX1BJTl9TSUQsCisJT1BBTF9DX1BJTl9BRE1JTjEsCisJLyogaGFsZiBVSUQncyAob25seSBm
aXJzdCA0IGJ5dGVzIHVzZWQpICovCisJT1BBTF9IQUxGX1VJRF9BVVRIT1JJVFlfT0JKX1JFRiwK
KwlPUEFMX0hBTEZfVUlEX0JPT0xFQU5fQUNFLAorCS8qIG9taXR0ZWQgb3B0aW9uYWwgcGFyYW1l
dGVyICovCisJT1BBTF9VSURfSEVYRkYsCit9OworCisvKgorICogVENHIFN0b3JhZ2UgU1NDIE1l
dGhvZHMuCisgKiBEZXJpdmVkIGZyb206IFRDR19TdG9yYWdlX0FyY2hpdGVjdHVyZV9Db3JlX1Nw
ZWNfdjIuMDFfcjEuMDAKKyAqIFNlY3Rpb246IDYuMyBBc3NpZ25lZCBVSURzCisgKi8KK3N0YXRp
YyBjb25zdCB1OCBPUEFMTUVUSE9EW11bOF0gPSB7CisJLyogUHJvcGVydGllcyAqLworCXsgMHgw
MCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHhmZiwgMHgwMSB9LAorCS8qIFNUQVJU
U0VTU0lPTiAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHhmZiwg
MHgwMiB9LAorCS8qIFJldmVydCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwg
MHgwMCwgMHgwMiwgMHgwMiB9LAorCS8qIEFjdGl2YXRlICovCisJeyAweDAwLCAweDAwLCAweDAw
LCAweDA2LCAweDAwLCAweDAwLCAweDAyLCAweDAzIH0sCisJLyogRW50ZXJwcmlzZSBHZXQgKi8K
Kwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYgfSwKKwkv
KiBFbnRlcnByaXNlIFNldCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgw
MCwgMHgwMCwgMHgwNyB9LAorCS8qIE5FWFQgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYs
IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDggfSwKKwkvKiBFbnRlcnByaXNlIEF1dGhlbnRpY2F0ZSAq
LworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwYyB9LAor
CS8qIEdldEFDTCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgw
MCwgMHgwZCB9LAorCS8qIEdlbktleSAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgw
MCwgMHgwMCwgMHgwMCwgMHgxMCB9LAorCS8qIHJldmVydFNQICovCisJeyAweDAwLCAweDAwLCAw
eDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDExIH0sCisJLyogR2V0ICovCisJeyAweDAw
LCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDE2IH0sCisJLyogU2V0ICov
CisJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDE3IH0sCisJ
LyogQXV0aGVudGljYXRlICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAw
LCAweDAwLCAweDFjIH0sCisJLyogUmFuZG9tICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA2
LCAweDAwLCAweDAwLCAweDA2LCAweDAxIH0sCisJLyogRXJhc2UgKi8KKwl7IDB4MDAsIDB4MDAs
IDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDgsIDB4MDMgfSwKK307CitzdGF0aWMgY29uc3Qg
c2l6ZV90IE9QQUxfTUVUSE9EX0xFTkdUSCA9IDg7CisKKy8qIEVudW0gZm9yIGluZGV4aW5nIHRo
ZSBPUEFMTUVUSE9EIGFycmF5ICovCitlbnVtIE9QQUxfTUVUSE9EIHsKKwlPUEFMX1BST1BFUlRJ
RVMsCisJT1BBTF9TVEFSVFNFU1NJT04sCisJT1BBTF9SRVZFUlQsCisJT1BBTF9BQ1RJVkFURSwK
KwlPUEFMX0VHRVQsCisJT1BBTF9FU0VULAorCU9QQUxfTkVYVCwKKwlPUEFMX0VBVVRIRU5USUNB
VEUsCisJT1BBTF9HRVRBQ0wsCisJT1BBTF9HRU5LRVksCisJT1BBTF9SRVZFUlRTUCwKKwlPUEFM
X0dFVCwKKwlPUEFMX1NFVCwKKwlPUEFMX0FVVEhFTlRJQ0FURSwKKwlPUEFMX1JBTkRPTSwKKwlP
UEFMX0VSQVNFLAorfTsKKworLyoKKyAqIFRva2VuIGRlZnMgZGVyaXZlZCBmcm9tOgorICogVENH
X1N0b3JhZ2VfQXJjaGl0ZWN0dXJlX0NvcmVfU3BlY192Mi4wMV9yMS4wMAorICogMy4yLjIgRGF0
YSBTdHJlYW0gRW5jb2RpbmcKKyAqLworZW51bSBPUEFMX1JFU1BPTlNFX1RPS0VOIHsKKwlPUEFM
X0RUQV9UT0tFTklEX0JZVEVTVFJJTkcgPSAweGUwLAorCU9QQUxfRFRBX1RPS0VOSURfU0lOVCA9
IDB4ZTEsCisJT1BBTF9EVEFfVE9LRU5JRF9VSU5UID0gMHhlMiwKKwlPUEFMX0RUQV9UT0tFTklE
X1RPS0VOID0gMHhlMywgLyogYWN0dWFsIHRva2VuIGlzIHJldHVybmVkICovCisJT1BBTF9EVEFf
VE9LRU5JRF9JTlZBTElEID0gMFgwCit9OworCitlbnVtIE9QQUxfVE9LRU4geworCS8qIEJvb2xl
YW4gKi8KKwlPUEFMX1RSVUUgPSAweDAxLAorCU9QQUxfRkFMU0UgPSAweDAwLAorCU9QQUxfQk9P
TEVBTl9FWFBSID0gMHgwMywKKwkvKiBjZWxsYmxvY2tzICovCisJT1BBTF9UQUJMRSA9IDB4MDAs
CisJT1BBTF9TVEFSVFJPVyA9IDB4MDEsCisJT1BBTF9FTkRST1cgPSAweDAyLAorCU9QQUxfU1RB
UlRDT0xVTU4gPSAweDAzLAorCU9QQUxfRU5EQ09MVU1OID0gMHgwNCwKKwlPUEFMX1ZBTFVFUyA9
IDB4MDEsCisJLyogYXV0aG9yaXR5IHRhYmxlICovCisJT1BBTF9QSU4gPSAweDAzLAorCS8qIGxv
Y2tpbmcgdG9rZW5zICovCisJT1BBTF9SQU5HRVNUQVJUID0gMHgwMywKKwlPUEFMX1JBTkdFTEVO
R1RIID0gMHgwNCwKKwlPUEFMX1JFQURMT0NLRU5BQkxFRCA9IDB4MDUsCisJT1BBTF9XUklURUxP
Q0tFTkFCTEVEID0gMHgwNiwKKwlPUEFMX1JFQURMT0NLRUQgPSAweDA3LAorCU9QQUxfV1JJVEVM
T0NLRUQgPSAweDA4LAorCU9QQUxfQUNUSVZFS0VZID0gMHgwQSwKKwkvKiBsb2NraW5nIGluZm8g
dGFibGUgKi8KKwlPUEFMX01BWFJBTkdFUyA9IDB4MDQsCisJIC8qIG1iciBjb250cm9sICovCisJ
T1BBTF9NQlJFTkFCTEUgPSAweDAxLAorCU9QQUxfTUJSRE9ORSA9IDB4MDIsCisJLyogcHJvcGVy
dGllcyAqLworCU9QQUxfSE9TVFBST1BFUlRJRVMgPSAweDAwLAorCS8qIGF0b21zICovCisJT1BB
TF9TVEFSVExJU1QgPSAweGYwLAorCU9QQUxfRU5ETElTVCA9IDB4ZjEsCisJT1BBTF9TVEFSVE5B
TUUgPSAweGYyLAorCU9QQUxfRU5ETkFNRSA9IDB4ZjMsCisJT1BBTF9DQUxMID0gMHhmOCwKKwlP
UEFMX0VORE9GREFUQSA9IDB4ZjksCisJT1BBTF9FTkRPRlNFU1NJT04gPSAweGZhLAorCU9QQUxf
U1RBUlRUUkFOU0FDVE9OID0gMHhmYiwKKwlPUEFMX0VORFRSQU5TQUNUT04gPSAweGZDLAorCU9Q
QUxfRU1QVFlBVE9NID0gMHhmZiwKKwlPUEFMX1dIRVJFID0gMHgwMCwKK307CisKKy8qIFVzZWZ1
bCB0aW55IGF0b21zLgorICogVXNlZnVsIGZvciB0YWJsZSBjb2x1bW5zIGV0YworICovCitlbnVt
IE9QQUxfVElOWV9BVE9NIHsKKwlPUEFMX1RJTllfVUlOVF8wMCA9IDB4MDAsCisJT1BBTF9USU5Z
X1VJTlRfMDEgPSAweDAxLAorCU9QQUxfVElOWV9VSU5UXzAyID0gMHgwMiwKKwlPUEFMX1RJTllf
VUlOVF8wMyA9IDB4MDMsCisJT1BBTF9USU5ZX1VJTlRfMDQgPSAweDA0LAorCU9QQUxfVElOWV9V
SU5UXzA1ID0gMHgwNSwKKwlPUEFMX1RJTllfVUlOVF8wNiA9IDB4MDYsCisJT1BBTF9USU5ZX1VJ
TlRfMDcgPSAweDA3LAorCU9QQUxfVElOWV9VSU5UXzA4ID0gMHgwOCwKKwlPUEFMX1RJTllfVUlO
VF8wOSA9IDB4MDksCisJT1BBTF9USU5ZX1VJTlRfMTAgPSAweDBhLAorCU9QQUxfVElOWV9VSU5U
XzExID0gMHgwYiwKKwlPUEFMX1RJTllfVUlOVF8xMiA9IDB4MGMsCisJT1BBTF9USU5ZX1VJTlRf
MTMgPSAweDBkLAorCU9QQUxfVElOWV9VSU5UXzE0ID0gMHgwZSwKKwlPUEFMX1RJTllfVUlOVF8x
NSA9IDB4MGYsCit9OworCitlbnVtIE9QQUxfQVRPTV9XSURUSCB7CisJT1BBTF9XSURUSF9USU5Z
LAorCU9QQUxfV0lEVEhfU0hPUlQsCisJT1BBTF9XSURUSF9NRURJVU0sCisJT1BBTF9XSURUSF9M
T05HLAorCU9QQUxfV0lEVEhfVE9LRU4KK307CisKKy8qIExvY2tpbmcgc3RhdGUgZm9yIGEgbG9j
a2luZyByYW5nZSAqLworZW51bSBPUEFMX0xPQ0tJTkdTVEFURSB7CisJT1BBTF9MT0NLSU5HX1JF
QURXUklURSA9IDB4MDEsCisJT1BBTF9MT0NLSU5HX1JFQURPTkxZID0gMHgwMiwKKwlPUEFMX0xP
Q0tJTkdfTE9DS0VEID0gMHgwMywKK307CisKKy8qCisgKiBTdHJ1Y3R1cmVzIHRvIGJ1aWxkIGFu
ZCBkZWNvZGUgdGhlIE9wYWwgU1NDIG1lc3NhZ2VzCisgKiBmaWVsZHMgdGhhdCBhcmUgTk9UIHJl
YWxseSBudW1lcmljIGFyZSBkZWZpbmVkIGFzIHU4W10gdG8KKyAqIGhlbHAgcmVkdWNlIHRoZSBl
bmRpYW5uZXNzIGlzc3VlcworICovCisKKy8qIFBhY2tldHMgZGVyaXZlZCBmcm9tOgorICogVENH
X1N0b3JhZ2VfQXJjaGl0ZWN0dXJlX0NvcmVfU3BlY192Mi4wMV9yMS4wMAorICogU2VjaW9uOiAz
LjIuMyBDb21QYWNrZXRzLCBQYWNrZXRzICYgU3VicGFja2V0cworICovCisKKy8qIENvbW0gUGFj
a2V0IChoZWFkZXIpIGZvciB0cmFuc21pc3Npb25zLiAqLworc3RydWN0IG9wYWxfY29tcGFja2V0
IHsKKwl1MzIgcmVzZXJ2ZWQwOworCXU4IGV4dGVuZGVkQ29tSURbNF07CisJdTMyIG91dHN0YW5k
aW5nRGF0YTsKKwl1MzIgbWluVHJhbnNmZXI7CisJdTMyIGxlbmd0aDsKK307CisKKy8qIFBhY2tl
dCBzdHJ1Y3R1cmUuICovCitzdHJ1Y3Qgb3BhbF9wYWNrZXQgeworCXUzMiBUU047CisJdTMyIEhT
TjsKKwl1MzIgc2VxX251bWJlcjsKKwl1MTYgcmVzZXJ2ZWQwOworCXUxNiBhY2tfdHlwZTsKKwl1
MzIgYWNrbm93bGVkZ21lbnQ7CisJdTMyIGxlbmd0aDsKK307CisKKy8qIERhdGEgc3ViIHBhY2tl
dCBoZWFkZXIgKi8KK3N0cnVjdCBvcGFsX2RhdGFfc3VicGFja2V0IHsKKwl1OCByZXNlcnZlZDBb
Nl07CisJdTE2IGtpbmQ7CisJdTMyIGxlbmd0aDsKK307CisKKy8qIGhlYWRlciBvZiBhIHJlc3Bv
bnNlICovCitzdHJ1Y3Qgb3BhbF9oZWFkZXIgeworCXN0cnVjdCBvcGFsX2NvbXBhY2tldCBjcDsK
KwlzdHJ1Y3Qgb3BhbF9wYWNrZXQgcGt0OworCXN0cnVjdCBvcGFsX2RhdGFfc3VicGFja2V0IHN1
YnBrdDsKK307CisKKyNkZWZpbmUgRkNfVFBFUiAgICAgICAweDAwMDEKKyNkZWZpbmUgRkNfTE9D
S0lORyAgICAweDAwMDIKKyNkZWZpbmUgRkNfR0VPTUVUUlkgICAweDAwMDMKKyNkZWZpbmUgRkNf
RU5URVJQUklTRSAweDAxMDAKKyNkZWZpbmUgRkNfREFUQVNUT1JFICAweDAyMDIKKyNkZWZpbmUg
RkNfU0lOR0xFVVNFUiAweDAyMDEKKyNkZWZpbmUgRkNfT1BBTFYxMDAgICAweDAyMDAKKyNkZWZp
bmUgRkNfT1BBTFYyMDAgICAweDAyMDMKKworLyoKKyAqIFRoZSBEaXNjb3ZlcnkgMCBIZWFkZXIu
IEFzIGRlZmluZWQgaW4KKyAqIE9wYWwgU1NDIERvY3VtZW50YXRpb24KKyAqIFNlY3Rpb246IDMu
My41IENhcGFiaWxpdHkgRGlzY292ZXJ5CisgKi8KK3N0cnVjdCBkMF9oZWFkZXIgeworCXUzMiBs
ZW5ndGg7IC8qIHRoZSBsZW5ndGggb2YgdGhlIGhlYWRlciA0OCBpbiAyLjAwLjEwMCAqLworCXUz
MiByZXZpc2lvbjsgLyoqPCByZXZpc2lvbiBvZiB0aGUgaGVhZGVyIDEgaW4gMi4wMC4xMDAgKi8K
Kwl1MzIgcmVzZXJ2ZWQwMTsKKwl1MzIgcmVzZXJ2ZWQwMjsKKwkvKgorCSAqIHRoZSByZW1haW5k
ZXIgb2YgdGhlIHN0cnVjdHVyZSBpcyB2ZW5kb3Igc3BlY2lmaWMgYW5kIHdpbGwgbm90IGJlCisJ
ICogYWRkcmVzc2VkIG5vdworCSAqLworCXU4IGlnbm9yZWRbMzJdOworfTsKKworLyoKKyAqIFRQ
ZXIgRmVhdHVyZSBEZXNjcmlwdG9yLiBDb250YWlucyBmbGFncyBpbmRpY2F0aW5nIHN1cHBvcnQg
Zm9yIHRoZQorICogVFBlciBmZWF0dXJlcyBkZXNjcmliZWQgaW4gdGhlIE9QQUwgc3BlY2lmaWNh
dGlvbi4gVGhlIG5hbWVzIG1hdGNoIHRoZQorICogT1BBTCB0ZXJtaW5vbG9neQorICoKKyAqIGNv
ZGUgPT0gMHgwMDEgaW4gMi4wMC4xMDAKKyAqLworc3RydWN0IGQwX3RwZXJfZmVhdHVyZXMgewor
CS8qCisJICogc3VwcG9ydGVkX2ZlYXR1cmVzIGJpdHM6CisJICogYml0IDc6IHJlc2VydmVkCisJ
ICogYml0IDY6IGNvbSBJRCBtYW5hZ2VtZW50CisJICogYml0IDU6IHJlc2VydmVkCisJICogYml0
IDQ6IHN0cmVhbWluZyBzdXBwb3J0CisJICogYml0IDM6IGJ1ZmZlciBtYW5hZ2VtZW50CisJICog
Yml0IDI6IEFDSy9OQUNLCisJICogYml0IDE6IGFzeW5jCisJICogYml0IDA6IHN5bmMKKwkgKi8K
Kwl1OCBzdXBwb3J0ZWRfZmVhdHVyZXM7CisJLyoKKwkgKiBieXRlcyA1IHRocm91Z2ggMTUgYXJl
IHJlc2VydmVkLCBidXQgd2UgcmVwcmVzZW50IHRoZSBmaXJzdCAzIGFzCisJICogdTggdG8ga2Vl
cCB0aGUgb3RoZXIgdHdvIDMyYml0cyBpbnRlZ2VycyBhbGlnbmVkLgorCSAqLworCXU4IHJlc2Vy
dmVkMDFbM107CisJdTMyIHJlc2VydmVkMDI7CisJdTMyIHJlc2VydmVkMDM7Cit9OworCisvKgor
ICogTG9ja2luZyBGZWF0dXJlIERlc2NyaXB0b3IuIENvbnRhaW5zIGZsYWdzIGluZGljYXRpbmcg
c3VwcG9ydCBmb3IgdGhlCisgKiBsb2NraW5nIGZlYXR1cmVzIGRlc2NyaWJlZCBpbiB0aGUgT1BB
TCBzcGVjaWZpY2F0aW9uLiBUaGUgbmFtZXMgbWF0Y2ggdGhlCisgKiBPUEFMIHRlcm1pbm9sb2d5
CisgKgorICogY29kZSA9PSAweDAwMDIgaW4gMi4wMC4xMDAKKyAqLworc3RydWN0IGQwX2xvY2tp
bmdfZmVhdHVyZXMgeworCS8qCisJICogc3VwcG9ydGVkX2ZlYXR1cmVzIGJpdHM6CisJICogYml0
cyA2LTc6IHJlc2VydmVkCisJICogYml0IDU6IE1CUiBkb25lCisJICogYml0IDQ6IE1CUiBlbmFi
bGVkCisJICogYml0IDM6IG1lZGlhIGVuY3J5cHRpb24KKwkgKiBiaXQgMjogbG9ja2VkCisJICog
Yml0IDE6IGxvY2tpbmcgZW5hYmxlZAorCSAqIGJpdCAwOiBsb2NraW5nIHN1cHBvcnRlZAorCSAq
LworCXU4IHN1cHBvcnRlZF9mZWF0dXJlczsKKwkvKgorCSAqIGJ5dGVzIDUgdGhyb3VnaCAxNSBh
cmUgcmVzZXJ2ZWQsIGJ1dCB3ZSByZXByZXNlbnQgdGhlIGZpcnN0IDMgYXMKKwkgKiB1OCB0byBr
ZWVwIHRoZSBvdGhlciB0d28gMzJiaXRzIGludGVnZXJzIGFsaWduZWQuCisJICovCisJdTggcmVz
ZXJ2ZWQwMVszXTsKKwl1MzIgcmVzZXJ2ZWQwMjsKKwl1MzIgcmVzZXJ2ZWQwMzsKK307CisKKy8q
CisgKiBHZW9tZXRyeSBGZWF0dXJlIERlc2NyaXB0b3IuIENvbnRhaW5zIGZsYWdzIGluZGljYXRp
bmcgc3VwcG9ydCBmb3IgdGhlCisgKiBnZW9tZXRyeSBmZWF0dXJlcyBkZXNjcmliZWQgaW4gdGhl
IE9QQUwgc3BlY2lmaWNhdGlvbi4gVGhlIG5hbWVzIG1hdGNoIHRoZQorICogT1BBTCB0ZXJtaW5v
bG9neQorICoKKyAqIGNvZGUgPT0gMHgwMDAzIGluIDIuMDAuMTAwCisgKi8KK3N0cnVjdCBkMF9n
ZW9tZXRyeV9mZWF0dXJlcyB7CisJLyoKKwkgKiBza2lwIDMyIGJpdHMgZnJvbSBoZWFkZXIsIG5l
ZWRlZCB0byBhbGlnbiB0aGUgc3RydWN0IHRvIDY0IGJpdHMuCisJICovCisJdTggaGVhZGVyWzRd
OworCS8qCisJICogcmVzZXJ2ZWQwMToKKwkgKiBiaXRzIDEtNjogcmVzZXJ2ZWQKKwkgKiBiaXQg
MDogYWxpZ24KKwkgKi8KKwl1OCByZXNlcnZlZDAxOworCXU4IHJlc2VydmVkMDJbN107CisJdTMy
IGxvZ2ljYWxfYmxvY2tfc2l6ZTsKKwl1NjQgYWxpZ25tZW50X2dyYW51bGFyaXR5OworCXU2NCBs
b3dlc3RfYWxpZ25lZF9sYmE7Cit9OworCisvKgorICogRW50ZXJwcmlzZSBTU0MgRmVhdHVyZQor
ICoKKyAqIGNvZGUgPT0gMHgwMTAwCisgKi8KK3N0cnVjdCBkMF9lbnRlcnByaXNlX3NzYyB7CisJ
dTE2IGJhc2VDb21JRDsKKwl1MTYgbnVtQ29tSURzOworCS8qIHJhbmdlX2Nyb3NzaW5nOgorCSAq
IGJpdHMgMS02OiByZXNlcnZlZAorCSAqIGJpdCAwOiByYW5nZSBjcm9zc2luZworCSAqLworCXU4
IHJhbmdlX2Nyb3NzaW5nOworCXU4IHJlc2VydmVkMDE7CisJdTE2IHJlc2VydmVkMDI7CisJdTMy
IHJlc2VydmVkMDM7CisJdTMyIHJlc2VydmVkMDQ7Cit9OworCisvKgorICogT3BhbCBWMSBmZWF0
dXJlCisgKgorICogY29kZSA9PSAweDAyMDAKKyAqLworc3RydWN0IGQwX29wYWxfdjEwMCB7CisJ
dTE2IGJhc2VDb21JRDsKKwl1MTYgbnVtQ29tSURzOworfTsKKworLyoKKyAqIFNpbmdsZSBVc2Vy
IE1vZGUgZmVhdHVyZQorICoKKyAqIGNvZGUgPT0gMHgwMjAxCisgKi8KK3N0cnVjdCBkMF9zaW5n
bGVfdXNlcl9tb2RlIHsKKwl1MzIgbnVtX2xvY2tpbmdfb2JqZWN0czsKKwkvKiByZXNlcnZlZDAx
OgorCSAqIGJpdCAwOiBhbnkKKwkgKiBiaXQgMTogYWxsCisJICogYml0IDI6IHBvbGljeQorCSAq
IGJpdHMgMy03OiByZXNlcnZlZAorCSAqLworCXU4IHJlc2VydmVkMDE7CisJdTggcmVzZXJ2ZWQw
MjsKKwl1MTYgcmVzZXJ2ZWQwMzsKKwl1MzIgcmVzZXJ2ZWQwNDsKK307CisKKy8qCisgKiBBZGRp
dG9uYWwgRGF0YXN0b3JlcyBmZWF0dXJlCisgKgorICogY29kZSA9PSAweDAyMDIKKyAqLworc3Ry
dWN0IGQwX2RhdGFzdG9yZV90YWJsZSB7CisJdTE2IHJlc2VydmVkMDE7CisJdTE2IG1heF90YWJs
ZXM7CisJdTMyIG1heF9zaXplX3RhYmxlczsKKwl1MzIgdGFibGVfc2l6ZV9hbGlnbm1lbnQ7Cit9
OworCisvKgorICogT1BBTCAyLjAgZmVhdHVyZQorICoKKyAqIGNvZGUgPT0gMHgwMjAzCisgKi8K
K3N0cnVjdCBkMF9vcGFsX3YyMDAgeworCXUxNiBiYXNlQ29tSUQ7CisJdTE2IG51bUNvbUlEczsK
KwkvKiByYW5nZV9jcm9zc2luZzoKKwkgKiBiaXRzIDEtNjogcmVzZXJ2ZWQKKwkgKiBiaXQgMDog
cmFuZ2UgY3Jvc3NpbmcKKwkgKi8KKwl1OCByYW5nZV9jcm9zc2luZzsKKwkvKiBudW1fbG9ja2lu
Z19hZG1pbl9hdXRoOgorCSAqIG5vdCBhbGlnbmVkIHRvIDE2IGJpdHMsIHNvIHVzZSB0d28gdTgu
CisJICogc3RvcmVkIGluIGJpZyBlbmRpYW46CisJICogMDogTVNCCisJICogMTogTFNCCisJICov
CisJdTggbnVtX2xvY2tpbmdfYWRtaW5fYXV0aFsyXTsKKwkvKiBudW1fbG9ja2luZ191c2VyX2F1
dGg6CisJICogbm90IGFsaWduZWQgdG8gMTYgYml0cywgc28gdXNlIHR3byB1OC4KKwkgKiBzdG9y
ZWQgaW4gYmlnIGVuZGlhbjoKKwkgKiAwOiBNU0IKKwkgKiAxOiBMU0IKKwkgKi8KKwl1OCBudW1f
bG9ja2luZ191c2VyX2F1dGhbMl07CisJdTggaW5pdGlhbFBJTjsKKwl1OCByZXZlcnRlZFBJTjsK
Kwl1OCByZXNlcnZlZDAxOworCXUzMiByZXNlcnZlZDAyOworfTsKKworLyogVW5pb24gb2YgZmVh
dHVyZXMgdXNlZCB0byBwYXJzZSB0aGUgZGlzY292ZXJ5IDAgcmVzcG9uc2UgKi8KK3N0cnVjdCBk
MF9mZWF0dXJlcyB7CisJdTE2IGNvZGU7CisJLyoKKwkgKiByX3ZlcnNpb24gYml0czoKKwkgKiBi
aXRzIDQtNzogdmVyc2lvbgorCSAqIGJpdHMgMC0zOiByZXNlcnZlZAorCSAqLworCXU4IHJfdmVy
c2lvbjsKKwl1OCBsZW5ndGg7CisJdTggZmVhdHVyZXNbXTsKK307CisKK3N0cnVjdCBrZXkgKnJl
cXVlc3RfdXNlcl9rZXkoY29uc3QgY2hhciAqbWFzdGVyX2Rlc2MsIGNvbnN0IHU4ICoqbWFzdGVy
X2tleSwKKwkJCSAgICAgc2l6ZV90ICptYXN0ZXJfa2V5bGVuKTsKKworI2VuZGlmIC8qIF9OVk1F
X09QQUxfSU5URVJOQUxfSCAqLwpkaWZmIC0tZ2l0IGEvYmxvY2svc2VkLmMgYi9ibG9jay9zZWQu
YwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi4yNDFiMWRjCi0tLSAvZGV2L251
bGwKKysrIGIvYmxvY2svc2VkLmMKQEAgLTAsMCArMSwyMDcgQEAKKy8qCisgKiBDb3B5cmlnaHQg
wqkgMjAxNiBJbnRlbCBDb3Jwb3JhdGlvbgorICoKKyAqIEF1dGhvcnM6CisgKiAgICBSYWZhZWwg
QW50b2dub2xsaSA8cmFmYWVsLmFudG9nbm9sbGlAaW50ZWwuY29tPgorICogICAgU2NvdHQgIEJh
dWVyICAgICAgPHNjb3R0LmJhdWVyQGludGVsLmNvbT4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMg
ZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdAor
ICogdW5kZXIgdGhlIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJs
aWMgTGljZW5zZSwKKyAqIHZlcnNpb24gMiwgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3
YXJlIEZvdW5kYXRpb24uCisgKgorICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRo
ZSBob3BlIGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVAorICogQU5ZIFdBUlJBTlRZOyB3
aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yCisg
KiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VIEdlbmVyYWwg
UHVibGljIExpY2Vuc2UgZm9yCisgKiBtb3JlIGRldGFpbHMuCisgKi8KKworI2luY2x1ZGUgPGxp
bnV4L2Jsa2Rldi5oPgorI2luY2x1ZGUgPGxpbnV4L3NlZC5oPgorI2luY2x1ZGUgPGxpbnV4L3Nl
ZC1vcGFsLmg+CisjaW5jbHVkZSA8YXNtL3VhY2Nlc3MuaD4KKworCitpbnQgc2VkX3NhdmUoc3Ry
dWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSwKKwkgICAgIHZvaWQg
KnNibXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbikKK3sKKwlzd2l0Y2ggKGtleS0+
c2VkX3R5cGUpIHsKKwljYXNlIE9QQUxfTE9DS19VTkxPQ0s6CisJCXJldHVybiBvcGFsX3NhdmUo
YmRldiwga2V5LCBzYm10X2RhdGEsIHN1Ym1pdF9mbik7CisJfQorCisJcmV0dXJuIC1FT1BOT1RT
VVBQOworfQorCitpbnQgc2VkX2xvY2tfdW5sb2NrKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYs
IHN0cnVjdCBzZWRfa2V5ICprZXksCisJCSAgICB2b2lkICpzYm10X2RhdGEsIHNlZF9zZWNfc3Vi
bWl0ICpzdWJtaXRfZm4pCit7CisJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBPUEFM
X0xPQ0tfVU5MT0NLOgorCQlyZXR1cm4gb3BhbF9sb2NrX3VubG9jayhiZGV2LCBrZXksIHNibXRf
ZGF0YSwgc3VibWl0X2ZuKTsKKwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisKK2ludCBz
ZWRfdGFrZV9vd25lcnNoaXAoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9r
ZXkgKmtleSwKKwkJICAgICAgIHZvaWQgKnNibXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1p
dF9mbikKK3sKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTDoKKwkJcmV0
dXJuIG9wYWxfdGFrZV9vd25lcnNoaXAoYmRldiwga2V5LCBzYm10X2RhdGEsIHN1Ym1pdF9mbik7
CisJfQorCisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQorCitpbnQgc2VkX2FjdGl2YXRlX2xzcChz
dHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5LAorCQkgICAgIHZv
aWQgKnNibXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbikKK3sKKworCXN3aXRjaCAo
a2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTDoKKwkJcmV0dXJuIG9wYWxfYWN0aXZhdGVfbHNw
KGJkZXYsIGtleSwgc2JtdF9kYXRhLCBzdWJtaXRfZm4pOworCX0KKworCXJldHVybiAtRU9QTk9U
U1VQUDsKK30KKworaW50IHNlZF9zZXRfcHcoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3Ry
dWN0IHNlZF9rZXkgKmtleSwKKwkgICAgICAgdm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1p
dCAqc3VibWl0X2ZuKQoreworCisJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBPUEFM
X1BXOgorCQlyZXR1cm4gb3BhbF9zZXRfbmV3X3B3KGJkZXYsIGtleSwgc2JtdF9kYXRhLCBzdWJt
aXRfZm4pOworCX0KKworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworaW50IHNlZF9hY3RpdmF0
ZV91c2VyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXksCisJ
CSAgICAgIHZvaWQgKnNibXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbikKK3sKKwor
CXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTF9BQ1RfVVNSOgorCQlyZXR1cm4g
b3BhbF9hY3RpdmF0ZV91c2VyKGJkZXYsIGtleSwgc2JtdF9kYXRhLCBzdWJtaXRfZm4pOworCX0K
KworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworaW50IHNlZF9yZXZlcnR0cGVyKHN0cnVjdCBi
bG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXksCisJCSAgIHZvaWQgKnNibXRf
ZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbikKK3sKKworCXN3aXRjaCAoa2V5LT5zZWRf
dHlwZSkgeworCWNhc2UgT1BBTDoKKwkJcmV0dXJuIG9wYWxfcmV2ZXJ0dHBlcihiZGV2LCBrZXks
IHNibXRfZGF0YSwgc3VibWl0X2ZuKTsKKwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisK
K2ludCBzZWRfc2V0dXBfbG9ja2luZ19yYW5nZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBz
dHJ1Y3Qgc2VkX2tleSAqa2V5LAorCQkJICAgIHZvaWQgKnNibXRfZGF0YSwgc2VkX3NlY19zdWJt
aXQgKnN1Ym1pdF9mbikKK3sKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BB
TF9MUl9TRVRVUDoKKwkJcmV0dXJuIG9wYWxfc2V0dXBfbG9ja2luZ19yYW5nZShiZGV2LCBrZXks
IHNibXRfZGF0YSwgc3VibWl0X2ZuKTsKKwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisK
K2ludCBzZWRfYWRkdXNlcl90b19scihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qg
c2VkX2tleSAqa2V5LAorCQkgICAgICB2b2lkICpzYm10X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpz
dWJtaXRfZm4pCit7CisKKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsKKwljYXNlIE9QQUxfTE9D
S19VTkxPQ0s6CisJCXJldHVybiBvcGFsX2FkZF91c2VyX3RvX2xyKGJkZXYsIGtleSwgc2JtdF9k
YXRhLCBzdWJtaXRfZm4pOworCX0KKworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworaW50IHNl
ZF9kb19tYnIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSwK
KwkgICAgICAgdm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKQorewor
CisJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBPUEFMX01CUl9EQVRBOgorCQlyZXR1
cm4gb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFkb3dfbWJyKGJkZXYsIGtleSwgc2JtdF9kYXRhLAor
CQkJCQkJICAgICAgc3VibWl0X2ZuKTsKKwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisK
K2ludCBzZWRfZXJhc2VfbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9r
ZXkgKmtleSwKKwkJIHZvaWQgKnNibXRfZGF0YSwgc2VkX3NlY19zdWJtaXQgKnN1Ym1pdF9mbikK
K3sKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTDoKKwkJcmV0dXJuIG9w
YWxfZXJhc2VfbG9ja2luZ19yYW5nZShiZGV2LCBrZXksIHNibXRfZGF0YSwgc3VibWl0X2ZuKTsK
Kwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisKK2ludCBzZWRfc2VjdXJlX2VyYXNlX2xy
KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXksCisJCQl2b2lk
ICpzYm10X2RhdGEsIHNlZF9zZWNfc3VibWl0ICpzdWJtaXRfZm4pCit7CisJc3dpdGNoIChrZXkt
PnNlZF90eXBlKSB7CisJY2FzZSBPUEFMX0FDVF9VU1I6CisJCXJldHVybiBvcGFsX3NlY3VyZV9l
cmFzZV9sb2NraW5nX3JhbmdlKGJkZXYsIGtleSwKKwkJCQkJCSAgICAgICBzYm10X2RhdGEsIHN1
Ym1pdF9mbik7CisKKwl9CisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQorCisKKyNkZWZpbmUgQ01E
X1RPX0ZOX0lORFgoY21kKSBcCisJKGNtZCkgLSBJT0NfU0VEX1NBVkUKKworaW50ICgqc2VkX2Zu
W10pKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXksCisJCSAg
dm9pZCAqc2JtdF9kYXRhLCBzZWRfc2VjX3N1Ym1pdCAqc3VibWl0X2ZuKSA9Cit7CisJc2VkX3Nh
dmUsCisJc2VkX2xvY2tfdW5sb2NrLAorCXNlZF90YWtlX293bmVyc2hpcCwKKwlzZWRfYWN0aXZh
dGVfbHNwLAorCXNlZF9zZXRfcHcsCisJc2VkX2FjdGl2YXRlX3VzZXIsCisJc2VkX3JldmVydHRw
ZXIsCisJc2VkX3NldHVwX2xvY2tpbmdfcmFuZ2UsCisJc2VkX2FkZHVzZXJfdG9fbHIsCisJc2Vk
X2RvX21iciwKKwlzZWRfZXJhc2VfbHIsCisJc2VkX3NlY3VyZV9lcmFzZV9scgorfTsKKworLyog
VGhlIHNibXRfY3RybF9kYXRhIGlzIGEgb3BhcXVlIHBvaW50ZXIgdG8gc29tZSBzdHJ1Y3R1cmUg
d2hpY2ggd2lsbCBiZSB1c2VkCisgKiBieSB0aGUgc3VibWl0X2ZuIHRvIHByb3Blcmx5IHN1Ym1p
dCB0aGUgb3BhbCBjb21tYW5kIHRvIHRoZSBjb250cm9sbGVyLgorICogVGhlIHN1Ym1pdF9mbiBt
dXN0IGJlIGEgYmxvY2tpbmcgY2FsbC4KKyAqLworaW50IGJsa2Rldl9zZWRfaW9jdGwoc3RydWN0
IGJsb2NrX2RldmljZSAqYmRldiwgZm1vZGVfdCBmbW9kZSwgdW5zaWduZWQgaW50IGNtZCwKKwkJ
ICAgICB1bnNpZ25lZCBsb25nIGFyZywgdm9pZCAqc2JtdF9jdHJsX2RhdGEsCisJCSAgICAgc2Vk
X3NlY19zdWJtaXQgKnN1Ym1pdF9mbikKK3sKKwlzdHJ1Y3Qgc2VkX2tleSBrZXk7CisKKwkgLyog
Q2FsbGVyIHNob3VsZCBkbyB0aGlzIGJ1dCBzaW5jZSB3ZSdyZSBnb2luZyB0byB1c2UgY21kIGFz
IGFuIGluZGV4CisJICogbGV0cyAndHJ1c3QgYnV0IHZlcmlmeScuCisJICovCisJaWYgKCFpc19z
ZWRfaW9jdGwoY21kKSkKKwkJcmV0dXJuIC1FSU5WQUw7CisJaWYgKGNvcHlfZnJvbV91c2VyKCZr
ZXksICh2b2lkIF9fdXNlciAqKWFyZywgc2l6ZW9mKGtleSkpKQorCQlyZXR1cm4gLUVGQVVMVDsK
KwlyZXR1cm4gc2VkX2ZuW0NNRF9UT19GTl9JTkRYKGNtZCldKGJkZXYsICZrZXksIHNibXRfY3Ry
bF9kYXRhLCBzdWJtaXRfZm4pOworfQorRVhQT1JUX1NZTUJPTF9HUEwoYmxrZGV2X3NlZF9pb2N0
bCk7Ci0tIAoyLjcuNAoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fCkxpbnV4LW52bWUgbWFpbGluZyBsaXN0CkxpbnV4LW52bWVAbGlzdHMuaW5mcmFkZWFk
Lm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LW52
bWUK

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
@ 2016-11-29 21:52   ` Scott Bauer
  0 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-29 21:52 UTC (permalink / raw)


This patch implements the necessary logic to bring an Opal
enabled drive out of a factory-enabled into a working
Opal state.

This patch set also enables logic to save a password to
be replayed during a resume from suspend. The key can be
saved in the driver or in the Kernel's Key managment.

Signed-off-by: Scott Bauer <scott.bauer at intel.com>
Signed-off-by: Rafael Antognolli <Rafael.Antognolli at intel.com>
---
 block/Makefile            |    2 +-
 block/sed-opal.c          | 3157 +++++++++++++++++++++++++++++++++++++++++++++
 block/sed-opal_internal.h |  601 +++++++++
 block/sed.c               |  207 +++
 4 files changed, 3966 insertions(+), 1 deletion(-)
 create mode 100644 block/sed-opal.c
 create mode 100644 block/sed-opal_internal.h
 create mode 100644 block/sed.c

diff --git a/block/Makefile b/block/Makefile
index 36acdd7..6632d42 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_BLOCK) := bio.o elevator.o blk-core.o blk-tag.o blk-sysfs.o \
 			blk-lib.o blk-mq.o blk-mq-tag.o \
 			blk-mq-sysfs.o blk-mq-cpumap.o ioctl.o \
 			genhd.o scsi_ioctl.o partition-generic.o ioprio.o \
-			badblocks.o partitions/
+			badblocks.o sed.o sed-opal.o partitions/
 
 obj-$(CONFIG_BOUNCE)	+= bounce.o
 obj-$(CONFIG_BLK_DEV_BSG)	+= bsg.o
diff --git a/block/sed-opal.c b/block/sed-opal.c
new file mode 100644
index 0000000..53602aa
--- /dev/null
+++ b/block/sed-opal.c
@@ -0,0 +1,3157 @@
+/*
+ * Copyright ? 2016 Intel Corporation
+ *
+ * Authors:
+ *    Rafael Antognolli <rafael.antognolli at intel.com>
+ *    Scott  Bauer      <scott.bauer at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":OPAL: " fmt
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/genhd.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <uapi/linux/sed-opal.h>
+#include <linux/sed.h>
+#include <linux/sed-opal.h>
+#include <linux/string.h>
+#include <linux/kdev_t.h>
+#include <linux/key.h>
+
+#include "sed-opal_internal.h"
+
+#define IO_BUFFER_LENGTH 2048
+
+#define MAX_TOKS 64
+
+typedef int (cont_fn)(void *data);
+
+struct opal_cmd {
+	struct block_device *bdev;
+	cont_fn *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 int (*opal_step)(struct opal_dev *dev);
+
+struct opal_dev {
+	dev_t majmin;
+	sed_sec_submit *submit_fn;
+	void *submit_data;
+	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;
+
+	opal_step error_cb;
+	void *error_cb_data;
+};
+
+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_dev *dev)
+{
+	return dev->submit_fn(dev->submit_data, dev->comID, TCG_SECP_01,
+			      dev->cmd.cmd, IO_BUFFER_LENGTH, true);
+}
+
+static int opal_recv_cmd(struct opal_dev *dev)
+{
+	return dev->submit_fn(dev->submit_data, dev->comID, TCG_SECP_01,
+			      dev->cmd.resp, IO_BUFFER_LENGTH, false);
+}
+
+static int opal_recv_check(struct opal_dev *dev)
+{
+	size_t buflen = IO_BUFFER_LENGTH;
+	void *buffer = dev->cmd.resp;
+	struct opal_header *hdr = buffer;
+	int ret;
+
+	do {
+		pr_debug("%s: Sent OPAL command: outstanding=%d, minTransfer=%d\n",
+			 dev->disk_name, hdr->cp.outstandingData,
+			 hdr->cp.minTransfer);
+
+		if (hdr->cp.outstandingData == 0 ||
+		    hdr->cp.minTransfer != 0)
+			return 0;
+
+		memset(buffer, 0, buflen);
+		ret = opal_recv_cmd(dev);
+	} while (!ret);
+
+	return ret;
+}
+
+static int opal_send_recv(struct opal_dev *dev, cont_fn *cont)
+{
+	int ret;
+
+	ret = opal_send_cmd(dev);
+	if (ret)
+		return ret;
+	ret = opal_recv_cmd(dev);
+	if (ret)
+		return ret;
+	ret = opal_recv_check(dev);
+	if (ret)
+		return ret;
+
+	return cont(dev);
+}
+
+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 int next(struct opal_dev *dev)
+{
+	opal_step func;
+	int error = 0;
+
+	do {
+
+		func = dev->funcs[dev->state];
+		if (!func)
+			break;
+
+		dev->state++;
+		error = func(dev);
+
+		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));
+
+			/*
+			 * We check for state > 2 because error_cb is
+			 * an end session call. We never start a session until
+			 * after state 2. So If we failed on state 2 or lower
+			 * that means we failed to start a session
+			 * due to a bad pw or something. Therefore is no reason
+			 * to end a non existant session.
+			 */
+			if (dev->error_cb && dev->state > 2)
+				dev->error_cb(dev->error_cb_data);
+		}
+	} while (!error);
+
+	return error;
+}
+
+static int opal_discovery0_end(struct opal_dev *dev)
+{
+	bool foundComID = false, supported = true, single_user = false;
+	const struct d0_header *hdr;
+	const u8 *epos, *cpos;
+	u16 comID = 0;
+	int error = 0;
+
+	epos = dev->cmd.resp;
+	cpos = dev->cmd.resp;
+	hdr = (struct d0_header *)dev->cmd.resp;
+
+	print_buffer(dev->cmd.resp, be32_to_cpu(hdr->length));
+
+	epos += be32_to_cpu(hdr->length); /* end of buffer */
+	cpos += sizeof(*hdr); /* current position on buffer */
+
+	while (cpos < epos && supported) {
+		const struct d0_features *body =
+			(const struct d0_features *)cpos;
+
+		switch (be16_to_cpu(body->code)) {
+		case FC_TPER:
+			supported = check_tper(body->features);
+			break;
+		case FC_SINGLEUSER:
+			single_user = check_SUM(body->features);
+			break;
+		case FC_GEOMETRY:
+			check_geometry(dev, body);
+			break;
+		case FC_LOCKING:
+		case FC_ENTERPRISE:
+		case FC_DATASTORE:
+			/* some ignored properties */
+			pr_debug("%s: Found OPAL feature description: %d\n",
+				 dev->disk_name, be16_to_cpu(body->code));
+			break;
+		case FC_OPALV100:
+			comID = get_comID_v100(body->features);
+			foundComID = true;
+			break;
+		case FC_OPALV200:
+			comID = get_comID_v200(body->features);
+			foundComID = true;
+			break;
+		case 0xbfff ... 0xffff:
+			/* vendor specific, just ignore */
+			break;
+		default:
+			pr_warn("%s: OPAL Unknown feature: %d\n",
+				dev->disk_name, be16_to_cpu(body->code));
+
+		}
+		cpos += body->length + 4;
+	}
+
+	if (!supported) {
+		pr_err("%s: Device not supported\n", dev->disk_name);
+		error = 1;
+		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);
+		error = 1;
+		goto err_callback;
+	}
+
+	dev->comID = comID;
+
+err_callback:
+	return error;
+}
+
+static int opal_discovery0(struct opal_dev *dev)
+{
+	int ret;
+
+	memset(dev->cmd.resp, 0, IO_BUFFER_LENGTH);
+	dev->comID = 0x0001;
+	ret = opal_recv_cmd(dev);
+	if (ret)
+		return ret;
+	return opal_discovery0_end(dev);
+}
+
+static void add_token_u8(struct opal_cmd *cmd, u8 tok)
+{
+	cmd->cmd[cmd->pos++] = tok;
+}
+
+static ssize_t test_and_add_token_u8(struct opal_cmd *cmd, u8 tok)
+{
+	BUILD_BUG_ON(IO_BUFFER_LENGTH >= SIZE_MAX);
+
+	if (cmd->pos >= IO_BUFFER_LENGTH - 1) {
+		pr_err("Error adding u8: end of buffer.\n");
+		return -ERANGE;
+	}
+
+	add_token_u8(cmd, tok);
+
+	return 1;
+}
+
+#define TINY_ATOM_DATA_MASK GENMASK(5, 0)
+#define TINY_ATOM_SIGNED BIT(6)
+
+#define SHORT_ATOM_ID BIT(7)
+#define SHORT_ATOM_BYTESTRING BIT(5)
+#define SHORT_ATOM_SIGNED BIT(4)
+#define SHORT_ATOM_LEN_MASK GENMASK(3, 0)
+
+static void add_short_atom_header(struct opal_cmd *cmd, bool bytestring,
+				  bool has_sign, int len)
+{
+	u8 atom;
+
+	atom = SHORT_ATOM_ID;
+	atom |= bytestring ? SHORT_ATOM_BYTESTRING : 0;
+	atom |= has_sign ? SHORT_ATOM_SIGNED : 0;
+	atom |= len & SHORT_ATOM_LEN_MASK;
+
+	add_token_u8(cmd, atom);
+}
+
+#define MEDIUM_ATOM_ID (BIT(7) | BIT(6))
+#define MEDIUM_ATOM_BYTESTRING BIT(4)
+#define MEDIUM_ATOM_SIGNED BIT(3)
+#define MEDIUM_ATOM_LEN_MASK GENMASK(2, 0)
+
+static void add_medium_atom_header(struct opal_cmd *cmd, bool bytestring,
+				   bool has_sign, int len)
+{
+	u8 header0;
+
+	header0 = MEDIUM_ATOM_ID;
+	header0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0;
+	header0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0;
+	header0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK;
+	cmd->cmd[cmd->pos++] = header0;
+	cmd->cmd[cmd->pos++] = len;
+}
+
+static void add_token_u64(struct opal_cmd *cmd, u64 number, size_t len)
+{
+	add_short_atom_header(cmd, false, false, len);
+
+	while (len--) {
+		u8 n = number >> (len * 8);
+
+		add_token_u8(cmd, n);
+	}
+}
+
+static ssize_t test_and_add_token_u64(struct opal_cmd *cmd, u64 number)
+{
+	int len;
+	int msb;
+
+	if (!(number & ~TINY_ATOM_DATA_MASK))
+		return test_and_add_token_u8(cmd, number);
+
+	msb = fls(number);
+	len = DIV_ROUND_UP(msb, 4);
+
+	if (cmd->pos >= IO_BUFFER_LENGTH - len - 1) {
+		pr_err("Error adding u64: end of buffer.\n");
+		return -ERANGE;
+	}
+
+	add_token_u64(cmd, number, len);
+
+	/* return length of token plus atom */
+	return len + 1;
+}
+
+static void add_token_bytestring(struct opal_cmd *cmd,
+				 const u8 *bytestring, size_t len)
+{
+	memcpy(&cmd->cmd[cmd->pos], bytestring, len);
+	cmd->pos += len;
+}
+
+static ssize_t test_and_add_token_bytestring(struct opal_cmd *cmd,
+					     const u8 *bytestring, size_t len)
+{
+	size_t header_len = 1;
+	bool is_short_atom = true;
+
+	if (len & ~SHORT_ATOM_LEN_MASK) {
+		header_len = 2;
+		is_short_atom = false;
+	}
+
+	if (cmd->pos >= IO_BUFFER_LENGTH - len - header_len) {
+		pr_err("Error adding bytestring: end of buffer.\n");
+		return -ERANGE;
+	}
+
+	if (is_short_atom)
+		add_short_atom_header(cmd, true, false, len);
+	else
+		add_medium_atom_header(cmd, true, false, len);
+
+	add_token_bytestring(cmd, bytestring, len);
+
+	return header_len + len;
+}
+
+#define LOCKING_RANGE_NON_GLOBAL 0x03
+
+static int build_locking_range(u8 *buffer, size_t length, u8 lr)
+{
+	if (length < OPAL_UID_LENGTH)
+		return -ERANGE;
+
+	memcpy(buffer, OPALUID[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
+
+	if (lr == 0)
+		return 0;
+	buffer[5] = LOCKING_RANGE_NON_GLOBAL;
+	buffer[7] = lr;
+
+	return 0;
+}
+
+static int build_locking_user(u8 *buffer, size_t length, u8 lr)
+{
+	if (length < OPAL_UID_LENGTH)
+		return -ERANGE;
+
+	memcpy(buffer, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH);
+
+	buffer[7] = lr + 1;
+
+	return 0;
+}
+
+/*
+ * N = number of format specifiers (1-999) to be replicated
+ * c = u8
+ * u = u64
+ * s = bytestring, length
+ *
+ * ret = test_and_add_token_va(cmd, "c",
+ *			       u8_val1);
+ *
+ * ret = test_and_add_token_va(cmd, "2c2u",
+ *			       u8_val1, u8_val2, u64_val1, u64_val2);
+ *
+ * ret = test_and_add_token_va(cmd, "3s",
+ *			       bytestring1, length1,
+ *			       bytestring2, length2,
+ *			       bytestring3, length3);
+ */
+static int test_and_add_token_va(struct opal_cmd *cmd,
+				 const char *fmt, ...)
+{
+	const u8 *it = fmt, *tmp;
+	int ret, num = 1, sum = 0;
+	va_list ap;
+
+	va_start(ap, fmt);
+
+	while (*it != '\0') {
+		u64 tok64 = 0;
+		u8 tok, *bstr;
+		size_t len;
+
+		ret = 0;
+
+		switch (*it) {
+		case '1' ... '9':
+			tmp = it;
+			num = 0;
+			while (*tmp >= '0' && *tmp <= '9')
+				num = num * 10 + (*tmp++ - '0');
+			it = tmp;
+			continue;
+		case 'c':
+			while (num--) {
+				tok = va_arg(ap, unsigned int);
+				ret = test_and_add_token_u8(cmd, tok);
+				if (ret < 0)
+					goto err;
+			}
+			num = 1;
+			break;
+		case 'u':
+			while (num--) {
+				tok64 = va_arg(ap, u64);
+				ret = test_and_add_token_u64(cmd, tok64);
+				if (ret < 0)
+					goto err;
+			}
+			num = 1;
+			break;
+		case 's':
+			while (num--) {
+				bstr = va_arg(ap, u8 *);
+				len = va_arg(ap, size_t);
+				ret = test_and_add_token_bytestring(cmd, bstr,
+								    len);
+				if (ret < 0)
+					goto err;
+			}
+			num = 1;
+			break;
+		case ' ':
+		case '\t':
+			/* ignored */
+			break;
+		default:
+			pr_warn("Unrecognized type.\n");
+		}
+
+		it++;
+		sum += ret;
+	}
+
+	va_end(ap);
+
+	return sum;
+
+ err:
+	pr_err("Token failed to be added.\n");
+	return ret;
+}
+
+static void set_comID(struct opal_cmd *cmd, u16 comID)
+{
+	struct opal_header *hdr = (struct opal_header *)cmd->cmd;
+
+	hdr->cp.extendedComID[0] = comID >> 8;
+	hdr->cp.extendedComID[1] = comID;
+	hdr->cp.extendedComID[2] = 0;
+	hdr->cp.extendedComID[3] = 0;
+}
+
+static int cmd_finalize(struct opal_cmd *cmd, u32 hsn, u32 tsn)
+{
+	struct opal_header *hdr;
+	int ret;
+
+	ret = test_and_add_token_va(cmd, "6c",
+				    OPAL_ENDOFDATA, OPAL_STARTLIST,
+				    0, 0, 0, OPAL_ENDLIST);
+
+	if (ret < 0) {
+		pr_err("Error finalizing command.\n");
+		return -EFAULT;
+	}
+
+	hdr = (struct opal_header *) cmd->cmd;
+
+	hdr->pkt.TSN = cpu_to_be32(tsn);
+	hdr->pkt.HSN = cpu_to_be32(hsn);
+
+	hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr));
+	while (cmd->pos % 4) {
+		if (cmd->pos >= IO_BUFFER_LENGTH) {
+			pr_err("Error: Buffer overrun\n");
+			return -ERANGE;
+		}
+		cmd->cmd[cmd->pos++] = 0;
+	}
+	hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) -
+				      sizeof(hdr->pkt));
+	hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp));
+
+	return 0;
+}
+
+static enum OPAL_RESPONSE_TOKEN token_type(const struct parsed_resp *resp,
+					   int n)
+{
+	const struct opal_resp_tok *tok;
+
+	if (n >= resp->num) {
+		pr_err("Token number doesn't exist: %d, resp: %d\n",
+		       n, resp->num);
+		return OPAL_DTA_TOKENID_INVALID;
+	}
+
+	tok = &resp->toks[n];
+	if (tok->len == 0) {
+		pr_err("Token length must be non-zero\n");
+		return OPAL_DTA_TOKENID_INVALID;
+	}
+
+	return tok->type;
+}
+
+/*
+ * This function returns 0 in case of invalid token. One should call
+ * token_type() first to find out if the token is valid or not.
+ */
+static enum OPAL_TOKEN response_get_token(const struct parsed_resp *resp,
+					  int n)
+{
+	const struct opal_resp_tok *tok;
+
+	if (n >= resp->num) {
+		pr_err("Token number doesn't exist: %d, resp: %d\n",
+		       n, resp->num);
+		return 0;
+	}
+
+	tok = &resp->toks[n];
+	if (tok->len == 0) {
+		pr_err("Token length must be non-zero\n");
+		return 0;
+	}
+
+	return tok->pos[0];
+}
+
+static size_t response_parse_tiny(struct opal_resp_tok *tok,
+				  const u8 *pos)
+{
+	tok->pos = pos;
+	tok->len = 1;
+	tok->width = OPAL_WIDTH_TINY;
+
+	if (pos[0] & TINY_ATOM_SIGNED) {
+		tok->type = OPAL_DTA_TOKENID_SINT;
+	} else {
+		tok->type = OPAL_DTA_TOKENID_UINT;
+		tok->stored.u = pos[0] & 0x3f;
+	}
+
+	return tok->len;
+}
+
+static size_t response_parse_short(struct opal_resp_tok *tok,
+				   const u8 *pos)
+{
+	tok->pos = pos;
+	tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1;
+	tok->width = OPAL_WIDTH_SHORT;
+
+	if (pos[0] & SHORT_ATOM_BYTESTRING) {
+		tok->type = OPAL_DTA_TOKENID_BYTESTRING;
+	} else if (pos[0] & SHORT_ATOM_SIGNED) {
+		tok->type = OPAL_DTA_TOKENID_SINT;
+	} else {
+		u64 u_integer = 0;
+		int i, b = 0;
+
+		tok->type = OPAL_DTA_TOKENID_UINT;
+		if (tok->len > 9) {
+			pr_warn("uint64 with more than 8 bytes\n");
+			return -EINVAL;
+		}
+		for (i = tok->len - 1; i > 0; i--) {
+			u_integer |= ((u64)pos[i] << (8 * b));
+			b++;
+		}
+		tok->stored.u = u_integer;
+	}
+
+	return tok->len;
+}
+
+static size_t response_parse_medium(struct opal_resp_tok *tok,
+				    const u8 *pos)
+{
+	tok->pos = pos;
+	tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2;
+	tok->width = OPAL_WIDTH_MEDIUM;
+
+	if (pos[0] & MEDIUM_ATOM_BYTESTRING)
+		tok->type = OPAL_DTA_TOKENID_BYTESTRING;
+	else if (pos[0] & MEDIUM_ATOM_SIGNED)
+		tok->type = OPAL_DTA_TOKENID_SINT;
+	else
+		tok->type = OPAL_DTA_TOKENID_UINT;
+
+	return tok->len;
+}
+
+#define LONG_ATOM_ID (BIT(7) | BIT(6) | BIT(5))
+#define LONG_ATOM_BYTESTRING BIT(1)
+#define LONG_ATOM_SIGNED BIT(0)
+static size_t response_parse_long(struct opal_resp_tok *tok,
+				  const u8 *pos)
+{
+	tok->pos = pos;
+	tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4;
+	tok->width = OPAL_WIDTH_LONG;
+
+	if (pos[0] & LONG_ATOM_BYTESTRING)
+		tok->type = OPAL_DTA_TOKENID_BYTESTRING;
+	else if (pos[0] & LONG_ATOM_SIGNED)
+		tok->type = OPAL_DTA_TOKENID_SINT;
+	else
+		tok->type = OPAL_DTA_TOKENID_UINT;
+
+	return tok->len;
+}
+
+static size_t response_parse_token(struct opal_resp_tok *tok,
+				   const u8 *pos)
+{
+	tok->pos = pos;
+	tok->len = 1;
+	tok->type = OPAL_DTA_TOKENID_TOKEN;
+	tok->width = OPAL_WIDTH_TOKEN;
+
+	return tok->len;
+}
+
+static int response_parse(const u8 *buf, size_t length,
+			  struct parsed_resp *resp)
+{
+	const struct opal_header *hdr;
+	struct opal_resp_tok *iter;
+	int ret, num_entries = 0;
+	u32 cpos = 0, total;
+	size_t token_length;
+	const u8 *pos;
+
+	if (!buf)
+		return -EFAULT;
+
+	if (!resp)
+		return -EFAULT;
+
+	hdr = (struct opal_header *)buf;
+	pos = buf;
+	pos += sizeof(*hdr);
+
+	pr_debug("Response size: cp: %d, pkt: %d, subpkt: %d\n",
+		 be32_to_cpu(hdr->cp.length),
+		 be32_to_cpu(hdr->pkt.length),
+		 be32_to_cpu(hdr->subpkt.length));
+
+	if ((hdr->cp.length == 0)
+	    || (hdr->pkt.length == 0)
+	    || (hdr->subpkt.length == 0)) {
+		pr_err("Bad header length. cp: %d, pkt: %d, subpkt: %d\n",
+		       be32_to_cpu(hdr->cp.length),
+		       be32_to_cpu(hdr->pkt.length),
+		       be32_to_cpu(hdr->subpkt.length));
+		print_buffer(pos, sizeof(*hdr));
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (pos > buf + length) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	iter = resp->toks;
+	total = be32_to_cpu(hdr->subpkt.length);
+	print_buffer(pos, total);
+	while (cpos < total) {
+		if (!(pos[0] & 0x80)) /* tiny atom */
+			token_length = response_parse_tiny(iter, pos);
+		else if (!(pos[0] & 0x40)) /* short atom */
+			token_length = response_parse_short(iter, pos);
+		else if (!(pos[0] & 0x20)) /* medium atom */
+			token_length = response_parse_medium(iter, pos);
+		else if (!(pos[0] & 0x10)) /* long atom */
+			token_length = response_parse_long(iter, pos);
+		else /* TOKEN */
+			token_length = response_parse_token(iter, pos);
+
+		if (token_length == -EINVAL) {
+			ret = -EINVAL;
+			goto err;
+		}
+
+		pos += token_length;
+		cpos += token_length;
+		iter++;
+		num_entries++;
+	}
+
+	if (num_entries == 0) {
+		pr_err("Couldn't parse response.\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	resp->num = num_entries;
+
+	return 0;
+err:
+	return ret;
+}
+
+static size_t response_get_string(const struct parsed_resp *resp, int n,
+				  const char **store)
+{
+	*store = NULL;
+	if (!resp) {
+		pr_err("Response is NULL\n");
+		return 0;
+	}
+
+	if (n > resp->num) {
+		pr_err("Response has %d tokens. Can't access %d\n",
+		       resp->num, n);
+		return 0;
+	}
+
+	if (resp->toks[n].type != OPAL_DTA_TOKENID_BYTESTRING) {
+		pr_err("Token is not a byte string!\n");
+		return 0;
+	}
+
+	*store = resp->toks[n].pos + 1;
+	return resp->toks[n].len - 1;
+}
+
+static u64 response_get_u64(const struct parsed_resp *resp, int n)
+{
+	if (!resp) {
+		pr_err("Response is NULL\n");
+		return 0;
+	}
+
+	if (n > resp->num) {
+		pr_err("Response has %d tokens. Can't access %d\n",
+		       resp->num, n);
+		return 0;
+	}
+
+	if (resp->toks[n].type != OPAL_DTA_TOKENID_UINT) {
+		pr_err("Token is not unsigned it: %d\n",
+		       resp->toks[n].type);
+		return 0;
+	}
+
+	if (!((resp->toks[n].width == OPAL_WIDTH_TINY) ||
+	      (resp->toks[n].width == OPAL_WIDTH_SHORT))) {
+		pr_err("Atom is not short or tiny: %d\n",
+		       resp->toks[n].width);
+		return 0;
+	}
+
+	return resp->toks[n].stored.u;
+}
+
+static u8 response_status(const struct parsed_resp *resp)
+{
+	if ((token_type(resp, 0) == OPAL_DTA_TOKENID_TOKEN)
+	    && (response_get_token(resp, 0) == OPAL_ENDOFSESSION)) {
+		return 0;
+	}
+
+	if (resp->num < 5)
+		return DTAERROR_NO_METHOD_STATUS;
+
+	if ((token_type(resp, resp->num - 1) != OPAL_DTA_TOKENID_TOKEN) ||
+	    (token_type(resp, resp->num - 5) != OPAL_DTA_TOKENID_TOKEN) ||
+	    (response_get_token(resp, resp->num - 1) != OPAL_ENDLIST) ||
+	    (response_get_token(resp, resp->num - 5) != OPAL_STARTLIST))
+		return DTAERROR_NO_METHOD_STATUS;
+
+	return response_get_u64(resp, resp->num - 4);
+}
+
+/* Parses and checks for errors */
+static int parse_and_check_status(struct opal_dev *dev)
+{
+	struct opal_cmd *cmd;
+	int error;
+
+	cmd = &dev->cmd;
+	print_buffer(cmd->cmd, cmd->pos);
+
+	error = response_parse(cmd->resp, IO_BUFFER_LENGTH, &dev->parsed);
+	if (error) {
+		pr_err("%s: Couldn't parse response.\n", dev->disk_name);
+		goto err_return;
+	}
+
+	error = response_status(&dev->parsed);
+	if (error)
+		pr_err("%s: Response Status: %d\n", dev->disk_name,
+		       error);
+
+ err_return:
+	return error;
+}
+
+static void clear_opal_cmd(struct opal_cmd *cmd)
+{
+	cmd->pos = sizeof(struct opal_header);
+	memset(cmd->cmd, 0, IO_BUFFER_LENGTH);
+	cmd->cb = NULL;
+	cmd->cb_data = NULL;
+}
+
+static int start_opal_session_cont(void *data)
+{
+	struct opal_dev *dev = data;
+	u32 HSN, TSN;
+	int error = 0;
+
+	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:
+	return error;
+}
+
+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;
+}
+
+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 continuation.
+ * We use this when we don't care about the response data
+ * and simply want to check the status and continue.
+ */
+static int generic_cont(void *data)
+{
+	struct opal_dev *dev = data;
+
+	return parse_and_check_status(dev);
+}
+
+static int end_session_cont(void *data)
+{
+	struct opal_dev *dev = data;
+
+	dev->HSN = 0;
+	dev->TSN = 0;
+	return generic_cont(data);
+}
+
+static int finalize_and_send(struct opal_dev *dev, struct opal_cmd *cmd,
+			     cont_fn 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);
+
+	return opal_send_recv(dev, cont);
+}
+
+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 int get_active_key_cont(void *data)
+{
+	struct opal_dev *dev = data;
+	const char *activekey;
+	size_t keylen;
+	int error = 0;
+
+	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;
+		goto err_return;
+	}
+
+	dev->prev_d_len = keylen;
+
+ err_return:
+	return error;
+}
+
+static int get_active_key(struct opal_dev *dev)
+{
+	const u8 *method;
+	u8 uid[OPAL_UID_LENGTH];
+	struct opal_cmd *cmd;
+	int ret;
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+	set_comID(cmd, dev->comID);
+
+	method = OPALMETHOD[OPAL_GET];
+
+	ret = build_locking_range(uid, sizeof(uid), dev->lr);
+	if (ret < 0) {
+		pr_err("%s: Can't build locking range\n", dev->disk_name);
+		return -EINVAL;
+	}
+
+	ret = test_and_add_token_va(cmd, "c2s 6c 4c 2c",
+				    OPAL_CALL,
+				    uid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+
+				    OPAL_STARTLIST,
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_03, /* startCloumn */
+				    OPAL_TINY_UINT_10, /* ActiveKey */
+				    OPAL_ENDNAME,
+
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_04, /* endColumn */
+				    OPAL_TINY_UINT_10, /* ActiveKey */
+				    OPAL_ENDNAME,
+
+				    OPAL_ENDLIST,
+				    OPAL_ENDLIST);
+	if (ret < 0) {
+		pr_err("%s: Error building get active key command\n",
+		       dev->disk_name);
+		return ret;
+	}
+
+	return finalize_and_send(dev, cmd, get_active_key_cont);
+}
+
+static inline int enable_global_lr(struct opal_cmd *cmd, u8 *uid,
+				   struct opal_user_lr_setup *setup)
+{
+	const u8 *method;
+
+	method = OPALMETHOD[OPAL_SET];
+	return test_and_add_token_va(cmd, "c2s 4c 2cuc 2cuc 4c 4c 3c",
+				     OPAL_CALL,
+				     uid, OPAL_UID_LENGTH,
+				     method, OPAL_METHOD_LENGTH,
+
+				     OPAL_STARTLIST,
+				     OPAL_STARTNAME,
+				     OPAL_VALUES,
+				     OPAL_STARTLIST,
+
+				     OPAL_STARTNAME,
+				     OPAL_TINY_UINT_05, /* ReadLockEnabled */
+				     !!setup->RLE,
+				     OPAL_ENDNAME,
+
+				     OPAL_STARTNAME,
+				     OPAL_TINY_UINT_06, /* WriteLockEnabled */
+				     !!setup->WLE,
+				     OPAL_ENDNAME,
+
+				     OPAL_STARTNAME,
+				     OPAL_READLOCKED,
+				     OPAL_FALSE,
+				     OPAL_ENDNAME,
+
+				     OPAL_STARTNAME,
+				     OPAL_WRITELOCKED,
+				     OPAL_FALSE,
+				     OPAL_ENDNAME,
+
+				     OPAL_ENDLIST,
+				     OPAL_ENDNAME,
+				     OPAL_ENDLIST);
+}
+
+static int setup_locking_range(struct opal_dev *dev)
+{
+	const u8 *method;
+	u8 uid[OPAL_UID_LENGTH];
+	struct opal_cmd *cmd;
+	struct opal_user_lr_setup *setup;
+	int ret;
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+	set_comID(cmd, dev->comID);
+
+	method = OPALMETHOD[OPAL_SET];
+	ret = build_locking_range(uid, sizeof(uid), dev->lr);
+	if (ret < 0) {
+		pr_err("%s: Can't build locking range\n", dev->disk_name);
+		return -EINVAL;
+	}
+	setup = dev->func_data[dev->state - 1];
+	if (dev->lr == 0)
+		ret = enable_global_lr(cmd, uid, setup);
+	else
+		ret = test_and_add_token_va(cmd, "c2s  4c 2cuc 2cuc 2cuc 2cu 4c",
+				    OPAL_CALL,
+				    uid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+				    OPAL_VALUES,
+				    OPAL_STARTLIST,
+
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_03, /* Range Start */
+				    setup->range_start,
+				    OPAL_ENDNAME,
+
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_04, /* Range Length */
+				    setup->range_length,
+				    OPAL_ENDNAME,
+
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_05, /* ReadLockEnabled */
+				    !!setup->RLE,
+				    OPAL_ENDNAME,
+
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_06, /* WriteLockEnabled */
+				    !!setup->WLE,
+
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST,
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST);
+	if (ret < 0) {
+		pr_err("%s: Error building Setup Locking range command.\n",
+		       dev->disk_name);
+		return ret;
+
+	}
+
+	return finalize_and_send(dev, cmd, generic_cont);
+}
+
+static int start_adminsp_opal_session(struct opal_dev *dev,
+				      enum OPAL_UID auth,
+				      const char *key,
+				      u8 key_len)
+{
+	const u8 *method, *smuid, *admin_sp, *hsa;
+	struct opal_cmd *cmd;
+	u32 HSN;
+	int ret;
+
+	if (key == NULL && auth != OPAL_ANYBODY_UID) {
+		pr_err("%s: Attempted to open ADMIN_SP Session without a Host" \
+		       "Challenge, and not as the Anybody UID\n", __func__);
+		return 1;
+	}
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+
+	set_comID(cmd, dev->comID);
+	HSN = GENERIC_HOST_SESSION_NUM;
+
+	smuid = OPALUID[OPAL_SMUID_UID];
+	method = OPALMETHOD[OPAL_STARTSESSION];
+	admin_sp = OPALUID[OPAL_ADMINSP_UID];
+
+	ret = test_and_add_token_va(cmd, "c2s cusc",
+				    OPAL_CALL,
+				    smuid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+				    OPAL_STARTLIST,
+				    HSN,
+				    admin_sp, OPAL_UID_LENGTH,
+				    OPAL_TINY_UINT_01);
+	if (ret < 0) {
+		pr_err("%s: Error building start adminsp session command.\n",
+		       dev->disk_name);
+		return ret;
+	}
+
+	switch (auth) {
+	case OPAL_ANYBODY_UID:
+		/* nothing left to do for anybody, just end and finalize */
+		ret = test_and_add_token_va(cmd, "c",
+					    OPAL_ENDLIST);
+		break;
+	case OPAL_SID_UID:
+		hsa = OPALUID[OPAL_SID_UID];
+		ret = test_and_add_token_va(cmd, "2c s 3c s 2c",
+					    OPAL_STARTNAME,
+					    OPAL_TINY_UINT_00, /* HostChallenge */
+					    key, key_len,
+					    OPAL_ENDNAME,
+					    OPAL_STARTNAME,
+					    OPAL_TINY_UINT_03, /* HostSignAuth */
+					    hsa, OPAL_UID_LENGTH,
+					    OPAL_ENDNAME,
+					    OPAL_ENDLIST);
+		break;
+	default:
+		pr_err("Cannot start Admin SP session with auth %d\n", auth);
+		return 1;
+	}
+
+	if (ret < 0) {
+		pr_err("%s: Error building start adminsp session command.\n",
+		       dev->disk_name);
+		return ret;
+	}
+
+	return finalize_and_send(dev, cmd, start_opal_session_cont);
+}
+
+static int start_anybodyASP_opal_session(struct opal_dev *dev)
+{
+	return start_adminsp_opal_session(dev, OPAL_ANYBODY_UID, NULL, 0);
+}
+
+static int start_SIDASP_opal_session(struct opal_dev *dev)
+{
+	int ret;
+	const u8 *key = dev->prev_data;
+
+	if (!key)
+		ret = start_adminsp_opal_session(dev, OPAL_SID_UID, dev->key,
+						 dev->key_len);
+	else {
+		ret = start_adminsp_opal_session(dev, OPAL_SID_UID, key,
+						 dev->prev_d_len);
+		kfree(key);
+		dev->prev_data = NULL;
+	}
+	return ret;
+}
+
+static int start_lockingsp_opal_session(struct opal_dev *dev,
+					enum OPAL_UID auth, const u8 *key,
+					u8 key_len)
+{
+
+	const u8 *method, *smuid, *locking_sp, *hsa;
+	struct opal_cmd *cmd;
+	size_t klen = key_len;
+	u32 HSN;
+	int ret;
+
+	if (key == NULL) {
+		pr_err("Cannot start Locking SP session without a key\n");
+		return -EINVAL;
+	}
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+
+	set_comID(cmd, dev->comID);
+	HSN = GENERIC_HOST_SESSION_NUM;
+
+	smuid = OPALUID[OPAL_SMUID_UID];
+	method = OPALMETHOD[OPAL_STARTSESSION];
+	locking_sp = OPALUID[OPAL_LOCKINGSP_UID];
+	hsa = OPALUID[auth];
+
+	ret = test_and_add_token_va(cmd, "c2s cusc 2csc 2csc c",
+				    OPAL_CALL,
+				    smuid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+
+				    OPAL_STARTLIST,
+				    HSN,
+				    locking_sp, OPAL_UID_LENGTH,
+				    OPAL_TINY_UINT_01,
+
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_00, /* HostChallenge */
+				    key, klen,
+				    OPAL_ENDNAME,
+
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_03, /* Host Sign Authority */
+				    hsa, OPAL_UID_LENGTH,
+				    OPAL_ENDNAME,
+
+				    OPAL_ENDLIST);
+
+	if (ret < 0) {
+		pr_err("%s: Error building start adminsp session command.\n",
+		       dev->disk_name);
+		return ret;
+	}
+	return finalize_and_send(dev, cmd, start_opal_session_cont);
+}
+
+static inline int start_admin1LSP_opal_session(struct opal_dev *dev)
+{
+	return start_lockingsp_opal_session(dev, OPAL_ADMIN1_UID,
+					    dev->key, dev->key_len);
+}
+
+static int start_auth_opal_session(struct opal_dev *dev)
+{
+	const u8 *method, *smuid, *locking_sp;
+	u8 lk_ul_user[OPAL_UID_LENGTH];
+	struct opal_cmd *cmd;
+	u32 HSN;
+	int ret;
+	struct opal_user_info *uinfo;
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+
+	set_comID(cmd, dev->comID);
+
+	HSN = GENERIC_HOST_SESSION_NUM;
+
+	uinfo = dev->func_data[dev->state - 1];
+
+	smuid = OPALUID[OPAL_SMUID_UID];
+	method = OPALMETHOD[OPAL_STARTSESSION];
+	locking_sp = OPALUID[OPAL_LOCKINGSP_UID];
+
+	if (uinfo->SUM) {
+		ret = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
+					 dev->lr);
+		if (ret < 0) {
+			pr_err("%s: Can't build locking user\n",
+			       dev->disk_name);
+			return ret;
+		}
+	} else if (uinfo->who != OPAL_ADMIN1 && !uinfo->SUM) {
+		ret = build_locking_user(lk_ul_user, sizeof(lk_ul_user),
+					 uinfo->who - 1);
+		if (ret < 0) {
+			pr_err("%s: Can't build locking user\n",
+			       dev->disk_name);
+			return ret;
+		}
+	} else
+		memcpy(lk_ul_user, OPALUID[OPAL_ADMIN1_UID], OPAL_UID_LENGTH);
+
+
+	ret = test_and_add_token_va(cmd, "c2s cus3cs3c s 2c",
+				    OPAL_CALL,
+				    smuid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+
+				    OPAL_STARTLIST,
+				    HSN,
+				    locking_sp, OPAL_UID_LENGTH,
+				    OPAL_TINY_UINT_01,
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_00,
+				    dev->key, dev->key_len,
+				    OPAL_ENDNAME,
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_03,
+
+				    lk_ul_user, OPAL_UID_LENGTH,
+
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST);
+
+	if (ret < 0) {
+		pr_err("%s: Error building STARTSESSION command.\n",
+		       dev->disk_name);
+		return ret;
+	}
+
+	return finalize_and_send(dev, cmd, start_opal_session_cont);
+}
+
+static int revert_tper(struct opal_dev *dev)
+{
+	const u8 *method, *smuid;
+	struct opal_cmd *cmd;
+	int ret;
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+
+	set_comID(cmd, dev->comID);
+
+	smuid = OPALUID[OPAL_ADMINSP_UID];
+	method = OPALMETHOD[OPAL_REVERT];
+
+	ret = test_and_add_token_va(cmd, "c2s 2c",
+				    OPAL_CALL,
+				    smuid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+				    OPAL_STARTLIST,
+				    OPAL_ENDLIST);
+	if (ret < 0) {
+		pr_err("%s: Error building REVERT TPER command.\n",
+		       dev->disk_name);
+		return ret;
+	}
+
+	return finalize_and_send(dev, cmd, generic_cont);
+}
+
+static int internal_activate_user(struct opal_dev *dev)
+{
+	const u8 *method;
+	u8 uid[OPAL_UID_LENGTH];
+	struct opal_cmd *cmd;
+	int ret;
+	struct opal_key_and_user *act;
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+	set_comID(cmd, dev->comID);
+
+	act = dev->func_data[dev->state - 1];
+
+	memcpy(uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH);
+	uid[7] = act->who.who;
+
+	method = OPALMETHOD[OPAL_SET];
+
+	ret = test_and_add_token_va(cmd, "c2s 3c c 4c 3c",
+				    OPAL_CALL,
+				    uid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_01, /* Values */
+
+				    OPAL_STARTLIST,
+
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_05, /* Enabled */
+				    OPAL_TINY_UINT_01, /* True */
+				    OPAL_ENDNAME,
+
+				    OPAL_ENDLIST,
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST);
+
+	if (ret < 0) {
+		pr_err("%s: Error building Activate UserN command.\n",
+		       dev->disk_name);
+		return ret;
+	}
+
+	return finalize_and_send(dev, cmd, generic_cont);
+}
+
+static int erase_locking_range(struct opal_dev *dev)
+{
+	const u8 *method;
+	u8 uid[OPAL_UID_LENGTH];
+	struct opal_cmd *cmd;
+	int ret;
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+	set_comID(cmd, dev->comID);
+
+	method = OPALMETHOD[OPAL_ERASE];
+
+	if (build_locking_range(uid, sizeof(uid), dev->lr) < 0) {
+		pr_err("%s: Can't build locking range\n", dev->disk_name);
+		return -EINVAL;
+	}
+
+	ret = test_and_add_token_va(cmd, "c2s 2c",
+				    OPAL_CALL,
+				    uid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+
+				    OPAL_STARTLIST,
+				    OPAL_ENDLIST);
+
+	if (ret < 0) {
+		pr_err("%s: Error building Erase Locking Range Cmmand.\n",
+		       dev->disk_name);
+		return ret;
+	}
+	return finalize_and_send(dev, cmd, generic_cont);
+}
+
+static int set_mbr_done(struct opal_dev *dev)
+{
+	const u8 *method, *uid;
+	struct opal_cmd *cmd;
+	int ret;
+	u8 mbr_done_tf = *(u8 *)dev->func_data[dev->state - 1];
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+	set_comID(cmd, dev->comID);
+
+	method = OPALMETHOD[OPAL_SET];
+	uid = OPALUID[OPAL_MBRCONTROL];
+
+	ret = test_and_add_token_va(cmd, "c2s 3c 6c 2c",
+				    OPAL_CALL,
+				    uid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+				    OPAL_VALUES,
+
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_02, /* Done */
+				    mbr_done_tf,       /* Done T or F */
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST,
+
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST);
+	if (ret < 0) {
+		pr_err("%s: Error Building set MBR Done command\n",
+		       dev->disk_name);
+		return ret;
+	}
+
+	return finalize_and_send(dev, cmd, generic_cont);
+}
+
+static int set_mbr_enable_disable(struct opal_dev *dev)
+{
+	const u8 *method, *uid;
+	struct opal_cmd *cmd;
+	int ret;
+	u8 mbr_en_dis = *(u8 *)dev->func_data[dev->state - 1];
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+	set_comID(cmd, dev->comID);
+
+	method = OPALMETHOD[OPAL_SET];
+	uid = OPALUID[OPAL_MBRCONTROL];
+
+	ret = test_and_add_token_va(cmd, "c2s 3c 6c 2c",
+				    OPAL_CALL,
+				    uid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+				    OPAL_VALUES,
+
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_01, /* Enable */
+				    mbr_en_dis,        /* Enable or Disable */
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST,
+
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST);
+	if (ret < 0) {
+		pr_err("%s: Error Building set MBR done command\n",
+		       dev->disk_name);
+		return ret;
+	}
+
+	return finalize_and_send(dev, cmd, generic_cont);
+}
+
+static int set_new_pw(struct opal_dev *dev)
+{
+	const u8 *method;
+	u8 cpin_uid[OPAL_UID_LENGTH];
+	struct opal_cmd *cmd;
+	int ret;
+	struct opal_new_pw *pw;
+	size_t key_len;
+	u8 *key;
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+	set_comID(cmd, dev->comID);
+
+	pw = dev->func_data[dev->state - 1];
+	key = pw->new_pin.key;
+	key_len = pw->new_pin.key_len;
+	memcpy(cpin_uid, OPALUID[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH);
+
+	if (pw->user_for_pw != OPAL_ADMIN1) {
+		cpin_uid[5] = 0x03;
+		if (pw->who.SUM)
+			cpin_uid[7] = pw->new_pin.lr + 1;
+		else
+			cpin_uid[7] = pw->user_for_pw;
+	}
+
+	method = OPALMETHOD[OPAL_SET];
+
+	ret = test_and_add_token_va(cmd, "c2s 3c 3cs2c 2c",
+				    OPAL_CALL,
+				    cpin_uid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_01, /* Values */
+
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_03, /* PIN */
+				    key, key_len,
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST,
+
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST);
+
+	if (ret < 0) {
+		pr_err("%s: Error building SET AMIN1 PIN command.\n",
+		       dev->disk_name);
+		return ret;
+	}
+
+	return finalize_and_send(dev, cmd, generic_cont);
+}
+
+static int set_sid_cpin_pin(struct opal_dev *dev)
+{
+	const u8 *method, *cpin_uid;
+	struct opal_cmd *cmd;
+	int ret;
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+	set_comID(cmd, dev->comID);
+
+	cpin_uid = OPALUID[OPAL_C_PIN_SID];
+	method = OPALMETHOD[OPAL_SET];
+
+	ret = test_and_add_token_va(cmd, "c2s 2c 4cs2c 2c",
+				    OPAL_CALL,
+				    cpin_uid, OPAL_UID_LENGTH,
+				    method, OPAL_METHOD_LENGTH,
+
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+
+				    OPAL_TINY_UINT_01, /* Values */
+				    OPAL_STARTLIST,
+				    OPAL_STARTNAME,
+				    OPAL_TINY_UINT_03, /* PIN */
+				    dev->key, dev->key_len,
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST,
+
+				    OPAL_ENDNAME,
+				    OPAL_ENDLIST);
+
+	if (ret < 0) {
+		pr_err("%s: Error building SET CPIN PIN command.\n",
+		       dev->disk_name);
+		return ret;
+	}
+
+	return finalize_and_send(dev, cmd, generic_cont);
+}
+
+static int query_locking_range_cont(void *data)
+{
+	struct opal_dev *dev = data;
+	int error;
+
+	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:
+	return error;
+}
+
+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 int get_lsp_lifecycle_cont(void *data)
+{
+	struct opal_dev *dev = data;
+	u8 lc_status;
+	int error = 0;
+
+	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;
+		goto err_return;
+	}
+
+err_return:
+	return error;
+}
+
+/* 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 int get_msid_cpin_pin_cont(void *data)
+{
+	const char *msid_pin;
+	struct opal_dev *dev = data;
+	size_t strlen;
+	int error = 0;
+
+	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;
+		goto err_return;
+	}
+
+	dev->prev_d_len = strlen;
+
+ err_return:
+	return error;
+}
+
+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(struct opal_dev *dev)
+{
+	dev->resume_from_suspend = false;
+	dev->resume_data = NULL;
+	dev->func_data = NULL;
+}
+
+static int build_end_opal_session(struct opal_dev *dev)
+{
+	struct opal_cmd *cmd;
+
+	cmd = &dev->cmd;
+	clear_opal_cmd(cmd);
+
+	set_comID(cmd, dev->comID);
+	return test_and_add_token_u8(cmd, OPAL_ENDOFSESSION);
+}
+
+static int end_opal_session(struct opal_dev *dev)
+{
+	int ret = build_end_opal_session(dev);
+
+	if (ret < 0)
+		return ret;
+	return finalize_and_send(dev, &dev->cmd, end_session_cont);
+}
+
+static struct opal_dev *find_opal_dev(dev_t majmin, u8 lr)
+{
+	struct opal_dev *iter, *opal_dev = NULL;
+
+	list_for_each_entry(iter, &opal_list, node) {
+		if (MAJOR(iter->majmin) != MAJOR(majmin) ||
+		    MINOR(iter->majmin) != MINOR(majmin))
+			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->state = new_dev->state;
+	old_dev->funcs = new_dev->funcs;
+	old_dev->majmin = new_dev->majmin;
+	old_dev->submit_fn = new_dev->submit_fn;
+	old_dev->submit_data = new_dev->submit_data;
+
+	clean_function_data(old_dev);
+
+	/*
+	 * 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->majmin, 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);
+
+	return error;
+}
+
+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;
+	return next(dev);
+}
+
+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->majmin = bdev->bd_dev;
+	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->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, void *sbmt_data,
+		  sed_sec_submit *submit_fn)
+{
+	struct opal_dev *new_dev = NULL;
+	u8 key_len = key_cmd->key_len;
+	u8 lr = key_cmd->lr;
+	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->submit_data = sbmt_data;
+	new_dev->submit_fn = submit_fn;
+
+	new_dev->state = 0;
+	return next(new_dev);
+}
+
+static struct opal_dev *get_registered_opal_dev(dev_t majmin, u8 lr)
+{
+	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 (MAJOR(iter->majmin) != MAJOR(majmin) ||
+		    MINOR(iter->majmin) != MINOR(majmin))
+			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;
+
+	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;
+
+	atomic_dec(&dev->in_use);
+	spin_lock(&list_spinlock);
+	list_for_each_entry(iter, &opal_list, node) {
+		if (iter == dev) {
+			found = true;
+			break;
+		}
+	}
+
+	spin_unlock(&list_spinlock);
+	if (!found) {
+		clean_opal_key(dev);
+		clean_function_data(dev);
+		kfree(dev);
+	}
+}
+
+static struct opal_dev *get_or_create_opal_dev(struct block_device *bdev,
+					       u8 lr, bool use_new)
+{
+	struct opal_dev *dev = NULL;
+
+	if (!use_new)
+		dev = get_registered_opal_dev(bdev->bd_dev, lr);
+
+	if (!dev)
+		dev = alloc_opal_dev(bdev, lr);
+
+	return dev;
+}
+
+static int setup_opal_dev(struct block_device *bdev,  struct opal_dev *dev,
+			  const opal_step *funcs,  struct opal_key *key,
+			  void *sbmt_data,  sed_sec_submit *submit_fn)
+{
+	int ret;
+
+	dev->state = 0;
+	dev->funcs = funcs;
+	dev->TSN = 0;
+	dev->HSN = 0;
+	dev->lr = key->lr;
+	dev->error_cb = end_opal_session_error;
+	dev->error_cb_data = dev;
+	dev->submit_fn = submit_fn;
+	dev->submit_data = sbmt_data;
+
+	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) {
+			pr_err("%s: Couldn't get key: %d\n",
+			       dev->disk_name, ret);
+			return ret;
+		}
+	}
+	dev->func_data = NULL;
+	return 0;
+}
+
+int opal_secure_erase_locking_range(struct block_device *bdev, struct sed_key *key,
+				    void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	struct opal_dev *dev;
+	void *data[3] = { NULL };
+	const opal_step erase_funcs[] = {
+		opal_discovery0,
+		start_auth_opal_session,
+		get_active_key,
+		gen_key,
+		end_opal_session,
+		NULL,
+	};
+	int ret;
+
+	dev = get_or_create_opal_dev(bdev, key->opal_act.key.lr, true);
+	if (!dev)
+		return -ENOMEM;
+
+	ret = setup_opal_dev(bdev, dev, erase_funcs, &key->opal_act.key,
+			     sbmt_data, submit_fn);
+	dev->func_data = data;
+	dev->func_data[1] = &key->opal_act.who;
+	if (ret)
+		goto error_return;
+
+	ret = next(dev);
+
+ error_return:
+	remove_and_clean_opal_dev(dev);
+	return ret;
+}
+EXPORT_SYMBOL(opal_secure_erase_locking_range);
+
+int opal_erase_locking_range(struct block_device *bdev, struct sed_key *key,
+			     void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	struct opal_dev *dev;
+	const opal_step erase_funcs[] = {
+		opal_discovery0,
+		start_auth_opal_session,
+		erase_locking_range,
+		end_opal_session,
+		NULL,
+	};
+	int ret;
+
+	dev = get_or_create_opal_dev(bdev, key->opal_lrs.key.lr, true);
+	if (!dev)
+		return -ENOMEM;
+
+	ret = setup_opal_dev(bdev, dev, erase_funcs, &key->opal_lrs.key,
+			     sbmt_data, submit_fn);
+	if (ret)
+		goto error_return;
+
+	ret = next(dev);
+
+ 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 *sbmt_data,
+				   sed_sec_submit *submit_fn)
+{
+	void *func_data[6] = { NULL };
+	struct opal_dev *dev;
+	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 (key->opal_mbr.enable_disable != OPAL_MBR_ENABLE &&
+	    key->opal_mbr.enable_disable != OPAL_MBR_DISABLE)
+		return -EINVAL;
+
+	dev = get_or_create_opal_dev(bdev, key->opal_mbr.key.lr, true);
+	if (!dev)
+		return -ENOMEM;
+
+	ret = setup_opal_dev(bdev, dev, mbr_funcs, &key->opal_mbr.key,
+			     sbmt_data, submit_fn);
+	if (ret)
+		goto error_return;
+
+	dev->num_func_data = 6;
+	dev->func_data = func_data;
+	dev->func_data[2] = &key->opal_mbr.enable_disable;
+	dev->func_data[5] = &key->opal_mbr.enable_disable;
+
+	ret = next(dev);
+
+ 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,
+	      void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	void *func_data[3] = { NULL };
+	struct opal_dev *dev;
+		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, key->opal_lk_unlk.key.lr, false);
+	if (!dev)
+		return -ENOMEM;
+	ret = setup_opal_dev(bdev, dev, _auth_funcs, &key->opal_lk_unlk.key,
+			     sbmt_data, submit_fn);
+	if (ret)
+		goto error_return;
+
+	dev->num_func_data = 3;
+	dev->func_data = func_data;
+	dev->func_data[1] = &key->opal_lk_unlk.authority;
+	dev->lkul = key->opal_lk_unlk;
+
+	ret = next(dev);
+
+ error_return:
+	remove_and_clean_opal_dev(dev);
+	return ret;
+}
+EXPORT_SYMBOL(opal_save);
+
+int opal_add_user_to_lr(struct block_device *bdev, struct sed_key *key,
+			void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	void *func_data[3] = { NULL };
+	struct opal_dev *dev;
+		const opal_step funcs[] = {
+		opal_discovery0,
+		start_admin1LSP_opal_session,
+		add_user_to_lr,
+		end_opal_session,
+		NULL
+	};
+	int ret;
+
+	if (!bdev || !bdev->bd_disk) {
+		pr_err("Can't assign user to LR without backing disk\n");
+		return -EFAULT;
+	}
+	if (key->opal_lk_unlk.l_state != OPAL_RO &&
+	    key->opal_lk_unlk.l_state != OPAL_RW) {
+		pr_err("Locking state was not RO or RW\n");
+		return -EINVAL;
+	}
+	if (key->opal_lk_unlk.authority.who < OPAL_USER1 &&
+	    key->opal_lk_unlk.authority.who > OPAL_USER9) {
+		pr_err("Authority was not within the range of users: %d\n",
+		       key->opal_lk_unlk.authority.who);
+		return -EINVAL;
+	}
+	if (key->opal_lk_unlk.authority.SUM) {
+		pr_err("%s not supported in SUM. Use setup locking range\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	dev = get_or_create_opal_dev(bdev, key->opal_lk_unlk.key.lr, true);
+	if (!dev)
+		return -ENOMEM;
+	ret = setup_opal_dev(bdev, dev, funcs, &key->opal_lk_unlk.key,
+				    sbmt_data, submit_fn);
+	if (ret)
+		goto error_return;
+
+	dev->num_func_data = 3;
+	dev->func_data = func_data;
+	dev->func_data[2] = &key->opal_lk_unlk;
+
+	ret = next(dev);
+
+ error_return:
+	remove_and_clean_opal_dev(dev);
+	return ret;
+
+}
+EXPORT_SYMBOL(opal_add_user_to_lr);
+
+int opal_reverttper(struct block_device *bdev, struct sed_key *key,
+		    void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	const opal_step revert_funcs[] = {
+		opal_discovery0,
+		start_SIDASP_opal_session,
+		revert_tper, /* controller will terminate session */
+		NULL,
+	};
+
+	return opal_register(bdev, &key->opal, revert_funcs,
+			     sbmt_data, submit_fn);
+}
+EXPORT_SYMBOL(opal_reverttper);
+
+/* These are global'd because both lock_unlock_internal
+ * and opal_unlock_from_suspend need them.
+ */
+const opal_step ulk_funcs_SUM[] = {
+	opal_discovery0,
+	start_auth_opal_session,
+	lock_unlock_locking_range_SUM,
+	end_opal_session,
+	NULL
+};
+const opal_step _unlock_funcs[] = {
+	opal_discovery0,
+	start_auth_opal_session,
+	lock_unlock_locking_range,
+	end_opal_session,
+	NULL
+};
+int opal_lock_unlock(struct block_device *bdev, struct sed_key *key,
+                     void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	void *func_data[3] = { NULL };
+	struct opal_dev *dev;
+	int ret;
+
+	if (key->opal_lk_unlk.authority.who < OPAL_ADMIN1 ||
+	    key->opal_lk_unlk.authority.who > OPAL_USER9)
+		return -EINVAL;
+
+	dev = get_or_create_opal_dev(bdev, key->opal_lk_unlk.key.lr, true);
+	if (!dev)
+		return -ENOMEM;
+
+	if (key->opal_lk_unlk.authority.SUM)
+		ret = setup_opal_dev(bdev, dev, ulk_funcs_SUM,
+				     &key->opal_lk_unlk.key,
+				     sbmt_data, submit_fn);
+	else
+		ret = setup_opal_dev(bdev, dev, _unlock_funcs,
+				     &key->opal_lk_unlk.key,
+				     sbmt_data, submit_fn);
+	if (ret)
+		goto error_return;
+
+	dev->num_func_data = 3;
+	dev->func_data = func_data;
+	dev->func_data[1] = &key->opal_lk_unlk.authority;
+	dev->func_data[2] = &key->opal_lk_unlk;
+
+	ret = next(dev);
+
+ error_return:
+	remove_and_clean_opal_dev(dev);
+	return ret;
+}
+EXPORT_SYMBOL(opal_lock_unlock);
+
+int opal_take_ownership(struct block_device *bdev, struct sed_key *key,
+			void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	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
+	};
+
+	return opal_register(bdev, &key->opal, owner_funcs, sbmt_data,
+			     submit_fn);
+}
+EXPORT_SYMBOL(opal_take_ownership);
+
+int opal_activate_lsp(struct block_device *bdev, struct sed_key *key,
+		      void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	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
+	};
+	struct opal_dev *dev;
+	int ret;
+
+	dev = get_or_create_opal_dev(bdev, key->opal.lr, true);
+	if (!dev)
+		return -ENOMEM;
+	ret = setup_opal_dev(bdev, dev, active_funcs, &key->opal,
+			     sbmt_data, submit_fn);
+	if (ret)
+		goto error_return;
+
+	ret = next(dev);
+
+ error_return:
+	remove_and_clean_opal_dev(dev);
+	return ret;
+}
+EXPORT_SYMBOL(opal_activate_lsp);
+
+int opal_setup_locking_range(struct block_device *bdev, struct sed_key *pw,
+			     void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	struct opal_dev *dev;
+	void *data[3] = { NULL };
+	const opal_step lr_funcs[] = {
+		opal_discovery0,
+		start_auth_opal_session,
+		setup_locking_range,
+		end_opal_session,
+		NULL,
+	};
+	int ret;
+
+	dev = get_or_create_opal_dev(bdev, pw->opal_lrs.key.lr, true);
+	if (!dev)
+		return -ENOMEM;
+
+	ret = setup_opal_dev(bdev, dev, lr_funcs, &pw->opal_lrs.key,
+			     sbmt_data, submit_fn);
+	if (ret)
+		goto error_return;
+
+	dev->func_data = data;
+	dev->num_func_data = 3;
+	dev->func_data[1] = &pw->opal_lrs.who;
+	dev->func_data[2] = &pw->opal_lrs;
+
+	ret = next(dev);
+
+ error_return:
+	remove_and_clean_opal_dev(dev);
+	return ret;
+}
+EXPORT_SYMBOL(opal_setup_locking_range);
+
+int opal_set_new_pw(struct block_device *bdev, struct sed_key *pw,
+		    void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	const opal_step pw_funcs[] = {
+		opal_discovery0,
+		start_auth_opal_session,
+		set_new_pw,
+		end_opal_session,
+		NULL
+	};
+	struct opal_dev *dev;
+	void *data[3] = { NULL };
+	int ret;
+
+	if (pw->sed_type != OPAL_PW)
+		return -EINVAL;
+
+	if (pw->opal_pw.who.who < OPAL_ADMIN1 ||
+	    pw->opal_pw.who.who > OPAL_USER9)
+		return -EINVAL;
+
+	dev = get_or_create_opal_dev(bdev, pw->opal_pw.current_pin.lr, true);
+	if (!dev)
+		return -ENOMEM;
+
+	ret = setup_opal_dev(bdev, dev, pw_funcs,
+			     &pw->opal_pw.current_pin,
+			     sbmt_data, submit_fn);
+	if (ret)
+		goto error_return;
+
+	dev->num_func_data = 3;
+	dev->func_data = data;
+	dev->func_data[1] = (void *) &pw->opal_pw.who;
+	dev->func_data[2] = (void *) &pw->opal_pw;
+
+	ret = next(dev);
+
+ error_return:
+	remove_and_clean_opal_dev(dev);
+	return ret;
+}
+EXPORT_SYMBOL(opal_set_new_pw);
+
+int opal_activate_user(struct block_device *bdev, struct sed_key *pw,
+		       void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	const opal_step act_funcs[] = {
+		opal_discovery0,
+		start_admin1LSP_opal_session,
+		internal_activate_user,
+		end_opal_session,
+		NULL
+	};
+	struct opal_dev *dev;
+	void *data[3] = { NULL };
+	int ret;
+
+	if (pw->sed_type != OPAL_ACT_USR) {
+		pr_err("Sed type was not act user\n");
+		return -EINVAL;
+	}
+
+	/* We can't activate Admin1 it's active as manufactured */
+	if (pw->opal_act.who.who < OPAL_USER1 &&
+	    pw->opal_act.who.who > OPAL_USER9) {
+		pr_err("Who was not a valid user: %d \n", pw->opal_act.who.who);
+		return -EINVAL;
+	}
+
+	dev = get_or_create_opal_dev(bdev, pw->opal_act.key.lr, true);
+	if (!dev)
+		return -ENOMEM;
+
+	ret = setup_opal_dev(bdev, dev, act_funcs, &pw->opal_act.key,
+			     sbmt_data, submit_fn);
+	if (ret)
+		goto error_return;
+
+	dev->num_func_data = 3;
+	dev->func_data = data;
+	dev->func_data[1] = &pw->opal_act;
+	dev->func_data[2] = &pw->opal_act;
+
+	ret = next(dev);
+
+ error_return:
+	remove_and_clean_opal_dev(dev);
+	return ret;
+
+}
+EXPORT_SYMBOL(opal_activate_user);
+
+int opal_unlock_from_suspend(struct opal_suspend_unlk *data)
+{
+	int majmin = data->dev;
+	struct opal_dev *iter, *dev = NULL;
+	void *func_data[3] = { NULL };
+	u8 count = 0;
+	struct opal_dev *todo[64] = { NULL };
+	int ret = 0;
+	bool was_failure = false;
+
+	spin_lock(&list_spinlock);
+	list_for_each_entry(iter, &opal_list, node) {
+		if (MAJOR(iter->majmin) != MAJOR(majmin) ||
+		    MINOR(iter->majmin) != MINOR(majmin))
+			continue;
+
+		if (atomic_add_unless(&iter->in_use, 1, 1)) {
+			if (count < 64)
+				todo[count++] = iter;
+			else
+				break;
+		}
+	}
+	spin_unlock(&list_spinlock);
+
+	while (count) {
+		dev = todo[--count];
+		dev->func_data = func_data;
+		dev->resume_from_suspend = true;
+		dev->resume_data = data;
+		dev->error_cb = end_opal_session_error;
+		dev->error_cb_data = dev;
+		dev->state = 0;
+		if (dev->lkul.authority.SUM)
+			dev->funcs = ulk_funcs_SUM;
+		else
+			dev->funcs = _unlock_funcs;
+		dev->TSN = 0;
+		dev->HSN = 0;
+		dev->func_data[2] = &dev->lkul;
+		dev->func_data[1] = &dev->lkul.authority;
+		ret = next(dev);
+		if (ret)
+			was_failure = true;
+		unlock_suspend_final(dev);
+	}
+	return was_failure ? 1 : 0;
+}
+EXPORT_SYMBOL(opal_unlock_from_suspend);
diff --git a/block/sed-opal_internal.h b/block/sed-opal_internal.h
new file mode 100644
index 0000000..12369eb
--- /dev/null
+++ b/block/sed-opal_internal.h
@@ -0,0 +1,601 @@
+/*
+ * Copyright ? 2016 Intel Corporation
+ *
+ * Authors:
+ *    Rafael Antognolli <rafael.antognolli at intel.com>
+ *    Scott  Bauer      <scott.bauer at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _NVME_OPAL_INTERNAL_H
+#define _NVME_OPAL_INTERNAL_H
+
+#include <linux/key-type.h>
+#include <keys/user-type.h>
+
+#define DTAERROR_NO_METHOD_STATUS 0x89
+#define GENERIC_HOST_SESSION_NUM 0x41
+
+
+
+/*
+ * Derived from:
+ * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * Section: 5.1.5 Method Status Codes
+ */
+static const char *opal_errors[] = {
+	"Success",
+	"Not Authorized",
+	"Unknown Error",
+	"SP Busy",
+	"SP Failed",
+	"SP Disabled",
+	"SP Frozen",
+	"No Sessions Available",
+	"Uniqueness Conflict",
+	"Insufficient Space",
+	"Insufficient Rows",
+	"Invalid Function",
+	"Invalid Parameter",
+	"Invalid Reference",
+	"Unknown Error",
+	"TPER Malfunction",
+	"Transaction Failure",
+	"Response Overflow",
+	"Authority Locked Out",
+};
+
+static const char *opal_error_to_human(int error)
+{
+	if (error == 0x3f)
+		return "Failed";
+
+	if (error >= ARRAY_SIZE(opal_errors) || error < 0)
+		return "Unknown Error";
+
+	return opal_errors[error];
+}
+
+/*
+ * User IDs used in the TCG storage SSCs
+ * Derived from: TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * Section: 6.3 Assigned UIDs
+ */
+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.
+ * Derived from: TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * Section: 6.3 Assigned UIDs
+ */
+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,
+};
+
+/*
+ * Token defs derived from:
+ * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * 3.2.2 Data Stream Encoding
+ */
+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
+ */
+
+/* Packets derived from:
+ * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * Secion: 3.2.3 ComPackets, Packets & Subpackets
+ */
+
+/* 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
+ * Section: 3.3.5 Capability Discovery
+ */
+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/block/sed.c b/block/sed.c
new file mode 100644
index 0000000..241b1dc
--- /dev/null
+++ b/block/sed.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright ? 2016 Intel Corporation
+ *
+ * Authors:
+ *    Rafael Antognolli <rafael.antognolli at intel.com>
+ *    Scott  Bauer      <scott.bauer at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/blkdev.h>
+#include <linux/sed.h>
+#include <linux/sed-opal.h>
+#include <asm/uaccess.h>
+
+
+int sed_save(struct block_device *bdev, struct sed_key *key,
+	     void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	switch (key->sed_type) {
+	case OPAL_LOCK_UNLOCK:
+		return opal_save(bdev, key, sbmt_data, submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_lock_unlock(struct block_device *bdev, struct sed_key *key,
+		    void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	switch (key->sed_type) {
+	case OPAL_LOCK_UNLOCK:
+		return opal_lock_unlock(bdev, key, sbmt_data, submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_take_ownership(struct block_device *bdev, struct sed_key *key,
+		       void *sbmt_data, sed_sec_submit *submit_fn)
+{
+
+	switch (key->sed_type) {
+	case OPAL:
+		return opal_take_ownership(bdev, key, sbmt_data, submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_activate_lsp(struct block_device *bdev, struct sed_key *key,
+		     void *sbmt_data, sed_sec_submit *submit_fn)
+{
+
+	switch (key->sed_type) {
+	case OPAL:
+		return opal_activate_lsp(bdev, key, sbmt_data, submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_set_pw(struct block_device *bdev, struct sed_key *key,
+	       void *sbmt_data, sed_sec_submit *submit_fn)
+{
+
+	switch (key->sed_type) {
+	case OPAL_PW:
+		return opal_set_new_pw(bdev, key, sbmt_data, submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_activate_user(struct block_device *bdev, struct sed_key *key,
+		      void *sbmt_data, sed_sec_submit *submit_fn)
+{
+
+	switch (key->sed_type) {
+	case OPAL_ACT_USR:
+		return opal_activate_user(bdev, key, sbmt_data, submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_reverttper(struct block_device *bdev, struct sed_key *key,
+		   void *sbmt_data, sed_sec_submit *submit_fn)
+{
+
+	switch (key->sed_type) {
+	case OPAL:
+		return opal_reverttper(bdev, key, sbmt_data, submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key,
+			    void *sbmt_data, sed_sec_submit *submit_fn)
+{
+
+	switch (key->sed_type) {
+	case OPAL_LR_SETUP:
+		return opal_setup_locking_range(bdev, key, sbmt_data, submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key,
+		      void *sbmt_data, sed_sec_submit *submit_fn)
+{
+
+	switch (key->sed_type) {
+	case OPAL_LOCK_UNLOCK:
+		return opal_add_user_to_lr(bdev, key, sbmt_data, submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_do_mbr(struct block_device *bdev, struct sed_key *key,
+	       void *sbmt_data, sed_sec_submit *submit_fn)
+{
+
+	switch (key->sed_type) {
+	case OPAL_MBR_DATA:
+		return opal_enable_disable_shadow_mbr(bdev, key, sbmt_data,
+						      submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_erase_lr(struct block_device *bdev, struct sed_key *key,
+		 void *sbmt_data, sed_sec_submit *submit_fn)
+{
+
+	switch (key->sed_type) {
+	case OPAL:
+		return opal_erase_locking_range(bdev, key, sbmt_data, submit_fn);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int sed_secure_erase_lr(struct block_device *bdev, struct sed_key *key,
+			void *sbmt_data, sed_sec_submit *submit_fn)
+{
+	switch (key->sed_type) {
+	case OPAL_ACT_USR:
+		return opal_secure_erase_locking_range(bdev, key,
+						       sbmt_data, submit_fn);
+
+	}
+	return -EOPNOTSUPP;
+}
+
+
+#define CMD_TO_FN_INDX(cmd) \
+	(cmd) - IOC_SED_SAVE
+
+int (*sed_fn[])(struct block_device *bdev, struct sed_key *key,
+		  void *sbmt_data, sed_sec_submit *submit_fn) =
+{
+	sed_save,
+	sed_lock_unlock,
+	sed_take_ownership,
+	sed_activate_lsp,
+	sed_set_pw,
+	sed_activate_user,
+	sed_reverttper,
+	sed_setup_locking_range,
+	sed_adduser_to_lr,
+	sed_do_mbr,
+	sed_erase_lr,
+	sed_secure_erase_lr
+};
+
+/* The sbmt_ctrl_data is a opaque pointer to some structure which will be used
+ * by the submit_fn to properly submit the opal command to the controller.
+ * The submit_fn must be a blocking call.
+ */
+int blkdev_sed_ioctl(struct block_device *bdev, fmode_t fmode, unsigned int cmd,
+		     unsigned long arg, void *sbmt_ctrl_data,
+		     sed_sec_submit *submit_fn)
+{
+	struct sed_key key;
+
+	 /* Caller should do this but since we're going to use cmd as an index
+	 * lets 'trust but verify'.
+	 */
+	if (!is_sed_ioctl(cmd))
+		return -EINVAL;
+	if (copy_from_user(&key, (void __user *)arg, sizeof(key)))
+		return -EFAULT;
+	return sed_fn[CMD_TO_FN_INDX(cmd)](bdev, &key, sbmt_ctrl_data, submit_fn);
+}
+EXPORT_SYMBOL_GPL(blkdev_sed_ioctl);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 3/4] nvme: Implement resume_from_suspend and sed block ioctl
  2016-11-29 21:51 ` Scott Bauer
@ 2016-11-29 21:52   ` Scott Bauer
  -1 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-29 21:52 UTC (permalink / raw)
  To: linux-nvme
  Cc: keith.busch, sagi, hch, Rafael.Antognolli, axboe, linux-block,
	Scott Bauer, jonathan.derrick, j.naumann

This patch implements the necessary logic to unlock a SED
enabled device coming back from an S3.

The patch also implements the ioctl handling from the block
layer.

Signed-off-by: Scott Bauer <scott.bauer@intel.com>
Signed-off-by: Rafael Antognolli <Rafael.Antognolli@intel.com>
---
 drivers/nvme/host/core.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/nvme/host/nvme.h |  4 ++-
 drivers/nvme/host/pci.c  |  7 ++++-
 3 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 79e679d..9a3eb41 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -28,6 +28,8 @@
 #include <linux/t10-pi.h>
 #include <scsi/sg.h>
 #include <asm/unaligned.h>
+#include <linux/sed.h>
+#include <linux/sed-opal.h>
 
 #include "nvme.h"
 #include "fabrics.h"
@@ -778,11 +780,57 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 	return status;
 }
 
+static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer,
+			   size_t len, bool send)
+{
+	struct request_queue *q;
+	struct request *req;
+	struct nvme_ns *ns;
+	struct nvme_command cmd = { 0 };
+	int ret;
+
+	ns = data;
+
+	if (send)
+		cmd.common.opcode = (u8)nvme_admin_security_send;
+	else
+		cmd.common.opcode = (u8)nvme_admin_security_recv;
+
+	cmd.common.nsid = ns->ns_id;
+	cmd.common.cdw10[0] = cpu_to_le32(((u32)secp) << 24 | ((u32)spsp) << 8);
+	cmd.common.cdw10[1] = cpu_to_le32(len);
+
+	q = ns->ctrl->admin_q;
+
+	req = nvme_alloc_request(q, &cmd, 0, NVME_QID_ANY);
+	if (IS_ERR(req)) {
+		ret = PTR_ERR(req);
+		return ret;
+	}
+
+	req->timeout = ADMIN_TIMEOUT;
+	req->special = NULL;
+
+	if (buffer && len) {
+		ret = blk_rq_map_kern(q, req, buffer, len, GFP_KERNEL);
+		if (ret)
+			goto out;
+	}
+
+	ret = blk_execute_rq(req->q, ns->disk, req, 1);
+ out:
+	blk_mq_free_request(req);
+	return ret;
+}
+
 static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
 		unsigned int cmd, unsigned long arg)
 {
 	struct nvme_ns *ns = bdev->bd_disk->private_data;
 
+	if (is_sed_ioctl(cmd))
+		return blkdev_sed_ioctl(bdev, mode, cmd, arg,
+					ns, nvme_sec_submit);
 	switch (cmd) {
 	case NVME_IOCTL_ID:
 		force_successful_syscall_return();
@@ -1067,6 +1115,34 @@ static const struct pr_ops nvme_pr_ops = {
 	.pr_clear	= nvme_pr_clear,
 };
 
+void nvme_unlock_from_suspend(struct nvme_ctrl *ctrl)
+{
+	struct opal_suspend_unlk ulk = { 0 };
+	struct nvme_ns *ns;
+
+	mutex_lock(&ctrl->namespaces_mutex);
+	if (list_empty(&ctrl->namespaces))
+		goto out_no_namespace;
+
+	ulk.submit_data = ns = list_first_entry(&ctrl->namespaces, struct nvme_ns, list);
+	kref_get(&ns->kref);
+
+	mutex_unlock(&ctrl->namespaces_mutex);
+
+	ulk.submit_fn = nvme_sec_submit;
+	ulk.dev = disk_devt(ns->disk);
+
+	if (opal_unlock_from_suspend(&ulk))
+		pr_warn("Failed to unlock one or more locking ranges!\n");
+
+	nvme_put_ns(ns);
+	return;
+
+ out_no_namespace:
+	mutex_unlock(&ctrl->namespaces_mutex);
+}
+EXPORT_SYMBOL_GPL(nvme_unlock_from_suspend);
+
 static const struct block_device_operations nvme_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= nvme_ioctl,
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index d47f5a5..ac7e5b1 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -240,7 +240,8 @@ static inline int nvme_error_status(u16 status)
 
 static inline bool nvme_req_needs_retry(struct request *req, u16 status)
 {
-	return !(status & NVME_SC_DNR || blk_noretry_request(req)) &&
+	return !(status & NVME_SC_DNR || status & NVME_SC_ACCESS_DENIED ||
+		 blk_noretry_request(req)) &&
 		(jiffies - req->start_time) < req->timeout &&
 		req->retries < nvme_max_retries;
 }
@@ -259,6 +260,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl);
 
 void nvme_queue_scan(struct nvme_ctrl *ctrl);
 void nvme_remove_namespaces(struct nvme_ctrl *ctrl);
+void nvme_unlock_from_suspend(struct nvme_ctrl *ctrl);
 
 #define NVME_NR_AERS	1
 void nvme_complete_async_event(struct nvme_ctrl *ctrl,
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 5e52034..1a1fc9b 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -43,6 +43,7 @@
 #include <linux/types.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 #include <asm/unaligned.h>
+#include <linux/sed-opal.h>
 
 #include "nvme.h"
 
@@ -1748,10 +1749,11 @@ static void nvme_reset_work(struct work_struct *work)
 {
 	struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work);
 	int result = -ENODEV;
-
+	bool was_suspend = false;
 	if (WARN_ON(dev->ctrl.state == NVME_CTRL_RESETTING))
 		goto out;
 
+	was_suspend = !!(dev->ctrl.ctrl_config & NVME_CC_SHN_NORMAL);
 	/*
 	 * If we're called to reset a live controller first shut it down before
 	 * moving on.
@@ -1779,6 +1781,9 @@ static void nvme_reset_work(struct work_struct *work)
 	if (result)
 		goto out;
 
+	if (was_suspend)
+		nvme_unlock_from_suspend(&dev->ctrl);
+
 	result = nvme_setup_io_queues(dev);
 	if (result)
 		goto out;
-- 
2.7.4


_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 3/4] nvme: Implement resume_from_suspend and sed block ioctl
@ 2016-11-29 21:52   ` Scott Bauer
  0 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-29 21:52 UTC (permalink / raw)


This patch implements the necessary logic to unlock a SED
enabled device coming back from an S3.

The patch also implements the ioctl handling from the block
layer.

Signed-off-by: Scott Bauer <scott.bauer at intel.com>
Signed-off-by: Rafael Antognolli <Rafael.Antognolli at intel.com>
---
 drivers/nvme/host/core.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/nvme/host/nvme.h |  4 ++-
 drivers/nvme/host/pci.c  |  7 ++++-
 3 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 79e679d..9a3eb41 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -28,6 +28,8 @@
 #include <linux/t10-pi.h>
 #include <scsi/sg.h>
 #include <asm/unaligned.h>
+#include <linux/sed.h>
+#include <linux/sed-opal.h>
 
 #include "nvme.h"
 #include "fabrics.h"
@@ -778,11 +780,57 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 	return status;
 }
 
+static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer,
+			   size_t len, bool send)
+{
+	struct request_queue *q;
+	struct request *req;
+	struct nvme_ns *ns;
+	struct nvme_command cmd = { 0 };
+	int ret;
+
+	ns = data;
+
+	if (send)
+		cmd.common.opcode = (u8)nvme_admin_security_send;
+	else
+		cmd.common.opcode = (u8)nvme_admin_security_recv;
+
+	cmd.common.nsid = ns->ns_id;
+	cmd.common.cdw10[0] = cpu_to_le32(((u32)secp) << 24 | ((u32)spsp) << 8);
+	cmd.common.cdw10[1] = cpu_to_le32(len);
+
+	q = ns->ctrl->admin_q;
+
+	req = nvme_alloc_request(q, &cmd, 0, NVME_QID_ANY);
+	if (IS_ERR(req)) {
+		ret = PTR_ERR(req);
+		return ret;
+	}
+
+	req->timeout = ADMIN_TIMEOUT;
+	req->special = NULL;
+
+	if (buffer && len) {
+		ret = blk_rq_map_kern(q, req, buffer, len, GFP_KERNEL);
+		if (ret)
+			goto out;
+	}
+
+	ret = blk_execute_rq(req->q, ns->disk, req, 1);
+ out:
+	blk_mq_free_request(req);
+	return ret;
+}
+
 static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
 		unsigned int cmd, unsigned long arg)
 {
 	struct nvme_ns *ns = bdev->bd_disk->private_data;
 
+	if (is_sed_ioctl(cmd))
+		return blkdev_sed_ioctl(bdev, mode, cmd, arg,
+					ns, nvme_sec_submit);
 	switch (cmd) {
 	case NVME_IOCTL_ID:
 		force_successful_syscall_return();
@@ -1067,6 +1115,34 @@ static const struct pr_ops nvme_pr_ops = {
 	.pr_clear	= nvme_pr_clear,
 };
 
+void nvme_unlock_from_suspend(struct nvme_ctrl *ctrl)
+{
+	struct opal_suspend_unlk ulk = { 0 };
+	struct nvme_ns *ns;
+
+	mutex_lock(&ctrl->namespaces_mutex);
+	if (list_empty(&ctrl->namespaces))
+		goto out_no_namespace;
+
+	ulk.submit_data = ns = list_first_entry(&ctrl->namespaces, struct nvme_ns, list);
+	kref_get(&ns->kref);
+
+	mutex_unlock(&ctrl->namespaces_mutex);
+
+	ulk.submit_fn = nvme_sec_submit;
+	ulk.dev = disk_devt(ns->disk);
+
+	if (opal_unlock_from_suspend(&ulk))
+		pr_warn("Failed to unlock one or more locking ranges!\n");
+
+	nvme_put_ns(ns);
+	return;
+
+ out_no_namespace:
+	mutex_unlock(&ctrl->namespaces_mutex);
+}
+EXPORT_SYMBOL_GPL(nvme_unlock_from_suspend);
+
 static const struct block_device_operations nvme_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= nvme_ioctl,
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index d47f5a5..ac7e5b1 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -240,7 +240,8 @@ static inline int nvme_error_status(u16 status)
 
 static inline bool nvme_req_needs_retry(struct request *req, u16 status)
 {
-	return !(status & NVME_SC_DNR || blk_noretry_request(req)) &&
+	return !(status & NVME_SC_DNR || status & NVME_SC_ACCESS_DENIED ||
+		 blk_noretry_request(req)) &&
 		(jiffies - req->start_time) < req->timeout &&
 		req->retries < nvme_max_retries;
 }
@@ -259,6 +260,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl);
 
 void nvme_queue_scan(struct nvme_ctrl *ctrl);
 void nvme_remove_namespaces(struct nvme_ctrl *ctrl);
+void nvme_unlock_from_suspend(struct nvme_ctrl *ctrl);
 
 #define NVME_NR_AERS	1
 void nvme_complete_async_event(struct nvme_ctrl *ctrl,
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 5e52034..1a1fc9b 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -43,6 +43,7 @@
 #include <linux/types.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 #include <asm/unaligned.h>
+#include <linux/sed-opal.h>
 
 #include "nvme.h"
 
@@ -1748,10 +1749,11 @@ static void nvme_reset_work(struct work_struct *work)
 {
 	struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work);
 	int result = -ENODEV;
-
+	bool was_suspend = false;
 	if (WARN_ON(dev->ctrl.state == NVME_CTRL_RESETTING))
 		goto out;
 
+	was_suspend = !!(dev->ctrl.ctrl_config & NVME_CC_SHN_NORMAL);
 	/*
 	 * If we're called to reset a live controller first shut it down before
 	 * moving on.
@@ -1779,6 +1781,9 @@ static void nvme_reset_work(struct work_struct *work)
 	if (result)
 		goto out;
 
+	if (was_suspend)
+		nvme_unlock_from_suspend(&dev->ctrl);
+
 	result = nvme_setup_io_queues(dev);
 	if (result)
 		goto out;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 4/4] Maintainers: Add Information for SED Opal library
  2016-11-29 21:51 ` Scott Bauer
@ 2016-11-29 21:52   ` Scott Bauer
  -1 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-29 21:52 UTC (permalink / raw)
  To: linux-nvme
  Cc: keith.busch, sagi, hch, Rafael.Antognolli, axboe, linux-block,
	Scott Bauer, jonathan.derrick, j.naumann

Signed-off-by: Scott Bauer <scott.bauer@intel.com>
Signed-off-by: Rafael Antognolli <Rafael.Antognolli@intel.com>
---
 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8d414840..929eba3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10846,6 +10846,16 @@ L:	linux-mmc@vger.kernel.org
 S:	Maintained
 F:	drivers/mmc/host/sdhci-spear.c
 
+SECURE ENCRYPTING DEVICE (SED) OPAL DRIVER
+M:	Scott Bauer <scott.bauer@intel.com>
+M:	Jonathan Derrick <jonathan.derrick@intel.com>
+M:	Rafael Antognolli <rafael.antognolli@intel.com>
+L:	linux-nvme@lists.infradead.org
+S:	Supported
+F:	block/sed*
+F:	include/linux/sed*
+F:	include/uapi/linux/sed*
+
 SECURITY SUBSYSTEM
 M:	James Morris <james.l.morris@oracle.com>
 M:	"Serge E. Hallyn" <serge@hallyn.com>
-- 
2.7.4


_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 4/4] Maintainers: Add Information for SED Opal library
@ 2016-11-29 21:52   ` Scott Bauer
  0 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-29 21:52 UTC (permalink / raw)


Signed-off-by: Scott Bauer <scott.bauer at intel.com>
Signed-off-by: Rafael Antognolli <Rafael.Antognolli at intel.com>
---
 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8d414840..929eba3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10846,6 +10846,16 @@ L:	linux-mmc at vger.kernel.org
 S:	Maintained
 F:	drivers/mmc/host/sdhci-spear.c
 
+SECURE ENCRYPTING DEVICE (SED) OPAL DRIVER
+M:	Scott Bauer <scott.bauer at intel.com>
+M:	Jonathan Derrick <jonathan.derrick at intel.com>
+M:	Rafael Antognolli <rafael.antognolli at intel.com>
+L:	linux-nvme at lists.infradead.org
+S:	Supported
+F:	block/sed*
+F:	include/linux/sed*
+F:	include/uapi/linux/sed*
+
 SECURITY SUBSYSTEM
 M:	James Morris <james.l.morris at oracle.com>
 M:	"Serge E. Hallyn" <serge at hallyn.com>
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 2/4] block: Add Sed-opal library
  2016-11-30 18:13     ` Keith Busch
@ 2016-11-30 18:09       ` Scott Bauer
  -1 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-30 18:09 UTC (permalink / raw)
  To: Keith Busch
  Cc: linux-nvme, Rafael.Antognolli, axboe, jonathan.derrick,
	j.naumann, hch, linux-block, sagi

es1;4205;0cOn Wed, Nov 30, 2016 at 01:13:57PM -0500, Keith Busch wrote:
> On Tue, Nov 29, 2016 at 02:52:00PM -0700, Scott Bauer wrote:
> > +	dev = get_or_create_opal_dev(bdev, key->opal_act.key.lr, true);
> > +	if (!dev)
> > +		return -ENOMEM;
> 
> The alloc_opal_dev from this call returns ERR_PTR values on error, so
> the check should be:
> 
> 	if (IS_ERR_OR_NULL(dev))
> 		return PTR_ERR(dev);

Nice catch, I'll go double check the rest of the return values for this
scenario.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
@ 2016-11-30 18:09       ` Scott Bauer
  0 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-11-30 18:09 UTC (permalink / raw)


es1;4205;0cOn Wed, Nov 30, 2016@01:13:57PM -0500, Keith Busch wrote:
> On Tue, Nov 29, 2016@02:52:00PM -0700, Scott Bauer wrote:
> > +	dev = get_or_create_opal_dev(bdev, key->opal_act.key.lr, true);
> > +	if (!dev)
> > +		return -ENOMEM;
> 
> The alloc_opal_dev from this call returns ERR_PTR values on error, so
> the check should be:
> 
> 	if (IS_ERR_OR_NULL(dev))
> 		return PTR_ERR(dev);

Nice catch, I'll go double check the rest of the return values for this
scenario.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 2/4] block: Add Sed-opal library
  2016-11-29 21:52   ` Scott Bauer
@ 2016-11-30 18:13     ` Keith Busch
  -1 siblings, 0 replies; 34+ messages in thread
From: Keith Busch @ 2016-11-30 18:13 UTC (permalink / raw)
  To: Scott Bauer
  Cc: linux-nvme, Rafael.Antognolli, axboe, jonathan.derrick,
	j.naumann, hch, linux-block, sagi

On Tue, Nov 29, 2016 at 02:52:00PM -0700, Scott Bauer wrote:
> +	dev = get_or_create_opal_dev(bdev, key->opal_act.key.lr, true);
> +	if (!dev)
> +		return -ENOMEM;

The alloc_opal_dev from this call returns ERR_PTR values on error, so
the check should be:

	if (IS_ERR_OR_NULL(dev))
		return PTR_ERR(dev);

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
@ 2016-11-30 18:13     ` Keith Busch
  0 siblings, 0 replies; 34+ messages in thread
From: Keith Busch @ 2016-11-30 18:13 UTC (permalink / raw)


On Tue, Nov 29, 2016@02:52:00PM -0700, Scott Bauer wrote:
> +	dev = get_or_create_opal_dev(bdev, key->opal_act.key.lr, true);
> +	if (!dev)
> +		return -ENOMEM;

The alloc_opal_dev from this call returns ERR_PTR values on error, so
the check should be:

	if (IS_ERR_OR_NULL(dev))
		return PTR_ERR(dev);

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 2/4] block: Add Sed-opal library
  2016-11-29 21:52   ` Scott Bauer
@ 2016-12-01  0:50     ` Keith Busch
  -1 siblings, 0 replies; 34+ messages in thread
From: Keith Busch @ 2016-12-01  0:50 UTC (permalink / raw)
  To: Scott Bauer
  Cc: hch, sagi, Rafael.Antognolli, linux-nvme, axboe, linux-block,
	jonathan.derrick, j.naumann

On Tue, Nov 29, 2016 at 02:52:00PM -0700, Scott Bauer wrote:
> +struct opal_dev {
> +	dev_t majmin;
> +	sed_sec_submit *submit_fn;
> +	void *submit_data;
> +	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;
> +
> +	opal_step error_cb;
> +	void *error_cb_data;
> +};

I think this structure could use some kernel-doc comments explaining what
all these fields are for. Some of them don't appear to be used anywhere
in the code, but it'd help to know what the fields are supposed to be for.

I think we should get rid of the "majmin" stuff and directly use
block_device. Then if we add the security send/receive operations to the
block_device_operations, that will simplify chaining the security request
to the driver without needing to thread the driver's requested callback
and data the way you have to here since all the necessary information
is encapsulated in the block_device.

We shouldn't need to be allocating an 'opal_dev' for every range. The
range-specific parts should be in a different structure that the opal_dev
can have a list of. That will simpify the unlock from suspend a bit.

> +/*
> + * 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, ...)

This custom formated string parser looks too complicated to me. I'll try
propose something simpler once I fully understand all the parts to this.

> +#define CMD_TO_FN_INDX(cmd) \
> +	(cmd) - IOC_SED_SAVE
> +
> +int (*sed_fn[])(struct block_device *bdev, struct sed_key *key,
> +		  void *sbmt_data, sed_sec_submit *submit_fn) =
> +{
> +	sed_save,
> +	sed_lock_unlock,
> +	sed_take_ownership,
> +	sed_activate_lsp,
> +	sed_set_pw,
> +	sed_activate_user,
> +	sed_reverttper,
> +	sed_setup_locking_range,
> +	sed_adduser_to_lr,
> +	sed_do_mbr,
> +	sed_erase_lr,
> +	sed_secure_erase_lr
> +};
> +
> +/* The sbmt_ctrl_data is a opaque pointer to some structure which will be used
> + * by the submit_fn to properly submit the opal command to the controller.
> + * The submit_fn must be a blocking call.
> + */
> +int blkdev_sed_ioctl(struct block_device *bdev, fmode_t fmode, unsigned int cmd,
> +		     unsigned long arg, void *sbmt_ctrl_data,
> +		     sed_sec_submit *submit_fn)
> +{
> +	struct sed_key key;
> +
> +	 /* Caller should do this but since we're going to use cmd as an index
> +	 * lets 'trust but verify'.
> +	 */
> +	if (!is_sed_ioctl(cmd))
> +		return -EINVAL;
> +	if (copy_from_user(&key, (void __user *)arg, sizeof(key)))
> +		return -EFAULT;
> +	return sed_fn[CMD_TO_FN_INDX(cmd)](bdev, &key, sbmt_ctrl_data, submit_fn);

I can appreciate how compact this is, but this is a little harder to
read IMO, and it works only because you were so careful in setting up
the array. I think expanding the ioctl into a switch will be easier to
follow, and has a more tolerent coding convention for future additions.

_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
@ 2016-12-01  0:50     ` Keith Busch
  0 siblings, 0 replies; 34+ messages in thread
From: Keith Busch @ 2016-12-01  0:50 UTC (permalink / raw)


On Tue, Nov 29, 2016@02:52:00PM -0700, Scott Bauer wrote:
> +struct opal_dev {
> +	dev_t majmin;
> +	sed_sec_submit *submit_fn;
> +	void *submit_data;
> +	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;
> +
> +	opal_step error_cb;
> +	void *error_cb_data;
> +};

I think this structure could use some kernel-doc comments explaining what
all these fields are for. Some of them don't appear to be used anywhere
in the code, but it'd help to know what the fields are supposed to be for.

I think we should get rid of the "majmin" stuff and directly use
block_device. Then if we add the security send/receive operations to the
block_device_operations, that will simplify chaining the security request
to the driver without needing to thread the driver's requested callback
and data the way you have to here since all the necessary information
is encapsulated in the block_device.

We shouldn't need to be allocating an 'opal_dev' for every range. The
range-specific parts should be in a different structure that the opal_dev
can have a list of. That will simpify the unlock from suspend a bit.

> +/*
> + * 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, ...)

This custom formated string parser looks too complicated to me. I'll try
propose something simpler once I fully understand all the parts to this.

> +#define CMD_TO_FN_INDX(cmd) \
> +	(cmd) - IOC_SED_SAVE
> +
> +int (*sed_fn[])(struct block_device *bdev, struct sed_key *key,
> +		  void *sbmt_data, sed_sec_submit *submit_fn) =
> +{
> +	sed_save,
> +	sed_lock_unlock,
> +	sed_take_ownership,
> +	sed_activate_lsp,
> +	sed_set_pw,
> +	sed_activate_user,
> +	sed_reverttper,
> +	sed_setup_locking_range,
> +	sed_adduser_to_lr,
> +	sed_do_mbr,
> +	sed_erase_lr,
> +	sed_secure_erase_lr
> +};
> +
> +/* The sbmt_ctrl_data is a opaque pointer to some structure which will be used
> + * by the submit_fn to properly submit the opal command to the controller.
> + * The submit_fn must be a blocking call.
> + */
> +int blkdev_sed_ioctl(struct block_device *bdev, fmode_t fmode, unsigned int cmd,
> +		     unsigned long arg, void *sbmt_ctrl_data,
> +		     sed_sec_submit *submit_fn)
> +{
> +	struct sed_key key;
> +
> +	 /* Caller should do this but since we're going to use cmd as an index
> +	 * lets 'trust but verify'.
> +	 */
> +	if (!is_sed_ioctl(cmd))
> +		return -EINVAL;
> +	if (copy_from_user(&key, (void __user *)arg, sizeof(key)))
> +		return -EFAULT;
> +	return sed_fn[CMD_TO_FN_INDX(cmd)](bdev, &key, sbmt_ctrl_data, submit_fn);

I can appreciate how compact this is, but this is a little harder to
read IMO, and it works only because you were so careful in setting up
the array. I think expanding the ioctl into a switch will be easier to
follow, and has a more tolerent coding convention for future additions.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 3/4] nvme: Implement resume_from_suspend and sed block ioctl
  2016-11-29 21:52   ` Scott Bauer
@ 2016-12-01  0:50     ` Keith Busch
  -1 siblings, 0 replies; 34+ messages in thread
From: Keith Busch @ 2016-12-01  0:50 UTC (permalink / raw)
  To: Scott Bauer
  Cc: hch, sagi, Rafael.Antognolli, linux-nvme, axboe, linux-block,
	jonathan.derrick, j.naumann

On Tue, Nov 29, 2016 at 02:52:01PM -0700, Scott Bauer wrote:
> +static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer,
> +			   size_t len, bool send)
> +{
> +	struct request_queue *q;
> +	struct request *req;
> +	struct nvme_ns *ns;
> +	struct nvme_command cmd = { 0 };
> +	int ret;
> +
> +	ns = data;
> +
> +	if (send)
> +		cmd.common.opcode = (u8)nvme_admin_security_send;
> +	else
> +		cmd.common.opcode = (u8)nvme_admin_security_recv;
> +
> +	cmd.common.nsid = ns->ns_id;
> +	cmd.common.cdw10[0] = cpu_to_le32(((u32)secp) << 24 | ((u32)spsp) << 8);
> +	cmd.common.cdw10[1] = cpu_to_le32(len);
> +
> +	q = ns->ctrl->admin_q;
> +
> +	req = nvme_alloc_request(q, &cmd, 0, NVME_QID_ANY);
> +	if (IS_ERR(req)) {
> +		ret = PTR_ERR(req);
> +		return ret;
> +	}
> +
> +	req->timeout = ADMIN_TIMEOUT;
> +	req->special = NULL;
> +
> +	if (buffer && len) {
> +		ret = blk_rq_map_kern(q, req, buffer, len, GFP_KERNEL);
> +		if (ret)
> +			goto out;
> +	}
> +
> +	ret = blk_execute_rq(req->q, ns->disk, req, 1);

I think you want to use the __nvme_submit_sync_command API instead of
duplicating some of the things it does for you.

_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 3/4] nvme: Implement resume_from_suspend and sed block ioctl
@ 2016-12-01  0:50     ` Keith Busch
  0 siblings, 0 replies; 34+ messages in thread
From: Keith Busch @ 2016-12-01  0:50 UTC (permalink / raw)


On Tue, Nov 29, 2016@02:52:01PM -0700, Scott Bauer wrote:
> +static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer,
> +			   size_t len, bool send)
> +{
> +	struct request_queue *q;
> +	struct request *req;
> +	struct nvme_ns *ns;
> +	struct nvme_command cmd = { 0 };
> +	int ret;
> +
> +	ns = data;
> +
> +	if (send)
> +		cmd.common.opcode = (u8)nvme_admin_security_send;
> +	else
> +		cmd.common.opcode = (u8)nvme_admin_security_recv;
> +
> +	cmd.common.nsid = ns->ns_id;
> +	cmd.common.cdw10[0] = cpu_to_le32(((u32)secp) << 24 | ((u32)spsp) << 8);
> +	cmd.common.cdw10[1] = cpu_to_le32(len);
> +
> +	q = ns->ctrl->admin_q;
> +
> +	req = nvme_alloc_request(q, &cmd, 0, NVME_QID_ANY);
> +	if (IS_ERR(req)) {
> +		ret = PTR_ERR(req);
> +		return ret;
> +	}
> +
> +	req->timeout = ADMIN_TIMEOUT;
> +	req->special = NULL;
> +
> +	if (buffer && len) {
> +		ret = blk_rq_map_kern(q, req, buffer, len, GFP_KERNEL);
> +		if (ret)
> +			goto out;
> +	}
> +
> +	ret = blk_execute_rq(req->q, ns->disk, req, 1);

I think you want to use the __nvme_submit_sync_command API instead of
duplicating some of the things it does for you.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 2/4] block: Add Sed-opal library
  2016-12-01  0:50     ` Keith Busch
@ 2016-12-01 10:04       ` Christoph Hellwig
  -1 siblings, 0 replies; 34+ messages in thread
From: Christoph Hellwig @ 2016-12-01 10:04 UTC (permalink / raw)
  To: Keith Busch
  Cc: Scott Bauer, hch, sagi, Rafael.Antognolli, linux-nvme, axboe,
	linux-block, jonathan.derrick, j.naumann

On Wed, Nov 30, 2016 at 07:50:07PM -0500, Keith Busch wrote:
> I think we should get rid of the "majmin" stuff

Absolutely agreed.

>
> and directly use
> block_device. Then if we add the security send/receive operations to the
> block_device_operations, that will simplify chaining the security request
> to the driver without needing to thread the driver's requested callback
> and data the way you have to here since all the necessary information
> is encapsulated in the block_device.

Maybe.  I need to look at the TCG spec again (oh my good, what a fucking
mess), but if I remember the context if it is the whole nvme controller
and not just a namespace, so a block_device might be the wrong context.
Then again we can always go from the block_device to the controller
fairly easily.  So instead of adding the security operation to the
block_device_operations which we don't really need for now maybe we
should add a security_conext to the block device so that we can avoid
all the lookup code?

> We shouldn't need to be allocating an 'opal_dev' for every range. The
> range-specific parts should be in a different structure that the opal_dev
> can have a list of. That will simpify the unlock from suspend a bit.

Agreed.

> I can appreciate how compact this is, but this is a little harder to
> read IMO, and it works only because you were so careful in setting up
> the array. I think expanding the ioctl into a switch will be easier to
> follow, and has a more tolerent coding convention for future additions.

Agreed.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
@ 2016-12-01 10:04       ` Christoph Hellwig
  0 siblings, 0 replies; 34+ messages in thread
From: Christoph Hellwig @ 2016-12-01 10:04 UTC (permalink / raw)


On Wed, Nov 30, 2016@07:50:07PM -0500, Keith Busch wrote:
> I think we should get rid of the "majmin" stuff

Absolutely agreed.

>
> and directly use
> block_device. Then if we add the security send/receive operations to the
> block_device_operations, that will simplify chaining the security request
> to the driver without needing to thread the driver's requested callback
> and data the way you have to here since all the necessary information
> is encapsulated in the block_device.

Maybe.  I need to look at the TCG spec again (oh my good, what a fucking
mess), but if I remember the context if it is the whole nvme controller
and not just a namespace, so a block_device might be the wrong context.
Then again we can always go from the block_device to the controller
fairly easily.  So instead of adding the security operation to the
block_device_operations which we don't really need for now maybe we
should add a security_conext to the block device so that we can avoid
all the lookup code?

> We shouldn't need to be allocating an 'opal_dev' for every range. The
> range-specific parts should be in a different structure that the opal_dev
> can have a list of. That will simpify the unlock from suspend a bit.

Agreed.

> I can appreciate how compact this is, but this is a little harder to
> read IMO, and it works only because you were so careful in setting up
> the array. I think expanding the ioctl into a switch will be easier to
> follow, and has a more tolerent coding convention for future additions.

Agreed.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 2/4] block: Add Sed-opal library
  2016-12-01 10:04       ` Christoph Hellwig
@ 2016-12-01 17:53         ` Scott Bauer
  -1 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-12-01 17:53 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Keith Busch, sagi, Rafael.Antognolli, linux-nvme, axboe,
	linux-block, jonathan.derrick, j.naumann

On Thu, Dec 01, 2016 at 02:04:56AM -0800, Christoph Hellwig wrote:
> On Wed, Nov 30, 2016 at 07:50:07PM -0500, Keith Busch wrote:
> > I think we should get rid of the "majmin" stuff
> 
> Absolutely agreed.
> 
> >
> > and directly use
> > block_device. Then if we add the security send/receive operations to the
> > block_device_operations, that will simplify chaining the security request
> > to the driver without needing to thread the driver's requested callback
> > and data the way you have to here since all the necessary information
> > is encapsulated in the block_device.
> 
> Maybe.  I need to look at the TCG spec again (oh my good, what a fucking
> mess), but if I remember the context if it is the whole nvme controller
> and not just a namespace, so a block_device might be the wrong context.
> Then again we can always go from the block_device to the controller
> fairly easily.  So instead of adding the security operation to the
> block_device_operations which we don't really need for now maybe we
> should add a security_conext to the block device so that we can avoid
> all the lookup code?

I spent some time this morning reading through the numerous specs/documents,
with a lot of coffee.

Specifically in:
https://www.trustedcomputinggroup.org/wp-content/uploads/TCG_SWG_SIIS_Version_1_02_Revision_1_00_20111230.pdf

5.5.2
Namespace

A target that has multiple Namespaces MAY have  multiple TPers. Each TPer
SHALL be associated with a different Namespace. Every Namespace on a device
is not required to have a TPer, but Namespaces that support the TCG Core
specification commands and functionality SHALL have a TPer. A TPer SHALL only
be associated with exactly one Namespace. A Namespace MAY have no TPer.

>From reading that it seems we will probably have to keep it at the block layer,
since its possible to have a valid "Locking range 1" on n1 and a "Locking range 1"
on n2.


[snip]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
@ 2016-12-01 17:53         ` Scott Bauer
  0 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-12-01 17:53 UTC (permalink / raw)


On Thu, Dec 01, 2016@02:04:56AM -0800, Christoph Hellwig wrote:
> On Wed, Nov 30, 2016@07:50:07PM -0500, Keith Busch wrote:
> > I think we should get rid of the "majmin" stuff
> 
> Absolutely agreed.
> 
> >
> > and directly use
> > block_device. Then if we add the security send/receive operations to the
> > block_device_operations, that will simplify chaining the security request
> > to the driver without needing to thread the driver's requested callback
> > and data the way you have to here since all the necessary information
> > is encapsulated in the block_device.
> 
> Maybe.  I need to look at the TCG spec again (oh my good, what a fucking
> mess), but if I remember the context if it is the whole nvme controller
> and not just a namespace, so a block_device might be the wrong context.
> Then again we can always go from the block_device to the controller
> fairly easily.  So instead of adding the security operation to the
> block_device_operations which we don't really need for now maybe we
> should add a security_conext to the block device so that we can avoid
> all the lookup code?

I spent some time this morning reading through the numerous specs/documents,
with a lot of coffee.

Specifically in:
https://www.trustedcomputinggroup.org/wp-content/uploads/TCG_SWG_SIIS_Version_1_02_Revision_1_00_20111230.pdf

5.5.2
Namespace

A target that has multiple Namespaces MAY have  multiple TPers. Each TPer
SHALL be associated with a different Namespace. Every Namespace on a device
is not required to have a TPer, but Namespaces that support the TCG Core
specification commands and functionality SHALL have a TPer. A TPer SHALL only
be associated with exactly one Namespace. A Namespace MAY have no TPer.

>From reading that it seems we will probably have to keep it at the block layer,
since its possible to have a valid "Locking range 1" on n1 and a "Locking range 1"
on n2.


[snip]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 2/4] block: Add Sed-opal library
  2016-12-01 17:53         ` Scott Bauer
@ 2016-12-01 18:22           ` Keith Busch
  -1 siblings, 0 replies; 34+ messages in thread
From: Keith Busch @ 2016-12-01 18:22 UTC (permalink / raw)
  To: Scott Bauer
  Cc: Christoph Hellwig, sagi, Rafael.Antognolli, linux-nvme, axboe,
	linux-block, jonathan.derrick, j.naumann

On Thu, Dec 01, 2016 at 10:53:43AM -0700, Scott Bauer wrote:
> > Maybe.  I need to look at the TCG spec again (oh my good, what a fucking
> > mess), but if I remember the context if it is the whole nvme controller
> > and not just a namespace, so a block_device might be the wrong context.
> > Then again we can always go from the block_device to the controller
> > fairly easily.  So instead of adding the security operation to the
> > block_device_operations which we don't really need for now maybe we
> > should add a security_conext to the block device so that we can avoid
> > all the lookup code?
> 
> I spent some time this morning reading through the numerous specs/documents,
> with a lot of coffee.
> 
> Specifically in:
> https://www.trustedcomputinggroup.org/wp-content/uploads/TCG_SWG_SIIS_Version_1_02_Revision_1_00_20111230.pdf
> 
> 5.5.2
> Namespace
> 
> A target that has multiple Namespaces MAY have  multiple TPers. Each TPer
> SHALL be associated with a different Namespace. Every Namespace on a device
> is not required to have a TPer, but Namespaces that support the TCG Core
> specification commands and functionality SHALL have a TPer. A TPer SHALL only
> be associated with exactly one Namespace. A Namespace MAY have no TPer.
> 
> From reading that it seems we will probably have to keep it at the block layer,
> since its possible to have a valid "Locking range 1" on n1 and a "Locking range 1"
> on n2.

Thanks for tracking that down! Specifically for NVMe, security
send/recieve requires NSID, so it is a little more difficult to get to
that if we're not using the abstracton that contains the namespace.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
@ 2016-12-01 18:22           ` Keith Busch
  0 siblings, 0 replies; 34+ messages in thread
From: Keith Busch @ 2016-12-01 18:22 UTC (permalink / raw)


On Thu, Dec 01, 2016@10:53:43AM -0700, Scott Bauer wrote:
> > Maybe.  I need to look at the TCG spec again (oh my good, what a fucking
> > mess), but if I remember the context if it is the whole nvme controller
> > and not just a namespace, so a block_device might be the wrong context.
> > Then again we can always go from the block_device to the controller
> > fairly easily.  So instead of adding the security operation to the
> > block_device_operations which we don't really need for now maybe we
> > should add a security_conext to the block device so that we can avoid
> > all the lookup code?
> 
> I spent some time this morning reading through the numerous specs/documents,
> with a lot of coffee.
> 
> Specifically in:
> https://www.trustedcomputinggroup.org/wp-content/uploads/TCG_SWG_SIIS_Version_1_02_Revision_1_00_20111230.pdf
> 
> 5.5.2
> Namespace
> 
> A target that has multiple Namespaces MAY have  multiple TPers. Each TPer
> SHALL be associated with a different Namespace. Every Namespace on a device
> is not required to have a TPer, but Namespaces that support the TCG Core
> specification commands and functionality SHALL have a TPer. A TPer SHALL only
> be associated with exactly one Namespace. A Namespace MAY have no TPer.
> 
> From reading that it seems we will probably have to keep it at the block layer,
> since its possible to have a valid "Locking range 1" on n1 and a "Locking range 1"
> on n2.

Thanks for tracking that down! Specifically for NVMe, security
send/recieve requires NSID, so it is a little more difficult to get to
that if we're not using the abstracton that contains the namespace.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 2/4] block: Add Sed-opal library
  2016-12-01 18:22           ` Keith Busch
@ 2016-12-09 17:45             ` Scott Bauer
  -1 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-12-09 17:45 UTC (permalink / raw)
  To: Keith Busch
  Cc: Christoph Hellwig, sagi, Rafael.Antognolli, linux-nvme, axboe,
	linux-block, jonathan.derrick, j.naumann

On Thu, Dec 01, 2016 at 01:22:39PM -0500, Keith Busch wrote:
> On Thu, Dec 01, 2016 at 10:53:43AM -0700, Scott Bauer wrote:
> > > Maybe.  I need to look at the TCG spec again (oh my good, what a fucking
> > > mess), but if I remember the context if it is the whole nvme controller
> > > and not just a namespace, so a block_device might be the wrong context.
> > > Then again we can always go from the block_device to the controller
> > > fairly easily.  So instead of adding the security operation to the
> > > block_device_operations which we don't really need for now maybe we
> > > should add a security_conext to the block device so that we can avoid
> > > all the lookup code?
> > 
> > I spent some time this morning reading through the numerous specs/documents,
> > with a lot of coffee.
> > 
> > Specifically in:
> > https://www.trustedcomputinggroup.org/wp-content/uploads/TCG_SWG_SIIS_Version_1_02_Revision_1_00_20111230.pdf
> > 
> > 5.5.2
> > Namespace
> > 
> > A target that has multiple Namespaces MAY have  multiple TPers. Each TPer
> > SHALL be associated with a different Namespace. Every Namespace on a device
> > is not required to have a TPer, but Namespaces that support the TCG Core
> > specification commands and functionality SHALL have a TPer. A TPer SHALL only
> > be associated with exactly one Namespace. A Namespace MAY have no TPer.
> > 
> > From reading that it seems we will probably have to keep it at the block layer,
> > since its possible to have a valid "Locking range 1" on n1 and a "Locking range 1"
> > on n2.
> 
> Thanks for tracking that down! Specifically for NVMe, security
> send/recieve requires NSID, so it is a little more difficult to get to
> that if we're not using the abstracton that contains the namespace.


So turns out that version is old and it has since changed:
https://www.trustedcomputinggroup.org/wp-content/uploads/TCG_SWG_SIIS_Version_1_05_Revision_1_00.pdf
(section 5.5)

So in this document Cristoph is right. There is a single TPER for the entire device.
For devices with multiple namespaces, there will be a single global locking range.
That single locking range covers the entire LBA range. Other locking ranges aren't allowed.

Now, for a drive with one namespace There is a global LR and it MAY be allowed to have
other user locking ranges as well.

Now, with this in mind, it sort of makes sense to move this from block/ back into lib/
and interface with the character dev. Instead of passing around block_devices, we
can pass around struct file *'s.

Does anyone have and qualms/comments/anecdotes before I move everything around?



^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
@ 2016-12-09 17:45             ` Scott Bauer
  0 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-12-09 17:45 UTC (permalink / raw)


On Thu, Dec 01, 2016@01:22:39PM -0500, Keith Busch wrote:
> On Thu, Dec 01, 2016@10:53:43AM -0700, Scott Bauer wrote:
> > > Maybe.  I need to look at the TCG spec again (oh my good, what a fucking
> > > mess), but if I remember the context if it is the whole nvme controller
> > > and not just a namespace, so a block_device might be the wrong context.
> > > Then again we can always go from the block_device to the controller
> > > fairly easily.  So instead of adding the security operation to the
> > > block_device_operations which we don't really need for now maybe we
> > > should add a security_conext to the block device so that we can avoid
> > > all the lookup code?
> > 
> > I spent some time this morning reading through the numerous specs/documents,
> > with a lot of coffee.
> > 
> > Specifically in:
> > https://www.trustedcomputinggroup.org/wp-content/uploads/TCG_SWG_SIIS_Version_1_02_Revision_1_00_20111230.pdf
> > 
> > 5.5.2
> > Namespace
> > 
> > A target that has multiple Namespaces MAY have  multiple TPers. Each TPer
> > SHALL be associated with a different Namespace. Every Namespace on a device
> > is not required to have a TPer, but Namespaces that support the TCG Core
> > specification commands and functionality SHALL have a TPer. A TPer SHALL only
> > be associated with exactly one Namespace. A Namespace MAY have no TPer.
> > 
> > From reading that it seems we will probably have to keep it at the block layer,
> > since its possible to have a valid "Locking range 1" on n1 and a "Locking range 1"
> > on n2.
> 
> Thanks for tracking that down! Specifically for NVMe, security
> send/recieve requires NSID, so it is a little more difficult to get to
> that if we're not using the abstracton that contains the namespace.


So turns out that version is old and it has since changed:
https://www.trustedcomputinggroup.org/wp-content/uploads/TCG_SWG_SIIS_Version_1_05_Revision_1_00.pdf
(section 5.5)

So in this document Cristoph is right. There is a single TPER for the entire device.
For devices with multiple namespaces, there will be a single global locking range.
That single locking range covers the entire LBA range. Other locking ranges aren't allowed.

Now, for a drive with one namespace There is a global LR and it MAY be allowed to have
other user locking ranges as well.

Now, with this in mind, it sort of makes sense to move this from block/ back into lib/
and interface with the character dev. Instead of passing around block_devices, we
can pass around struct file *'s.

Does anyone have and qualms/comments/anecdotes before I move everything around?

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 2/4] block: Add Sed-opal library
  2016-12-09 17:45             ` Scott Bauer
@ 2016-12-09 18:30               ` Christoph Hellwig
  -1 siblings, 0 replies; 34+ messages in thread
From: Christoph Hellwig @ 2016-12-09 18:30 UTC (permalink / raw)
  To: Scott Bauer
  Cc: Keith Busch, linux-block, sagi, Rafael.Antognolli, axboe,
	linux-nvme, Christoph Hellwig, jonathan.derrick, j.naumann

On Fri, Dec 09, 2016 at 10:45:30AM -0700, Scott Bauer wrote:
> Now, with this in mind, it sort of makes sense to move this from
> block/ back into lib/ and interface with the character dev. Instead
> of passing around block_devices, we can pass around struct file *'s.
>

Even the character device is always backed by the queues, and I'd really
not prefer to have a struct file here - that's not useful at all
for in-kernel users.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
@ 2016-12-09 18:30               ` Christoph Hellwig
  0 siblings, 0 replies; 34+ messages in thread
From: Christoph Hellwig @ 2016-12-09 18:30 UTC (permalink / raw)


On Fri, Dec 09, 2016@10:45:30AM -0700, Scott Bauer wrote:
> Now, with this in mind, it sort of makes sense to move this from
> block/ back into lib/ and interface with the character dev. Instead
> of passing around block_devices, we can pass around struct file *'s.
>

Even the character device is always backed by the queues, and I'd really
not prefer to have a struct file here - that's not useful at all
for in-kernel users.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 2/4] block: Add Sed-opal library
  2016-12-09 18:30               ` Christoph Hellwig
@ 2016-12-09 18:50                 ` Scott Bauer
  -1 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-12-09 18:50 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Keith Busch, linux-block, sagi, Rafael.Antognolli, axboe,
	linux-nvme, jonathan.derrick, j.naumann

On Fri, Dec 09, 2016 at 10:30:34AM -0800, Christoph Hellwig wrote:
> On Fri, Dec 09, 2016 at 10:45:30AM -0700, Scott Bauer wrote:
> > Now, with this in mind, it sort of makes sense to move this from
> > block/ back into lib/ and interface with the character dev. Instead
> > of passing around block_devices, we can pass around struct file *'s.
> >
> 
> Even the character device is always backed by the queues, and I'd really
> not prefer to have a struct file here - that's not useful at all
> for in-kernel users.

Is your main concern that if an in-kernel user wants to use this functionality
they have to pass us a block device pointer, and may not be able to? Is that
why you wanted to pass a function pointer to the code because a driver/kernel-user
can probably always have that availiable to send to us?


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/4] block: Add Sed-opal library
@ 2016-12-09 18:50                 ` Scott Bauer
  0 siblings, 0 replies; 34+ messages in thread
From: Scott Bauer @ 2016-12-09 18:50 UTC (permalink / raw)


On Fri, Dec 09, 2016@10:30:34AM -0800, Christoph Hellwig wrote:
> On Fri, Dec 09, 2016@10:45:30AM -0700, Scott Bauer wrote:
> > Now, with this in mind, it sort of makes sense to move this from
> > block/ back into lib/ and interface with the character dev. Instead
> > of passing around block_devices, we can pass around struct file *'s.
> >
> 
> Even the character device is always backed by the queues, and I'd really
> not prefer to have a struct file here - that's not useful at all
> for in-kernel users.

Is your main concern that if an in-kernel user wants to use this functionality
they have to pass us a block device pointer, and may not be able to? Is that
why you wanted to pass a function pointer to the code because a driver/kernel-user
can probably always have that availiable to send to us?

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 4/4] Maintainers: Add Information for SED Opal library
  2017-02-10 16:46   ` Elliott, Robert (Persistent Memory)
@ 2017-02-10 16:44     ` Scott Bauer
  2017-02-11  2:24       ` Elliott, Robert (Persistent Memory)
  2017-02-13  8:04       ` hch
  0 siblings, 2 replies; 34+ messages in thread
From: Scott Bauer @ 2017-02-10 16:44 UTC (permalink / raw)


On Fri, Feb 10, 2017@08:46:09AM -0800, Elliott, Robert (Persistent Memory) wrote:
> 
> 
> > -----Original Message-----
> > From: linux-block-owner at vger.kernel.org [mailto:linux-block-
> > owner at vger.kernel.org] On Behalf Of Scott Bauer
> > Sent: Tuesday, November 29, 2016 3:52 PM
> > To: linux-nvme at lists.infradead.org
> > Cc: Rafael.Antognolli at intel.com; axboe at fb.com; keith.busch at intel.com;
> > jonathan.derrick at intel.com; j.naumann at fu-berlin.de; hch at infradead.org;
> > linux-block at vger.kernel.org; sagi at grimberg.me; Scott Bauer
> > <scott.bauer at intel.com>
> > Subject: [PATCH v2 4/4] Maintainers: Add Information for SED Opal library
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 8d414840..929eba3 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -10846,6 +10846,16 @@ L:linux-mmc at vger.kernel.org
> >  S:Maintained
> >  F:drivers/mmc/host/sdhci-spear.c
> >
> > +SECURE ENCRYPTING DEVICE (SED) OPAL DRIVER
> > +M:Scott Bauer <scott.bauer at intel.com>
> > +M:Jonathan Derrick <jonathan.derrick at intel.com>
> > +M:Rafael Antognolli <rafael.antognolli at intel.com>
> > +L:linux-nvme at lists.infradead.org
> > +S:Supported
> > +F:block/sed*
> > +F:include/linux/sed*
> > +F:include/uapi/linux/sed*
> 
> Since this is in the block tree and is not nvme specific, could you use
> linux-block as the main list?

Sure, that's fine. Is there a way to denote "main list" in maintainers,
or just list it first?

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 4/4] Maintainers: Add Information for SED Opal library
  2016-11-29 21:52   ` Scott Bauer
  (?)
@ 2017-02-10 16:46   ` Elliott, Robert (Persistent Memory)
  2017-02-10 16:44     ` Scott Bauer
  -1 siblings, 1 reply; 34+ messages in thread
From: Elliott, Robert (Persistent Memory) @ 2017-02-10 16:46 UTC (permalink / raw)




> -----Original Message-----
> From: linux-block-owner at vger.kernel.org [mailto:linux-block-
> owner at vger.kernel.org] On Behalf Of Scott Bauer
> Sent: Tuesday, November 29, 2016 3:52 PM
> To: linux-nvme at lists.infradead.org
> Cc: Rafael.Antognolli at intel.com; axboe at fb.com; keith.busch at intel.com;
> jonathan.derrick at intel.com; j.naumann at fu-berlin.de; hch at infradead.org;
> linux-block at vger.kernel.org; sagi at grimberg.me; Scott Bauer
> <scott.bauer at intel.com>
> Subject: [PATCH v2 4/4] Maintainers: Add Information for SED Opal library
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8d414840..929eba3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -10846,6 +10846,16 @@ L:	linux-mmc at vger.kernel.org
>  S:	Maintained
>  F:	drivers/mmc/host/sdhci-spear.c
> 
> +SECURE ENCRYPTING DEVICE (SED) OPAL DRIVER
> +M:	Scott Bauer <scott.bauer at intel.com>
> +M:	Jonathan Derrick <jonathan.derrick at intel.com>
> +M:	Rafael Antognolli <rafael.antognolli at intel.com>
> +L:	linux-nvme at lists.infradead.org
> +S:	Supported
> +F:	block/sed*
> +F:	include/linux/sed*
> +F:	include/uapi/linux/sed*

Since this is in the block tree and is not nvme specific, could you use 
linux-block as the main list?

Apparently the series has progressed to v6, but only on the 
linux-nvme list.

---
Robert Elliott, HPE Persistent Memory

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 4/4] Maintainers: Add Information for SED Opal library
  2017-02-10 16:44     ` Scott Bauer
@ 2017-02-11  2:24       ` Elliott, Robert (Persistent Memory)
  2017-02-13  8:04       ` hch
  1 sibling, 0 replies; 34+ messages in thread
From: Elliott, Robert (Persistent Memory) @ 2017-02-11  2:24 UTC (permalink / raw)


> Sure, that's fine. Is there a way to denote "main list" in maintainers,
> or just list it first?

I think scripts/get_maintainer.pl uses all of them, so any order will work.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 4/4] Maintainers: Add Information for SED Opal library
  2017-02-10 16:44     ` Scott Bauer
  2017-02-11  2:24       ` Elliott, Robert (Persistent Memory)
@ 2017-02-13  8:04       ` hch
  1 sibling, 0 replies; 34+ messages in thread
From: hch @ 2017-02-13  8:04 UTC (permalink / raw)


On Fri, Feb 10, 2017@09:44:59AM -0700, Scott Bauer wrote:
> > > +F:include/linux/sed*
> > > +F:include/uapi/linux/sed*
> > 
> > Since this is in the block tree and is not nvme specific, could you use
> > linux-block as the main list?
> 
> Sure, that's fine. Is there a way to denote "main list" in maintainers,
> or just list it first?

I'd just use linux-block - traffic isn't much higher than the nvme list,
and it fits a lot better.  FYI, I hope to have ATA (and as byproduct
SCSI) support ready for the next merge window.

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2017-02-13  8:04 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-29 21:51 [PATCH v2 0/4] SED OPAL Library Scott Bauer
2016-11-29 21:51 ` Scott Bauer
2016-11-29 21:51 ` [PATCH v2 1/4] include: Add definitions for sed Scott Bauer
2016-11-29 21:51   ` Scott Bauer
2016-11-29 21:52 ` [PATCH v2 2/4] block: Add Sed-opal library Scott Bauer
2016-11-29 21:52   ` Scott Bauer
2016-11-30 18:13   ` Keith Busch
2016-11-30 18:13     ` Keith Busch
2016-11-30 18:09     ` Scott Bauer
2016-11-30 18:09       ` Scott Bauer
2016-12-01  0:50   ` Keith Busch
2016-12-01  0:50     ` Keith Busch
2016-12-01 10:04     ` Christoph Hellwig
2016-12-01 10:04       ` Christoph Hellwig
2016-12-01 17:53       ` Scott Bauer
2016-12-01 17:53         ` Scott Bauer
2016-12-01 18:22         ` Keith Busch
2016-12-01 18:22           ` Keith Busch
2016-12-09 17:45           ` Scott Bauer
2016-12-09 17:45             ` Scott Bauer
2016-12-09 18:30             ` Christoph Hellwig
2016-12-09 18:30               ` Christoph Hellwig
2016-12-09 18:50               ` Scott Bauer
2016-12-09 18:50                 ` Scott Bauer
2016-11-29 21:52 ` [PATCH v2 3/4] nvme: Implement resume_from_suspend and sed block ioctl Scott Bauer
2016-11-29 21:52   ` Scott Bauer
2016-12-01  0:50   ` Keith Busch
2016-12-01  0:50     ` Keith Busch
2016-11-29 21:52 ` [PATCH v2 4/4] Maintainers: Add Information for SED Opal library Scott Bauer
2016-11-29 21:52   ` Scott Bauer
2017-02-10 16:46   ` Elliott, Robert (Persistent Memory)
2017-02-10 16:44     ` Scott Bauer
2017-02-11  2:24       ` Elliott, Robert (Persistent Memory)
2017-02-13  8:04       ` hch

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