* [RFC PATCH 0/6] Sed Opal @ 2016-10-31 21:58 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) To: linux-nvme Cc: Rafael.Antognolli, axboe, keith.busch, jonathan.derrick, j.naumann, hch, linux-block 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, either 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. We have userland tooling staged in nvme-cli which can be used for testing: https://github.com/linux-nvme/nvme-cli/pull/137 Once we've fixed any nits and issues we will merge the userland tooling into the master branch of nvme-cli. I have a series of test scripts I've been using which can be helpful if people want to test or immediately start using and testing the code: https://github.com/ScottyBauer/nvme-cli-sed-sh At a high level the code works by declaring a set of opal_step functions, which we save in our opal_dev structure. The opal_step functions declare the functions which are necessary to do the opal command. We start dispatching the commands to the device, which return immediately. The thread from userland calls into wait_for_cmd_completion to wait until all the commands have finished. Each new command is issued in an interrupt that signaled the completion of the previous command. If a command requires information to complete we pass that information in the opal_dev structure in the func_data. If a command needs to save data to give to a future command it is saved in the prev_data. On a side note, since these files are new I assume we will need to add a new entry into MAINTAINERS for this code base, can anyone confirm that? ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 0/6] Sed Opal @ 2016-10-31 21:58 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) 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, either 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. We have userland tooling staged in nvme-cli which can be used for testing: https://github.com/linux-nvme/nvme-cli/pull/137 Once we've fixed any nits and issues we will merge the userland tooling into the master branch of nvme-cli. I have a series of test scripts I've been using which can be helpful if people want to test or immediately start using and testing the code: https://github.com/ScottyBauer/nvme-cli-sed-sh At a high level the code works by declaring a set of opal_step functions, which we save in our opal_dev structure. The opal_step functions declare the functions which are necessary to do the opal command. We start dispatching the commands to the device, which return immediately. The thread from userland calls into wait_for_cmd_completion to wait until all the commands have finished. Each new command is issued in an interrupt that signaled the completion of the previous command. If a command requires information to complete we pass that information in the opal_dev structure in the func_data. If a command needs to save data to give to a future command it is saved in the prev_data. On a side note, since these files are new I assume we will need to add a new entry into MAINTAINERS for this code base, can anyone confirm that? ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 1/6] Include: Add definitions for sed 2016-10-31 21:58 ` Scott Bauer @ 2016-10-31 21:58 ` Scott Bauer -1 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) To: linux-nvme Cc: Rafael.Antognolli, axboe, keith.busch, jonathan.derrick, j.naumann, hch, linux-block, Scott Bauer This patch adds the definitions and structures for the SED Opal code. Signed-off-by: Scott Bauer <scott.bauer@intel.com> Signed-off-by: Rafael Antognolli <Rafael.Antognolli@intel.com> --- include/linux/sed-opal.h | 58 +++++++++++++++++++++ include/linux/sed.h | 91 ++++++++++++++++++++++++++++++++ include/uapi/linux/sed-opal.h | 118 ++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/sed.h | 55 ++++++++++++++++++++ 4 files changed, 322 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..e0ee21e --- /dev/null +++ b/include/linux/sed-opal.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Rafael Antognolli <rafael.antognolli@intel.com> + * Scott Bauer <scott.bauer@intel.com> + */ + +#ifndef LINUX_OPAL_H +#define LINUX_OPAL_H + +#include <linux/sed.h> +#include <linux/kernel.h> + +enum { + TCG_SECP_00 = 0, + TCG_SECP_01, +}; + +struct opal_suspend_unlk { + void *data; + const char *name; + struct sec_ops ops; +}; + +int opal_save(struct block_device *bdev, struct sed_key *key); +int opal_lock_unlock(struct block_device *bdev, struct sed_key *key); +int opal_take_ownership(struct block_device *bdev, struct sed_key *key); +int opal_activate_lsp(struct block_device *bdev, struct sed_key *key); +int opal_set_new_pw(struct block_device *bdev, struct sed_key *key); +int opal_activate_user(struct block_device *bdev, struct sed_key *key); +int opal_reverttper(struct block_device *bdev, struct sed_key *key); +int opal_setup_locking_range(struct block_device *bdev, struct sed_key *key); +int opal_add_user_to_lr(struct block_device *bdev, struct sed_key *key); +int opal_enable_disable_shadow_mbr(struct block_device *bdev, struct sed_key *key); +int opal_unlock_from_suspend(struct opal_suspend_unlk *data); +int opal_erase_locking_range(struct block_device *bdev, struct sed_key *key); + +#endif /* LINUX_OPAL_H */ diff --git a/include/linux/sed.h b/include/linux/sed.h new file mode 100644 index 0000000..6c9bae9 --- /dev/null +++ b/include/linux/sed.h @@ -0,0 +1,91 @@ +/* + * Self-Encrypting Drive interface - sed.h + * + * Copyright (C) 2016 Intel Corporation <jonathan.derrick@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> + +/* + * sec_ops - transport specific Trusted Send/Receive functions + * See SPC-4 for specific definitions + * + * @sec_send: sends the payload to the trusted peripheral + * SPSP: Security Protocol Specific + * SECP: Security Protocol + * buf: Payload + * len: Payload length + * @recv: Receives a payload from the trusted peripheral + * SPSP: Security Protocol Specific + * SECP: Security Protocol + * buf: Payload + * len: Payload length + */ + +typedef void (sec_cb)(int error, void *data); + +struct sec_ops { + int (*send)(void *data, __u16 SPSP, __u8 SECP, + void *buffer, size_t len, + sec_cb *cb, void *cb_data); + int (*recv)(void *data, __u16 SPSP, __u8 SECP, + void *buffer, size_t len, + sec_cb *cb, void *cb_data); +}; + + +#ifdef CONFIG_SED +int sed_save(struct block_device *bdev, struct sed_key *key); +int sed_lock_unlock(struct block_device *bdev, struct sed_key *key); +int sed_take_ownership(struct block_device *bdev, struct sed_key *key); +int sed_activate_lsp(struct block_device *bdev, struct sed_key *key); +int sed_set_pw(struct block_device *bdev, struct sed_key *key); +int sed_activate_user(struct block_device *bdev, struct sed_key *key); +int sed_reverttper(struct block_device *bdev, struct sed_key *key); +int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key); +int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key); +int sed_do_mbr(struct block_device *bdev, struct sed_key *key); +int sed_erase_lr(struct block_device *bdev, struct sed_key *key); +#else +static inline int sed_save(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_lock_unlock(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_take_ownership(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_activate_lsp(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_set_pw(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_activate_user(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_reverttper(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_do_mbr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_erase_lr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +#endif + +#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..527eb9a --- /dev/null +++ b/include/uapi/linux/sed-opal.h @@ -0,0 +1,118 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Author: + * Rafael Antognolli <rafael.antognolli@intel.com> + * Scott Bauer <rafael.antognolli@intel.com> + */ + +#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_activate_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..6973044 --- /dev/null +++ b/include/uapi/linux/sed.h @@ -0,0 +1,55 @@ +/* + * Definitions for the self-encrypting drive interface + * Copyright (c) 2016, Intel Corporation. + * + * 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> + +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 __user *opal; + struct opal_new_pw __user *opal_pw; + struct opal_activate_user __user *opal_act; + struct opal_user_lr_setup __user *opal_lrs; + struct opal_lock_unlock __user *opal_lk_unlk; + struct opal_mbr_data __user *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) + +#endif /* _UAPI_SED_H */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* [RFC PATCH 1/6] Include: Add definitions for sed @ 2016-10-31 21:58 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 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 | 58 +++++++++++++++++++++ include/linux/sed.h | 91 ++++++++++++++++++++++++++++++++ include/uapi/linux/sed-opal.h | 118 ++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/sed.h | 55 ++++++++++++++++++++ 4 files changed, 322 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..e0ee21e --- /dev/null +++ b/include/linux/sed-opal.h @@ -0,0 +1,58 @@ +/* + * Copyright ? 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Rafael Antognolli <rafael.antognolli at intel.com> + * Scott Bauer <scott.bauer at intel.com> + */ + +#ifndef LINUX_OPAL_H +#define LINUX_OPAL_H + +#include <linux/sed.h> +#include <linux/kernel.h> + +enum { + TCG_SECP_00 = 0, + TCG_SECP_01, +}; + +struct opal_suspend_unlk { + void *data; + const char *name; + struct sec_ops ops; +}; + +int opal_save(struct block_device *bdev, struct sed_key *key); +int opal_lock_unlock(struct block_device *bdev, struct sed_key *key); +int opal_take_ownership(struct block_device *bdev, struct sed_key *key); +int opal_activate_lsp(struct block_device *bdev, struct sed_key *key); +int opal_set_new_pw(struct block_device *bdev, struct sed_key *key); +int opal_activate_user(struct block_device *bdev, struct sed_key *key); +int opal_reverttper(struct block_device *bdev, struct sed_key *key); +int opal_setup_locking_range(struct block_device *bdev, struct sed_key *key); +int opal_add_user_to_lr(struct block_device *bdev, struct sed_key *key); +int opal_enable_disable_shadow_mbr(struct block_device *bdev, struct sed_key *key); +int opal_unlock_from_suspend(struct opal_suspend_unlk *data); +int opal_erase_locking_range(struct block_device *bdev, struct sed_key *key); + +#endif /* LINUX_OPAL_H */ diff --git a/include/linux/sed.h b/include/linux/sed.h new file mode 100644 index 0000000..6c9bae9 --- /dev/null +++ b/include/linux/sed.h @@ -0,0 +1,91 @@ +/* + * Self-Encrypting Drive interface - sed.h + * + * Copyright (C) 2016 Intel Corporation <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> + +/* + * sec_ops - transport specific Trusted Send/Receive functions + * See SPC-4 for specific definitions + * + * @sec_send: sends the payload to the trusted peripheral + * SPSP: Security Protocol Specific + * SECP: Security Protocol + * buf: Payload + * len: Payload length + * @recv: Receives a payload from the trusted peripheral + * SPSP: Security Protocol Specific + * SECP: Security Protocol + * buf: Payload + * len: Payload length + */ + +typedef void (sec_cb)(int error, void *data); + +struct sec_ops { + int (*send)(void *data, __u16 SPSP, __u8 SECP, + void *buffer, size_t len, + sec_cb *cb, void *cb_data); + int (*recv)(void *data, __u16 SPSP, __u8 SECP, + void *buffer, size_t len, + sec_cb *cb, void *cb_data); +}; + + +#ifdef CONFIG_SED +int sed_save(struct block_device *bdev, struct sed_key *key); +int sed_lock_unlock(struct block_device *bdev, struct sed_key *key); +int sed_take_ownership(struct block_device *bdev, struct sed_key *key); +int sed_activate_lsp(struct block_device *bdev, struct sed_key *key); +int sed_set_pw(struct block_device *bdev, struct sed_key *key); +int sed_activate_user(struct block_device *bdev, struct sed_key *key); +int sed_reverttper(struct block_device *bdev, struct sed_key *key); +int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key); +int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key); +int sed_do_mbr(struct block_device *bdev, struct sed_key *key); +int sed_erase_lr(struct block_device *bdev, struct sed_key *key); +#else +static inline int sed_save(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_lock_unlock(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_take_ownership(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_activate_lsp(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_set_pw(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_activate_user(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_reverttper(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_do_mbr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static inline int sed_erase_lr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +#endif + +#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..527eb9a --- /dev/null +++ b/include/uapi/linux/sed-opal.h @@ -0,0 +1,118 @@ +/* + * Copyright ? 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Author: + * Rafael Antognolli <rafael.antognolli at intel.com> + * Scott Bauer <rafael.antognolli at intel.com> + */ + +#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_activate_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..6973044 --- /dev/null +++ b/include/uapi/linux/sed.h @@ -0,0 +1,55 @@ +/* + * Definitions for the self-encrypting drive interface + * Copyright (c) 2016, Intel Corporation. + * + * 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> + +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 __user *opal; + struct opal_new_pw __user *opal_pw; + struct opal_activate_user __user *opal_act; + struct opal_user_lr_setup __user *opal_lrs; + struct opal_lock_unlock __user *opal_lk_unlk; + struct opal_mbr_data __user *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) + +#endif /* _UAPI_SED_H */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* [RFC PATCH 2/6] lib: Add Sed-opal library 2016-10-31 21:58 ` Scott Bauer @ 2016-10-31 21:58 ` Scott Bauer -1 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) To: linux-nvme Cc: keith.busch, hch, Rafael.Antognolli, axboe, linux-block, Scott Bauer, jonathan.derrick, j.naumann VGhpcyBwYXRjaCBpbXBsZW1lbnRzIHRoZSBuZWNlc3NhcnkgbG9naWMgdG8gYnJpbmcgYW4gT3Bh bAplbmFibGVkIGRyaXZlIG91dCBvZiBhIGZhY3RvcnktZW5hYmxlZCBpbnRvIGEgd29ya2luZwpP cGFsIHN0YXRlLgoKVGhpcyBwYXRjaCBzZXQgYWxzbyBlbmFibGVzIGxvZ2ljIHRvIHNhdmUgYSBw YXNzd29yZCB0bwpiZSByZXBsYXllZCBkdXJpbmcgYSByZXN1bWUgZnJvbSBzdXNwZW5kLiBUaGUg a2V5IGNhbiBiZQpzYXZlZCBpbiB0aGUgZHJpdmVyIG9yIGluIHRoZSBLZXJuZWwncyBLZXkgbWFu YWdtZW50LgoKU2lnbmVkLW9mZi1ieTogU2NvdHQgQmF1ZXIgPHNjb3R0LmJhdWVyQGludGVsLmNv bT4KU2lnbmVkLW9mZi1ieTogUmFmYWVsIEFudG9nbm9sbGkgPFJhZmFlbC5BbnRvZ25vbGxpQGlu dGVsLmNvbT4KLS0tCiBsaWIvc2VkLW9wYWwuYyAgICAgICAgICB8IDMzMzcgKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIGxpYi9zZWQtb3BhbF9pbnRlcm5h bC5oIHwgIDU4NiArKysrKysrKysKIGxpYi9zZWQtb3BhbF9rZXkuYyAgICAgIHwgICA0NiArCiBs aWIvc2VkLmMgICAgICAgICAgICAgICB8ICAzMDMgKysrKysKIDQgZmlsZXMgY2hhbmdlZCwgNDI3 MiBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL3NlZC1vcGFsLmMKIGNyZWF0 ZSBtb2RlIDEwMDY0NCBsaWIvc2VkLW9wYWxfaW50ZXJuYWwuaAogY3JlYXRlIG1vZGUgMTAwNjQ0 IGxpYi9zZWQtb3BhbF9rZXkuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGxpYi9zZWQuYwoKZGlmZiAt LWdpdCBhL2xpYi9zZWQtb3BhbC5jIGIvbGliL3NlZC1vcGFsLmMKbmV3IGZpbGUgbW9kZSAxMDA2 NDQKaW5kZXggMDAwMDAwMC4uMTBiMzM0OAotLS0gL2Rldi9udWxsCisrKyBiL2xpYi9zZWQtb3Bh bC5jCkBAIC0wLDAgKzEsMzMzNyBAQAorLyoKKyAqIENvcHlyaWdodCDCqSAyMDE2IEludGVsIENv cnBvcmF0aW9uCisgKgorICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBj aGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEKKyAqIGNvcHkgb2YgdGhpcyBzb2Z0d2Fy ZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCisg KiB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcg d2l0aG91dCBsaW1pdGF0aW9uCisgKiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBt ZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwKKyAqIGFuZC9vciBzZWxsIGNv cGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZQor ICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dp bmcgY29uZGl0aW9uczoKKyAqCisgKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhp cyBwZXJtaXNzaW9uIG5vdGljZSAoaW5jbHVkaW5nIHRoZSBuZXh0CisgKiBwYXJhZ3JhcGgpIHNo YWxsIGJlIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2Yg dGhlCisgKiBTb2Z0d2FyZS4KKyAqCisgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElT IiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwg SU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFC SUxJVFksCisgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklO R0VNRU5ULiAgSU4gTk8gRVZFTlQgU0hBTEwKKyAqIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBI T0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCisgKiBMSUFC SUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lT RSwgQVJJU0lORworICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09G VFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUworICogSU4gVEhFIFNPRlRXQVJFLgor ICoKKyAqIEF1dGhvcnM6CisgKiAgICBSYWZhZWwgQW50b2dub2xsaSA8cmFmYWVsLmFudG9nbm9s bGlAaW50ZWwuY29tPgorICogICAgU2NvdHQgIEJhdWVyICAgICAgPHNjb3R0LmJhdWVyQGludGVs LmNvbT4KKyAqLworCisjZGVmaW5lIHByX2ZtdChmbXQpIEtCVUlMRF9NT0ROQU1FICI6T1BBTDog IiBmbXQKKworI2luY2x1ZGUgPGxpbnV4L2RlbGF5Lmg+CisjaW5jbHVkZSA8bGludXgvZGV2aWNl Lmg+CisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvbGlzdC5oPgor I2luY2x1ZGUgPGxpbnV4L2dlbmhkLmg+CisjaW5jbHVkZSA8bGludXgvc2xhYi5oPgorI2luY2x1 ZGUgPGxpbnV4L3VhY2Nlc3MuaD4KKyNpbmNsdWRlIDx1YXBpL2xpbnV4L3NlZC1vcGFsLmg+Cisj aW5jbHVkZSA8bGludXgvc2VkLmg+CisjaW5jbHVkZSA8bGludXgvc2VkLW9wYWwuaD4KKyNpbmNs dWRlIDxsaW51eC9zdHJpbmcuaD4KKworI2luY2x1ZGUgInNlZC1vcGFsX2ludGVybmFsLmgiCisK KyNkZWZpbmUgSU9fQlVGRkVSX0xFTkdUSCAyMDQ4CisKKyNkZWZpbmUgTUFYX1RPS1MgNjQKKwor c3RydWN0IG9wYWxfY21kIHsKKwlzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2OworCXNlY19jYiAq Y2I7CisJdm9pZCAqY2JfZGF0YTsKKworCXNpemVfdCBwb3M7CisJdTggY21kX2J1ZltJT19CVUZG RVJfTEVOR1RIICogMl07CisJdTggcmVzcF9idWZbSU9fQlVGRkVSX0xFTkdUSCAqIDJdOworCXU4 ICpjbWQ7CisJdTggKnJlc3A7Cit9OworCisvKgorICogT24gdGhlIHBhcnNlZCByZXNwb25zZSwg d2UgZG9uJ3Qgc3RvcmUgYWdhaW4gdGhlIHRva3MgdGhhdCBhcmUgYWxyZWFkeQorICogc3RvcmVk IGluIHRoZSByZXNwb25zZSBidWZmZXIuIEluc3RlYWQsIGZvciBlYWNoIHRva2VuLCB3ZSBqdXN0 IHN0b3JlIGEKKyAqIHBvaW50ZXIgdG8gdGhlIHBvc2l0aW9uIGluIHRoZSBidWZmZXIgd2hlcmUg dGhlIHRva2VuIHN0YXJ0cywgYW5kIHRoZSBzaXplCisgKiBvZiB0aGUgdG9rZW4gaW4gYnl0ZXMu CisgKi8KK3N0cnVjdCBvcGFsX3Jlc3BfdG9rIHsKKwljb25zdCB1OCAqcG9zOworCXNpemVfdCBs ZW47CisJZW51bSBPUEFMX1JFU1BPTlNFX1RPS0VOIHR5cGU7CisJZW51bSBPUEFMX0FUT01fV0lE VEggd2lkdGg7CisJdW5pb24geworCQl1NjQgdTsKKwkJczY0IHM7CisJfSBzdG9yZWQ7Cit9Owor CisvKgorICogRnJvbSB0aGUgcmVzcG9uc2UgaGVhZGVyIGl0J3Mgbm90IHBvc3NpYmxlIHRvIGtu b3cgaG93IG1hbnkgdG9rZW5zIHRoZXJlIGFyZQorICogb24gdGhlIHBheWxvYWQuIFNvIHdlIGhh cmRjb2RlIHRoYXQgdGhlIG1heGltdW0gd2lsbCBiZSBNQVhfVE9LUywgYW5kIGxhdGVyCisgKiBp ZiB3ZSBzdGFydCBkZWFsaW5nIHdpdGggbWVzc2FnZXMgdGhhdCBoYXZlIG1vcmUgdGhhbiB0aGF0 LCB3ZSBjYW4gaW5jcmVhc2UKKyAqIHRoaXMgbnVtYmVyLiBUaGlzIGlzIGRvbmUgdG8gYXZvaWQg aGF2aW5nIHRvIG1ha2UgdHdvIHBhc3NlcyB0aHJvdWdoIHRoZQorICogcmVzcG9uc2UsIHRoZSBm aXJzdCBvbmUgY291bnRpbmcgaG93IG1hbnkgdG9rZW5zIHdlIGhhdmUgYW5kIHRoZSBzZWNvbmQg b25lCisgKiBhY3R1YWxseSBzdG9yaW5nIHRoZSBwb3NpdGlvbnMuCisgKi8KK3N0cnVjdCBwYXJz ZWRfcmVzcCB7CisJaW50IG51bTsKKwlzdHJ1Y3Qgb3BhbF9yZXNwX3RvayB0b2tzW01BWF9UT0tT XTsKK307CisKK3N0cnVjdCBvcGFsX2RldjsKKwordHlwZWRlZiB2b2lkICgqb3BhbF9jYikoaW50 IGVycm9yLCBzdHJ1Y3Qgb3BhbF9kZXYgKmRldik7CisKK3R5cGVkZWYgaW50ICgqb3BhbF9zdGVw KShzdHJ1Y3Qgb3BhbF9kZXYgKmRldik7CisKK3N0cnVjdCBvcGFsX2NvbXBsZXRpb24geworCXN0 cnVjdCBjb21wbGV0aW9uIGNtZF9jb21wbGV0aW9uOworCWludCBjb21wbGV0aW9uX3N0YXR1czsK K307CisKK3N0cnVjdCBvcGFsX2RldiB7CisJc3RydWN0IGJsb2NrX2RldmljZSAqYmRldjsKKwlz dHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpjb21wbGV0aW9uOworCXN0cnVjdCBvcGFsX2xvY2tfdW5s b2NrIGxrdWw7CisJY29uc3Qgb3BhbF9zdGVwICpmdW5jczsKKwl2b2lkICoqZnVuY19kYXRhOwor CWJvb2wgcmVzdW1lX2Zyb21fc3VzcGVuZDsKKwlzdHJ1Y3Qgb3BhbF9zdXNwZW5kX3VubGsgKnJl c3VtZV9kYXRhOworCXNpemVfdCBudW1fZnVuY19kYXRhOworCWF0b21pY190IGluX3VzZTsKKwlz ZWN0b3JfdCBzdGFydDsKKwlzZWN0b3JfdCBsZW5ndGg7CisJdTggbHI7CisJdTgga2V5X3R5cGU7 CisJdTgga2V5X25hbWVbT1BBTF9LRVlfTUFYXTsKKwlzaXplX3Qga2V5X25hbWVfbGVuOworCXU4 IGtleVtPUEFMX0tFWV9NQVhdOworCXNpemVfdCBrZXlfbGVuOworCXUxNiBjb21JRDsKKwl1MzIg SFNOOworCXUzMiBUU047CisJdTY0IGFsaWduOworCXU2NCBsb3dlc3RfbGJhOworCXN0cnVjdCBs aXN0X2hlYWQgbm9kZTsKKwljaGFyIGRpc2tfbmFtZVtESVNLX05BTUVfTEVOXTsKKwlpbnQgc3Rh dGU7CisKKwlzdHJ1Y3Qgb3BhbF9jbWQgY21kOworCXN0cnVjdCBwYXJzZWRfcmVzcCBwYXJzZWQ7 CisKKwlzaXplX3QgcHJldl9kX2xlbjsKKwl2b2lkICpwcmV2X2RhdGE7CisKKwlzZWNfY2IgKmZp bmFsX2NiOworCXZvaWQgKmZpbmFsX2NiX2RhdGE7CisJb3BhbF9zdGVwIGVycm9yX2NiOworCXZv aWQgKmVycm9yX2NiX2RhdGE7CisJb3BhbF9jYiBvcGVyX2NiOworfTsKKworTElTVF9IRUFEKG9w YWxfbGlzdCk7CitERUZJTkVfU1BJTkxPQ0sobGlzdF9zcGlubG9jayk7CisKK3N0YXRpYyB2b2lk IHByaW50X2J1ZmZlcihjb25zdCB1OCAqcHRyLCB1MzIgbGVuZ3RoKQoreworI2lmZGVmIERFQlVH CisJcHJpbnRfaGV4X2R1bXBfYnl0ZXMoIk9QQUw6ICIsIERVTVBfUFJFRklYX09GRlNFVCwgcHRy LCBsZW5ndGgpOworCXByX2RlYnVnKCJcbiIpOworI2VuZGlmCit9CisKKyNkZWZpbmUgVFBFUl9T WU5DX1NVUFBPUlRFRCBCSVQoMCkKKworc3RhdGljIGJvb2wgY2hlY2tfdHBlcihjb25zdCB2b2lk ICpkYXRhKQoreworCWNvbnN0IHN0cnVjdCBkMF90cGVyX2ZlYXR1cmVzICp0cGVyID0gZGF0YTsK Kwl1OCBmbGFncyA9IHRwZXItPnN1cHBvcnRlZF9mZWF0dXJlczsKKworCWlmICghKGZsYWdzICYg VFBFUl9TWU5DX1NVUFBPUlRFRCkpIHsKKwkJcHJfZXJyKCJUUGVyIHN5bmMgbm90IHN1cHBvcnRl ZC4gZmxhZ3MgPSAlZFxuIiwKKwkJICAgICAgIHRwZXItPnN1cHBvcnRlZF9mZWF0dXJlcyk7CisJ CXJldHVybiBmYWxzZTsKKwl9CisKKwlyZXR1cm4gdHJ1ZTsKK30KKworc3RhdGljIGJvb2wgY2hl Y2tfU1VNKGNvbnN0IHZvaWQgKmRhdGEpCit7CisJY29uc3Qgc3RydWN0IGQwX3NpbmdsZV91c2Vy X21vZGUgKnN1bSA9IGRhdGE7CisJdTMyIG5sbyA9IGJlMzJfdG9fY3B1KHN1bS0+bnVtX2xvY2tp bmdfb2JqZWN0cyk7CisKKwlpZiAobmxvID09IDApIHsKKwkJcHJfZXJyKCJOZWVkIGF0IGxlYXN0 IG9uZSBsb2NraW5nIG9iamVjdC5cbiIpOworCQlyZXR1cm4gZmFsc2U7CisJfQorCisJcHJfZGVi dWcoIk51bWJlciBvZiBsb2NraW5nIG9iamVjdHM6ICVkXG4iLCBubG8pOworCisJcmV0dXJuIHRy dWU7Cit9CisKK3N0YXRpYyB1MTYgZ2V0X2NvbUlEX3YxMDAoY29uc3Qgdm9pZCAqZGF0YSkKK3sK Kwljb25zdCBzdHJ1Y3QgZDBfb3BhbF92MTAwICp2MTAwID0gZGF0YTsKKworCXJldHVybiBiZTE2 X3RvX2NwdSh2MTAwLT5iYXNlQ29tSUQpOworfQorCitzdGF0aWMgdTE2IGdldF9jb21JRF92MjAw KGNvbnN0IHZvaWQgKmRhdGEpCit7CisJY29uc3Qgc3RydWN0IGQwX29wYWxfdjIwMCAqdjIwMCA9 IGRhdGE7CisKKwlyZXR1cm4gYmUxNl90b19jcHUodjIwMC0+YmFzZUNvbUlEKTsKK30KKworc3Rh dGljIGludCBfX29wYWxfc2VuZF9jbWQoc3RydWN0IG9wYWxfc3VzcGVuZF91bmxrICpkYXRhLCB1 MTYgY29tSUQsCisJCQkgICB2b2lkICpidWZmZXIsIHNpemVfdCBidWZsZW4sIHNlY19jYiAqY2Is CisJCQkgICB2b2lkICpjYl9kYXRhKQoreworCXJldHVybiBkYXRhLT5vcHMuc2VuZChkYXRhLT5k YXRhLCBjb21JRCwgVENHX1NFQ1BfMDEsIGJ1ZmZlciwgYnVmbGVuLAorCQkJICAgICBjYiwgY2Jf ZGF0YSk7Cit9CitzdGF0aWMgaW50IF9vcGFsX3NlbmRfY21kKHN0cnVjdCBibG9ja19kZXZpY2Ug KmJkZXYsIHUxNiBjb21JRCwKKwkJCSAgdm9pZCAqYnVmZmVyLCBzaXplX3QgYnVmbGVuLAorCQkJ ICBzZWNfY2IgKmNiLCB2b2lkICpjYl9kYXRhKQoreworCWNvbnN0IHN0cnVjdCBzZWNfb3BzICpv cHMgPSBiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzOworCisJcmV0dXJuIG9wcy0+c2VuZChi ZGV2LT5iZF9kaXNrLT5wcml2YXRlX2RhdGEsIGNvbUlELAorCQkJIFRDR19TRUNQXzAxLCBidWZm ZXIsIGJ1ZmxlbiwKKwkJCSBjYiwgY2JfZGF0YSk7Cit9CisKK3N0YXRpYyBpbnQgX19vcGFsX3Jl Y3ZfY21kKHN0cnVjdCBvcGFsX3N1c3BlbmRfdW5sayAqZGF0YSwgdTE2IGNvbUlELAorCQkJICAg dm9pZCAqYnVmZmVyLCBzaXplX3QgYnVmbGVuLCBzZWNfY2IgKmNiLAorCQkJICAgdm9pZCAqY2Jf ZGF0YSkKK3sKKwlyZXR1cm4gZGF0YS0+b3BzLnJlY3YoZGF0YS0+ZGF0YSwgY29tSUQsIFRDR19T RUNQXzAxLCBidWZmZXIsIGJ1ZmxlbiwKKwkJCSAgICAgY2IsIGNiX2RhdGEpOworfQorCitzdGF0 aWMgaW50IF9vcGFsX3JlY3ZfY21kKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHUxNiBjb21J RCwKKwkJCSAgdm9pZCAqYnVmZmVyLCBzaXplX3QgYnVmbGVuLAorCQkJICBzZWNfY2IgKmNiLCB2 b2lkICpjYl9kYXRhKQoreworCWNvbnN0IHN0cnVjdCBzZWNfb3BzICpvcHMgPSBiZGV2LT5iZF9k aXNrLT5mb3BzLT5zZWNfb3BzOworCisJcmV0dXJuIG9wcy0+cmVjdihiZGV2LT5iZF9kaXNrLT5w cml2YXRlX2RhdGEsIGNvbUlELAorCQkJIFRDR19TRUNQXzAxLCBidWZmZXIsIGJ1ZmxlbiwKKwkJ CSBjYiwgY2JfZGF0YSk7Cit9CisKK3N0YXRpYyB2b2lkIG9wYWxfc2VuZF9jYl9jb250KGludCBl cnJvciwgdm9pZCAqZGF0YSkKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJc2l6 ZV90IGJ1ZmxlbiA9IElPX0JVRkZFUl9MRU5HVEg7CisJdm9pZCAqYnVmZmVyID0gZGV2LT5jbWQu cmVzcDsKKwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9IGJ1ZmZlcjsKKworCXByX2RlYnVnKCIl czogU2VudCBPUEFMIGNvbW1hbmQ6IGVycm9yPSVkLCBvdXRzdGFuZGluZz0lZCwgbWluVHJhbnNm ZXI9JWRcbiIsCisJICAgICAgIGRldi0+ZGlza19uYW1lLCBlcnJvciwgaGRyLT5jcC5vdXRzdGFu ZGluZ0RhdGEsCisJICAgICAgIGhkci0+Y3AubWluVHJhbnNmZXIpOworCisJaWYgKGVycm9yIHx8 IGhkci0+Y3Aub3V0c3RhbmRpbmdEYXRhID09IDAgfHwKKwkgICAgaGRyLT5jcC5taW5UcmFuc2Zl ciAhPSAwKSB7CisJCWlmIChkZXYtPmNtZC5jYikKKwkJCWRldi0+Y21kLmNiKGVycm9yLCBkZXYt PmNtZC5jYl9kYXRhKTsKKwkJcmV0dXJuOworCX0KKworCW1lbXNldChidWZmZXIsIDAsIGJ1Zmxl bik7CisJaWYgKGRldi0+cmVzdW1lX2Zyb21fc3VzcGVuZCkKKwkJX19vcGFsX3JlY3ZfY21kKGRl di0+cmVzdW1lX2RhdGEsIGRldi0+Y29tSUQsCisJCQkJYnVmZmVyLCBidWZsZW4sIG9wYWxfc2Vu ZF9jYl9jb250LCBkZXYpOworCWVsc2UKKwkJX29wYWxfcmVjdl9jbWQoZGV2LT5iZGV2LCBkZXYt PmNvbUlELCBidWZmZXIsIGJ1ZmxlbiwKKwkJCSAgICAgICBvcGFsX3NlbmRfY2JfY29udCwgZGV2 KTsKK30KKworc3RhdGljIHZvaWQgb3BhbF9zZW5kX2NiKGludCBlcnJvciwgdm9pZCAqZGF0YSkK K3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJc2l6ZV90IGJ1ZmxlbiA9IElPX0JV RkZFUl9MRU5HVEg7CisJdm9pZCAqYnVmZmVyID0gZGV2LT5jbWQucmVzcDsKKworCWlmIChlcnJv cikgeworCQlpZiAoZGV2LT5jbWQuY2IpCisJCQlkZXYtPmNtZC5jYihlcnJvciwgZGV2LT5jbWQu Y2JfZGF0YSk7CisJCXJldHVybjsKKwl9CisKKwltZW1zZXQoYnVmZmVyLCAwLCBidWZsZW4pOwor CWlmIChkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQpCisJCV9fb3BhbF9yZWN2X2NtZChkZXYtPnJl c3VtZV9kYXRhLCBkZXYtPmNvbUlELAorCQkJCWJ1ZmZlciwgYnVmbGVuLCBvcGFsX3NlbmRfY2Jf Y29udCwgZGV2KTsKKwllbHNlCisJCV9vcGFsX3JlY3ZfY21kKGRldi0+YmRldiwgZGV2LT5jb21J RCwgYnVmZmVyLCBidWZsZW4sCisJCQkgICAgICAgb3BhbF9zZW5kX2NiX2NvbnQsIGRldik7Cit9 CisKK3N0YXRpYyBpbnQgb3BhbF9zZW5kX3JlY3Yoc3RydWN0IG9wYWxfZGV2ICpkZXYsIHNlY19j YiAqY2IsIHZvaWQgKmNiX2RhdGEpCit7CisJc2l6ZV90IGJ1ZmxlbiA9IElPX0JVRkZFUl9MRU5H VEg7CisJdm9pZCAqYnVmZmVyID0gZGV2LT5jbWQuY21kOworCWludCByZXQ7CisKKwlkZXYtPmNt ZC5jYiA9IGNiOworCWRldi0+Y21kLmNiX2RhdGEgPSBjYl9kYXRhOworCWlmIChkZXYtPnJlc3Vt ZV9mcm9tX3N1c3BlbmQpCisJCXJldCA9IF9fb3BhbF9zZW5kX2NtZChkZXYtPnJlc3VtZV9kYXRh LCBkZXYtPmNvbUlELCBidWZmZXIsCisJCQkJICAgICAgYnVmbGVuLCBvcGFsX3NlbmRfY2IsIGRl dik7CisJZWxzZQorCQlyZXQgPSBfb3BhbF9zZW5kX2NtZChkZXYtPmJkZXYsIGRldi0+Y29tSUQs IGJ1ZmZlciwgYnVmbGVuLAorCQkJCSAgICAgb3BhbF9zZW5kX2NiLCBkZXYpOworCisJcmV0dXJu IHJldDsKK30KKworc3RhdGljIHZvaWQgY2hlY2tfZ2VvbWV0cnkoc3RydWN0IG9wYWxfZGV2ICpk ZXYsIGNvbnN0IHZvaWQgKmRhdGEpCit7CisJY29uc3Qgc3RydWN0IGQwX2dlb21ldHJ5X2ZlYXR1 cmVzICpnZW8gPSBkYXRhOworCisJZGV2LT5hbGlnbiA9IGdlby0+YWxpZ25tZW50X2dyYW51bGFy aXR5OworCWRldi0+bG93ZXN0X2xiYSA9IGdlby0+bG93ZXN0X2FsaWduZWRfbGJhOworfQorCitz dGF0aWMgdm9pZCBvcGFsX2Rpc2NvdmVyeTBfZW5kKGludCBlcnJvciwgdm9pZCAqZGF0YSkKK3sK Kwlib29sIGZvdW5kQ29tSUQgPSBmYWxzZSwgc3VwcG9ydGVkID0gdHJ1ZSwgc2luZ2xlX3VzZXIg PSBmYWxzZTsKKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJY29uc3Qgc3RydWN0IGQw X2hlYWRlciAqaGRyOworCWNvbnN0IHU4ICplcG9zLCAqY3BvczsKKwl1MTYgY29tSUQgPSAwOwor CisJaWYgKGVycm9yKSB7CisJCXByX2VycigiJXM6IFNlbmRpbmcgZGlzY292ZXJ5MCBmYWlsZWRc biIsIGRldi0+ZGlza19uYW1lKTsKKwkJZ290byBlcnJfY2FsbGJhY2s7CisJfQorCisJZXBvcyA9 IGRldi0+Y21kLnJlc3A7CisJY3BvcyA9IGRldi0+Y21kLnJlc3A7CisJaGRyID0gKHN0cnVjdCBk MF9oZWFkZXIgKilkZXYtPmNtZC5yZXNwOworCisJcHJpbnRfYnVmZmVyKGRldi0+Y21kLnJlc3As IGJlMzJfdG9fY3B1KGhkci0+bGVuZ3RoKSk7CisKKwllcG9zICs9IGJlMzJfdG9fY3B1KGhkci0+ bGVuZ3RoKTsgLyogZW5kIG9mIGJ1ZmZlciAqLworCWNwb3MgKz0gc2l6ZW9mKCpoZHIpOyAvKiBj dXJyZW50IHBvc2l0aW9uIG9uIGJ1ZmZlciAqLworCisJd2hpbGUgKGNwb3MgPCBlcG9zICYmIHN1 cHBvcnRlZCkgeworCQljb25zdCBzdHJ1Y3QgZDBfZmVhdHVyZXMgKmJvZHkgPQorCQkJKGNvbnN0 IHN0cnVjdCBkMF9mZWF0dXJlcyAqKWNwb3M7CisKKwkJc3dpdGNoIChiZTE2X3RvX2NwdShib2R5 LT5jb2RlKSkgeworCQljYXNlIEZDX1RQRVI6CisJCQlzdXBwb3J0ZWQgPSBjaGVja190cGVyKGJv ZHktPmZlYXR1cmVzKTsKKwkJCWJyZWFrOworCQljYXNlIEZDX1NJTkdMRVVTRVI6CisJCQlzaW5n bGVfdXNlciA9IGNoZWNrX1NVTShib2R5LT5mZWF0dXJlcyk7CisJCQlicmVhazsKKwkJY2FzZSBG Q19HRU9NRVRSWToKKwkJCWNoZWNrX2dlb21ldHJ5KGRldiwgYm9keSk7CisJCQlicmVhazsKKwkJ Y2FzZSBGQ19MT0NLSU5HOgorCQljYXNlIEZDX0VOVEVSUFJJU0U6CisJCWNhc2UgRkNfREFUQVNU T1JFOgorCQkJLyogc29tZSBpZ25vcmVkIHByb3BlcnRpZXMgKi8KKwkJCXByX2RlYnVnKCIlczog Rm91bmQgT1BBTCBmZWF0dXJlIGRlc2NyaXB0aW9uOiAlZFxuIiwKKwkJCQkgZGV2LT5kaXNrX25h bWUsIGJlMTZfdG9fY3B1KGJvZHktPmNvZGUpKTsKKwkJCWJyZWFrOworCQljYXNlIEZDX09QQUxW MTAwOgorCQkJY29tSUQgPSBnZXRfY29tSURfdjEwMChib2R5LT5mZWF0dXJlcyk7CisJCQlmb3Vu ZENvbUlEID0gdHJ1ZTsKKwkJCWJyZWFrOworCQljYXNlIEZDX09QQUxWMjAwOgorCQkJY29tSUQg PSBnZXRfY29tSURfdjIwMChib2R5LT5mZWF0dXJlcyk7CisJCQlmb3VuZENvbUlEID0gdHJ1ZTsK KwkJCWJyZWFrOworCQlkZWZhdWx0OgorCQkJaWYgKGJlMTZfdG9fY3B1KGJvZHktPmNvZGUpID4g MHhiZmZmKSB7CisJCQkJLyogdmVuZG9yIHNwZWNpZmljLCBqdXN0IGlnbm9yZSAqLworCQkJfSBl bHNlIHsKKwkJCQlwcl93YXJuKCIlczogT1BBTCBVbmtub3duIGZlYXR1cmU6ICVkXG4iLAorCQkJ CQlkZXYtPmRpc2tfbmFtZSwgYmUxNl90b19jcHUoYm9keS0+Y29kZSkpOworCQkJfQorCQl9CisJ CWNwb3MgKz0gYm9keS0+bGVuZ3RoICsgNDsKKwl9CisKKwlpZiAoIXN1cHBvcnRlZCkgeworCQlw cl9lcnIoIiVzOiBEZXZpY2Ugbm90IHN1cHBvcnRlZFxuIiwgZGV2LT5kaXNrX25hbWUpOworCQln b3RvIGVycl9jYWxsYmFjazsKKwl9CisKKwlpZiAoIXNpbmdsZV91c2VyKQorCQlwcl93YXJuKCIl czogRGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCBzaW5nbGUgdXNlciBtb2RlXG4iLAorCQkJZGV2LT5k aXNrX25hbWUpOworCisJaWYgKCFmb3VuZENvbUlEKSB7CisJCXByX3dhcm4oIiVzOiBDb3VsZCBu b3QgZmluZCBPUEFMIGNvbUlEIGZvciBkZXZpY2UuIE9QQUwga2VybmVsIHVubG9ja2luZyB3aWxs IGJlIGRpc2FibGVkXG4iLAorCQkJZGV2LT5kaXNrX25hbWUpOworCQlnb3RvIGVycl9jYWxsYmFj azsKKwl9CisKKwlkZXYtPmNvbUlEID0gY29tSUQ7CisKK2Vycl9jYWxsYmFjazoKKwlpZiAoZGV2 LT5vcGVyX2NiKQorCQlkZXYtPm9wZXJfY2IoZXJyb3IsIGRldik7Cit9CisKK3N0YXRpYyBpbnQg b3BhbF9kaXNjb3ZlcnkwKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCW1lbXNldChkZXYtPmNt ZC5yZXNwLCAwLCBJT19CVUZGRVJfTEVOR1RIKTsKKworCWlmIChkZXYtPnJlc3VtZV9mcm9tX3N1 c3BlbmQpCisJCXJldHVybiBfX29wYWxfcmVjdl9jbWQoZGV2LT5yZXN1bWVfZGF0YSwgMHgwMDAx LAorCQkJCSAgICAgICBkZXYtPmNtZC5yZXNwLCBJT19CVUZGRVJfTEVOR1RILAorCQkJCSAgICAg ICBvcGFsX2Rpc2NvdmVyeTBfZW5kLCBkZXYpOworCisJcmV0dXJuIF9vcGFsX3JlY3ZfY21kKGRl di0+YmRldiwgMHgwMDAxLCBkZXYtPmNtZC5yZXNwLAorCQkJICAgICAgSU9fQlVGRkVSX0xFTkdU SCwgb3BhbF9kaXNjb3ZlcnkwX2VuZCwKKwkJCSAgICAgIGRldik7Cit9CisKK3N0YXRpYyB2b2lk IGFkZF90b2tlbl91OChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTggdG9rKQoreworCWNtZC0+Y21k W2NtZC0+cG9zKytdID0gdG9rOworfQorCitzdGF0aWMgc3NpemVfdCB0ZXN0X2FuZF9hZGRfdG9r ZW5fdTgoc3RydWN0IG9wYWxfY21kICpjbWQsIHU4IHRvaykKK3sKKwlCVUlMRF9CVUdfT04oSU9f QlVGRkVSX0xFTkdUSCA+PSBTSVpFX01BWCk7CisKKwlpZiAoY21kLT5wb3MgPj0gSU9fQlVGRkVS X0xFTkdUSCAtIDEpIHsKKwkJcHJfZXJyKCJFcnJvciBhZGRpbmcgdTg6IGVuZCBvZiBidWZmZXIu XG4iKTsKKwkJcmV0dXJuIC1FUkFOR0U7CisJfQorCisJYWRkX3Rva2VuX3U4KGNtZCwgdG9rKTsK KworCXJldHVybiAxOworfQorCisjZGVmaW5lIFRJTllfQVRPTV9EQVRBX01BU0sgR0VOTUFTSyg1 LCAwKQorI2RlZmluZSBUSU5ZX0FUT01fU0lHTkVEIEJJVCg2KQorCisjZGVmaW5lIFNIT1JUX0FU T01fSUQgQklUKDcpCisjZGVmaW5lIFNIT1JUX0FUT01fQllURVNUUklORyBCSVQoNSkKKyNkZWZp bmUgU0hPUlRfQVRPTV9TSUdORUQgQklUKDQpCisjZGVmaW5lIFNIT1JUX0FUT01fTEVOX01BU0sg R0VOTUFTSygzLCAwKQorCitzdGF0aWMgdm9pZCBhZGRfc2hvcnRfYXRvbV9oZWFkZXIoc3RydWN0 IG9wYWxfY21kICpjbWQsIGJvb2wgYnl0ZXN0cmluZywKKwkJCQkgIGJvb2wgaGFzX3NpZ24sIGlu dCBsZW4pCit7CisJdTggYXRvbTsKKworCWF0b20gPSBTSE9SVF9BVE9NX0lEOworCWF0b20gfD0g Ynl0ZXN0cmluZyA/IFNIT1JUX0FUT01fQllURVNUUklORyA6IDA7CisJYXRvbSB8PSBoYXNfc2ln biA/IFNIT1JUX0FUT01fU0lHTkVEIDogMDsKKwlhdG9tIHw9IGxlbiAmIFNIT1JUX0FUT01fTEVO X01BU0s7CisKKwlhZGRfdG9rZW5fdTgoY21kLCBhdG9tKTsKK30KKworI2RlZmluZSBNRURJVU1f QVRPTV9JRCAoQklUKDcpIHwgQklUKDYpKQorI2RlZmluZSBNRURJVU1fQVRPTV9CWVRFU1RSSU5H IEJJVCg0KQorI2RlZmluZSBNRURJVU1fQVRPTV9TSUdORUQgQklUKDMpCisjZGVmaW5lIE1FRElV TV9BVE9NX0xFTl9NQVNLIEdFTk1BU0soMiwgMCkKKworc3RhdGljIHZvaWQgYWRkX21lZGl1bV9h dG9tX2hlYWRlcihzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgYm9vbCBieXRlc3RyaW5nLAorCQkJCSAg IGJvb2wgaGFzX3NpZ24sIGludCBsZW4pCit7CisJdTggaGVhZGVyMDsKKworCWhlYWRlcjAgPSBN RURJVU1fQVRPTV9JRDsKKwloZWFkZXIwIHw9IGJ5dGVzdHJpbmcgPyBNRURJVU1fQVRPTV9CWVRF U1RSSU5HIDogMDsKKwloZWFkZXIwIHw9IGhhc19zaWduID8gTUVESVVNX0FUT01fU0lHTkVEIDog MDsKKwloZWFkZXIwIHw9IChsZW4gPj4gOCkgJiBNRURJVU1fQVRPTV9MRU5fTUFTSzsKKwljbWQt PmNtZFtjbWQtPnBvcysrXSA9IGhlYWRlcjA7CisJY21kLT5jbWRbY21kLT5wb3MrK10gPSBsZW47 Cit9CisKK3N0YXRpYyB2b2lkIGFkZF90b2tlbl91NjQoc3RydWN0IG9wYWxfY21kICpjbWQsIHU2 NCBudW1iZXIsIHNpemVfdCBsZW4pCit7CisJYWRkX3Nob3J0X2F0b21faGVhZGVyKGNtZCwgZmFs c2UsIGZhbHNlLCBsZW4pOworCisJd2hpbGUgKGxlbi0tKSB7CisJCXU4IG4gPSBudW1iZXIgPj4g KGxlbiAqIDgpOworCisJCWFkZF90b2tlbl91OChjbWQsIG4pOworCX0KK30KKworc3RhdGljIHNz aXplX3QgdGVzdF9hbmRfYWRkX3Rva2VuX3U2NChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTY0IG51 bWJlcikKK3sKKwlpbnQgbGVuOworCWludCBtc2I7CisKKwlpZiAoIShudW1iZXIgJiB+VElOWV9B VE9NX0RBVEFfTUFTSykpCisJCXJldHVybiB0ZXN0X2FuZF9hZGRfdG9rZW5fdTgoY21kLCBudW1i ZXIpOworCisJbXNiID0gZmxzKG51bWJlcik7CisJbGVuID0gRElWX1JPVU5EX1VQKG1zYiwgNCk7 CisKKwlpZiAoY21kLT5wb3MgPj0gSU9fQlVGRkVSX0xFTkdUSCAtIGxlbiAtIDEpIHsKKwkJcHJf ZXJyKCJFcnJvciBhZGRpbmcgdTY0OiBlbmQgb2YgYnVmZmVyLlxuIik7CisJCXJldHVybiAtRVJB TkdFOworCX0KKworCWFkZF90b2tlbl91NjQoY21kLCBudW1iZXIsIGxlbik7CisKKwkvKiByZXR1 cm4gbGVuZ3RoIG9mIHRva2VuIHBsdXMgYXRvbSAqLworCXJldHVybiBsZW4gKyAxOworfQorCitz dGF0aWMgdm9pZCBhZGRfdG9rZW5fYnl0ZXN0cmluZyhzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwKKwkJ CQkgY29uc3QgdTggKmJ5dGVzdHJpbmcsIHNpemVfdCBsZW4pCit7CisJbWVtY3B5KCZjbWQtPmNt ZFtjbWQtPnBvc10sIGJ5dGVzdHJpbmcsIGxlbik7CisJY21kLT5wb3MgKz0gbGVuOworfQorCitz dGF0aWMgc3NpemVfdCB0ZXN0X2FuZF9hZGRfdG9rZW5fYnl0ZXN0cmluZyhzdHJ1Y3Qgb3BhbF9j bWQgKmNtZCwKKwkJCQkJICAgICBjb25zdCB1OCAqYnl0ZXN0cmluZywgc2l6ZV90IGxlbikKK3sK KwlzaXplX3QgaGVhZGVyX2xlbiA9IDE7CisJYm9vbCBpc19zaG9ydF9hdG9tID0gdHJ1ZTsKKwor CWlmIChsZW4gJiB+U0hPUlRfQVRPTV9MRU5fTUFTSykgeworCQloZWFkZXJfbGVuID0gMjsKKwkJ aXNfc2hvcnRfYXRvbSA9IGZhbHNlOworCX0KKworCWlmIChjbWQtPnBvcyA+PSBJT19CVUZGRVJf TEVOR1RIIC0gbGVuIC0gaGVhZGVyX2xlbikgeworCQlwcl9lcnIoIkVycm9yIGFkZGluZyBieXRl c3RyaW5nOiBlbmQgb2YgYnVmZmVyLlxuIik7CisJCXJldHVybiAtRVJBTkdFOworCX0KKworCWlm IChpc19zaG9ydF9hdG9tKQorCQlhZGRfc2hvcnRfYXRvbV9oZWFkZXIoY21kLCB0cnVlLCBmYWxz ZSwgbGVuKTsKKwllbHNlCisJCWFkZF9tZWRpdW1fYXRvbV9oZWFkZXIoY21kLCB0cnVlLCBmYWxz ZSwgbGVuKTsKKworCWFkZF90b2tlbl9ieXRlc3RyaW5nKGNtZCwgYnl0ZXN0cmluZywgbGVuKTsK KworCXJldHVybiBoZWFkZXJfbGVuICsgbGVuOworfQorCisjZGVmaW5lIExPQ0tJTkdfUkFOR0Vf Tk9OX0dMT0JBTCAweDAzCisKK3N0YXRpYyBpbnQgYnVpbGRfbG9ja2luZ19yYW5nZSh1OCAqYnVm ZmVyLCBzaXplX3QgbGVuZ3RoLCB1OCBscikKK3sKKwlpZiAobGVuZ3RoIDwgT1BBTF9VSURfTEVO R1RIKQorCQlyZXR1cm4gLUVSQU5HRTsKKworCW1lbWNweShidWZmZXIsIE9QQUxVSURbT1BBTF9M T0NLSU5HUkFOR0VfR0xPQkFMXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCWlmIChsciA9PSAwKQor CQlyZXR1cm4gMDsKKwlidWZmZXJbNV0gPSBMT0NLSU5HX1JBTkdFX05PTl9HTE9CQUw7CisJYnVm ZmVyWzddID0gbHI7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBidWlsZF9sb2NraW5n X3VzZXIodTggKmJ1ZmZlciwgc2l6ZV90IGxlbmd0aCwgdTggbHIpCit7CisJaWYgKGxlbmd0aCA8 IE9QQUxfVUlEX0xFTkdUSCkKKwkJcmV0dXJuIC1FUkFOR0U7CisKKwltZW1jcHkoYnVmZmVyLCBP UEFMVUlEW09QQUxfVVNFUjFfVUlEXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCWJ1ZmZlcls3XSA9 IGxyICsgMTsKKworCXJldHVybiAwOworfQorCisvKgorICogTiA9IG51bWJlciBvZiBmb3JtYXQg c3BlY2lmaWVycyAoMS05OTkpIHRvIGJlIHJlcGxpY2F0ZWQKKyAqIGMgPSB1OAorICogdSA9IHU2 NAorICogcyA9IGJ5dGVzdHJpbmcsIGxlbmd0aAorICoKKyAqIHJldCA9IHRlc3RfYW5kX2FkZF90 b2tlbl92YShjbWQsICJjIiwKKyAqCQkJICAgICAgIHU4X3ZhbDEpOworICoKKyAqIHJldCA9IHRl c3RfYW5kX2FkZF90b2tlbl92YShjbWQsICIyYzJ1IiwKKyAqCQkJICAgICAgIHU4X3ZhbDEsIHU4 X3ZhbDIsIHU2NF92YWwxLCB1NjRfdmFsMik7CisgKgorICogcmV0ID0gdGVzdF9hbmRfYWRkX3Rv a2VuX3ZhKGNtZCwgIjNzIiwKKyAqCQkJICAgICAgIGJ5dGVzdHJpbmcxLCBsZW5ndGgxLAorICoJ CQkgICAgICAgYnl0ZXN0cmluZzIsIGxlbmd0aDIsCisgKgkJCSAgICAgICBieXRlc3RyaW5nMywg bGVuZ3RoMyk7CisgKi8KK3N0YXRpYyBpbnQgdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKHN0cnVjdCBv cGFsX2NtZCAqY21kLAorCQkJCSBjb25zdCBjaGFyICpmbXQsIC4uLikKK3sKKwljb25zdCB1OCAq aXQgPSBmbXQsICp0bXA7CisJaW50IHJldCwgbnVtID0gMSwgc3VtID0gMDsKKwl2YV9saXN0IGFw OworCisJdmFfc3RhcnQoYXAsIGZtdCk7CisKKwl3aGlsZSAoKml0ICE9ICdcMCcpIHsKKwkJdTY0 IHRvazY0ID0gMDsKKwkJdTggdG9rLCAqYnN0cjsKKwkJc2l6ZV90IGxlbjsKKworCQlyZXQgPSAw OworCisJCXN3aXRjaCAoKml0KSB7CisJCWNhc2UgJzEnIC4uLiAnOSc6CisJCQl0bXAgPSBpdDsK KwkJCW51bSA9IDA7CisJCQl3aGlsZSAoKnRtcCA+PSAnMCcgJiYgKnRtcCA8PSAnOScpCisJCQkJ bnVtID0gbnVtICogMTAgKyAoKnRtcCsrIC0gJzAnKTsKKwkJCWl0ID0gdG1wOworCQkJY29udGlu dWU7CisJCWNhc2UgJ2MnOgorCQkJd2hpbGUgKG51bS0tKSB7CisJCQkJdG9rID0gdmFfYXJnKGFw LCB1bnNpZ25lZCBpbnQpOworCQkJCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl91OChjbWQsIHRv ayk7CisJCQkJaWYgKHJldCA8IDApCisJCQkJCWdvdG8gZXJyOworCQkJfQorCQkJbnVtID0gMTsK KwkJCWJyZWFrOworCQljYXNlICd1JzoKKwkJCXdoaWxlIChudW0tLSkgeworCQkJCXRvazY0ID0g dmFfYXJnKGFwLCB1NjQpOworCQkJCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl91NjQoY21kLCB0 b2s2NCk7CisJCQkJaWYgKHJldCA8IDApCisJCQkJCWdvdG8gZXJyOworCQkJfQorCQkJbnVtID0g MTsKKwkJCWJyZWFrOworCQljYXNlICdzJzoKKwkJCXdoaWxlIChudW0tLSkgeworCQkJCWJzdHIg PSB2YV9hcmcoYXAsIHU4ICopOworCQkJCWxlbiA9IHZhX2FyZyhhcCwgc2l6ZV90KTsKKwkJCQly ZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fYnl0ZXN0cmluZyhjbWQsIGJzdHIsCisJCQkJCQkJCSAg ICBsZW4pOworCQkJCWlmIChyZXQgPCAwKQorCQkJCQlnb3RvIGVycjsKKwkJCX0KKwkJCW51bSA9 IDE7CisJCQlicmVhazsKKwkJY2FzZSAnICc6CisJCWNhc2UgJ1x0JzoKKwkJCS8qIGlnbm9yZWQg Ki8KKwkJCWJyZWFrOworCQlkZWZhdWx0OgorCQkJcHJfd2FybigiVW5yZWNvZ25pemVkIHR5cGUu XG4iKTsKKwkJfQorCisJCWl0Kys7CisJCXN1bSArPSByZXQ7CisJfQorCisJdmFfZW5kKGFwKTsK KworCXJldHVybiBzdW07CisKKyBlcnI6CisJcHJfZXJyKCJUb2tlbiBmYWlsZWQgdG8gYmUgYWRk ZWQuXG4iKTsKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgdm9pZCBzZXRfY29tSUQoc3RydWN0 IG9wYWxfY21kICpjbWQsIHUxNiBjb21JRCkKK3sKKwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9 IChzdHJ1Y3Qgb3BhbF9oZWFkZXIgKiljbWQtPmNtZDsKKworCWhkci0+Y3AuZXh0ZW5kZWRDb21J RFswXSA9IGNvbUlEID4+IDg7CisJaGRyLT5jcC5leHRlbmRlZENvbUlEWzFdID0gY29tSUQ7CisJ aGRyLT5jcC5leHRlbmRlZENvbUlEWzJdID0gMDsKKwloZHItPmNwLmV4dGVuZGVkQ29tSURbM10g PSAwOworfQorCitzdGF0aWMgaW50IGNtZF9maW5hbGl6ZShzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwg dTMyIGhzbiwgdTMyIHRzbikKK3sKKwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkcjsKKwlpbnQgcmV0 OworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgIjZjIiwKKwkJCQkgICAgT1BB TF9FTkRPRkRBVEEsIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICAwLCAwLCAwLCBPUEFMX0VORExJ U1QpOworCisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCJFcnJvciBmaW5hbGl6aW5nIGNvbW1h bmQuXG4iKTsKKwkJcmV0dXJuIC1FRkFVTFQ7CisJfQorCisJaGRyID0gKHN0cnVjdCBvcGFsX2hl YWRlciAqKSBjbWQtPmNtZDsKKworCWhkci0+cGt0LlRTTiA9IGNwdV90b19iZTMyKHRzbik7CisJ aGRyLT5wa3QuSFNOID0gY3B1X3RvX2JlMzIoaHNuKTsKKworCWhkci0+c3VicGt0Lmxlbmd0aCA9 IGNwdV90b19iZTMyKGNtZC0+cG9zIC0gc2l6ZW9mKCpoZHIpKTsKKwl3aGlsZSAoY21kLT5wb3Mg JSA0KSB7CisJCWlmIChjbWQtPnBvcyA+PSBJT19CVUZGRVJfTEVOR1RIKSB7CisJCQlwcl9lcnIo IkVycm9yOiBCdWZmZXIgb3ZlcnJ1blxuIik7CisJCQlyZXR1cm4gLUVSQU5HRTsKKwkJfQorCQlj bWQtPmNtZFtjbWQtPnBvcysrXSA9IDA7CisJfQorCWhkci0+cGt0Lmxlbmd0aCA9IGNwdV90b19i ZTMyKGNtZC0+cG9zIC0gc2l6ZW9mKGhkci0+Y3ApIC0KKwkJCQkgICAgICBzaXplb2YoaGRyLT5w a3QpKTsKKwloZHItPmNwLmxlbmd0aCA9IGNwdV90b19iZTMyKGNtZC0+cG9zIC0gc2l6ZW9mKGhk ci0+Y3ApKTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgZW51bSBPUEFMX1JFU1BPTlNFX1RP S0VOIHRva2VuX3R5cGUoY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLAorCQkJCQkgICBp bnQgbikKK3sKKwljb25zdCBzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rOworCisJaWYgKG4gPj0g cmVzcC0+bnVtKSB7CisJCXByX2VycigiVG9rZW4gbnVtYmVyIGRvZXNuJ3QgZXhpc3Q6ICVkLCBy ZXNwOiAlZFxuIiwKKwkJICAgICAgIG4sIHJlc3AtPm51bSk7CisJCXJldHVybiBPUEFMX0RUQV9U T0tFTklEX0lOVkFMSUQ7CisJfQorCisJdG9rID0gJnJlc3AtPnRva3Nbbl07CisJaWYgKHRvay0+ bGVuID09IDApIHsKKwkJcHJfZXJyKCJUb2tlbiBsZW5ndGggbXVzdCBiZSBub24temVyb1xuIik7 CisJCXJldHVybiBPUEFMX0RUQV9UT0tFTklEX0lOVkFMSUQ7CisJfQorCisJcmV0dXJuIHRvay0+ dHlwZTsKK30KKworLyoKKyAqIFRoaXMgZnVuY3Rpb24gcmV0dXJucyAwIGluIGNhc2Ugb2YgaW52 YWxpZCB0b2tlbi4gT25lIHNob3VsZCBjYWxsCisgKiB0b2tlbl90eXBlKCkgZmlyc3QgdG8gZmlu ZCBvdXQgaWYgdGhlIHRva2VuIGlzIHZhbGlkIG9yIG5vdC4KKyAqLworc3RhdGljIGVudW0gT1BB TF9UT0tFTiByZXNwb25zZV9nZXRfdG9rZW4oY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNw LAorCQkJCQkgIGludCBuKQoreworCWNvbnN0IHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2s7CisK KwlpZiAobiA+PSByZXNwLT5udW0pIHsKKwkJcHJfZXJyKCJUb2tlbiBudW1iZXIgZG9lc24ndCBl eGlzdDogJWQsIHJlc3A6ICVkXG4iLAorCQkgICAgICAgbiwgcmVzcC0+bnVtKTsKKwkJcmV0dXJu IDA7CisJfQorCisJdG9rID0gJnJlc3AtPnRva3Nbbl07CisJaWYgKHRvay0+bGVuID09IDApIHsK KwkJcHJfZXJyKCJUb2tlbiBsZW5ndGggbXVzdCBiZSBub24temVyb1xuIik7CisJCXJldHVybiAw OworCX0KKworCXJldHVybiB0b2stPnBvc1swXTsKK30KKworc3RhdGljIHNpemVfdCByZXNwb25z ZV9wYXJzZV90aW55KHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2ssCisJCQkJICBjb25zdCB1OCAq cG9zKQoreworCXRvay0+cG9zID0gcG9zOworCXRvay0+bGVuID0gMTsKKwl0b2stPndpZHRoID0g T1BBTF9XSURUSF9USU5ZOworCisJaWYgKHBvc1swXSAmIFRJTllfQVRPTV9TSUdORUQpIHsKKwkJ dG9rLT50eXBlID0gT1BBTF9EVEFfVE9LRU5JRF9TSU5UOworCX0gZWxzZSB7CisJCXRvay0+dHlw ZSA9IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKKwkJdG9rLT5zdG9yZWQudSA9IHBvc1swXSAmIDB4 M2Y7CisJfQorCisJcmV0dXJuIHRvay0+bGVuOworfQorCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNl X3BhcnNlX3Nob3J0KHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2ssCisJCQkJICAgY29uc3QgdTgg KnBvcykKK3sKKwl0b2stPnBvcyA9IHBvczsKKwl0b2stPmxlbiA9IChwb3NbMF0gJiBTSE9SVF9B VE9NX0xFTl9NQVNLKSArIDE7CisJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhfU0hPUlQ7CisKKwlp ZiAocG9zWzBdICYgU0hPUlRfQVRPTV9CWVRFU1RSSU5HKSB7CisJCXRvay0+dHlwZSA9IE9QQUxf RFRBX1RPS0VOSURfQllURVNUUklORzsKKwl9IGVsc2UgaWYgKHBvc1swXSAmIFNIT1JUX0FUT01f U0lHTkVEKSB7CisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfU0lOVDsKKwl9IGVsc2Ug eworCQl1NjQgdV9pbnRlZ2VyID0gMDsKKwkJaW50IGksIGIgPSAwOworCisJCXRvay0+dHlwZSA9 IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKKwkJaWYgKHRvay0+bGVuID4gOSkKKwkJCXByX3dhcm4o InVpbnQ2NCB3aXRoIG1vcmUgdGhhbiA4IGJ5dGVzXG4iKTsKKwkJZm9yIChpID0gdG9rLT5sZW4g LSAxOyBpID4gMDsgaS0tKSB7CisJCQl1X2ludGVnZXIgfD0gKCh1NjQpcG9zW2ldIDw8ICg4ICog YikpOworCQkJYisrOworCQl9CisJCXRvay0+c3RvcmVkLnUgPSB1X2ludGVnZXI7CisJfQorCisJ cmV0dXJuIHRvay0+bGVuOworfQorCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX3BhcnNlX21lZGl1 bShzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rLAorCQkJCSAgICBjb25zdCB1OCAqcG9zKQorewor CXRvay0+cG9zID0gcG9zOworCXRvay0+bGVuID0gKCgocG9zWzBdICYgTUVESVVNX0FUT01fTEVO X01BU0spIDw8IDgpIHwgcG9zWzFdKSArIDI7CisJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhfTUVE SVVNOworCisJaWYgKHBvc1swXSAmIE1FRElVTV9BVE9NX0JZVEVTVFJJTkcpCisJCXRvay0+dHlw ZSA9IE9QQUxfRFRBX1RPS0VOSURfQllURVNUUklORzsKKwllbHNlIGlmIChwb3NbMF0gJiBNRURJ VU1fQVRPTV9TSUdORUQpCisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfU0lOVDsKKwll bHNlCisJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKKworCXJldHVybiB0b2st PmxlbjsKK30KKworI2RlZmluZSBMT05HX0FUT01fSUQgKEJJVCg3KSB8IEJJVCg2KSB8IEJJVCg1 KSkKKyNkZWZpbmUgTE9OR19BVE9NX0JZVEVTVFJJTkcgQklUKDEpCisjZGVmaW5lIExPTkdfQVRP TV9TSUdORUQgQklUKDApCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX3BhcnNlX2xvbmcoc3RydWN0 IG9wYWxfcmVzcF90b2sgKnRvaywKKwkJCQkgIGNvbnN0IHU4ICpwb3MpCit7CisJdG9rLT5wb3Mg PSBwb3M7CisJdG9rLT5sZW4gPSAoKHBvc1sxXSA8PCAxNikgfCAocG9zWzJdIDw8IDgpIHwgcG9z WzNdKSArIDQ7CisJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhfTE9ORzsKKworCWlmIChwb3NbMF0g JiBMT05HX0FUT01fQllURVNUUklORykKKwkJdG9rLT50eXBlID0gT1BBTF9EVEFfVE9LRU5JRF9C WVRFU1RSSU5HOworCWVsc2UgaWYgKHBvc1swXSAmIExPTkdfQVRPTV9TSUdORUQpCisJCXRvay0+ dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfU0lOVDsKKwllbHNlCisJCXRvay0+dHlwZSA9IE9QQUxf RFRBX1RPS0VOSURfVUlOVDsKKworCXJldHVybiB0b2stPmxlbjsKK30KKworc3RhdGljIHNpemVf dCByZXNwb25zZV9wYXJzZV90b2tlbihzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rLAorCQkJCSAg IGNvbnN0IHU4ICpwb3MpCit7CisJdG9rLT5wb3MgPSBwb3M7CisJdG9rLT5sZW4gPSAxOworCXRv ay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfVE9LRU47CisJdG9rLT53aWR0aCA9IE9QQUxfV0lE VEhfVE9LRU47CisKKwlyZXR1cm4gdG9rLT5sZW47Cit9CisKK3N0YXRpYyBpbnQgcmVzcG9uc2Vf cGFyc2UoY29uc3QgdTggKmJ1Ziwgc2l6ZV90IGxlbmd0aCwKKwkJCSAgc3RydWN0IHBhcnNlZF9y ZXNwICpyZXNwKQoreworCWNvbnN0IHN0cnVjdCBvcGFsX2hlYWRlciAqaGRyOworCXN0cnVjdCBv cGFsX3Jlc3BfdG9rICppdGVyOworCWludCByZXQsIG51bV9lbnRyaWVzID0gMDsKKwl1MzIgY3Bv cyA9IDAsIHRvdGFsOworCXNpemVfdCB0b2tlbl9sZW5ndGg7CisJY29uc3QgdTggKnBvczsKKwor CWlmICghYnVmKQorCQlyZXR1cm4gLUVGQVVMVDsKKworCWlmICghcmVzcCkKKwkJcmV0dXJuIC1F RkFVTFQ7CisKKwloZHIgPSAoc3RydWN0IG9wYWxfaGVhZGVyICopYnVmOworCXBvcyA9IGJ1ZjsK Kwlwb3MgKz0gc2l6ZW9mKCpoZHIpOworCisJcHJfZGVidWcoIlJlc3BvbnNlIHNpemU6IGNwOiAl ZCwgcGt0OiAlZCwgc3VicGt0OiAlZFxuIiwKKwkJIGJlMzJfdG9fY3B1KGhkci0+Y3AubGVuZ3Ro KSwKKwkJIGJlMzJfdG9fY3B1KGhkci0+cGt0Lmxlbmd0aCksCisJCSBiZTMyX3RvX2NwdShoZHIt PnN1YnBrdC5sZW5ndGgpKTsKKworCWlmICgoaGRyLT5jcC5sZW5ndGggPT0gMCkKKwkgICAgfHwg KGhkci0+cGt0Lmxlbmd0aCA9PSAwKQorCSAgICB8fCAoaGRyLT5zdWJwa3QubGVuZ3RoID09IDAp KSB7CisJCXByX2VycigiQmFkIGhlYWRlciBsZW5ndGguIGNwOiAlZCwgcGt0OiAlZCwgc3VicGt0 OiAlZFxuIiwKKwkJICAgICAgIGJlMzJfdG9fY3B1KGhkci0+Y3AubGVuZ3RoKSwKKwkJICAgICAg IGJlMzJfdG9fY3B1KGhkci0+cGt0Lmxlbmd0aCksCisJCSAgICAgICBiZTMyX3RvX2NwdShoZHIt PnN1YnBrdC5sZW5ndGgpKTsKKwkJcHJpbnRfYnVmZmVyKHBvcywgc2l6ZW9mKCpoZHIpKTsKKwkJ cmV0ID0gLUVJTlZBTDsKKwkJZ290byBlcnI7CisJfQorCisJaWYgKHBvcyA+IGJ1ZiArIGxlbmd0 aCkgeworCQlyZXQgPSAtRUZBVUxUOworCQlnb3RvIGVycjsKKwl9CisKKwlpdGVyID0gcmVzcC0+ dG9rczsKKwl0b3RhbCA9IGJlMzJfdG9fY3B1KGhkci0+c3VicGt0Lmxlbmd0aCk7CisJcHJpbnRf YnVmZmVyKHBvcywgdG90YWwpOworCXdoaWxlIChjcG9zIDwgdG90YWwpIHsKKwkJaWYgKCEocG9z WzBdICYgMHg4MCkpIC8qIHRpbnkgYXRvbSAqLworCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2Vf cGFyc2VfdGlueShpdGVyLCBwb3MpOworCQllbHNlIGlmICghKHBvc1swXSAmIDB4NDApKSAvKiBz aG9ydCBhdG9tICovCisJCQl0b2tlbl9sZW5ndGggPSByZXNwb25zZV9wYXJzZV9zaG9ydChpdGVy LCBwb3MpOworCQllbHNlIGlmICghKHBvc1swXSAmIDB4MjApKSAvKiBtZWRpdW0gYXRvbSAqLwor CQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfbWVkaXVtKGl0ZXIsIHBvcyk7CisJCWVs c2UgaWYgKCEocG9zWzBdICYgMHgxMCkpIC8qIGxvbmcgYXRvbSAqLworCQkJdG9rZW5fbGVuZ3Ro ID0gcmVzcG9uc2VfcGFyc2VfbG9uZyhpdGVyLCBwb3MpOworCQllbHNlIC8qIFRPS0VOICovCisJ CQl0b2tlbl9sZW5ndGggPSByZXNwb25zZV9wYXJzZV90b2tlbihpdGVyLCBwb3MpOworCisJCXBv cyArPSB0b2tlbl9sZW5ndGg7CisJCWNwb3MgKz0gdG9rZW5fbGVuZ3RoOworCQlpdGVyKys7CisJ CW51bV9lbnRyaWVzKys7CisJfQorCisJaWYgKG51bV9lbnRyaWVzID09IDApIHsKKwkJcHJfZXJy KCJDb3VsZG4ndCBwYXJzZSByZXNwb25zZS5cbiIpOworCQlyZXQgPSAtRUlOVkFMOworCQlnb3Rv IGVycjsKKwl9CisJcmVzcC0+bnVtID0gbnVtX2VudHJpZXM7CisKKwlyZXR1cm4gMDsKK2VycjoK KwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX2dldF9zdHJpbmcoY29u c3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLCBpbnQgbiwKKwkJCQkgIGNvbnN0IGNoYXIgKipz dG9yZSkKK3sKKwkqc3RvcmUgPSBOVUxMOworCWlmICghcmVzcCkgeworCQlwcl9lcnIoIlJlc3Bv bnNlIGlzIE5VTExcbiIpOworCQlyZXR1cm4gMDsKKwl9CisKKwlpZiAobiA+IHJlc3AtPm51bSkg eworCQlwcl9lcnIoIlJlc3BvbnNlIGhhcyAlZCB0b2tlbnMuIENhbid0IGFjY2VzcyAlZFxuIiwK KwkJICAgICAgIHJlc3AtPm51bSwgbik7CisJCXJldHVybiAwOworCX0KKworCWlmIChyZXNwLT50 b2tzW25dLnR5cGUgIT0gT1BBTF9EVEFfVE9LRU5JRF9CWVRFU1RSSU5HKSB7CisJCXByX2Vycigi VG9rZW4gaXMgbm90IGEgYnl0ZSBzdHJpbmchXG4iKTsKKwkJcmV0dXJuIDA7CisJfQorCisJKnN0 b3JlID0gcmVzcC0+dG9rc1tuXS5wb3MgKyAxOworCXJldHVybiByZXNwLT50b2tzW25dLmxlbiAt IDE7Cit9CisKK3N0YXRpYyB1NjQgcmVzcG9uc2VfZ2V0X3U2NChjb25zdCBzdHJ1Y3QgcGFyc2Vk X3Jlc3AgKnJlc3AsIGludCBuKQoreworCWlmICghcmVzcCkgeworCQlwcl9lcnIoIlJlc3BvbnNl IGlzIE5VTExcbiIpOworCQlyZXR1cm4gMDsKKwl9CisKKwlpZiAobiA+IHJlc3AtPm51bSkgewor CQlwcl9lcnIoIlJlc3BvbnNlIGhhcyAlZCB0b2tlbnMuIENhbid0IGFjY2VzcyAlZFxuIiwKKwkJ ICAgICAgIHJlc3AtPm51bSwgbik7CisJCXJldHVybiAwOworCX0KKworCWlmIChyZXNwLT50b2tz W25dLnR5cGUgIT0gT1BBTF9EVEFfVE9LRU5JRF9VSU5UKSB7CisJCXByX2VycigiVG9rZW4gaXMg bm90IHVuc2lnbmVkIGl0OiAlZFxuIiwKKwkJICAgICAgIHJlc3AtPnRva3Nbbl0udHlwZSk7CisJ CXJldHVybiAwOworCX0KKworCWlmICghKChyZXNwLT50b2tzW25dLndpZHRoID09IE9QQUxfV0lE VEhfVElOWSkgfHwKKwkgICAgICAocmVzcC0+dG9rc1tuXS53aWR0aCA9PSBPUEFMX1dJRFRIX1NI T1JUKSkpIHsKKwkJcHJfZXJyKCJBdG9tIGlzIG5vdCBzaG9ydCBvciB0aW55OiAlZFxuIiwKKwkJ ICAgICAgIHJlc3AtPnRva3Nbbl0ud2lkdGgpOworCQlyZXR1cm4gMDsKKwl9CisKKwlyZXR1cm4g cmVzcC0+dG9rc1tuXS5zdG9yZWQudTsKK30KKworc3RhdGljIHU4IHJlc3BvbnNlX3N0YXR1cyhj b25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJlc3ApCit7CisJaWYgKCh0b2tlbl90eXBlKHJlc3As IDApID09IE9QQUxfRFRBX1RPS0VOSURfVE9LRU4pCisJICAgICYmIChyZXNwb25zZV9nZXRfdG9r ZW4ocmVzcCwgMCkgPT0gT1BBTF9FTkRPRlNFU1NJT04pKSB7CisJCXJldHVybiAwOworCX0KKwor CWlmIChyZXNwLT5udW0gPCA1KQorCQlyZXR1cm4gRFRBRVJST1JfTk9fTUVUSE9EX1NUQVRVUzsK KworCWlmICgodG9rZW5fdHlwZShyZXNwLCByZXNwLT5udW0gLSAxKSAhPSBPUEFMX0RUQV9UT0tF TklEX1RPS0VOKSB8fAorCSAgICAodG9rZW5fdHlwZShyZXNwLCByZXNwLT5udW0gLSA1KSAhPSBP UEFMX0RUQV9UT0tFTklEX1RPS0VOKSB8fAorCSAgICAocmVzcG9uc2VfZ2V0X3Rva2VuKHJlc3As IHJlc3AtPm51bSAtIDEpICE9IE9QQUxfRU5ETElTVCkgfHwKKwkgICAgKHJlc3BvbnNlX2dldF90 b2tlbihyZXNwLCByZXNwLT5udW0gLSA1KSAhPSBPUEFMX1NUQVJUTElTVCkpCisJCXJldHVybiBE VEFFUlJPUl9OT19NRVRIT0RfU1RBVFVTOworCisJcmV0dXJuIHJlc3BvbnNlX2dldF91NjQocmVz cCwgcmVzcC0+bnVtIC0gNCk7Cit9CisKKy8qIFBhcnNlcyBhbmQgY2hlY2tzIGZvciBlcnJvcnMg Ki8KK3N0YXRpYyBpbnQgcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhzdHJ1Y3Qgb3BhbF9kZXYgKmRl dikKK3sKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgZXJyb3I7CisKKwljbWQgPSAmZGV2 LT5jbWQ7CisJcHJpbnRfYnVmZmVyKGNtZC0+Y21kLCBjbWQtPnBvcyk7CisKKwllcnJvciA9IHJl c3BvbnNlX3BhcnNlKGNtZC0+cmVzcCwgSU9fQlVGRkVSX0xFTkdUSCwgJmRldi0+cGFyc2VkKTsK KwlpZiAoZXJyb3IpIHsKKwkJcHJfZXJyKCIlczogQ291bGRuJ3QgcGFyc2UgcmVzcG9uc2UuXG4i LCBkZXYtPmRpc2tfbmFtZSk7CisJCWdvdG8gZXJyX3JldHVybjsKKwl9CisKKwllcnJvciA9IHJl c3BvbnNlX3N0YXR1cygmZGV2LT5wYXJzZWQpOworCWlmIChlcnJvcikKKwkJcHJfZXJyKCIlczog UmVzcG9uc2UgU3RhdHVzOiAlZFxuIiwgZGV2LT5kaXNrX25hbWUsCisJCSAgICAgICBlcnJvcik7 CisKKyBlcnJfcmV0dXJuOgorCXJldHVybiBlcnJvcjsKK30KKworc3RhdGljIHZvaWQgY2xlYXJf b3BhbF9jbWQoc3RydWN0IG9wYWxfY21kICpjbWQpCit7CisJY21kLT5wb3MgPSBzaXplb2Yoc3Ry dWN0IG9wYWxfaGVhZGVyKTsKKwltZW1zZXQoY21kLT5jbWQsIDAsIElPX0JVRkZFUl9MRU5HVEgp OworCWNtZC0+Y2IgPSBOVUxMOworCWNtZC0+Y2JfZGF0YSA9IE5VTEw7Cit9CisKK3N0YXRpYyB2 b2lkIHN0YXJ0X29wYWxfc2Vzc2lvbl9jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKK3sKKwlz dHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisJdTMyIEhTTiwgVFNOOworCisJaWYgKGVycm9y KQorCQlnb3RvIGVycl9yZXR1cm47CisKKwllcnJvciA9IHBhcnNlX2FuZF9jaGVja19zdGF0dXMo ZGV2KTsKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJyX3JldHVybjsKKworCUhTTiA9IHJlc3BvbnNl X2dldF91NjQoJmRldi0+cGFyc2VkLCA0KTsKKwlUU04gPSByZXNwb25zZV9nZXRfdTY0KCZkZXYt PnBhcnNlZCwgNSk7CisKKwlpZiAoSFNOID09IDAgJiYgVFNOID09IDApIHsKKwkJcHJfZXJyKCIl czogQ291bGRuJ3QgYXV0aGVudGljYXRlIHNlc3Npb25cbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJ ZXJyb3IgPSAtRVBFUk07CisJCWdvdG8gZXJyX3JldHVybjsKKwl9CisKKwlkZXYtPkhTTiA9IEhT TjsKKwlkZXYtPlRTTiA9IFRTTjsKKworZXJyX3JldHVybjoKKwlpZiAoZGV2LT5vcGVyX2NiKQor CQlkZXYtPm9wZXJfY2IoZXJyb3IsIGRldik7Cit9CisKK3N0YXRpYyBpbnQgZ2V0X29wYWxfa2V5 KHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXN0cnVjdCBrZXkgKnVrZXkgPSBOVUxMOworCWNv bnN0IHU4ICp0bXBrZXkgPSBOVUxMOworCXNpemVfdCB0bXBsZW47CisJaW50IHJldCA9IDA7CisK KwlpZiAoZGV2LT5rZXlfdHlwZSA9PSBPUEFMX0tFWV9QTEFJTikgeworCQl0bXBrZXkgPSBkZXYt PmtleV9uYW1lOworCQl0bXBsZW4gPSBkZXYtPmtleV9uYW1lX2xlbjsKKwl9IGVsc2UgaWYgKGRl di0+a2V5X3R5cGUgPT0gT1BBTF9LRVlfS0VZUklORykgeworCQl1a2V5ID0gcmVxdWVzdF91c2Vy X2tleShkZXYtPmtleV9uYW1lLCAmdG1wa2V5LCAmdG1wbGVuKTsKKwkJaWYgKElTX0VSUih1a2V5 KSkgeworCQkJcHJfZXJyKCIlczogQ2FuJ3QgcmV0cmlldmUga2V5OiAlbGRcbiIsIGRldi0+ZGlz a19uYW1lLAorCQkJICAgICAgIFBUUl9FUlIodWtleSkpOworCQkJcmV0dXJuIFBUUl9FUlIodWtl eSk7CisJCX0KKwl9IGVsc2UgeworCQlwcl9lcnIoIlJlcXVlc3RlZCBpbnZhbGlkIGtleSB0eXBl OiAlZFxuIiwgZGV2LT5rZXlfdHlwZSk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWlmICh0 bXBsZW4gPiBPUEFMX0tFWV9NQVgpIHsKKwkJcHJfZXJyKCJSZXF1ZXN0ZWQga2V5IHdpdGggaW52 YWxpZCBzaXplOiAlemRcbiIsIHRtcGxlbik7CisJCXJldCA9IC1FSU5WQUw7CisJCWdvdG8gZXJy X2V4aXQ7CisJfQorCisJZGV2LT5rZXlfbGVuID0gdG1wbGVuOworCWlmICghbWVtY3B5KGRldi0+ a2V5LCB0bXBrZXksIHRtcGxlbikpIHsKKwkJcHJfZXJyKCJFcnJvciB3aGVuIGNvcHlpbmcga2V5 Iik7CisJCXJldCA9IC1FRkFVTFQ7CisJCWdvdG8gZXJyX2V4aXQ7CisJfQorCitlcnJfZXhpdDoK KwlrZXlfcHV0KHVrZXkpOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyB2b2lkIGNsZWFuX29w YWxfa2V5KHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCW1lbXNldChkZXYtPmtleSwgMCwgT1BB TF9LRVlfTUFYKTsKKwlkZXYtPmtleV9sZW4gPSAwOworfQorCitzdGF0aWMgaW5saW5lIHZvaWQg Y2xlYW5fZnVuY3Rpb25fZGF0YShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwkJZGV2LT5mdW5j X2RhdGEgPSBOVUxMOworCQlkZXYtPm51bV9mdW5jX2RhdGEgPSAwOworfQorCisvKiBUaGlzIGlz IGEgZ2VuZXJpYyBjb250aW51ZSBmbi4KKyAqIFdlIHVzZSB0aGlzIHdoZW4gd2UgZG9uJ3QgY2Fy ZSBhYm91dCB0aGUgcmVzcG9uc2UgZGF0YQorICogYW5kIHNpbXBseSB3YW50IHRvIGNoZWNrIHRo ZSBzdGF0dXMgYW5kIGNvbnRpbnVlLgorICovCitzdGF0aWMgdm9pZCBnZW5lcmljX2NvbnQoaW50 IGVycm9yLCB2b2lkICpkYXRhKQoreworCXN0cnVjdCBvcGFsX2RldiAqZGV2ID0gZGF0YTsKKwor CWlmIChlcnJvcikKKwkJZ290byBlcnJfcmV0dXJuOworCisJZXJyb3IgPSBwYXJzZV9hbmRfY2hl Y2tfc3RhdHVzKGRldik7CisKKyBlcnJfcmV0dXJuOgorCWlmIChkZXYtPm9wZXJfY2IpCisJCWRl di0+b3Blcl9jYihlcnJvciwgZGV2KTsKK30KKworc3RhdGljIHZvaWQgZW5kX3Nlc3Npb25fY29u dChpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRh OworCisJZGV2LT5IU04gPSAwOworCWRldi0+VFNOID0gMDsKKwlnZW5lcmljX2NvbnQoZXJyb3Is IGRhdGEpOworfQorCitzdGF0aWMgaW50IGZpbmFsaXplX2FuZF9zZW5kKHN0cnVjdCBvcGFsX2Rl diAqZGV2LCBzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwKKwkJCSAgICAgc2VjX2NiIGNvbnQpCit7CisJ aW50IHJldDsKKworCXJldCA9IGNtZF9maW5hbGl6ZShjbWQsIGRldi0+SFNOLCBkZXYtPlRTTik7 CisJaWYgKHJldCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBmaW5hbGl6aW5nIGNvbW1hbmQgYnVm ZmVyOiAlZFxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lLCByZXQpOworCQlyZXR1cm4gcmV0 OworCX0KKworCXByaW50X2J1ZmZlcihjbWQtPmNtZCwgY21kLT5wb3MpOworCisJcmV0ID0gb3Bh bF9zZW5kX3JlY3YoZGV2LCBjb250LCBkZXYpOworCWlmIChyZXQpCisJCXByX2VycigiJXM6IEVy cm9yIHJ1bm5pbmcgY29tbWFuZDogJWRcbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSwgcmV0 KTsKKworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgd2FpdF9mb3JfY21kX2NvbXBsZXRp b24oc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbikKK3sKKwl3YWl0X2Zvcl9jb21w bGV0aW9uX2ludGVycnVwdGlibGUoJmNvbXBsZXRpb24tPmNtZF9jb21wbGV0aW9uKTsKKwlyZXR1 cm4gY29tcGxldGlvbi0+Y29tcGxldGlvbl9zdGF0dXM7Cit9CisKK3N0YXRpYyBpbnQgZ2VuX2tl eShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0aG9kOworCXU4IHVpZFtP UEFMX1VJRF9MRU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwlj bWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBk ZXYtPmNvbUlEKTsKKworCW1lbWNweSh1aWQsIGRldi0+cHJldl9kYXRhLCBtaW4oc2l6ZW9mKHVp ZCksIGRldi0+cHJldl9kX2xlbikpOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRU5LRVld OworCWtmcmVlKGRldi0+cHJldl9kYXRhKTsKKwlkZXYtPnByZXZfZGF0YSA9IE5VTEw7CisKKwly ZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDJjIiwKKwkJCQkgICAgT1BBTF9D QUxMLAorCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFM X01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxf RU5ETElTVCk7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcg Z2VuIGtleSBjb21tYW5kXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4g cmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19j b250KTsKK30KKworc3RhdGljIHZvaWQgZ2V0X2FjdGl2ZV9rZXlfY29udChpbnQgZXJyb3IsIHZv aWQgKmRhdGEpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOworCWNvbnN0IGNoYXIg KmFjdGl2ZWtleTsKKwlzaXplX3Qga2V5bGVuOworCisJaWYgKGVycm9yKQorCQlnb3RvIGVycl9y ZXR1cm47CisKKwllcnJvciA9IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoZGV2KTsKKwlpZiAoZXJy b3IpCisJCWdvdG8gZXJyX3JldHVybjsKKwlrZXlsZW4gPSByZXNwb25zZV9nZXRfc3RyaW5nKCZk ZXYtPnBhcnNlZCwgNCwgJmFjdGl2ZWtleSk7CisJaWYgKCFhY3RpdmVrZXkpIHsKKwkJcHJfZXJy KCIlczogQ291bGRuJ3QgZXh0cmFjdCB0aGUgQWN0aXZla2V5IGZyb20gdGhlIHJlc3BvbnNlXG4i LAorCQkgICAgICAgX19mdW5jX18pOworCQllcnJvciA9IDB4MEE7CisJCWdvdG8gZXJyX3JldHVy bjsKKwl9CisJZGV2LT5wcmV2X2RhdGEgPSBrbWVtZHVwKGFjdGl2ZWtleSwga2V5bGVuLCBHRlBf S0VSTkVMKTsKKworCWlmICghZGV2LT5wcmV2X2RhdGEpCisJCWVycm9yID0gLUVOT01FTTsKKwor CWRldi0+cHJldl9kX2xlbiA9IGtleWxlbjsKKworZXJyX3JldHVybjoKKwlpZiAoZGV2LT5vcGVy X2NiKQorCQlkZXYtPm9wZXJfY2IoZXJyb3IsIGRldik7Cit9CisKK3N0YXRpYyBpbnQgZ2V0X2Fj dGl2ZV9rZXkoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29uc3QgdTggKm1ldGhvZDsKKwl1 OCB1aWRbT1BBTF9VSURfTEVOR1RIXTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0 OworCisJY21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlE KGNtZCwgZGV2LT5jb21JRCk7CisKKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfR0VUXTsKKwor CXJldCA9IGJ1aWxkX2xvY2tpbmdfcmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5scik7CisJ aWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9ja2luZyByYW5nZVxu IiwgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlyZXQgPSB0ZXN0 X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDZjIDRjIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxM LAorCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01F VEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RB UlRMSVNULAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRf MDMsIC8qIHN0YXJ0Q2xvdW1uICovCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzEwLCAvKiBBY3Rp dmVLZXkgKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1F LAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wNCwgLyogZW5kQ29sdW1uICovCisJCQkJICAgIE9Q QUxfVElOWV9VSU5UXzEwLCAvKiBBY3RpdmVLZXkgKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAor CisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKwlpZiAocmV0 IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBnZXQgYWN0aXZlIGtleSBjb21t YW5kXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKwor CXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2V0X2FjdGl2ZV9rZXlfY29udCk7 Cit9CisKK3N0YXRpYyBpbnQgc2V0dXBfbG9ja2luZ19yYW5nZShzdHJ1Y3Qgb3BhbF9kZXYgKmRl dikKK3sKKwljb25zdCB1OCAqbWV0aG9kOworCXU4IHVpZFtPUEFMX1VJRF9MRU5HVEhdOworCXN0 cnVjdCBvcGFsX2NtZCAqY21kOworCXN0cnVjdCBvcGFsX3VzZXJfbHJfc2V0dXAgKnNldHVwOwor CWludCByZXQ7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlz ZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9T RVRdOworCXJldCA9IGJ1aWxkX2xvY2tpbmdfcmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5s cik7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9ja2luZyBy YW5nZVxuIiwgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisJc2V0dXAg PSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRf dG9rZW5fdmEoY21kLCAiYzJzICA0YyAyY3VjIDJjdWMgMmN1YyAyY3UgNGMiLAorCQkJCSAgICBP UEFMX0NBTEwsCisJCQkJICAgIHVpZCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2Qs IE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAg T1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVkFMVUVTLAorCQkJCSAgICBPUEFMX1NUQVJU TElTVCwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRf MDMsIC8qIFJhbmdlIFN0YXJ0ICovCisJCQkJICAgIHNldHVwLT5yYW5nZV9zdGFydCwKKwkJCQkg ICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFM X1RJTllfVUlOVF8wNCwgLyogUmFuZ2UgTGVuZ3RoICovCisJCQkJICAgIHNldHVwLT5yYW5nZV9s ZW5ndGgsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwK KwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDUsIC8qIFJlYWRMb2NrRW5hYmxlZCAqLworCQkJCSAg ICAhIXNldHVwLT5STEUsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKworCQkJCSAgICBPUEFMX1NU QVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIFdyaXRlTG9ja0VuYWJsZWQg Ki8KKwkJCQkgICAgISFzZXR1cC0+V0xFLAorCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkg ICAgT1BBTF9FTkRMSVNULAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5E TElTVCk7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgU2V0 dXAgTG9ja2luZyByYW5nZSBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsK KwkJcmV0dXJuIHJldDsKKworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNt ZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBzdGFydF9hZG1pbnNwX29wYWxfc2Vz c2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldiwKKwkJCQkgICAgICBlbnVtIE9QQUxfVUlEIGF1dGgs CisJCQkJICAgICAgY29uc3QgY2hhciAqa2V5LAorCQkJCSAgICAgIHU4IGtleV9sZW4pCit7CisJ Y29uc3QgdTggKm1ldGhvZCwgKnNtdWlkLCAqYWRtaW5fc3AsICpoc2E7CisJc3RydWN0IG9wYWxf Y21kICpjbWQ7CisJdTMyIEhTTjsKKwlpbnQgcmV0OworCisJaWYgKGtleSA9PSBOVUxMICYmIGF1 dGggIT0gT1BBTF9BTllCT0RZX1VJRCkgeworCQlwcl9lcnIoIiVzOiBBdHRlbXB0ZWQgdG8gb3Bl biBBRE1JTl9TUCBTZXNzaW9uIHdpdGhvdXQgYSBIb3N0IiBcCisJCSAgICAgICAiQ2hhbGxlbmdl LCBhbmQgbm90IGFzIHRoZSBBbnlib2R5IFVJRFxuIiwgX19mdW5jX18pOworCQlyZXR1cm4gMTsK Kwl9CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKworCXNldF9j b21JRChjbWQsIGRldi0+Y29tSUQpOworCUhTTiA9IDB4NDE7CisKKwlzbXVpZCA9IE9QQUxVSURb T1BBTF9TTVVJRF9VSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TVEFSVFNFU1NJT05d OworCWFkbWluX3NwID0gT1BBTFVJRFtPUEFMX0FETUlOU1BfVUlEXTsKKworCXJldCA9IHRlc3Rf YW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgY3VzYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJ CQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhP RF9MRU5HVEgsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBIU04sCisJCQkJICAg IGFkbWluX3NwLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxKTsK KwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBzdGFydCBhZG1p bnNwIHNlc3Npb24gY29tbWFuZC5cbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJl dHVybiByZXQ7CisJfQorCisJc3dpdGNoIChhdXRoKSB7CisJY2FzZSBPUEFMX0FOWUJPRFlfVUlE OgorCQkvKiBub3RoaW5nIGxlZnQgdG8gZG8gZm9yIGFueWJvZHksIGp1c3QgZW5kIGFuZCBmaW5h bGl6ZSAqLworCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYyIsCisJCQkJCSAg ICBPUEFMX0VORExJU1QpOworCQlicmVhazsKKwljYXNlIE9QQUxfU0lEX1VJRDoKKwkJaHNhID0g T1BBTFVJRFtPUEFMX1NJRF9VSURdOworCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21k LCAiMmMgcyAzYyBzIDJjIiwKKwkJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCQkgICAgT1BB TF9USU5ZX1VJTlRfMDAsIC8qIEhvc3RDaGFsbGVuZ2UgKi8KKwkJCQkJICAgIGtleSwga2V5X2xl biwKKwkJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJ CQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIEhvc3RTaWduQXV0aCAqLworCQkJCQkgICAgaHNh LCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJCSAgICBPUEFM X0VORExJU1QpOworCQlicmVhazsKKwlkZWZhdWx0OgorCQlwcl9lcnIoIkNhbm5vdCBzdGFydCBB ZG1pbiBTUCBzZXNzaW9uIHdpdGggYXV0aCAlZFxuIiwgYXV0aCk7CisJCXJldHVybiAxOworCX0K KworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIHN0YXJ0IGFk bWluc3Agc2Vzc2lvbiBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJ cmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0 YXJ0X29wYWxfc2Vzc2lvbl9jb250KTsKK30KKworc3RhdGljIGludCBzdGFydF9hbnlib2R5QVNQ X29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlyZXR1cm4gc3RhcnRfYWRt aW5zcF9vcGFsX3Nlc3Npb24oZGV2LCBPUEFMX0FOWUJPRFlfVUlELCBOVUxMLCAwKTsKK30KKwor c3RhdGljIGludCBzdGFydF9TSURBU1Bfb3BhbF9zZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2 KQoreworCWludCByZXQ7CisJY29uc3QgdTggKmtleSA9IGRldi0+cHJldl9kYXRhOworCisJaWYg KCFrZXkpCisJCXJldCA9IHN0YXJ0X2FkbWluc3Bfb3BhbF9zZXNzaW9uKGRldiwgT1BBTF9TSURf VUlELCBkZXYtPmtleSwKKwkJCQkJCSBkZXYtPmtleV9sZW4pOworCWVsc2UgeworCQlyZXQgPSBz dGFydF9hZG1pbnNwX29wYWxfc2Vzc2lvbihkZXYsIE9QQUxfU0lEX1VJRCwga2V5LAorCQkJCQkJ IGRldi0+cHJldl9kX2xlbik7CisJCWtmcmVlKGtleSk7CisJCWRldi0+cHJldl9kYXRhID0gTlVM TDsKKwl9CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBzdGFydF9sb2NraW5nc3Bfb3Bh bF9zZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2LAorCQkJCQllbnVtIE9QQUxfVUlEIGF1dGgs IGNvbnN0IHU4ICprZXksCisJCQkJCXU4IGtleV9sZW4pCit7CisKKwljb25zdCB1OCAqbWV0aG9k LCAqc211aWQsICpsb2NraW5nX3NwLCAqaHNhOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCXNp emVfdCBrbGVuID0ga2V5X2xlbjsKKwl1MzIgSFNOOworCWludCByZXQ7CisKKwlpZiAoa2V5ID09 IE5VTEwpIHsKKwkJcHJfZXJyKCJDYW5ub3Qgc3RhcnQgTG9ja2luZyBTUCBzZXNzaW9uIHdpdGhv dXQgYSBrZXlcbiIpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwljbWQgPSAmZGV2LT5jbWQ7 CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwor CUhTTiA9IDB4NDE7CisKKwlzbXVpZCA9IE9QQUxVSURbT1BBTF9TTVVJRF9VSURdOworCW1ldGhv ZCA9IE9QQUxNRVRIT0RbT1BBTF9TVEFSVFNFU1NJT05dOworCWxvY2tpbmdfc3AgPSBPUEFMVUlE W09QQUxfTE9DS0lOR1NQX1VJRF07CisJaHNhID0gT1BBTFVJRFthdXRoXTsKKworCXJldCA9IHRl c3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgY3VzYyAyY3NjIDJjc2MgYyIsCisJCQkJICAg IE9QQUxfQ0FMTCwKKwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0 aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJ ICAgIEhTTiwKKwkJCQkgICAgbG9ja2luZ19zcCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBP UEFMX1RJTllfVUlOVF8wMSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BB TF9USU5ZX1VJTlRfMDAsIC8qIEhvc3RDaGFsbGVuZ2UgKi8KKwkJCQkgICAga2V5LCBrbGVuLAor CQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAg IE9QQUxfVElOWV9VSU5UXzAzLCAvKiBIb3N0IFNpZ24gQXV0aG9yaXR5ICovCisJCQkJICAgIGhz YSwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BB TF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxk aW5nIHN0YXJ0IGFkbWluc3Agc2Vzc2lvbiBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlz a19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRl diwgY21kLCBzdGFydF9vcGFsX3Nlc3Npb25fY29udCk7Cit9CisKK3N0YXRpYyBpbmxpbmUgaW50 IHN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJ cmV0dXJuIHN0YXJ0X2xvY2tpbmdzcF9vcGFsX3Nlc3Npb24oZGV2LCBPUEFMX0FETUlOMV9VSUQs CisJCQkJCSAgICBkZXYtPmtleSwgZGV2LT5rZXlfbGVuKTsKK30KKworc3RhdGljIGludCBzdGFy dF9hdXRoX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAq bWV0aG9kLCAqc211aWQsICpsb2NraW5nX3NwOworCXU4IGxrX3VsX3VzZXJbT1BBTF9VSURfTEVO R1RIXTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwl1MzIgSFNOOworCWludCByZXQ7CisJc3Ry dWN0IG9wYWxfdXNlcl9pbmZvICp1aW5mbzsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9v cGFsX2NtZChjbWQpOworCisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwlIU04gPSAw eDQxOworCisJdWluZm8gPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07CisKKwlzbXVp ZCA9IE9QQUxVSURbT1BBTF9TTVVJRF9VSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9T VEFSVFNFU1NJT05dOworCWxvY2tpbmdfc3AgPSBPUEFMVUlEW09QQUxfTE9DS0lOR1NQX1VJRF07 CisKKwlpZiAodWluZm8tPlNVTSkgeworCQlyZXQgPSBidWlsZF9sb2NraW5nX3VzZXIobGtfdWxf dXNlciwgc2l6ZW9mKGxrX3VsX3VzZXIpLAorCQkJCQkgZGV2LT5scik7CisJCWlmIChyZXQgPCAw KSB7CisJCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHVzZXJcbiIsCisJCQkgICAg ICAgZGV2LT5kaXNrX25hbWUpOworCQkJcmV0dXJuIHJldDsKKwkJfQorCX0gZWxzZSBpZiAodWlu Zm8tPndobyAhPSBPUEFMX0FETUlOMSAmJiAhdWluZm8tPlNVTSkgeworCQlyZXQgPSBidWlsZF9s b2NraW5nX3VzZXIobGtfdWxfdXNlciwgc2l6ZW9mKGxrX3VsX3VzZXIpLAorCQkJCQkgdWluZm8t PndobyAtIDEpOworCQlpZiAocmV0IDwgMCkgeworCQkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQg bG9ja2luZyB1c2VyXG4iLAorCQkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJCXJldHVybiBy ZXQ7CisJCX0KKwl9IGVsc2UKKwkJbWVtY3B5KGxrX3VsX3VzZXIsIE9QQUxVSURbT1BBTF9BRE1J TjFfVUlEXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2Vu X3ZhKGNtZCwgImMycyBjdXMzY3MzYyBzIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAg ICBzbXVpZCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xF TkdUSCwKKworCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAgSFNOLAorCQkJCSAgICBs b2NraW5nX3NwLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLAor CQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDAsCisJCQkJ ICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4sCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkg ICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLAorCisJCQkJICAg IGxrX3VsX3VzZXIsIE9QQUxfVUlEX0xFTkdUSCwKKworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJ CQkJICAgIE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBF cnJvciBidWlsZGluZyBTVEFSVFNFU1NJT04gY29tbWFuZC5cbiIsCisJCSAgICAgICBkZXYtPmRp c2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5k KGRldiwgY21kLCBzdGFydF9vcGFsX3Nlc3Npb25fY29udCk7Cit9CisKK3N0YXRpYyBpbnQgcmV2 ZXJ0X3RwZXIoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJY29uc3QgdTggKm1ldGhvZCwgKnNt dWlkOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwljbWQgPSAmZGV2LT5j bWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQp OworCisJc211aWQgPSBPUEFMVUlEW09QQUxfQURNSU5TUF9VSURdOworCW1ldGhvZCA9IE9QQUxN RVRIT0RbT1BBTF9SRVZFUlRdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwg ImMycyAyYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xF TkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisJCQkJICAgIE9QQUxf U1RBUlRMSVNULAorCQkJCSAgICBPUEFMX0VORExJU1QpOworCWlmIChyZXQgPCAwKSB7CisJCXBy X2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIFJFVkVSVCBUUEVSIGNvbW1hbmQuXG4iLAorCQkgICAg ICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6 ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBpbnRl cm5hbF9hY3RpdmF0ZV91c2VyKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCWNvbnN0IHU4ICpt ZXRob2Q7CisJdTggdWlkW09QQUxfVUlEX0xFTkdUSF07CisJc3RydWN0IG9wYWxfY21kICpjbWQ7 CisJaW50IHJldDsKKwlzdHJ1Y3Qgb3BhbF9hY3RpdmF0ZV91c2VyICphY3Q7CisKKwljbWQgPSAm ZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNv bUlEKTsKKworCWFjdCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKworCW1lbWNw eSh1aWQsIE9QQUxVSURbT1BBTF9VU0VSMV9VSURdLCBPUEFMX1VJRF9MRU5HVEgpOworCXVpZFs3 XSA9IGFjdC0+d2hvLndobzsKKworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOworCisJ cmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAzYyBjIDRjIDNjIiwKKwkJCQkg ICAgT1BBTF9DQUxMLAorCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0 aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJ ICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSwgLyogVmFsdWVz ICovCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUs CisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzA1LCAvKiBFbmFibGVkICovCisJCQkJICAgIE9QQUxf VElOWV9VSU5UXzAxLCAvKiBUcnVlICovCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKworCQkJCSAg ICBPUEFMX0VORExJU1QsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9FTkRM SVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEFj dGl2YXRlIFVzZXJOIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQly ZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2Vu ZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBlcmFzZV9sb2NraW5nX3JhbmdlKHN0cnVjdCBv cGFsX2RldiAqZGV2KQoreworCWNvbnN0IHU4ICptZXRob2Q7CisJdTggdWlkW09QQUxfVUlEX0xF TkdUSF07CisJc3RydWN0IG9wYWxfY21kICpjbWQ7CisJaW50IHJldDsKKworCWNtZCA9ICZkZXYt PmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQp OworCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0VSQVNFXTsKKworCWlmIChidWlsZF9sb2Nr aW5nX3JhbmdlKHVpZCwgc2l6ZW9mKHVpZCksIGRldi0+bHIpIDwgMCkgeworCQlwcl9lcnIoIiVz OiBDYW4ndCBidWlsZCBsb2NraW5nIHJhbmdlXG4iLCBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVy biAtRUlOVkFMOworCX0KKworCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMg MmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIHVpZCwgT1BBTF9VSURfTEVOR1RILAor CQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFMX1NUQVJU TElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2Vy cigiJXM6IEVycm9yIGJ1aWxkaW5nIEVyYXNlIExvY2tpbmcgUmFuZ2UgQ21tYW5kLlxuIiwKKwkJ ICAgICAgIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIHJldDsKKwl9CisJcmV0dXJuIGZpbmFs aXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOworfQorCitzdGF0aWMgaW50IHNl dF9tYnJfZG9uZShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0aG9kLCAq dWlkOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwl1OCBtYnJfZG9uZV90 ZiA9ICoodTggKilkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07CisKKwljbWQgPSAmZGV2 LT5jbWQ7CisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlE KTsKKworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOworCXVpZCA9IE9QQUxVSURbT1BB TF9NQlJDT05UUk9MXTsKKworCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMg M2MgNmMgMmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIHVpZCwgT1BBTF9VSURfTEVO R1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFM X1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVkFMVUVT LAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJ CQkgICAgT1BBTF9USU5ZX1VJTlRfMDIsIC8qIERvbmUgKi8KKwkJCQkgICAgbWJyX2RvbmVfdGYs ICAgICAgIC8qIERvbmUgVCBvciBGICovCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAg T1BBTF9FTkRMSVNULAorCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9FTkRM SVNUKTsKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBCdWlsZGluZyBzZXQg TUJSIERvbnQvTm90IGRvbmUgY29tbWFuZFxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsK KwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQs IGdlbmVyaWNfY29udCk7Cit9CisKK3N0YXRpYyBpbnQgc2V0X21icl9lbmFibGVfZGlzYWJsZShz dHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwljb25zdCB1OCAqbWV0aG9kLCAqdWlkOworCXN0cnVj dCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisKKwl1OCBtYnJfZW5fZGlzID0gKih1OCAqKWRl di0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVh cl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCisJbWV0aG9k ID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07CisJdWlkID0gT1BBTFVJRFtPUEFMX01CUkNPTlRST0xd OworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAzYyA2YyAyYyIsCisJ CQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAg IG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAor CQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9WQUxVRVMsCisKKwkJCQkgICAg T1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJ TllfVUlOVF8wMSwgLyogRW5hYmxlICovCisJCQkJICAgIG1icl9lbl9kaXMsICAgICAgICAvKiBF bmFibGUgb3IgRGlzYWJsZSAqLworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxf RU5ETElTVCwKKworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElTVCk7 CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgc2V0IE1CUiBE b250L05vdCBkb25lIGNvbW1hbmRcbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJl dHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5l cmljX2NvbnQpOworfQorCitzdGF0aWMgaW50IHNldF9uZXdfcHcoc3RydWN0IG9wYWxfZGV2ICpk ZXYpCit7CisJY29uc3QgdTggKm1ldGhvZDsKKwl1OCBjcGluX3VpZFtPUEFMX1VJRF9MRU5HVEhd OworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWludCByZXQ7CisJc3RydWN0IG9wYWxfbmV3X3B3 ICpwdzsKKwlzaXplX3Qga2V5X2xlbjsKKwl1OCAqa2V5OworCisJY21kID0gJmRldi0+Y21kOwor CWNsZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwlw dyA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKKwlrZXkgPSBwdy0+bmV3X3Bpbi5r ZXk7CisJa2V5X2xlbiA9IHB3LT5uZXdfcGluLmtleV9sZW47CisJbWVtY3B5KGNwaW5fdWlkLCBP UEFMVUlEW09QQUxfQ19QSU5fQURNSU4xXSwgT1BBTF9VSURfTEVOR1RIKTsKKworCWlmIChwdy0+ dXNlcl9mb3JfcHcgIT0gT1BBTF9BRE1JTjEpIHsKKwkJY3Bpbl91aWRbNV0gPSAweDAzOworCQlp ZiAocHctPndoby5TVU0pCisJCQljcGluX3VpZFs3XSA9IHB3LT5uZXdfcGluLmxyICsgMTsKKwkJ ZWxzZQorCQkJY3Bpbl91aWRbN10gPSBwdy0+dXNlcl9mb3JfcHc7CisJfQorCisJbWV0aG9kID0g T1BBTE1FVEhPRFtPUEFMX1NFVF07CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21k LCAiYzJzIDNjIDNjczJjIDJjIiwKKwkJCQkgICAgT1BBTF9DQUxMLAorCQkJCSAgICBjcGluX3Vp ZCwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwK KworCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJ ICAgIE9QQUxfVElOWV9VSU5UXzAxLCAvKiBWYWx1ZXMgKi8KKworCQkJCSAgICBPUEFMX1NUQVJU TElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAz LCAvKiBQSU4gKi8KKwkJCQkgICAga2V5LCBrZXlfbGVuLAorCQkJCSAgICBPUEFMX0VORE5BTUUs CisJCQkJICAgIE9QQUxfRU5ETElTVCwKKworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAg IE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBi dWlsZGluZyBTRVQgQU1JTjEgUElOIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25h bWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYs IGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBzZXRfc2lkX2NwaW5fcGluKHN0 cnVjdCBvcGFsX2RldiAqZGV2KQoreworCWNvbnN0IHU4ICptZXRob2QsICpjcGluX3VpZDsKKwlz dHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0OworCisJY21kID0gJmRldi0+Y21kOworCWNs ZWFyX29wYWxfY21kKGNtZCk7CisJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7CisKKwljcGlu X3VpZCA9IE9QQUxVSURbT1BBTF9DX1BJTl9TSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BB TF9TRVRdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAyYyA0Y3My YyAyYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgY3Bpbl91aWQsIE9QQUxfVUlEX0xF TkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9MRU5HVEgsCisKKwkJCQkgICAgT1BB TF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCisJCQkJICAgIE9QQUxfVElO WV9VSU5UXzAxLCAvKiBWYWx1ZXMgKi8KKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAg IE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElOICovCisJ CQkJICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4sCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJ CQkgICAgT1BBTF9FTkRMSVNULAorCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BB TF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxk aW5nIFNFVCBDUElOIFBJTiBjb21tYW5kLlxuIiwKKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsK KwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQs IGdlbmVyaWNfY29udCk7Cit9CisKK3N0YXRpYyB2b2lkIHF1ZXJ5X2xvY2tpbmdfcmFuZ2VfY29u dChpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRh OworCisJaWYgKGVycm9yKQorCQlnb3RvIGVycl9yZXR1cm47CisKKwllcnJvciA9IHBhcnNlX2Fu ZF9jaGVja19zdGF0dXMoZGV2KTsKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJyX3JldHVybjsKKwor CWRldi0+c3RhcnQgPSByZXNwb25zZV9nZXRfdTY0KCZkZXYtPnBhcnNlZCwgNCk7CisJZGV2LT5s ZW5ndGggPSByZXNwb25zZV9nZXRfdTY0KCZkZXYtPnBhcnNlZCwgOCk7CisKK2Vycl9yZXR1cm46 CisJaWYgKGRldi0+b3Blcl9jYikKKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYpOworfQorCitz dGF0aWMgaW50IHF1ZXJ5X2xvY2tpbmdfcmFuZ2Uoc3RydWN0IG9wYWxfZGV2ICpkZXYpCit7CisJ dTggbHJfYnVmZmVyW09QQUxfVUlEX0xFTkdUSF07CisJc3RydWN0IG9wYWxfY21kICpjbWQ7CisJ Y29uc3QgdTggKm1ldGhvZDsKKwlpbnQgcmV0OworCisJY21kID0gJmRldi0+Y21kOworCWNsZWFy X29wYWxfY21kKGNtZCk7CisKKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfR0VUXTsKKworCWlm IChidWlsZF9sb2NraW5nX3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1ZmZlciksIGRldi0+ bHIpIDwgMCkgeworCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHJhbmdlXG4iLCBk ZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCXNldF9jb21JRChjbWQs IGRldi0+Y29tSUQpOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAx MmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVO R1RILAorCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKKworCQkJCSAgICBPUEFM X1NUQVJUTElTVCwKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlRO QU1FLAorCQkJCSAgICBPUEFMX1NUQVJUQ09MVU1OLAorCQkJCSAgICBPUEFMX1JBTkdFU1RBUlQs CisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAg IE9QQUxfRU5EQ09MVU1OLAorCQkJCSAgICBPUEFMX1JBTkdFTEVOR1RILAorCQkJCSAgICBPUEFM X0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsK KworCWlmIChyZXQgPCAwKSB7CisJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEdFVCBMb2Nr aW5nIFJhbmdlIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1 cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgcXVlcnlf bG9ja2luZ19yYW5nZV9jb250KTsKK30KKworc3RhdGljIGludCBhZGRfdXNlcl90b19scihzdHJ1 Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwl1OCBscl9idWZmZXJbT1BBTF9VSURfTEVOR1RIXTsKKwl1 OCB1c2VyX3VpZFtPUEFMX1VJRF9MRU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWNv bnN0IHU4ICptZXRob2Q7CisJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrdWw7CisJaW50IHJl dDsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9jb21J RChjbWQsIGRldi0+Y29tSUQpOworCisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07CisK Kwlsa3VsID0gZGV2LT5mdW5jX2RhdGFbZGV2LT5zdGF0ZSAtIDFdOworCisJbWVtY3B5KGxyX2J1 ZmZlciwgT1BBTFVJRFtPUEFMX0xPQ0tJTkdSQU5HRV9BQ0VfUkRMT0NLRURdLAorCSAgICAgICBP UEFMX1VJRF9MRU5HVEgpOworCisJaWYgKGxrdWwtPmxfc3RhdGUgPT0gT1BBTF9SVykKKwkJbWVt Y3B5KGxyX2J1ZmZlciwgT1BBTFVJRFtPUEFMX0xPQ0tJTkdSQU5HRV9BQ0VfV1JMT0NLRURdLAor CQkgICAgICAgT1BBTF9VSURfTEVOR1RIKTsKKworCWxyX2J1ZmZlcls3XSA9IGRldi0+bHI7CisK KwltZW1jcHkodXNlcl91aWQsIE9QQUxVSURbT1BBTF9VU0VSMV9VSURdLCBPUEFMX1VJRF9MRU5H VEgpOworCXVzZXJfdWlkWzddID0gbGt1bC0+YXV0aG9yaXR5LndobzsKKworCXJldCA9IHRlc3Rf YW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgM2MgM2MgMmMgMnNjIGMyc2MgY3MyYyA1YyIsCisJ CQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgbHJfYnVmZmVyLCBPUEFMX1VJRF9MRU5HVEgsCisJ CQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRM SVNULAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDEs IC8qIFZhbHVlcyAqLworCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCQkJCSAgICBPUEFMX1NU QVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIEJvb2xlYW5FeHByICovCisK KwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCisJCQkJ ICAgIE9QQUxVSURbT1BBTF9IQUxGX1VJRF9BVVRIT1JJVFlfT0JKX1JFRl0sCisJCQkJICAgIE9Q QUxfVUlEX0xFTkdUSF9IQUxGLAorCQkJCSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAor CQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAg IE9QQUxVSURbT1BBTF9IQUxGX1VJRF9BVVRIT1JJVFlfT0JKX1JFRl0sCisJCQkJICAgIE9QQUxf VUlEX0xFTkdUSF9IQUxGLAorCQkJCSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAorCQkJ CSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJICAgIE9Q QUxVSURbT1BBTF9IQUxGX1VJRF9CT09MRUFOX0FDRV0sCisJCQkJICAgIE9QQUxfVUlEX0xFTkdU SF9IQUxGLAorCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSwKKwkJCQkgICAgT1BBTF9FTkROQU1F LAorCisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCQkJCSAg ICBPUEFMX0VORExJU1QsCisJCQkJICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgT1BBTF9FTkRM SVNUKTsKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBhZGQg dXNlciB0byBsb2NraW5nIHJhbmdlIGNvbW1hbmQuXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25h bWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYs IGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworc3RhdGljIGludCBsb2NrX3VubG9ja19sb2NraW5n X3JhbmdlKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXU4IGxyX2J1ZmZlcltPUEFMX1VJRF9M RU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWNvbnN0IHU4ICptZXRob2Q7CisJc3Ry dWN0IG9wYWxfbG9ja191bmxvY2sgKmxrdWw7CisJaW50IHJldDsKKwl1OCByZWFkX2xvY2tlZCA9 IDEsIHdyaXRlX2xvY2tlZCA9IDE7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xlYXJfb3BhbF9j bWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKworCW1ldGhvZCA9IE9QQUxN RVRIT0RbT1BBTF9TRVRdOworCWxrdWwgPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0YXRlIC0gMV07 CisJaWYgKGJ1aWxkX2xvY2tpbmdfcmFuZ2UobHJfYnVmZmVyLCBzaXplb2YobHJfYnVmZmVyKSwg ZGV2LT5scikgPCAwKSB7CisJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2Vc biIsIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJc3dpdGNoIChs a3VsLT5sX3N0YXRlKSB7CisJY2FzZSBPUEFMX1JPOgorCQlyZWFkX2xvY2tlZCA9IDA7CisJCXdy aXRlX2xvY2tlZCA9IDE7CisJCWJyZWFrOworCWNhc2UgT1BBTF9SVzoKKwkJcmVhZF9sb2NrZWQg PSAwOworCQl3cml0ZV9sb2NrZWQgPSAwOworCQlicmVhazsKKwljYXNlIE9QQUxfTEs6CisJCS8q IHZhcnMgYXJlIGluaXRhbGl6ZWQgdG8gbG9ja2VkICovCisJCWJyZWFrOworCWRlZmF1bHQ6CisJ CXByX2VycigiVHJpZWQgdG8gc2V0IGFuIGludmFsaWQgbG9ja2luZyBzdGF0ZS4uLiByZXR1cm5p bmcgdG8gdWxhbmRcbiIpOworCQlyZXR1cm4gMTsKKwl9CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRf dG9rZW5fdmEoY21kLCAiYzJzYyAzYyA0YyA0YyAzYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJ CQkgICAgbHJfYnVmZmVyLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9N RVRIT0RfTEVOR1RILAorCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICBPUEFMX1NU QVJUTkFNRSwKKwkJCQkgICAgT1BBTF9WQUxVRVMsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAor CisJCQkJICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1JFQURMT0NLRUQsCisJCQkJ ICAgIHJlYWRfbG9ja2VkLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9T VEFSVE5BTUUsCisJCQkJICAgIE9QQUxfV1JJVEVMT0NLRUQsCisJCQkJICAgIHdyaXRlX2xvY2tl ZCwKKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfRU5ETElTVCwKKwkJCQkg ICAgT1BBTF9FTkROQU1FLAorCQkJCSAgICBPUEFMX0VORExJU1QpOworCisJaWYgKHJldCA8IDAp IHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgU0VUIGNvbW1hbmQuXG4iLCBkZXYtPmRp c2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChk ZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworCitzdGF0aWMgaW50IGxvY2tfdW5sb2NrX2xv Y2tpbmdfcmFuZ2VfU1VNKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXU4IGxyX2J1ZmZlcltP UEFMX1VJRF9MRU5HVEhdOworCXN0cnVjdCBvcGFsX2NtZCAqY21kOworCWNvbnN0IHU4ICptZXRo b2Q7CisJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrdWw7CisJaW50IHJldDsKKwl1OCByZWFk X2xvY2tlZCA9IDEsIHdyaXRlX2xvY2tlZCA9IDE7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisJY2xl YXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKKworCW1ldGhv ZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOworCWxrdWwgPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0 YXRlIC0gMV07CisJaWYgKGJ1aWxkX2xvY2tpbmdfcmFuZ2UobHJfYnVmZmVyLCBzaXplb2YobHJf YnVmZmVyKSwgZGV2LT5scikgPCAwKSB7CisJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tp bmcgcmFuZ2VcbiIsIGRldi0+ZGlza19uYW1lKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJ c3dpdGNoIChsa3VsLT5sX3N0YXRlKSB7CisJY2FzZSBPUEFMX1JPOgorCQlyZWFkX2xvY2tlZCA9 IDA7CisJCXdyaXRlX2xvY2tlZCA9IDE7CisJCWJyZWFrOworCWNhc2UgT1BBTF9SVzoKKwkJcmVh ZF9sb2NrZWQgPSAwOworCQl3cml0ZV9sb2NrZWQgPSAwOworCQlicmVhazsKKwljYXNlIE9QQUxf TEs6CisJCS8qIHZhcnMgYXJlIGluaXRhbGl6ZWQgdG8gbG9ja2VkICovCisJCWJyZWFrOworCWRl ZmF1bHQ6CisJCXByX2VycigiVHJpZWQgdG8gc2V0IGFuIGludmFsaWQgbG9ja2luZyBzdGF0ZS5c biIpOworCQlyZXR1cm4gMTsKKwl9CisKKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21k LCAiYzJzYyAzYyA0YyA0YyA0YyA0YyAzYyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAg bHJfYnVmZmVyLCBPUEFMX1VJRF9MRU5HVEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0Rf TEVOR1RILAorCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFN RSwKKwkJCQkgICAgT1BBTF9WQUxVRVMsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNULAorCisJCQkJ ICAgIE9QQUxfU1RBUlROQU1FLAorCQkJCSAgICBPUEFMX1JFQURMT0NLRU5BQkxFRCwKKwkJCQkg ICAgT1BBTF9UUlVFLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFS VE5BTUUsCisJCQkJICAgIE9QQUxfV1JJVEVMT0NLRU5BQkxFRCwKKwkJCQkgICAgT1BBTF9UUlVF LAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCisJCQkJ ICAgIE9QQUxfUkVBRExPQ0tFRCwKKwkJCQkgICAgcmVhZF9sb2NrZWQsCisJCQkJICAgIE9QQUxf RU5ETkFNRSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9XUklURUxP Q0tFRCwKKwkJCQkgICAgd3JpdGVfbG9ja2VkLAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisKKwkJ CQkgICAgT1BBTF9FTkRMSVNULAorCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxf RU5ETElTVCk7CisJaWYgKHJldCA8IDApIHsKKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcg U0VUIGNvbW1hbmQuXG4iLCBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCXJl dHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKK30KKworaW50 IGFjdGl2YXRlX2xzcChzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwl1OCB1c2VyX2xyW09QQUxf VUlEX0xFTkdUSF07CisJY29uc3QgdTggKm1ldGhvZCwgKnVpZDsKKwlzdHJ1Y3Qgb3BhbF9jbWQg KmNtZDsKKwlpbnQgcmV0OworCXNpemVfdCB1aW50XzMgPSAweDgzOworCisJY21kID0gJmRldi0+ Y21kOworCisJY2xlYXJfb3BhbF9jbWQoY21kKTsKKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlE KTsKKworCXVpZCA9IE9QQUxVSURbT1BBTF9MT0NLSU5HU1BfVUlEXTsKKwltZXRob2QgPSBPUEFM TUVUSE9EW09QQUxfQUNUSVZBVEVdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNt ZCwgImMycyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5H VEgsCisJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RIKTsKKwlpZiAocmV0IDwgMCkg eworCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBBY3RpdmF0ZSBMb2NraW5nU1AgY29tbWFu ZC5cbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCS8q IEFjdGl2YXRpbmcgYXMgU1VNICovCisJaWYgKGRldi0+bHIgPiAwKSB7CisJCXJldCA9IGJ1aWxk X2xvY2tpbmdfcmFuZ2UodXNlcl9sciwgc2l6ZW9mKHVzZXJfbHIpLCBkZXYtPmxyKTsKKwkJaWYg KHJldCA8IDApIHsKKwkJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgdXNlclxuIiwK KwkJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCQlyZXR1cm4gcmV0OworCQl9CisJCXRlc3Rf YW5kX2FkZF90b2tlbl92YShjbWQsICIyYyA0YyBjc2MgMmMiLAorCQkJCSAgICAgIE9QQUxfU1RB UlRMSVNULAorCQkJCSAgICAgIE9QQUxfU1RBUlROQU1FLAorCisJCQkJICAgICAgdWludF8zLAor CQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzA2LAorCQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzAw LAorCQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzAwLAorCisJCQkJICAgICAgT1BBTF9TVEFSVExJ U1QsCisJCQkJICAgICAgdXNlcl9sciwgT1BBTF9VSURfTEVOR1RILAorCQkJCSAgICAgIE9QQUxf RU5ETElTVCwKKworCQkJCSAgICAgIE9QQUxfRU5ETkFNRSwKKwkJCQkgICAgICBPUEFMX0VORExJ U1QpOworCX0gZWxzZSAvKiBBY3RpYXZlIE5vcm1hbCBNb2RlICovCisJCXJldCA9IHRlc3RfYW5k X2FkZF90b2tlbl92YShjbWQsICIyYyIsCisJCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKwkJCQkJ ICAgIE9QQUxfRU5ETElTVCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoIiVzOiBFcnJv ciBidWlsZGluZyBBY3RpdmF0ZSBMb2NraW5nU1AgY29tbWFuZC5cbiIsCisJCSAgICAgICBkZXYt PmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZpbmFsaXplX2FuZF9z ZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOworfQorCitzdGF0aWMgdm9pZCBnZXRfbHNwX2xp ZmVjeWNsZV9jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKK3sKKworCXN0cnVjdCBvcGFsX2Rl diAqZGV2ID0gZGF0YTsKKwl1OCBsY19zdGF0dXM7CisKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJy X3JldHVybjsKKworCWVycm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhkZXYpOworCWlmIChl cnJvcikKKwkJZ290byBlcnJfcmV0dXJuOworCisJbGNfc3RhdHVzID0gcmVzcG9uc2VfZ2V0X3U2 NCgmZGV2LT5wYXJzZWQsIDQpOworCS8qIDB4MDggaXMgTWFudWZhY3VyZWQgSW5hY3RpdmUgKi8K KwkvKiAweDA5IGlzIE1hbnVmYWN0dXJlZCAqLworCWlmIChsY19zdGF0dXMgIT0gMHgwOCkgewor CQlwcl9lcnIoIiVzOiBDb3VsZG4ndCBkZXRlcm1pbmUgdGhlIHN0YXR1cyBvZiB0aGUgTGlmY3lj bGUgc3RhdGVcbiIsCisJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCWVycm9yID0gLUVOT0RF VjsKKwl9CisKK2Vycl9yZXR1cm46CisJaWYgKGRldi0+b3Blcl9jYikKKwkJZGV2LT5vcGVyX2Ni KGVycm9yLCBkZXYpOworfQorCisvKiBEZXRlcm1pbmUgaWYgd2UncmUgaW4gdGhlIE1hbnVmYWN0 dXJlZCBJbmFjdGl2ZSBvciBBY3RpdmUgc3RhdGUgKi8KK2ludCBnZXRfbHNwX2xpZmVjeWNsZShz dHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwljb25zdCB1 OCAqbWV0aG9kLCAqdWlkOworCWludCByZXQ7CisKKwljbWQgPSAmZGV2LT5jbWQ7CisKKwljbGVh cl9vcGFsX2NtZChjbWQpOworCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOworCisJdWlkID0g T1BBTFVJRFtPUEFMX0xPQ0tJTkdTUF9VSURdOworCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9H RVRdOworCisJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyAyYyA0YyA0YyAy YyIsCisJCQkJICAgIE9QQUxfQ0FMTCwKKwkJCQkgICAgdWlkLCBPUEFMX1VJRF9MRU5HVEgsCisJ CQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAorCisJCQkJICAgIE9QQUxfU1RBUlRM SVNULAorCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwK KwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIFN0YXJ0IENvbHVtbiAqLworCQkJCSAgICBP UEFMX1RJTllfVUlOVF8wNiwgLyogTGlmY3ljbGUgQ29sdW1uICovCisJCQkJICAgIE9QQUxfRU5E TkFNRSwKKworCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRf MDQsIC8qIEVuZCBDb2x1bW4gKi8KKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIExpZmVj eWNsZSBDb2x1bW4gKi8KKwkJCQkgICAgT1BBTF9FTkROQU1FLAorCisJCQkJICAgIE9QQUxfRU5E TElTVCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2Vy cigiJXM6IEVycm9yIEJ1aWxkaW5nIEdFVCBMaWZlY3ljbGUgU3RhdHVzIGNvbW1hbmRcbiIsCisJ CSAgICAgICBkZXYtPmRpc2tfbmFtZSk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIGZp bmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZXRfbHNwX2xpZmVjeWNsZV9jb250KTsKK30KKwor c3RhdGljIHZvaWQgZ2V0X21zaWRfY3Bpbl9waW5fY29udChpbnQgZXJyb3IsIHZvaWQgKmRhdGEp Cit7CisJY29uc3QgY2hhciAqbXNpZF9waW47CisJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRh OworCXNpemVfdCBzdHJsZW47CisKKwlpZiAoZXJyb3IpCisJCWdvdG8gZXJyX3JldHVybjsKKwor CWVycm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhkZXYpOworCWlmIChlcnJvcikKKwkJZ290 byBlcnJfcmV0dXJuOworCisJc3RybGVuID0gcmVzcG9uc2VfZ2V0X3N0cmluZygmZGV2LT5wYXJz ZWQsIDQsICZtc2lkX3Bpbik7CisJaWYgKCFtc2lkX3BpbikgeworCQlwcl9lcnIoIiVzOiBDb3Vs ZG4ndCBleHRyYWN0IFBJTiBmcm9tIHJlc3BvbnNlXG4iLCBfX2Z1bmNfXyk7CisJCWVycm9yID0g MTsKKwkJZ290byBlcnJfcmV0dXJuOworCX0KKworCWRldi0+cHJldl9kYXRhID0ga21lbWR1cCht c2lkX3Bpbiwgc3RybGVuLCBHRlBfS0VSTkVMKTsKKwlpZiAoIWRldi0+cHJldl9kYXRhKQorCQll cnJvciA9IC1FTk9NRU07CisKKwlkZXYtPnByZXZfZF9sZW4gPSBzdHJsZW47CisKKyBlcnJfcmV0 dXJuOgorCWlmIChkZXYtPm9wZXJfY2IpCisJCWRldi0+b3Blcl9jYihlcnJvciwgZGV2KTsKK30K Kworc3RhdGljIGludCBnZXRfbXNpZF9jcGluX3BpbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sK Kwljb25zdCB1OCAqbWV0aG9kLCAqc211aWQ7CisJaW50IHJldDsKKwlzdHJ1Y3Qgb3BhbF9jbWQg KmNtZDsKKworCWNtZCA9ICZkZXYtPmNtZDsKKwljbGVhcl9vcGFsX2NtZChjbWQpOworCXNldF9j b21JRChjbWQsIGRldi0+Y29tSUQpOworCisJc211aWQgPSBPUEFMVUlEW09QQUxfQ19QSU5fTVNJ RF07CisJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0dFVF07CisKKwlyZXQgPSB0ZXN0X2FuZF9h ZGRfdG9rZW5fdmEoY21kLCAiYyAycyAxMmMiLAorCQkJCSAgICBPUEFMX0NBTEwsCisKKwkJCQkg ICAgc211aWQsIE9QQUxfVUlEX0xFTkdUSCwKKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9M RU5HVEgsCisKKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCisJCQkJICAgIE9QQUxfU1RBUlRMSVNU LAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8q IFNhcnQgQ29sdW1uICovCisJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAvKiBQSU4gKi8KKwkJ CQkgICAgT1BBTF9FTkROQU1FLAorCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKKwkJCQkgICAgT1BB TF9USU5ZX1VJTlRfMDQsIC8qIEVuZCBDb2x1bW4gKi8KKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRf MDMsIC8qIFBJTiAqLworCQkJCSAgICBPUEFMX0VORE5BTUUsCisJCQkJICAgIE9QQUxfRU5ETElT VCwKKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKKworCWlmIChyZXQgPCAwKSB7CisJCXByX2Vycigi JXM6IEVycm9yIGJ1aWxkaW5nIEdldCBNU0lEIENQSU4gUElOIGNvbW1hbmQuXG4iLAorCQkgICAg ICAgZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiBmaW5hbGl6 ZV9hbmRfc2VuZChkZXYsIGNtZCwgZ2V0X21zaWRfY3Bpbl9waW5fY29udCk7Cit9CisKK3N0YXRp YyB2b2lkIHVubG9ja19zdXNwZW5kX2ZpbmFsKGludCBlcnJvciwgdm9pZCAqZGF0YSkKK3sKKwlz dHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CisKKwlkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQg PSBmYWxzZTsKKwlkZXYtPnJlc3VtZV9kYXRhID0gTlVMTDsKKwlkZXYtPmZ1bmNfZGF0YSA9IE5V TEw7CisJZGV2LT5iZGV2ID0gTlVMTDsKK30KKworc3RhdGljIGludCBidWlsZF9lbmRfb3BhbF9z ZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2KQoreworCXN0cnVjdCBvcGFsX2NtZCAqY21kOwor CisJY21kID0gJmRldi0+Y21kOworCWNsZWFyX29wYWxfY21kKGNtZCk7CisKKwlzZXRfY29tSUQo Y21kLCBkZXYtPmNvbUlEKTsKKwlyZXR1cm4gdGVzdF9hbmRfYWRkX3Rva2VuX3U4KGNtZCwgT1BB TF9FTkRPRlNFU1NJT04pOworfQorCitzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb24oc3RydWN0 IG9wYWxfZGV2ICpkZXYpCit7CisJaWYgKGJ1aWxkX2VuZF9vcGFsX3Nlc3Npb24oZGV2KSA8IDAp CisJCXJldHVybiAtMTsKKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCAmZGV2LT5jbWQs IGVuZF9zZXNzaW9uX2NvbnQpOworfQorCitzdGF0aWMgc3RydWN0IG9wYWxfZGV2ICpmaW5kX29w YWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHU4IGxyKQoreworCXN0cnVjdCBvcGFs X2RldiAqaXRlciwgKm9wYWxfZGV2ID0gTlVMTDsKKworCWxpc3RfZm9yX2VhY2hfZW50cnkoaXRl ciwgJm9wYWxfbGlzdCwgbm9kZSkgeworCQlpZiAoc3RybmNtcChpdGVyLT5kaXNrX25hbWUsIGJk ZXYtPmJkX2Rpc2stPmRpc2tfbmFtZSwKKwkJCSAgICBESVNLX05BTUVfTEVOKSkKKwkJCWNvbnRp bnVlOworCQlpZiAoaXRlci0+bHIgPT0gbHIpIHsKKwkJCW9wYWxfZGV2ID0gaXRlcjsKKwkJCWJy ZWFrOworCQl9CisJfQorCisJcmV0dXJuIG9wYWxfZGV2OworfQorCitzdGF0aWMgaW50IHVwZGF0 ZV9vcGFsX2RldihzdHJ1Y3Qgb3BhbF9kZXYgKm9sZF9kZXYsIHN0cnVjdCBvcGFsX2RldiAqbmV3 X2RldikKK3sKKwlpZiAoIWF0b21pY19hZGRfdW5sZXNzKCZvbGRfZGV2LT5pbl91c2UsIDEsIDEp KSB7CisJCXByX2VycigiJXM6IGRldiB3YXMgaW4gdXNlXG4iLCBfX2Z1bmNfXyk7CisJCXJldHVy biAtRUJVU1k7CisJfQorCisJb2xkX2Rldi0+a2V5X25hbWVfbGVuID0gbmV3X2Rldi0+a2V5X25h bWVfbGVuOworCWlmICghbWVtY3B5KG9sZF9kZXYtPmtleV9uYW1lLCBuZXdfZGV2LT5rZXlfbmFt ZSwgb2xkX2Rldi0+a2V5X25hbWVfbGVuKSkgeworCQlwcl9lcnIoIiVzOiBFcnJvciB1cGRhdGlu ZyBkZXZpY2U6XG4iLCBvbGRfZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVGQVVMVDsKKwl9 CisKKwlpZiAoIXN0cm5jcHkob2xkX2Rldi0+ZGlza19uYW1lLCBuZXdfZGV2LT5kaXNrX25hbWUs IERJU0tfTkFNRV9MRU4pKSB7CisJCXByX2VycigiJXM6IEVycm9yIHJlZ2lzdGVyaW5nIGRldmlj ZTogY29weWluZyBkaXNrIG5hbWVcbiIsCisJCSAgICAgICBvbGRfZGV2LT5kaXNrX25hbWUpOwor CQlyZXR1cm4gLUVGQVVMVDsKKwl9CisKKwlvbGRfZGV2LT5jb21JRCA9IG5ld19kZXYtPmNvbUlE OworCW9sZF9kZXYtPnN0YXJ0ID0gbmV3X2Rldi0+c3RhcnQ7CisJb2xkX2Rldi0+bGVuZ3RoID0g bmV3X2Rldi0+bGVuZ3RoOworCW9sZF9kZXYtPmFsaWduID0gbmV3X2Rldi0+YWxpZ247CisJb2xk X2Rldi0+bG93ZXN0X2xiYSA9IG5ld19kZXYtPmxvd2VzdF9sYmE7CisJb2xkX2Rldi0+YmRldiA9 IE5VTEw7CisJb2xkX2Rldi0+ZmluYWxfY2IgPSBuZXdfZGV2LT5maW5hbF9jYjsKKwlvbGRfZGV2 LT5maW5hbF9jYl9kYXRhID0gbmV3X2Rldi0+ZmluYWxfY2JfZGF0YTsKKwlvbGRfZGV2LT5vcGVy X2NiID0gbmV3X2Rldi0+b3Blcl9jYjsKKwlvbGRfZGV2LT5zdGF0ZSA9IG5ld19kZXYtPnN0YXRl OworCW9sZF9kZXYtPmZ1bmNzID0gbmV3X2Rldi0+ZnVuY3M7CisKKwlrZnJlZShvbGRfZGV2LT5j b21wbGV0aW9uKTsKKwljbGVhbl9mdW5jdGlvbl9kYXRhKG9sZF9kZXYpOworCisJb2xkX2Rldi0+ Y29tcGxldGlvbiA9IG5ld19kZXYtPmNvbXBsZXRpb247CisKKwkvKgorCSAqIFdvbid0IGJlIGFi bGUgdG8gYXV0byB1bmxvY2sgdGhpcyBsb2NraW5nIHJhbmdlIGJhc2VkIG9uIGJsb2NrCisJICog cmVxdWVzdGVzLgorCSAqLworCWlmIChvbGRfZGV2LT5sZW5ndGggPT0gMCkKKwkJcHJfd2Fybigi JXM6IE1pc3NpbmcgYmxvY2sgaW5mb3JtYXRpb24gZm9yIGxvY2tpbmcgcmFuZ2UgJWRcbiIsCisJ CQlvbGRfZGV2LT5kaXNrX25hbWUsIG9sZF9kZXYtPmxyKTsKKworCXJldHVybiAwOworfQorCitp bnQgb3BhbF9yZWdpc3Rlcl9jb250KHN0cnVjdCBvcGFsX2RldiAqbmV3X2RldikKK3sKKwlzdHJ1 Y3Qgb3BhbF9kZXYgKm9sZF9kZXY7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKwlpbnQgZXJyb3Ig PSAwOworCisJc3Bpbl9sb2NrX2lycXNhdmUoJmxpc3Rfc3BpbmxvY2ssIGZsYWdzKTsKKworCW9s ZF9kZXYgPSBmaW5kX29wYWxfZGV2KG5ld19kZXYtPmJkZXYsIG5ld19kZXYtPmxyKTsKKwlpZiAo IW9sZF9kZXYpIHsKKwkJbGlzdF9hZGRfdGFpbCgmbmV3X2Rldi0+bm9kZSwgJm9wYWxfbGlzdCk7 CisJCW9sZF9kZXYgPSBuZXdfZGV2OworCX0gZWxzZSB7CisJCWlmIChvbGRfZGV2ID09IG5ld19k ZXYpCisJCQllcnJvciA9IDA7CisJCWVsc2UgeworCQkJZXJyb3IgPSB1cGRhdGVfb3BhbF9kZXYo b2xkX2RldiwgbmV3X2Rldik7CisJCQljbGVhbl9vcGFsX2tleShuZXdfZGV2KTsKKwkJCWtmcmVl KG5ld19kZXYpOworCQl9CisJfQorCisJaWYgKGVycm9yKQorCQlsaXN0X2RlbCgmb2xkX2Rldi0+ bm9kZSk7CisKKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZsaXN0X3NwaW5sb2NrLCBmbGFncyk7 CisKKwlpZiAoIWVycm9yKQorCQlwcl9pbmZvKCIlczogUmVnaXN0ZXJlZCBrZXkgZm9yIGxvY2tp bmcgcmFuZ2U6ICVkXG4iLAorCQkJb2xkX2Rldi0+ZGlza19uYW1lLCBvbGRfZGV2LT5scik7CisK KwlpZiAob2xkX2Rldi0+b3Blcl9jYikKKwkJb2xkX2Rldi0+b3Blcl9jYihlcnJvciwgb2xkX2Rl dik7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHZvaWQgbmV4dChpbnQgZXJyb3IsIHN0cnVj dCBvcGFsX2RldiAqZGV2KQoreworCW9wYWxfc3RlcCBmdW5jID0gZGV2LT5mdW5jc1tkZXYtPnN0 YXRlXTsKKwl2b2lkICpjYl9kYXRhID0gZGV2LT5maW5hbF9jYl9kYXRhOworCXNlY19jYiAqY2Ig PSBkZXYtPmZpbmFsX2NiOworCWJvb2wgZG9uZSA9IGZhbHNlOworCisKKwlpZiAoZXJyb3IgfHwg IWZ1bmMpIHsKKwkJZG9uZSA9IHRydWU7CisJCWdvdG8gbmV4dF9leGl0OworCX0KKwlkZXYtPnN0 YXRlKys7CisJZGV2LT5vcGVyX2NiID0gbmV4dDsKKwllcnJvciA9IGZ1bmMoZGV2KTsKKyBuZXh0 X2V4aXQ6CisJaWYgKGVycm9yKSB7CisJCXByX2VycigiJXM6IEVycm9yIG9uIHN0ZXAgZnVuY3Rp b246ICVkIHdpdGggZXJyb3IgJWQ6ICVzXG4iLAorCQkgICAgICAgZGV2LT5kaXNrX25hbWUsIGRl di0+c3RhdGUsIGVycm9yLAorCQkgICAgICAgb3BhbF9lcnJvcl90b19odW1hbihlcnJvcikpOwor CisKKwkJYXRvbWljX2RlYygmZGV2LT5pbl91c2UpOworCQlpZiAoZGV2LT5lcnJvcl9jYikgewor CQkJZGV2LT5lcnJvcl9jYihkZXYtPmVycm9yX2NiX2RhdGEpOworCQkJcmV0dXJuOworCQl9CisJ CWlmIChjYikKKwkJCWNiKGVycm9yLCBjYl9kYXRhKTsKKworCQlkZXYtPmNvbXBsZXRpb24tPmNv bXBsZXRpb25fc3RhdHVzID0gZXJyb3I7CisJCWNvbXBsZXRlKCZkZXYtPmNvbXBsZXRpb24tPmNt ZF9jb21wbGV0aW9uKTsKKwl9IGVsc2UgaWYgKCFlcnJvciAmJiBkb25lKSB7CisJCWF0b21pY19k ZWMoJmRldi0+aW5fdXNlKTsKKwkJaWYgKGNiKQorCQkJY2IoZXJyb3IsIGNiX2RhdGEpOworCQlk ZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVzID0gZXJyb3I7CisJCWNvbXBsZXRlKCZk ZXYtPmNvbXBsZXRpb24tPmNtZF9jb21wbGV0aW9uKTsKKwl9Cit9CisKK2NvbnN0IG9wYWxfc3Rl cCBlcnJvcl9lbmRfc2Vzc2lvbltdID0geworCWVuZF9vcGFsX3Nlc3Npb24sCisJTlVMTCwKK307 CitzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb25fZXJyb3Ioc3RydWN0IG9wYWxfZGV2ICpkZXYp Cit7CisKKwlkZXYtPmZ1bmNzID0gZXJyb3JfZW5kX3Nlc3Npb247CisJZGV2LT5zdGF0ZSA9IDA7 CisJZGV2LT5lcnJvcl9jYiA9IE5VTEw7CisJbmV4dCgwLCBkZXYpOworCXJldHVybiAwOworfQor CitzdGF0aWMgc3RydWN0IG9wYWxfZGV2ICphbGxvY19vcGFsX2RldihzdHJ1Y3QgYmxvY2tfZGV2 aWNlICpiZGV2LCB1OCBscikKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKm9wYWxfZGV2OworCXN0cnVj dCByZXF1ZXN0X3F1ZXVlICpxOworCXVuc2lnbmVkIGxvbmcgZG1hX2FsaWduOworCWNvbnN0IGNo YXIgKmRpc2tfbmFtZTsKKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKKwlpbnQgcmV0OworCisJb3Bh bF9kZXYgPSBremFsbG9jKHNpemVvZigqb3BhbF9kZXYpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIW9w YWxfZGV2KQorCQlyZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKKworCW9wYWxfZGV2LT5iZGV2ID0g YmRldjsKKwlvcGFsX2Rldi0+bHIgPSBscjsKKwljbWQgPSAmb3BhbF9kZXYtPmNtZDsKKwljbWQt PmNtZCA9IGNtZC0+Y21kX2J1ZjsKKwljbWQtPnJlc3AgPSBjbWQtPnJlc3BfYnVmOworCisJZGlz a19uYW1lID0gYmRldi0+YmRfZGlzay0+ZGlza19uYW1lOworCWlmICghc3RybmNweShvcGFsX2Rl di0+ZGlza19uYW1lLCBkaXNrX25hbWUsIERJU0tfTkFNRV9MRU4pKSB7CisJCXByX2VycigiJXM6 IEVycm9yIHJlZ2lzdGVyaW5nIGRldmljZTogY29weWluZyBkaXNrIG5hbWVcbiIsCisJCSAgICAg ICBkaXNrX25hbWUpOworCQlyZXQgPSAtRUZBVUxUOworCQlnb3RvIGVycl9mcmVlX2RldjsKKwl9 CisKKwlxID0gYmRldi0+YmRfcXVldWU7CisJZG1hX2FsaWduID0gKHF1ZXVlX2RtYV9hbGlnbm1l bnQocSkgfCBxLT5kbWFfcGFkX21hc2spICsgMTsKKwljbWQtPmNtZCA9ICh1OCAqKXJvdW5kX3Vw KCh1aW50cHRyX3QpY21kLT5jbWQsIGRtYV9hbGlnbik7CisJY21kLT5yZXNwID0gKHU4ICopcm91 bmRfdXAoKHVpbnRwdHJfdCljbWQtPnJlc3AsIGRtYV9hbGlnbik7CisKKwlJTklUX0xJU1RfSEVB RCgmb3BhbF9kZXYtPm5vZGUpOworCWF0b21pY19zZXQoJm9wYWxfZGV2LT5pbl91c2UsIDEpOwor CisJb3BhbF9kZXYtPmNvbXBsZXRpb24gPSBremFsbG9jKHNpemVvZigqb3BhbF9kZXYtPmNvbXBs ZXRpb24pLAorCQkJCSAgICAgICBHRlBfS0VSTkVMKTsKKworCWlmICghb3BhbF9kZXYtPmNvbXBs ZXRpb24pCisJCWdvdG8gZXJyX2ZyZWVfZGV2OworCisJaW5pdF9jb21wbGV0aW9uKCZvcGFsX2Rl di0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24pOworCW9wYWxfZGV2LT5jb21wbGV0aW9uLT5j b21wbGV0aW9uX3N0YXR1cyA9IDA7CisJb3BhbF9kZXYtPnN0YXRlID0gMDsKKworCXJldHVybiBv cGFsX2RldjsKKworZXJyX2ZyZWVfZGV2OgorCWtmcmVlKG9wYWxfZGV2KTsKKwlyZXR1cm4gRVJS X1BUUihyZXQpOworfQorCitpbnQgb3BhbF9yZWdpc3RlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpi ZGV2LCBzdHJ1Y3Qgb3BhbF9rZXkgKmtleV9jbWQsCisJCSAgY29uc3Qgb3BhbF9zdGVwICpmdW5j cykKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKm5ld19kZXYgPSBOVUxMOworCXU4IGtleV9sZW4gPSBr ZXlfY21kLT5rZXlfbGVuOworCXU4IGxyID0ga2V5X2NtZC0+bHI7CisJc3RydWN0IG9wYWxfY29t cGxldGlvbiAqY29tcGxldGlvbjsKKwlpbnQgcmV0OworCisJbmV3X2RldiA9IGFsbG9jX29wYWxf ZGV2KGJkZXYsIGxyKTsKKwlpZiAoSVNfRVJSKG5ld19kZXYpKSB7CisJCXByX2VycigiJXM6IEVy cm9yIHJlZ2lzdGVyaW5nIGRldmljZTogYWxsb2NhdGlvblxuIiwKKwkJICAgICAgIGJkZXYtPmJk X2Rpc2stPmRpc2tfbmFtZSk7CisJCXJldHVybiBQVFJfRVJSKG5ld19kZXYpOworCX0KKworCWlm ICghbWVtY3B5KG5ld19kZXYtPmtleV9uYW1lLCBrZXlfY21kLT5rZXksIGtleV9sZW4pKSB7CisJ CXByX2VycigiJXM6IEVycm9yIHJlZ2lzdGVyaW5nIGtleTogY291bGRuJ3QgY29weSBrZXlcbiIs CisJCSAgICAgICBuZXdfZGV2LT5kaXNrX25hbWUpOworCQlyZXR1cm4gLUVGQVVMVDsKKwl9CisK KwluZXdfZGV2LT5rZXlfbmFtZV9sZW4gPSBrZXlfbGVuOworCW5ld19kZXYtPmtleV90eXBlID0g a2V5X2NtZC0+a2V5X3R5cGU7CisJcmV0ID0gZ2V0X29wYWxfa2V5KG5ld19kZXYpOworCWlmIChy ZXQpIHsKKwkJcHJfZXJyKCIlczogQ291bGRuJ3QgZ2V0IGtleTogJWRcbiIsIG5ld19kZXYtPmRp c2tfbmFtZSwgcmV0KTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwluZXdfZGV2LT5mdW5jcyA9IGZ1 bmNzOworCisJbmV3X2Rldi0+c3RhdGUgPSAwOworCWNvbXBsZXRpb24gPSBuZXdfZGV2LT5jb21w bGV0aW9uOworCW5leHQoMCwgbmV3X2Rldik7CisKKwlyZXR1cm4gd2FpdF9mb3JfY21kX2NvbXBs ZXRpb24oY29tcGxldGlvbik7Cit9CisKK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9kZXYgKmdldF9yZWdp c3RlcmVkX29wYWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkJCQl1OCBscikK K3sKKwljb25zdCBjaGFyICpkaXNrbmFtZSA9IGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZTsKKwlz dHJ1Y3Qgb3BhbF9kZXYgKml0ZXIsICpkZXYgPSBOVUxMOworCXVuc2lnbmVkIGxvbmcgZmxhZ3M7 CisJYm9vbCBpbl91c2UgPSBmYWxzZTsKKworCXNwaW5fbG9ja19pcnFzYXZlKCZsaXN0X3NwaW5s b2NrLCBmbGFncyk7CisJbGlzdF9mb3JfZWFjaF9lbnRyeShpdGVyLCAmb3BhbF9saXN0LCBub2Rl KSB7CisJCWlmIChzdHJuY21wKGl0ZXItPmRpc2tfbmFtZSwgZGlza25hbWUsIERJU0tfTkFNRV9M RU4pKQorCQkJY29udGludWU7CisJCWlmIChpdGVyLT5sciA9PSBscikgeworCQkJZGV2ID0gaXRl cjsKKwkJCWlmICghYXRvbWljX2FkZF91bmxlc3MoJml0ZXItPmluX3VzZSwgMSwgMSkpIHsKKwkJ CQlkZXYgPSBOVUxMOworCQkJCWluX3VzZSA9IHRydWU7CisJCQl9CisJCQlicmVhazsKKwkJfQor CX0KKworCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmxpc3Rfc3BpbmxvY2ssIGZsYWdzKTsKKwor CWlmICghZGV2KQorCQlyZXR1cm4gTlVMTDsKKworCWRldi0+YmRldiA9IGJkZXY7CisJcmV0dXJu IGRldjsKK30KKworLyogRnJlZSB1cCB0aGUgT3BhbCBkZXYgYW5kIGl0cyBrZXlzIGR1cmluZyB0 d28gc2NlbmFyaW9zOgorICoKKyAqIDEpIFdoZW4gYSBjb21tYW5kIGlzIGNvbXBsZXRlIHRoYXQg bm8gbG9uZ2VyIHJlcXVpcmVzCisgKiAgICB0aGUgb3BhbCBkZXYgdG8gYmUgYXJvdW5kLgorICog MikgV2hlbiBhIGNvbW1hbmQsIGluY2x1ZGluZyBPcGFsIFNhdmUgZmFpbHMgd2UgY2xlYW4KKyAq ICAgIGFuZCBmcmVlIHRoZSBvcGFsIGRldi4KKyAqCisgKiAgICBJZiB3ZSBmaW5kIHRoZSBvcGFs IGRldiBzdHJ1Y3R1cmUgaW4gdGhlIGxpc3Qgb2YKKyAqICAgIHNhdmVkIHBhc3N3b3JkcyB3ZSB3 aWxsICpub3QqIHJlbW92ZSBpdC4KKyAqLworc3RhdGljIHZvaWQgcmVtb3ZlX2FuZF9jbGVhbl9v cGFsX2RldihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKK3sKKwlzdHJ1Y3Qgb3BhbF9kZXYgKml0ZXI7 CisJYm9vbCBmb3VuZCA9IGZhbHNlOworCisJc3Bpbl9sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKwls aXN0X2Zvcl9lYWNoX2VudHJ5KGl0ZXIsICZvcGFsX2xpc3QsIG5vZGUpIHsKKwkJaWYgKGl0ZXIg PT0gZGV2KSB7CisJCQlmb3VuZCA9IHRydWU7CisJCQlicmVhazsKKwkJfQorCX0KKworCXNwaW5f dW5sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKwlpZiAoIWZvdW5kKSB7CisJCWNsZWFuX29wYWxfa2V5 KGRldik7CisJCWNsZWFuX2Z1bmN0aW9uX2RhdGEoZGV2KTsKKwkJa2ZyZWUoZGV2KTsKKwl9Cit9 CisKK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9kZXYgKmdldF9vcl9jcmVhdGVfb3BhbF9kZXYoc3RydWN0 IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCQkJICAgICAgIHU4IGxyLCBib29sIHVzZV9uZXcpCit7 CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7CisKKwlpZiAodXNlX25ldykKKwkJcmV0dXJuIGFsbG9j X29wYWxfZGV2KGJkZXYsIGxyKTsKKworCWRldiA9IGdldF9yZWdpc3RlcmVkX29wYWxfZGV2KGJk ZXYsIGxyKTsKKwlpZiAoIWRldikgeworCQlkZXYgPSBhbGxvY19vcGFsX2RldihiZGV2LCBscik7 CisJCWlmICghZGV2KQorCQkJcmV0dXJuIE5VTEw7CisJfQorCXJldHVybiBkZXY7Cit9CisKK3N0 YXRpYyBzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpzZXR1cF9vcGFsX2RldihzdHJ1Y3QgYmxvY2tf ZGV2aWNlICpiZGV2LAorCQkJCQkgICAgICBzdHJ1Y3Qgb3BhbF9kZXYgKmRldiwKKwkJCQkJICAg ICAgY29uc3Qgb3BhbF9zdGVwICpmdW5jcywKKwkJCQkJICAgICAgc3RydWN0IG9wYWxfa2V5ICpr ZXkpCit7CisJaW50IHJldDsKKworCWRldi0+YmRldiA9IGJkZXY7CisJZGV2LT5zdGF0ZSA9IDA7 CisJZGV2LT5mdW5jcyA9IGZ1bmNzOworCWRldi0+VFNOID0gMDsKKwlkZXYtPkhTTiA9IDA7CisJ ZGV2LT5maW5hbF9jYiA9IE5VTEw7CisJZGV2LT5maW5hbF9jYl9kYXRhID0gTlVMTDsKKwlkZXYt PmxyID0ga2V5LT5scjsKKwlkZXYtPmVycm9yX2NiID0gZW5kX29wYWxfc2Vzc2lvbl9lcnJvcjsK KwlkZXYtPmVycm9yX2NiX2RhdGEgPSBkZXY7CisKKwlpZiAoa2V5KSB7CisJCW1lbWNweShkZXYt PmtleV9uYW1lLCBrZXktPmtleSwga2V5LT5rZXlfbGVuKTsKKwkJZGV2LT5rZXlfbmFtZV9sZW4g PSBrZXktPmtleV9sZW47CisJCWRldi0+a2V5X3R5cGUgPSBrZXktPmtleV90eXBlOworCisJCXJl dCA9IGdldF9vcGFsX2tleShkZXYpOworCQlpZiAocmV0KSB7CisJCQlrZnJlZShkZXYtPmNvbXBs ZXRpb24pOworCQkJcHJfZXJyKCIlczogQ291bGRuJ3QgZ2V0IGtleTogJWRcbiIsCisJCQkgICAg ICAgZGV2LT5kaXNrX25hbWUsIHJldCk7CisJCQlyZXR1cm4gRVJSX1BUUihyZXQpOworCQl9CisJ fQorCWRldi0+ZnVuY19kYXRhID0gTlVMTDsKKwlkZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25f c3RhdHVzID0gMDsKKworCXJldHVybiBkZXYtPmNvbXBsZXRpb247Cit9CisKK3N0YXRpYyBpbnQg aW50ZXJuYWxfc2V0dXBfbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCSAgICAgc3Ry dWN0IG9wYWxfdXNlcl9scl9zZXR1cCAqc2V0dXApCit7CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7 CisJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKKwl2b2lkICpkYXRhWzNdID0g eyBOVUxMIH07CisJY29uc3Qgb3BhbF9zdGVwIGxyX2Z1bmNzW10gPSB7CisJCW9wYWxfZGlzY292 ZXJ5MCwKKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCisJCXNldHVwX2xvY2tpbmdfcmFuZ2Us CisJCWdldF9hY3RpdmVfa2V5LAorCQlnZW5fa2V5LAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlO VUxMLAorCX07CisJaW50IHJldDsKKworCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRl diwgc2V0dXAtPmtleS5sciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJldHVybiAtRU5PTUVNOwor CisJY29tcGxldGlvbiA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwgbHJfZnVuY3MsICZzZXR1 cC0+a2V5KTsKKwlpZiAoSVNfRVJSKGNvbXBsZXRpb24pKSB7CisJCXJldCA9IFBUUl9FUlIoY29t cGxldGlvbik7CisJCWdvdG8gZXJyb3JfcmV0dXJuOworCX0KKworCWRldi0+ZnVuY19kYXRhID0g ZGF0YTsKKwlkZXYtPm51bV9mdW5jX2RhdGEgPSAzOworCWRldi0+ZnVuY19kYXRhWzFdID0gJnNl dHVwLT53aG87CisJZGV2LT5mdW5jX2RhdGFbMl0gPSBzZXR1cDsKKworCW5leHQoMCwgZGV2KTsK KwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsKKworIGVycm9yX3Jl dHVybjoKKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7CisJcmV0dXJuIHJldDsKK30K KworaW50IG9wYWxfcmV2ZXJ0KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBvcGFs X2tleSAqa2V5KQoreworCWNvbnN0IG9wYWxfc3RlcCByZXZlcnRfZnVuY3NbXSA9IHsKKwkJb3Bh bF9kaXNjb3ZlcnkwLAorCQlzdGFydF9TSURBU1Bfb3BhbF9zZXNzaW9uLAorCQlyZXZlcnRfdHBl ciwgLyogY29udHJvbGxlciB3aWxsIHRlcm1pbmF0ZSBzZXNzaW9uICovCisJCU5VTEwsCisJfTsK KworCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYsIGtleSwgcmV2ZXJ0X2Z1bmNzKTsKK30KKwor aW50IGFjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IG9wYWxf YWN0aXZhdGVfdXNlciAqYWN0KQoreworCWNvbnN0IG9wYWxfc3RlcCBhY3RfZnVuY3NbXSA9IHsK KwkJb3BhbF9kaXNjb3ZlcnkwLAorCQlzdGFydF9hZG1pbjFMU1Bfb3BhbF9zZXNzaW9uLAorCQlp bnRlcm5hbF9hY3RpdmF0ZV91c2VyLAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlOVUxMCisJfTsK KwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpjb21wbGV0 aW9uOworCXZvaWQgKmRhdGFbM10gPSB7IE5VTEwgfTsKKwlpbnQgcmV0OworCisJZGV2ID0gZ2V0 X29yX2NyZWF0ZV9vcGFsX2RldihiZGV2LCBhY3QtPmtleS5sciwgdHJ1ZSk7CisJaWYgKCFkZXYp CisJCXJldHVybiAtRU5PTUVNOworCisJY29tcGxldGlvbiA9IHNldHVwX29wYWxfZGV2KGJkZXYs IGRldiwgYWN0X2Z1bmNzLCAmYWN0LT5rZXkpOworCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsK KwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1cm47CisJfQor CisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7CisJZGV2 LT5mdW5jX2RhdGFbMV0gPSBhY3Q7CisJZGV2LT5mdW5jX2RhdGFbMl0gPSBhY3Q7CisKKwluZXh0 KDAsIGRldik7CisJcmV0ID0gd2FpdF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxldGlvbik7CisK KyBlcnJvcl9yZXR1cm46CisJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2RldihkZXYpOworCXJldHVy biByZXQ7Cit9CisKK2ludCBvcGFsX3NldF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBz dHJ1Y3Qgb3BhbF9uZXdfcHcgKnB3KQorCit7CisJY29uc3Qgb3BhbF9zdGVwIHB3X2Z1bmNzW10g PSB7CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCisJCXNl dF9uZXdfcHcsCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEwKKwl9OworCXN0cnVjdCBvcGFs X2RldiAqZGV2OworCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJdm9pZCAq ZGF0YVszXSA9IHsgTlVMTCB9OworCWludCByZXQ7CisKKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29w YWxfZGV2KGJkZXYsIHB3LT5jdXJyZW50X3Bpbi5sciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJl dHVybiAtRU5PTUVNOworCisJY29tcGxldGlvbiA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwg cHdfZnVuY3MsICZwdy0+Y3VycmVudF9waW4pOworCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsK KwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1cm47CisJfQor CisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7CisJZGV2 LT5mdW5jX2RhdGFbMV0gPSAodm9pZCAqKSAmcHctPndobzsKKwlkZXYtPmZ1bmNfZGF0YVsyXSA9 ICh2b2lkICopIHB3OworCisJbmV4dCgwLCBkZXYpOworCXJldCA9IHdhaXRfZm9yX2NtZF9jb21w bGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJyb3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5f b3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworfQorCitpbnQgb3BhbF9hY3RfbHNwX2ludChz dHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgb3BhbF9rZXkgKmtleSwKKwkJICAgICBj b25zdCBvcGFsX3N0ZXAgKmZ1bmNzKQoreworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXN0cnVj dCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJaW50IHJldDsKKworCWRldiA9IGdldF9v cl9jcmVhdGVfb3BhbF9kZXYoYmRldiwga2V5LT5sciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJl dHVybiAtRU5PTUVNOworCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2RldihiZGV2LCBkZXYsIGZ1 bmNzLCBrZXkpOworCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsKKwkJcmV0ID0gUFRSX0VSUihj b21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1cm47CisJfQorCisJbmV4dCgwLCBkZXYpOwor CXJldCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJyb3JfcmV0 dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworfQor CisKK3N0YXRpYyBpbnQgb3BhbF9zYXZlX2ludGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2UgKmJk ZXYsCisJCQkgICAgICBzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayAqbGspCit7CisJdm9pZCAqZnVu Y19kYXRhWzNdID0geyBOVUxMIH07CisJc3RydWN0IG9wYWxfZGV2ICpkZXY7CisJc3RydWN0IG9w YWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKKwljb25zdCBvcGFsX3N0ZXAgX2F1dGhfZnVuY3Nb XSA9IHsKKwkJb3BhbF9kaXNjb3ZlcnkwLAorCQlzdGFydF9hdXRoX29wYWxfc2Vzc2lvbiwKKwkJ cXVlcnlfbG9ja2luZ19yYW5nZSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJb3BhbF9yZWdpc3Rl cl9jb250LAorCQlOVUxMCisJfTsKKwlpbnQgcmV0OworCisJZGV2ID0gZ2V0X29yX2NyZWF0ZV9v cGFsX2RldihiZGV2LCBsay0+a2V5LmxyLCBmYWxzZSk7CisJaWYgKCFkZXYpCisJCXJldHVybiAt RU5PTUVNOworCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2RldihiZGV2LCBkZXYsIF9hdXRoX2Z1 bmNzLCAmbGstPmtleSk7CisJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgeworCQlyZXQgPSBQVFJf RVJSKGNvbXBsZXRpb24pOworCQlnb3RvIGVycm9yX3JldHVybjsKKwl9CisKKwlkZXYtPm51bV9m dW5jX2RhdGEgPSAzOworCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOworCWRldi0+ZnVuY19k YXRhWzFdID0gJmxrLT5hdXRob3JpdHk7CisJZGV2LT5sa3VsID0gKmxrOworCisJbmV4dCgwLCBk ZXYpOworCXJldCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJy b3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0 OworfQorCitzdGF0aWMgaW50IGFkZF91c2VyX2xyX2ludGVybmFsKHN0cnVjdCBibG9ja19kZXZp Y2UgKmJkZXYsCisJCQkJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrKQoreworCXZvaWQgKmZ1 bmNfZGF0YVszXSA9IHsgTlVMTCB9OworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXN0cnVjdCBv cGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJY29uc3Qgb3BhbF9zdGVwIGZ1bmNzW10gPSB7 CisJCW9wYWxfZGlzY292ZXJ5MCwKKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxfc2Vzc2lvbiwKKwkJ YWRkX3VzZXJfdG9fbHIsCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEwKKwl9OworCWludCBy ZXQ7CisKKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJkZXYsIGxrLT5rZXkubHIsIHRy dWUpOworCWlmICghZGV2KQorCQlyZXR1cm4gLUVOT01FTTsKKwljb21wbGV0aW9uID0gc2V0dXBf b3BhbF9kZXYoYmRldiwgZGV2LCBmdW5jcywgJmxrLT5rZXkpOworCWlmIChJU19FUlIoY29tcGxl dGlvbikpIHsKKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKKwkJZ290byBlcnJvcl9yZXR1 cm47CisJfQorCisJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKKwlkZXYtPmZ1bmNfZGF0YSA9IGZ1 bmNfZGF0YTsKKwlkZXYtPmZ1bmNfZGF0YVsyXSA9IGxrOworCisJbmV4dCgwLCBkZXYpOworCXJl dCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCisgZXJyb3JfcmV0dXJu OgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYoZGV2KTsKKwlyZXR1cm4gcmV0OworfQorCitz dGF0aWMgaW50IGxvY2tfdW5sb2NrX2ludGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYs CisJCQkJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrKQoreworCXZvaWQgKmZ1bmNfZGF0YVsz XSA9IHsgTlVMTCB9OworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXN0cnVjdCBvcGFsX2NvbXBs ZXRpb24gKmNvbXBsZXRpb247CisKKwljb25zdCBvcGFsX3N0ZXAgdWxrX2Z1bmNzX1NVTVtdID0g eworCQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAorCQlsb2Nr X3VubG9ja19sb2NraW5nX3JhbmdlX1NVTSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJTlVMTAor CX07CisJY29uc3Qgb3BhbF9zdGVwIF91bmxvY2tfZnVuY3NbXSA9IHsKKwkJb3BhbF9kaXNjb3Zl cnkwLAorCQlzdGFydF9hdXRoX29wYWxfc2Vzc2lvbiwKKwkJbG9ja191bmxvY2tfbG9ja2luZ19y YW5nZSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJTlVMTAorCX07CisJaW50IHJldDsKKworCWRl diA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgbGstPmtleS5sciwgdHJ1ZSk7CisJaWYg KCFkZXYpCisJCXJldHVybiAtRU5PTUVNOworCisJaWYgKGxrLT5hdXRob3JpdHkuU1VNKQorCQlj b21wbGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCB1bGtfZnVuY3NfU1VNLCAmbGst PmtleSk7CisJZWxzZQorCQljb21wbGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBf dW5sb2NrX2Z1bmNzLCAmbGstPmtleSk7CisKKwlpZiAoSVNfRVJSKGNvbXBsZXRpb24pKSB7CisJ CXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7CisJCWdvdG8gZXJyb3JfcmV0dXJuOworCX0KKwor CWRldi0+bnVtX2Z1bmNfZGF0YSA9IDM7CisJZGV2LT5mdW5jX2RhdGEgPSBmdW5jX2RhdGE7CisJ ZGV2LT5mdW5jX2RhdGFbMV0gPSAmbGstPmF1dGhvcml0eTsKKwlkZXYtPmZ1bmNfZGF0YVsyXSA9 IGxrOworCisJbmV4dCgwLCBkZXYpOworCXJldCA9IHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNv bXBsZXRpb24pOworCisgZXJyb3JfcmV0dXJuOgorCXJlbW92ZV9hbmRfY2xlYW5fb3BhbF9kZXYo ZGV2KTsKKwlyZXR1cm4gcmV0OworfQorCitpbnQgb3BhbF9lcmFzZV9sb2NraW5nX3JhbmdlKHN0 cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisJc3RydWN0 IG9wYWxfZGV2ICpkZXY7CisJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKKwlz dHJ1Y3Qgb3BhbF9rZXkgazsKKwlpbnQgcmV0OworCWNvbnN0IG9wYWxfc3RlcCBlcmFzZV9mdW5j c1tdID0geworCQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Np b24sCisJCWVyYXNlX2xvY2tpbmdfcmFuZ2UsCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEws CisJfTsKKworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzaykgeworCQlwcl9lcnIoIkNhbid0 IHNhdmUgcGFzc3dvcmQgZm9yIE5VTEwgYmxvY2sgZGV2aWNlLlxuIik7CisJCXJldHVybiAtRUlO VkFMOworCX0KKworCWlmIChjb3B5X2Zyb21fdXNlcigmaywga2V5LT5vcGFsLCBzaXplb2YoKmtl eS0+b3BhbCkpKQorCQlyZXR1cm4gLUVGQVVMVDsKKworCWRldiA9IGdldF9vcl9jcmVhdGVfb3Bh bF9kZXYoYmRldiwgay5sciwgdHJ1ZSk7CisJaWYgKCFkZXYpCisJCXJldHVybiAtRU5PTUVNOwor CisJY29tcGxldGlvbiA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwgZXJhc2VfZnVuY3MsICZr KTsKKwlpZiAoSVNfRVJSKGNvbXBsZXRpb24pKSB7CisJCXJldCA9IFBUUl9FUlIoY29tcGxldGlv bik7CisJCWdvdG8gZXJyb3JfcmV0dXJuOworCX0KKworCW5leHQoMCwgZGV2KTsKKwlyZXQgPSB3 YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsKKworIGVycm9yX3JldHVybjoKKwly ZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7CisJcmV0dXJuIHJldDsKK30KK0VYUE9SVF9T WU1CT0wob3BhbF9lcmFzZV9sb2NraW5nX3JhbmdlKTsKKworaW50IG9wYWxfZW5hYmxlX2Rpc2Fi bGVfc2hhZG93X21icihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LAorCQkJCSAgIHN0cnVjdCBz ZWRfa2V5ICprZXkpCit7CisJdm9pZCAqZnVuY19kYXRhWzZdID0geyBOVUxMIH07CisJc3RydWN0 IG9wYWxfbWJyX2RhdGEgbWJyOworCXN0cnVjdCBvcGFsX2RldiAqZGV2OworCXN0cnVjdCBvcGFs X2NvbXBsZXRpb24gKmNvbXBsZXRpb247CisJY29uc3Qgb3BhbF9zdGVwIG1icl9mdW5jc1tdID0g eworCQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24sCisJ CXNldF9tYnJfZG9uZSwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJc3RhcnRfYWRtaW4xTFNQX29w YWxfc2Vzc2lvbiwKKwkJc2V0X21icl9lbmFibGVfZGlzYWJsZSwKKwkJZW5kX29wYWxfc2Vzc2lv biwKKwkJTlVMTCwKKwl9OworCWludCByZXQ7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rp c2spIHsKKwkJcHJfZXJyKCJDYW4ndCBzYXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmlj ZS5cbiIpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlpZiAoY29weV9mcm9tX3VzZXIoJm1i ciwga2V5LT5vcGFsX21iciwgc2l6ZW9mKCprZXktPm9wYWxfbWJyKSkpCisJCXJldHVybiAtRUZB VUxUOworCisJaWYgKG1ici5lbmFibGVfZGlzYWJsZSAhPSBPUEFMX01CUl9FTkFCTEUgJiYKKwkg ICAgbWJyLmVuYWJsZV9kaXNhYmxlICE9IE9QQUxfTUJSX0RJU0FCTEUpCisJCXJldHVybiAtRUlO VkFMOworCisJZGV2ID0gZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihiZGV2LCBtYnIua2V5LmxyLCB0 cnVlKTsKKwlpZiAoIWRldikKKwkJcmV0dXJuIC1FTk9NRU07CisKKwljb21wbGV0aW9uID0gc2V0 dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBtYnJfZnVuY3MsICZtYnIua2V5KTsKKwlpZiAoSVNfRVJS KGNvbXBsZXRpb24pKSB7CisJCXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7CisJCWdvdG8gZXJy b3JfcmV0dXJuOworCX0KKworCWRldi0+bnVtX2Z1bmNfZGF0YSA9IDY7CisJZGV2LT5mdW5jX2Rh dGEgPSBmdW5jX2RhdGE7CisJZGV2LT5mdW5jX2RhdGFbMl0gPSAmbWJyLmVuYWJsZV9kaXNhYmxl OworCWRldi0+ZnVuY19kYXRhWzVdID0gJm1ici5lbmFibGVfZGlzYWJsZTsKKworCW5leHQoMCwg ZGV2KTsKKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsKKworIGVy cm9yX3JldHVybjoKKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7CisJcmV0dXJuIHJl dDsKKworfQorRVhQT1JUX1NZTUJPTChvcGFsX2VuYWJsZV9kaXNhYmxlX3NoYWRvd19tYnIpOwor CitpbnQgb3BhbF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5 ICprZXkpCit7CisJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgbGt1bDsKKworCWlmICghYmRldiB8 fCAhYmRldi0+YmRfZGlzaykgeworCQlwcl9lcnIoIkNhbid0IHNhdmUgcGFzc3dvcmQgZm9yIE5V TEwgYmxvY2sgZGV2aWNlLlxuIik7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWlmIChjb3B5 X2Zyb21fdXNlcigmbGt1bCwga2V5LT5vcGFsX2xrX3VubGssIHNpemVvZigqa2V5LT5vcGFsKSkp CisJCXJldHVybiAtRUZBVUxUOworCisJcmV0dXJuIG9wYWxfc2F2ZV9pbnRlcm5hbChiZGV2LCAm bGt1bCk7Cit9CitFWFBPUlRfU1lNQk9MKG9wYWxfc2F2ZSk7CisKK2ludCBvcGFsX2FkZF91c2Vy X3RvX2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7 CisJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgbGt1bDsKKworCWlmIChjb3B5X2Zyb21fdXNlcigm bGt1bCwga2V5LT5vcGFsX2xrX3VubGssIHNpemVvZihsa3VsKSkpCisJCXJldHVybiAtRUZBVUxU OworCisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7CisJCXByX2VycigiQ2FuJ3QgYXNz aWduIHVzZXIgdG8gTFIgd2l0aG91dCBiYWNraW5nIGRpc2tcbiIpOworCQlyZXR1cm4gLUVGQVVM VDsKKwl9CisJaWYgKGxrdWwubF9zdGF0ZSAhPSBPUEFMX1JPICYmIGxrdWwubF9zdGF0ZSAhPSBP UEFMX1JXKSB7CisJCXByX2VycigiTG9ja2luZyBzdGF0ZSB3YXMgbm90IFJPIG9yIFJXXG4iKTsK KwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCWlmIChsa3VsLmF1dGhvcml0eS53aG8gPCBPUEFMX1VT RVIxICYmCisJICAgIGxrdWwuYXV0aG9yaXR5LndobyA+IE9QQUxfVVNFUjkpIHsKKwkJcHJfZXJy KCJBdXRob3JpdHkgd2FzIG5vdCB3aXRoaW4gdGhlIHJhbmdlIG9mIHVzZXJzOiAlZFxuIiwKKwkJ ICAgICAgIGxrdWwuYXV0aG9yaXR5Lndobyk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKwlpZiAo bGt1bC5hdXRob3JpdHkuU1VNKSB7CisJCXByX2VycigiJXMgbm90IHN1cHBvcnRlZCBpbiBTVU0u IFVzZSBzZXR1cCBsb2NraW5nIHJhbmdlXG4iLAorCQkgICAgICAgX19mdW5jX18pOworCQlyZXR1 cm4gLUVJTlZBTDsKKwl9CisKKwlyZXR1cm4gYWRkX3VzZXJfbHJfaW50ZXJuYWwoYmRldiwgJmxr dWwpOworfQorRVhQT1JUX1NZTUJPTChvcGFsX2FkZF91c2VyX3RvX2xyKTsKKworaW50IG9wYWxf cmV2ZXJ0dHBlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5 KQoreworCXN0cnVjdCBvcGFsX2tleSBrOworCisJaWYgKGNvcHlfZnJvbV91c2VyKCZrLCBrZXkt Pm9wYWwsIHNpemVvZigqa2V5LT5vcGFsKSkpCisJCXJldHVybiAtRUZBVUxUOworCisJcmV0dXJu IG9wYWxfcmV2ZXJ0KGJkZXYsICZrKTsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF9yZXZlcnR0cGVy KTsKKworaW50IG9wYWxfbG9ja191bmxvY2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3Ry dWN0IHNlZF9rZXkgKmtleSkKK3sKKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayBrOworCisJaWYg KGNvcHlfZnJvbV91c2VyKCZrLCBrZXktPm9wYWxfbGtfdW5saywgc2l6ZW9mKCprZXktPm9wYWxf bGtfdW5saykpKQorCQlyZXR1cm4gLUVGQVVMVDsKKworCWlmIChrLmF1dGhvcml0eS53aG8gPCBP UEFMX0FETUlOMSB8fCBrLmF1dGhvcml0eS53aG8gPj0gT1BBTF9VU0VSOSkKKwkJcmV0dXJuIC1F SU5WQUw7CisKKwlyZXR1cm4gbG9ja191bmxvY2tfaW50ZXJuYWwoYmRldiwgJmspOworfQorRVhQ T1JUX1NZTUJPTChvcGFsX2xvY2tfdW5sb2NrKTsKKworaW50IG9wYWxfdGFrZV9vd25lcnNoaXAo c3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlzdHJ1 Y3Qgb3BhbF9rZXkgazsKKwljb25zdCBvcGFsX3N0ZXAgb3duZXJfZnVuY3NbXSA9IHsKKwkJb3Bh bF9kaXNjb3ZlcnkwLAorCQlzdGFydF9hbnlib2R5QVNQX29wYWxfc2Vzc2lvbiwKKwkJZ2V0X21z aWRfY3Bpbl9waW4sCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCXN0YXJ0X1NJREFTUF9vcGFsX3Nl c3Npb24sCisJCXNldF9zaWRfY3Bpbl9waW4sCisJCWVuZF9vcGFsX3Nlc3Npb24sCisJCU5VTEwK Kwl9OworCisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7CisJCXByX2VycigiQ2FuJ3Qg c2F2ZSBwYXNzd29yZCBmb3IgTlVMTCBibG9jayBkZXZpY2UuXG4iKTsKKwkJcmV0dXJuIC1FSU5W QUw7CisJfQorCisJaWYgKGNvcHlfZnJvbV91c2VyKCZrLCBrZXktPm9wYWwsIHNpemVvZigqa2V5 LT5vcGFsKSkpCisJCXJldHVybiAtRUZBVUxUOworCisJcmV0dXJuIG9wYWxfcmVnaXN0ZXIoYmRl diwgJmssIG93bmVyX2Z1bmNzKTsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF90YWtlX293bmVyc2hp cCk7CisKK2ludCBvcGFsX2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBz dHJ1Y3Qgc2VkX2tleSAqa2V5KQoreworCXN0cnVjdCBvcGFsX2tleSBrOworCWNvbnN0IG9wYWxf c3RlcCBhY3RpdmVfZnVuY3NbXSA9IHsKKwkJb3BhbF9kaXNjb3ZlcnkwLAorCQlzdGFydF9TSURB U1Bfb3BhbF9zZXNzaW9uLCAvKiBPcGVuIHNlc3Npb24gYXMgU0lEIGF1dGggKi8KKwkJZ2V0X2xz cF9saWZlY3ljbGUsCisJCWFjdGl2YXRlX2xzcCwKKwkJZW5kX29wYWxfc2Vzc2lvbiwKKwkJTlVM TAorCX07CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2spIHsKKwkJcHJfZXJyKCJDYW4n dCBzYXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmljZS5cbiIpOworCQlyZXR1cm4gLUVJ TlZBTDsKKwl9CisKKwlpZiAoY29weV9mcm9tX3VzZXIoJmssIGtleS0+b3BhbCwgc2l6ZW9mKCpr ZXktPm9wYWwpKSkKKwkJcmV0dXJuIC1FRkFVTFQ7CisKKwlyZXR1cm4gb3BhbF9hY3RfbHNwX2lu dChiZGV2LCAmaywgYWN0aXZlX2Z1bmNzKTsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF9hY3RpdmF0 ZV9sc3ApOworCitpbnQgb3BhbF9zZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZp Y2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICpwdykKK3sKKwlzdHJ1Y3Qgb3BhbF91c2VyX2xyX3Nl dHVwIGs7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2spIHsKKwkJcHJfZXJyKCJDYW4n dCBzYXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmljZS5cbiIpOworCQlyZXR1cm4gLUVJ TlZBTDsKKwl9CisKKwlpZiAoY29weV9mcm9tX3VzZXIoJmssIHB3LT5vcGFsX2xycywgc2l6ZW9m KCpwdy0+b3BhbF9scnMpKSkKKwkJcmV0dXJuIC1FRkFVTFQ7CisKKwlyZXR1cm4gaW50ZXJuYWxf c2V0dXBfbHIoYmRldiwgJmspOworfQorCitpbnQgb3BhbF9zZXRfbmV3X3B3KHN0cnVjdCBibG9j a19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICpwdykKK3sKKwlzdHJ1Y3Qgb3BhbF9uZXdf cHcgazsKKworCWlmIChwdy0+c2VkX3R5cGUgIT0gT1BBTF9QVykKKwkJcmV0dXJuIC1FSU5WQUw7 CisKKwlpZiAoY29weV9mcm9tX3VzZXIoJmssIHB3LT5vcGFsX3B3LCBzaXplb2YoKnB3LT5vcGFs X3B3KSkpCisJCXJldHVybiAtRUZBVUxUOworCisJaWYgKGsud2hvLndobyA8IE9QQUxfQURNSU4x IHx8IGsud2hvLndobyA+IE9QQUxfVVNFUjkpCisJCXJldHVybiAtRUlOVkFMOworCisJcmV0dXJu IG9wYWxfc2V0X3B3KGJkZXYsICZrKTsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF9zZXRfbmV3X3B3 KTsKKworaW50IG9wYWxfYWN0aXZhdGVfdXNlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBz dHJ1Y3Qgc2VkX2tleSAqcHcpCit7CisJc3RydWN0IG9wYWxfYWN0aXZhdGVfdXNlciBrOworCisJ aWYgKHB3LT5zZWRfdHlwZSAhPSBPUEFMX0FDVF9VU1IpIHsKKwkJcHJfZXJyKCJTZWQgdHlwZSB3 YXMgbm90IGFjdCB1c2VyXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJaWYgKGNvcHlf ZnJvbV91c2VyKCZrLCBwdy0+b3BhbF9hY3QsIHNpemVvZigqcHctPm9wYWxfYWN0KSkpIHsKKwkJ cHJfZXJyKCJjb3B5IGZyb20gdXNlciBlcnJvclxuIik7CisJCXJldHVybiAtRUZBVUxUOworCX0K KworCS8qIFdlIGNhbid0IGFjdGl2YXRlIEFkbWluMSBpdCdzIGFjdGl2ZSBhcyBtYW51ZmFjdHVy ZWQgKi8KKwlpZiAoay53aG8ud2hvIDwgT1BBTF9VU0VSMSAmJiBrLndoby53aG8gPiBPUEFMX1VT RVI5KSB7CisJCXByX2VycigiV2hvIHdhcyBub3QgYSB2YWxpZCB1c2VyOiAlZCBcbiIsIGsud2hv Lndobyk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCXJldHVybiBhY3RpdmF0ZV91c2VyKGJk ZXYsICZrKTsKKworfQorRVhQT1JUX1NZTUJPTChvcGFsX2FjdGl2YXRlX3VzZXIpOworCitpbnQg b3BhbF91bmxvY2tfZnJvbV9zdXNwZW5kKHN0cnVjdCBvcGFsX3N1c3BlbmRfdW5sayAqZGF0YSkK K3sKKwljb25zdCBjaGFyICpkaXNrbmFtZSA9IGRhdGEtPm5hbWU7CisJc3RydWN0IG9wYWxfZGV2 ICppdGVyLCAqZGV2ID0gTlVMTDsKKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpjb21wbGV0aW9u OworCXZvaWQgKmZ1bmNfZGF0YVszXSA9IHsgTlVMTCB9OworCWNvbnN0IG9wYWxfc3RlcCBfdW5s b2NrX2Z1bmNzX1NVTVtdID0geworCQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2F1dGhfb3Bh bF9zZXNzaW9uLAorCQlsb2NrX3VubG9ja19sb2NraW5nX3JhbmdlLAorCQllbmRfb3BhbF9zZXNz aW9uLAorCQlOVUxMCisJfTsKKwljb25zdCBvcGFsX3N0ZXAgX3VubG9ja19mdW5jc1tdID0gewor CQlvcGFsX2Rpc2NvdmVyeTAsCisJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAorCQlsb2NrX3Vu bG9ja19sb2NraW5nX3JhbmdlLAorCQllbmRfb3BhbF9zZXNzaW9uLAorCQlOVUxMCisJfTsKKwor CisJc3Bpbl9sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGl0ZXIs ICZvcGFsX2xpc3QsIG5vZGUpIHsKKwkJaWYgKHN0cm5jbXAoaXRlci0+ZGlza19uYW1lLCBkaXNr bmFtZSwgRElTS19OQU1FX0xFTikpIHsKKwkJCXByX2VycigiaXRlcmRpc2sgd2FzICVzIGFuZCBk aXNrbmFtZSBpcyAlc1xuIiwKKwkJCSAgICAgICBpdGVyLT5kaXNrX25hbWUsIGRpc2tuYW1lKTsK KwkJCWNvbnRpbnVlOworCQl9CisJCWlmIChhdG9taWNfYWRkX3VubGVzcygmaXRlci0+aW5fdXNl LCAxLCAxKSkgeworCQkJZGV2ID0gaXRlcjsKKwkJCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRh OworCQkJZGV2LT5yZXN1bWVfZnJvbV9zdXNwZW5kID0gdHJ1ZTsKKwkJCWRldi0+cmVzdW1lX2Rh dGEgPSBkYXRhOworCQkJZGV2LT5maW5hbF9jYiA9IHVubG9ja19zdXNwZW5kX2ZpbmFsOworCQkJ ZGV2LT5maW5hbF9jYl9kYXRhID0gZGV2OworCQkJZGV2LT5lcnJvcl9jYiA9IGVuZF9vcGFsX3Nl c3Npb25fZXJyb3I7CisJCQlkZXYtPmVycm9yX2NiX2RhdGEgPSBkZXY7CisJCQlkZXYtPnN0YXRl ID0gMDsKKwkJCWlmIChkZXYtPmxrdWwuYXV0aG9yaXR5LlNVTSkKKwkJCQlkZXYtPmZ1bmNzID0g X3VubG9ja19mdW5jc19TVU07CisJCQllbHNlCisJCQkJZGV2LT5mdW5jcyA9IF91bmxvY2tfZnVu Y3M7CisJCQlkZXYtPlRTTiA9IDA7CisJCQlkZXYtPkhTTiA9IDA7CisJCQlkZXYtPmZ1bmNfZGF0 YVsyXSA9ICZkZXYtPmxrdWw7CisJCQlkZXYtPmZ1bmNfZGF0YVsxXSA9ICZkZXYtPmxrdWwuYXV0 aG9yaXR5OworCQkJY29tcGxldGlvbiA9IGRldi0+Y29tcGxldGlvbjsKKwkJCW5leHQoMCwgZGV2 KTsKKwkJCXdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24pOworCQl9CisJfQorCXNw aW5fdW5sb2NrKCZsaXN0X3NwaW5sb2NrKTsKKworCWlmICghZGV2KQorCQlyZXR1cm4gLUVOT0RF VjsKKwlyZXR1cm4gMDsKK30KK0VYUE9SVF9TWU1CT0wob3BhbF91bmxvY2tfZnJvbV9zdXNwZW5k KTsKZGlmZiAtLWdpdCBhL2xpYi9zZWQtb3BhbF9pbnRlcm5hbC5oIGIvbGliL3NlZC1vcGFsX2lu dGVybmFsLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uYzlkMzg4MwotLS0g L2Rldi9udWxsCisrKyBiL2xpYi9zZWQtb3BhbF9pbnRlcm5hbC5oCkBAIC0wLDAgKzEsNTg2IEBA CisvKgorICogQ29weXJpZ2h0IMKpIDIwMTYgSW50ZWwgQ29ycG9yYXRpb24KKyAqCisgKiBQZXJt aXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBv YnRhaW5pbmcgYQorICogY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3Vt ZW50YXRpb24gZmlsZXMgKHRoZSAiU29mdHdhcmUiKSwKKyAqIHRvIGRlYWwgaW4gdGhlIFNvZnR3 YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24KKyAq IHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmli dXRlLCBzdWJsaWNlbnNlLAorICogYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwg YW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlCisgKiBTb2Z0d2FyZSBpcyBmdXJuaXNo ZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgorICoKKyAq IFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIChp bmNsdWRpbmcgdGhlIG5leHQKKyAqIHBhcmFncmFwaCkgc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxs IGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUKKyAqIFNvZnR3YXJlLgorICoK KyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9G IEFOWSBLSU5ELCBFWFBSRVNTIE9SCisgKiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1J VEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKKyAqIEZJVE5FU1MgRk9S IEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuICBJTiBOTyBFVkVOVCBT SEFMTAorICogVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBB TlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBB Q1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HCisgKiBGUk9NLCBP VVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9U SEVSIERFQUxJTkdTCisgKiBJTiBUSEUgU09GVFdBUkUuCisgKgorICogQXV0aG9yOgorICogICAg UmFmYWVsIEFudG9nbm9sbGkgPHJhZmFlbC5hbnRvZ25vbGxpQGludGVsLmNvbT4KKyAqICAgIFNj b3R0ICBCYXVlciAgICAgIDxzY290dC5iYXVlckBpbnRlbC5jb20+CisgKi8KKworI2lmbmRlZiBf TlZNRV9PUEFMX0lOVEVSTkFMX0gKKyNkZWZpbmUgX05WTUVfT1BBTF9JTlRFUk5BTF9ICisKKyNp bmNsdWRlIDxsaW51eC9rZXktdHlwZS5oPgorI2luY2x1ZGUgPGtleXMvdXNlci10eXBlLmg+CisK KyNkZWZpbmUgRFRBRVJST1JfTk9fTUVUSE9EX1NUQVRVUyAweDg5CisKK3N0YXRpYyBjb25zdCBj aGFyICpvcGFsX2Vycm9yc1sxOV0gPSB7CisJIlN1Y2Nlc3MiLAorCSJOb3QgQXV0aG9yaXplZCIs CisJIlVua25vd24gRXJyb3IiLAorCSJTUCBCdXN5IiwKKwkiU1AgRmFpbGVkIiwKKwkiU1AgRGlz YWJsZWQiLAorCSJTUCBGcm96ZW4iLAorCSJObyBTZXNzaW9ucyBBdmFpbGFibGUiLAorCSJVbmlx dWVuZXNzIENvbmZsaWN0IiwKKwkiSW5zdWZmaWNpZW50IFNwYWNlIiwKKwkiSW5zdWZmaWNpZW50 IFJvd3MiLAorCSJJbnZhbGlkIEZ1bmN0aW9uIiwKKwkiSW52YWxpZCBQYXJhbWV0ZXIiLAorCSJJ bnZhbGlkIFJlZmVyZW5jZSIsCisJIlVua25vd24gRXJyb3IiLAorCSJUUEVSIE1hbGZ1bmN0aW9u IiwKKwkiVHJhbnNhY3Rpb24gRmFpbHVyZSIsCisJIlJlc3BvbnNlIE92ZXJmbG93IiwKKwkiQXV0 aG9yaXR5IExvY2tlZCBPdXQiLAorfTsKKworc3RhdGljIGNvbnN0IGNoYXIgKm9wYWxfZXJyb3Jf dG9faHVtYW4oaW50IGVycm9yKQoreworCWlmIChlcnJvciA9PSAweDNmKQorCQlyZXR1cm4gIkZh aWxlZCI7CisKKwlpZiAoZXJyb3IgPj0gc2l6ZW9mKG9wYWxfZXJyb3JzKSB8fCBlcnJvciA8IDAp CisJCXJldHVybiAiVW5rbm93biBFcnJvciI7CisKKwlyZXR1cm4gb3BhbF9lcnJvcnNbZXJyb3Jd OworfQorCisvKiBVc2VyIElEcyB1c2VkIGluIHRoZSBUQ0cgc3RvcmFnZSBTU0NzICovCitzdGF0 aWMgY29uc3QgdTggT1BBTFVJRFtdWzhdID0geworCS8qIHVzZXJzICovCisKKwkvKiBzZXNzaW9u IG1hbmFnZW1lbnQgICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw eDAwLCAweGZmfSwKKwkvKiBzcGVjaWFsICJ0aGlzU1AiIHN5bnRheCAqLworCXsgMHgwMCwgMHgw MCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMSB9LAorCS8qIEFkbWluaXN0cmF0 aXZlIFNQICovCisJeyAweDAwLCAweDAwLCAweDAyLCAweDA1LCAweDAwLCAweDAwLCAweDAwLCAw eDAxIH0sCisJLyogTG9ja2luZyBTUCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMiwgMHgwNSwgMHgw MCwgMHgwMCwgMHgwMCwgMHgwMiB9LAorCS8qIEVOVEVSUFJJU0UgTG9ja2luZyBTUCAgKi8KKwl7 IDB4MDAsIDB4MDAsIDB4MDIsIDB4MDUsIDB4MDAsIDB4MDEsIDB4MDAsIDB4MDEgfSwKKwkvKiBh bnlib2R5ICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAwLCAweDAwLCAw eDAxIH0sCisJLyogU0lEICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAw LCAweDAwLCAweDA2IH0sCisJLyogQURNSU4xICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA5 LCAweDAwLCAweDAxLCAweDAwLCAweDAxIH0sCisJLyogVVNFUjEgKi8KKwl7IDB4MDAsIDB4MDAs IDB4MDAsIDB4MDksIDB4MDAsIDB4MDMsIDB4MDAsIDB4MDEgfSwKKwkvKiBVU0VSMiAqLworCXsg MHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMywgMHgwMCwgMHgwMiB9LAorCS8qIFBT SUQgdXNlciAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMSwgMHhmZiwg MHgwMSB9LAorCS8qIEJhbmRNYXN0ZXIgMCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwg MHgwMCwgMHgwMCwgMHg4MCwgMHgwMSB9LAorCSAvKiBFcmFzZU1hc3RlciAqLworCXsgMHgwMCwg MHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMCwgMHg4NCwgMHgwMSB9LAorCisJLyogdGFibGVz ICovCisKKwkvKiBMb2NraW5nX0dsb2JhbFJhbmdlICovCisJeyAweDAwLCAweDAwLCAweDA4LCAw eDAyLCAweDAwLCAweDAwLCAweDAwLCAweDAxIH0sCisJLyogQUNFX0xvY2tpbmdfUmFuZ2VfU2V0 X1JkTG9ja2VkIFVJRCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOCwgMHgwMCwgMHgwMywg MHhFMCwgMHgwMSB9LAorCS8qIEFDRV9Mb2NraW5nX1JhbmdlX1NldF9XckxvY2tlZCBVSUQgKi8K Kwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDgsIDB4MDAsIDB4MDMsIDB4RTgsIDB4MDEgfSwKKwkv KiBNQlIgQ29udHJvbCAqLworCXsgMHgwMCwgMHgwMCwgMHgwOCwgMHgwMywgMHgwMCwgMHgwMCwg MHgwMCwgMHgwMSB9LAorCS8qIFNoYWRvdyBNQlIgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDgsIDB4 MDQsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAgfSwKKwkvKiBBVVRIT1JJVFlfVEFCTEUgKi8KKwl7 IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDB9LAorCS8qIENf UElOX1RBQkxFICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDBCLCAweDAwLCAweDAwLCAweDAw LCAweDAwfSwKKwkvKiBPUEFMIExvY2tpbmcgSW5mbyAqLworCXsgMHgwMCwgMHgwMCwgMHgwOCwg MHgwMSwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMSB9LAorCS8qIEVudGVycHJpc2UgTG9ja2luZyBJ bmZvICovCisJeyAweDAwLCAweDAwLCAweDA4LCAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAw IH0sCisKKwkvKiBDX1BJTl9UQUJMRSBvYmplY3QgSUQncyAqLworCisJLyogQ19QSU5fTVNJRCAq LworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwQiwgMHgwMCwgMHgwMCwgMHg4NCwgMHgwMn0sCisJ LyogQ19QSU5fU0lEICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDBCLCAweDAwLCAweDAwLCAw eDAwLCAweDAxfSwKKwkgLyogQ19QSU5fQURNSU4xICovCisJeyAweDAwLCAweDAwLCAweDAwLCAw eDBCLCAweDAwLCAweDAxLCAweDAwLCAweDAxfSwKKworCS8qIGhhbGYgVUlEJ3MgKG9ubHkgZmly c3QgNCBieXRlcyB1c2VkKSAqLworCisJLyogSGFsZi1VSUQg4oCTIEF1dGhvcml0eV9vYmplY3Rf cmVmICovCisJeyAweDAwLCAweDAwLCAweDBDLCAweDA1LCAweGZmLCAweGZmLCAweGZmLCAweGZm IH0sCisJLyogSGFsZi1VSUQg4oCTIEJvb2xlYW4gQUNFICovCisJeyAweDAwLCAweDAwLCAweDA0 LCAweDBFLCAweGZmLCAweGZmLCAweGZmLCAweGZmIH0sCisKKwkvKiBzcGVjaWFsIHZhbHVlIGZv ciBvbWl0dGVkIG9wdGlvbmFsIHBhcmFtZXRlciAqLworCisJLyogSEVYRkYgZm9yIG9taXR0ZWQg Ki8KKwl7IDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmZ9LAor fTsKK3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9VSURfTEVOR1RIID0gODsKK3N0YXRpYyBjb25z dCBzaXplX3QgT1BBTF9NU0lEX0tFWUxFTiA9IDE1Oworc3RhdGljIGNvbnN0IHNpemVfdCBPUEFM X1VJRF9MRU5HVEhfSEFMRiA9IDQ7CisKKworLyogRW51bSB0byBpbmRleCBPUEFMVUlEIGFycmF5 ICovCitlbnVtIE9QQUxfVUlEIHsKKwkvKiB1c2VycyAqLworCU9QQUxfU01VSURfVUlELAorCU9Q QUxfVEhJU1NQX1VJRCwKKwlPUEFMX0FETUlOU1BfVUlELAorCU9QQUxfTE9DS0lOR1NQX1VJRCwK KwlPUEFMX0VOVEVSUFJJU0VfTE9DS0lOR1NQX1VJRCwKKwlPUEFMX0FOWUJPRFlfVUlELAorCU9Q QUxfU0lEX1VJRCwKKwlPUEFMX0FETUlOMV9VSUQsCisJT1BBTF9VU0VSMV9VSUQsCisJT1BBTF9V U0VSMl9VSUQsCisJT1BBTF9QU0lEX1VJRCwKKwlPUEFMX0VOVEVSUFJJU0VfQkFORE1BU1RFUjBf VUlELAorCU9QQUxfRU5URVJQUklTRV9FUkFTRU1BU1RFUl9VSUQsCisJLyogdGFibGVzICovCisJ T1BBTF9MT0NLSU5HUkFOR0VfR0xPQkFMLAorCU9QQUxfTE9DS0lOR1JBTkdFX0FDRV9SRExPQ0tF RCwKKwlPUEFMX0xPQ0tJTkdSQU5HRV9BQ0VfV1JMT0NLRUQsCisJT1BBTF9NQlJDT05UUk9MLAor CU9QQUxfTUJSLAorCU9QQUxfQVVUSE9SSVRZX1RBQkxFLAorCU9QQUxfQ19QSU5fVEFCTEUsCisJ T1BBTF9MT0NLSU5HX0lORk9fVEFCTEUsCisJT1BBTF9FTlRFUlBSSVNFX0xPQ0tJTkdfSU5GT19U QUJMRSwKKwkvKiBDX1BJTl9UQUJMRSBvYmplY3QgSUQncyAqLworCU9QQUxfQ19QSU5fTVNJRCwK KwlPUEFMX0NfUElOX1NJRCwKKwlPUEFMX0NfUElOX0FETUlOMSwKKwkvKiBoYWxmIFVJRCdzIChv bmx5IGZpcnN0IDQgYnl0ZXMgdXNlZCkgKi8KKwlPUEFMX0hBTEZfVUlEX0FVVEhPUklUWV9PQkpf UkVGLAorCU9QQUxfSEFMRl9VSURfQk9PTEVBTl9BQ0UsCisJLyogb21pdHRlZCBvcHRpb25hbCBw YXJhbWV0ZXIgKi8KKwlPUEFMX1VJRF9IRVhGRiwKK307CisKKy8qCisgKiBUQ0cgU3RvcmFnZSBT U0MgTWV0aG9kcy4KKyAqLworc3RhdGljIGNvbnN0IHU4IE9QQUxNRVRIT0RbXVs4XSA9IHsKKwkv KiBQcm9wZXJ0aWVzICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw eGZmLCAweDAxIH0sCisJLyogU1RBUlRTRVNTSU9OICovCisJeyAweDAwLCAweDAwLCAweDAwLCAw eDAwLCAweDAwLCAweDAwLCAweGZmLCAweDAyIH0sCisJLyogUmV2ZXJ0ICovCisJeyAweDAwLCAw eDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAyLCAweDAyIH0sCisJLyogQWN0aXZhdGUg Ki8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDIsIDB4MDMgfSwK KwkvKiBFbnRlcnByaXNlIEdldCAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwg MHgwMCwgMHgwMCwgMHgwNiB9LAorCS8qIEVudGVycHJpc2UgU2V0ICovCisJeyAweDAwLCAweDAw LCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDA3IH0sCisJLyogTkVYVCAqLworCXsg MHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOCB9LAorCS8qIEVu dGVycHJpc2UgQXV0aGVudGljYXRlICovCisJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAw LCAweDAwLCAweDAwLCAweDBjIH0sCisJLyogR2V0QUNMICovCisJeyAweDAwLCAweDAwLCAweDAw LCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDBkIH0sCisJLyogR2VuS2V5ICovCisJeyAweDAw LCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDEwIH0sCisJLyogcmV2ZXJ0 U1AgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MTEg fSwKKwkvKiBHZXQgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4 MDAsIDB4MTYgfSwKKwkvKiBTZXQgKi8KKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAs IDB4MDAsIDB4MDAsIDB4MTcgfSwKKwkvKiBBdXRoZW50aWNhdGUgKi8KKwl7IDB4MDAsIDB4MDAs IDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MWMgfSwKKwkvKiBSYW5kb20gKi8KKwl7 IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDEgfSwKKwkvKiBF cmFzZSAqLworCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwOCwgMHgw MyB9LAorfTsKK3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9NRVRIT0RfTEVOR1RIID0gODsKKwor LyogRW51bSBmb3IgaW5kZXhpbmcgdGhlIE9QQUxNRVRIT0QgYXJyYXkgKi8KK2VudW0gT1BBTF9N RVRIT0QgeworCU9QQUxfUFJPUEVSVElFUywKKwlPUEFMX1NUQVJUU0VTU0lPTiwKKwlPUEFMX1JF VkVSVCwKKwlPUEFMX0FDVElWQVRFLAorCU9QQUxfRUdFVCwKKwlPUEFMX0VTRVQsCisJT1BBTF9O RVhULAorCU9QQUxfRUFVVEhFTlRJQ0FURSwKKwlPUEFMX0dFVEFDTCwKKwlPUEFMX0dFTktFWSwK KwlPUEFMX1JFVkVSVFNQLAorCU9QQUxfR0VULAorCU9QQUxfU0VULAorCU9QQUxfQVVUSEVOVElD QVRFLAorCU9QQUxfUkFORE9NLAorCU9QQUxfRVJBU0UsCit9OworCitlbnVtIE9QQUxfUkVTUE9O U0VfVE9LRU4geworCU9QQUxfRFRBX1RPS0VOSURfQllURVNUUklORyA9IDB4ZTAsCisJT1BBTF9E VEFfVE9LRU5JRF9TSU5UID0gMHhlMSwKKwlPUEFMX0RUQV9UT0tFTklEX1VJTlQgPSAweGUyLAor CU9QQUxfRFRBX1RPS0VOSURfVE9LRU4gPSAweGUzLCAvKiBhY3R1YWwgdG9rZW4gaXMgcmV0dXJu ZWQgKi8KKwlPUEFMX0RUQV9UT0tFTklEX0lOVkFMSUQgPSAwWDAKK307CisKK2VudW0gT1BBTF9U T0tFTiB7CisJLyogQm9vbGVhbiAqLworCU9QQUxfVFJVRSA9IDB4MDEsCisJT1BBTF9GQUxTRSA9 IDB4MDAsCisJT1BBTF9CT09MRUFOX0VYUFIgPSAweDAzLAorCS8qIGNlbGxibG9ja3MgKi8KKwlP UEFMX1RBQkxFID0gMHgwMCwKKwlPUEFMX1NUQVJUUk9XID0gMHgwMSwKKwlPUEFMX0VORFJPVyA9 IDB4MDIsCisJT1BBTF9TVEFSVENPTFVNTiA9IDB4MDMsCisJT1BBTF9FTkRDT0xVTU4gPSAweDA0 LAorCU9QQUxfVkFMVUVTID0gMHgwMSwKKwkvKiBhdXRob3JpdHkgdGFibGUgKi8KKwlPUEFMX1BJ TiA9IDB4MDMsCisJLyogbG9ja2luZyB0b2tlbnMgKi8KKwlPUEFMX1JBTkdFU1RBUlQgPSAweDAz LAorCU9QQUxfUkFOR0VMRU5HVEggPSAweDA0LAorCU9QQUxfUkVBRExPQ0tFTkFCTEVEID0gMHgw NSwKKwlPUEFMX1dSSVRFTE9DS0VOQUJMRUQgPSAweDA2LAorCU9QQUxfUkVBRExPQ0tFRCA9IDB4 MDcsCisJT1BBTF9XUklURUxPQ0tFRCA9IDB4MDgsCisJT1BBTF9BQ1RJVkVLRVkgPSAweDBBLAor CS8qIGxvY2tpbmcgaW5mbyB0YWJsZSAqLworCU9QQUxfTUFYUkFOR0VTID0gMHgwNCwKKwkgLyog bWJyIGNvbnRyb2wgKi8KKwlPUEFMX01CUkVOQUJMRSA9IDB4MDEsCisJT1BBTF9NQlJET05FID0g MHgwMiwKKwkvKiBwcm9wZXJ0aWVzICovCisJT1BBTF9IT1NUUFJPUEVSVElFUyA9IDB4MDAsCisJ LyogYXRvbXMgKi8KKwlPUEFMX1NUQVJUTElTVCA9IDB4ZjAsCisJT1BBTF9FTkRMSVNUID0gMHhm MSwKKwlPUEFMX1NUQVJUTkFNRSA9IDB4ZjIsCisJT1BBTF9FTkROQU1FID0gMHhmMywKKwlPUEFM X0NBTEwgPSAweGY4LAorCU9QQUxfRU5ET0ZEQVRBID0gMHhmOSwKKwlPUEFMX0VORE9GU0VTU0lP TiA9IDB4ZmEsCisJT1BBTF9TVEFSVFRSQU5TQUNUT04gPSAweGZiLAorCU9QQUxfRU5EVFJBTlNB Q1RPTiA9IDB4ZkMsCisJT1BBTF9FTVBUWUFUT00gPSAweGZmLAorCU9QQUxfV0hFUkUgPSAweDAw LAorfTsKKworLyogVXNlZnVsIHRpbnkgYXRvbXMuCisgKiBVc2VmdWwgZm9yIHRhYmxlIGNvbHVt bnMgZXRjCisgKi8KK2VudW0gT1BBTF9USU5ZX0FUT00geworCU9QQUxfVElOWV9VSU5UXzAwID0g MHgwMCwKKwlPUEFMX1RJTllfVUlOVF8wMSA9IDB4MDEsCisJT1BBTF9USU5ZX1VJTlRfMDIgPSAw eDAyLAorCU9QQUxfVElOWV9VSU5UXzAzID0gMHgwMywKKwlPUEFMX1RJTllfVUlOVF8wNCA9IDB4 MDQsCisJT1BBTF9USU5ZX1VJTlRfMDUgPSAweDA1LAorCU9QQUxfVElOWV9VSU5UXzA2ID0gMHgw NiwKKwlPUEFMX1RJTllfVUlOVF8wNyA9IDB4MDcsCisJT1BBTF9USU5ZX1VJTlRfMDggPSAweDA4 LAorCU9QQUxfVElOWV9VSU5UXzA5ID0gMHgwOSwKKwlPUEFMX1RJTllfVUlOVF8xMCA9IDB4MGEs CisJT1BBTF9USU5ZX1VJTlRfMTEgPSAweDBiLAorCU9QQUxfVElOWV9VSU5UXzEyID0gMHgwYywK KwlPUEFMX1RJTllfVUlOVF8xMyA9IDB4MGQsCisJT1BBTF9USU5ZX1VJTlRfMTQgPSAweDBlLAor CU9QQUxfVElOWV9VSU5UXzE1ID0gMHgwZiwKK307CisKK2VudW0gT1BBTF9BVE9NX1dJRFRIIHsK KwlPUEFMX1dJRFRIX1RJTlksCisJT1BBTF9XSURUSF9TSE9SVCwKKwlPUEFMX1dJRFRIX01FRElV TSwKKwlPUEFMX1dJRFRIX0xPTkcsCisJT1BBTF9XSURUSF9UT0tFTgorfTsKKworLyogTG9ja2lu ZyBzdGF0ZSBmb3IgYSBsb2NraW5nIHJhbmdlICovCitlbnVtIE9QQUxfTE9DS0lOR1NUQVRFIHsK KwlPUEFMX0xPQ0tJTkdfUkVBRFdSSVRFID0gMHgwMSwKKwlPUEFMX0xPQ0tJTkdfUkVBRE9OTFkg PSAweDAyLAorCU9QQUxfTE9DS0lOR19MT0NLRUQgPSAweDAzLAorfTsKKworLyoKKyAqIFN0cnVj dHVyZXMgdG8gYnVpbGQgYW5kIGRlY29kZSB0aGUgT3BhbCBTU0MgbWVzc2FnZXMKKyAqIGZpZWxk cyB0aGF0IGFyZSBOT1QgcmVhbGx5IG51bWVyaWMgYXJlIGRlZmluZWQgYXMgdThbXSB0bworICog aGVscCByZWR1Y2UgdGhlIGVuZGlhbm5lc3MgaXNzdWVzCisgKi8KKworLyogQ29tbSBQYWNrZXQg KGhlYWRlcikgZm9yIHRyYW5zbWlzc2lvbnMuICovCitzdHJ1Y3Qgb3BhbF9jb21wYWNrZXQgewor CXUzMiByZXNlcnZlZDA7CisJdTggZXh0ZW5kZWRDb21JRFs0XTsKKwl1MzIgb3V0c3RhbmRpbmdE YXRhOworCXUzMiBtaW5UcmFuc2ZlcjsKKwl1MzIgbGVuZ3RoOworfTsKKworLyogUGFja2V0IHN0 cnVjdHVyZS4gKi8KK3N0cnVjdCBvcGFsX3BhY2tldCB7CisJdTMyIFRTTjsKKwl1MzIgSFNOOwor CXUzMiBzZXFfbnVtYmVyOworCXUxNiByZXNlcnZlZDA7CisJdTE2IGFja190eXBlOworCXUzMiBh Y2tub3dsZWRnbWVudDsKKwl1MzIgbGVuZ3RoOworfTsKKworLyogRGF0YSBzdWIgcGFja2V0IGhl YWRlciAqLworc3RydWN0IG9wYWxfZGF0YV9zdWJwYWNrZXQgeworCXU4IHJlc2VydmVkMFs2XTsK Kwl1MTYga2luZDsKKwl1MzIgbGVuZ3RoOworfTsKKworLyogaGVhZGVyIG9mIGEgcmVzcG9uc2Ug Ki8KK3N0cnVjdCBvcGFsX2hlYWRlciB7CisJc3RydWN0IG9wYWxfY29tcGFja2V0IGNwOworCXN0 cnVjdCBvcGFsX3BhY2tldCBwa3Q7CisJc3RydWN0IG9wYWxfZGF0YV9zdWJwYWNrZXQgc3VicGt0 OworfTsKKworI2RlZmluZSBGQ19UUEVSICAgICAgIDB4MDAwMQorI2RlZmluZSBGQ19MT0NLSU5H ICAgIDB4MDAwMgorI2RlZmluZSBGQ19HRU9NRVRSWSAgIDB4MDAwMworI2RlZmluZSBGQ19FTlRF UlBSSVNFIDB4MDEwMAorI2RlZmluZSBGQ19EQVRBU1RPUkUgIDB4MDIwMgorI2RlZmluZSBGQ19T SU5HTEVVU0VSIDB4MDIwMQorI2RlZmluZSBGQ19PUEFMVjEwMCAgIDB4MDIwMAorI2RlZmluZSBG Q19PUEFMVjIwMCAgIDB4MDIwMworCisvKgorICogVGhlIERpc2NvdmVyeSAwIEhlYWRlci4gQXMg ZGVmaW5lZCBpbgorICogT3BhbCBTU0MgRG9jdW1lbnRhdGlvbgorICovCitzdHJ1Y3QgZDBfaGVh ZGVyIHsKKwl1MzIgbGVuZ3RoOyAvKiB0aGUgbGVuZ3RoIG9mIHRoZSBoZWFkZXIgNDggaW4gMi4w MC4xMDAgKi8KKwl1MzIgcmV2aXNpb247IC8qKjwgcmV2aXNpb24gb2YgdGhlIGhlYWRlciAxIGlu IDIuMDAuMTAwICovCisJdTMyIHJlc2VydmVkMDE7CisJdTMyIHJlc2VydmVkMDI7CisJLyoKKwkg KiB0aGUgcmVtYWluZGVyIG9mIHRoZSBzdHJ1Y3R1cmUgaXMgdmVuZG9yIHNwZWNpZmljIGFuZCB3 aWxsIG5vdCBiZQorCSAqIGFkZHJlc3NlZCBub3cKKwkgKi8KKwl1OCBpZ25vcmVkWzMyXTsKK307 CisKKy8qCisgKiBUUGVyIEZlYXR1cmUgRGVzY3JpcHRvci4gQ29udGFpbnMgZmxhZ3MgaW5kaWNh dGluZyBzdXBwb3J0IGZvciB0aGUKKyAqIFRQZXIgZmVhdHVyZXMgZGVzY3JpYmVkIGluIHRoZSBP UEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRjaCB0aGUKKyAqIE9QQUwgdGVybWlub2xv Z3kKKyAqCisgKiBjb2RlID09IDB4MDAxIGluIDIuMDAuMTAwCisgKi8KK3N0cnVjdCBkMF90cGVy X2ZlYXR1cmVzIHsKKwkvKgorCSAqIHN1cHBvcnRlZF9mZWF0dXJlcyBiaXRzOgorCSAqIGJpdCA3 OiByZXNlcnZlZAorCSAqIGJpdCA2OiBjb20gSUQgbWFuYWdlbWVudAorCSAqIGJpdCA1OiByZXNl cnZlZAorCSAqIGJpdCA0OiBzdHJlYW1pbmcgc3VwcG9ydAorCSAqIGJpdCAzOiBidWZmZXIgbWFu YWdlbWVudAorCSAqIGJpdCAyOiBBQ0svTkFDSworCSAqIGJpdCAxOiBhc3luYworCSAqIGJpdCAw OiBzeW5jCisJICovCisJdTggc3VwcG9ydGVkX2ZlYXR1cmVzOworCS8qCisJICogYnl0ZXMgNSB0 aHJvdWdoIDE1IGFyZSByZXNlcnZlZCwgYnV0IHdlIHJlcHJlc2VudCB0aGUgZmlyc3QgMyBhcwor CSAqIHU4IHRvIGtlZXAgdGhlIG90aGVyIHR3byAzMmJpdHMgaW50ZWdlcnMgYWxpZ25lZC4KKwkg Ki8KKwl1OCByZXNlcnZlZDAxWzNdOworCXUzMiByZXNlcnZlZDAyOworCXUzMiByZXNlcnZlZDAz OworfTsKKworLyoKKyAqIExvY2tpbmcgRmVhdHVyZSBEZXNjcmlwdG9yLiBDb250YWlucyBmbGFn cyBpbmRpY2F0aW5nIHN1cHBvcnQgZm9yIHRoZQorICogbG9ja2luZyBmZWF0dXJlcyBkZXNjcmli ZWQgaW4gdGhlIE9QQUwgc3BlY2lmaWNhdGlvbi4gVGhlIG5hbWVzIG1hdGNoIHRoZQorICogT1BB TCB0ZXJtaW5vbG9neQorICoKKyAqIGNvZGUgPT0gMHgwMDAyIGluIDIuMDAuMTAwCisgKi8KK3N0 cnVjdCBkMF9sb2NraW5nX2ZlYXR1cmVzIHsKKwkvKgorCSAqIHN1cHBvcnRlZF9mZWF0dXJlcyBi aXRzOgorCSAqIGJpdHMgNi03OiByZXNlcnZlZAorCSAqIGJpdCA1OiBNQlIgZG9uZQorCSAqIGJp dCA0OiBNQlIgZW5hYmxlZAorCSAqIGJpdCAzOiBtZWRpYSBlbmNyeXB0aW9uCisJICogYml0IDI6 IGxvY2tlZAorCSAqIGJpdCAxOiBsb2NraW5nIGVuYWJsZWQKKwkgKiBiaXQgMDogbG9ja2luZyBz dXBwb3J0ZWQKKwkgKi8KKwl1OCBzdXBwb3J0ZWRfZmVhdHVyZXM7CisJLyoKKwkgKiBieXRlcyA1 IHRocm91Z2ggMTUgYXJlIHJlc2VydmVkLCBidXQgd2UgcmVwcmVzZW50IHRoZSBmaXJzdCAzIGFz CisJICogdTggdG8ga2VlcCB0aGUgb3RoZXIgdHdvIDMyYml0cyBpbnRlZ2VycyBhbGlnbmVkLgor CSAqLworCXU4IHJlc2VydmVkMDFbM107CisJdTMyIHJlc2VydmVkMDI7CisJdTMyIHJlc2VydmVk MDM7Cit9OworCisvKgorICogR2VvbWV0cnkgRmVhdHVyZSBEZXNjcmlwdG9yLiBDb250YWlucyBm bGFncyBpbmRpY2F0aW5nIHN1cHBvcnQgZm9yIHRoZQorICogZ2VvbWV0cnkgZmVhdHVyZXMgZGVz Y3JpYmVkIGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRjaCB0aGUKKyAq IE9QQUwgdGVybWlub2xvZ3kKKyAqCisgKiBjb2RlID09IDB4MDAwMyBpbiAyLjAwLjEwMAorICov CitzdHJ1Y3QgZDBfZ2VvbWV0cnlfZmVhdHVyZXMgeworCS8qCisJICogc2tpcCAzMiBiaXRzIGZy b20gaGVhZGVyLCBuZWVkZWQgdG8gYWxpZ24gdGhlIHN0cnVjdCB0byA2NCBiaXRzLgorCSAqLwor CXU4IGhlYWRlcls0XTsKKwkvKgorCSAqIHJlc2VydmVkMDE6CisJICogYml0cyAxLTY6IHJlc2Vy dmVkCisJICogYml0IDA6IGFsaWduCisJICovCisJdTggcmVzZXJ2ZWQwMTsKKwl1OCByZXNlcnZl ZDAyWzddOworCXUzMiBsb2dpY2FsX2Jsb2NrX3NpemU7CisJdTY0IGFsaWdubWVudF9ncmFudWxh cml0eTsKKwl1NjQgbG93ZXN0X2FsaWduZWRfbGJhOworfTsKKworLyoKKyAqIEVudGVycHJpc2Ug U1NDIEZlYXR1cmUKKyAqCisgKiBjb2RlID09IDB4MDEwMAorICovCitzdHJ1Y3QgZDBfZW50ZXJw cmlzZV9zc2MgeworCXUxNiBiYXNlQ29tSUQ7CisJdTE2IG51bUNvbUlEczsKKwkvKiByYW5nZV9j cm9zc2luZzoKKwkgKiBiaXRzIDEtNjogcmVzZXJ2ZWQKKwkgKiBiaXQgMDogcmFuZ2UgY3Jvc3Np bmcKKwkgKi8KKwl1OCByYW5nZV9jcm9zc2luZzsKKwl1OCByZXNlcnZlZDAxOworCXUxNiByZXNl cnZlZDAyOworCXUzMiByZXNlcnZlZDAzOworCXUzMiByZXNlcnZlZDA0OworfTsKKworLyoKKyAq IE9wYWwgVjEgZmVhdHVyZQorICoKKyAqIGNvZGUgPT0gMHgwMjAwCisgKi8KK3N0cnVjdCBkMF9v cGFsX3YxMDAgeworCXUxNiBiYXNlQ29tSUQ7CisJdTE2IG51bUNvbUlEczsKK307CisKKy8qCisg KiBTaW5nbGUgVXNlciBNb2RlIGZlYXR1cmUKKyAqCisgKiBjb2RlID09IDB4MDIwMQorICovCitz dHJ1Y3QgZDBfc2luZ2xlX3VzZXJfbW9kZSB7CisJdTMyIG51bV9sb2NraW5nX29iamVjdHM7CisJ LyogcmVzZXJ2ZWQwMToKKwkgKiBiaXQgMDogYW55CisJICogYml0IDE6IGFsbAorCSAqIGJpdCAy OiBwb2xpY3kKKwkgKiBiaXRzIDMtNzogcmVzZXJ2ZWQKKwkgKi8KKwl1OCByZXNlcnZlZDAxOwor CXU4IHJlc2VydmVkMDI7CisJdTE2IHJlc2VydmVkMDM7CisJdTMyIHJlc2VydmVkMDQ7Cit9Owor CisvKgorICogQWRkaXRvbmFsIERhdGFzdG9yZXMgZmVhdHVyZQorICoKKyAqIGNvZGUgPT0gMHgw MjAyCisgKi8KK3N0cnVjdCBkMF9kYXRhc3RvcmVfdGFibGUgeworCXUxNiByZXNlcnZlZDAxOwor CXUxNiBtYXhfdGFibGVzOworCXUzMiBtYXhfc2l6ZV90YWJsZXM7CisJdTMyIHRhYmxlX3NpemVf YWxpZ25tZW50OworfTsKKworLyoKKyAqIE9QQUwgMi4wIGZlYXR1cmUKKyAqCisgKiBjb2RlID09 IDB4MDIwMworICovCitzdHJ1Y3QgZDBfb3BhbF92MjAwIHsKKwl1MTYgYmFzZUNvbUlEOworCXUx NiBudW1Db21JRHM7CisJLyogcmFuZ2VfY3Jvc3Npbmc6CisJICogYml0cyAxLTY6IHJlc2VydmVk CisJICogYml0IDA6IHJhbmdlIGNyb3NzaW5nCisJICovCisJdTggcmFuZ2VfY3Jvc3Npbmc7CisJ LyogbnVtX2xvY2tpbmdfYWRtaW5fYXV0aDoKKwkgKiBub3QgYWxpZ25lZCB0byAxNiBiaXRzLCBz byB1c2UgdHdvIHU4LgorCSAqIHN0b3JlZCBpbiBiaWcgZW5kaWFuOgorCSAqIDA6IE1TQgorCSAq IDE6IExTQgorCSAqLworCXU4IG51bV9sb2NraW5nX2FkbWluX2F1dGhbMl07CisJLyogbnVtX2xv Y2tpbmdfdXNlcl9hdXRoOgorCSAqIG5vdCBhbGlnbmVkIHRvIDE2IGJpdHMsIHNvIHVzZSB0d28g dTguCisJICogc3RvcmVkIGluIGJpZyBlbmRpYW46CisJICogMDogTVNCCisJICogMTogTFNCCisJ ICovCisJdTggbnVtX2xvY2tpbmdfdXNlcl9hdXRoWzJdOworCXU4IGluaXRpYWxQSU47CisJdTgg cmV2ZXJ0ZWRQSU47CisJdTggcmVzZXJ2ZWQwMTsKKwl1MzIgcmVzZXJ2ZWQwMjsKK307CisKKy8q IFVuaW9uIG9mIGZlYXR1cmVzIHVzZWQgdG8gcGFyc2UgdGhlIGRpc2NvdmVyeSAwIHJlc3BvbnNl ICovCitzdHJ1Y3QgZDBfZmVhdHVyZXMgeworCXUxNiBjb2RlOworCS8qCisJICogcl92ZXJzaW9u IGJpdHM6CisJICogYml0cyA0LTc6IHZlcnNpb24KKwkgKiBiaXRzIDAtMzogcmVzZXJ2ZWQKKwkg Ki8KKwl1OCByX3ZlcnNpb247CisJdTggbGVuZ3RoOworCXU4IGZlYXR1cmVzW107Cit9OworCitz dHJ1Y3Qga2V5ICpyZXF1ZXN0X3VzZXJfa2V5KGNvbnN0IGNoYXIgKm1hc3Rlcl9kZXNjLCBjb25z dCB1OCAqKm1hc3Rlcl9rZXksCisJCQkgICAgIHNpemVfdCAqbWFzdGVyX2tleWxlbik7CisKKyNl bmRpZiAvKiBfTlZNRV9PUEFMX0lOVEVSTkFMX0ggKi8KZGlmZiAtLWdpdCBhL2xpYi9zZWQtb3Bh bF9rZXkuYyBiL2xpYi9zZWQtb3BhbF9rZXkuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAw MDAwMDAwLi4wYjRkZTAxCi0tLSAvZGV2L251bGwKKysrIGIvbGliL3NlZC1vcGFsX2tleS5jCkBA IC0wLDAgKzEsNDYgQEAKKy8qCisgKiBDb3B5cmlnaHQgwqkgMjAxNiBJbnRlbCBDb3Jwb3JhdGlv bgorICoKKyAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0 byBhbnkgcGVyc29uIG9idGFpbmluZyBhCisgKiBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFz c29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLAorICogdG8gZGVh bCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQg bGltaXRhdGlvbgorICogdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1 Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsCisgKiBhbmQvb3Igc2VsbCBjb3BpZXMgb2Yg dGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUKKyAqIFNvZnR3 YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRp dGlvbnM6CisgKgorICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlz c2lvbiBub3RpY2UgKGluY2x1ZGluZyB0aGUgbmV4dAorICogcGFyYWdyYXBoKSBzaGFsbCBiZSBp bmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZQorICog U29mdHdhcmUuCisgKgorICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhP VVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1IKKyAqIElNUExJRUQsIElOQ0xVRElO RyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAor ICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4g IElOIE5PIEVWRU5UIFNIQUxMCisgKiBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBC RSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUgorICogTElBQklMSVRZLCBX SEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJ TkcKKyAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9S IFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MKKyAqIElOIFRIRSBTT0ZUV0FSRS4KKyAqCisgKiBB dXRob3I6CisgKiAgICBSYWZhZWwgQW50b2dub2xsaSA8cmFmYWVsLmFudG9nbm9sbGlAaW50ZWwu Y29tPgorICovCisKKyNpbmNsdWRlIDxsaW51eC9rZXkuaD4KKyNpbmNsdWRlICJzZWQtb3BhbF9p bnRlcm5hbC5oIgorCitzdHJ1Y3Qga2V5ICpyZXF1ZXN0X3VzZXJfa2V5KGNvbnN0IGNoYXIgKm1h c3Rlcl9kZXNjLCBjb25zdCB1OCAqKm1hc3Rlcl9rZXksCisJCQkgICAgIHNpemVfdCAqbWFzdGVy X2tleWxlbikKK3sKKwljb25zdCBzdHJ1Y3QgdXNlcl9rZXlfcGF5bG9hZCAqdXBheWxvYWQ7CisJ c3RydWN0IGtleSAqdWtleTsKKworCXVrZXkgPSByZXF1ZXN0X2tleSgma2V5X3R5cGVfdXNlciwg bWFzdGVyX2Rlc2MsIE5VTEwpOworCWlmIChJU19FUlIodWtleSkpCisJCWdvdG8gZXJyb3I7CisK Kwlkb3duX3JlYWQoJnVrZXktPnNlbSk7CisJdXBheWxvYWQgPSB1c2VyX2tleV9wYXlsb2FkKHVr ZXkpOworCSptYXN0ZXJfa2V5ID0gdXBheWxvYWQtPmRhdGE7CisJKm1hc3Rlcl9rZXlsZW4gPSB1 cGF5bG9hZC0+ZGF0YWxlbjsKK2Vycm9yOgorCXJldHVybiB1a2V5OworfQpkaWZmIC0tZ2l0IGEv bGliL3NlZC5jIGIvbGliL3NlZC5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAu LjA2Y2FjZDkKLS0tIC9kZXYvbnVsbAorKysgYi9saWIvc2VkLmMKQEAgLTAsMCArMSwzMDMgQEAK KyNpbmNsdWRlIDxsaW51eC9ibGtkZXYuaD4KKyNpbmNsdWRlIDxsaW51eC9zZWQuaD4KKyNpbmNs dWRlIDxsaW51eC9zZWQtb3BhbC5oPgorCisjaWZuZGVmIENPTkZJR19TRURfT1BBTAorc3RhdGlj IGludCBzZWRfb3BhbF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf a2V5ICpzZWQpCisJeyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KK3N0YXRpYyBpbnQgc2VkX29wYWxf bG9ja191bmxvY2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtl eSkKKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQorc3RhdGljIGludCBzZWRfb3BhbF90YWtlX293 bmVyc2hpcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQor CXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9CitzdGF0aWMgaW50IHNlZF9vcGFsX2FjdGl2YXRlX2xz cChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorCXsgcmV0 dXJuIC1FT1BOT1RTVVBQOyB9CitzdGF0aWMgaW50IHNlZF9vcGFsX3NldF9wdyhzdHJ1Y3QgYmxv Y2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorCXsgcmV0dXJuIC1FT1BOT1RT VVBQOyB9CitzdGF0aWMgaW50IHNlZF9vcGFsX2FjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2Rl dmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKKwl7IHJldHVybiAtRU9QTk9UU1VQUDsg fQorc3RhdGljIGludCBzZWRfb3BhbF9yZXZlcnR0cGVyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJk ZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCisJeyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KK3N0YXRp YyBpbnQgc2VkX29wYWxfc2V0dXBfbG9ja2luZ19yYW5nZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpi ZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorCXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9CitzdGF0 aWMgaW50IHNlZF9vcGFsX2FkZHVzZXJfdG9fbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg c3RydWN0IHNlZF9rZXkgKmtleSkKKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQorc3RhdGljIGlu dCBzZWRfb3BhbF9kb19tYnIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9r ZXkgKmtleSkKKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQorc3RhdGljIGludCBzZWRfb3BhbF9l cmFzZV9scihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQor CXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9CisKKyNlbHNlCisKK3N0YXRpYyBpbnQgc2VkX29wYWxf c2F2ZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQorewor CisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8 CisJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQorCQlyZXR1cm4gLUVPUE5PVFNV UFA7CisKKwlyZXR1cm4gb3BhbF9zYXZlKGJkZXYsIGtleSk7Cit9CisKK3N0YXRpYyBpbnQgc2Vk X29wYWxfbG9ja191bmxvY2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9r ZXkgKmtleSkKK3sKKworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRf ZGlzay0+Zm9wcyB8fAorCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0 dXJuIC1FT1BOT1RTVVBQOworCisJcmV0dXJuIG9wYWxfbG9ja191bmxvY2soYmRldiwga2V5KTsK K30KKworc3RhdGljIGludCBzZWRfb3BhbF90YWtlX293bmVyc2hpcChzdHJ1Y3QgYmxvY2tfZGV2 aWNlICpiZGV2LAorCQkJCSAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlpZiAoIWJkZXYg fHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKKwkgICAgIWJkZXYt PmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVybiAtRU9QTk9UU1VQUDsKKworCXJldHVy biBvcGFsX3Rha2Vfb3duZXJzaGlwKGJkZXYsIGtleSk7Cit9CisKK3N0YXRpYyBpbnQgc2VkX29w YWxfYWN0aXZhdGVfbHNwKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkJIHN0cnVjdCBz ZWRfa2V5ICprZXkpCit7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYt PmJkX2Rpc2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJ CXJldHVybiAtRU9QTk9UU1VQUDsKKworCXJldHVybiBvcGFsX2FjdGl2YXRlX2xzcChiZGV2LCBr ZXkpOworfQorCitzdGF0aWMgaW50IHNlZF9vcGFsX3NldF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNl ICpiZGV2LAorCQkJICAgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKworCWlmICghYmRldiB8fCAh YmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAorCSAgICAhYmRldi0+YmRf ZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJuIC1FT1BOT1RTVVBQOworCisJcmV0dXJuIG9w YWxfc2V0X25ld19wdyhiZGV2LCBrZXkpOworfQorCitzdGF0aWMgaW50IHNlZF9vcGFsX2FjdGl2 YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCQkgIHN0cnVjdCBzZWRfa2V5 ICprZXkpCit7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rp c2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVy biAtRU9QTk9UU1VQUDsKKworCXJldHVybiBvcGFsX2FjdGl2YXRlX3VzZXIoYmRldiwga2V5KTsK K30KKworc3RhdGljIGludCBzZWRfb3BhbF9yZXZlcnR0cGVyKHN0cnVjdCBibG9ja19kZXZpY2Ug KmJkZXYsCisJCQkgICAgICAgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKworCWlmICghYmRldiB8 fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAorCSAgICAhYmRldi0+ YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJuIC1FT1BOT1RTVVBQOworCisJcmV0dXJu IG9wYWxfcmV2ZXJ0dHBlcihiZGV2LCBrZXkpOworfQorCitzdGF0aWMgaW50IHNlZF9vcGFsX3Nl dHVwX2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkgICAgIHN0cnVjdCBzZWRfa2V5 ICprZXkpCit7CisKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rp c2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVy biAtRU9QTk9UU1VQUDsKKworCXJldHVybiBvcGFsX3NldHVwX2xvY2tpbmdfcmFuZ2UoYmRldiwg a2V5KTsKK30KKworc3RhdGljIGludCBzZWRfb3BhbF9hZGR1c2VyX3RvX2xyKHN0cnVjdCBibG9j a19kZXZpY2UgKmJkZXYsCisJCQkgICAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisKKwlpZiAo IWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKKwkgICAg IWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVybiAtRU9QTk9UU1VQUDsKKwor CXJldHVybiBvcGFsX2FkZF91c2VyX3RvX2xyKGJkZXYsIGtleSk7Cit9CisKK3N0YXRpYyBpbnQg c2VkX29wYWxfZG9fbWJyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCisJCQkgICBzdHJ1Y3Qg c2VkX2tleSAqa2V5KQoreworCisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2 LT5iZF9kaXNrLT5mb3BzIHx8CisJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQor CQlyZXR1cm4gLUVPUE5PVFNVUFA7CisKKwlyZXR1cm4gb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFk b3dfbWJyKGJkZXYsIGtleSk7Cit9CisKK3N0YXRpYyBpbnQgc2VkX29wYWxfZXJhc2VfbHIoc3Ry dWN0IGJsb2NrX2RldmljZSAqYmRldiwKKwkJCSAgICAgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sK KworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8 fAorCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJuIC1FT1BOT1RT VVBQOworCisJcmV0dXJuIG9wYWxfZXJhc2VfbG9ja2luZ19yYW5nZShiZGV2LCBrZXkpOworfQor I2VuZGlmCisKK2ludCBzZWRfc2F2ZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qg c2VkX2tleSAqa2V5KQoreworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+ YmRfZGlzay0+Zm9wcyB8fAorCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJ cmV0dXJuIC1FT1BOT1RTVVBQOworCisJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBP UEFMX0xPQ0tfVU5MT0NLOgorCQlyZXR1cm4gc2VkX29wYWxfc2F2ZShiZGV2LCBrZXkpOworCX0K KworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworaW50IHNlZF9sb2NrX3VubG9jayhzdHJ1Y3Qg YmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQoreworCWlmICghYmRldiB8 fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAorCSAgICAhYmRldi0+ YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJuIC1FT1BOT1RTVVBQOworCisJc3dpdGNo IChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBPUEFMX0xPQ0tfVU5MT0NLOgorCQlyZXR1cm4gc2Vk X29wYWxfbG9ja191bmxvY2soYmRldiwga2V5KTsKKwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7 Cit9CisKK2ludCBzZWRfdGFrZV9vd25lcnNoaXAoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg c3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwg IWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19v cHMpCisJCXJldHVybiAtRU9QTk9UU1VQUDsKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgewor CWNhc2UgT1BBTDoKKwkJcmV0dXJuIHNlZF9vcGFsX3Rha2Vfb3duZXJzaGlwKGJkZXYsIGtleSk7 CisJfQorCisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQorCitpbnQgc2VkX2FjdGl2YXRlX2xzcChz dHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQoreworCWlmICgh YmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAorCSAgICAh YmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJuIC1FT1BOT1RTVVBQOworCisJ c3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBPUEFMOgorCQlyZXR1cm4gc2VkX29wYWxf YWN0aXZhdGVfbHNwKGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQor CitpbnQgc2VkX3NldF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tl eSAqa2V5KQoreworCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlz ay0+Zm9wcyB8fAorCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKKwkJcmV0dXJu IC1FT1BOT1RTVVBQOworCisJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7CisJY2FzZSBPUEFMX1BX OgorCQlyZXR1cm4gc2VkX29wYWxfc2V0X3B3KGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1F T1BOT1RTVVBQOworfQorCitpbnQgc2VkX2FjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2Rldmlj ZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJk X2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZv cHMtPnNlY19vcHMpCisJCXJldHVybiAtRU9QTk9UU1VQUDsKKworCXN3aXRjaCAoa2V5LT5zZWRf dHlwZSkgeworCWNhc2UgT1BBTF9BQ1RfVVNSOgorCQlyZXR1cm4gc2VkX29wYWxfYWN0aXZhdGVf dXNlcihiZGV2LCBrZXkpOworCX0KKworCXJldHVybiAtRU9QTk9UU1VQUDsKK30KKworaW50IHNl ZF9yZXZlcnR0cGVyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICpr ZXkpCit7CisJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5m b3BzIHx8CisJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQorCQlyZXR1cm4gLUVP UE5PVFNVUFA7CisKKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsKKwljYXNlIE9QQUw6CisJCXJl dHVybiBzZWRfb3BhbF9yZXZlcnR0cGVyKGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1FT1BO T1RTVVBQOworfQorCitpbnQgc2VkX3NldHVwX2xvY2tpbmdfcmFuZ2Uoc3RydWN0IGJsb2NrX2Rl dmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKK3sKKwlpZiAoIWJkZXYgfHwgIWJkZXYt PmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2st PmZvcHMtPnNlY19vcHMpCisJCXJldHVybiAtRU9QTk9UU1VQUDsKKworCXN3aXRjaCAoa2V5LT5z ZWRfdHlwZSkgeworCWNhc2UgT1BBTF9MUl9TRVRVUDoKKwkJcmV0dXJuIHNlZF9vcGFsX3NldHVw X2xyKGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQorCitpbnQgc2Vk X2FkZHVzZXJfdG9fbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkg KmtleSkKK3sKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2st PmZvcHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVybiAt RU9QTk9UU1VQUDsKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTF9MT0NL X1VOTE9DSzoKKwkJcmV0dXJuIHNlZF9vcGFsX2FkZHVzZXJfdG9fbHIoYmRldiwga2V5KTsKKwl9 CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisKK2ludCBzZWRfZG9fbWJyKHN0cnVjdCBibG9j a19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCit7CisJaWYgKCFiZGV2IHx8ICFi ZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8CisJICAgICFiZGV2LT5iZF9k aXNrLT5mb3BzLT5zZWNfb3BzKQorCQlyZXR1cm4gLUVPUE5PVFNVUFA7CisKKwlzd2l0Y2ggKGtl eS0+c2VkX3R5cGUpIHsKKwljYXNlIE9QQUxfTUJSX0RBVEE6CisJCXJldHVybiBzZWRfb3BhbF9k b19tYnIoYmRldiwga2V5KTsKKwl9CisKKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cit9CisKK2ludCBz ZWRfZXJhc2VfbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtl eSkKK3sKKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZv cHMgfHwKKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCisJCXJldHVybiAtRU9Q Tk9UU1VQUDsKKworCXN3aXRjaCAoa2V5LT5zZWRfdHlwZSkgeworCWNhc2UgT1BBTDoKKwkJcmV0 dXJuIHNlZF9vcGFsX2VyYXNlX2xyKGJkZXYsIGtleSk7CisJfQorCisJcmV0dXJuIC1FT1BOT1RT VVBQOworfQotLSAKMi43LjQKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fXwpMaW51eC1udm1lIG1haWxpbmcgbGlzdApMaW51eC1udm1lQGxpc3RzLmluZnJh ZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51 eC1udm1lCg== ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 2/6] lib: Add Sed-opal library @ 2016-10-31 21:58 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 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> --- lib/sed-opal.c | 3337 +++++++++++++++++++++++++++++++++++++++++++++++ lib/sed-opal_internal.h | 586 +++++++++ lib/sed-opal_key.c | 46 + lib/sed.c | 303 +++++ 4 files changed, 4272 insertions(+) create mode 100644 lib/sed-opal.c create mode 100644 lib/sed-opal_internal.h create mode 100644 lib/sed-opal_key.c create mode 100644 lib/sed.c diff --git a/lib/sed-opal.c b/lib/sed-opal.c new file mode 100644 index 0000000..10b3348 --- /dev/null +++ b/lib/sed-opal.c @@ -0,0 +1,3337 @@ +/* + * Copyright ? 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Rafael Antognolli <rafael.antognolli at intel.com> + * Scott Bauer <scott.bauer at intel.com> + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ":OPAL: " fmt + +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/genhd.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <uapi/linux/sed-opal.h> +#include <linux/sed.h> +#include <linux/sed-opal.h> +#include <linux/string.h> + +#include "sed-opal_internal.h" + +#define IO_BUFFER_LENGTH 2048 + +#define MAX_TOKS 64 + +struct opal_cmd { + struct block_device *bdev; + sec_cb *cb; + void *cb_data; + + size_t pos; + u8 cmd_buf[IO_BUFFER_LENGTH * 2]; + u8 resp_buf[IO_BUFFER_LENGTH * 2]; + u8 *cmd; + u8 *resp; +}; + +/* + * On the parsed response, we don't store again the toks that are already + * stored in the response buffer. Instead, for each token, we just store a + * pointer to the position in the buffer where the token starts, and the size + * of the token in bytes. + */ +struct opal_resp_tok { + const u8 *pos; + size_t len; + enum OPAL_RESPONSE_TOKEN type; + enum OPAL_ATOM_WIDTH width; + union { + u64 u; + s64 s; + } stored; +}; + +/* + * From the response header it's not possible to know how many tokens there are + * on the payload. So we hardcode that the maximum will be MAX_TOKS, and later + * if we start dealing with messages that have more than that, we can increase + * this number. This is done to avoid having to make two passes through the + * response, the first one counting how many tokens we have and the second one + * actually storing the positions. + */ +struct parsed_resp { + int num; + struct opal_resp_tok toks[MAX_TOKS]; +}; + +struct opal_dev; + +typedef void (*opal_cb)(int error, struct opal_dev *dev); + +typedef int (*opal_step)(struct opal_dev *dev); + +struct opal_completion { + struct completion cmd_completion; + int completion_status; +}; + +struct opal_dev { + struct block_device *bdev; + struct opal_completion *completion; + struct opal_lock_unlock lkul; + const opal_step *funcs; + void **func_data; + bool resume_from_suspend; + struct opal_suspend_unlk *resume_data; + size_t num_func_data; + atomic_t in_use; + sector_t start; + sector_t length; + u8 lr; + u8 key_type; + u8 key_name[OPAL_KEY_MAX]; + size_t key_name_len; + u8 key[OPAL_KEY_MAX]; + size_t key_len; + u16 comID; + u32 HSN; + u32 TSN; + u64 align; + u64 lowest_lba; + struct list_head node; + char disk_name[DISK_NAME_LEN]; + int state; + + struct opal_cmd cmd; + struct parsed_resp parsed; + + size_t prev_d_len; + void *prev_data; + + sec_cb *final_cb; + void *final_cb_data; + opal_step error_cb; + void *error_cb_data; + opal_cb oper_cb; +}; + +LIST_HEAD(opal_list); +DEFINE_SPINLOCK(list_spinlock); + +static void print_buffer(const u8 *ptr, u32 length) +{ +#ifdef DEBUG + print_hex_dump_bytes("OPAL: ", DUMP_PREFIX_OFFSET, ptr, length); + pr_debug("\n"); +#endif +} + +#define TPER_SYNC_SUPPORTED BIT(0) + +static bool check_tper(const void *data) +{ + const struct d0_tper_features *tper = data; + u8 flags = tper->supported_features; + + if (!(flags & TPER_SYNC_SUPPORTED)) { + pr_err("TPer sync not supported. flags = %d\n", + tper->supported_features); + return false; + } + + return true; +} + +static bool check_SUM(const void *data) +{ + const struct d0_single_user_mode *sum = data; + u32 nlo = be32_to_cpu(sum->num_locking_objects); + + if (nlo == 0) { + pr_err("Need at least one locking object.\n"); + return false; + } + + pr_debug("Number of locking objects: %d\n", nlo); + + return true; +} + +static u16 get_comID_v100(const void *data) +{ + const struct d0_opal_v100 *v100 = data; + + return be16_to_cpu(v100->baseComID); +} + +static u16 get_comID_v200(const void *data) +{ + const struct d0_opal_v200 *v200 = data; + + return be16_to_cpu(v200->baseComID); +} + +static int __opal_send_cmd(struct opal_suspend_unlk *data, u16 comID, + void *buffer, size_t buflen, sec_cb *cb, + void *cb_data) +{ + return data->ops.send(data->data, comID, TCG_SECP_01, buffer, buflen, + cb, cb_data); +} +static int _opal_send_cmd(struct block_device *bdev, u16 comID, + void *buffer, size_t buflen, + sec_cb *cb, void *cb_data) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + + return ops->send(bdev->bd_disk->private_data, comID, + TCG_SECP_01, buffer, buflen, + cb, cb_data); +} + +static int __opal_recv_cmd(struct opal_suspend_unlk *data, u16 comID, + void *buffer, size_t buflen, sec_cb *cb, + void *cb_data) +{ + return data->ops.recv(data->data, comID, TCG_SECP_01, buffer, buflen, + cb, cb_data); +} + +static int _opal_recv_cmd(struct block_device *bdev, u16 comID, + void *buffer, size_t buflen, + sec_cb *cb, void *cb_data) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + + return ops->recv(bdev->bd_disk->private_data, comID, + TCG_SECP_01, buffer, buflen, + cb, cb_data); +} + +static void opal_send_cb_cont(int error, void *data) +{ + struct opal_dev *dev = data; + size_t buflen = IO_BUFFER_LENGTH; + void *buffer = dev->cmd.resp; + struct opal_header *hdr = buffer; + + pr_debug("%s: Sent OPAL command: error=%d, outstanding=%d, minTransfer=%d\n", + dev->disk_name, error, hdr->cp.outstandingData, + hdr->cp.minTransfer); + + if (error || hdr->cp.outstandingData == 0 || + hdr->cp.minTransfer != 0) { + if (dev->cmd.cb) + dev->cmd.cb(error, dev->cmd.cb_data); + return; + } + + memset(buffer, 0, buflen); + if (dev->resume_from_suspend) + __opal_recv_cmd(dev->resume_data, dev->comID, + buffer, buflen, opal_send_cb_cont, dev); + else + _opal_recv_cmd(dev->bdev, dev->comID, buffer, buflen, + opal_send_cb_cont, dev); +} + +static void opal_send_cb(int error, void *data) +{ + struct opal_dev *dev = data; + size_t buflen = IO_BUFFER_LENGTH; + void *buffer = dev->cmd.resp; + + if (error) { + if (dev->cmd.cb) + dev->cmd.cb(error, dev->cmd.cb_data); + return; + } + + memset(buffer, 0, buflen); + if (dev->resume_from_suspend) + __opal_recv_cmd(dev->resume_data, dev->comID, + buffer, buflen, opal_send_cb_cont, dev); + else + _opal_recv_cmd(dev->bdev, dev->comID, buffer, buflen, + opal_send_cb_cont, dev); +} + +static int opal_send_recv(struct opal_dev *dev, sec_cb *cb, void *cb_data) +{ + size_t buflen = IO_BUFFER_LENGTH; + void *buffer = dev->cmd.cmd; + int ret; + + dev->cmd.cb = cb; + dev->cmd.cb_data = cb_data; + if (dev->resume_from_suspend) + ret = __opal_send_cmd(dev->resume_data, dev->comID, buffer, + buflen, opal_send_cb, dev); + else + ret = _opal_send_cmd(dev->bdev, dev->comID, buffer, buflen, + opal_send_cb, dev); + + return ret; +} + +static void check_geometry(struct opal_dev *dev, const void *data) +{ + const struct d0_geometry_features *geo = data; + + dev->align = geo->alignment_granularity; + dev->lowest_lba = geo->lowest_aligned_lba; +} + +static void opal_discovery0_end(int error, void *data) +{ + bool foundComID = false, supported = true, single_user = false; + struct opal_dev *dev = data; + const struct d0_header *hdr; + const u8 *epos, *cpos; + u16 comID = 0; + + if (error) { + pr_err("%s: Sending discovery0 failed\n", dev->disk_name); + goto err_callback; + } + + epos = dev->cmd.resp; + cpos = dev->cmd.resp; + hdr = (struct d0_header *)dev->cmd.resp; + + print_buffer(dev->cmd.resp, be32_to_cpu(hdr->length)); + + epos += be32_to_cpu(hdr->length); /* end of buffer */ + cpos += sizeof(*hdr); /* current position on buffer */ + + while (cpos < epos && supported) { + const struct d0_features *body = + (const struct d0_features *)cpos; + + switch (be16_to_cpu(body->code)) { + case FC_TPER: + supported = check_tper(body->features); + break; + case FC_SINGLEUSER: + single_user = check_SUM(body->features); + break; + case FC_GEOMETRY: + check_geometry(dev, body); + break; + case FC_LOCKING: + case FC_ENTERPRISE: + case FC_DATASTORE: + /* some ignored properties */ + pr_debug("%s: Found OPAL feature description: %d\n", + dev->disk_name, be16_to_cpu(body->code)); + break; + case FC_OPALV100: + comID = get_comID_v100(body->features); + foundComID = true; + break; + case FC_OPALV200: + comID = get_comID_v200(body->features); + foundComID = true; + break; + default: + if (be16_to_cpu(body->code) > 0xbfff) { + /* vendor specific, just ignore */ + } else { + pr_warn("%s: OPAL Unknown feature: %d\n", + dev->disk_name, be16_to_cpu(body->code)); + } + } + cpos += body->length + 4; + } + + if (!supported) { + pr_err("%s: Device not supported\n", dev->disk_name); + goto err_callback; + } + + if (!single_user) + pr_warn("%s: Device doesn't support single user mode\n", + dev->disk_name); + + if (!foundComID) { + pr_warn("%s: Could not find OPAL comID for device. OPAL kernel unlocking will be disabled\n", + dev->disk_name); + goto err_callback; + } + + dev->comID = comID; + +err_callback: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static int opal_discovery0(struct opal_dev *dev) +{ + memset(dev->cmd.resp, 0, IO_BUFFER_LENGTH); + + if (dev->resume_from_suspend) + return __opal_recv_cmd(dev->resume_data, 0x0001, + dev->cmd.resp, IO_BUFFER_LENGTH, + opal_discovery0_end, dev); + + return _opal_recv_cmd(dev->bdev, 0x0001, dev->cmd.resp, + IO_BUFFER_LENGTH, opal_discovery0_end, + dev); +} + +static void add_token_u8(struct opal_cmd *cmd, u8 tok) +{ + cmd->cmd[cmd->pos++] = tok; +} + +static ssize_t test_and_add_token_u8(struct opal_cmd *cmd, u8 tok) +{ + BUILD_BUG_ON(IO_BUFFER_LENGTH >= SIZE_MAX); + + if (cmd->pos >= IO_BUFFER_LENGTH - 1) { + pr_err("Error adding u8: end of buffer.\n"); + return -ERANGE; + } + + add_token_u8(cmd, tok); + + return 1; +} + +#define TINY_ATOM_DATA_MASK GENMASK(5, 0) +#define TINY_ATOM_SIGNED BIT(6) + +#define SHORT_ATOM_ID BIT(7) +#define SHORT_ATOM_BYTESTRING BIT(5) +#define SHORT_ATOM_SIGNED BIT(4) +#define SHORT_ATOM_LEN_MASK GENMASK(3, 0) + +static void add_short_atom_header(struct opal_cmd *cmd, bool bytestring, + bool has_sign, int len) +{ + u8 atom; + + atom = SHORT_ATOM_ID; + atom |= bytestring ? SHORT_ATOM_BYTESTRING : 0; + atom |= has_sign ? SHORT_ATOM_SIGNED : 0; + atom |= len & SHORT_ATOM_LEN_MASK; + + add_token_u8(cmd, atom); +} + +#define MEDIUM_ATOM_ID (BIT(7) | BIT(6)) +#define MEDIUM_ATOM_BYTESTRING BIT(4) +#define MEDIUM_ATOM_SIGNED BIT(3) +#define MEDIUM_ATOM_LEN_MASK GENMASK(2, 0) + +static void add_medium_atom_header(struct opal_cmd *cmd, bool bytestring, + bool has_sign, int len) +{ + u8 header0; + + header0 = MEDIUM_ATOM_ID; + header0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0; + header0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0; + header0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK; + cmd->cmd[cmd->pos++] = header0; + cmd->cmd[cmd->pos++] = len; +} + +static void add_token_u64(struct opal_cmd *cmd, u64 number, size_t len) +{ + add_short_atom_header(cmd, false, false, len); + + while (len--) { + u8 n = number >> (len * 8); + + add_token_u8(cmd, n); + } +} + +static ssize_t test_and_add_token_u64(struct opal_cmd *cmd, u64 number) +{ + int len; + int msb; + + if (!(number & ~TINY_ATOM_DATA_MASK)) + return test_and_add_token_u8(cmd, number); + + msb = fls(number); + len = DIV_ROUND_UP(msb, 4); + + if (cmd->pos >= IO_BUFFER_LENGTH - len - 1) { + pr_err("Error adding u64: end of buffer.\n"); + return -ERANGE; + } + + add_token_u64(cmd, number, len); + + /* return length of token plus atom */ + return len + 1; +} + +static void add_token_bytestring(struct opal_cmd *cmd, + const u8 *bytestring, size_t len) +{ + memcpy(&cmd->cmd[cmd->pos], bytestring, len); + cmd->pos += len; +} + +static ssize_t test_and_add_token_bytestring(struct opal_cmd *cmd, + const u8 *bytestring, size_t len) +{ + size_t header_len = 1; + bool is_short_atom = true; + + if (len & ~SHORT_ATOM_LEN_MASK) { + header_len = 2; + is_short_atom = false; + } + + if (cmd->pos >= IO_BUFFER_LENGTH - len - header_len) { + pr_err("Error adding bytestring: end of buffer.\n"); + return -ERANGE; + } + + if (is_short_atom) + add_short_atom_header(cmd, true, false, len); + else + add_medium_atom_header(cmd, true, false, len); + + add_token_bytestring(cmd, bytestring, len); + + return header_len + len; +} + +#define LOCKING_RANGE_NON_GLOBAL 0x03 + +static int build_locking_range(u8 *buffer, size_t length, u8 lr) +{ + if (length < OPAL_UID_LENGTH) + return -ERANGE; + + memcpy(buffer, OPALUID[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH); + + if (lr == 0) + return 0; + buffer[5] = LOCKING_RANGE_NON_GLOBAL; + buffer[7] = lr; + + return 0; +} + +static int build_locking_user(u8 *buffer, size_t length, u8 lr) +{ + if (length < OPAL_UID_LENGTH) + return -ERANGE; + + memcpy(buffer, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH); + + buffer[7] = lr + 1; + + return 0; +} + +/* + * N = number of format specifiers (1-999) to be replicated + * c = u8 + * u = u64 + * s = bytestring, length + * + * ret = test_and_add_token_va(cmd, "c", + * u8_val1); + * + * ret = test_and_add_token_va(cmd, "2c2u", + * u8_val1, u8_val2, u64_val1, u64_val2); + * + * ret = test_and_add_token_va(cmd, "3s", + * bytestring1, length1, + * bytestring2, length2, + * bytestring3, length3); + */ +static int test_and_add_token_va(struct opal_cmd *cmd, + const char *fmt, ...) +{ + const u8 *it = fmt, *tmp; + int ret, num = 1, sum = 0; + va_list ap; + + va_start(ap, fmt); + + while (*it != '\0') { + u64 tok64 = 0; + u8 tok, *bstr; + size_t len; + + ret = 0; + + switch (*it) { + case '1' ... '9': + tmp = it; + num = 0; + while (*tmp >= '0' && *tmp <= '9') + num = num * 10 + (*tmp++ - '0'); + it = tmp; + continue; + case 'c': + while (num--) { + tok = va_arg(ap, unsigned int); + ret = test_and_add_token_u8(cmd, tok); + if (ret < 0) + goto err; + } + num = 1; + break; + case 'u': + while (num--) { + tok64 = va_arg(ap, u64); + ret = test_and_add_token_u64(cmd, tok64); + if (ret < 0) + goto err; + } + num = 1; + break; + case 's': + while (num--) { + bstr = va_arg(ap, u8 *); + len = va_arg(ap, size_t); + ret = test_and_add_token_bytestring(cmd, bstr, + len); + if (ret < 0) + goto err; + } + num = 1; + break; + case ' ': + case '\t': + /* ignored */ + break; + default: + pr_warn("Unrecognized type.\n"); + } + + it++; + sum += ret; + } + + va_end(ap); + + return sum; + + err: + pr_err("Token failed to be added.\n"); + return ret; +} + +static void set_comID(struct opal_cmd *cmd, u16 comID) +{ + struct opal_header *hdr = (struct opal_header *)cmd->cmd; + + hdr->cp.extendedComID[0] = comID >> 8; + hdr->cp.extendedComID[1] = comID; + hdr->cp.extendedComID[2] = 0; + hdr->cp.extendedComID[3] = 0; +} + +static int cmd_finalize(struct opal_cmd *cmd, u32 hsn, u32 tsn) +{ + struct opal_header *hdr; + int ret; + + ret = test_and_add_token_va(cmd, "6c", + OPAL_ENDOFDATA, OPAL_STARTLIST, + 0, 0, 0, OPAL_ENDLIST); + + if (ret < 0) { + pr_err("Error finalizing command.\n"); + return -EFAULT; + } + + hdr = (struct opal_header *) cmd->cmd; + + hdr->pkt.TSN = cpu_to_be32(tsn); + hdr->pkt.HSN = cpu_to_be32(hsn); + + hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr)); + while (cmd->pos % 4) { + if (cmd->pos >= IO_BUFFER_LENGTH) { + pr_err("Error: Buffer overrun\n"); + return -ERANGE; + } + cmd->cmd[cmd->pos++] = 0; + } + hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) - + sizeof(hdr->pkt)); + hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp)); + + return 0; +} + +static enum OPAL_RESPONSE_TOKEN token_type(const struct parsed_resp *resp, + int n) +{ + const struct opal_resp_tok *tok; + + if (n >= resp->num) { + pr_err("Token number doesn't exist: %d, resp: %d\n", + n, resp->num); + return OPAL_DTA_TOKENID_INVALID; + } + + tok = &resp->toks[n]; + if (tok->len == 0) { + pr_err("Token length must be non-zero\n"); + return OPAL_DTA_TOKENID_INVALID; + } + + return tok->type; +} + +/* + * This function returns 0 in case of invalid token. One should call + * token_type() first to find out if the token is valid or not. + */ +static enum OPAL_TOKEN response_get_token(const struct parsed_resp *resp, + int n) +{ + const struct opal_resp_tok *tok; + + if (n >= resp->num) { + pr_err("Token number doesn't exist: %d, resp: %d\n", + n, resp->num); + return 0; + } + + tok = &resp->toks[n]; + if (tok->len == 0) { + pr_err("Token length must be non-zero\n"); + return 0; + } + + return tok->pos[0]; +} + +static size_t response_parse_tiny(struct opal_resp_tok *tok, + const u8 *pos) +{ + tok->pos = pos; + tok->len = 1; + tok->width = OPAL_WIDTH_TINY; + + if (pos[0] & TINY_ATOM_SIGNED) { + tok->type = OPAL_DTA_TOKENID_SINT; + } else { + tok->type = OPAL_DTA_TOKENID_UINT; + tok->stored.u = pos[0] & 0x3f; + } + + return tok->len; +} + +static size_t response_parse_short(struct opal_resp_tok *tok, + const u8 *pos) +{ + tok->pos = pos; + tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1; + tok->width = OPAL_WIDTH_SHORT; + + if (pos[0] & SHORT_ATOM_BYTESTRING) { + tok->type = OPAL_DTA_TOKENID_BYTESTRING; + } else if (pos[0] & SHORT_ATOM_SIGNED) { + tok->type = OPAL_DTA_TOKENID_SINT; + } else { + u64 u_integer = 0; + int i, b = 0; + + tok->type = OPAL_DTA_TOKENID_UINT; + if (tok->len > 9) + pr_warn("uint64 with more than 8 bytes\n"); + for (i = tok->len - 1; i > 0; i--) { + u_integer |= ((u64)pos[i] << (8 * b)); + b++; + } + tok->stored.u = u_integer; + } + + return tok->len; +} + +static size_t response_parse_medium(struct opal_resp_tok *tok, + const u8 *pos) +{ + tok->pos = pos; + tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2; + tok->width = OPAL_WIDTH_MEDIUM; + + if (pos[0] & MEDIUM_ATOM_BYTESTRING) + tok->type = OPAL_DTA_TOKENID_BYTESTRING; + else if (pos[0] & MEDIUM_ATOM_SIGNED) + tok->type = OPAL_DTA_TOKENID_SINT; + else + tok->type = OPAL_DTA_TOKENID_UINT; + + return tok->len; +} + +#define LONG_ATOM_ID (BIT(7) | BIT(6) | BIT(5)) +#define LONG_ATOM_BYTESTRING BIT(1) +#define LONG_ATOM_SIGNED BIT(0) +static size_t response_parse_long(struct opal_resp_tok *tok, + const u8 *pos) +{ + tok->pos = pos; + tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4; + tok->width = OPAL_WIDTH_LONG; + + if (pos[0] & LONG_ATOM_BYTESTRING) + tok->type = OPAL_DTA_TOKENID_BYTESTRING; + else if (pos[0] & LONG_ATOM_SIGNED) + tok->type = OPAL_DTA_TOKENID_SINT; + else + tok->type = OPAL_DTA_TOKENID_UINT; + + return tok->len; +} + +static size_t response_parse_token(struct opal_resp_tok *tok, + const u8 *pos) +{ + tok->pos = pos; + tok->len = 1; + tok->type = OPAL_DTA_TOKENID_TOKEN; + tok->width = OPAL_WIDTH_TOKEN; + + return tok->len; +} + +static int response_parse(const u8 *buf, size_t length, + struct parsed_resp *resp) +{ + const struct opal_header *hdr; + struct opal_resp_tok *iter; + int ret, num_entries = 0; + u32 cpos = 0, total; + size_t token_length; + const u8 *pos; + + if (!buf) + return -EFAULT; + + if (!resp) + return -EFAULT; + + hdr = (struct opal_header *)buf; + pos = buf; + pos += sizeof(*hdr); + + pr_debug("Response size: cp: %d, pkt: %d, subpkt: %d\n", + be32_to_cpu(hdr->cp.length), + be32_to_cpu(hdr->pkt.length), + be32_to_cpu(hdr->subpkt.length)); + + if ((hdr->cp.length == 0) + || (hdr->pkt.length == 0) + || (hdr->subpkt.length == 0)) { + pr_err("Bad header length. cp: %d, pkt: %d, subpkt: %d\n", + be32_to_cpu(hdr->cp.length), + be32_to_cpu(hdr->pkt.length), + be32_to_cpu(hdr->subpkt.length)); + print_buffer(pos, sizeof(*hdr)); + ret = -EINVAL; + goto err; + } + + if (pos > buf + length) { + ret = -EFAULT; + goto err; + } + + iter = resp->toks; + total = be32_to_cpu(hdr->subpkt.length); + print_buffer(pos, total); + while (cpos < total) { + if (!(pos[0] & 0x80)) /* tiny atom */ + token_length = response_parse_tiny(iter, pos); + else if (!(pos[0] & 0x40)) /* short atom */ + token_length = response_parse_short(iter, pos); + else if (!(pos[0] & 0x20)) /* medium atom */ + token_length = response_parse_medium(iter, pos); + else if (!(pos[0] & 0x10)) /* long atom */ + token_length = response_parse_long(iter, pos); + else /* TOKEN */ + token_length = response_parse_token(iter, pos); + + pos += token_length; + cpos += token_length; + iter++; + num_entries++; + } + + if (num_entries == 0) { + pr_err("Couldn't parse response.\n"); + ret = -EINVAL; + goto err; + } + resp->num = num_entries; + + return 0; +err: + return ret; +} + +static size_t response_get_string(const struct parsed_resp *resp, int n, + const char **store) +{ + *store = NULL; + if (!resp) { + pr_err("Response is NULL\n"); + return 0; + } + + if (n > resp->num) { + pr_err("Response has %d tokens. Can't access %d\n", + resp->num, n); + return 0; + } + + if (resp->toks[n].type != OPAL_DTA_TOKENID_BYTESTRING) { + pr_err("Token is not a byte string!\n"); + return 0; + } + + *store = resp->toks[n].pos + 1; + return resp->toks[n].len - 1; +} + +static u64 response_get_u64(const struct parsed_resp *resp, int n) +{ + if (!resp) { + pr_err("Response is NULL\n"); + return 0; + } + + if (n > resp->num) { + pr_err("Response has %d tokens. Can't access %d\n", + resp->num, n); + return 0; + } + + if (resp->toks[n].type != OPAL_DTA_TOKENID_UINT) { + pr_err("Token is not unsigned it: %d\n", + resp->toks[n].type); + return 0; + } + + if (!((resp->toks[n].width == OPAL_WIDTH_TINY) || + (resp->toks[n].width == OPAL_WIDTH_SHORT))) { + pr_err("Atom is not short or tiny: %d\n", + resp->toks[n].width); + return 0; + } + + return resp->toks[n].stored.u; +} + +static u8 response_status(const struct parsed_resp *resp) +{ + if ((token_type(resp, 0) == OPAL_DTA_TOKENID_TOKEN) + && (response_get_token(resp, 0) == OPAL_ENDOFSESSION)) { + return 0; + } + + if (resp->num < 5) + return DTAERROR_NO_METHOD_STATUS; + + if ((token_type(resp, resp->num - 1) != OPAL_DTA_TOKENID_TOKEN) || + (token_type(resp, resp->num - 5) != OPAL_DTA_TOKENID_TOKEN) || + (response_get_token(resp, resp->num - 1) != OPAL_ENDLIST) || + (response_get_token(resp, resp->num - 5) != OPAL_STARTLIST)) + return DTAERROR_NO_METHOD_STATUS; + + return response_get_u64(resp, resp->num - 4); +} + +/* Parses and checks for errors */ +static int parse_and_check_status(struct opal_dev *dev) +{ + struct opal_cmd *cmd; + int error; + + cmd = &dev->cmd; + print_buffer(cmd->cmd, cmd->pos); + + error = response_parse(cmd->resp, IO_BUFFER_LENGTH, &dev->parsed); + if (error) { + pr_err("%s: Couldn't parse response.\n", dev->disk_name); + goto err_return; + } + + error = response_status(&dev->parsed); + if (error) + pr_err("%s: Response Status: %d\n", dev->disk_name, + error); + + err_return: + return error; +} + +static void clear_opal_cmd(struct opal_cmd *cmd) +{ + cmd->pos = sizeof(struct opal_header); + memset(cmd->cmd, 0, IO_BUFFER_LENGTH); + cmd->cb = NULL; + cmd->cb_data = NULL; +} + +static void start_opal_session_cont(int error, void *data) +{ + struct opal_dev *dev = data; + u32 HSN, TSN; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + if (error) + goto err_return; + + HSN = response_get_u64(&dev->parsed, 4); + TSN = response_get_u64(&dev->parsed, 5); + + if (HSN == 0 && TSN == 0) { + pr_err("%s: Couldn't authenticate session\n", dev->disk_name); + error = -EPERM; + goto err_return; + } + + dev->HSN = HSN; + dev->TSN = TSN; + +err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static int get_opal_key(struct opal_dev *dev) +{ + struct key *ukey = NULL; + const u8 *tmpkey = NULL; + size_t tmplen; + int ret = 0; + + if (dev->key_type == OPAL_KEY_PLAIN) { + tmpkey = dev->key_name; + tmplen = dev->key_name_len; + } else if (dev->key_type == OPAL_KEY_KEYRING) { + ukey = request_user_key(dev->key_name, &tmpkey, &tmplen); + if (IS_ERR(ukey)) { + pr_err("%s: Can't retrieve key: %ld\n", dev->disk_name, + PTR_ERR(ukey)); + return PTR_ERR(ukey); + } + } else { + pr_err("Requested invalid key type: %d\n", dev->key_type); + return -EINVAL; + } + + if (tmplen > OPAL_KEY_MAX) { + pr_err("Requested key with invalid size: %zd\n", tmplen); + ret = -EINVAL; + goto err_exit; + } + + dev->key_len = tmplen; + if (!memcpy(dev->key, tmpkey, tmplen)) { + pr_err("Error when copying key"); + ret = -EFAULT; + goto err_exit; + } + +err_exit: + key_put(ukey); + + return 0; +} + +static void clean_opal_key(struct opal_dev *dev) +{ + memset(dev->key, 0, OPAL_KEY_MAX); + dev->key_len = 0; +} + +static inline void clean_function_data(struct opal_dev *dev) +{ + dev->func_data = NULL; + dev->num_func_data = 0; +} + +/* This is a generic continue fn. + * We use this when we don't care about the response data + * and simply want to check the status and continue. + */ +static void generic_cont(int error, void *data) +{ + struct opal_dev *dev = data; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + + err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static void end_session_cont(int error, void *data) +{ + struct opal_dev *dev = data; + + dev->HSN = 0; + dev->TSN = 0; + generic_cont(error, data); +} + +static int finalize_and_send(struct opal_dev *dev, struct opal_cmd *cmd, + sec_cb cont) +{ + int ret; + + ret = cmd_finalize(cmd, dev->HSN, dev->TSN); + if (ret) { + pr_err("%s: Error finalizing command buffer: %d\n", + dev->disk_name, ret); + return ret; + } + + print_buffer(cmd->cmd, cmd->pos); + + ret = opal_send_recv(dev, cont, dev); + if (ret) + pr_err("%s: Error running command: %d\n", + dev->disk_name, ret); + + return ret; +} + +static int wait_for_cmd_completion(struct opal_completion *completion) +{ + wait_for_completion_interruptible(&completion->cmd_completion); + return completion->completion_status; +} + +static int gen_key(struct opal_dev *dev) +{ + const u8 *method; + u8 uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len)); + method = OPALMETHOD[OPAL_GENKEY]; + kfree(dev->prev_data); + dev->prev_data = NULL; + + ret = test_and_add_token_va(cmd, "c2s 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building gen key command\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static void get_active_key_cont(int error, void *data) +{ + struct opal_dev *dev = data; + const char *activekey; + size_t keylen; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + if (error) + goto err_return; + keylen = response_get_string(&dev->parsed, 4, &activekey); + if (!activekey) { + pr_err("%s: Couldn't extract the Activekey from the response\n", + __func__); + error = 0x0A; + goto err_return; + } + dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL); + + if (!dev->prev_data) + error = -ENOMEM; + + dev->prev_d_len = keylen; + +err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static int get_active_key(struct opal_dev *dev) +{ + const u8 *method; + u8 uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_GET]; + + ret = build_locking_range(uid, sizeof(uid), dev->lr); + if (ret < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + + ret = test_and_add_token_va(cmd, "c2s 6c 4c 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* startCloumn */ + OPAL_TINY_UINT_10, /* ActiveKey */ + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_04, /* endColumn */ + OPAL_TINY_UINT_10, /* ActiveKey */ + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building get active key command\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, get_active_key_cont); +} + +static int setup_locking_range(struct opal_dev *dev) +{ + const u8 *method; + u8 uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + struct opal_user_lr_setup *setup; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + ret = build_locking_range(uid, sizeof(uid), dev->lr); + if (ret < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + setup = dev->func_data[dev->state - 1]; + + ret = test_and_add_token_va(cmd, "c2s 4c 2cuc 2cuc 2cuc 2cu 4c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_VALUES, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* Range Start */ + setup->range_start, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_04, /* Range Length */ + setup->range_length, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_05, /* ReadLockEnabled */ + !!setup->RLE, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_06, /* WriteLockEnabled */ + !!setup->WLE, + + OPAL_ENDNAME, + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building Setup Locking range command.\n", + dev->disk_name); + return ret; + + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int start_adminsp_opal_session(struct opal_dev *dev, + enum OPAL_UID auth, + const char *key, + u8 key_len) +{ + const u8 *method, *smuid, *admin_sp, *hsa; + struct opal_cmd *cmd; + u32 HSN; + int ret; + + if (key == NULL && auth != OPAL_ANYBODY_UID) { + pr_err("%s: Attempted to open ADMIN_SP Session without a Host" \ + "Challenge, and not as the Anybody UID\n", __func__); + return 1; + } + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + set_comID(cmd, dev->comID); + HSN = 0x41; + + smuid = OPALUID[OPAL_SMUID_UID]; + method = OPALMETHOD[OPAL_STARTSESSION]; + admin_sp = OPALUID[OPAL_ADMINSP_UID]; + + ret = test_and_add_token_va(cmd, "c2s cusc", + OPAL_CALL, + smuid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + OPAL_STARTLIST, + HSN, + admin_sp, OPAL_UID_LENGTH, + OPAL_TINY_UINT_01); + if (ret < 0) { + pr_err("%s: Error building start adminsp session command.\n", + dev->disk_name); + return ret; + } + + switch (auth) { + case OPAL_ANYBODY_UID: + /* nothing left to do for anybody, just end and finalize */ + ret = test_and_add_token_va(cmd, "c", + OPAL_ENDLIST); + break; + case OPAL_SID_UID: + hsa = OPALUID[OPAL_SID_UID]; + ret = test_and_add_token_va(cmd, "2c s 3c s 2c", + OPAL_STARTNAME, + OPAL_TINY_UINT_00, /* HostChallenge */ + key, key_len, + OPAL_ENDNAME, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* HostSignAuth */ + hsa, OPAL_UID_LENGTH, + OPAL_ENDNAME, + OPAL_ENDLIST); + break; + default: + pr_err("Cannot start Admin SP session with auth %d\n", auth); + return 1; + } + + if (ret < 0) { + pr_err("%s: Error building start adminsp session command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, start_opal_session_cont); +} + +static int start_anybodyASP_opal_session(struct opal_dev *dev) +{ + return start_adminsp_opal_session(dev, OPAL_ANYBODY_UID, NULL, 0); +} + +static int start_SIDASP_opal_session(struct opal_dev *dev) +{ + int ret; + const u8 *key = dev->prev_data; + + if (!key) + ret = start_adminsp_opal_session(dev, OPAL_SID_UID, dev->key, + dev->key_len); + else { + ret = start_adminsp_opal_session(dev, OPAL_SID_UID, key, + dev->prev_d_len); + kfree(key); + dev->prev_data = NULL; + } + return ret; +} + +static int start_lockingsp_opal_session(struct opal_dev *dev, + enum OPAL_UID auth, const u8 *key, + u8 key_len) +{ + + const u8 *method, *smuid, *locking_sp, *hsa; + struct opal_cmd *cmd; + size_t klen = key_len; + u32 HSN; + int ret; + + if (key == NULL) { + pr_err("Cannot start Locking SP session without a key\n"); + return -EINVAL; + } + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + set_comID(cmd, dev->comID); + HSN = 0x41; + + smuid = OPALUID[OPAL_SMUID_UID]; + method = OPALMETHOD[OPAL_STARTSESSION]; + locking_sp = OPALUID[OPAL_LOCKINGSP_UID]; + hsa = OPALUID[auth]; + + ret = test_and_add_token_va(cmd, "c2s cusc 2csc 2csc c", + OPAL_CALL, + smuid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + HSN, + locking_sp, OPAL_UID_LENGTH, + OPAL_TINY_UINT_01, + + OPAL_STARTNAME, + OPAL_TINY_UINT_00, /* HostChallenge */ + key, klen, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* Host Sign Authority */ + hsa, OPAL_UID_LENGTH, + OPAL_ENDNAME, + + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building start adminsp session command.\n", + dev->disk_name); + return ret; + } + return finalize_and_send(dev, cmd, start_opal_session_cont); +} + +static inline int start_admin1LSP_opal_session(struct opal_dev *dev) +{ + return start_lockingsp_opal_session(dev, OPAL_ADMIN1_UID, + dev->key, dev->key_len); +} + +static int start_auth_opal_session(struct opal_dev *dev) +{ + const u8 *method, *smuid, *locking_sp; + u8 lk_ul_user[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + u32 HSN; + int ret; + struct opal_user_info *uinfo; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + set_comID(cmd, dev->comID); + + HSN = 0x41; + + uinfo = dev->func_data[dev->state - 1]; + + smuid = OPALUID[OPAL_SMUID_UID]; + method = OPALMETHOD[OPAL_STARTSESSION]; + locking_sp = OPALUID[OPAL_LOCKINGSP_UID]; + + if (uinfo->SUM) { + ret = build_locking_user(lk_ul_user, sizeof(lk_ul_user), + dev->lr); + if (ret < 0) { + pr_err("%s: Can't build locking user\n", + dev->disk_name); + return ret; + } + } else if (uinfo->who != OPAL_ADMIN1 && !uinfo->SUM) { + ret = build_locking_user(lk_ul_user, sizeof(lk_ul_user), + uinfo->who - 1); + if (ret < 0) { + pr_err("%s: Can't build locking user\n", + dev->disk_name); + return ret; + } + } else + memcpy(lk_ul_user, OPALUID[OPAL_ADMIN1_UID], OPAL_UID_LENGTH); + + + ret = test_and_add_token_va(cmd, "c2s cus3cs3c s 2c", + OPAL_CALL, + smuid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + HSN, + locking_sp, OPAL_UID_LENGTH, + OPAL_TINY_UINT_01, + OPAL_STARTNAME, + OPAL_TINY_UINT_00, + dev->key, dev->key_len, + OPAL_ENDNAME, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, + + lk_ul_user, OPAL_UID_LENGTH, + + OPAL_ENDNAME, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building STARTSESSION command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, start_opal_session_cont); +} + +static int revert_tper(struct opal_dev *dev) +{ + const u8 *method, *smuid; + struct opal_cmd *cmd; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + set_comID(cmd, dev->comID); + + smuid = OPALUID[OPAL_ADMINSP_UID]; + method = OPALMETHOD[OPAL_REVERT]; + + ret = test_and_add_token_va(cmd, "c2s 2c", + OPAL_CALL, + smuid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + OPAL_STARTLIST, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building REVERT TPER command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int internal_activate_user(struct opal_dev *dev) +{ + const u8 *method; + u8 uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + int ret; + struct opal_activate_user *act; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + act = dev->func_data[dev->state - 1]; + + memcpy(uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH); + uid[7] = act->who.who; + + method = OPALMETHOD[OPAL_SET]; + + ret = test_and_add_token_va(cmd, "c2s 3c c 4c 3c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_01, /* Values */ + + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_TINY_UINT_05, /* Enabled */ + OPAL_TINY_UINT_01, /* True */ + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building Activate UserN command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int erase_locking_range(struct opal_dev *dev) +{ + const u8 *method; + u8 uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_ERASE]; + + if (build_locking_range(uid, sizeof(uid), dev->lr) < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + + ret = test_and_add_token_va(cmd, "c2s 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building Erase Locking Range Cmmand.\n", + dev->disk_name); + return ret; + } + return finalize_and_send(dev, cmd, generic_cont); +} + +static int set_mbr_done(struct opal_dev *dev) +{ + const u8 *method, *uid; + struct opal_cmd *cmd; + int ret; + + u8 mbr_done_tf = *(u8 *)dev->func_data[dev->state - 1]; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + uid = OPALUID[OPAL_MBRCONTROL]; + + ret = test_and_add_token_va(cmd, "c2s 3c 6c 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_VALUES, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_02, /* Done */ + mbr_done_tf, /* Done T or F */ + OPAL_ENDNAME, + OPAL_ENDLIST, + + OPAL_ENDNAME, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error Building set MBR Dont/Not done command\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int set_mbr_enable_disable(struct opal_dev *dev) +{ + const u8 *method, *uid; + struct opal_cmd *cmd; + int ret; + + u8 mbr_en_dis = *(u8 *)dev->func_data[dev->state - 1]; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + uid = OPALUID[OPAL_MBRCONTROL]; + + ret = test_and_add_token_va(cmd, "c2s 3c 6c 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_VALUES, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_01, /* Enable */ + mbr_en_dis, /* Enable or Disable */ + OPAL_ENDNAME, + OPAL_ENDLIST, + + OPAL_ENDNAME, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error Building set MBR Dont/Not done command\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int set_new_pw(struct opal_dev *dev) +{ + const u8 *method; + u8 cpin_uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + int ret; + struct opal_new_pw *pw; + size_t key_len; + u8 *key; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + pw = dev->func_data[dev->state - 1]; + key = pw->new_pin.key; + key_len = pw->new_pin.key_len; + memcpy(cpin_uid, OPALUID[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH); + + if (pw->user_for_pw != OPAL_ADMIN1) { + cpin_uid[5] = 0x03; + if (pw->who.SUM) + cpin_uid[7] = pw->new_pin.lr + 1; + else + cpin_uid[7] = pw->user_for_pw; + } + + method = OPALMETHOD[OPAL_SET]; + + ret = test_and_add_token_va(cmd, "c2s 3c 3cs2c 2c", + OPAL_CALL, + cpin_uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_01, /* Values */ + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* PIN */ + key, key_len, + OPAL_ENDNAME, + OPAL_ENDLIST, + + OPAL_ENDNAME, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building SET AMIN1 PIN command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int set_sid_cpin_pin(struct opal_dev *dev) +{ + const u8 *method, *cpin_uid; + struct opal_cmd *cmd; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + cpin_uid = OPALUID[OPAL_C_PIN_SID]; + method = OPALMETHOD[OPAL_SET]; + + ret = test_and_add_token_va(cmd, "c2s 2c 4cs2c 2c", + OPAL_CALL, + cpin_uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + + OPAL_TINY_UINT_01, /* Values */ + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* PIN */ + dev->key, dev->key_len, + OPAL_ENDNAME, + OPAL_ENDLIST, + + OPAL_ENDNAME, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building SET CPIN PIN command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static void query_locking_range_cont(int error, void *data) +{ + struct opal_dev *dev = data; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + if (error) + goto err_return; + + dev->start = response_get_u64(&dev->parsed, 4); + dev->length = response_get_u64(&dev->parsed, 8); + +err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static int query_locking_range(struct opal_dev *dev) +{ + u8 lr_buffer[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + const u8 *method; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + method = OPALMETHOD[OPAL_GET]; + + if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + + set_comID(cmd, dev->comID); + + ret = test_and_add_token_va(cmd, "c2s 12c", + OPAL_CALL, + lr_buffer, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_STARTCOLUMN, + OPAL_RANGESTART, + OPAL_ENDNAME, + OPAL_STARTNAME, + OPAL_ENDCOLUMN, + OPAL_RANGELENGTH, + OPAL_ENDNAME, + OPAL_ENDLIST, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building GET Locking Range command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, query_locking_range_cont); +} + +static int add_user_to_lr(struct opal_dev *dev) +{ + u8 lr_buffer[OPAL_UID_LENGTH]; + u8 user_uid[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + const u8 *method; + struct opal_lock_unlock *lkul; + int ret; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + + lkul = dev->func_data[dev->state - 1]; + + memcpy(lr_buffer, OPALUID[OPAL_LOCKINGRANGE_ACE_RDLOCKED], + OPAL_UID_LENGTH); + + if (lkul->l_state == OPAL_RW) + memcpy(lr_buffer, OPALUID[OPAL_LOCKINGRANGE_ACE_WRLOCKED], + OPAL_UID_LENGTH); + + lr_buffer[7] = dev->lr; + + memcpy(user_uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH); + user_uid[7] = lkul->authority.who; + + ret = test_and_add_token_va(cmd, "c2s 3c 3c 2c 2sc c2sc cs2c 5c", + OPAL_CALL, + lr_buffer, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_01, /* Values */ + + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* BooleanExpr */ + + OPAL_STARTLIST, + OPAL_STARTNAME, + + OPALUID[OPAL_HALF_UID_AUTHORITY_OBJ_REF], + OPAL_UID_LENGTH_HALF, + user_uid, OPAL_UID_LENGTH, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPALUID[OPAL_HALF_UID_AUTHORITY_OBJ_REF], + OPAL_UID_LENGTH_HALF, + user_uid, OPAL_UID_LENGTH, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPALUID[OPAL_HALF_UID_BOOLEAN_ACE], + OPAL_UID_LENGTH_HALF, + OPAL_TINY_UINT_01, + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building add user to locking range command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static int lock_unlock_locking_range(struct opal_dev *dev) +{ + u8 lr_buffer[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + const u8 *method; + struct opal_lock_unlock *lkul; + int ret; + u8 read_locked = 1, write_locked = 1; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + lkul = dev->func_data[dev->state - 1]; + if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + + switch (lkul->l_state) { + case OPAL_RO: + read_locked = 0; + write_locked = 1; + break; + case OPAL_RW: + read_locked = 0; + write_locked = 0; + break; + case OPAL_LK: + /* vars are initalized to locked */ + break; + default: + pr_err("Tried to set an invalid locking state... returning to uland\n"); + return 1; + } + + ret = test_and_add_token_va(cmd, "c2sc 3c 4c 4c 3c", + OPAL_CALL, + lr_buffer, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_VALUES, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_READLOCKED, + read_locked, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_WRITELOCKED, + write_locked, + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building SET command.\n", dev->disk_name); + return ret; + } + return finalize_and_send(dev, cmd, generic_cont); +} + + +static int lock_unlock_locking_range_SUM(struct opal_dev *dev) +{ + u8 lr_buffer[OPAL_UID_LENGTH]; + struct opal_cmd *cmd; + const u8 *method; + struct opal_lock_unlock *lkul; + int ret; + u8 read_locked = 1, write_locked = 1; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + method = OPALMETHOD[OPAL_SET]; + lkul = dev->func_data[dev->state - 1]; + if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) { + pr_err("%s: Can't build locking range\n", dev->disk_name); + return -EINVAL; + } + + switch (lkul->l_state) { + case OPAL_RO: + read_locked = 0; + write_locked = 1; + break; + case OPAL_RW: + read_locked = 0; + write_locked = 0; + break; + case OPAL_LK: + /* vars are initalized to locked */ + break; + default: + pr_err("Tried to set an invalid locking state.\n"); + return 1; + } + + ret = test_and_add_token_va(cmd, "c2sc 3c 4c 4c 4c 4c 3c", + OPAL_CALL, + lr_buffer, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_VALUES, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_READLOCKENABLED, + OPAL_TRUE, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_WRITELOCKENABLED, + OPAL_TRUE, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_READLOCKED, + read_locked, + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_WRITELOCKED, + write_locked, + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDNAME, + OPAL_ENDLIST); + if (ret < 0) { + pr_err("%s: Error building SET command.\n", dev->disk_name); + return ret; + } + return finalize_and_send(dev, cmd, generic_cont); +} + +int activate_lsp(struct opal_dev *dev) +{ + u8 user_lr[OPAL_UID_LENGTH]; + const u8 *method, *uid; + struct opal_cmd *cmd; + int ret; + size_t uint_3 = 0x83; + + cmd = &dev->cmd; + + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + uid = OPALUID[OPAL_LOCKINGSP_UID]; + method = OPALMETHOD[OPAL_ACTIVATE]; + + ret = test_and_add_token_va(cmd, "c2s", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH); + if (ret < 0) { + pr_err("%s: Error building Activate LockingSP command.\n", + dev->disk_name); + return ret; + } + /* Activating as SUM */ + if (dev->lr > 0) { + ret = build_locking_range(user_lr, sizeof(user_lr), dev->lr); + if (ret < 0) { + pr_err("%s: Can't build locking user\n", + dev->disk_name); + return ret; + } + test_and_add_token_va(cmd, "2c 4c csc 2c", + OPAL_STARTLIST, + OPAL_STARTNAME, + + uint_3, + OPAL_TINY_UINT_06, + OPAL_TINY_UINT_00, + OPAL_TINY_UINT_00, + + OPAL_STARTLIST, + user_lr, OPAL_UID_LENGTH, + OPAL_ENDLIST, + + OPAL_ENDNAME, + OPAL_ENDLIST); + } else /* Actiave Normal Mode */ + ret = test_and_add_token_va(cmd, "2c", + OPAL_STARTLIST, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building Activate LockingSP command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, generic_cont); +} + +static void get_lsp_lifecycle_cont(int error, void *data) +{ + + struct opal_dev *dev = data; + u8 lc_status; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + if (error) + goto err_return; + + lc_status = response_get_u64(&dev->parsed, 4); + /* 0x08 is Manufacured Inactive */ + /* 0x09 is Manufactured */ + if (lc_status != 0x08) { + pr_err("%s: Couldn't determine the status of the Lifcycle state\n", + dev->disk_name); + error = -ENODEV; + } + +err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +/* Determine if we're in the Manufactured Inactive or Active state */ +int get_lsp_lifecycle(struct opal_dev *dev) +{ + struct opal_cmd *cmd; + const u8 *method, *uid; + int ret; + + cmd = &dev->cmd; + + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + uid = OPALUID[OPAL_LOCKINGSP_UID]; + method = OPALMETHOD[OPAL_GET]; + + ret = test_and_add_token_va(cmd, "c2s 2c 4c 4c 2c", + OPAL_CALL, + uid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTLIST, + + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* Start Column */ + OPAL_TINY_UINT_06, /* Lifcycle Column */ + OPAL_ENDNAME, + + OPAL_STARTNAME, + OPAL_TINY_UINT_04, /* End Column */ + OPAL_TINY_UINT_06, /* Lifecycle Column */ + OPAL_ENDNAME, + + OPAL_ENDLIST, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error Building GET Lifecycle Status command\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, get_lsp_lifecycle_cont); +} + +static void get_msid_cpin_pin_cont(int error, void *data) +{ + const char *msid_pin; + struct opal_dev *dev = data; + size_t strlen; + + if (error) + goto err_return; + + error = parse_and_check_status(dev); + if (error) + goto err_return; + + strlen = response_get_string(&dev->parsed, 4, &msid_pin); + if (!msid_pin) { + pr_err("%s: Couldn't extract PIN from response\n", __func__); + error = 1; + goto err_return; + } + + dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL); + if (!dev->prev_data) + error = -ENOMEM; + + dev->prev_d_len = strlen; + + err_return: + if (dev->oper_cb) + dev->oper_cb(error, dev); +} + +static int get_msid_cpin_pin(struct opal_dev *dev) +{ + const u8 *method, *smuid; + int ret; + struct opal_cmd *cmd; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + set_comID(cmd, dev->comID); + + smuid = OPALUID[OPAL_C_PIN_MSID]; + method = OPALMETHOD[OPAL_GET]; + + ret = test_and_add_token_va(cmd, "c 2s 12c", + OPAL_CALL, + + smuid, OPAL_UID_LENGTH, + method, OPAL_METHOD_LENGTH, + + OPAL_STARTLIST, + OPAL_STARTLIST, + OPAL_STARTNAME, + OPAL_TINY_UINT_03, /* Sart Column */ + OPAL_TINY_UINT_03, /* PIN */ + OPAL_ENDNAME, + OPAL_STARTNAME, + OPAL_TINY_UINT_04, /* End Column */ + OPAL_TINY_UINT_03, /* PIN */ + OPAL_ENDNAME, + OPAL_ENDLIST, + OPAL_ENDLIST); + + if (ret < 0) { + pr_err("%s: Error building Get MSID CPIN PIN command.\n", + dev->disk_name); + return ret; + } + + return finalize_and_send(dev, cmd, get_msid_cpin_pin_cont); +} + +static void unlock_suspend_final(int error, void *data) +{ + struct opal_dev *dev = data; + + dev->resume_from_suspend = false; + dev->resume_data = NULL; + dev->func_data = NULL; + dev->bdev = NULL; +} + +static int build_end_opal_session(struct opal_dev *dev) +{ + struct opal_cmd *cmd; + + cmd = &dev->cmd; + clear_opal_cmd(cmd); + + set_comID(cmd, dev->comID); + return test_and_add_token_u8(cmd, OPAL_ENDOFSESSION); +} + +static int end_opal_session(struct opal_dev *dev) +{ + if (build_end_opal_session(dev) < 0) + return -1; + return finalize_and_send(dev, &dev->cmd, end_session_cont); +} + +static struct opal_dev *find_opal_dev(struct block_device *bdev, u8 lr) +{ + struct opal_dev *iter, *opal_dev = NULL; + + list_for_each_entry(iter, &opal_list, node) { + if (strncmp(iter->disk_name, bdev->bd_disk->disk_name, + DISK_NAME_LEN)) + continue; + if (iter->lr == lr) { + opal_dev = iter; + break; + } + } + + return opal_dev; +} + +static int update_opal_dev(struct opal_dev *old_dev, struct opal_dev *new_dev) +{ + if (!atomic_add_unless(&old_dev->in_use, 1, 1)) { + pr_err("%s: dev was in use\n", __func__); + return -EBUSY; + } + + old_dev->key_name_len = new_dev->key_name_len; + if (!memcpy(old_dev->key_name, new_dev->key_name, old_dev->key_name_len)) { + pr_err("%s: Error updating device:\n", old_dev->disk_name); + return -EFAULT; + } + + if (!strncpy(old_dev->disk_name, new_dev->disk_name, DISK_NAME_LEN)) { + pr_err("%s: Error registering device: copying disk name\n", + old_dev->disk_name); + return -EFAULT; + } + + old_dev->comID = new_dev->comID; + old_dev->start = new_dev->start; + old_dev->length = new_dev->length; + old_dev->align = new_dev->align; + old_dev->lowest_lba = new_dev->lowest_lba; + old_dev->bdev = NULL; + old_dev->final_cb = new_dev->final_cb; + old_dev->final_cb_data = new_dev->final_cb_data; + old_dev->oper_cb = new_dev->oper_cb; + old_dev->state = new_dev->state; + old_dev->funcs = new_dev->funcs; + + kfree(old_dev->completion); + clean_function_data(old_dev); + + old_dev->completion = new_dev->completion; + + /* + * Won't be able to auto unlock this locking range based on block + * requestes. + */ + if (old_dev->length == 0) + pr_warn("%s: Missing block information for locking range %d\n", + old_dev->disk_name, old_dev->lr); + + return 0; +} + +int opal_register_cont(struct opal_dev *new_dev) +{ + struct opal_dev *old_dev; + unsigned long flags; + int error = 0; + + spin_lock_irqsave(&list_spinlock, flags); + + old_dev = find_opal_dev(new_dev->bdev, new_dev->lr); + if (!old_dev) { + list_add_tail(&new_dev->node, &opal_list); + old_dev = new_dev; + } else { + if (old_dev == new_dev) + error = 0; + else { + error = update_opal_dev(old_dev, new_dev); + clean_opal_key(new_dev); + kfree(new_dev); + } + } + + if (error) + list_del(&old_dev->node); + + spin_unlock_irqrestore(&list_spinlock, flags); + + if (!error) + pr_info("%s: Registered key for locking range: %d\n", + old_dev->disk_name, old_dev->lr); + + if (old_dev->oper_cb) + old_dev->oper_cb(error, old_dev); + + return 0; +} + +static void next(int error, struct opal_dev *dev) +{ + opal_step func = dev->funcs[dev->state]; + void *cb_data = dev->final_cb_data; + sec_cb *cb = dev->final_cb; + bool done = false; + + + if (error || !func) { + done = true; + goto next_exit; + } + dev->state++; + dev->oper_cb = next; + error = func(dev); + next_exit: + if (error) { + pr_err("%s: Error on step function: %d with error %d: %s\n", + dev->disk_name, dev->state, error, + opal_error_to_human(error)); + + + atomic_dec(&dev->in_use); + if (dev->error_cb) { + dev->error_cb(dev->error_cb_data); + return; + } + if (cb) + cb(error, cb_data); + + dev->completion->completion_status = error; + complete(&dev->completion->cmd_completion); + } else if (!error && done) { + atomic_dec(&dev->in_use); + if (cb) + cb(error, cb_data); + dev->completion->completion_status = error; + complete(&dev->completion->cmd_completion); + } +} + +const opal_step error_end_session[] = { + end_opal_session, + NULL, +}; +static int end_opal_session_error(struct opal_dev *dev) +{ + + dev->funcs = error_end_session; + dev->state = 0; + dev->error_cb = NULL; + next(0, dev); + return 0; +} + +static struct opal_dev *alloc_opal_dev(struct block_device *bdev, u8 lr) +{ + struct opal_dev *opal_dev; + struct request_queue *q; + unsigned long dma_align; + const char *disk_name; + struct opal_cmd *cmd; + int ret; + + opal_dev = kzalloc(sizeof(*opal_dev), GFP_KERNEL); + if (!opal_dev) + return ERR_PTR(-ENOMEM); + + opal_dev->bdev = bdev; + opal_dev->lr = lr; + cmd = &opal_dev->cmd; + cmd->cmd = cmd->cmd_buf; + cmd->resp = cmd->resp_buf; + + disk_name = bdev->bd_disk->disk_name; + if (!strncpy(opal_dev->disk_name, disk_name, DISK_NAME_LEN)) { + pr_err("%s: Error registering device: copying disk name\n", + disk_name); + ret = -EFAULT; + goto err_free_dev; + } + + q = bdev->bd_queue; + dma_align = (queue_dma_alignment(q) | q->dma_pad_mask) + 1; + cmd->cmd = (u8 *)round_up((uintptr_t)cmd->cmd, dma_align); + cmd->resp = (u8 *)round_up((uintptr_t)cmd->resp, dma_align); + + INIT_LIST_HEAD(&opal_dev->node); + atomic_set(&opal_dev->in_use, 1); + + opal_dev->completion = kzalloc(sizeof(*opal_dev->completion), + GFP_KERNEL); + + if (!opal_dev->completion) + goto err_free_dev; + + init_completion(&opal_dev->completion->cmd_completion); + opal_dev->completion->completion_status = 0; + opal_dev->state = 0; + + return opal_dev; + +err_free_dev: + kfree(opal_dev); + return ERR_PTR(ret); +} + +int opal_register(struct block_device *bdev, struct opal_key *key_cmd, + const opal_step *funcs) +{ + struct opal_dev *new_dev = NULL; + u8 key_len = key_cmd->key_len; + u8 lr = key_cmd->lr; + struct opal_completion *completion; + int ret; + + new_dev = alloc_opal_dev(bdev, lr); + if (IS_ERR(new_dev)) { + pr_err("%s: Error registering device: allocation\n", + bdev->bd_disk->disk_name); + return PTR_ERR(new_dev); + } + + if (!memcpy(new_dev->key_name, key_cmd->key, key_len)) { + pr_err("%s: Error registering key: couldn't copy key\n", + new_dev->disk_name); + return -EFAULT; + } + + new_dev->key_name_len = key_len; + new_dev->key_type = key_cmd->key_type; + ret = get_opal_key(new_dev); + if (ret) { + pr_err("%s: Couldn't get key: %d\n", new_dev->disk_name, ret); + return ret; + } + + new_dev->funcs = funcs; + + new_dev->state = 0; + completion = new_dev->completion; + next(0, new_dev); + + return wait_for_cmd_completion(completion); +} + +static struct opal_dev *get_registered_opal_dev(struct block_device *bdev, + u8 lr) +{ + const char *diskname = bdev->bd_disk->disk_name; + struct opal_dev *iter, *dev = NULL; + unsigned long flags; + bool in_use = false; + + spin_lock_irqsave(&list_spinlock, flags); + list_for_each_entry(iter, &opal_list, node) { + if (strncmp(iter->disk_name, diskname, DISK_NAME_LEN)) + continue; + if (iter->lr == lr) { + dev = iter; + if (!atomic_add_unless(&iter->in_use, 1, 1)) { + dev = NULL; + in_use = true; + } + break; + } + } + + spin_unlock_irqrestore(&list_spinlock, flags); + + if (!dev) + return NULL; + + dev->bdev = bdev; + return dev; +} + +/* Free up the Opal dev and its keys during two scenarios: + * + * 1) When a command is complete that no longer requires + * the opal dev to be around. + * 2) When a command, including Opal Save fails we clean + * and free the opal dev. + * + * If we find the opal dev structure in the list of + * saved passwords we will *not* remove it. + */ +static void remove_and_clean_opal_dev(struct opal_dev *dev) +{ + struct opal_dev *iter; + bool found = false; + + spin_lock(&list_spinlock); + list_for_each_entry(iter, &opal_list, node) { + if (iter == dev) { + found = true; + break; + } + } + + spin_unlock(&list_spinlock); + if (!found) { + clean_opal_key(dev); + clean_function_data(dev); + kfree(dev); + } +} + +static struct opal_dev *get_or_create_opal_dev(struct block_device *bdev, + u8 lr, bool use_new) +{ + struct opal_dev *dev; + + if (use_new) + return alloc_opal_dev(bdev, lr); + + dev = get_registered_opal_dev(bdev, lr); + if (!dev) { + dev = alloc_opal_dev(bdev, lr); + if (!dev) + return NULL; + } + return dev; +} + +static struct opal_completion *setup_opal_dev(struct block_device *bdev, + struct opal_dev *dev, + const opal_step *funcs, + struct opal_key *key) +{ + int ret; + + dev->bdev = bdev; + dev->state = 0; + dev->funcs = funcs; + dev->TSN = 0; + dev->HSN = 0; + dev->final_cb = NULL; + dev->final_cb_data = NULL; + dev->lr = key->lr; + dev->error_cb = end_opal_session_error; + dev->error_cb_data = dev; + + if (key) { + memcpy(dev->key_name, key->key, key->key_len); + dev->key_name_len = key->key_len; + dev->key_type = key->key_type; + + ret = get_opal_key(dev); + if (ret) { + kfree(dev->completion); + pr_err("%s: Couldn't get key: %d\n", + dev->disk_name, ret); + return ERR_PTR(ret); + } + } + dev->func_data = NULL; + dev->completion->completion_status = 0; + + return dev->completion; +} + +static int internal_setup_lr(struct block_device *bdev, + struct opal_user_lr_setup *setup) +{ + struct opal_dev *dev; + struct opal_completion *completion; + void *data[3] = { NULL }; + const opal_step lr_funcs[] = { + opal_discovery0, + start_auth_opal_session, + setup_locking_range, + get_active_key, + gen_key, + end_opal_session, + NULL, + }; + int ret; + + dev = get_or_create_opal_dev(bdev, setup->key.lr, true); + if (!dev) + return -ENOMEM; + + completion = setup_opal_dev(bdev, dev, lr_funcs, &setup->key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->func_data = data; + dev->num_func_data = 3; + dev->func_data[1] = &setup->who; + dev->func_data[2] = setup; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +int opal_revert(struct block_device *bdev, struct opal_key *key) +{ + const opal_step revert_funcs[] = { + opal_discovery0, + start_SIDASP_opal_session, + revert_tper, /* controller will terminate session */ + NULL, + }; + + return opal_register(bdev, key, revert_funcs); +} + +int activate_user(struct block_device *bdev, struct opal_activate_user *act) +{ + const opal_step act_funcs[] = { + opal_discovery0, + start_admin1LSP_opal_session, + internal_activate_user, + end_opal_session, + NULL + }; + struct opal_dev *dev; + struct opal_completion *completion; + void *data[3] = { NULL }; + int ret; + + dev = get_or_create_opal_dev(bdev, act->key.lr, true); + if (!dev) + return -ENOMEM; + + completion = setup_opal_dev(bdev, dev, act_funcs, &act->key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 3; + dev->func_data = data; + dev->func_data[1] = act; + dev->func_data[2] = act; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +int opal_set_pw(struct block_device *bdev, struct opal_new_pw *pw) + +{ + const opal_step pw_funcs[] = { + opal_discovery0, + start_auth_opal_session, + set_new_pw, + end_opal_session, + NULL + }; + struct opal_dev *dev; + struct opal_completion *completion; + void *data[3] = { NULL }; + int ret; + + dev = get_or_create_opal_dev(bdev, pw->current_pin.lr, true); + if (!dev) + return -ENOMEM; + + completion = setup_opal_dev(bdev, dev, pw_funcs, &pw->current_pin); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 3; + dev->func_data = data; + dev->func_data[1] = (void *) &pw->who; + dev->func_data[2] = (void *) pw; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +int opal_act_lsp_int(struct block_device *bdev, struct opal_key *key, + const opal_step *funcs) +{ + struct opal_dev *dev; + struct opal_completion *completion; + int ret; + + dev = get_or_create_opal_dev(bdev, key->lr, true); + if (!dev) + return -ENOMEM; + completion = setup_opal_dev(bdev, dev, funcs, key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + + +static int opal_save_internal(struct block_device *bdev, + struct opal_lock_unlock *lk) +{ + void *func_data[3] = { NULL }; + struct opal_dev *dev; + struct opal_completion *completion; + const opal_step _auth_funcs[] = { + opal_discovery0, + start_auth_opal_session, + query_locking_range, + end_opal_session, + opal_register_cont, + NULL + }; + int ret; + + dev = get_or_create_opal_dev(bdev, lk->key.lr, false); + if (!dev) + return -ENOMEM; + completion = setup_opal_dev(bdev, dev, _auth_funcs, &lk->key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 3; + dev->func_data = func_data; + dev->func_data[1] = &lk->authority; + dev->lkul = *lk; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +static int add_user_lr_internal(struct block_device *bdev, + struct opal_lock_unlock *lk) +{ + void *func_data[3] = { NULL }; + struct opal_dev *dev; + struct opal_completion *completion; + const opal_step funcs[] = { + opal_discovery0, + start_admin1LSP_opal_session, + add_user_to_lr, + end_opal_session, + NULL + }; + int ret; + + dev = get_or_create_opal_dev(bdev, lk->key.lr, true); + if (!dev) + return -ENOMEM; + completion = setup_opal_dev(bdev, dev, funcs, &lk->key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 3; + dev->func_data = func_data; + dev->func_data[2] = lk; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +static int lock_unlock_internal(struct block_device *bdev, + struct opal_lock_unlock *lk) +{ + void *func_data[3] = { NULL }; + struct opal_dev *dev; + struct opal_completion *completion; + + const opal_step ulk_funcs_SUM[] = { + opal_discovery0, + start_auth_opal_session, + lock_unlock_locking_range_SUM, + end_opal_session, + NULL + }; + const opal_step _unlock_funcs[] = { + opal_discovery0, + start_auth_opal_session, + lock_unlock_locking_range, + end_opal_session, + NULL + }; + int ret; + + dev = get_or_create_opal_dev(bdev, lk->key.lr, true); + if (!dev) + return -ENOMEM; + + if (lk->authority.SUM) + completion = setup_opal_dev(bdev, dev, ulk_funcs_SUM, &lk->key); + else + completion = setup_opal_dev(bdev, dev, _unlock_funcs, &lk->key); + + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 3; + dev->func_data = func_data; + dev->func_data[1] = &lk->authority; + dev->func_data[2] = lk; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} + +int opal_erase_locking_range(struct block_device *bdev, struct sed_key *key) +{ + struct opal_dev *dev; + struct opal_completion *completion; + struct opal_key k; + int ret; + const opal_step erase_funcs[] = { + opal_discovery0, + start_admin1LSP_opal_session, + erase_locking_range, + end_opal_session, + NULL, + }; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) + return -EFAULT; + + dev = get_or_create_opal_dev(bdev, k.lr, true); + if (!dev) + return -ENOMEM; + + completion = setup_opal_dev(bdev, dev, erase_funcs, &k); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; +} +EXPORT_SYMBOL(opal_erase_locking_range); + +int opal_enable_disable_shadow_mbr(struct block_device *bdev, + struct sed_key *key) +{ + void *func_data[6] = { NULL }; + struct opal_mbr_data mbr; + struct opal_dev *dev; + struct opal_completion *completion; + const opal_step mbr_funcs[] = { + opal_discovery0, + start_admin1LSP_opal_session, + set_mbr_done, + end_opal_session, + start_admin1LSP_opal_session, + set_mbr_enable_disable, + end_opal_session, + NULL, + }; + int ret; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&mbr, key->opal_mbr, sizeof(*key->opal_mbr))) + return -EFAULT; + + if (mbr.enable_disable != OPAL_MBR_ENABLE && + mbr.enable_disable != OPAL_MBR_DISABLE) + return -EINVAL; + + dev = get_or_create_opal_dev(bdev, mbr.key.lr, true); + if (!dev) + return -ENOMEM; + + completion = setup_opal_dev(bdev, dev, mbr_funcs, &mbr.key); + if (IS_ERR(completion)) { + ret = PTR_ERR(completion); + goto error_return; + } + + dev->num_func_data = 6; + dev->func_data = func_data; + dev->func_data[2] = &mbr.enable_disable; + dev->func_data[5] = &mbr.enable_disable; + + next(0, dev); + ret = wait_for_cmd_completion(completion); + + error_return: + remove_and_clean_opal_dev(dev); + return ret; + +} +EXPORT_SYMBOL(opal_enable_disable_shadow_mbr); + +int opal_save(struct block_device *bdev, struct sed_key *key) +{ + struct opal_lock_unlock lkul; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&lkul, key->opal_lk_unlk, sizeof(*key->opal))) + return -EFAULT; + + return opal_save_internal(bdev, &lkul); +} +EXPORT_SYMBOL(opal_save); + +int opal_add_user_to_lr(struct block_device *bdev, struct sed_key *key) +{ + struct opal_lock_unlock lkul; + + if (copy_from_user(&lkul, key->opal_lk_unlk, sizeof(lkul))) + return -EFAULT; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't assign user to LR without backing disk\n"); + return -EFAULT; + } + if (lkul.l_state != OPAL_RO && lkul.l_state != OPAL_RW) { + pr_err("Locking state was not RO or RW\n"); + return -EINVAL; + } + if (lkul.authority.who < OPAL_USER1 && + lkul.authority.who > OPAL_USER9) { + pr_err("Authority was not within the range of users: %d\n", + lkul.authority.who); + return -EINVAL; + } + if (lkul.authority.SUM) { + pr_err("%s not supported in SUM. Use setup locking range\n", + __func__); + return -EINVAL; + } + + return add_user_lr_internal(bdev, &lkul); +} +EXPORT_SYMBOL(opal_add_user_to_lr); + +int opal_reverttper(struct block_device *bdev, struct sed_key *key) +{ + struct opal_key k; + + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) + return -EFAULT; + + return opal_revert(bdev, &k); +} +EXPORT_SYMBOL(opal_reverttper); + +int opal_lock_unlock(struct block_device *bdev, struct sed_key *key) +{ + struct opal_lock_unlock k; + + if (copy_from_user(&k, key->opal_lk_unlk, sizeof(*key->opal_lk_unlk))) + return -EFAULT; + + if (k.authority.who < OPAL_ADMIN1 || k.authority.who >= OPAL_USER9) + return -EINVAL; + + return lock_unlock_internal(bdev, &k); +} +EXPORT_SYMBOL(opal_lock_unlock); + +int opal_take_ownership(struct block_device *bdev, struct sed_key *key) +{ + struct opal_key k; + const opal_step owner_funcs[] = { + opal_discovery0, + start_anybodyASP_opal_session, + get_msid_cpin_pin, + end_opal_session, + start_SIDASP_opal_session, + set_sid_cpin_pin, + end_opal_session, + NULL + }; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) + return -EFAULT; + + return opal_register(bdev, &k, owner_funcs); +} +EXPORT_SYMBOL(opal_take_ownership); + +int opal_activate_lsp(struct block_device *bdev, struct sed_key *key) +{ + struct opal_key k; + const opal_step active_funcs[] = { + opal_discovery0, + start_SIDASP_opal_session, /* Open session as SID auth */ + get_lsp_lifecycle, + activate_lsp, + end_opal_session, + NULL + }; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) + return -EFAULT; + + return opal_act_lsp_int(bdev, &k, active_funcs); +} +EXPORT_SYMBOL(opal_activate_lsp); + +int opal_setup_locking_range(struct block_device *bdev, struct sed_key *pw) +{ + struct opal_user_lr_setup k; + + if (!bdev || !bdev->bd_disk) { + pr_err("Can't save password for NULL block device.\n"); + return -EINVAL; + } + + if (copy_from_user(&k, pw->opal_lrs, sizeof(*pw->opal_lrs))) + return -EFAULT; + + return internal_setup_lr(bdev, &k); +} + +int opal_set_new_pw(struct block_device *bdev, struct sed_key *pw) +{ + struct opal_new_pw k; + + if (pw->sed_type != OPAL_PW) + return -EINVAL; + + if (copy_from_user(&k, pw->opal_pw, sizeof(*pw->opal_pw))) + return -EFAULT; + + if (k.who.who < OPAL_ADMIN1 || k.who.who > OPAL_USER9) + return -EINVAL; + + return opal_set_pw(bdev, &k); +} +EXPORT_SYMBOL(opal_set_new_pw); + +int opal_activate_user(struct block_device *bdev, struct sed_key *pw) +{ + struct opal_activate_user k; + + if (pw->sed_type != OPAL_ACT_USR) { + pr_err("Sed type was not act user\n"); + return -EINVAL; + } + + if (copy_from_user(&k, pw->opal_act, sizeof(*pw->opal_act))) { + pr_err("copy from user error\n"); + return -EFAULT; + } + + /* We can't activate Admin1 it's active as manufactured */ + if (k.who.who < OPAL_USER1 && k.who.who > OPAL_USER9) { + pr_err("Who was not a valid user: %d \n", k.who.who); + return -EINVAL; + } + + return activate_user(bdev, &k); + +} +EXPORT_SYMBOL(opal_activate_user); + +int opal_unlock_from_suspend(struct opal_suspend_unlk *data) +{ + const char *diskname = data->name; + struct opal_dev *iter, *dev = NULL; + struct opal_completion *completion; + void *func_data[3] = { NULL }; + const opal_step _unlock_funcs_SUM[] = { + opal_discovery0, + start_auth_opal_session, + lock_unlock_locking_range, + end_opal_session, + NULL + }; + const opal_step _unlock_funcs[] = { + opal_discovery0, + start_auth_opal_session, + lock_unlock_locking_range, + end_opal_session, + NULL + }; + + + spin_lock(&list_spinlock); + list_for_each_entry(iter, &opal_list, node) { + if (strncmp(iter->disk_name, diskname, DISK_NAME_LEN)) { + pr_err("iterdisk was %s and diskname is %s\n", + iter->disk_name, diskname); + continue; + } + if (atomic_add_unless(&iter->in_use, 1, 1)) { + dev = iter; + dev->func_data = func_data; + dev->resume_from_suspend = true; + dev->resume_data = data; + dev->final_cb = unlock_suspend_final; + dev->final_cb_data = dev; + dev->error_cb = end_opal_session_error; + dev->error_cb_data = dev; + dev->state = 0; + if (dev->lkul.authority.SUM) + dev->funcs = _unlock_funcs_SUM; + else + dev->funcs = _unlock_funcs; + dev->TSN = 0; + dev->HSN = 0; + dev->func_data[2] = &dev->lkul; + dev->func_data[1] = &dev->lkul.authority; + completion = dev->completion; + next(0, dev); + wait_for_cmd_completion(completion); + } + } + spin_unlock(&list_spinlock); + + if (!dev) + return -ENODEV; + return 0; +} +EXPORT_SYMBOL(opal_unlock_from_suspend); diff --git a/lib/sed-opal_internal.h b/lib/sed-opal_internal.h new file mode 100644 index 0000000..c9d3883 --- /dev/null +++ b/lib/sed-opal_internal.h @@ -0,0 +1,586 @@ +/* + * Copyright ? 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Author: + * Rafael Antognolli <rafael.antognolli at intel.com> + * Scott Bauer <scott.bauer at intel.com> + */ + +#ifndef _NVME_OPAL_INTERNAL_H +#define _NVME_OPAL_INTERNAL_H + +#include <linux/key-type.h> +#include <keys/user-type.h> + +#define DTAERROR_NO_METHOD_STATUS 0x89 + +static const char *opal_errors[19] = { + "Success", + "Not Authorized", + "Unknown Error", + "SP Busy", + "SP Failed", + "SP Disabled", + "SP Frozen", + "No Sessions Available", + "Uniqueness Conflict", + "Insufficient Space", + "Insufficient Rows", + "Invalid Function", + "Invalid Parameter", + "Invalid Reference", + "Unknown Error", + "TPER Malfunction", + "Transaction Failure", + "Response Overflow", + "Authority Locked Out", +}; + +static const char *opal_error_to_human(int error) +{ + if (error == 0x3f) + return "Failed"; + + if (error >= sizeof(opal_errors) || error < 0) + return "Unknown Error"; + + return opal_errors[error]; +} + +/* User IDs used in the TCG storage SSCs */ +static const u8 OPALUID[][8] = { + /* users */ + + /* session management */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, + /* special "thisSP" syntax */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* Administrative SP */ + { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 }, + /* Locking SP */ + { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 }, + /* ENTERPRISE Locking SP */ + { 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, 0x01 }, + /* anybody */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 }, + /* SID */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 }, + /* ADMIN1 */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 }, + /* USER1 */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 }, + /* USER2 */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 }, + /* PSID user */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 }, + /* BandMaster 0 */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x01 }, + /* EraseMaster */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x84, 0x01 }, + + /* tables */ + + /* Locking_GlobalRange */ + { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 }, + /* ACE_Locking_Range_Set_RdLocked UID */ + { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x01 }, + /* ACE_Locking_Range_Set_WrLocked UID */ + { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x01 }, + /* MBR Control */ + { 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01 }, + /* Shadow MBR */ + { 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 }, + /* AUTHORITY_TABLE */ + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00}, + /* C_PIN_TABLE */ + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00}, + /* OPAL Locking Info */ + { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 }, + /* Enterprise Locking Info */ + { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 }, + + /* C_PIN_TABLE object ID's */ + + /* C_PIN_MSID */ + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02}, + /* C_PIN_SID */ + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01}, + /* C_PIN_ADMIN1 */ + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01}, + + /* half UID's (only first 4 bytes used) */ + + /* Half-UID ? Authority_object_ref */ + { 0x00, 0x00, 0x0C, 0x05, 0xff, 0xff, 0xff, 0xff }, + /* Half-UID ? Boolean ACE */ + { 0x00, 0x00, 0x04, 0x0E, 0xff, 0xff, 0xff, 0xff }, + + /* special value for omitted optional parameter */ + + /* HEXFF for omitted */ + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, +}; +static const size_t OPAL_UID_LENGTH = 8; +static const size_t OPAL_MSID_KEYLEN = 15; +static const size_t OPAL_UID_LENGTH_HALF = 4; + + +/* Enum to index OPALUID array */ +enum OPAL_UID { + /* users */ + OPAL_SMUID_UID, + OPAL_THISSP_UID, + OPAL_ADMINSP_UID, + OPAL_LOCKINGSP_UID, + OPAL_ENTERPRISE_LOCKINGSP_UID, + OPAL_ANYBODY_UID, + OPAL_SID_UID, + OPAL_ADMIN1_UID, + OPAL_USER1_UID, + OPAL_USER2_UID, + OPAL_PSID_UID, + OPAL_ENTERPRISE_BANDMASTER0_UID, + OPAL_ENTERPRISE_ERASEMASTER_UID, + /* tables */ + OPAL_LOCKINGRANGE_GLOBAL, + OPAL_LOCKINGRANGE_ACE_RDLOCKED, + OPAL_LOCKINGRANGE_ACE_WRLOCKED, + OPAL_MBRCONTROL, + OPAL_MBR, + OPAL_AUTHORITY_TABLE, + OPAL_C_PIN_TABLE, + OPAL_LOCKING_INFO_TABLE, + OPAL_ENTERPRISE_LOCKING_INFO_TABLE, + /* C_PIN_TABLE object ID's */ + OPAL_C_PIN_MSID, + OPAL_C_PIN_SID, + OPAL_C_PIN_ADMIN1, + /* half UID's (only first 4 bytes used) */ + OPAL_HALF_UID_AUTHORITY_OBJ_REF, + OPAL_HALF_UID_BOOLEAN_ACE, + /* omitted optional parameter */ + OPAL_UID_HEXFF, +}; + +/* + * TCG Storage SSC Methods. + */ +static const u8 OPALMETHOD[][8] = { + /* Properties */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01 }, + /* STARTSESSION */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02 }, + /* Revert */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02 }, + /* Activate */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03 }, + /* Enterprise Get */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06 }, + /* Enterprise Set */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07 }, + /* NEXT */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08 }, + /* Enterprise Authenticate */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c }, + /* GetACL */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d }, + /* GenKey */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10 }, + /* revertSP */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11 }, + /* Get */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16 }, + /* Set */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17 }, + /* Authenticate */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c }, + /* Random */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 }, + /* Erase */ + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 }, +}; +static const size_t OPAL_METHOD_LENGTH = 8; + +/* Enum for indexing the OPALMETHOD array */ +enum OPAL_METHOD { + OPAL_PROPERTIES, + OPAL_STARTSESSION, + OPAL_REVERT, + OPAL_ACTIVATE, + OPAL_EGET, + OPAL_ESET, + OPAL_NEXT, + OPAL_EAUTHENTICATE, + OPAL_GETACL, + OPAL_GENKEY, + OPAL_REVERTSP, + OPAL_GET, + OPAL_SET, + OPAL_AUTHENTICATE, + OPAL_RANDOM, + OPAL_ERASE, +}; + +enum OPAL_RESPONSE_TOKEN { + OPAL_DTA_TOKENID_BYTESTRING = 0xe0, + OPAL_DTA_TOKENID_SINT = 0xe1, + OPAL_DTA_TOKENID_UINT = 0xe2, + OPAL_DTA_TOKENID_TOKEN = 0xe3, /* actual token is returned */ + OPAL_DTA_TOKENID_INVALID = 0X0 +}; + +enum OPAL_TOKEN { + /* Boolean */ + OPAL_TRUE = 0x01, + OPAL_FALSE = 0x00, + OPAL_BOOLEAN_EXPR = 0x03, + /* cellblocks */ + OPAL_TABLE = 0x00, + OPAL_STARTROW = 0x01, + OPAL_ENDROW = 0x02, + OPAL_STARTCOLUMN = 0x03, + OPAL_ENDCOLUMN = 0x04, + OPAL_VALUES = 0x01, + /* authority table */ + OPAL_PIN = 0x03, + /* locking tokens */ + OPAL_RANGESTART = 0x03, + OPAL_RANGELENGTH = 0x04, + OPAL_READLOCKENABLED = 0x05, + OPAL_WRITELOCKENABLED = 0x06, + OPAL_READLOCKED = 0x07, + OPAL_WRITELOCKED = 0x08, + OPAL_ACTIVEKEY = 0x0A, + /* locking info table */ + OPAL_MAXRANGES = 0x04, + /* mbr control */ + OPAL_MBRENABLE = 0x01, + OPAL_MBRDONE = 0x02, + /* properties */ + OPAL_HOSTPROPERTIES = 0x00, + /* atoms */ + OPAL_STARTLIST = 0xf0, + OPAL_ENDLIST = 0xf1, + OPAL_STARTNAME = 0xf2, + OPAL_ENDNAME = 0xf3, + OPAL_CALL = 0xf8, + OPAL_ENDOFDATA = 0xf9, + OPAL_ENDOFSESSION = 0xfa, + OPAL_STARTTRANSACTON = 0xfb, + OPAL_ENDTRANSACTON = 0xfC, + OPAL_EMPTYATOM = 0xff, + OPAL_WHERE = 0x00, +}; + +/* Useful tiny atoms. + * Useful for table columns etc + */ +enum OPAL_TINY_ATOM { + OPAL_TINY_UINT_00 = 0x00, + OPAL_TINY_UINT_01 = 0x01, + OPAL_TINY_UINT_02 = 0x02, + OPAL_TINY_UINT_03 = 0x03, + OPAL_TINY_UINT_04 = 0x04, + OPAL_TINY_UINT_05 = 0x05, + OPAL_TINY_UINT_06 = 0x06, + OPAL_TINY_UINT_07 = 0x07, + OPAL_TINY_UINT_08 = 0x08, + OPAL_TINY_UINT_09 = 0x09, + OPAL_TINY_UINT_10 = 0x0a, + OPAL_TINY_UINT_11 = 0x0b, + OPAL_TINY_UINT_12 = 0x0c, + OPAL_TINY_UINT_13 = 0x0d, + OPAL_TINY_UINT_14 = 0x0e, + OPAL_TINY_UINT_15 = 0x0f, +}; + +enum OPAL_ATOM_WIDTH { + OPAL_WIDTH_TINY, + OPAL_WIDTH_SHORT, + OPAL_WIDTH_MEDIUM, + OPAL_WIDTH_LONG, + OPAL_WIDTH_TOKEN +}; + +/* Locking state for a locking range */ +enum OPAL_LOCKINGSTATE { + OPAL_LOCKING_READWRITE = 0x01, + OPAL_LOCKING_READONLY = 0x02, + OPAL_LOCKING_LOCKED = 0x03, +}; + +/* + * Structures to build and decode the Opal SSC messages + * fields that are NOT really numeric are defined as u8[] to + * help reduce the endianness issues + */ + +/* Comm Packet (header) for transmissions. */ +struct opal_compacket { + u32 reserved0; + u8 extendedComID[4]; + u32 outstandingData; + u32 minTransfer; + u32 length; +}; + +/* Packet structure. */ +struct opal_packet { + u32 TSN; + u32 HSN; + u32 seq_number; + u16 reserved0; + u16 ack_type; + u32 acknowledgment; + u32 length; +}; + +/* Data sub packet header */ +struct opal_data_subpacket { + u8 reserved0[6]; + u16 kind; + u32 length; +}; + +/* header of a response */ +struct opal_header { + struct opal_compacket cp; + struct opal_packet pkt; + struct opal_data_subpacket subpkt; +}; + +#define FC_TPER 0x0001 +#define FC_LOCKING 0x0002 +#define FC_GEOMETRY 0x0003 +#define FC_ENTERPRISE 0x0100 +#define FC_DATASTORE 0x0202 +#define FC_SINGLEUSER 0x0201 +#define FC_OPALV100 0x0200 +#define FC_OPALV200 0x0203 + +/* + * The Discovery 0 Header. As defined in + * Opal SSC Documentation + */ +struct d0_header { + u32 length; /* the length of the header 48 in 2.00.100 */ + u32 revision; /**< revision of the header 1 in 2.00.100 */ + u32 reserved01; + u32 reserved02; + /* + * the remainder of the structure is vendor specific and will not be + * addressed now + */ + u8 ignored[32]; +}; + +/* + * TPer Feature Descriptor. Contains flags indicating support for the + * TPer features described in the OPAL specification. The names match the + * OPAL terminology + * + * code == 0x001 in 2.00.100 + */ +struct d0_tper_features { + /* + * supported_features bits: + * bit 7: reserved + * bit 6: com ID management + * bit 5: reserved + * bit 4: streaming support + * bit 3: buffer management + * bit 2: ACK/NACK + * bit 1: async + * bit 0: sync + */ + u8 supported_features; + /* + * bytes 5 through 15 are reserved, but we represent the first 3 as + * u8 to keep the other two 32bits integers aligned. + */ + u8 reserved01[3]; + u32 reserved02; + u32 reserved03; +}; + +/* + * Locking Feature Descriptor. Contains flags indicating support for the + * locking features described in the OPAL specification. The names match the + * OPAL terminology + * + * code == 0x0002 in 2.00.100 + */ +struct d0_locking_features { + /* + * supported_features bits: + * bits 6-7: reserved + * bit 5: MBR done + * bit 4: MBR enabled + * bit 3: media encryption + * bit 2: locked + * bit 1: locking enabled + * bit 0: locking supported + */ + u8 supported_features; + /* + * bytes 5 through 15 are reserved, but we represent the first 3 as + * u8 to keep the other two 32bits integers aligned. + */ + u8 reserved01[3]; + u32 reserved02; + u32 reserved03; +}; + +/* + * Geometry Feature Descriptor. Contains flags indicating support for the + * geometry features described in the OPAL specification. The names match the + * OPAL terminology + * + * code == 0x0003 in 2.00.100 + */ +struct d0_geometry_features { + /* + * skip 32 bits from header, needed to align the struct to 64 bits. + */ + u8 header[4]; + /* + * reserved01: + * bits 1-6: reserved + * bit 0: align + */ + u8 reserved01; + u8 reserved02[7]; + u32 logical_block_size; + u64 alignment_granularity; + u64 lowest_aligned_lba; +}; + +/* + * Enterprise SSC Feature + * + * code == 0x0100 + */ +struct d0_enterprise_ssc { + u16 baseComID; + u16 numComIDs; + /* range_crossing: + * bits 1-6: reserved + * bit 0: range crossing + */ + u8 range_crossing; + u8 reserved01; + u16 reserved02; + u32 reserved03; + u32 reserved04; +}; + +/* + * Opal V1 feature + * + * code == 0x0200 + */ +struct d0_opal_v100 { + u16 baseComID; + u16 numComIDs; +}; + +/* + * Single User Mode feature + * + * code == 0x0201 + */ +struct d0_single_user_mode { + u32 num_locking_objects; + /* reserved01: + * bit 0: any + * bit 1: all + * bit 2: policy + * bits 3-7: reserved + */ + u8 reserved01; + u8 reserved02; + u16 reserved03; + u32 reserved04; +}; + +/* + * Additonal Datastores feature + * + * code == 0x0202 + */ +struct d0_datastore_table { + u16 reserved01; + u16 max_tables; + u32 max_size_tables; + u32 table_size_alignment; +}; + +/* + * OPAL 2.0 feature + * + * code == 0x0203 + */ +struct d0_opal_v200 { + u16 baseComID; + u16 numComIDs; + /* range_crossing: + * bits 1-6: reserved + * bit 0: range crossing + */ + u8 range_crossing; + /* num_locking_admin_auth: + * not aligned to 16 bits, so use two u8. + * stored in big endian: + * 0: MSB + * 1: LSB + */ + u8 num_locking_admin_auth[2]; + /* num_locking_user_auth: + * not aligned to 16 bits, so use two u8. + * stored in big endian: + * 0: MSB + * 1: LSB + */ + u8 num_locking_user_auth[2]; + u8 initialPIN; + u8 revertedPIN; + u8 reserved01; + u32 reserved02; +}; + +/* Union of features used to parse the discovery 0 response */ +struct d0_features { + u16 code; + /* + * r_version bits: + * bits 4-7: version + * bits 0-3: reserved + */ + u8 r_version; + u8 length; + u8 features[]; +}; + +struct key *request_user_key(const char *master_desc, const u8 **master_key, + size_t *master_keylen); + +#endif /* _NVME_OPAL_INTERNAL_H */ diff --git a/lib/sed-opal_key.c b/lib/sed-opal_key.c new file mode 100644 index 0000000..0b4de01 --- /dev/null +++ b/lib/sed-opal_key.c @@ -0,0 +1,46 @@ +/* + * Copyright ? 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Author: + * Rafael Antognolli <rafael.antognolli at intel.com> + */ + +#include <linux/key.h> +#include "sed-opal_internal.h" + +struct key *request_user_key(const char *master_desc, const u8 **master_key, + size_t *master_keylen) +{ + const struct user_key_payload *upayload; + struct key *ukey; + + ukey = request_key(&key_type_user, master_desc, NULL); + if (IS_ERR(ukey)) + goto error; + + down_read(&ukey->sem); + upayload = user_key_payload(ukey); + *master_key = upayload->data; + *master_keylen = upayload->datalen; +error: + return ukey; +} diff --git a/lib/sed.c b/lib/sed.c new file mode 100644 index 0000000..06cacd9 --- /dev/null +++ b/lib/sed.c @@ -0,0 +1,303 @@ +#include <linux/blkdev.h> +#include <linux/sed.h> +#include <linux/sed-opal.h> + +#ifndef CONFIG_SED_OPAL +static int sed_opal_save(struct block_device *bdev, struct sed_key *sed) + { return -EOPNOTSUPP; } +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_take_ownership(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_activate_lsp(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_set_pw(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_activate_user(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_reverttper(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_setup_locking_range(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_adduser_to_lr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_do_mbr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } +static int sed_opal_erase_lr(struct block_device *bdev, struct sed_key *key) + { return -EOPNOTSUPP; } + +#else + +static int sed_opal_save(struct block_device *bdev, struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_save(bdev, key); +} + +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_lock_unlock(bdev, key); +} + +static int sed_opal_take_ownership(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_take_ownership(bdev, key); +} + +static int sed_opal_activate_lsp(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_activate_lsp(bdev, key); +} + +static int sed_opal_set_pw(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_set_new_pw(bdev, key); +} + +static int sed_opal_activate_user(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_activate_user(bdev, key); +} + +static int sed_opal_reverttper(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_reverttper(bdev, key); +} + +static int sed_opal_setup_lr(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_setup_locking_range(bdev, key); +} + +static int sed_opal_adduser_to_lr(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_add_user_to_lr(bdev, key); +} + +static int sed_opal_do_mbr(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_enable_disable_shadow_mbr(bdev, key); +} + +static int sed_opal_erase_lr(struct block_device *bdev, + struct sed_key *key) +{ + + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + return opal_erase_locking_range(bdev, key); +} +#endif + +int sed_save(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_LOCK_UNLOCK: + return sed_opal_save(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_lock_unlock(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_LOCK_UNLOCK: + return sed_opal_lock_unlock(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_take_ownership(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL: + return sed_opal_take_ownership(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_activate_lsp(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL: + return sed_opal_activate_lsp(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_set_pw(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_PW: + return sed_opal_set_pw(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_activate_user(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_ACT_USR: + return sed_opal_activate_user(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_reverttper(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL: + return sed_opal_reverttper(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_LR_SETUP: + return sed_opal_setup_lr(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_LOCK_UNLOCK: + return sed_opal_adduser_to_lr(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_do_mbr(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL_MBR_DATA: + return sed_opal_do_mbr(bdev, key); + } + + return -EOPNOTSUPP; +} + +int sed_erase_lr(struct block_device *bdev, struct sed_key *key) +{ + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || + !bdev->bd_disk->fops->sec_ops) + return -EOPNOTSUPP; + + switch (key->sed_type) { + case OPAL: + return sed_opal_erase_lr(bdev, key); + } + + return -EOPNOTSUPP; +} -- 2.7.4 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [RFC PATCH 2/6] lib: Add Sed-opal library 2016-10-31 21:58 ` Scott Bauer @ 2016-11-01 18:56 ` Jon Derrick -1 siblings, 0 replies; 32+ messages in thread From: Jon Derrick @ 2016-11-01 18:56 UTC (permalink / raw) To: Scott Bauer Cc: keith.busch, hch, Rafael.Antognolli, linux-nvme, axboe, linux-block, j.naumann SGkgUmFmYWVsLCBTY290dCwKCgpGaXJzdCBvZmYsIGNvbmdyYXRzIG9uIHRoZSBzZXQhIEl0IGxv b2tzIGdvb2Qgc28gZmFyLgoKSnVzdCBzb21lIHNtYWxsIG5pdHMgYmVsb3cgc2luY2UgeW91IGhh dmUgdG8gcmVzcGluIGl0IGFueXdheXMgOikKCk9uIE1vbiwgT2N0IDMxLCAyMDE2IGF0IDAzOjU4 OjE1UE0gLTA2MDAsIFNjb3R0IEJhdWVyIHdyb3RlOgo+IFRoaXMgcGF0Y2ggaW1wbGVtZW50cyB0 aGUgbmVjZXNzYXJ5IGxvZ2ljIHRvIGJyaW5nIGFuIE9wYWwKPiBlbmFibGVkIGRyaXZlIG91dCBv ZiBhIGZhY3RvcnktZW5hYmxlZCBpbnRvIGEgd29ya2luZwo+IE9wYWwgc3RhdGUuCj4gCj4gVGhp cyBwYXRjaCBzZXQgYWxzbyBlbmFibGVzIGxvZ2ljIHRvIHNhdmUgYSBwYXNzd29yZCB0bwo+IGJl IHJlcGxheWVkIGR1cmluZyBhIHJlc3VtZSBmcm9tIHN1c3BlbmQuIFRoZSBrZXkgY2FuIGJlCj4g c2F2ZWQgaW4gdGhlIGRyaXZlciBvciBpbiB0aGUgS2VybmVsJ3MgS2V5IG1hbmFnbWVudC4KPiAK PiBTaWduZWQtb2ZmLWJ5OiBTY290dCBCYXVlciA8c2NvdHQuYmF1ZXJAaW50ZWwuY29tPgo+IFNp Z25lZC1vZmYtYnk6IFJhZmFlbCBBbnRvZ25vbGxpIDxSYWZhZWwuQW50b2dub2xsaUBpbnRlbC5j b20+Cj4gLS0tCj4gIGxpYi9zZWQtb3BhbC5jICAgICAgICAgIHwgMzMzNyArKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwo+ICBsaWIvc2VkLW9wYWxfaW50ZXJu YWwuaCB8ICA1ODYgKysrKysrKysrCj4gIGxpYi9zZWQtb3BhbF9rZXkuYyAgICAgIHwgICA0NiAr Cj4gIGxpYi9zZWQuYyAgICAgICAgICAgICAgIHwgIDMwMyArKysrKwo+ICA0IGZpbGVzIGNoYW5n ZWQsIDQyNzIgaW5zZXJ0aW9ucygrKQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL3NlZC1vcGFs LmMKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGxpYi9zZWQtb3BhbF9pbnRlcm5hbC5oCj4gIGNyZWF0 ZSBtb2RlIDEwMDY0NCBsaWIvc2VkLW9wYWxfa2V5LmMKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGxp Yi9zZWQuYwo+IAo+IGRpZmYgLS1naXQgYS9saWIvc2VkLW9wYWwuYyBiL2xpYi9zZWQtb3BhbC5j Cj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwLi4xMGIzMzQ4Cj4gLS0tIC9k ZXYvbnVsbAo+ICsrKyBiL2xpYi9zZWQtb3BhbC5jCj4gQEAgLTAsMCArMSwzMzM3IEBACj4gKy8q Cj4gKyAqIENvcHlyaWdodCDCqSAyMDE2IEludGVsIENvcnBvcmF0aW9uCj4gKyAqCj4gKyAqIFBl cm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29u IG9idGFpbmluZyBhCj4gKyAqIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBk b2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCj4gKyAqIHRvIGRlYWwgaW4gdGhl IFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRp b24KPiArICogdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gs IGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsCj4gKyAqIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUg U29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZQo+ICsgKiBTb2Z0d2Fy ZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRp b25zOgo+ICsgKgo+ICsgKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJt aXNzaW9uIG5vdGljZSAoaW5jbHVkaW5nIHRoZSBuZXh0Cj4gKyAqIHBhcmFncmFwaCkgc2hhbGwg YmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUK PiArICogU29mdHdhcmUuCj4gKyAqCj4gKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMg SVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCj4gKyAqIElNUExJ RUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hB TlRBQklMSVRZLAo+ICsgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9O SU5GUklOR0VNRU5ULiAgSU4gTk8gRVZFTlQgU0hBTEwKPiArICogVEhFIEFVVEhPUlMgT1IgQ09Q WVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIK PiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBP UiBPVEhFUldJU0UsIEFSSVNJTkcKPiArICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04g V0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUwo+ICsgKiBJTiBU SEUgU09GVFdBUkUuCj4gKyAqCj4gKyAqIEF1dGhvcnM6Cj4gKyAqICAgIFJhZmFlbCBBbnRvZ25v bGxpIDxyYWZhZWwuYW50b2dub2xsaUBpbnRlbC5jb20+Cj4gKyAqICAgIFNjb3R0ICBCYXVlciAg ICAgIDxzY290dC5iYXVlckBpbnRlbC5jb20+Cj4gKyAqLwo+ICsKPiArI2RlZmluZSBwcl9mbXQo Zm10KSBLQlVJTERfTU9ETkFNRSAiOk9QQUw6ICIgZm10Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgv ZGVsYXkuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2RldmljZS5oPgo+ICsjaW5jbHVkZSA8bGludXgv a2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9saXN0Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9n ZW5oZC5oPgo+ICsjaW5jbHVkZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvdWFj Y2Vzcy5oPgo+ICsjaW5jbHVkZSA8dWFwaS9saW51eC9zZWQtb3BhbC5oPgo+ICsjaW5jbHVkZSA8 bGludXgvc2VkLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zZWQtb3BhbC5oPgo+ICsjaW5jbHVkZSA8 bGludXgvc3RyaW5nLmg+Cj4gKwo+ICsjaW5jbHVkZSAic2VkLW9wYWxfaW50ZXJuYWwuaCIKPiAr Cj4gKyNkZWZpbmUgSU9fQlVGRkVSX0xFTkdUSCAyMDQ4Cj4gKwo+ICsjZGVmaW5lIE1BWF9UT0tT IDY0Cj4gKwo+ICtzdHJ1Y3Qgb3BhbF9jbWQgewo+ICsJc3RydWN0IGJsb2NrX2RldmljZSAqYmRl djsKPiArCXNlY19jYiAqY2I7Cj4gKwl2b2lkICpjYl9kYXRhOwo+ICsKPiArCXNpemVfdCBwb3M7 Cj4gKwl1OCBjbWRfYnVmW0lPX0JVRkZFUl9MRU5HVEggKiAyXTsKPiArCXU4IHJlc3BfYnVmW0lP X0JVRkZFUl9MRU5HVEggKiAyXTsKPiArCXU4ICpjbWQ7Cj4gKwl1OCAqcmVzcDsKPiArfTsKPiAr Cj4gKy8qCj4gKyAqIE9uIHRoZSBwYXJzZWQgcmVzcG9uc2UsIHdlIGRvbid0IHN0b3JlIGFnYWlu IHRoZSB0b2tzIHRoYXQgYXJlIGFscmVhZHkKPiArICogc3RvcmVkIGluIHRoZSByZXNwb25zZSBi dWZmZXIuIEluc3RlYWQsIGZvciBlYWNoIHRva2VuLCB3ZSBqdXN0IHN0b3JlIGEKPiArICogcG9p bnRlciB0byB0aGUgcG9zaXRpb24gaW4gdGhlIGJ1ZmZlciB3aGVyZSB0aGUgdG9rZW4gc3RhcnRz LCBhbmQgdGhlIHNpemUKPiArICogb2YgdGhlIHRva2VuIGluIGJ5dGVzLgo+ICsgKi8KPiArc3Ry dWN0IG9wYWxfcmVzcF90b2sgewo+ICsJY29uc3QgdTggKnBvczsKPiArCXNpemVfdCBsZW47Cj4g KwllbnVtIE9QQUxfUkVTUE9OU0VfVE9LRU4gdHlwZTsKPiArCWVudW0gT1BBTF9BVE9NX1dJRFRI IHdpZHRoOwo+ICsJdW5pb24gewo+ICsJCXU2NCB1Owo+ICsJCXM2NCBzOwo+ICsJfSBzdG9yZWQ7 Cj4gK307Cj4gKwo+ICsvKgo+ICsgKiBGcm9tIHRoZSByZXNwb25zZSBoZWFkZXIgaXQncyBub3Qg cG9zc2libGUgdG8ga25vdyBob3cgbWFueSB0b2tlbnMgdGhlcmUgYXJlCj4gKyAqIG9uIHRoZSBw YXlsb2FkLiBTbyB3ZSBoYXJkY29kZSB0aGF0IHRoZSBtYXhpbXVtIHdpbGwgYmUgTUFYX1RPS1Ms IGFuZCBsYXRlcgo+ICsgKiBpZiB3ZSBzdGFydCBkZWFsaW5nIHdpdGggbWVzc2FnZXMgdGhhdCBo YXZlIG1vcmUgdGhhbiB0aGF0LCB3ZSBjYW4gaW5jcmVhc2UKPiArICogdGhpcyBudW1iZXIuIFRo aXMgaXMgZG9uZSB0byBhdm9pZCBoYXZpbmcgdG8gbWFrZSB0d28gcGFzc2VzIHRocm91Z2ggdGhl Cj4gKyAqIHJlc3BvbnNlLCB0aGUgZmlyc3Qgb25lIGNvdW50aW5nIGhvdyBtYW55IHRva2VucyB3 ZSBoYXZlIGFuZCB0aGUgc2Vjb25kIG9uZQo+ICsgKiBhY3R1YWxseSBzdG9yaW5nIHRoZSBwb3Np dGlvbnMuCj4gKyAqLwo+ICtzdHJ1Y3QgcGFyc2VkX3Jlc3Agewo+ICsJaW50IG51bTsKPiArCXN0 cnVjdCBvcGFsX3Jlc3BfdG9rIHRva3NbTUFYX1RPS1NdOwo+ICt9Owo+ICsKPiArc3RydWN0IG9w YWxfZGV2Owo+ICsKPiArdHlwZWRlZiB2b2lkICgqb3BhbF9jYikoaW50IGVycm9yLCBzdHJ1Y3Qg b3BhbF9kZXYgKmRldik7Cj4gKwo+ICt0eXBlZGVmIGludCAoKm9wYWxfc3RlcCkoc3RydWN0IG9w YWxfZGV2ICpkZXYpOwo+ICsKPiArc3RydWN0IG9wYWxfY29tcGxldGlvbiB7Cj4gKwlzdHJ1Y3Qg Y29tcGxldGlvbiBjbWRfY29tcGxldGlvbjsKPiArCWludCBjb21wbGV0aW9uX3N0YXR1czsKPiAr fTsKPiArCj4gK3N0cnVjdCBvcGFsX2RldiB7Cj4gKwlzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2 Owo+ICsJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCXN0cnVjdCBvcGFs X2xvY2tfdW5sb2NrIGxrdWw7Cj4gKwljb25zdCBvcGFsX3N0ZXAgKmZ1bmNzOwo+ICsJdm9pZCAq KmZ1bmNfZGF0YTsKPiArCWJvb2wgcmVzdW1lX2Zyb21fc3VzcGVuZDsKPiArCXN0cnVjdCBvcGFs X3N1c3BlbmRfdW5sayAqcmVzdW1lX2RhdGE7Cj4gKwlzaXplX3QgbnVtX2Z1bmNfZGF0YTsKPiAr CWF0b21pY190IGluX3VzZTsKPiArCXNlY3Rvcl90IHN0YXJ0Owo+ICsJc2VjdG9yX3QgbGVuZ3Ro Owo+ICsJdTggbHI7Cj4gKwl1OCBrZXlfdHlwZTsKPiArCXU4IGtleV9uYW1lW09QQUxfS0VZX01B WF07Cj4gKwlzaXplX3Qga2V5X25hbWVfbGVuOwo+ICsJdTgga2V5W09QQUxfS0VZX01BWF07Cj4g KwlzaXplX3Qga2V5X2xlbjsKPiArCXUxNiBjb21JRDsKPiArCXUzMiBIU047Cj4gKwl1MzIgVFNO Owo+ICsJdTY0IGFsaWduOwo+ICsJdTY0IGxvd2VzdF9sYmE7Cj4gKwlzdHJ1Y3QgbGlzdF9oZWFk IG5vZGU7Cj4gKwljaGFyIGRpc2tfbmFtZVtESVNLX05BTUVfTEVOXTsKPiArCWludCBzdGF0ZTsK PiArCj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgY21kOwo+ICsJc3RydWN0IHBhcnNlZF9yZXNwIHBhcnNl ZDsKPiArCj4gKwlzaXplX3QgcHJldl9kX2xlbjsKPiArCXZvaWQgKnByZXZfZGF0YTsKPiArCj4g KwlzZWNfY2IgKmZpbmFsX2NiOwo+ICsJdm9pZCAqZmluYWxfY2JfZGF0YTsKPiArCW9wYWxfc3Rl cCBlcnJvcl9jYjsKPiArCXZvaWQgKmVycm9yX2NiX2RhdGE7Cj4gKwlvcGFsX2NiIG9wZXJfY2I7 Cj4gK307Cj4gKwo+ICtMSVNUX0hFQUQob3BhbF9saXN0KTsKPiArREVGSU5FX1NQSU5MT0NLKGxp c3Rfc3BpbmxvY2spOwo+ICsKPiArc3RhdGljIHZvaWQgcHJpbnRfYnVmZmVyKGNvbnN0IHU4ICpw dHIsIHUzMiBsZW5ndGgpCj4gK3sKPiArI2lmZGVmIERFQlVHCj4gKwlwcmludF9oZXhfZHVtcF9i eXRlcygiT1BBTDogIiwgRFVNUF9QUkVGSVhfT0ZGU0VULCBwdHIsIGxlbmd0aCk7Cj4gKwlwcl9k ZWJ1ZygiXG4iKTsKPiArI2VuZGlmCj4gK30KPiArCj4gKyNkZWZpbmUgVFBFUl9TWU5DX1NVUFBP UlRFRCBCSVQoMCkKPiArCj4gK3N0YXRpYyBib29sIGNoZWNrX3RwZXIoY29uc3Qgdm9pZCAqZGF0 YSkKPiArewo+ICsJY29uc3Qgc3RydWN0IGQwX3RwZXJfZmVhdHVyZXMgKnRwZXIgPSBkYXRhOwo+ ICsJdTggZmxhZ3MgPSB0cGVyLT5zdXBwb3J0ZWRfZmVhdHVyZXM7Cj4gKwo+ICsJaWYgKCEoZmxh Z3MgJiBUUEVSX1NZTkNfU1VQUE9SVEVEKSkgewo+ICsJCXByX2VycigiVFBlciBzeW5jIG5vdCBz dXBwb3J0ZWQuIGZsYWdzID0gJWRcbiIsCj4gKwkJICAgICAgIHRwZXItPnN1cHBvcnRlZF9mZWF0 dXJlcyk7Cj4gKwkJcmV0dXJuIGZhbHNlOwo+ICsJfQo+ICsKPiArCXJldHVybiB0cnVlOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgYm9vbCBjaGVja19TVU0oY29uc3Qgdm9pZCAqZGF0YSkKPiArewo+ICsJ Y29uc3Qgc3RydWN0IGQwX3NpbmdsZV91c2VyX21vZGUgKnN1bSA9IGRhdGE7Cj4gKwl1MzIgbmxv ID0gYmUzMl90b19jcHUoc3VtLT5udW1fbG9ja2luZ19vYmplY3RzKTsKPiArCj4gKwlpZiAobmxv ID09IDApIHsKPiArCQlwcl9lcnIoIk5lZWQgYXQgbGVhc3Qgb25lIGxvY2tpbmcgb2JqZWN0Llxu Iik7Cj4gKwkJcmV0dXJuIGZhbHNlOwo+ICsJfQo+ICsKPiArCXByX2RlYnVnKCJOdW1iZXIgb2Yg bG9ja2luZyBvYmplY3RzOiAlZFxuIiwgbmxvKTsKPiArCj4gKwlyZXR1cm4gdHJ1ZTsKPiArfQo+ ICsKPiArc3RhdGljIHUxNiBnZXRfY29tSURfdjEwMChjb25zdCB2b2lkICpkYXRhKQo+ICt7Cj4g Kwljb25zdCBzdHJ1Y3QgZDBfb3BhbF92MTAwICp2MTAwID0gZGF0YTsKPiArCj4gKwlyZXR1cm4g YmUxNl90b19jcHUodjEwMC0+YmFzZUNvbUlEKTsKPiArfQo+ICsKPiArc3RhdGljIHUxNiBnZXRf Y29tSURfdjIwMChjb25zdCB2b2lkICpkYXRhKQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3QgZDBfb3Bh bF92MjAwICp2MjAwID0gZGF0YTsKPiArCj4gKwlyZXR1cm4gYmUxNl90b19jcHUodjIwMC0+YmFz ZUNvbUlEKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBfX29wYWxfc2VuZF9jbWQoc3RydWN0IG9w YWxfc3VzcGVuZF91bmxrICpkYXRhLCB1MTYgY29tSUQsCj4gKwkJCSAgIHZvaWQgKmJ1ZmZlciwg c2l6ZV90IGJ1Zmxlbiwgc2VjX2NiICpjYiwKPiArCQkJICAgdm9pZCAqY2JfZGF0YSkKPiArewo+ ICsJcmV0dXJuIGRhdGEtPm9wcy5zZW5kKGRhdGEtPmRhdGEsIGNvbUlELCBUQ0dfU0VDUF8wMSwg YnVmZmVyLCBidWZsZW4sCj4gKwkJCSAgICAgY2IsIGNiX2RhdGEpOwo+ICt9Cj4gK3N0YXRpYyBp bnQgX29wYWxfc2VuZF9jbWQoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgdTE2IGNvbUlELAo+ ICsJCQkgIHZvaWQgKmJ1ZmZlciwgc2l6ZV90IGJ1ZmxlbiwKPiArCQkJICBzZWNfY2IgKmNiLCB2 b2lkICpjYl9kYXRhKQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3Qgc2VjX29wcyAqb3BzID0gYmRldi0+ YmRfZGlzay0+Zm9wcy0+c2VjX29wczsKPiArCj4gKwlyZXR1cm4gb3BzLT5zZW5kKGJkZXYtPmJk X2Rpc2stPnByaXZhdGVfZGF0YSwgY29tSUQsCj4gKwkJCSBUQ0dfU0VDUF8wMSwgYnVmZmVyLCBi dWZsZW4sCj4gKwkJCSBjYiwgY2JfZGF0YSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgX19vcGFs X3JlY3ZfY21kKHN0cnVjdCBvcGFsX3N1c3BlbmRfdW5sayAqZGF0YSwgdTE2IGNvbUlELAo+ICsJ CQkgICB2b2lkICpidWZmZXIsIHNpemVfdCBidWZsZW4sIHNlY19jYiAqY2IsCj4gKwkJCSAgIHZv aWQgKmNiX2RhdGEpCj4gK3sKPiArCXJldHVybiBkYXRhLT5vcHMucmVjdihkYXRhLT5kYXRhLCBj b21JRCwgVENHX1NFQ1BfMDEsIGJ1ZmZlciwgYnVmbGVuLAo+ICsJCQkgICAgIGNiLCBjYl9kYXRh KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBfb3BhbF9yZWN2X2NtZChzdHJ1Y3QgYmxvY2tfZGV2 aWNlICpiZGV2LCB1MTYgY29tSUQsCj4gKwkJCSAgdm9pZCAqYnVmZmVyLCBzaXplX3QgYnVmbGVu LAo+ICsJCQkgIHNlY19jYiAqY2IsIHZvaWQgKmNiX2RhdGEpCj4gK3sKPiArCWNvbnN0IHN0cnVj dCBzZWNfb3BzICpvcHMgPSBiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzOwo+ICsKPiArCXJl dHVybiBvcHMtPnJlY3YoYmRldi0+YmRfZGlzay0+cHJpdmF0ZV9kYXRhLCBjb21JRCwKPiArCQkJ IFRDR19TRUNQXzAxLCBidWZmZXIsIGJ1ZmxlbiwKPiArCQkJIGNiLCBjYl9kYXRhKTsKPiArfQo+ ICsKPiArc3RhdGljIHZvaWQgb3BhbF9zZW5kX2NiX2NvbnQoaW50IGVycm9yLCB2b2lkICpkYXRh KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7Cj4gKwlzaXplX3QgYnVmbGVu ID0gSU9fQlVGRkVSX0xFTkdUSDsKPiArCXZvaWQgKmJ1ZmZlciA9IGRldi0+Y21kLnJlc3A7Cj4g KwlzdHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9IGJ1ZmZlcjsKPiArCj4gKwlwcl9kZWJ1ZygiJXM6 IFNlbnQgT1BBTCBjb21tYW5kOiBlcnJvcj0lZCwgb3V0c3RhbmRpbmc9JWQsIG1pblRyYW5zZmVy PSVkXG4iLAo+ICsJICAgICAgIGRldi0+ZGlza19uYW1lLCBlcnJvciwgaGRyLT5jcC5vdXRzdGFu ZGluZ0RhdGEsCj4gKwkgICAgICAgaGRyLT5jcC5taW5UcmFuc2Zlcik7Cj4gKwo+ICsJaWYgKGVy cm9yIHx8IGhkci0+Y3Aub3V0c3RhbmRpbmdEYXRhID09IDAgfHwKPiArCSAgICBoZHItPmNwLm1p blRyYW5zZmVyICE9IDApIHsKPiArCQlpZiAoZGV2LT5jbWQuY2IpCj4gKwkJCWRldi0+Y21kLmNi KGVycm9yLCBkZXYtPmNtZC5jYl9kYXRhKTsKPiArCQlyZXR1cm47Cj4gKwl9Cj4gKwo+ICsJbWVt c2V0KGJ1ZmZlciwgMCwgYnVmbGVuKTsKPiArCWlmIChkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQp Cj4gKwkJX19vcGFsX3JlY3ZfY21kKGRldi0+cmVzdW1lX2RhdGEsIGRldi0+Y29tSUQsCj4gKwkJ CQlidWZmZXIsIGJ1Zmxlbiwgb3BhbF9zZW5kX2NiX2NvbnQsIGRldik7Cj4gKwllbHNlCj4gKwkJ X29wYWxfcmVjdl9jbWQoZGV2LT5iZGV2LCBkZXYtPmNvbUlELCBidWZmZXIsIGJ1ZmxlbiwKPiAr CQkJICAgICAgIG9wYWxfc2VuZF9jYl9jb250LCBkZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9p ZCBvcGFsX3NlbmRfY2IoaW50IGVycm9yLCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3Qgb3Bh bF9kZXYgKmRldiA9IGRhdGE7Cj4gKwlzaXplX3QgYnVmbGVuID0gSU9fQlVGRkVSX0xFTkdUSDsK PiArCXZvaWQgKmJ1ZmZlciA9IGRldi0+Y21kLnJlc3A7Cj4gKwo+ICsJaWYgKGVycm9yKSB7Cj4g KwkJaWYgKGRldi0+Y21kLmNiKQo+ICsJCQlkZXYtPmNtZC5jYihlcnJvciwgZGV2LT5jbWQuY2Jf ZGF0YSk7Cj4gKwkJcmV0dXJuOwo+ICsJfQo+ICsKPiArCW1lbXNldChidWZmZXIsIDAsIGJ1Zmxl bik7Cj4gKwlpZiAoZGV2LT5yZXN1bWVfZnJvbV9zdXNwZW5kKQo+ICsJCV9fb3BhbF9yZWN2X2Nt ZChkZXYtPnJlc3VtZV9kYXRhLCBkZXYtPmNvbUlELAo+ICsJCQkJYnVmZmVyLCBidWZsZW4sIG9w YWxfc2VuZF9jYl9jb250LCBkZXYpOwo+ICsJZWxzZQo+ICsJCV9vcGFsX3JlY3ZfY21kKGRldi0+ YmRldiwgZGV2LT5jb21JRCwgYnVmZmVyLCBidWZsZW4sCj4gKwkJCSAgICAgICBvcGFsX3NlbmRf Y2JfY29udCwgZGV2KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBvcGFsX3NlbmRfcmVjdihzdHJ1 Y3Qgb3BhbF9kZXYgKmRldiwgc2VjX2NiICpjYiwgdm9pZCAqY2JfZGF0YSkKPiArewo+ICsJc2l6 ZV90IGJ1ZmxlbiA9IElPX0JVRkZFUl9MRU5HVEg7Cj4gKwl2b2lkICpidWZmZXIgPSBkZXYtPmNt ZC5jbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWRldi0+Y21kLmNiID0gY2I7Cj4gKwlkZXYtPmNt ZC5jYl9kYXRhID0gY2JfZGF0YTsKPiArCWlmIChkZXYtPnJlc3VtZV9mcm9tX3N1c3BlbmQpCj4g KwkJcmV0ID0gX19vcGFsX3NlbmRfY21kKGRldi0+cmVzdW1lX2RhdGEsIGRldi0+Y29tSUQsIGJ1 ZmZlciwKPiArCQkJCSAgICAgIGJ1Zmxlbiwgb3BhbF9zZW5kX2NiLCBkZXYpOwo+ICsJZWxzZQo+ ICsJCXJldCA9IF9vcGFsX3NlbmRfY21kKGRldi0+YmRldiwgZGV2LT5jb21JRCwgYnVmZmVyLCBi dWZsZW4sCj4gKwkJCQkgICAgIG9wYWxfc2VuZF9jYiwgZGV2KTsKPiArCj4gKwlyZXR1cm4gcmV0 Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjaGVja19nZW9tZXRyeShzdHJ1Y3Qgb3BhbF9kZXYg KmRldiwgY29uc3Qgdm9pZCAqZGF0YSkKPiArewo+ICsJY29uc3Qgc3RydWN0IGQwX2dlb21ldHJ5 X2ZlYXR1cmVzICpnZW8gPSBkYXRhOwo+ICsKPiArCWRldi0+YWxpZ24gPSBnZW8tPmFsaWdubWVu dF9ncmFudWxhcml0eTsKPiArCWRldi0+bG93ZXN0X2xiYSA9IGdlby0+bG93ZXN0X2FsaWduZWRf bGJhOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBvcGFsX2Rpc2NvdmVyeTBfZW5kKGludCBlcnJv ciwgdm9pZCAqZGF0YSkKPiArewo+ICsJYm9vbCBmb3VuZENvbUlEID0gZmFsc2UsIHN1cHBvcnRl ZCA9IHRydWUsIHNpbmdsZV91c2VyID0gZmFsc2U7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9 IGRhdGE7Cj4gKwljb25zdCBzdHJ1Y3QgZDBfaGVhZGVyICpoZHI7Cj4gKwljb25zdCB1OCAqZXBv cywgKmNwb3M7Cj4gKwl1MTYgY29tSUQgPSAwOwo+ICsKPiArCWlmIChlcnJvcikgewo+ICsJCXBy X2VycigiJXM6IFNlbmRpbmcgZGlzY292ZXJ5MCBmYWlsZWRcbiIsIGRldi0+ZGlza19uYW1lKTsK PiArCQlnb3RvIGVycl9jYWxsYmFjazsKPiArCX0KPiArCj4gKwllcG9zID0gZGV2LT5jbWQucmVz cDsKPiArCWNwb3MgPSBkZXYtPmNtZC5yZXNwOwo+ICsJaGRyID0gKHN0cnVjdCBkMF9oZWFkZXIg KilkZXYtPmNtZC5yZXNwOwo+ICsKPiArCXByaW50X2J1ZmZlcihkZXYtPmNtZC5yZXNwLCBiZTMy X3RvX2NwdShoZHItPmxlbmd0aCkpOwo+ICsKPiArCWVwb3MgKz0gYmUzMl90b19jcHUoaGRyLT5s ZW5ndGgpOyAvKiBlbmQgb2YgYnVmZmVyICovCj4gKwljcG9zICs9IHNpemVvZigqaGRyKTsgLyog Y3VycmVudCBwb3NpdGlvbiBvbiBidWZmZXIgKi8KPiArCj4gKwl3aGlsZSAoY3BvcyA8IGVwb3Mg JiYgc3VwcG9ydGVkKSB7Cj4gKwkJY29uc3Qgc3RydWN0IGQwX2ZlYXR1cmVzICpib2R5ID0KPiAr CQkJKGNvbnN0IHN0cnVjdCBkMF9mZWF0dXJlcyAqKWNwb3M7Cj4gKwo+ICsJCXN3aXRjaCAoYmUx Nl90b19jcHUoYm9keS0+Y29kZSkpIHsKPiArCQljYXNlIEZDX1RQRVI6Cj4gKwkJCXN1cHBvcnRl ZCA9IGNoZWNrX3RwZXIoYm9keS0+ZmVhdHVyZXMpOwo+ICsJCQlicmVhazsKPiArCQljYXNlIEZD X1NJTkdMRVVTRVI6Cj4gKwkJCXNpbmdsZV91c2VyID0gY2hlY2tfU1VNKGJvZHktPmZlYXR1cmVz KTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBGQ19HRU9NRVRSWToKPiArCQkJY2hlY2tfZ2VvbWV0 cnkoZGV2LCBib2R5KTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBGQ19MT0NLSU5HOgo+ICsJCWNh c2UgRkNfRU5URVJQUklTRToKPiArCQljYXNlIEZDX0RBVEFTVE9SRToKPiArCQkJLyogc29tZSBp Z25vcmVkIHByb3BlcnRpZXMgKi8KPiArCQkJcHJfZGVidWcoIiVzOiBGb3VuZCBPUEFMIGZlYXR1 cmUgZGVzY3JpcHRpb246ICVkXG4iLAo+ICsJCQkJIGRldi0+ZGlza19uYW1lLCBiZTE2X3RvX2Nw dShib2R5LT5jb2RlKSk7Cj4gKwkJCWJyZWFrOwo+ICsJCWNhc2UgRkNfT1BBTFYxMDA6Cj4gKwkJ CWNvbUlEID0gZ2V0X2NvbUlEX3YxMDAoYm9keS0+ZmVhdHVyZXMpOwo+ICsJCQlmb3VuZENvbUlE ID0gdHJ1ZTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBGQ19PUEFMVjIwMDoKPiArCQkJY29tSUQg PSBnZXRfY29tSURfdjIwMChib2R5LT5mZWF0dXJlcyk7Cj4gKwkJCWZvdW5kQ29tSUQgPSB0cnVl Owo+ICsJCQlicmVhazsKPiArCQlkZWZhdWx0Ogo+ICsJCQlpZiAoYmUxNl90b19jcHUoYm9keS0+ Y29kZSkgPiAweGJmZmYpIHsKPiArCQkJCS8qIHZlbmRvciBzcGVjaWZpYywganVzdCBpZ25vcmUg Ki8KPiArCQkJfSBlbHNlIHsKPiArCQkJCXByX3dhcm4oIiVzOiBPUEFMIFVua25vd24gZmVhdHVy ZTogJWRcbiIsCj4gKwkJCQkJZGV2LT5kaXNrX25hbWUsIGJlMTZfdG9fY3B1KGJvZHktPmNvZGUp KTsKPiArCQkJfQpTbWFsbCBuaXQsIGhvdyBhYm91dDoKCmNhc2UgMHhiZmZmIC4uLiAweGZmZmY6 CgkvKiB2ZW5kb3Igc3BlY2lmaWMsIGp1c3QgaWdub3JlICovCglicmVhazsKZGVmYXVsdDoKCXBy X3dhcm4oLi4uCgoKCj4gKwkJfQo+ICsJCWNwb3MgKz0gYm9keS0+bGVuZ3RoICsgNDsKPiArCX0K PiArCj4gKwlpZiAoIXN1cHBvcnRlZCkgewo+ICsJCXByX2VycigiJXM6IERldmljZSBub3Qgc3Vw cG9ydGVkXG4iLCBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJZ290byBlcnJfY2FsbGJhY2s7Cj4gKwl9 Cj4gKwo+ICsJaWYgKCFzaW5nbGVfdXNlcikKPiArCQlwcl93YXJuKCIlczogRGV2aWNlIGRvZXNu J3Qgc3VwcG9ydCBzaW5nbGUgdXNlciBtb2RlXG4iLAo+ICsJCQlkZXYtPmRpc2tfbmFtZSk7Cj4g Kwo+ICsJaWYgKCFmb3VuZENvbUlEKSB7Cj4gKwkJcHJfd2FybigiJXM6IENvdWxkIG5vdCBmaW5k IE9QQUwgY29tSUQgZm9yIGRldmljZS4gT1BBTCBrZXJuZWwgdW5sb2NraW5nIHdpbGwgYmUgZGlz YWJsZWRcbiIsCj4gKwkJCWRldi0+ZGlza19uYW1lKTsKPiArCQlnb3RvIGVycl9jYWxsYmFjazsK PiArCX0KPiArCj4gKwlkZXYtPmNvbUlEID0gY29tSUQ7Cj4gKwo+ICtlcnJfY2FsbGJhY2s6Cj4g KwlpZiAoZGV2LT5vcGVyX2NiKQo+ICsJCWRldi0+b3Blcl9jYihlcnJvciwgZGV2KTsKPiArfQo+ ICsKPiArc3RhdGljIGludCBvcGFsX2Rpc2NvdmVyeTAoc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4g K3sKPiArCW1lbXNldChkZXYtPmNtZC5yZXNwLCAwLCBJT19CVUZGRVJfTEVOR1RIKTsKPiArCj4g KwlpZiAoZGV2LT5yZXN1bWVfZnJvbV9zdXNwZW5kKQo+ICsJCXJldHVybiBfX29wYWxfcmVjdl9j bWQoZGV2LT5yZXN1bWVfZGF0YSwgMHgwMDAxLAo+ICsJCQkJICAgICAgIGRldi0+Y21kLnJlc3As IElPX0JVRkZFUl9MRU5HVEgsCj4gKwkJCQkgICAgICAgb3BhbF9kaXNjb3ZlcnkwX2VuZCwgZGV2 KTsKPiArCj4gKwlyZXR1cm4gX29wYWxfcmVjdl9jbWQoZGV2LT5iZGV2LCAweDAwMDEsIGRldi0+ Y21kLnJlc3AsCj4gKwkJCSAgICAgIElPX0JVRkZFUl9MRU5HVEgsIG9wYWxfZGlzY292ZXJ5MF9l bmQsCj4gKwkJCSAgICAgIGRldik7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGFkZF90b2tlbl91 OChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTggdG9rKQo+ICt7Cj4gKwljbWQtPmNtZFtjbWQtPnBv cysrXSA9IHRvazsKPiArfQo+ICsKPiArc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRkX3Rva2Vu X3U4KHN0cnVjdCBvcGFsX2NtZCAqY21kLCB1OCB0b2spCj4gK3sKPiArCUJVSUxEX0JVR19PTihJ T19CVUZGRVJfTEVOR1RIID49IFNJWkVfTUFYKTsKPiArCj4gKwlpZiAoY21kLT5wb3MgPj0gSU9f QlVGRkVSX0xFTkdUSCAtIDEpIHsKPiArCQlwcl9lcnIoIkVycm9yIGFkZGluZyB1ODogZW5kIG9m IGJ1ZmZlci5cbiIpOwo+ICsJCXJldHVybiAtRVJBTkdFOwo+ICsJfQo+ICsKPiArCWFkZF90b2tl bl91OChjbWQsIHRvayk7Cj4gKwo+ICsJcmV0dXJuIDE7Cj4gK30KPiArCj4gKyNkZWZpbmUgVElO WV9BVE9NX0RBVEFfTUFTSyBHRU5NQVNLKDUsIDApCj4gKyNkZWZpbmUgVElOWV9BVE9NX1NJR05F RCBCSVQoNikKPiArCj4gKyNkZWZpbmUgU0hPUlRfQVRPTV9JRCBCSVQoNykKPiArI2RlZmluZSBT SE9SVF9BVE9NX0JZVEVTVFJJTkcgQklUKDUpCj4gKyNkZWZpbmUgU0hPUlRfQVRPTV9TSUdORUQg QklUKDQpCj4gKyNkZWZpbmUgU0hPUlRfQVRPTV9MRU5fTUFTSyBHRU5NQVNLKDMsIDApCj4gKwo+ ICtzdGF0aWMgdm9pZCBhZGRfc2hvcnRfYXRvbV9oZWFkZXIoc3RydWN0IG9wYWxfY21kICpjbWQs IGJvb2wgYnl0ZXN0cmluZywKPiArCQkJCSAgYm9vbCBoYXNfc2lnbiwgaW50IGxlbikKPiArewo+ ICsJdTggYXRvbTsKPiArCj4gKwlhdG9tID0gU0hPUlRfQVRPTV9JRDsKPiArCWF0b20gfD0gYnl0 ZXN0cmluZyA/IFNIT1JUX0FUT01fQllURVNUUklORyA6IDA7Cj4gKwlhdG9tIHw9IGhhc19zaWdu ID8gU0hPUlRfQVRPTV9TSUdORUQgOiAwOwo+ICsJYXRvbSB8PSBsZW4gJiBTSE9SVF9BVE9NX0xF Tl9NQVNLOwo+ICsKPiArCWFkZF90b2tlbl91OChjbWQsIGF0b20pOwo+ICt9Cj4gKwo+ICsjZGVm aW5lIE1FRElVTV9BVE9NX0lEIChCSVQoNykgfCBCSVQoNikpCj4gKyNkZWZpbmUgTUVESVVNX0FU T01fQllURVNUUklORyBCSVQoNCkKPiArI2RlZmluZSBNRURJVU1fQVRPTV9TSUdORUQgQklUKDMp Cj4gKyNkZWZpbmUgTUVESVVNX0FUT01fTEVOX01BU0sgR0VOTUFTSygyLCAwKQo+ICsKPiArc3Rh dGljIHZvaWQgYWRkX21lZGl1bV9hdG9tX2hlYWRlcihzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgYm9v bCBieXRlc3RyaW5nLAo+ICsJCQkJICAgYm9vbCBoYXNfc2lnbiwgaW50IGxlbikKPiArewo+ICsJ dTggaGVhZGVyMDsKPiArCj4gKwloZWFkZXIwID0gTUVESVVNX0FUT01fSUQ7Cj4gKwloZWFkZXIw IHw9IGJ5dGVzdHJpbmcgPyBNRURJVU1fQVRPTV9CWVRFU1RSSU5HIDogMDsKPiArCWhlYWRlcjAg fD0gaGFzX3NpZ24gPyBNRURJVU1fQVRPTV9TSUdORUQgOiAwOwo+ICsJaGVhZGVyMCB8PSAobGVu ID4+IDgpICYgTUVESVVNX0FUT01fTEVOX01BU0s7Cj4gKwljbWQtPmNtZFtjbWQtPnBvcysrXSA9 IGhlYWRlcjA7Cj4gKwljbWQtPmNtZFtjbWQtPnBvcysrXSA9IGxlbjsKPiArfQo+ICsKPiArc3Rh dGljIHZvaWQgYWRkX3Rva2VuX3U2NChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTY0IG51bWJlciwg c2l6ZV90IGxlbikKPiArewo+ICsJYWRkX3Nob3J0X2F0b21faGVhZGVyKGNtZCwgZmFsc2UsIGZh bHNlLCBsZW4pOwo+ICsKPiArCXdoaWxlIChsZW4tLSkgewo+ICsJCXU4IG4gPSBudW1iZXIgPj4g KGxlbiAqIDgpOwo+ICsKPiArCQlhZGRfdG9rZW5fdTgoY21kLCBuKTsKPiArCX0KPiArfQo+ICsK PiArc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRkX3Rva2VuX3U2NChzdHJ1Y3Qgb3BhbF9jbWQg KmNtZCwgdTY0IG51bWJlcikKPiArewo+ICsJaW50IGxlbjsKPiArCWludCBtc2I7Cj4gKwo+ICsJ aWYgKCEobnVtYmVyICYgflRJTllfQVRPTV9EQVRBX01BU0spKQo+ICsJCXJldHVybiB0ZXN0X2Fu ZF9hZGRfdG9rZW5fdTgoY21kLCBudW1iZXIpOwo+ICsKPiArCW1zYiA9IGZscyhudW1iZXIpOwo+ ICsJbGVuID0gRElWX1JPVU5EX1VQKG1zYiwgNCk7Cj4gKwo+ICsJaWYgKGNtZC0+cG9zID49IElP X0JVRkZFUl9MRU5HVEggLSBsZW4gLSAxKSB7Cj4gKwkJcHJfZXJyKCJFcnJvciBhZGRpbmcgdTY0 OiBlbmQgb2YgYnVmZmVyLlxuIik7Cj4gKwkJcmV0dXJuIC1FUkFOR0U7Cj4gKwl9Cj4gKwo+ICsJ YWRkX3Rva2VuX3U2NChjbWQsIG51bWJlciwgbGVuKTsKPiArCj4gKwkvKiByZXR1cm4gbGVuZ3Ro IG9mIHRva2VuIHBsdXMgYXRvbSAqLwo+ICsJcmV0dXJuIGxlbiArIDE7Cj4gK30KPiArCj4gK3N0 YXRpYyB2b2lkIGFkZF90b2tlbl9ieXRlc3RyaW5nKHN0cnVjdCBvcGFsX2NtZCAqY21kLAo+ICsJ CQkJIGNvbnN0IHU4ICpieXRlc3RyaW5nLCBzaXplX3QgbGVuKQo+ICt7Cj4gKwltZW1jcHkoJmNt ZC0+Y21kW2NtZC0+cG9zXSwgYnl0ZXN0cmluZywgbGVuKTsKPiArCWNtZC0+cG9zICs9IGxlbjsK PiArfQo+ICsKPiArc3RhdGljIHNzaXplX3QgdGVzdF9hbmRfYWRkX3Rva2VuX2J5dGVzdHJpbmco c3RydWN0IG9wYWxfY21kICpjbWQsCj4gKwkJCQkJICAgICBjb25zdCB1OCAqYnl0ZXN0cmluZywg c2l6ZV90IGxlbikKPiArewo+ICsJc2l6ZV90IGhlYWRlcl9sZW4gPSAxOwo+ICsJYm9vbCBpc19z aG9ydF9hdG9tID0gdHJ1ZTsKPiArCj4gKwlpZiAobGVuICYgflNIT1JUX0FUT01fTEVOX01BU0sp IHsKPiArCQloZWFkZXJfbGVuID0gMjsKPiArCQlpc19zaG9ydF9hdG9tID0gZmFsc2U7Cj4gKwl9 Cj4gKwo+ICsJaWYgKGNtZC0+cG9zID49IElPX0JVRkZFUl9MRU5HVEggLSBsZW4gLSBoZWFkZXJf bGVuKSB7Cj4gKwkJcHJfZXJyKCJFcnJvciBhZGRpbmcgYnl0ZXN0cmluZzogZW5kIG9mIGJ1ZmZl ci5cbiIpOwo+ICsJCXJldHVybiAtRVJBTkdFOwo+ICsJfQo+ICsKPiArCWlmIChpc19zaG9ydF9h dG9tKQo+ICsJCWFkZF9zaG9ydF9hdG9tX2hlYWRlcihjbWQsIHRydWUsIGZhbHNlLCBsZW4pOwo+ ICsJZWxzZQo+ICsJCWFkZF9tZWRpdW1fYXRvbV9oZWFkZXIoY21kLCB0cnVlLCBmYWxzZSwgbGVu KTsKPiArCj4gKwlhZGRfdG9rZW5fYnl0ZXN0cmluZyhjbWQsIGJ5dGVzdHJpbmcsIGxlbik7Cj4g Kwo+ICsJcmV0dXJuIGhlYWRlcl9sZW4gKyBsZW47Cj4gK30KPiArCj4gKyNkZWZpbmUgTE9DS0lO R19SQU5HRV9OT05fR0xPQkFMIDB4MDMKPiArCj4gK3N0YXRpYyBpbnQgYnVpbGRfbG9ja2luZ19y YW5nZSh1OCAqYnVmZmVyLCBzaXplX3QgbGVuZ3RoLCB1OCBscikKPiArewo+ICsJaWYgKGxlbmd0 aCA8IE9QQUxfVUlEX0xFTkdUSCkKPiArCQlyZXR1cm4gLUVSQU5HRTsKPiArCj4gKwltZW1jcHko YnVmZmVyLCBPUEFMVUlEW09QQUxfTE9DS0lOR1JBTkdFX0dMT0JBTF0sIE9QQUxfVUlEX0xFTkdU SCk7Cj4gKwo+ICsJaWYgKGxyID09IDApCj4gKwkJcmV0dXJuIDA7Cj4gKwlidWZmZXJbNV0gPSBM T0NLSU5HX1JBTkdFX05PTl9HTE9CQUw7Cj4gKwlidWZmZXJbN10gPSBscjsKPiArCj4gKwlyZXR1 cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBidWlsZF9sb2NraW5nX3VzZXIodTggKmJ1ZmZl ciwgc2l6ZV90IGxlbmd0aCwgdTggbHIpCj4gK3sKPiArCWlmIChsZW5ndGggPCBPUEFMX1VJRF9M RU5HVEgpCj4gKwkJcmV0dXJuIC1FUkFOR0U7Cj4gKwo+ICsJbWVtY3B5KGJ1ZmZlciwgT1BBTFVJ RFtPUEFMX1VTRVIxX1VJRF0sIE9QQUxfVUlEX0xFTkdUSCk7Cj4gKwo+ICsJYnVmZmVyWzddID0g bHIgKyAxOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBOID0gbnVtYmVy IG9mIGZvcm1hdCBzcGVjaWZpZXJzICgxLTk5OSkgdG8gYmUgcmVwbGljYXRlZAo+ICsgKiBjID0g dTgKPiArICogdSA9IHU2NAo+ICsgKiBzID0gYnl0ZXN0cmluZywgbGVuZ3RoCj4gKyAqCj4gKyAq IHJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjIiwKPiArICoJCQkgICAgICAgdThf dmFsMSk7Cj4gKyAqCj4gKyAqIHJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICIyYzJ1 IiwKPiArICoJCQkgICAgICAgdThfdmFsMSwgdThfdmFsMiwgdTY0X3ZhbDEsIHU2NF92YWwyKTsK PiArICoKPiArICogcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgIjNzIiwKPiArICoJ CQkgICAgICAgYnl0ZXN0cmluZzEsIGxlbmd0aDEsCj4gKyAqCQkJICAgICAgIGJ5dGVzdHJpbmcy LCBsZW5ndGgyLAo+ICsgKgkJCSAgICAgICBieXRlc3RyaW5nMywgbGVuZ3RoMyk7Cj4gKyAqLwo+ ICtzdGF0aWMgaW50IHRlc3RfYW5kX2FkZF90b2tlbl92YShzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwK PiArCQkJCSBjb25zdCBjaGFyICpmbXQsIC4uLikKPiArewo+ICsJY29uc3QgdTggKml0ID0gZm10 LCAqdG1wOwo+ICsJaW50IHJldCwgbnVtID0gMSwgc3VtID0gMDsKPiArCXZhX2xpc3QgYXA7Cj4g Kwo+ICsJdmFfc3RhcnQoYXAsIGZtdCk7Cj4gKwo+ICsJd2hpbGUgKCppdCAhPSAnXDAnKSB7Cj4g KwkJdTY0IHRvazY0ID0gMDsKPiArCQl1OCB0b2ssICpic3RyOwo+ICsJCXNpemVfdCBsZW47Cj4g Kwo+ICsJCXJldCA9IDA7Cj4gKwo+ICsJCXN3aXRjaCAoKml0KSB7Cj4gKwkJY2FzZSAnMScgLi4u ICc5JzoKPiArCQkJdG1wID0gaXQ7Cj4gKwkJCW51bSA9IDA7Cj4gKwkJCXdoaWxlICgqdG1wID49 ICcwJyAmJiAqdG1wIDw9ICc5JykKPiArCQkJCW51bSA9IG51bSAqIDEwICsgKCp0bXArKyAtICcw Jyk7Cj4gKwkJCWl0ID0gdG1wOwo+ICsJCQljb250aW51ZTsKPiArCQljYXNlICdjJzoKPiArCQkJ d2hpbGUgKG51bS0tKSB7Cj4gKwkJCQl0b2sgPSB2YV9hcmcoYXAsIHVuc2lnbmVkIGludCk7Cj4g KwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdTgoY21kLCB0b2spOwo+ICsJCQkJaWYgKHJl dCA8IDApCj4gKwkJCQkJZ290byBlcnI7Cj4gKwkJCX0KPiArCQkJbnVtID0gMTsKPiArCQkJYnJl YWs7Cj4gKwkJY2FzZSAndSc6Cj4gKwkJCXdoaWxlIChudW0tLSkgewo+ICsJCQkJdG9rNjQgPSB2 YV9hcmcoYXAsIHU2NCk7Cj4gKwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdTY0KGNtZCwg dG9rNjQpOwo+ICsJCQkJaWYgKHJldCA8IDApCj4gKwkJCQkJZ290byBlcnI7Cj4gKwkJCX0KPiAr CQkJbnVtID0gMTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSAncyc6Cj4gKwkJCXdoaWxlIChudW0t LSkgewo+ICsJCQkJYnN0ciA9IHZhX2FyZyhhcCwgdTggKik7Cj4gKwkJCQlsZW4gPSB2YV9hcmco YXAsIHNpemVfdCk7Cj4gKwkJCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fYnl0ZXN0cmluZyhj bWQsIGJzdHIsCj4gKwkJCQkJCQkJICAgIGxlbik7Cj4gKwkJCQlpZiAocmV0IDwgMCkKPiArCQkJ CQlnb3RvIGVycjsKPiArCQkJfQo+ICsJCQludW0gPSAxOwo+ICsJCQlicmVhazsKPiArCQljYXNl ICcgJzoKPiArCQljYXNlICdcdCc6Cj4gKwkJCS8qIGlnbm9yZWQgKi8KPiArCQkJYnJlYWs7Cj4g KwkJZGVmYXVsdDoKPiArCQkJcHJfd2FybigiVW5yZWNvZ25pemVkIHR5cGUuXG4iKTsKPiArCQl9 Cj4gKwo+ICsJCWl0Kys7Cj4gKwkJc3VtICs9IHJldDsKPiArCX0KPiArCj4gKwl2YV9lbmQoYXAp Owo+ICsKPiArCXJldHVybiBzdW07Cj4gKwo+ICsgZXJyOgo+ICsJcHJfZXJyKCJUb2tlbiBmYWls ZWQgdG8gYmUgYWRkZWQuXG4iKTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyB2 b2lkIHNldF9jb21JRChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCwgdTE2IGNvbUlEKQo+ICt7Cj4gKwlz dHJ1Y3Qgb3BhbF9oZWFkZXIgKmhkciA9IChzdHJ1Y3Qgb3BhbF9oZWFkZXIgKiljbWQtPmNtZDsK PiArCj4gKwloZHItPmNwLmV4dGVuZGVkQ29tSURbMF0gPSBjb21JRCA+PiA4Owo+ICsJaGRyLT5j cC5leHRlbmRlZENvbUlEWzFdID0gY29tSUQ7Cj4gKwloZHItPmNwLmV4dGVuZGVkQ29tSURbMl0g PSAwOwo+ICsJaGRyLT5jcC5leHRlbmRlZENvbUlEWzNdID0gMDsKPiArfQo+ICsKPiArc3RhdGlj IGludCBjbWRfZmluYWxpemUoc3RydWN0IG9wYWxfY21kICpjbWQsIHUzMiBoc24sIHUzMiB0c24p Cj4gK3sKPiArCXN0cnVjdCBvcGFsX2hlYWRlciAqaGRyOwo+ICsJaW50IHJldDsKPiArCj4gKwly ZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiNmMiLAo+ICsJCQkJICAgIE9QQUxfRU5E T0ZEQVRBLCBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICAwLCAwLCAwLCBPUEFMX0VORExJU1Qp Owo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCJFcnJvciBmaW5hbGl6aW5nIGNv bW1hbmQuXG4iKTsKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCX0KPiArCj4gKwloZHIgPSAoc3Ry dWN0IG9wYWxfaGVhZGVyICopIGNtZC0+Y21kOwo+ICsKPiArCWhkci0+cGt0LlRTTiA9IGNwdV90 b19iZTMyKHRzbik7Cj4gKwloZHItPnBrdC5IU04gPSBjcHVfdG9fYmUzMihoc24pOwo+ICsKPiAr CWhkci0+c3VicGt0Lmxlbmd0aCA9IGNwdV90b19iZTMyKGNtZC0+cG9zIC0gc2l6ZW9mKCpoZHIp KTsKPiArCXdoaWxlIChjbWQtPnBvcyAlIDQpIHsKPiArCQlpZiAoY21kLT5wb3MgPj0gSU9fQlVG RkVSX0xFTkdUSCkgewo+ICsJCQlwcl9lcnIoIkVycm9yOiBCdWZmZXIgb3ZlcnJ1blxuIik7Cj4g KwkJCXJldHVybiAtRVJBTkdFOwo+ICsJCX0KPiArCQljbWQtPmNtZFtjbWQtPnBvcysrXSA9IDA7 Cj4gKwl9Cj4gKwloZHItPnBrdC5sZW5ndGggPSBjcHVfdG9fYmUzMihjbWQtPnBvcyAtIHNpemVv ZihoZHItPmNwKSAtCj4gKwkJCQkgICAgICBzaXplb2YoaGRyLT5wa3QpKTsKPiArCWhkci0+Y3Au bGVuZ3RoID0gY3B1X3RvX2JlMzIoY21kLT5wb3MgLSBzaXplb2YoaGRyLT5jcCkpOwo+ICsKPiAr CXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZW51bSBPUEFMX1JFU1BPTlNFX1RPS0VOIHRv a2VuX3R5cGUoY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLAo+ICsJCQkJCSAgIGludCBu KQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3Qgb3BhbF9yZXNwX3RvayAqdG9rOwo+ICsKPiArCWlmIChu ID49IHJlc3AtPm51bSkgewo+ICsJCXByX2VycigiVG9rZW4gbnVtYmVyIGRvZXNuJ3QgZXhpc3Q6 ICVkLCByZXNwOiAlZFxuIiwKPiArCQkgICAgICAgbiwgcmVzcC0+bnVtKTsKPiArCQlyZXR1cm4g T1BBTF9EVEFfVE9LRU5JRF9JTlZBTElEOwo+ICsJfQo+ICsKPiArCXRvayA9ICZyZXNwLT50b2tz W25dOwo+ICsJaWYgKHRvay0+bGVuID09IDApIHsKPiArCQlwcl9lcnIoIlRva2VuIGxlbmd0aCBt dXN0IGJlIG5vbi16ZXJvXG4iKTsKPiArCQlyZXR1cm4gT1BBTF9EVEFfVE9LRU5JRF9JTlZBTElE Owo+ICsJfQo+ICsKPiArCXJldHVybiB0b2stPnR5cGU7Cj4gK30KPiArCj4gKy8qCj4gKyAqIFRo aXMgZnVuY3Rpb24gcmV0dXJucyAwIGluIGNhc2Ugb2YgaW52YWxpZCB0b2tlbi4gT25lIHNob3Vs ZCBjYWxsCj4gKyAqIHRva2VuX3R5cGUoKSBmaXJzdCB0byBmaW5kIG91dCBpZiB0aGUgdG9rZW4g aXMgdmFsaWQgb3Igbm90Lgo+ICsgKi8KPiArc3RhdGljIGVudW0gT1BBTF9UT0tFTiByZXNwb25z ZV9nZXRfdG9rZW4oY29uc3Qgc3RydWN0IHBhcnNlZF9yZXNwICpyZXNwLAo+ICsJCQkJCSAgaW50 IG4pCj4gK3sKPiArCWNvbnN0IHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2s7Cj4gKwo+ICsJaWYg KG4gPj0gcmVzcC0+bnVtKSB7Cj4gKwkJcHJfZXJyKCJUb2tlbiBudW1iZXIgZG9lc24ndCBleGlz dDogJWQsIHJlc3A6ICVkXG4iLAo+ICsJCSAgICAgICBuLCByZXNwLT5udW0pOwo+ICsJCXJldHVy biAwOwo+ICsJfQo+ICsKPiArCXRvayA9ICZyZXNwLT50b2tzW25dOwo+ICsJaWYgKHRvay0+bGVu ID09IDApIHsKPiArCQlwcl9lcnIoIlRva2VuIGxlbmd0aCBtdXN0IGJlIG5vbi16ZXJvXG4iKTsK PiArCQlyZXR1cm4gMDsKPiArCX0KPiArCj4gKwlyZXR1cm4gdG9rLT5wb3NbMF07Cj4gK30KPiAr Cj4gK3N0YXRpYyBzaXplX3QgcmVzcG9uc2VfcGFyc2VfdGlueShzdHJ1Y3Qgb3BhbF9yZXNwX3Rv ayAqdG9rLAo+ICsJCQkJICBjb25zdCB1OCAqcG9zKQo+ICt7Cj4gKwl0b2stPnBvcyA9IHBvczsK PiArCXRvay0+bGVuID0gMTsKPiArCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX1RJTlk7Cj4gKwo+ ICsJaWYgKHBvc1swXSAmIFRJTllfQVRPTV9TSUdORUQpIHsKPiArCQl0b2stPnR5cGUgPSBPUEFM X0RUQV9UT0tFTklEX1NJTlQ7Cj4gKwl9IGVsc2Ugewo+ICsJCXRvay0+dHlwZSA9IE9QQUxfRFRB X1RPS0VOSURfVUlOVDsKPiArCQl0b2stPnN0b3JlZC51ID0gcG9zWzBdICYgMHgzZjsKPiArCX0K PiArCj4gKwlyZXR1cm4gdG9rLT5sZW47Cj4gK30KPiArCj4gK3N0YXRpYyBzaXplX3QgcmVzcG9u c2VfcGFyc2Vfc2hvcnQoc3RydWN0IG9wYWxfcmVzcF90b2sgKnRvaywKPiArCQkJCSAgIGNvbnN0 IHU4ICpwb3MpCj4gK3sKPiArCXRvay0+cG9zID0gcG9zOwo+ICsJdG9rLT5sZW4gPSAocG9zWzBd ICYgU0hPUlRfQVRPTV9MRU5fTUFTSykgKyAxOwo+ICsJdG9rLT53aWR0aCA9IE9QQUxfV0lEVEhf U0hPUlQ7Cj4gKwo+ICsJaWYgKHBvc1swXSAmIFNIT1JUX0FUT01fQllURVNUUklORykgewo+ICsJ CXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfQllURVNUUklORzsKPiArCX0gZWxzZSBpZiAo cG9zWzBdICYgU0hPUlRfQVRPTV9TSUdORUQpIHsKPiArCQl0b2stPnR5cGUgPSBPUEFMX0RUQV9U T0tFTklEX1NJTlQ7Cj4gKwl9IGVsc2Ugewo+ICsJCXU2NCB1X2ludGVnZXIgPSAwOwo+ICsJCWlu dCBpLCBiID0gMDsKPiArCj4gKwkJdG9rLT50eXBlID0gT1BBTF9EVEFfVE9LRU5JRF9VSU5UOwo+ ICsJCWlmICh0b2stPmxlbiA+IDkpClNob3VsZCB0aGlzIGJlIGxlbiA+IDggb3IgbGVuID49IDkg PwoKPiArCQkJcHJfd2FybigidWludDY0IHdpdGggbW9yZSB0aGFuIDggYnl0ZXNcbiIpOwo+ICsJ CWZvciAoaSA9IHRvay0+bGVuIC0gMTsgaSA+IDA7IGktLSkgewo+ICsJCQl1X2ludGVnZXIgfD0g KCh1NjQpcG9zW2ldIDw8ICg4ICogYikpOwo+ICsJCQliKys7Cj4gKwkJfQpJdCBkb2Vzbid0IGxv b2sgcGFydGljdWxhcmx5IHNhZmUgdG8ga2VlcCB1c2luZyB0aGlzIGRyaXZlciBvbiBhIGRyaXZl CmlmIGl0IHJldHVybnMgYSBsZW4gPiA4LiBCdXQgdGhlIHNwZWNzIGRvIGFsbG93IDE2LWJ5dGUg ZGF0YSBpbiBhIHNob3J0CmF0b20sIHNvIG1heWJlIHdlIHNob3VsZCBiYWlsIG9uIGFsbG93aW5n IHRoZSBkcml2ZXIgdG8gbWFuYWdlIHRoZQpkcml2ZSwgb3IgY2hhbmdlIHRoZSB0eXBlcyB0byBz b21lIDE2LWJ5dGUgdHlwZT8KCj4gKwkJdG9rLT5zdG9yZWQudSA9IHVfaW50ZWdlcjsKPiArCX0K PiArCj4gKwlyZXR1cm4gdG9rLT5sZW47Cj4gK30KPiArCj4gK3N0YXRpYyBzaXplX3QgcmVzcG9u c2VfcGFyc2VfbWVkaXVtKHN0cnVjdCBvcGFsX3Jlc3BfdG9rICp0b2ssCj4gKwkJCQkgICAgY29u c3QgdTggKnBvcykKPiArewo+ICsJdG9rLT5wb3MgPSBwb3M7Cj4gKwl0b2stPmxlbiA9ICgoKHBv c1swXSAmIE1FRElVTV9BVE9NX0xFTl9NQVNLKSA8PCA4KSB8IHBvc1sxXSkgKyAyOwo+ICsJdG9r LT53aWR0aCA9IE9QQUxfV0lEVEhfTUVESVVNOwo+ICsKPiArCWlmIChwb3NbMF0gJiBNRURJVU1f QVRPTV9CWVRFU1RSSU5HKQo+ICsJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfQllURVNU UklORzsKPiArCWVsc2UgaWYgKHBvc1swXSAmIE1FRElVTV9BVE9NX1NJR05FRCkKPiArCQl0b2st PnR5cGUgPSBPUEFMX0RUQV9UT0tFTklEX1NJTlQ7Cj4gKwllbHNlCj4gKwkJdG9rLT50eXBlID0g T1BBTF9EVEFfVE9LRU5JRF9VSU5UOwo+ICsKPiArCXJldHVybiB0b2stPmxlbjsKPiArfQo+ICsK PiArI2RlZmluZSBMT05HX0FUT01fSUQgKEJJVCg3KSB8IEJJVCg2KSB8IEJJVCg1KSkKPiArI2Rl ZmluZSBMT05HX0FUT01fQllURVNUUklORyBCSVQoMSkKPiArI2RlZmluZSBMT05HX0FUT01fU0lH TkVEIEJJVCgwKQo+ICtzdGF0aWMgc2l6ZV90IHJlc3BvbnNlX3BhcnNlX2xvbmcoc3RydWN0IG9w YWxfcmVzcF90b2sgKnRvaywKPiArCQkJCSAgY29uc3QgdTggKnBvcykKPiArewo+ICsJdG9rLT5w b3MgPSBwb3M7Cj4gKwl0b2stPmxlbiA9ICgocG9zWzFdIDw8IDE2KSB8IChwb3NbMl0gPDwgOCkg fCBwb3NbM10pICsgNDsKPiArCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX0xPTkc7Cj4gKwo+ICsJ aWYgKHBvc1swXSAmIExPTkdfQVRPTV9CWVRFU1RSSU5HKQo+ICsJCXRvay0+dHlwZSA9IE9QQUxf RFRBX1RPS0VOSURfQllURVNUUklORzsKPiArCWVsc2UgaWYgKHBvc1swXSAmIExPTkdfQVRPTV9T SUdORUQpCj4gKwkJdG9rLT50eXBlID0gT1BBTF9EVEFfVE9LRU5JRF9TSU5UOwo+ICsJZWxzZQo+ ICsJCXRvay0+dHlwZSA9IE9QQUxfRFRBX1RPS0VOSURfVUlOVDsKPiArCj4gKwlyZXR1cm4gdG9r LT5sZW47Cj4gK30KPiArCj4gK3N0YXRpYyBzaXplX3QgcmVzcG9uc2VfcGFyc2VfdG9rZW4oc3Ry dWN0IG9wYWxfcmVzcF90b2sgKnRvaywKPiArCQkJCSAgIGNvbnN0IHU4ICpwb3MpCj4gK3sKPiAr CXRvay0+cG9zID0gcG9zOwo+ICsJdG9rLT5sZW4gPSAxOwo+ICsJdG9rLT50eXBlID0gT1BBTF9E VEFfVE9LRU5JRF9UT0tFTjsKPiArCXRvay0+d2lkdGggPSBPUEFMX1dJRFRIX1RPS0VOOwo+ICsK PiArCXJldHVybiB0b2stPmxlbjsKPiArfQo+ICsKPiArc3RhdGljIGludCByZXNwb25zZV9wYXJz ZShjb25zdCB1OCAqYnVmLCBzaXplX3QgbGVuZ3RoLAo+ICsJCQkgIHN0cnVjdCBwYXJzZWRfcmVz cCAqcmVzcCkKPiArewo+ICsJY29uc3Qgc3RydWN0IG9wYWxfaGVhZGVyICpoZHI7Cj4gKwlzdHJ1 Y3Qgb3BhbF9yZXNwX3RvayAqaXRlcjsKPiArCWludCByZXQsIG51bV9lbnRyaWVzID0gMDsKPiAr CXUzMiBjcG9zID0gMCwgdG90YWw7Cj4gKwlzaXplX3QgdG9rZW5fbGVuZ3RoOwo+ICsJY29uc3Qg dTggKnBvczsKPiArCj4gKwlpZiAoIWJ1ZikKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlp ZiAoIXJlc3ApCj4gKwkJcmV0dXJuIC1FRkFVTFQ7Cj4gKwo+ICsJaGRyID0gKHN0cnVjdCBvcGFs X2hlYWRlciAqKWJ1ZjsKPiArCXBvcyA9IGJ1ZjsKPiArCXBvcyArPSBzaXplb2YoKmhkcik7Cj4g Kwo+ICsJcHJfZGVidWcoIlJlc3BvbnNlIHNpemU6IGNwOiAlZCwgcGt0OiAlZCwgc3VicGt0OiAl ZFxuIiwKPiArCQkgYmUzMl90b19jcHUoaGRyLT5jcC5sZW5ndGgpLAo+ICsJCSBiZTMyX3RvX2Nw dShoZHItPnBrdC5sZW5ndGgpLAo+ICsJCSBiZTMyX3RvX2NwdShoZHItPnN1YnBrdC5sZW5ndGgp KTsKPiArCj4gKwlpZiAoKGhkci0+Y3AubGVuZ3RoID09IDApCj4gKwkgICAgfHwgKGhkci0+cGt0 Lmxlbmd0aCA9PSAwKQo+ICsJICAgIHx8IChoZHItPnN1YnBrdC5sZW5ndGggPT0gMCkpIHsKPiAr CQlwcl9lcnIoIkJhZCBoZWFkZXIgbGVuZ3RoLiBjcDogJWQsIHBrdDogJWQsIHN1YnBrdDogJWRc biIsCj4gKwkJICAgICAgIGJlMzJfdG9fY3B1KGhkci0+Y3AubGVuZ3RoKSwKPiArCQkgICAgICAg YmUzMl90b19jcHUoaGRyLT5wa3QubGVuZ3RoKSwKPiArCQkgICAgICAgYmUzMl90b19jcHUoaGRy LT5zdWJwa3QubGVuZ3RoKSk7Cj4gKwkJcHJpbnRfYnVmZmVyKHBvcywgc2l6ZW9mKCpoZHIpKTsK PiArCQlyZXQgPSAtRUlOVkFMOwo+ICsJCWdvdG8gZXJyOwo+ICsJfQo+ICsKPiArCWlmIChwb3Mg PiBidWYgKyBsZW5ndGgpIHsKPiArCQlyZXQgPSAtRUZBVUxUOwo+ICsJCWdvdG8gZXJyOwo+ICsJ fQo+ICsKPiArCWl0ZXIgPSByZXNwLT50b2tzOwo+ICsJdG90YWwgPSBiZTMyX3RvX2NwdShoZHIt PnN1YnBrdC5sZW5ndGgpOwo+ICsJcHJpbnRfYnVmZmVyKHBvcywgdG90YWwpOwo+ICsJd2hpbGUg KGNwb3MgPCB0b3RhbCkgewo+ICsJCWlmICghKHBvc1swXSAmIDB4ODApKSAvKiB0aW55IGF0b20g Ki8KPiArCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfdGlueShpdGVyLCBwb3MpOwo+ ICsJCWVsc2UgaWYgKCEocG9zWzBdICYgMHg0MCkpIC8qIHNob3J0IGF0b20gKi8KPiArCQkJdG9r ZW5fbGVuZ3RoID0gcmVzcG9uc2VfcGFyc2Vfc2hvcnQoaXRlciwgcG9zKTsKPiArCQllbHNlIGlm ICghKHBvc1swXSAmIDB4MjApKSAvKiBtZWRpdW0gYXRvbSAqLwo+ICsJCQl0b2tlbl9sZW5ndGgg PSByZXNwb25zZV9wYXJzZV9tZWRpdW0oaXRlciwgcG9zKTsKPiArCQllbHNlIGlmICghKHBvc1sw XSAmIDB4MTApKSAvKiBsb25nIGF0b20gKi8KPiArCQkJdG9rZW5fbGVuZ3RoID0gcmVzcG9uc2Vf cGFyc2VfbG9uZyhpdGVyLCBwb3MpOwo+ICsJCWVsc2UgLyogVE9LRU4gKi8KPiArCQkJdG9rZW5f bGVuZ3RoID0gcmVzcG9uc2VfcGFyc2VfdG9rZW4oaXRlciwgcG9zKTsKPiArCj4gKwkJcG9zICs9 IHRva2VuX2xlbmd0aDsKPiArCQljcG9zICs9IHRva2VuX2xlbmd0aDsKPiArCQlpdGVyKys7Cj4g KwkJbnVtX2VudHJpZXMrKzsKPiArCX0KPiArCj4gKwlpZiAobnVtX2VudHJpZXMgPT0gMCkgewo+ ICsJCXByX2VycigiQ291bGRuJ3QgcGFyc2UgcmVzcG9uc2UuXG4iKTsKPiArCQlyZXQgPSAtRUlO VkFMOwo+ICsJCWdvdG8gZXJyOwo+ICsJfQo+ICsJcmVzcC0+bnVtID0gbnVtX2VudHJpZXM7Cj4g Kwo+ICsJcmV0dXJuIDA7Cj4gK2VycjoKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRp YyBzaXplX3QgcmVzcG9uc2VfZ2V0X3N0cmluZyhjb25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJl c3AsIGludCBuLAo+ICsJCQkJICBjb25zdCBjaGFyICoqc3RvcmUpCj4gK3sKPiArCSpzdG9yZSA9 IE5VTEw7Cj4gKwlpZiAoIXJlc3ApIHsKPiArCQlwcl9lcnIoIlJlc3BvbnNlIGlzIE5VTExcbiIp Owo+ICsJCXJldHVybiAwOwo+ICsJfQo+ICsKPiArCWlmIChuID4gcmVzcC0+bnVtKSB7Cj4gKwkJ cHJfZXJyKCJSZXNwb25zZSBoYXMgJWQgdG9rZW5zLiBDYW4ndCBhY2Nlc3MgJWRcbiIsCj4gKwkJ ICAgICAgIHJlc3AtPm51bSwgbik7Cj4gKwkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ICsJaWYgKHJl c3AtPnRva3Nbbl0udHlwZSAhPSBPUEFMX0RUQV9UT0tFTklEX0JZVEVTVFJJTkcpIHsKPiArCQlw cl9lcnIoIlRva2VuIGlzIG5vdCBhIGJ5dGUgc3RyaW5nIVxuIik7Cj4gKwkJcmV0dXJuIDA7Cj4g Kwl9Cj4gKwo+ICsJKnN0b3JlID0gcmVzcC0+dG9rc1tuXS5wb3MgKyAxOwo+ICsJcmV0dXJuIHJl c3AtPnRva3Nbbl0ubGVuIC0gMTsKPiArfQo+ICsKPiArc3RhdGljIHU2NCByZXNwb25zZV9nZXRf dTY0KGNvbnN0IHN0cnVjdCBwYXJzZWRfcmVzcCAqcmVzcCwgaW50IG4pCj4gK3sKPiArCWlmICgh cmVzcCkgewo+ICsJCXByX2VycigiUmVzcG9uc2UgaXMgTlVMTFxuIik7Cj4gKwkJcmV0dXJuIDA7 Cj4gKwl9Cj4gKwo+ICsJaWYgKG4gPiByZXNwLT5udW0pIHsKPiArCQlwcl9lcnIoIlJlc3BvbnNl IGhhcyAlZCB0b2tlbnMuIENhbid0IGFjY2VzcyAlZFxuIiwKPiArCQkgICAgICAgcmVzcC0+bnVt LCBuKTsKPiArCQlyZXR1cm4gMDsKPiArCX0KPiArCj4gKwlpZiAocmVzcC0+dG9rc1tuXS50eXBl ICE9IE9QQUxfRFRBX1RPS0VOSURfVUlOVCkgewo+ICsJCXByX2VycigiVG9rZW4gaXMgbm90IHVu c2lnbmVkIGl0OiAlZFxuIiwKPiArCQkgICAgICAgcmVzcC0+dG9rc1tuXS50eXBlKTsKPiArCQly ZXR1cm4gMDsKPiArCX0KPiArCj4gKwlpZiAoISgocmVzcC0+dG9rc1tuXS53aWR0aCA9PSBPUEFM X1dJRFRIX1RJTlkpIHx8Cj4gKwkgICAgICAocmVzcC0+dG9rc1tuXS53aWR0aCA9PSBPUEFMX1dJ RFRIX1NIT1JUKSkpIHsKPiArCQlwcl9lcnIoIkF0b20gaXMgbm90IHNob3J0IG9yIHRpbnk6ICVk XG4iLAo+ICsJCSAgICAgICByZXNwLT50b2tzW25dLndpZHRoKTsKPiArCQlyZXR1cm4gMDsKPiAr CX0KPiArCj4gKwlyZXR1cm4gcmVzcC0+dG9rc1tuXS5zdG9yZWQudTsKPiArfQo+ICsKPiArc3Rh dGljIHU4IHJlc3BvbnNlX3N0YXR1cyhjb25zdCBzdHJ1Y3QgcGFyc2VkX3Jlc3AgKnJlc3ApCj4g K3sKPiArCWlmICgodG9rZW5fdHlwZShyZXNwLCAwKSA9PSBPUEFMX0RUQV9UT0tFTklEX1RPS0VO KQo+ICsJICAgICYmIChyZXNwb25zZV9nZXRfdG9rZW4ocmVzcCwgMCkgPT0gT1BBTF9FTkRPRlNF U1NJT04pKSB7Cj4gKwkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ICsJaWYgKHJlc3AtPm51bSA8IDUp Cj4gKwkJcmV0dXJuIERUQUVSUk9SX05PX01FVEhPRF9TVEFUVVM7Cj4gKwo+ICsJaWYgKCh0b2tl bl90eXBlKHJlc3AsIHJlc3AtPm51bSAtIDEpICE9IE9QQUxfRFRBX1RPS0VOSURfVE9LRU4pIHx8 Cj4gKwkgICAgKHRva2VuX3R5cGUocmVzcCwgcmVzcC0+bnVtIC0gNSkgIT0gT1BBTF9EVEFfVE9L RU5JRF9UT0tFTikgfHwKPiArCSAgICAocmVzcG9uc2VfZ2V0X3Rva2VuKHJlc3AsIHJlc3AtPm51 bSAtIDEpICE9IE9QQUxfRU5ETElTVCkgfHwKPiArCSAgICAocmVzcG9uc2VfZ2V0X3Rva2VuKHJl c3AsIHJlc3AtPm51bSAtIDUpICE9IE9QQUxfU1RBUlRMSVNUKSkKPiArCQlyZXR1cm4gRFRBRVJS T1JfTk9fTUVUSE9EX1NUQVRVUzsKPiArCj4gKwlyZXR1cm4gcmVzcG9uc2VfZ2V0X3U2NChyZXNw LCByZXNwLT5udW0gLSA0KTsKPiArfQo+ICsKPiArLyogUGFyc2VzIGFuZCBjaGVja3MgZm9yIGVy cm9ycyAqLwo+ICtzdGF0aWMgaW50IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoc3RydWN0IG9wYWxf ZGV2ICpkZXYpCj4gK3sKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJaW50IGVycm9yOwo+ ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsKPiArCXByaW50X2J1ZmZlcihjbWQtPmNtZCwgY21kLT5w b3MpOwo+ICsKPiArCWVycm9yID0gcmVzcG9uc2VfcGFyc2UoY21kLT5yZXNwLCBJT19CVUZGRVJf TEVOR1RILCAmZGV2LT5wYXJzZWQpOwo+ICsJaWYgKGVycm9yKSB7Cj4gKwkJcHJfZXJyKCIlczog Q291bGRuJ3QgcGFyc2UgcmVzcG9uc2UuXG4iLCBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJZ290byBl cnJfcmV0dXJuOwo+ICsJfQo+ICsKPiArCWVycm9yID0gcmVzcG9uc2Vfc3RhdHVzKCZkZXYtPnBh cnNlZCk7Cj4gKwlpZiAoZXJyb3IpCj4gKwkJcHJfZXJyKCIlczogUmVzcG9uc2UgU3RhdHVzOiAl ZFxuIiwgZGV2LT5kaXNrX25hbWUsCj4gKwkJICAgICAgIGVycm9yKTsKPiArCj4gKyBlcnJfcmV0 dXJuOgo+ICsJcmV0dXJuIGVycm9yOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjbGVhcl9vcGFs X2NtZChzdHJ1Y3Qgb3BhbF9jbWQgKmNtZCkKPiArewo+ICsJY21kLT5wb3MgPSBzaXplb2Yoc3Ry dWN0IG9wYWxfaGVhZGVyKTsKPiArCW1lbXNldChjbWQtPmNtZCwgMCwgSU9fQlVGRkVSX0xFTkdU SCk7Cj4gKwljbWQtPmNiID0gTlVMTDsKPiArCWNtZC0+Y2JfZGF0YSA9IE5VTEw7Cj4gK30KPiAr Cj4gK3N0YXRpYyB2b2lkIHN0YXJ0X29wYWxfc2Vzc2lvbl9jb250KGludCBlcnJvciwgdm9pZCAq ZGF0YSkKPiArewo+ICsJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwo+ICsJdTMyIEhTTiwg VFNOOwo+ICsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4gKwo+ICsJZXJy b3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7Cj4gKwlpZiAoZXJyb3IpCj4gKwkJZ290 byBlcnJfcmV0dXJuOwo+ICsKPiArCUhTTiA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2Vk LCA0KTsKPiArCVRTTiA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2VkLCA1KTsKPiArCj4g KwlpZiAoSFNOID09IDAgJiYgVFNOID09IDApIHsKPiArCQlwcl9lcnIoIiVzOiBDb3VsZG4ndCBh dXRoZW50aWNhdGUgc2Vzc2lvblxuIiwgZGV2LT5kaXNrX25hbWUpOwo+ICsJCWVycm9yID0gLUVQ RVJNOwo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCX0KPiArCj4gKwlkZXYtPkhTTiA9IEhTTjsK PiArCWRldi0+VFNOID0gVFNOOwo+ICsKPiArZXJyX3JldHVybjoKPiArCWlmIChkZXYtPm9wZXJf Y2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50 IGdldF9vcGFsX2tleShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJc3RydWN0IGtleSAq dWtleSA9IE5VTEw7Cj4gKwljb25zdCB1OCAqdG1wa2V5ID0gTlVMTDsKPiArCXNpemVfdCB0bXBs ZW47Cj4gKwlpbnQgcmV0ID0gMDsKPiArCj4gKwlpZiAoZGV2LT5rZXlfdHlwZSA9PSBPUEFMX0tF WV9QTEFJTikgewo+ICsJCXRtcGtleSA9IGRldi0+a2V5X25hbWU7Cj4gKwkJdG1wbGVuID0gZGV2 LT5rZXlfbmFtZV9sZW47Cj4gKwl9IGVsc2UgaWYgKGRldi0+a2V5X3R5cGUgPT0gT1BBTF9LRVlf S0VZUklORykgewo+ICsJCXVrZXkgPSByZXF1ZXN0X3VzZXJfa2V5KGRldi0+a2V5X25hbWUsICZ0 bXBrZXksICZ0bXBsZW4pOwo+ICsJCWlmIChJU19FUlIodWtleSkpIHsKPiArCQkJcHJfZXJyKCIl czogQ2FuJ3QgcmV0cmlldmUga2V5OiAlbGRcbiIsIGRldi0+ZGlza19uYW1lLAo+ICsJCQkgICAg ICAgUFRSX0VSUih1a2V5KSk7Cj4gKwkJCXJldHVybiBQVFJfRVJSKHVrZXkpOwo+ICsJCX0KPiAr CX0gZWxzZSB7Cj4gKwkJcHJfZXJyKCJSZXF1ZXN0ZWQgaW52YWxpZCBrZXkgdHlwZTogJWRcbiIs IGRldi0+a2V5X3R5cGUpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWlmICh0 bXBsZW4gPiBPUEFMX0tFWV9NQVgpIHsKPiArCQlwcl9lcnIoIlJlcXVlc3RlZCBrZXkgd2l0aCBp bnZhbGlkIHNpemU6ICV6ZFxuIiwgdG1wbGVuKTsKPiArCQlyZXQgPSAtRUlOVkFMOwo+ICsJCWdv dG8gZXJyX2V4aXQ7Cj4gKwl9Cj4gKwo+ICsJZGV2LT5rZXlfbGVuID0gdG1wbGVuOwo+ICsJaWYg KCFtZW1jcHkoZGV2LT5rZXksIHRtcGtleSwgdG1wbGVuKSkgewo+ICsJCXByX2VycigiRXJyb3Ig d2hlbiBjb3B5aW5nIGtleSIpOwo+ICsJCXJldCA9IC1FRkFVTFQ7Cj4gKwkJZ290byBlcnJfZXhp dDsKPiArCX0KPiArCj4gK2Vycl9leGl0Ogo+ICsJa2V5X3B1dCh1a2V5KTsKPiArCj4gKwlyZXR1 cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgY2xlYW5fb3BhbF9rZXkoc3RydWN0IG9wYWxf ZGV2ICpkZXYpCj4gK3sKPiArCW1lbXNldChkZXYtPmtleSwgMCwgT1BBTF9LRVlfTUFYKTsKPiAr CWRldi0+a2V5X2xlbiA9IDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgdm9pZCBjbGVhbl9m dW5jdGlvbl9kYXRhKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwkJZGV2LT5mdW5jX2Rh dGEgPSBOVUxMOwo+ICsJCWRldi0+bnVtX2Z1bmNfZGF0YSA9IDA7Cj4gK30KPiArCj4gKy8qIFRo aXMgaXMgYSBnZW5lcmljIGNvbnRpbnVlIGZuLgo+ICsgKiBXZSB1c2UgdGhpcyB3aGVuIHdlIGRv bid0IGNhcmUgYWJvdXQgdGhlIHJlc3BvbnNlIGRhdGEKPiArICogYW5kIHNpbXBseSB3YW50IHRv IGNoZWNrIHRoZSBzdGF0dXMgYW5kIGNvbnRpbnVlLgo+ICsgKi8KPiArc3RhdGljIHZvaWQgZ2Vu ZXJpY19jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKPiArewo+ICsJc3RydWN0IG9wYWxfZGV2 ICpkZXYgPSBkYXRhOwo+ICsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4g Kwo+ICsJZXJyb3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7Cj4gKwo+ICsgZXJyX3Jl dHVybjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYp Owo+ICt9CgpIb3cgYWJvdXQ6CgpzdGF0aWMgdm9pZCBnZW5lcmljX2NvbnQoaW50IGVycm9yLCB2 b2lkICpkYXRhKQp7CglzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7CgoJaWYgKCFlcnJvcikK CQllcnJvciA9IHBhcnNlX2FuZF9jaGVja19zdGF0dXMoZGV2KTsKCglpZiAoZGV2LT5vcGVyX2Ni KQoJCWRldi0+b3Blcl9jYihlcnJvciwgZGV2KTsKfQoKPiArCj4gK3N0YXRpYyB2b2lkIGVuZF9z ZXNzaW9uX2NvbnQoaW50IGVycm9yLCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9k ZXYgKmRldiA9IGRhdGE7Cj4gKwo+ICsJZGV2LT5IU04gPSAwOwo+ICsJZGV2LT5UU04gPSAwOwo+ ICsJZ2VuZXJpY19jb250KGVycm9yLCBkYXRhKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBmaW5h bGl6ZV9hbmRfc2VuZChzdHJ1Y3Qgb3BhbF9kZXYgKmRldiwgc3RydWN0IG9wYWxfY21kICpjbWQs Cj4gKwkJCSAgICAgc2VjX2NiIGNvbnQpCj4gK3sKPiArCWludCByZXQ7Cj4gKwo+ICsJcmV0ID0g Y21kX2ZpbmFsaXplKGNtZCwgZGV2LT5IU04sIGRldi0+VFNOKTsKPiArCWlmIChyZXQpIHsKPiAr CQlwcl9lcnIoIiVzOiBFcnJvciBmaW5hbGl6aW5nIGNvbW1hbmQgYnVmZmVyOiAlZFxuIiwKPiAr CQkgICAgICAgZGV2LT5kaXNrX25hbWUsIHJldCk7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiAr Cj4gKwlwcmludF9idWZmZXIoY21kLT5jbWQsIGNtZC0+cG9zKTsKPiArCj4gKwlyZXQgPSBvcGFs X3NlbmRfcmVjdihkZXYsIGNvbnQsIGRldik7Cj4gKwlpZiAocmV0KQo+ICsJCXByX2VycigiJXM6 IEVycm9yIHJ1bm5pbmcgY29tbWFuZDogJWRcbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1l LCByZXQpOwo+ICsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgd2FpdF9m b3JfY21kX2NvbXBsZXRpb24oc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbikKPiAr ewo+ICsJd2FpdF9mb3JfY29tcGxldGlvbl9pbnRlcnJ1cHRpYmxlKCZjb21wbGV0aW9uLT5jbWRf Y29tcGxldGlvbik7Cj4gKwlyZXR1cm4gY29tcGxldGlvbi0+Y29tcGxldGlvbl9zdGF0dXM7Cj4g K30KPiArCj4gK3N0YXRpYyBpbnQgZ2VuX2tleShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ ICsJY29uc3QgdTggKm1ldGhvZDsKPiArCXU4IHVpZFtPUEFMX1VJRF9MRU5HVEhdOwo+ICsJc3Ry dWN0IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsK PiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsK PiArCj4gKwltZW1jcHkodWlkLCBkZXYtPnByZXZfZGF0YSwgbWluKHNpemVvZih1aWQpLCBkZXYt PnByZXZfZF9sZW4pKTsKPiArCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRU5LRVldOwo+ICsJ a2ZyZWUoZGV2LT5wcmV2X2RhdGEpOwo+ICsJZGV2LT5wcmV2X2RhdGEgPSBOVUxMOwo+ICsKPiAr CXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgMmMiLAo+ICsJCQkJICAgIE9Q QUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRo b2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4g KwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIl czogRXJyb3IgYnVpbGRpbmcgZ2VuIGtleSBjb21tYW5kXG4iLAo+ICsJCSAgICAgICBkZXYtPmRp c2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVf YW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29udCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lk IGdldF9hY3RpdmVfa2V5X2NvbnQoaW50IGVycm9yLCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1 Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7Cj4gKwljb25zdCBjaGFyICphY3RpdmVrZXk7Cj4gKwlz aXplX3Qga2V5bGVuOwo+ICsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4g Kwo+ICsJZXJyb3IgPSBwYXJzZV9hbmRfY2hlY2tfc3RhdHVzKGRldik7Cj4gKwlpZiAoZXJyb3Ip Cj4gKwkJZ290byBlcnJfcmV0dXJuOwo+ICsJa2V5bGVuID0gcmVzcG9uc2VfZ2V0X3N0cmluZygm ZGV2LT5wYXJzZWQsIDQsICZhY3RpdmVrZXkpOwo+ICsJaWYgKCFhY3RpdmVrZXkpIHsKPiArCQlw cl9lcnIoIiVzOiBDb3VsZG4ndCBleHRyYWN0IHRoZSBBY3RpdmVrZXkgZnJvbSB0aGUgcmVzcG9u c2VcbiIsCj4gKwkJICAgICAgIF9fZnVuY19fKTsKPiArCQllcnJvciA9IDB4MEE7Cj4gKwkJZ290 byBlcnJfcmV0dXJuOwo+ICsJfQo+ICsJZGV2LT5wcmV2X2RhdGEgPSBrbWVtZHVwKGFjdGl2ZWtl eSwga2V5bGVuLCBHRlBfS0VSTkVMKTsKPiArCj4gKwlpZiAoIWRldi0+cHJldl9kYXRhKQo+ICsJ CWVycm9yID0gLUVOT01FTTsKPiArCj4gKwlkZXYtPnByZXZfZF9sZW4gPSBrZXlsZW47Cj4gKwo+ ICtlcnJfcmV0dXJuOgo+ICsJaWYgKGRldi0+b3Blcl9jYikKPiArCQlkZXYtPm9wZXJfY2IoZXJy b3IsIGRldik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZ2V0X2FjdGl2ZV9rZXkoc3RydWN0IG9w YWxfZGV2ICpkZXYpCj4gK3sKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwl1OCB1aWRbT1BBTF9V SURfTEVOR1RIXTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJaW50IHJldDsKPiArCj4g KwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsJc2V0X2NvbUlE KGNtZCwgZGV2LT5jb21JRCk7Cj4gKwo+ICsJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0dFVF07 Cj4gKwo+ICsJcmV0ID0gYnVpbGRfbG9ja2luZ19yYW5nZSh1aWQsIHNpemVvZih1aWQpLCBkZXYt PmxyKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogQ2FuJ3QgYnVpbGQgbG9j a2luZyByYW5nZVxuIiwgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJ fQo+ICsKPiArCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgNmMgNGMgMmMi LAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwK PiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BB TF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9T VEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIHN0YXJ0Q2xvdW1uICov Cj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMTAsIC8qIEFjdGl2ZUtleSAqLwo+ICsJCQkJICAg IE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAg T1BBTF9USU5ZX1VJTlRfMDQsIC8qIGVuZENvbHVtbiAqLwo+ICsJCQkJICAgIE9QQUxfVElOWV9V SU5UXzEwLCAvKiBBY3RpdmVLZXkgKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJ CQkJICAgIE9QQUxfRU5ETElTVCwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsJaWYgKHJl dCA8IDApIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBnZXQgYWN0aXZlIGtleSBj b21tYW5kXG4iLAo+ICsJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsK PiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdldF9hY3Rp dmVfa2V5X2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNldHVwX2xvY2tpbmdfcmFuZ2Uo c3RydWN0IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwl1OCB1 aWRbT1BBTF9VSURfTEVOR1RIXTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJc3RydWN0 IG9wYWxfdXNlcl9scl9zZXR1cCAqc2V0dXA7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZk ZXYtPmNtZDsKPiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwlzZXRfY29tSUQoY21kLCBkZXYt PmNvbUlEKTsKPiArCj4gKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU0VUXTsKPiArCXJldCA9 IGJ1aWxkX2xvY2tpbmdfcmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5scik7Cj4gKwlpZiAo cmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIs IGRldi0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCXNldHVwID0g ZGV2LT5mdW5jX2RhdGFbZGV2LT5zdGF0ZSAtIDFdOwo+ICsKPiArCXJldCA9IHRlc3RfYW5kX2Fk ZF90b2tlbl92YShjbWQsICJjMnMgIDRjIDJjdWMgMmN1YyAyY3VjIDJjdSA0YyIsCj4gKwkJCQkg ICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIHVpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAg IG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElT VCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywKPiAr CQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4g KwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIFJhbmdlIFN0YXJ0ICovCj4gKwkJCQkgICAg c2V0dXAtPnJhbmdlX3N0YXJ0LAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkg ICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDQsIC8qIFJhbmdl IExlbmd0aCAqLwo+ICsJCQkJICAgIHNldHVwLT5yYW5nZV9sZW5ndGgsCj4gKwkJCQkgICAgT1BB TF9FTkROQU1FLAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFM X1RJTllfVUlOVF8wNSwgLyogUmVhZExvY2tFbmFibGVkICovCj4gKwkJCQkgICAgISFzZXR1cC0+ UkxFLAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5B TUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIFdyaXRlTG9ja0VuYWJsZWQgKi8K PiArCQkJCSAgICAhIXNldHVwLT5XTEUsCj4gKwo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiAr CQkJCSAgICBPUEFMX0VORExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+ICsJCQkJICAg IE9QQUxfRU5ETElTVCk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9y IGJ1aWxkaW5nIFNldHVwIExvY2tpbmcgcmFuZ2UgY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRl di0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCX0KPiArCj4gKwlyZXR1cm4g ZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29udCk7Cj4gK30KPiArCj4gK3N0 YXRpYyBpbnQgc3RhcnRfYWRtaW5zcF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYs Cj4gKwkJCQkgICAgICBlbnVtIE9QQUxfVUlEIGF1dGgsCj4gKwkJCQkgICAgICBjb25zdCBjaGFy ICprZXksCj4gKwkJCQkgICAgICB1OCBrZXlfbGVuKQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9k LCAqc211aWQsICphZG1pbl9zcCwgKmhzYTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJ dTMyIEhTTjsKPiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKGtleSA9PSBOVUxMICYmIGF1dGggIT0g T1BBTF9BTllCT0RZX1VJRCkgewo+ICsJCXByX2VycigiJXM6IEF0dGVtcHRlZCB0byBvcGVuIEFE TUlOX1NQIFNlc3Npb24gd2l0aG91dCBhIEhvc3QiIFwKPiArCQkgICAgICAgIkNoYWxsZW5nZSwg YW5kIG5vdCBhcyB0aGUgQW55Ym9keSBVSURcbiIsIF9fZnVuY19fKTsKPiArCQlyZXR1cm4gMTsK PiArCX0KPiArCj4gKwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ ICsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsJSFNOID0gMHg0MTsKPiArCj4g KwlzbXVpZCA9IE9QQUxVSURbT1BBTF9TTVVJRF9VSURdOwo+ICsJbWV0aG9kID0gT1BBTE1FVEhP RFtPUEFMX1NUQVJUU0VTU0lPTl07Cj4gKwlhZG1pbl9zcCA9IE9QQUxVSURbT1BBTF9BRE1JTlNQ X1VJRF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3ZhKGNtZCwgImMycyBjdXNj IiwKPiArCQkJCSAgICBPUEFMX0NBTEwsCj4gKwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdU SCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCQkJCSAgICBPUEFM X1NUQVJUTElTVCwKPiArCQkJCSAgICBIU04sCj4gKwkJCQkgICAgYWRtaW5fc3AsIE9QQUxfVUlE X0xFTkdUSCwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSk7Cj4gKwlpZiAocmV0IDwgMCkg ewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIHN0YXJ0IGFkbWluc3Agc2Vzc2lvbiBj b21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7 Cj4gKwl9Cj4gKwo+ICsJc3dpdGNoIChhdXRoKSB7Cj4gKwljYXNlIE9QQUxfQU5ZQk9EWV9VSUQ6 Cj4gKwkJLyogbm90aGluZyBsZWZ0IHRvIGRvIGZvciBhbnlib2R5LCBqdXN0IGVuZCBhbmQgZmlu YWxpemUgKi8KPiArCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYyIsCj4gKwkJ CQkJICAgIE9QQUxfRU5ETElTVCk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIE9QQUxfU0lEX1VJRDoK PiArCQloc2EgPSBPUEFMVUlEW09QQUxfU0lEX1VJRF07Cj4gKwkJcmV0ID0gdGVzdF9hbmRfYWRk X3Rva2VuX3ZhKGNtZCwgIjJjIHMgM2MgcyAyYyIsCj4gKwkJCQkJICAgIE9QQUxfU1RBUlROQU1F LAo+ICsJCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMCwgLyogSG9zdENoYWxsZW5nZSAqLwo+ICsJ CQkJCSAgICBrZXksIGtleV9sZW4sCj4gKwkJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJCQkg ICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAvKiBIb3N0 U2lnbkF1dGggKi8KPiArCQkJCQkgICAgaHNhLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkJICAg IE9QQUxfRU5ETkFNRSwKPiArCQkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCQlicmVhazsKPiAr CWRlZmF1bHQ6Cj4gKwkJcHJfZXJyKCJDYW5ub3Qgc3RhcnQgQWRtaW4gU1Agc2Vzc2lvbiB3aXRo IGF1dGggJWRcbiIsIGF1dGgpOwo+ICsJCXJldHVybiAxOwo+ICsJfQo+ICsKPiArCWlmIChyZXQg PCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgc3RhcnQgYWRtaW5zcCBzZXNz aW9uIGNvbW1hbmQuXG4iLAo+ICsJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJu IHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0 YXJ0X29wYWxfc2Vzc2lvbl9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzdGFydF9hbnli b2R5QVNQX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJcmV0dXJu IHN0YXJ0X2FkbWluc3Bfb3BhbF9zZXNzaW9uKGRldiwgT1BBTF9BTllCT0RZX1VJRCwgTlVMTCwg MCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgc3RhcnRfU0lEQVNQX29wYWxfc2Vzc2lvbihzdHJ1 Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJaW50IHJldDsKPiArCWNvbnN0IHU4ICprZXkgPSBk ZXYtPnByZXZfZGF0YTsKPiArCj4gKwlpZiAoIWtleSkKPiArCQlyZXQgPSBzdGFydF9hZG1pbnNw X29wYWxfc2Vzc2lvbihkZXYsIE9QQUxfU0lEX1VJRCwgZGV2LT5rZXksCj4gKwkJCQkJCSBkZXYt PmtleV9sZW4pOwo+ICsJZWxzZSB7Cj4gKwkJcmV0ID0gc3RhcnRfYWRtaW5zcF9vcGFsX3Nlc3Np b24oZGV2LCBPUEFMX1NJRF9VSUQsIGtleSwKPiArCQkJCQkJIGRldi0+cHJldl9kX2xlbik7Cj4g KwkJa2ZyZWUoa2V5KTsKPiArCQlkZXYtPnByZXZfZGF0YSA9IE5VTEw7Cj4gKwl9Cj4gKwlyZXR1 cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHN0YXJ0X2xvY2tpbmdzcF9vcGFsX3Nlc3Np b24oc3RydWN0IG9wYWxfZGV2ICpkZXYsCj4gKwkJCQkJZW51bSBPUEFMX1VJRCBhdXRoLCBjb25z dCB1OCAqa2V5LAo+ICsJCQkJCXU4IGtleV9sZW4pCj4gK3sKPiArCj4gKwljb25zdCB1OCAqbWV0 aG9kLCAqc211aWQsICpsb2NraW5nX3NwLCAqaHNhOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7 Cj4gKwlzaXplX3Qga2xlbiA9IGtleV9sZW47Cj4gKwl1MzIgSFNOOwo+ICsJaW50IHJldDsKPiAr Cj4gKwlpZiAoa2V5ID09IE5VTEwpIHsKPiArCQlwcl9lcnIoIkNhbm5vdCBzdGFydCBMb2NraW5n IFNQIHNlc3Npb24gd2l0aG91dCBhIGtleVxuIik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9 Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCj4g KwlzZXRfY29tSUQoY21kLCBkZXYtPmNvbUlEKTsKPiArCUhTTiA9IDB4NDE7Cj4gKwo+ICsJc211 aWQgPSBPUEFMVUlEW09QQUxfU01VSURfVUlEXTsKPiArCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BB TF9TVEFSVFNFU1NJT05dOwo+ICsJbG9ja2luZ19zcCA9IE9QQUxVSURbT1BBTF9MT0NLSU5HU1Bf VUlEXTsKPiArCWhzYSA9IE9QQUxVSURbYXV0aF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk X3Rva2VuX3ZhKGNtZCwgImMycyBjdXNjIDJjc2MgMmNzYyBjIiwKPiArCQkJCSAgICBPUEFMX0NB TEwsCj4gKwkJCQkgICAgc211aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2Qs IE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJ CQkgICAgSFNOLAo+ICsJCQkJICAgIGxvY2tpbmdfc3AsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJ CSAgICBPUEFMX1RJTllfVUlOVF8wMSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4g KwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDAsIC8qIEhvc3RDaGFsbGVuZ2UgKi8KPiArCQkJCSAg ICBrZXksIGtsZW4sCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+ICsKPiArCQkJCSAgICBPUEFM X1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogSG9zdCBTaWduIEF1 dGhvcml0eSAqLwo+ICsJCQkJICAgIGhzYSwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9Q QUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlpZiAocmV0 IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIHN0YXJ0IGFkbWluc3Agc2Vz c2lvbiBjb21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVy biByZXQ7Cj4gKwl9Cj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0YXJ0 X29wYWxfc2Vzc2lvbl9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBpbnQgc3RhcnRf YWRtaW4xTFNQX29wYWxfc2Vzc2lvbihzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJcmV0 dXJuIHN0YXJ0X2xvY2tpbmdzcF9vcGFsX3Nlc3Npb24oZGV2LCBPUEFMX0FETUlOMV9VSUQsCj4g KwkJCQkJICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4pOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50 IHN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwlj b25zdCB1OCAqbWV0aG9kLCAqc211aWQsICpsb2NraW5nX3NwOwo+ICsJdTggbGtfdWxfdXNlcltP UEFMX1VJRF9MRU5HVEhdOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwl1MzIgSFNOOwo+ ICsJaW50IHJldDsKPiArCXN0cnVjdCBvcGFsX3VzZXJfaW5mbyAqdWluZm87Cj4gKwo+ICsJY21k ID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCj4gKwlzZXRfY29tSUQo Y21kLCBkZXYtPmNvbUlEKTsKPiArCj4gKwlIU04gPSAweDQxOwpDYW4gd2UgI2RlZmluZSB0aGlz OyBpdCdzIHVzZWQgYSBmZXcgb3RoZXIgcGxhY2VzIGFuZCBpcyBtYWdpY2t5Cgo+ICsKPiArCXVp bmZvID0gZGV2LT5mdW5jX2RhdGFbZGV2LT5zdGF0ZSAtIDFdOwo+ICsKPiArCXNtdWlkID0gT1BB TFVJRFtPUEFMX1NNVUlEX1VJRF07Cj4gKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU1RBUlRT RVNTSU9OXTsKPiArCWxvY2tpbmdfc3AgPSBPUEFMVUlEW09QQUxfTE9DS0lOR1NQX1VJRF07Cj4g Kwo+ICsJaWYgKHVpbmZvLT5TVU0pIHsKPiArCQlyZXQgPSBidWlsZF9sb2NraW5nX3VzZXIobGtf dWxfdXNlciwgc2l6ZW9mKGxrX3VsX3VzZXIpLAo+ICsJCQkJCSBkZXYtPmxyKTsKPiArCQlpZiAo cmV0IDwgMCkgewo+ICsJCQlwcl9lcnIoIiVzOiBDYW4ndCBidWlsZCBsb2NraW5nIHVzZXJcbiIs Cj4gKwkJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJCXJldHVybiByZXQ7Cj4gKwkJfQo+ ICsJfSBlbHNlIGlmICh1aW5mby0+d2hvICE9IE9QQUxfQURNSU4xICYmICF1aW5mby0+U1VNKSB7 Cj4gKwkJcmV0ID0gYnVpbGRfbG9ja2luZ191c2VyKGxrX3VsX3VzZXIsIHNpemVvZihsa191bF91 c2VyKSwKPiArCQkJCQkgdWluZm8tPndobyAtIDEpOwo+ICsJCWlmIChyZXQgPCAwKSB7Cj4gKwkJ CXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgdXNlclxuIiwKPiArCQkJICAgICAgIGRl di0+ZGlza19uYW1lKTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwl9IGVsc2UKPiArCQlt ZW1jcHkobGtfdWxfdXNlciwgT1BBTFVJRFtPUEFMX0FETUlOMV9VSURdLCBPUEFMX1VJRF9MRU5H VEgpOwo+ICsKPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIGN1 czNjczNjIHMgMmMiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICBzbXVpZCwgT1BB TF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsK PiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBIU04sCj4gKwkJCQkgICAgbG9j a2luZ19zcCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLAo+ ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAwLAo+ ICsJCQkJICAgIGRldi0+a2V5LCBkZXYtPmtleV9sZW4sCj4gKwkJCQkgICAgT1BBTF9FTkROQU1F LAo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAz LAo+ICsKPiArCQkJCSAgICBsa191bF91c2VyLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwo+ICsJCQkJ ICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsKPiArCWlmIChy ZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgU1RBUlRTRVNTSU9OIGNv bW1hbmQuXG4iLAo+ICsJCSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsK PiArCX0KPiArCj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIHN0YXJ0X29w YWxfc2Vzc2lvbl9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCByZXZlcnRfdHBlcihzdHJ1 Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJY29uc3QgdTggKm1ldGhvZCwgKnNtdWlkOwo+ICsJ c3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZkZXYtPmNt ZDsKPiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5j b21JRCk7Cj4gKwo+ICsJc211aWQgPSBPUEFMVUlEW09QQUxfQURNSU5TUF9VSURdOwo+ICsJbWV0 aG9kID0gT1BBTE1FVEhPRFtPUEFMX1JFVkVSVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk X3Rva2VuX3ZhKGNtZCwgImMycyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAg IHNtdWlkLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkgICAgbWV0aG9kLCBPUEFMX01FVEhPRF9M RU5HVEgsCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNU KTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcgUkVW RVJUIFRQRVIgY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1lKTsKPiArCQly ZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsIGNt ZCwgZ2VuZXJpY19jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBpbnRlcm5hbF9hY3RpdmF0 ZV91c2VyKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9kOwo+ ICsJdTggdWlkW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiAr CWludCByZXQ7Cj4gKwlzdHJ1Y3Qgb3BhbF9hY3RpdmF0ZV91c2VyICphY3Q7Cj4gKwo+ICsJY21k ID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQs IGRldi0+Y29tSUQpOwo+ICsKPiArCWFjdCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAx XTsKPiArCj4gKwltZW1jcHkodWlkLCBPUEFMVUlEW09QQUxfVVNFUjFfVUlEXSwgT1BBTF9VSURf TEVOR1RIKTsKPiArCXVpZFs3XSA9IGFjdC0+d2hvLndobzsKPiArCj4gKwltZXRob2QgPSBPUEFM TUVUSE9EW09QQUxfU0VUXTsKPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21k LCAiYzJzIDNjIGMgNGMgM2MiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQs IE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwK PiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUs Cj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDEsIC8qIFZhbHVlcyAqLwo+ICsKPiArCQkJCSAg ICBPUEFMX1NUQVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkg ICAgT1BBTF9USU5ZX1VJTlRfMDUsIC8qIEVuYWJsZWQgKi8KPiArCQkJCSAgICBPUEFMX1RJTllf VUlOVF8wMSwgLyogVHJ1ZSAqLwo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkg ICAgT1BBTF9FTkRMSVNULAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJCSAgICBPUEFM X0VORExJU1QpOwo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3Ig YnVpbGRpbmcgQWN0aXZhdGUgVXNlck4gY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlz a19uYW1lKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9h bmRfc2VuZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBl cmFzZV9sb2NraW5nX3JhbmdlKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1 OCAqbWV0aG9kOwo+ICsJdTggdWlkW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9j bWQgKmNtZDsKPiArCWludCByZXQ7Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJf b3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1l dGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9FUkFTRV07Cj4gKwo+ICsJaWYgKGJ1aWxkX2xvY2tpbmdf cmFuZ2UodWlkLCBzaXplb2YodWlkKSwgZGV2LT5scikgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczog Q2FuJ3QgYnVpbGQgbG9ja2luZyByYW5nZVxuIiwgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVy biAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQs ICJjMnMgMmMiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlE X0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJ CQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlp ZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEVyYXNlIExvY2tp bmcgUmFuZ2UgQ21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJl dHVybiByZXQ7Cj4gKwl9Cj4gKwlyZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdl bmVyaWNfY29udCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgc2V0X21icl9kb25lKHN0cnVjdCBv cGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9kLCAqdWlkOwo+ICsJc3RydWN0 IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXU4IG1icl9kb25lX3RmID0gKih1 OCAqKWRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKPiArCj4gKwljbWQgPSAmZGV2LT5j bWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21J RCk7Cj4gKwo+ICsJbWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07Cj4gKwl1aWQgPSBPUEFM VUlEW09QQUxfTUJSQ09OVFJPTF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3Zh KGNtZCwgImMycyAzYyA2YyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIHVp ZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RI LAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFN RSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1Qs Cj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDIs IC8qIERvbmUgKi8KPiArCQkJCSAgICBtYnJfZG9uZV90ZiwgICAgICAgLyogRG9uZSBUIG9yIEYg Ki8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsK PiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCWlm IChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgc2V0IE1CUiBEb250 L05vdCBkb25lIGNvbW1hbmRcbiIsCnMvRG9udC9Eb25lLyA/CgoKPiArCQkgICAgICAgZGV2LT5k aXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXpl X2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50 IHNldF9tYnJfZW5hYmxlX2Rpc2FibGUoc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCWNv bnN0IHU4ICptZXRob2QsICp1aWQ7Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWludCBy ZXQ7Cj4gKwo+ICsJdTggbWJyX2VuX2RpcyA9ICoodTggKilkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0 YXRlIC0gMV07Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21k KTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9QQUxN RVRIT0RbT1BBTF9TRVRdOwo+ICsJdWlkID0gT1BBTFVJRFtPUEFMX01CUkNPTlRST0xdOwo+ICsK PiArCXJldCA9IHRlc3RfYW5kX2FkZF90b2tlbl92YShjbWQsICJjMnMgM2MgNmMgMmMiLAo+ICsJ CQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAgICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJ CSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFS VExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9WQUxVRVMs Cj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1F LAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLCAvKiBFbmFibGUgKi8KPiArCQkJCSAgICBt YnJfZW5fZGlzLCAgICAgICAgLyogRW5hYmxlIG9yIERpc2FibGUgKi8KPiArCQkJCSAgICBPUEFM X0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsKPiArCQkJCSAgICBPUEFMX0VO RE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJ cHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgc2V0IE1CUiBEb250L05vdCBkb25lIGNvbW1hbmRc biIsCnMvRG9udC9Eb25lLyA/CgoKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJl dHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21k LCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNldF9uZXdfcHcoc3RydWN0 IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwl1OCBjcGluX3Vp ZFtPUEFMX1VJRF9MRU5HVEhdOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwlpbnQgcmV0 Owo+ICsJc3RydWN0IG9wYWxfbmV3X3B3ICpwdzsKPiArCXNpemVfdCBrZXlfbGVuOwo+ICsJdTgg KmtleTsKPiArCj4gKwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7Cj4gKwo+ICsJcHcgPSBkZXYtPmZ1bmNfZGF0 YVtkZXYtPnN0YXRlIC0gMV07Cj4gKwlrZXkgPSBwdy0+bmV3X3Bpbi5rZXk7Cj4gKwlrZXlfbGVu ID0gcHctPm5ld19waW4ua2V5X2xlbjsKPiArCW1lbWNweShjcGluX3VpZCwgT1BBTFVJRFtPUEFM X0NfUElOX0FETUlOMV0sIE9QQUxfVUlEX0xFTkdUSCk7Cj4gKwo+ICsJaWYgKHB3LT51c2VyX2Zv cl9wdyAhPSBPUEFMX0FETUlOMSkgewo+ICsJCWNwaW5fdWlkWzVdID0gMHgwMzsKPiArCQlpZiAo cHctPndoby5TVU0pCj4gKwkJCWNwaW5fdWlkWzddID0gcHctPm5ld19waW4ubHIgKyAxOwo+ICsJ CWVsc2UKPiArCQkJY3Bpbl91aWRbN10gPSBwdy0+dXNlcl9mb3JfcHc7Cj4gKwl9Cj4gKwo+ICsJ bWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX1NFVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk X3Rva2VuX3ZhKGNtZCwgImMycyAzYyAzY3MyYyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ ICsJCQkJICAgIGNwaW5fdWlkLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkgICAgbWV0aG9kLCBP UEFMX01FVEhPRF9MRU5HVEgsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsJCQkJ ICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAxLCAvKiBWYWx1 ZXMgKi8KPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJU1QsCj4gKwkJCQkgICAgT1BBTF9TVEFS VE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDMsIC8qIFBJTiAqLwo+ICsJCQkJICAg IGtleSwga2V5X2xlbiwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9F TkRMSVNULAo+ICsKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRM SVNUKTsKPiArCj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxk aW5nIFNFVCBBTUlOMSBQSU4gY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1l KTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2Vu ZChkZXYsIGNtZCwgZ2VuZXJpY19jb250KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzZXRfc2lk X2NwaW5fcGluKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9k LCAqY3Bpbl91aWQ7Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWludCByZXQ7Cj4gKwo+ ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21J RChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCWNwaW5fdWlkID0gT1BBTFVJRFtPUEFMX0NfUElO X1NJRF07Cj4gKwltZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfU0VUXTsKPiArCj4gKwlyZXQgPSB0 ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDJjIDRjczJjIDJjIiwKPiArCQkJCSAgICBP UEFMX0NBTEwsCj4gKwkJCQkgICAgY3Bpbl91aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAg ICBtZXRob2QsIE9QQUxfTUVUSE9EX0xFTkdUSCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVExJ U1QsCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfVElOWV9V SU5UXzAxLCAvKiBWYWx1ZXMgKi8KPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAg ICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElOICov Cj4gKwkJCQkgICAgZGV2LT5rZXksIGRldi0+a2V5X2xlbiwKPiArCQkJCSAgICBPUEFMX0VORE5B TUUsCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsKPiArCQkJCSAgICBPUEFMX0VORE5BTUUs Cj4gKwkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXBy X2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIFNFVCBDUElOIFBJTiBjb21tYW5kLlxuIiwKPiArCQkg ICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0 dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgdm9pZCBxdWVyeV9sb2NraW5nX3JhbmdlX2NvbnQoaW50IGVycm9yLCB2b2lkICpk YXRhKQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldiA9IGRhdGE7Cj4gKwo+ICsJaWYgKGVy cm9yKQo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCj4gKwllcnJvciA9IHBhcnNlX2FuZF9jaGVj a19zdGF0dXMoZGV2KTsKPiArCWlmIChlcnJvcikKPiArCQlnb3RvIGVycl9yZXR1cm47Cj4gKwo+ ICsJZGV2LT5zdGFydCA9IHJlc3BvbnNlX2dldF91NjQoJmRldi0+cGFyc2VkLCA0KTsKPiArCWRl di0+bGVuZ3RoID0gcmVzcG9uc2VfZ2V0X3U2NCgmZGV2LT5wYXJzZWQsIDgpOwo+ICsKPiArZXJy X3JldHVybjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBk ZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHF1ZXJ5X2xvY2tpbmdfcmFuZ2Uoc3RydWN0IG9w YWxfZGV2ICpkZXYpCj4gK3sKPiArCXU4IGxyX2J1ZmZlcltPUEFMX1VJRF9MRU5HVEhdOwo+ICsJ c3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwljb25zdCB1OCAqbWV0aG9kOwo+ICsJaW50IHJldDsK PiArCj4gKwljbWQgPSAmZGV2LT5jbWQ7Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsKPiAr CW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9HRVRdOwo+ICsKPiArCWlmIChidWlsZF9sb2NraW5n X3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1ZmZlciksIGRldi0+bHIpIDwgMCkgewo+ICsJ CXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIsIGRldi0+ZGlza19uYW1l KTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlzZXRfY29tSUQoY21kLCBkZXYt PmNvbUlEKTsKPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzIDEy YyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURf TEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsKPiArCQkJ CSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAg ICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1NUQVJUQ09MVU1OLAo+ICsJCQkJICAg IE9QQUxfUkFOR0VTVEFSVCwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BB TF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRDT0xVTU4sCj4gKwkJCQkgICAgT1BBTF9S QU5HRUxFTkdUSCwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9FTkRM SVNULAo+ICsJCQkJICAgIE9QQUxfRU5ETElTVCk7Cj4gKwo+ICsJaWYgKHJldCA8IDApIHsKPiAr CQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBHRVQgTG9ja2luZyBSYW5nZSBjb21tYW5kLlxu IiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4g Kwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBxdWVyeV9sb2NraW5nX3Jh bmdlX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkZF91c2VyX3RvX2xyKHN0cnVjdCBv cGFsX2RldiAqZGV2KQo+ICt7Cj4gKwl1OCBscl9idWZmZXJbT1BBTF9VSURfTEVOR1RIXTsKPiAr CXU4IHVzZXJfdWlkW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsK PiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayAqbGt1bDsK PiArCWludCByZXQ7Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQo Y21kKTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9Q QUxNRVRIT0RbT1BBTF9TRVRdOwo+ICsKPiArCWxrdWwgPSBkZXYtPmZ1bmNfZGF0YVtkZXYtPnN0 YXRlIC0gMV07Cj4gKwo+ICsJbWVtY3B5KGxyX2J1ZmZlciwgT1BBTFVJRFtPUEFMX0xPQ0tJTkdS QU5HRV9BQ0VfUkRMT0NLRURdLAo+ICsJICAgICAgIE9QQUxfVUlEX0xFTkdUSCk7Cj4gKwo+ICsJ aWYgKGxrdWwtPmxfc3RhdGUgPT0gT1BBTF9SVykKPiArCQltZW1jcHkobHJfYnVmZmVyLCBPUEFM VUlEW09QQUxfTE9DS0lOR1JBTkdFX0FDRV9XUkxPQ0tFRF0sCj4gKwkJICAgICAgIE9QQUxfVUlE X0xFTkdUSCk7Cj4gKwo+ICsJbHJfYnVmZmVyWzddID0gZGV2LT5scjsKPiArCj4gKwltZW1jcHko dXNlcl91aWQsIE9QQUxVSURbT1BBTF9VU0VSMV9VSURdLCBPUEFMX1VJRF9MRU5HVEgpOwo+ICsJ dXNlcl91aWRbN10gPSBsa3VsLT5hdXRob3JpdHkud2hvOwo+ICsKPiArCXJldCA9IHRlc3RfYW5k X2FkZF90b2tlbl92YShjbWQsICJjMnMgM2MgM2MgMmMgMnNjIGMyc2MgY3MyYyA1YyIsCj4gKwkJ CQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVOR1RILAo+ ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsKPiArCQkJCSAgICBPUEFM X1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1RJ TllfVUlOVF8wMSwgLyogVmFsdWVzICovCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzAzLCAv KiBCb29sZWFuRXhwciAqLwo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAg ICBPUEFMX1NUQVJUTkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTFVJRFtPUEFMX0hBTEZfVUlEX0FV VEhPUklUWV9PQkpfUkVGXSwKPiArCQkJCSAgICBPUEFMX1VJRF9MRU5HVEhfSEFMRiwKPiArCQkJ CSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwK PiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTFVJRFtPUEFMX0hB TEZfVUlEX0FVVEhPUklUWV9PQkpfUkVGXSwKPiArCQkJCSAgICBPUEFMX1VJRF9MRU5HVEhfSEFM RiwKPiArCQkJCSAgICB1c2VyX3VpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxf RU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTFVJ RFtPUEFMX0hBTEZfVUlEX0JPT0xFQU5fQUNFXSwKPiArCQkJCSAgICBPUEFMX1VJRF9MRU5HVEhf SEFMRiwKPiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMSwKPiArCQkJCSAgICBPUEFMX0VORE5B TUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfRU5ETElTVCwKPiArCQkJCSAgICBPUEFMX0VORE5BTUUs Cj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCQkJ CSAgICBPUEFMX0VORExJU1QpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlwcl9lcnIoIiVzOiBF cnJvciBidWlsZGluZyBhZGQgdXNlciB0byBsb2NraW5nIHJhbmdlIGNvbW1hbmQuXG4iLAo+ICsJ CSAgICAgICBkZXYtPmRpc2tfbmFtZSk7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwly ZXR1cm4gZmluYWxpemVfYW5kX3NlbmQoZGV2LCBjbWQsIGdlbmVyaWNfY29udCk7Cj4gK30KPiAr Cj4gK3N0YXRpYyBpbnQgbG9ja191bmxvY2tfbG9ja2luZ19yYW5nZShzdHJ1Y3Qgb3BhbF9kZXYg KmRldikKPiArewo+ICsJdTggbHJfYnVmZmVyW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qg b3BhbF9jbWQgKmNtZDsKPiArCWNvbnN0IHU4ICptZXRob2Q7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2Nr X3VubG9jayAqbGt1bDsKPiArCWludCByZXQ7Cj4gKwl1OCByZWFkX2xvY2tlZCA9IDEsIHdyaXRl X2xvY2tlZCA9IDE7Cj4gKwo+ICsJY21kID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQo Y21kKTsKPiArCXNldF9jb21JRChjbWQsIGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9Q QUxNRVRIT0RbT1BBTF9TRVRdOwo+ICsJbGt1bCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUg LSAxXTsKPiArCWlmIChidWlsZF9sb2NraW5nX3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1 ZmZlciksIGRldi0+bHIpIDwgMCkgewo+ICsJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tp bmcgcmFuZ2VcbiIsIGRldi0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0K PiArCj4gKwlzd2l0Y2ggKGxrdWwtPmxfc3RhdGUpIHsKPiArCWNhc2UgT1BBTF9STzoKPiArCQly ZWFkX2xvY2tlZCA9IDA7Cj4gKwkJd3JpdGVfbG9ja2VkID0gMTsKPiArCQlicmVhazsKPiArCWNh c2UgT1BBTF9SVzoKPiArCQlyZWFkX2xvY2tlZCA9IDA7Cj4gKwkJd3JpdGVfbG9ja2VkID0gMDsK PiArCQlicmVhazsKPiArCWNhc2UgT1BBTF9MSzoKPiArCQkvKiB2YXJzIGFyZSBpbml0YWxpemVk IHRvIGxvY2tlZCAqLwo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoKPiArCQlwcl9lcnIoIlRyaWVk IHRvIHNldCBhbiBpbnZhbGlkIGxvY2tpbmcgc3RhdGUuLi4gcmV0dXJuaW5nIHRvIHVsYW5kXG4i KTsKPiArCQlyZXR1cm4gMTsKPiArCX0KPiArCj4gKwlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5f dmEoY21kLCAiYzJzYyAzYyA0YyA0YyAzYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJ ICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9N RVRIT0RfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsKPiArCQkJCSAgICBP UEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywKPiArCQkJCSAgICBPUEFMX1NU QVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9S RUFETE9DS0VELAo+ICsJCQkJICAgIHJlYWRfbG9ja2VkLAo+ICsJCQkJICAgIE9QQUxfRU5ETkFN RSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9XUklURUxP Q0tFRCwKPiArCQkJCSAgICB3cml0ZV9sb2NrZWQsCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+ ICsKPiArCQkJCSAgICBPUEFMX0VORExJU1QsCj4gKwkJCQkgICAgT1BBTF9FTkROQU1FLAo+ICsJ CQkJICAgIE9QQUxfRU5ETElTVCk7Cj4gKwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlwcl9lcnIo IiVzOiBFcnJvciBidWlsZGluZyBTRVQgY29tbWFuZC5cbiIsIGRldi0+ZGlza19uYW1lKTsKPiAr CQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21k LCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICsKPiArc3RhdGljIGludCBsb2NrX3VubG9ja19s b2NraW5nX3JhbmdlX1NVTShzdHJ1Y3Qgb3BhbF9kZXYgKmRldikKPiArewo+ICsJdTggbHJfYnVm ZmVyW09QQUxfVUlEX0xFTkdUSF07Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWNvbnN0 IHU4ICptZXRob2Q7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayAqbGt1bDsKPiArCWludCBy ZXQ7Cj4gKwl1OCByZWFkX2xvY2tlZCA9IDEsIHdyaXRlX2xvY2tlZCA9IDE7Cj4gKwo+ICsJY21k ID0gJmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQs IGRldi0+Y29tSUQpOwo+ICsKPiArCW1ldGhvZCA9IE9QQUxNRVRIT0RbT1BBTF9TRVRdOwo+ICsJ bGt1bCA9IGRldi0+ZnVuY19kYXRhW2Rldi0+c3RhdGUgLSAxXTsKPiArCWlmIChidWlsZF9sb2Nr aW5nX3JhbmdlKGxyX2J1ZmZlciwgc2l6ZW9mKGxyX2J1ZmZlciksIGRldi0+bHIpIDwgMCkgewo+ ICsJCXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgcmFuZ2VcbiIsIGRldi0+ZGlza19u YW1lKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlzd2l0Y2ggKGxrdWwtPmxf c3RhdGUpIHsKPiArCWNhc2UgT1BBTF9STzoKPiArCQlyZWFkX2xvY2tlZCA9IDA7Cj4gKwkJd3Jp dGVfbG9ja2VkID0gMTsKPiArCQlicmVhazsKPiArCWNhc2UgT1BBTF9SVzoKPiArCQlyZWFkX2xv Y2tlZCA9IDA7Cj4gKwkJd3JpdGVfbG9ja2VkID0gMDsKPiArCQlicmVhazsKPiArCWNhc2UgT1BB TF9MSzoKPiArCQkvKiB2YXJzIGFyZSBpbml0YWxpemVkIHRvIGxvY2tlZCAqLwo+ICsJCWJyZWFr Owo+ICsJZGVmYXVsdDoKPiArCQlwcl9lcnIoIlRyaWVkIHRvIHNldCBhbiBpbnZhbGlkIGxvY2tp bmcgc3RhdGUuXG4iKTsKPiArCQlyZXR1cm4gMTsKPiArCX0KPiArCj4gKwlyZXQgPSB0ZXN0X2Fu ZF9hZGRfdG9rZW5fdmEoY21kLCAiYzJzYyAzYyA0YyA0YyA0YyA0YyAzYyIsCj4gKwkJCQkgICAg T1BBTF9DQUxMLAo+ICsJCQkJICAgIGxyX2J1ZmZlciwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJ ICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVOR1RILAo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNU LAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTkFNRSwKPiArCQkJCSAgICBPUEFMX1ZBTFVFUywK PiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUs Cj4gKwkJCQkgICAgT1BBTF9SRUFETE9DS0VOQUJMRUQsCj4gKwkJCQkgICAgT1BBTF9UUlVFLAo+ ICsJCQkJICAgIE9QQUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4g KwkJCQkgICAgT1BBTF9XUklURUxPQ0tFTkFCTEVELAo+ICsJCQkJICAgIE9QQUxfVFJVRSwKPiAr CQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJ CQkJICAgIE9QQUxfUkVBRExPQ0tFRCwKPiArCQkJCSAgICByZWFkX2xvY2tlZCwKPiArCQkJCSAg ICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAg IE9QQUxfV1JJVEVMT0NLRUQsCj4gKwkJCQkgICAgd3JpdGVfbG9ja2VkLAo+ICsJCQkJICAgIE9Q QUxfRU5ETkFNRSwKPiArCj4gKwkJCQkgICAgT1BBTF9FTkRMSVNULAo+ICsJCQkJICAgIE9QQUxf RU5ETkFNRSwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsJaWYgKHJldCA8IDApIHsKPiAr CQlwcl9lcnIoIiVzOiBFcnJvciBidWlsZGluZyBTRVQgY29tbWFuZC5cbiIsIGRldi0+ZGlza19u YW1lKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5k KGRldiwgY21kLCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtpbnQgYWN0aXZhdGVfbHNwKHN0 cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwl1OCB1c2VyX2xyW09QQUxfVUlEX0xFTkdUSF07 Cj4gKwljb25zdCB1OCAqbWV0aG9kLCAqdWlkOwo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4g KwlpbnQgcmV0Owo+ICsJc2l6ZV90IHVpbnRfMyA9IDB4ODM7Cj4gKwo+ICsJY21kID0gJmRldi0+ Y21kOwo+ICsKPiArCWNsZWFyX29wYWxfY21kKGNtZCk7Cj4gKwlzZXRfY29tSUQoY21kLCBkZXYt PmNvbUlEKTsKPiArCj4gKwl1aWQgPSBPUEFMVUlEW09QQUxfTE9DS0lOR1NQX1VJRF07Cj4gKwlt ZXRob2QgPSBPUEFMTUVUSE9EW09QQUxfQUNUSVZBVEVdOwo+ICsKPiArCXJldCA9IHRlc3RfYW5k X2FkZF90b2tlbl92YShjbWQsICJjMnMiLAo+ICsJCQkJICAgIE9QQUxfQ0FMTCwKPiArCQkJCSAg ICB1aWQsIE9QQUxfVUlEX0xFTkdUSCwKPiArCQkJCSAgICBtZXRob2QsIE9QQUxfTUVUSE9EX0xF TkdUSCk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5n IEFjdGl2YXRlIExvY2tpbmdTUCBjb21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25h bWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwkvKiBBY3RpdmF0aW5nIGFzIFNVTSAqLwo+ ICsJaWYgKGRldi0+bHIgPiAwKSB7Cj4gKwkJcmV0ID0gYnVpbGRfbG9ja2luZ19yYW5nZSh1c2Vy X2xyLCBzaXplb2YodXNlcl9sciksIGRldi0+bHIpOwo+ICsJCWlmIChyZXQgPCAwKSB7Cj4gKwkJ CXByX2VycigiJXM6IENhbid0IGJ1aWxkIGxvY2tpbmcgdXNlclxuIiwKPiArCQkJICAgICAgIGRl di0+ZGlza19uYW1lKTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwkJdGVzdF9hbmRfYWRk X3Rva2VuX3ZhKGNtZCwgIjJjIDRjIGNzYyAyYyIsCj4gKwkJCQkgICAgICBPUEFMX1NUQVJUTElT VCwKPiArCQkJCSAgICAgIE9QQUxfU1RBUlROQU1FLAo+ICsKPiArCQkJCSAgICAgIHVpbnRfMywK PiArCQkJCSAgICAgIE9QQUxfVElOWV9VSU5UXzA2LAo+ICsJCQkJICAgICAgT1BBTF9USU5ZX1VJ TlRfMDAsCj4gKwkJCQkgICAgICBPUEFMX1RJTllfVUlOVF8wMCwKPiArCj4gKwkJCQkgICAgICBP UEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICAgIHVzZXJfbHIsIE9QQUxfVUlEX0xFTkdUSCwKPiAr CQkJCSAgICAgIE9QQUxfRU5ETElTVCwKPiArCj4gKwkJCQkgICAgICBPUEFMX0VORE5BTUUsCj4g KwkJCQkgICAgICBPUEFMX0VORExJU1QpOwo+ICsJfSBlbHNlIC8qIEFjdGlhdmUgTm9ybWFsIE1v ZGUgKi8KPiArCQlyZXQgPSB0ZXN0X2FuZF9hZGRfdG9rZW5fdmEoY21kLCAiMmMiLAo+ICsJCQkJ CSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCQkgICAgT1BBTF9FTkRMSVNUKTsKPiArCj4gKwlp ZiAocmV0IDwgMCkgewo+ICsJCXByX2VycigiJXM6IEVycm9yIGJ1aWxkaW5nIEFjdGl2YXRlIExv Y2tpbmdTUCBjb21tYW5kLlxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJl dHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21k LCBnZW5lcmljX2NvbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBnZXRfbHNwX2xpZmVjeWNs ZV9jb250KGludCBlcnJvciwgdm9pZCAqZGF0YSkKPiArewo+ICsKPiArCXN0cnVjdCBvcGFsX2Rl diAqZGV2ID0gZGF0YTsKPiArCXU4IGxjX3N0YXR1czsKPiArCj4gKwlpZiAoZXJyb3IpCj4gKwkJ Z290byBlcnJfcmV0dXJuOwo+ICsKPiArCWVycm9yID0gcGFyc2VfYW5kX2NoZWNrX3N0YXR1cyhk ZXYpOwo+ICsJaWYgKGVycm9yKQo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCj4gKwlsY19zdGF0 dXMgPSByZXNwb25zZV9nZXRfdTY0KCZkZXYtPnBhcnNlZCwgNCk7Cj4gKwkvKiAweDA4IGlzIE1h bnVmYWN1cmVkIEluYWN0aXZlICovCj4gKwkvKiAweDA5IGlzIE1hbnVmYWN0dXJlZCAqLwo+ICsJ aWYgKGxjX3N0YXR1cyAhPSAweDA4KSB7Cj4gKwkJcHJfZXJyKCIlczogQ291bGRuJ3QgZGV0ZXJt aW5lIHRoZSBzdGF0dXMgb2YgdGhlIExpZmN5Y2xlIHN0YXRlXG4iLAo+ICsJCSAgICAgICBkZXYt PmRpc2tfbmFtZSk7Cj4gKwkJZXJyb3IgPSAtRU5PREVWOwo+ICsJfQo+ICsKPiArZXJyX3JldHVy bjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5vcGVyX2NiKGVycm9yLCBkZXYpOwo+ ICt9Cj4gKwo+ICsvKiBEZXRlcm1pbmUgaWYgd2UncmUgaW4gdGhlIE1hbnVmYWN0dXJlZCBJbmFj dGl2ZSBvciBBY3RpdmUgc3RhdGUgKi8KPiAraW50IGdldF9sc3BfbGlmZWN5Y2xlKHN0cnVjdCBv cGFsX2RldiAqZGV2KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9jbWQgKmNtZDsKPiArCWNvbnN0IHU4 ICptZXRob2QsICp1aWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsKPiAr Cj4gKwljbGVhcl9vcGFsX2NtZChjbWQpOwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7 Cj4gKwo+ICsJdWlkID0gT1BBTFVJRFtPUEFMX0xPQ0tJTkdTUF9VSURdOwo+ICsJbWV0aG9kID0g T1BBTE1FVEhPRFtPUEFMX0dFVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRkX3Rva2VuX3Zh KGNtZCwgImMycyAyYyA0YyA0YyAyYyIsCj4gKwkJCQkgICAgT1BBTF9DQUxMLAo+ICsJCQkJICAg IHVpZCwgT1BBTF9VSURfTEVOR1RILAo+ICsJCQkJICAgIG1ldGhvZCwgT1BBTF9NRVRIT0RfTEVO R1RILAo+ICsKPiArCQkJCSAgICBPUEFMX1NUQVJUTElTVCwKPiArCQkJCSAgICBPUEFMX1NUQVJU TElTVCwKPiArCj4gKwkJCQkgICAgT1BBTF9TVEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5Z X1VJTlRfMDMsIC8qIFN0YXJ0IENvbHVtbiAqLwo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzA2 LCAvKiBMaWZjeWNsZSBDb2x1bW4gKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJ CQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5UXzA0LCAvKiBF bmQgQ29sdW1uICovCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDYsIC8qIExpZmVjeWNsZSBD b2x1bW4gKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwo+ICsJCQkJICAgIE9QQUxfRU5E TElTVCwKPiArCQkJCSAgICBPUEFMX0VORExJU1QpOwo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4g KwkJcHJfZXJyKCIlczogRXJyb3IgQnVpbGRpbmcgR0VUIExpZmVjeWNsZSBTdGF0dXMgY29tbWFu ZFxuIiwKPiArCQkgICAgICAgZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9 Cj4gKwo+ICsJcmV0dXJuIGZpbmFsaXplX2FuZF9zZW5kKGRldiwgY21kLCBnZXRfbHNwX2xpZmVj eWNsZV9jb250KTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgZ2V0X21zaWRfY3Bpbl9waW5fY29u dChpbnQgZXJyb3IsIHZvaWQgKmRhdGEpCj4gK3sKPiArCWNvbnN0IGNoYXIgKm1zaWRfcGluOwo+ ICsJc3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwo+ICsJc2l6ZV90IHN0cmxlbjsKPiArCj4g KwlpZiAoZXJyb3IpCj4gKwkJZ290byBlcnJfcmV0dXJuOwo+ICsKPiArCWVycm9yID0gcGFyc2Vf YW5kX2NoZWNrX3N0YXR1cyhkZXYpOwo+ICsJaWYgKGVycm9yKQo+ICsJCWdvdG8gZXJyX3JldHVy bjsKPiArCj4gKwlzdHJsZW4gPSByZXNwb25zZV9nZXRfc3RyaW5nKCZkZXYtPnBhcnNlZCwgNCwg Jm1zaWRfcGluKTsKPiArCWlmICghbXNpZF9waW4pIHsKPiArCQlwcl9lcnIoIiVzOiBDb3VsZG4n dCBleHRyYWN0IFBJTiBmcm9tIHJlc3BvbnNlXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJZXJyb3IgPSAx Owo+ICsJCWdvdG8gZXJyX3JldHVybjsKPiArCX0KPiArCj4gKwlkZXYtPnByZXZfZGF0YSA9IGtt ZW1kdXAobXNpZF9waW4sIHN0cmxlbiwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWRldi0+cHJldl9k YXRhKQo+ICsJCWVycm9yID0gLUVOT01FTTsKPiArCj4gKwlkZXYtPnByZXZfZF9sZW4gPSBzdHJs ZW47Cj4gKwo+ICsgZXJyX3JldHVybjoKPiArCWlmIChkZXYtPm9wZXJfY2IpCj4gKwkJZGV2LT5v cGVyX2NiKGVycm9yLCBkZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGdldF9tc2lkX2NwaW5f cGluKHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwljb25zdCB1OCAqbWV0aG9kLCAqc211 aWQ7Cj4gKwlpbnQgcmV0Owo+ICsJc3RydWN0IG9wYWxfY21kICpjbWQ7Cj4gKwo+ICsJY21kID0g JmRldi0+Y21kOwo+ICsJY2xlYXJfb3BhbF9jbWQoY21kKTsKPiArCXNldF9jb21JRChjbWQsIGRl di0+Y29tSUQpOwo+ICsKPiArCXNtdWlkID0gT1BBTFVJRFtPUEFMX0NfUElOX01TSURdOwo+ICsJ bWV0aG9kID0gT1BBTE1FVEhPRFtPUEFMX0dFVF07Cj4gKwo+ICsJcmV0ID0gdGVzdF9hbmRfYWRk X3Rva2VuX3ZhKGNtZCwgImMgMnMgMTJjIiwKPiArCQkJCSAgICBPUEFMX0NBTEwsCj4gKwo+ICsJ CQkJICAgIHNtdWlkLCBPUEFMX1VJRF9MRU5HVEgsCj4gKwkJCQkgICAgbWV0aG9kLCBPUEFMX01F VEhPRF9MRU5HVEgsCj4gKwo+ICsJCQkJICAgIE9QQUxfU1RBUlRMSVNULAo+ICsJCQkJICAgIE9Q QUxfU1RBUlRMSVNULAo+ICsJCQkJICAgIE9QQUxfU1RBUlROQU1FLAo+ICsJCQkJICAgIE9QQUxf VElOWV9VSU5UXzAzLCAvKiBTYXJ0IENvbHVtbiAqLwo+ICsJCQkJICAgIE9QQUxfVElOWV9VSU5U XzAzLCAvKiBQSU4gKi8KPiArCQkJCSAgICBPUEFMX0VORE5BTUUsCj4gKwkJCQkgICAgT1BBTF9T VEFSVE5BTUUsCj4gKwkJCQkgICAgT1BBTF9USU5ZX1VJTlRfMDQsIC8qIEVuZCBDb2x1bW4gKi8K PiArCQkJCSAgICBPUEFMX1RJTllfVUlOVF8wMywgLyogUElOICovCj4gKwkJCQkgICAgT1BBTF9F TkROQU1FLAo+ICsJCQkJICAgIE9QQUxfRU5ETElTVCwKPiArCQkJCSAgICBPUEFMX0VORExJU1Qp Owo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgYnVpbGRpbmcg R2V0IE1TSUQgQ1BJTiBQSU4gY29tbWFuZC5cbiIsCj4gKwkJICAgICAgIGRldi0+ZGlza19uYW1l KTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2Vu ZChkZXYsIGNtZCwgZ2V0X21zaWRfY3Bpbl9waW5fY29udCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2 b2lkIHVubG9ja19zdXNwZW5kX2ZpbmFsKGludCBlcnJvciwgdm9pZCAqZGF0YSkKPiArewo+ICsJ c3RydWN0IG9wYWxfZGV2ICpkZXYgPSBkYXRhOwo+ICsKPiArCWRldi0+cmVzdW1lX2Zyb21fc3Vz cGVuZCA9IGZhbHNlOwo+ICsJZGV2LT5yZXN1bWVfZGF0YSA9IE5VTEw7Cj4gKwlkZXYtPmZ1bmNf ZGF0YSA9IE5VTEw7Cj4gKwlkZXYtPmJkZXYgPSBOVUxMOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50 IGJ1aWxkX2VuZF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCXN0 cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsKPiArCWNtZCA9ICZkZXYtPmNtZDsKPiArCWNsZWFyX29w YWxfY21kKGNtZCk7Cj4gKwo+ICsJc2V0X2NvbUlEKGNtZCwgZGV2LT5jb21JRCk7Cj4gKwlyZXR1 cm4gdGVzdF9hbmRfYWRkX3Rva2VuX3U4KGNtZCwgT1BBTF9FTkRPRlNFU1NJT04pOwo+ICt9Cj4g Kwo+ICtzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb24oc3RydWN0IG9wYWxfZGV2ICpkZXYpCj4g K3sKPiArCWlmIChidWlsZF9lbmRfb3BhbF9zZXNzaW9uKGRldikgPCAwKQo+ICsJCXJldHVybiAt MTsKPiArCXJldHVybiBmaW5hbGl6ZV9hbmRfc2VuZChkZXYsICZkZXYtPmNtZCwgZW5kX3Nlc3Np b25fY29udCk7Cj4gK30KQW55IHJlYXNvbiB3ZSBjYW50OgoKaW50IHJldCA9IGJ1aWxkXy4uLgpp ZiAocmV0IDwgMCkKCXJldHVybiByZXQ7CgoKPiArCj4gK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9kZXYg KmZpbmRfb3BhbF9kZXYoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgdTggbHIpCj4gK3sKPiAr CXN0cnVjdCBvcGFsX2RldiAqaXRlciwgKm9wYWxfZGV2ID0gTlVMTDsKPiArCj4gKwlsaXN0X2Zv cl9lYWNoX2VudHJ5KGl0ZXIsICZvcGFsX2xpc3QsIG5vZGUpIHsKPiArCQlpZiAoc3RybmNtcChp dGVyLT5kaXNrX25hbWUsIGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZSwKPiArCQkJICAgIERJU0tf TkFNRV9MRU4pKQo+ICsJCQljb250aW51ZTsKPiArCQlpZiAoaXRlci0+bHIgPT0gbHIpIHsKPiAr CQkJb3BhbF9kZXYgPSBpdGVyOwo+ICsJCQlicmVhazsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJcmV0 dXJuIG9wYWxfZGV2Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHVwZGF0ZV9vcGFsX2RldihzdHJ1 Y3Qgb3BhbF9kZXYgKm9sZF9kZXYsIHN0cnVjdCBvcGFsX2RldiAqbmV3X2RldikKPiArewo+ICsJ aWYgKCFhdG9taWNfYWRkX3VubGVzcygmb2xkX2Rldi0+aW5fdXNlLCAxLCAxKSkgewo+ICsJCXBy X2VycigiJXM6IGRldiB3YXMgaW4gdXNlXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJcmV0dXJuIC1FQlVT WTsKPiArCX0KPiArCj4gKwlvbGRfZGV2LT5rZXlfbmFtZV9sZW4gPSBuZXdfZGV2LT5rZXlfbmFt ZV9sZW47Cj4gKwlpZiAoIW1lbWNweShvbGRfZGV2LT5rZXlfbmFtZSwgbmV3X2Rldi0+a2V5X25h bWUsIG9sZF9kZXYtPmtleV9uYW1lX2xlbikpIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJvciB1cGRh dGluZyBkZXZpY2U6XG4iLCBvbGRfZGV2LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiAtRUZBVUxU Owo+ICsJfQo+ICsKPiArCWlmICghc3RybmNweShvbGRfZGV2LT5kaXNrX25hbWUsIG5ld19kZXYt PmRpc2tfbmFtZSwgRElTS19OQU1FX0xFTikpIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJvciByZWdp c3RlcmluZyBkZXZpY2U6IGNvcHlpbmcgZGlzayBuYW1lXG4iLAo+ICsJCSAgICAgICBvbGRfZGV2 LT5kaXNrX25hbWUpOwo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsJfQo+ICsKPiArCW9sZF9kZXYt PmNvbUlEID0gbmV3X2Rldi0+Y29tSUQ7Cj4gKwlvbGRfZGV2LT5zdGFydCA9IG5ld19kZXYtPnN0 YXJ0Owo+ICsJb2xkX2Rldi0+bGVuZ3RoID0gbmV3X2Rldi0+bGVuZ3RoOwo+ICsJb2xkX2Rldi0+ YWxpZ24gPSBuZXdfZGV2LT5hbGlnbjsKPiArCW9sZF9kZXYtPmxvd2VzdF9sYmEgPSBuZXdfZGV2 LT5sb3dlc3RfbGJhOwo+ICsJb2xkX2Rldi0+YmRldiA9IE5VTEw7Cj4gKwlvbGRfZGV2LT5maW5h bF9jYiA9IG5ld19kZXYtPmZpbmFsX2NiOwo+ICsJb2xkX2Rldi0+ZmluYWxfY2JfZGF0YSA9IG5l d19kZXYtPmZpbmFsX2NiX2RhdGE7Cj4gKwlvbGRfZGV2LT5vcGVyX2NiID0gbmV3X2Rldi0+b3Bl cl9jYjsKPiArCW9sZF9kZXYtPnN0YXRlID0gbmV3X2Rldi0+c3RhdGU7Cj4gKwlvbGRfZGV2LT5m dW5jcyA9IG5ld19kZXYtPmZ1bmNzOwo+ICsKPiArCWtmcmVlKG9sZF9kZXYtPmNvbXBsZXRpb24p Owo+ICsJY2xlYW5fZnVuY3Rpb25fZGF0YShvbGRfZGV2KTsKPiArCj4gKwlvbGRfZGV2LT5jb21w bGV0aW9uID0gbmV3X2Rldi0+Y29tcGxldGlvbjsKPiArCj4gKwkvKgo+ICsJICogV29uJ3QgYmUg YWJsZSB0byBhdXRvIHVubG9jayB0aGlzIGxvY2tpbmcgcmFuZ2UgYmFzZWQgb24gYmxvY2sKPiAr CSAqIHJlcXVlc3Rlcy4KPiArCSAqLwo+ICsJaWYgKG9sZF9kZXYtPmxlbmd0aCA9PSAwKQo+ICsJ CXByX3dhcm4oIiVzOiBNaXNzaW5nIGJsb2NrIGluZm9ybWF0aW9uIGZvciBsb2NraW5nIHJhbmdl ICVkXG4iLAo+ICsJCQlvbGRfZGV2LT5kaXNrX25hbWUsIG9sZF9kZXYtPmxyKTsKPiArCj4gKwly ZXR1cm4gMDsKPiArfQo+ICsKPiAraW50IG9wYWxfcmVnaXN0ZXJfY29udChzdHJ1Y3Qgb3BhbF9k ZXYgKm5ld19kZXYpCj4gK3sKPiArCXN0cnVjdCBvcGFsX2RldiAqb2xkX2RldjsKPiArCXVuc2ln bmVkIGxvbmcgZmxhZ3M7Cj4gKwlpbnQgZXJyb3IgPSAwOwo+ICsKPiArCXNwaW5fbG9ja19pcnFz YXZlKCZsaXN0X3NwaW5sb2NrLCBmbGFncyk7Cj4gKwo+ICsJb2xkX2RldiA9IGZpbmRfb3BhbF9k ZXYobmV3X2Rldi0+YmRldiwgbmV3X2Rldi0+bHIpOwo+ICsJaWYgKCFvbGRfZGV2KSB7Cj4gKwkJ bGlzdF9hZGRfdGFpbCgmbmV3X2Rldi0+bm9kZSwgJm9wYWxfbGlzdCk7Cj4gKwkJb2xkX2RldiA9 IG5ld19kZXY7Cj4gKwl9IGVsc2Ugewo+ICsJCWlmIChvbGRfZGV2ID09IG5ld19kZXYpCj4gKwkJ CWVycm9yID0gMDsKPiArCQllbHNlIHsKPiArCQkJZXJyb3IgPSB1cGRhdGVfb3BhbF9kZXYob2xk X2RldiwgbmV3X2Rldik7Cj4gKwkJCWNsZWFuX29wYWxfa2V5KG5ld19kZXYpOwo+ICsJCQlrZnJl ZShuZXdfZGV2KTsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJaWYgKGVycm9yKQo+ICsJCWxpc3RfZGVs KCZvbGRfZGV2LT5ub2RlKTsKPiArCj4gKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZsaXN0X3Nw aW5sb2NrLCBmbGFncyk7Cj4gKwo+ICsJaWYgKCFlcnJvcikKPiArCQlwcl9pbmZvKCIlczogUmVn aXN0ZXJlZCBrZXkgZm9yIGxvY2tpbmcgcmFuZ2U6ICVkXG4iLAo+ICsJCQlvbGRfZGV2LT5kaXNr X25hbWUsIG9sZF9kZXYtPmxyKTsKPiArCj4gKwlpZiAob2xkX2Rldi0+b3Blcl9jYikKPiArCQlv bGRfZGV2LT5vcGVyX2NiKGVycm9yLCBvbGRfZGV2KTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ ICsKPiArc3RhdGljIHZvaWQgbmV4dChpbnQgZXJyb3IsIHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ ICt7Cj4gKwlvcGFsX3N0ZXAgZnVuYyA9IGRldi0+ZnVuY3NbZGV2LT5zdGF0ZV07Cj4gKwl2b2lk ICpjYl9kYXRhID0gZGV2LT5maW5hbF9jYl9kYXRhOwo+ICsJc2VjX2NiICpjYiA9IGRldi0+Zmlu YWxfY2I7Cj4gKwlib29sIGRvbmUgPSBmYWxzZTsKPiArCj4gKwo+ICsJaWYgKGVycm9yIHx8ICFm dW5jKSB7Cj4gKwkJZG9uZSA9IHRydWU7Cj4gKwkJZ290byBuZXh0X2V4aXQ7Cj4gKwl9Cj4gKwlk ZXYtPnN0YXRlKys7Cj4gKwlkZXYtPm9wZXJfY2IgPSBuZXh0Owo+ICsJZXJyb3IgPSBmdW5jKGRl dik7Cj4gKyBuZXh0X2V4aXQ6Cj4gKwlpZiAoZXJyb3IpIHsKPiArCQlwcl9lcnIoIiVzOiBFcnJv ciBvbiBzdGVwIGZ1bmN0aW9uOiAlZCB3aXRoIGVycm9yICVkOiAlc1xuIiwKPiArCQkgICAgICAg ZGV2LT5kaXNrX25hbWUsIGRldi0+c3RhdGUsIGVycm9yLAo+ICsJCSAgICAgICBvcGFsX2Vycm9y X3RvX2h1bWFuKGVycm9yKSk7Cj4gKwo+ICsKPiArCQlhdG9taWNfZGVjKCZkZXYtPmluX3VzZSk7 Cj4gKwkJaWYgKGRldi0+ZXJyb3JfY2IpIHsKPiArCQkJZGV2LT5lcnJvcl9jYihkZXYtPmVycm9y X2NiX2RhdGEpOwo+ICsJCQlyZXR1cm47Cj4gKwkJfQo+ICsJCWlmIChjYikKPiArCQkJY2IoZXJy b3IsIGNiX2RhdGEpOwo+ICsKPiArCQlkZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVz ID0gZXJyb3I7Cj4gKwkJY29tcGxldGUoJmRldi0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24p Owo+ICsJfSBlbHNlIGlmICghZXJyb3IgJiYgZG9uZSkgewo+ICsJCWF0b21pY19kZWMoJmRldi0+ aW5fdXNlKTsKPiArCQlpZiAoY2IpCj4gKwkJCWNiKGVycm9yLCBjYl9kYXRhKTsKPiArCQlkZXYt PmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVzID0gZXJyb3I7Cj4gKwkJY29tcGxldGUoJmRl di0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24pOwo+ICsJfQo+ICt9Cj4gKwo+ICtjb25zdCBv cGFsX3N0ZXAgZXJyb3JfZW5kX3Nlc3Npb25bXSA9IHsKPiArCWVuZF9vcGFsX3Nlc3Npb24sCj4g KwlOVUxMLAo+ICt9Owo+ICtzdGF0aWMgaW50IGVuZF9vcGFsX3Nlc3Npb25fZXJyb3Ioc3RydWN0 IG9wYWxfZGV2ICpkZXYpCj4gK3sKPiArCj4gKwlkZXYtPmZ1bmNzID0gZXJyb3JfZW5kX3Nlc3Np b247Cj4gKwlkZXYtPnN0YXRlID0gMDsKPiArCWRldi0+ZXJyb3JfY2IgPSBOVUxMOwo+ICsJbmV4 dCgwLCBkZXYpOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1Y3Qgb3BhbF9k ZXYgKmFsbG9jX29wYWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHU4IGxyKQo+ICt7 Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKm9wYWxfZGV2Owo+ICsJc3RydWN0IHJlcXVlc3RfcXVldWUg KnE7Cj4gKwl1bnNpZ25lZCBsb25nIGRtYV9hbGlnbjsKPiArCWNvbnN0IGNoYXIgKmRpc2tfbmFt ZTsKPiArCXN0cnVjdCBvcGFsX2NtZCAqY21kOwo+ICsJaW50IHJldDsKPiArCj4gKwlvcGFsX2Rl diA9IGt6YWxsb2Moc2l6ZW9mKCpvcGFsX2RldiksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCFvcGFs X2RldikKPiArCQlyZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKPiArCj4gKwlvcGFsX2Rldi0+YmRl diA9IGJkZXY7Cj4gKwlvcGFsX2Rldi0+bHIgPSBscjsKPiArCWNtZCA9ICZvcGFsX2Rldi0+Y21k Owo+ICsJY21kLT5jbWQgPSBjbWQtPmNtZF9idWY7Cj4gKwljbWQtPnJlc3AgPSBjbWQtPnJlc3Bf YnVmOwo+ICsKPiArCWRpc2tfbmFtZSA9IGJkZXYtPmJkX2Rpc2stPmRpc2tfbmFtZTsKPiArCWlm ICghc3RybmNweShvcGFsX2Rldi0+ZGlza19uYW1lLCBkaXNrX25hbWUsIERJU0tfTkFNRV9MRU4p KSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgcmVnaXN0ZXJpbmcgZGV2aWNlOiBjb3B5aW5nIGRp c2sgbmFtZVxuIiwKPiArCQkgICAgICAgZGlza19uYW1lKTsKPiArCQlyZXQgPSAtRUZBVUxUOwo+ ICsJCWdvdG8gZXJyX2ZyZWVfZGV2Owo+ICsJfQo+ICsKPiArCXEgPSBiZGV2LT5iZF9xdWV1ZTsK PiArCWRtYV9hbGlnbiA9IChxdWV1ZV9kbWFfYWxpZ25tZW50KHEpIHwgcS0+ZG1hX3BhZF9tYXNr KSArIDE7Cj4gKwljbWQtPmNtZCA9ICh1OCAqKXJvdW5kX3VwKCh1aW50cHRyX3QpY21kLT5jbWQs IGRtYV9hbGlnbik7Cj4gKwljbWQtPnJlc3AgPSAodTggKilyb3VuZF91cCgodWludHB0cl90KWNt ZC0+cmVzcCwgZG1hX2FsaWduKTsKPiArCj4gKwlJTklUX0xJU1RfSEVBRCgmb3BhbF9kZXYtPm5v ZGUpOwo+ICsJYXRvbWljX3NldCgmb3BhbF9kZXYtPmluX3VzZSwgMSk7Cj4gKwo+ICsJb3BhbF9k ZXYtPmNvbXBsZXRpb24gPSBremFsbG9jKHNpemVvZigqb3BhbF9kZXYtPmNvbXBsZXRpb24pLAo+ ICsJCQkJICAgICAgIEdGUF9LRVJORUwpOwo+ICsKPiArCWlmICghb3BhbF9kZXYtPmNvbXBsZXRp b24pCj4gKwkJZ290byBlcnJfZnJlZV9kZXY7Cj4gKwo+ICsJaW5pdF9jb21wbGV0aW9uKCZvcGFs X2Rldi0+Y29tcGxldGlvbi0+Y21kX2NvbXBsZXRpb24pOwo+ICsJb3BhbF9kZXYtPmNvbXBsZXRp b24tPmNvbXBsZXRpb25fc3RhdHVzID0gMDsKPiArCW9wYWxfZGV2LT5zdGF0ZSA9IDA7Cj4gKwo+ ICsJcmV0dXJuIG9wYWxfZGV2Owo+ICsKPiArZXJyX2ZyZWVfZGV2Ogo+ICsJa2ZyZWUob3BhbF9k ZXYpOwo+ICsJcmV0dXJuIEVSUl9QVFIocmV0KTsKPiArfQo+ICsKPiAraW50IG9wYWxfcmVnaXN0 ZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IG9wYWxfa2V5ICprZXlfY21kLAo+ ICsJCSAgY29uc3Qgb3BhbF9zdGVwICpmdW5jcykKPiArewo+ICsJc3RydWN0IG9wYWxfZGV2ICpu ZXdfZGV2ID0gTlVMTDsKPiArCXU4IGtleV9sZW4gPSBrZXlfY21kLT5rZXlfbGVuOwo+ICsJdTgg bHIgPSBrZXlfY21kLT5scjsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247 Cj4gKwlpbnQgcmV0Owo+ICsKPiArCW5ld19kZXYgPSBhbGxvY19vcGFsX2RldihiZGV2LCBscik7 Cj4gKwlpZiAoSVNfRVJSKG5ld19kZXYpKSB7Cj4gKwkJcHJfZXJyKCIlczogRXJyb3IgcmVnaXN0 ZXJpbmcgZGV2aWNlOiBhbGxvY2F0aW9uXG4iLAo+ICsJCSAgICAgICBiZGV2LT5iZF9kaXNrLT5k aXNrX25hbWUpOwo+ICsJCXJldHVybiBQVFJfRVJSKG5ld19kZXYpOwo+ICsJfQo+ICsKPiArCWlm ICghbWVtY3B5KG5ld19kZXYtPmtleV9uYW1lLCBrZXlfY21kLT5rZXksIGtleV9sZW4pKSB7Cj4g KwkJcHJfZXJyKCIlczogRXJyb3IgcmVnaXN0ZXJpbmcga2V5OiBjb3VsZG4ndCBjb3B5IGtleVxu IiwKPiArCQkgICAgICAgbmV3X2Rldi0+ZGlza19uYW1lKTsKPiArCQlyZXR1cm4gLUVGQVVMVDsK PiArCX0KPiArCj4gKwluZXdfZGV2LT5rZXlfbmFtZV9sZW4gPSBrZXlfbGVuOwo+ICsJbmV3X2Rl di0+a2V5X3R5cGUgPSBrZXlfY21kLT5rZXlfdHlwZTsKPiArCXJldCA9IGdldF9vcGFsX2tleShu ZXdfZGV2KTsKPiArCWlmIChyZXQpIHsKPiArCQlwcl9lcnIoIiVzOiBDb3VsZG4ndCBnZXQga2V5 OiAlZFxuIiwgbmV3X2Rldi0+ZGlza19uYW1lLCByZXQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9 Cj4gKwo+ICsJbmV3X2Rldi0+ZnVuY3MgPSBmdW5jczsKPiArCj4gKwluZXdfZGV2LT5zdGF0ZSA9 IDA7Cj4gKwljb21wbGV0aW9uID0gbmV3X2Rldi0+Y29tcGxldGlvbjsKPiArCW5leHQoMCwgbmV3 X2Rldik7Cj4gKwo+ICsJcmV0dXJuIHdhaXRfZm9yX2NtZF9jb21wbGV0aW9uKGNvbXBsZXRpb24p Owo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IG9wYWxfZGV2ICpnZXRfcmVnaXN0ZXJlZF9vcGFs X2RldihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LAo+ICsJCQkJCQl1OCBscikKPiArewo+ICsJ Y29uc3QgY2hhciAqZGlza25hbWUgPSBiZGV2LT5iZF9kaXNrLT5kaXNrX25hbWU7Cj4gKwlzdHJ1 Y3Qgb3BhbF9kZXYgKml0ZXIsICpkZXYgPSBOVUxMOwo+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsK PiArCWJvb2wgaW5fdXNlID0gZmFsc2U7Cj4gKwo+ICsJc3Bpbl9sb2NrX2lycXNhdmUoJmxpc3Rf c3BpbmxvY2ssIGZsYWdzKTsKPiArCWxpc3RfZm9yX2VhY2hfZW50cnkoaXRlciwgJm9wYWxfbGlz dCwgbm9kZSkgewo+ICsJCWlmIChzdHJuY21wKGl0ZXItPmRpc2tfbmFtZSwgZGlza25hbWUsIERJ U0tfTkFNRV9MRU4pKQo+ICsJCQljb250aW51ZTsKPiArCQlpZiAoaXRlci0+bHIgPT0gbHIpIHsK PiArCQkJZGV2ID0gaXRlcjsKPiArCQkJaWYgKCFhdG9taWNfYWRkX3VubGVzcygmaXRlci0+aW5f dXNlLCAxLCAxKSkgewo+ICsJCQkJZGV2ID0gTlVMTDsKPiArCQkJCWluX3VzZSA9IHRydWU7Cj4g KwkJCX0KPiArCQkJYnJlYWs7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCXNwaW5fdW5sb2NrX2lycXJl c3RvcmUoJmxpc3Rfc3BpbmxvY2ssIGZsYWdzKTsKPiArCj4gKwlpZiAoIWRldikKPiArCQlyZXR1 cm4gTlVMTDsKPiArCj4gKwlkZXYtPmJkZXYgPSBiZGV2Owo+ICsJcmV0dXJuIGRldjsKPiArfQo+ ICsKPiArLyogRnJlZSB1cCB0aGUgT3BhbCBkZXYgYW5kIGl0cyBrZXlzIGR1cmluZyB0d28gc2Nl bmFyaW9zOgo+ICsgKgo+ICsgKiAxKSBXaGVuIGEgY29tbWFuZCBpcyBjb21wbGV0ZSB0aGF0IG5v IGxvbmdlciByZXF1aXJlcwo+ICsgKiAgICB0aGUgb3BhbCBkZXYgdG8gYmUgYXJvdW5kLgo+ICsg KiAyKSBXaGVuIGEgY29tbWFuZCwgaW5jbHVkaW5nIE9wYWwgU2F2ZSBmYWlscyB3ZSBjbGVhbgo+ ICsgKiAgICBhbmQgZnJlZSB0aGUgb3BhbCBkZXYuCj4gKyAqCj4gKyAqICAgIElmIHdlIGZpbmQg dGhlIG9wYWwgZGV2IHN0cnVjdHVyZSBpbiB0aGUgbGlzdCBvZgo+ICsgKiAgICBzYXZlZCBwYXNz d29yZHMgd2Ugd2lsbCAqbm90KiByZW1vdmUgaXQuCj4gKyAqLwo+ICtzdGF0aWMgdm9pZCByZW1v dmVfYW5kX2NsZWFuX29wYWxfZGV2KHN0cnVjdCBvcGFsX2RldiAqZGV2KQo+ICt7Cj4gKwlzdHJ1 Y3Qgb3BhbF9kZXYgKml0ZXI7Cj4gKwlib29sIGZvdW5kID0gZmFsc2U7Cj4gKwo+ICsJc3Bpbl9s b2NrKCZsaXN0X3NwaW5sb2NrKTsKPiArCWxpc3RfZm9yX2VhY2hfZW50cnkoaXRlciwgJm9wYWxf bGlzdCwgbm9kZSkgewo+ICsJCWlmIChpdGVyID09IGRldikgewo+ICsJCQlmb3VuZCA9IHRydWU7 Cj4gKwkJCWJyZWFrOwo+ICsJCX0KPiArCX0KPiArCj4gKwlzcGluX3VubG9jaygmbGlzdF9zcGlu bG9jayk7Cj4gKwlpZiAoIWZvdW5kKSB7Cj4gKwkJY2xlYW5fb3BhbF9rZXkoZGV2KTsKPiArCQlj bGVhbl9mdW5jdGlvbl9kYXRhKGRldik7Cj4gKwkJa2ZyZWUoZGV2KTsKPiArCX0KPiArfQo+ICsK PiArc3RhdGljIHN0cnVjdCBvcGFsX2RldiAqZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihzdHJ1Y3Qg YmxvY2tfZGV2aWNlICpiZGV2LAo+ICsJCQkJCSAgICAgICB1OCBsciwgYm9vbCB1c2VfbmV3KQo+ ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKPiArCj4gKwlpZiAodXNlX25ldykKPiArCQly ZXR1cm4gYWxsb2Nfb3BhbF9kZXYoYmRldiwgbHIpOwo+ICsKPiArCWRldiA9IGdldF9yZWdpc3Rl cmVkX29wYWxfZGV2KGJkZXYsIGxyKTsKPiArCWlmICghZGV2KSB7Cj4gKwkJZGV2ID0gYWxsb2Nf b3BhbF9kZXYoYmRldiwgbHIpOwo+ICsJCWlmICghZGV2KQo+ICsJCQlyZXR1cm4gTlVMTDsKTm8g bmVlZCBmb3IgdGhpcyBjaGVjayB3aGVuIHlvdSBhbHJlYWR5IHJldHVybiBkZXYKCgo+ICsJfQo+ ICsJcmV0dXJuIGRldjsKPiArfQpJbnN0ZWFkLCBob3cgYWJvdXQ6CnN0YXRpYyBzdHJ1Y3Qgb3Bh bF9kZXYgKmdldF9vcl9jcmVhdGVfb3BhbF9kZXYoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwK CQkJCQkgICAgICAgdTggbHIsIGJvb2wgdXNlX25ldykKewoJc3RydWN0IG9wYWxfZGV2ICpkZXYg PSBOVUxMOwoKCWlmICghdXNlX25ldykKCQlkZXYgPSBnZXRfcmVnaXN0ZXJlZF9vcGFsX2Rldihi ZGV2LCBscik7CgoJaWYgKCFkZXYpCgkJZGV2ID0gYWxsb2Nfb3BhbF9kZXYoYmRldiwgbHIpOwoK CXJldHVybiBkZXY7Cn0KCgo+ICsKPiArc3RhdGljIHN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKnNl dHVwX29wYWxfZGV2KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQkJICAgICAgc3Ry dWN0IG9wYWxfZGV2ICpkZXYsCj4gKwkJCQkJICAgICAgY29uc3Qgb3BhbF9zdGVwICpmdW5jcywK PiArCQkJCQkgICAgICBzdHJ1Y3Qgb3BhbF9rZXkgKmtleSkKPiArewo+ICsJaW50IHJldDsKPiAr Cj4gKwlkZXYtPmJkZXYgPSBiZGV2Owo+ICsJZGV2LT5zdGF0ZSA9IDA7Cj4gKwlkZXYtPmZ1bmNz ID0gZnVuY3M7Cj4gKwlkZXYtPlRTTiA9IDA7Cj4gKwlkZXYtPkhTTiA9IDA7Cj4gKwlkZXYtPmZp bmFsX2NiID0gTlVMTDsKPiArCWRldi0+ZmluYWxfY2JfZGF0YSA9IE5VTEw7Cj4gKwlkZXYtPmxy ID0ga2V5LT5scjsKPiArCWRldi0+ZXJyb3JfY2IgPSBlbmRfb3BhbF9zZXNzaW9uX2Vycm9yOwo+ ICsJZGV2LT5lcnJvcl9jYl9kYXRhID0gZGV2Owo+ICsKPiArCWlmIChrZXkpIHsKPiArCQltZW1j cHkoZGV2LT5rZXlfbmFtZSwga2V5LT5rZXksIGtleS0+a2V5X2xlbik7Cj4gKwkJZGV2LT5rZXlf bmFtZV9sZW4gPSBrZXktPmtleV9sZW47Cj4gKwkJZGV2LT5rZXlfdHlwZSA9IGtleS0+a2V5X3R5 cGU7Cj4gKwo+ICsJCXJldCA9IGdldF9vcGFsX2tleShkZXYpOwo+ICsJCWlmIChyZXQpIHsKPiAr CQkJa2ZyZWUoZGV2LT5jb21wbGV0aW9uKTsKPiArCQkJcHJfZXJyKCIlczogQ291bGRuJ3QgZ2V0 IGtleTogJWRcbiIsCj4gKwkJCSAgICAgICBkZXYtPmRpc2tfbmFtZSwgcmV0KTsKPiArCQkJcmV0 dXJuIEVSUl9QVFIocmV0KTsKPiArCQl9Cj4gKwl9Cj4gKwlkZXYtPmZ1bmNfZGF0YSA9IE5VTEw7 Cj4gKwlkZXYtPmNvbXBsZXRpb24tPmNvbXBsZXRpb25fc3RhdHVzID0gMDsKPiArCj4gKwlyZXR1 cm4gZGV2LT5jb21wbGV0aW9uOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGludGVybmFsX3NldHVw X2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCSAgICAgc3RydWN0IG9wYWxfdXNl cl9scl9zZXR1cCAqc2V0dXApCj4gK3sKPiArCXN0cnVjdCBvcGFsX2RldiAqZGV2Owo+ICsJc3Ry dWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCXZvaWQgKmRhdGFbM10gPSB7IE5V TEwgfTsKPiArCWNvbnN0IG9wYWxfc3RlcCBscl9mdW5jc1tdID0gewo+ICsJCW9wYWxfZGlzY292 ZXJ5MCwKPiArCQlzdGFydF9hdXRoX29wYWxfc2Vzc2lvbiwKPiArCQlzZXR1cF9sb2NraW5nX3Jh bmdlLAo+ICsJCWdldF9hY3RpdmVfa2V5LAo+ICsJCWdlbl9rZXksCj4gKwkJZW5kX29wYWxfc2Vz c2lvbiwKPiArCQlOVUxMLAo+ICsJfTsKPiArCWludCByZXQ7Cj4gKwo+ICsJZGV2ID0gZ2V0X29y X2NyZWF0ZV9vcGFsX2RldihiZGV2LCBzZXR1cC0+a2V5LmxyLCB0cnVlKTsKPiArCWlmICghZGV2 KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWNvbXBsZXRpb24gPSBzZXR1cF9vcGFsX2Rl dihiZGV2LCBkZXYsIGxyX2Z1bmNzLCAmc2V0dXAtPmtleSk7Cj4gKwlpZiAoSVNfRVJSKGNvbXBs ZXRpb24pKSB7Cj4gKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKPiArCQlnb3RvIGVycm9y X3JldHVybjsKPiArCX0KPiArCj4gKwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7Cj4gKwlkZXYtPm51 bV9mdW5jX2RhdGEgPSAzOwo+ICsJZGV2LT5mdW5jX2RhdGFbMV0gPSAmc2V0dXAtPndobzsKPiAr CWRldi0+ZnVuY19kYXRhWzJdID0gc2V0dXA7Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0 ID0gd2FpdF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0 dXJuOgo+ICsJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsK PiArfQo+ICsKPiAraW50IG9wYWxfcmV2ZXJ0KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0 cnVjdCBvcGFsX2tleSAqa2V5KQo+ICt7Cj4gKwljb25zdCBvcGFsX3N0ZXAgcmV2ZXJ0X2Z1bmNz W10gPSB7Cj4gKwkJb3BhbF9kaXNjb3ZlcnkwLAo+ICsJCXN0YXJ0X1NJREFTUF9vcGFsX3Nlc3Np b24sCj4gKwkJcmV2ZXJ0X3RwZXIsIC8qIGNvbnRyb2xsZXIgd2lsbCB0ZXJtaW5hdGUgc2Vzc2lv biAqLwo+ICsJCU5VTEwsCj4gKwl9Owo+ICsKPiArCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYs IGtleSwgcmV2ZXJ0X2Z1bmNzKTsKPiArfQo+ICsKPiAraW50IGFjdGl2YXRlX3VzZXIoc3RydWN0 IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IG9wYWxfYWN0aXZhdGVfdXNlciAqYWN0KQo+ICt7 Cj4gKwljb25zdCBvcGFsX3N0ZXAgYWN0X2Z1bmNzW10gPSB7Cj4gKwkJb3BhbF9kaXNjb3Zlcnkw LAo+ICsJCXN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24sCj4gKwkJaW50ZXJuYWxfYWN0aXZh dGVfdXNlciwKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCU5VTEwKPiArCX07Cj4gKwlzdHJ1 Y3Qgb3BhbF9kZXYgKmRldjsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247 Cj4gKwl2b2lkICpkYXRhWzNdID0geyBOVUxMIH07Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWRldiA9 IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgYWN0LT5rZXkubHIsIHRydWUpOwo+ICsJaWYg KCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJY29tcGxldGlvbiA9IHNldHVwX29w YWxfZGV2KGJkZXYsIGRldiwgYWN0X2Z1bmNzLCAmYWN0LT5rZXkpOwo+ICsJaWYgKElTX0VSUihj b21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBl cnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKPiArCWRl di0+ZnVuY19kYXRhID0gZGF0YTsKPiArCWRldi0+ZnVuY19kYXRhWzFdID0gYWN0Owo+ICsJZGV2 LT5mdW5jX2RhdGFbMl0gPSBhY3Q7Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0ID0gd2Fp dF9mb3JfY21kX2NvbXBsZXRpb24oY29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0dXJuOgo+ ICsJcmVtb3ZlX2FuZF9jbGVhbl9vcGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ ICsKPiAraW50IG9wYWxfc2V0X3B3KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBv cGFsX25ld19wdyAqcHcpCj4gKwo+ICt7Cj4gKwljb25zdCBvcGFsX3N0ZXAgcHdfZnVuY3NbXSA9 IHsKPiArCQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCj4g KwkJc2V0X25ld19wdywKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCU5VTEwKPiArCX07Cj4g KwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBs ZXRpb247Cj4gKwl2b2lkICpkYXRhWzNdID0geyBOVUxMIH07Cj4gKwlpbnQgcmV0Owo+ICsKPiAr CWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgcHctPmN1cnJlbnRfcGluLmxyLCB0 cnVlKTsKPiArCWlmICghZGV2KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWNvbXBsZXRp b24gPSBzZXR1cF9vcGFsX2RldihiZGV2LCBkZXYsIHB3X2Z1bmNzLCAmcHctPmN1cnJlbnRfcGlu KTsKPiArCWlmIChJU19FUlIoY29tcGxldGlvbikpIHsKPiArCQlyZXQgPSBQVFJfRVJSKGNvbXBs ZXRpb24pOwo+ICsJCWdvdG8gZXJyb3JfcmV0dXJuOwo+ICsJfQo+ICsKPiArCWRldi0+bnVtX2Z1 bmNfZGF0YSA9IDM7Cj4gKwlkZXYtPmZ1bmNfZGF0YSA9IGRhdGE7Cj4gKwlkZXYtPmZ1bmNfZGF0 YVsxXSA9ICh2b2lkICopICZwdy0+d2hvOwo+ICsJZGV2LT5mdW5jX2RhdGFbMl0gPSAodm9pZCAq KSBwdzsKPiArCj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxl dGlvbihjb21wbGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVfYW5kX2Ns ZWFuX29wYWxfZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtpbnQgb3BhbF9h Y3RfbHNwX2ludChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgb3BhbF9rZXkgKmtl eSwKPiArCQkgICAgIGNvbnN0IG9wYWxfc3RlcCAqZnVuY3MpCj4gK3sKPiArCXN0cnVjdCBvcGFs X2RldiAqZGV2Owo+ICsJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCWlu dCByZXQ7Cj4gKwo+ICsJZGV2ID0gZ2V0X29yX2NyZWF0ZV9vcGFsX2RldihiZGV2LCBrZXktPmxy LCB0cnVlKTsKPiArCWlmICghZGV2KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsJY29tcGxldGlv biA9IHNldHVwX29wYWxfZGV2KGJkZXYsIGRldiwgZnVuY3MsIGtleSk7Cj4gKwlpZiAoSVNfRVJS KGNvbXBsZXRpb24pKSB7Cj4gKwkJcmV0ID0gUFRSX0VSUihjb21wbGV0aW9uKTsKPiArCQlnb3Rv IGVycm9yX3JldHVybjsKPiArCX0KPiArCj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0 X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4g KwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4g Kwo+ICsKPiArc3RhdGljIGludCBvcGFsX3NhdmVfaW50ZXJuYWwoc3RydWN0IGJsb2NrX2Rldmlj ZSAqYmRldiwKPiArCQkJICAgICAgc3RydWN0IG9wYWxfbG9ja191bmxvY2sgKmxrKQo+ICt7Cj4g Kwl2b2lkICpmdW5jX2RhdGFbM10gPSB7IE5VTEwgfTsKPiArCXN0cnVjdCBvcGFsX2RldiAqZGV2 Owo+ICsJc3RydWN0IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCWNvbnN0IG9wYWxf c3RlcCBfYXV0aF9mdW5jc1tdID0gewo+ICsJCW9wYWxfZGlzY292ZXJ5MCwKPiArCQlzdGFydF9h dXRoX29wYWxfc2Vzc2lvbiwKPiArCQlxdWVyeV9sb2NraW5nX3JhbmdlLAo+ICsJCWVuZF9vcGFs X3Nlc3Npb24sCj4gKwkJb3BhbF9yZWdpc3Rlcl9jb250LAo+ICsJCU5VTEwKPiArCX07Cj4gKwlp bnQgcmV0Owo+ICsKPiArCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgbGstPmtl eS5sciwgZmFsc2UpOwo+ICsJaWYgKCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwljb21w bGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBfYXV0aF9mdW5jcywgJmxrLT5rZXkp Owo+ICsJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBUUl9FUlIoY29tcGxl dGlvbik7Cj4gKwkJZ290byBlcnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZGV2LT5udW1fZnVu Y19kYXRhID0gMzsKPiArCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOwo+ICsJZGV2LT5mdW5j X2RhdGFbMV0gPSAmbGstPmF1dGhvcml0eTsKPiArCWRldi0+bGt1bCA9ICpsazsKPiArCj4gKwlu ZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9u KTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxfZGV2KGRl dik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkZF91c2VyX2xyX2lu dGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQlzdHJ1Y3Qgb3BhbF9sb2Nr X3VubG9jayAqbGspCj4gK3sKPiArCXZvaWQgKmZ1bmNfZGF0YVszXSA9IHsgTlVMTCB9Owo+ICsJ c3RydWN0IG9wYWxfZGV2ICpkZXY7Cj4gKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpjb21wbGV0 aW9uOwo+ICsJY29uc3Qgb3BhbF9zdGVwIGZ1bmNzW10gPSB7Cj4gKwkJb3BhbF9kaXNjb3Zlcnkw LAo+ICsJCXN0YXJ0X2FkbWluMUxTUF9vcGFsX3Nlc3Npb24sCj4gKwkJYWRkX3VzZXJfdG9fbHIs Cj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlOVUxMCj4gKwl9Owo+ICsJaW50IHJldDsKPiAr Cj4gKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJkZXYsIGxrLT5rZXkubHIsIHRydWUp Owo+ICsJaWYgKCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwljb21wbGV0aW9uID0gc2V0 dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBmdW5jcywgJmxrLT5rZXkpOwo+ICsJaWYgKElTX0VSUihj b21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBl cnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZGV2LT5udW1fZnVuY19kYXRhID0gMzsKPiArCWRl di0+ZnVuY19kYXRhID0gZnVuY19kYXRhOwo+ICsJZGV2LT5mdW5jX2RhdGFbMl0gPSBsazsKPiAr Cj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21w bGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVfYW5kX2NsZWFuX29wYWxf ZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGxvY2tfdW5s b2NrX2ludGVybmFsKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQlzdHJ1Y3Qgb3Bh bF9sb2NrX3VubG9jayAqbGspCj4gK3sKPiArCXZvaWQgKmZ1bmNfZGF0YVszXSA9IHsgTlVMTCB9 Owo+ICsJc3RydWN0IG9wYWxfZGV2ICpkZXY7Cj4gKwlzdHJ1Y3Qgb3BhbF9jb21wbGV0aW9uICpj b21wbGV0aW9uOwo+ICsKPiArCWNvbnN0IG9wYWxfc3RlcCB1bGtfZnVuY3NfU1VNW10gPSB7Cj4g KwkJb3BhbF9kaXNjb3ZlcnkwLAo+ICsJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAo+ICsJCWxv Y2tfdW5sb2NrX2xvY2tpbmdfcmFuZ2VfU1VNLAo+ICsJCWVuZF9vcGFsX3Nlc3Npb24sCj4gKwkJ TlVMTAo+ICsJfTsKPiArCWNvbnN0IG9wYWxfc3RlcCBfdW5sb2NrX2Z1bmNzW10gPSB7Cj4gKwkJ b3BhbF9kaXNjb3ZlcnkwLAo+ICsJCXN0YXJ0X2F1dGhfb3BhbF9zZXNzaW9uLAo+ICsJCWxvY2tf dW5sb2NrX2xvY2tpbmdfcmFuZ2UsCj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlOVUxMCj4g Kwl9Owo+ICsJaW50IHJldDsKPiArCj4gKwlkZXYgPSBnZXRfb3JfY3JlYXRlX29wYWxfZGV2KGJk ZXYsIGxrLT5rZXkubHIsIHRydWUpOwo+ICsJaWYgKCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07 Cj4gKwo+ICsJaWYgKGxrLT5hdXRob3JpdHkuU1VNKQo+ICsJCWNvbXBsZXRpb24gPSBzZXR1cF9v cGFsX2RldihiZGV2LCBkZXYsIHVsa19mdW5jc19TVU0sICZsay0+a2V5KTsKPiArCWVsc2UKPiAr CQljb21wbGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBfdW5sb2NrX2Z1bmNzLCAm bGstPmtleSk7Cj4gKwo+ICsJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgewo+ICsJCXJldCA9IFBU Ul9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBlcnJvcl9yZXR1cm47Cj4gKwl9Cj4gKwo+ICsJ ZGV2LT5udW1fZnVuY19kYXRhID0gMzsKPiArCWRldi0+ZnVuY19kYXRhID0gZnVuY19kYXRhOwo+ ICsJZGV2LT5mdW5jX2RhdGFbMV0gPSAmbGstPmF1dGhvcml0eTsKPiArCWRldi0+ZnVuY19kYXRh WzJdID0gbGs7Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0ID0gd2FpdF9mb3JfY21kX2Nv bXBsZXRpb24oY29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0dXJuOgo+ICsJcmVtb3ZlX2Fu ZF9jbGVhbl9vcGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiAraW50IG9w YWxfZXJhc2VfbG9ja2luZ19yYW5nZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qg c2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9kZXYgKmRldjsKPiArCXN0cnVjdCBv cGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247Cj4gKwlzdHJ1Y3Qgb3BhbF9rZXkgazsKPiArCWlu dCByZXQ7Cj4gKwljb25zdCBvcGFsX3N0ZXAgZXJhc2VfZnVuY3NbXSA9IHsKPiArCQlvcGFsX2Rp c2NvdmVyeTAsCj4gKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxfc2Vzc2lvbiwKPiArCQllcmFzZV9s b2NraW5nX3JhbmdlLAo+ICsJCWVuZF9vcGFsX3Nlc3Npb24sCj4gKwkJTlVMTCwKPiArCX07Cj4g Kwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBz YXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlO VkFMOwo+ICsJfQo+ICsKPiArCWlmIChjb3B5X2Zyb21fdXNlcigmaywga2V5LT5vcGFsLCBzaXpl b2YoKmtleS0+b3BhbCkpKQo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsKPiArCWRldiA9IGdldF9v cl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgay5sciwgdHJ1ZSk7Cj4gKwlpZiAoIWRldikKPiArCQly ZXR1cm4gLUVOT01FTTsKPiArCj4gKwljb21wbGV0aW9uID0gc2V0dXBfb3BhbF9kZXYoYmRldiwg ZGV2LCBlcmFzZV9mdW5jcywgJmspOwo+ICsJaWYgKElTX0VSUihjb21wbGV0aW9uKSkgewo+ICsJ CXJldCA9IFBUUl9FUlIoY29tcGxldGlvbik7Cj4gKwkJZ290byBlcnJvcl9yZXR1cm47Cj4gKwl9 Cj4gKwo+ICsJbmV4dCgwLCBkZXYpOwo+ICsJcmV0ID0gd2FpdF9mb3JfY21kX2NvbXBsZXRpb24o Y29tcGxldGlvbik7Cj4gKwo+ICsgZXJyb3JfcmV0dXJuOgo+ICsJcmVtb3ZlX2FuZF9jbGVhbl9v cGFsX2RldihkZXYpOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICtFWFBPUlRfU1lNQk9MKG9wYWxf ZXJhc2VfbG9ja2luZ19yYW5nZSk7Cj4gKwo+ICtpbnQgb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFk b3dfbWJyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQkgICBzdHJ1Y3Qgc2VkX2tl eSAqa2V5KQo+ICt7Cj4gKwl2b2lkICpmdW5jX2RhdGFbNl0gPSB7IE5VTEwgfTsKPiArCXN0cnVj dCBvcGFsX21icl9kYXRhIG1icjsKPiArCXN0cnVjdCBvcGFsX2RldiAqZGV2Owo+ICsJc3RydWN0 IG9wYWxfY29tcGxldGlvbiAqY29tcGxldGlvbjsKPiArCWNvbnN0IG9wYWxfc3RlcCBtYnJfZnVu Y3NbXSA9IHsKPiArCQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfYWRtaW4xTFNQX29wYWxf c2Vzc2lvbiwKPiArCQlzZXRfbWJyX2RvbmUsCj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlz dGFydF9hZG1pbjFMU1Bfb3BhbF9zZXNzaW9uLAo+ICsJCXNldF9tYnJfZW5hYmxlX2Rpc2FibGUs Cj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiArCQlOVUxMLAo+ICsJfTsKPiArCWludCByZXQ7Cj4g Kwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBz YXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRldmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlO VkFMOwo+ICsJfQo+ICsKPiArCWlmIChjb3B5X2Zyb21fdXNlcigmbWJyLCBrZXktPm9wYWxfbWJy LCBzaXplb2YoKmtleS0+b3BhbF9tYnIpKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlp ZiAobWJyLmVuYWJsZV9kaXNhYmxlICE9IE9QQUxfTUJSX0VOQUJMRSAmJgo+ICsJICAgIG1ici5l bmFibGVfZGlzYWJsZSAhPSBPUEFMX01CUl9ESVNBQkxFKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ ICsKPiArCWRldiA9IGdldF9vcl9jcmVhdGVfb3BhbF9kZXYoYmRldiwgbWJyLmtleS5sciwgdHJ1 ZSk7Cj4gKwlpZiAoIWRldikKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwljb21wbGV0aW9u ID0gc2V0dXBfb3BhbF9kZXYoYmRldiwgZGV2LCBtYnJfZnVuY3MsICZtYnIua2V5KTsKPiArCWlm IChJU19FUlIoY29tcGxldGlvbikpIHsKPiArCQlyZXQgPSBQVFJfRVJSKGNvbXBsZXRpb24pOwo+ ICsJCWdvdG8gZXJyb3JfcmV0dXJuOwo+ICsJfQo+ICsKPiArCWRldi0+bnVtX2Z1bmNfZGF0YSA9 IDY7Cj4gKwlkZXYtPmZ1bmNfZGF0YSA9IGZ1bmNfZGF0YTsKPiArCWRldi0+ZnVuY19kYXRhWzJd ID0gJm1ici5lbmFibGVfZGlzYWJsZTsKPiArCWRldi0+ZnVuY19kYXRhWzVdID0gJm1ici5lbmFi bGVfZGlzYWJsZTsKPiArCj4gKwluZXh0KDAsIGRldik7Cj4gKwlyZXQgPSB3YWl0X2Zvcl9jbWRf Y29tcGxldGlvbihjb21wbGV0aW9uKTsKPiArCj4gKyBlcnJvcl9yZXR1cm46Cj4gKwlyZW1vdmVf YW5kX2NsZWFuX29wYWxfZGV2KGRldik7Cj4gKwlyZXR1cm4gcmV0Owo+ICsKPiArfQo+ICtFWFBP UlRfU1lNQk9MKG9wYWxfZW5hYmxlX2Rpc2FibGVfc2hhZG93X21icik7Cj4gKwo+ICtpbnQgb3Bh bF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4g K3sKPiArCXN0cnVjdCBvcGFsX2xvY2tfdW5sb2NrIGxrdWw7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8 ICFiZGV2LT5iZF9kaXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBzYXZlIHBhc3N3b3JkIGZvciBO VUxMIGJsb2NrIGRldmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiAr CWlmIChjb3B5X2Zyb21fdXNlcigmbGt1bCwga2V5LT5vcGFsX2xrX3VubGssIHNpemVvZigqa2V5 LT5vcGFsKSkpCj4gKwkJcmV0dXJuIC1FRkFVTFQ7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfc2F2ZV9p bnRlcm5hbChiZGV2LCAmbGt1bCk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX3NhdmUpOwo+ ICsKPiAraW50IG9wYWxfYWRkX3VzZXJfdG9fbHIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg c3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsJc3RydWN0IG9wYWxfbG9ja191bmxvY2sgbGt1 bDsKPiArCj4gKwlpZiAoY29weV9mcm9tX3VzZXIoJmxrdWwsIGtleS0+b3BhbF9sa191bmxrLCBz aXplb2YobGt1bCkpKQo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsKPiArCWlmICghYmRldiB8fCAh YmRldi0+YmRfZGlzaykgewo+ICsJCXByX2VycigiQ2FuJ3QgYXNzaWduIHVzZXIgdG8gTFIgd2l0 aG91dCBiYWNraW5nIGRpc2tcbiIpOwo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsJfQo+ICsJaWYg KGxrdWwubF9zdGF0ZSAhPSBPUEFMX1JPICYmIGxrdWwubF9zdGF0ZSAhPSBPUEFMX1JXKSB7Cj4g KwkJcHJfZXJyKCJMb2NraW5nIHN0YXRlIHdhcyBub3QgUk8gb3IgUldcbiIpOwo+ICsJCXJldHVy biAtRUlOVkFMOwo+ICsJfQo+ICsJaWYgKGxrdWwuYXV0aG9yaXR5LndobyA8IE9QQUxfVVNFUjEg JiYKPiArCSAgICBsa3VsLmF1dGhvcml0eS53aG8gPiBPUEFMX1VTRVI5KSB7Cj4gKwkJcHJfZXJy KCJBdXRob3JpdHkgd2FzIG5vdCB3aXRoaW4gdGhlIHJhbmdlIG9mIHVzZXJzOiAlZFxuIiwKPiAr CQkgICAgICAgbGt1bC5hdXRob3JpdHkud2hvKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0K PiArCWlmIChsa3VsLmF1dGhvcml0eS5TVU0pIHsKPiArCQlwcl9lcnIoIiVzIG5vdCBzdXBwb3J0 ZWQgaW4gU1VNLiBVc2Ugc2V0dXAgbG9ja2luZyByYW5nZVxuIiwKPiArCQkgICAgICAgX19mdW5j X18pOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXJldHVybiBhZGRfdXNlcl9s cl9pbnRlcm5hbChiZGV2LCAmbGt1bCk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX2FkZF91 c2VyX3RvX2xyKTsKPiArCj4gK2ludCBvcGFsX3JldmVydHRwZXIoc3RydWN0IGJsb2NrX2Rldmlj ZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsJc3RydWN0IG9wYWxfa2V5IGs7 Cj4gKwo+ICsJaWYgKGNvcHlfZnJvbV91c2VyKCZrLCBrZXktPm9wYWwsIHNpemVvZigqa2V5LT5v cGFsKSkpCj4gKwkJcmV0dXJuIC1FRkFVTFQ7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfcmV2ZXJ0KGJk ZXYsICZrKTsKPiArfQo+ICtFWFBPUlRfU1lNQk9MKG9wYWxfcmV2ZXJ0dHBlcik7Cj4gKwo+ICtp bnQgb3BhbF9sb2NrX3VubG9jayhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk X2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9sb2NrX3VubG9jayBrOwo+ICsKPiArCWlm IChjb3B5X2Zyb21fdXNlcigmaywga2V5LT5vcGFsX2xrX3VubGssIHNpemVvZigqa2V5LT5vcGFs X2xrX3VubGspKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlpZiAoay5hdXRob3JpdHku d2hvIDwgT1BBTF9BRE1JTjEgfHwgay5hdXRob3JpdHkud2hvID49IE9QQUxfVVNFUjkpClNob3Vs ZCB0aGlzIGJlID4gT1BBTF9VU0VSOSA/CgoKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwly ZXR1cm4gbG9ja191bmxvY2tfaW50ZXJuYWwoYmRldiwgJmspOwo+ICt9Cj4gK0VYUE9SVF9TWU1C T0wob3BhbF9sb2NrX3VubG9jayk7Cj4gKwo+ICtpbnQgb3BhbF90YWtlX293bmVyc2hpcChzdHJ1 Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1 Y3Qgb3BhbF9rZXkgazsKPiArCWNvbnN0IG9wYWxfc3RlcCBvd25lcl9mdW5jc1tdID0gewo+ICsJ CW9wYWxfZGlzY292ZXJ5MCwKPiArCQlzdGFydF9hbnlib2R5QVNQX29wYWxfc2Vzc2lvbiwKPiAr CQlnZXRfbXNpZF9jcGluX3BpbiwKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCXN0YXJ0X1NJ REFTUF9vcGFsX3Nlc3Npb24sCj4gKwkJc2V0X3NpZF9jcGluX3BpbiwKPiArCQllbmRfb3BhbF9z ZXNzaW9uLAo+ICsJCU5VTEwKPiArCX07Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9k aXNrKSB7Cj4gKwkJcHJfZXJyKCJDYW4ndCBzYXZlIHBhc3N3b3JkIGZvciBOVUxMIGJsb2NrIGRl dmljZS5cbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWlmIChjb3B5X2Zy b21fdXNlcigmaywga2V5LT5vcGFsLCBzaXplb2YoKmtleS0+b3BhbCkpKQo+ICsJCXJldHVybiAt RUZBVUxUOwo+ICsKPiArCXJldHVybiBvcGFsX3JlZ2lzdGVyKGJkZXYsICZrLCBvd25lcl9mdW5j cyk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX3Rha2Vfb3duZXJzaGlwKTsKPiArCj4gK2lu dCBvcGFsX2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk X2tleSAqa2V5KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9rZXkgazsKPiArCWNvbnN0IG9wYWxfc3Rl cCBhY3RpdmVfZnVuY3NbXSA9IHsKPiArCQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfU0lE QVNQX29wYWxfc2Vzc2lvbiwgLyogT3BlbiBzZXNzaW9uIGFzIFNJRCBhdXRoICovCj4gKwkJZ2V0 X2xzcF9saWZlY3ljbGUsCj4gKwkJYWN0aXZhdGVfbHNwLAo+ICsJCWVuZF9vcGFsX3Nlc3Npb24s Cj4gKwkJTlVMTAo+ICsJfTsKPiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2spIHsK PiArCQlwcl9lcnIoIkNhbid0IHNhdmUgcGFzc3dvcmQgZm9yIE5VTEwgYmxvY2sgZGV2aWNlLlxu Iik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJaWYgKGNvcHlfZnJvbV91c2Vy KCZrLCBrZXktPm9wYWwsIHNpemVvZigqa2V5LT5vcGFsKSkpCj4gKwkJcmV0dXJuIC1FRkFVTFQ7 Cj4gKwo+ICsJcmV0dXJuIG9wYWxfYWN0X2xzcF9pbnQoYmRldiwgJmssIGFjdGl2ZV9mdW5jcyk7 Cj4gK30KPiArRVhQT1JUX1NZTUJPTChvcGFsX2FjdGl2YXRlX2xzcCk7Cj4gKwo+ICtpbnQgb3Bh bF9zZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBz ZWRfa2V5ICpwdykKPiArewo+ICsJc3RydWN0IG9wYWxfdXNlcl9scl9zZXR1cCBrOwo+ICsKPiAr CWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzaykgewo+ICsJCXByX2VycigiQ2FuJ3Qgc2F2ZSBw YXNzd29yZCBmb3IgTlVMTCBibG9jayBkZXZpY2UuXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsK PiArCX0KPiArCj4gKwlpZiAoY29weV9mcm9tX3VzZXIoJmssIHB3LT5vcGFsX2xycywgc2l6ZW9m KCpwdy0+b3BhbF9scnMpKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiArCj4gKwlyZXR1cm4gaW50 ZXJuYWxfc2V0dXBfbHIoYmRldiwgJmspOwo+ICt9Cj4gKwo+ICtpbnQgb3BhbF9zZXRfbmV3X3B3 KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICpwdykKPiArewo+ICsJ c3RydWN0IG9wYWxfbmV3X3B3IGs7Cj4gKwo+ICsJaWYgKHB3LT5zZWRfdHlwZSAhPSBPUEFMX1BX KQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWlmIChjb3B5X2Zyb21fdXNlcigmaywgcHct Pm9wYWxfcHcsIHNpemVvZigqcHctPm9wYWxfcHcpKSkKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiAr Cj4gKwlpZiAoay53aG8ud2hvIDwgT1BBTF9BRE1JTjEgfHwgay53aG8ud2hvID4gT1BBTF9VU0VS OSkKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlyZXR1cm4gb3BhbF9zZXRfcHcoYmRldiwg JmspOwo+ICt9Cj4gK0VYUE9SVF9TWU1CT0wob3BhbF9zZXRfbmV3X3B3KTsKPiArCj4gK2ludCBv cGFsX2FjdGl2YXRlX3VzZXIoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9r ZXkgKnB3KQo+ICt7Cj4gKwlzdHJ1Y3Qgb3BhbF9hY3RpdmF0ZV91c2VyIGs7Cj4gKwo+ICsJaWYg KHB3LT5zZWRfdHlwZSAhPSBPUEFMX0FDVF9VU1IpIHsKPiArCQlwcl9lcnIoIlNlZCB0eXBlIHdh cyBub3QgYWN0IHVzZXJcbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWlm IChjb3B5X2Zyb21fdXNlcigmaywgcHctPm9wYWxfYWN0LCBzaXplb2YoKnB3LT5vcGFsX2FjdCkp KSB7Cj4gKwkJcHJfZXJyKCJjb3B5IGZyb20gdXNlciBlcnJvclxuIik7Cj4gKwkJcmV0dXJuIC1F RkFVTFQ7Cj4gKwl9Cj4gKwo+ICsJLyogV2UgY2FuJ3QgYWN0aXZhdGUgQWRtaW4xIGl0J3MgYWN0 aXZlIGFzIG1hbnVmYWN0dXJlZCAqLwo+ICsJaWYgKGsud2hvLndobyA8IE9QQUxfVVNFUjEgJiYg ay53aG8ud2hvID4gT1BBTF9VU0VSOSkgewo+ICsJCXByX2VycigiV2hvIHdhcyBub3QgYSB2YWxp ZCB1c2VyOiAlZCBcbiIsIGsud2hvLndobyk7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4g Kwo+ICsJcmV0dXJuIGFjdGl2YXRlX3VzZXIoYmRldiwgJmspOwo+ICsKPiArfQo+ICtFWFBPUlRf U1lNQk9MKG9wYWxfYWN0aXZhdGVfdXNlcik7Cj4gKwo+ICtpbnQgb3BhbF91bmxvY2tfZnJvbV9z dXNwZW5kKHN0cnVjdCBvcGFsX3N1c3BlbmRfdW5sayAqZGF0YSkKPiArewo+ICsJY29uc3QgY2hh ciAqZGlza25hbWUgPSBkYXRhLT5uYW1lOwo+ICsJc3RydWN0IG9wYWxfZGV2ICppdGVyLCAqZGV2 ID0gTlVMTDsKPiArCXN0cnVjdCBvcGFsX2NvbXBsZXRpb24gKmNvbXBsZXRpb247Cj4gKwl2b2lk ICpmdW5jX2RhdGFbM10gPSB7IE5VTEwgfTsKPiArCWNvbnN0IG9wYWxfc3RlcCBfdW5sb2NrX2Z1 bmNzX1NVTVtdID0gewo+ICsJCW9wYWxfZGlzY292ZXJ5MCwKPiArCQlzdGFydF9hdXRoX29wYWxf c2Vzc2lvbiwKPiArCQlsb2NrX3VubG9ja19sb2NraW5nX3JhbmdlLApEaWQgeW91IG1lYW4gdG8g dXNlIGxvY2tfdW5sb2NrX2xvY2tpbmdfcmFuZ2VfU1VNID8KQ2FuIHdlIHB1bGwgdGhlc2UgdHdv IGFycmF5cyBvdXQgc2luY2UgdGhleSBhcmUgcmVxdWlyZWQgZm9yIGJvdGggdGhpcwpmdW5jdGlv biBhbmQgbG9ja191bmxvY2tfaW50ZXJuYWwgPwoKCj4gKwkJZW5kX29wYWxfc2Vzc2lvbiwKPiAr CQlOVUxMCj4gKwl9Owo+ICsJY29uc3Qgb3BhbF9zdGVwIF91bmxvY2tfZnVuY3NbXSA9IHsKPiAr CQlvcGFsX2Rpc2NvdmVyeTAsCj4gKwkJc3RhcnRfYXV0aF9vcGFsX3Nlc3Npb24sCj4gKwkJbG9j a191bmxvY2tfbG9ja2luZ19yYW5nZSwKPiArCQllbmRfb3BhbF9zZXNzaW9uLAo+ICsJCU5VTEwK PiArCX07Cj4gKwo+ICsKPiArCXNwaW5fbG9jaygmbGlzdF9zcGlubG9jayk7Cj4gKwlsaXN0X2Zv cl9lYWNoX2VudHJ5KGl0ZXIsICZvcGFsX2xpc3QsIG5vZGUpIHsKPiArCQlpZiAoc3RybmNtcChp dGVyLT5kaXNrX25hbWUsIGRpc2tuYW1lLCBESVNLX05BTUVfTEVOKSkgewo+ICsJCQlwcl9lcnIo Iml0ZXJkaXNrIHdhcyAlcyBhbmQgZGlza25hbWUgaXMgJXNcbiIsCj4gKwkJCSAgICAgICBpdGVy LT5kaXNrX25hbWUsIGRpc2tuYW1lKTsKPiArCQkJY29udGludWU7Cj4gKwkJfQo+ICsJCWlmIChh dG9taWNfYWRkX3VubGVzcygmaXRlci0+aW5fdXNlLCAxLCAxKSkgewo+ICsJCQlkZXYgPSBpdGVy Owo+ICsJCQlkZXYtPmZ1bmNfZGF0YSA9IGZ1bmNfZGF0YTsKPiArCQkJZGV2LT5yZXN1bWVfZnJv bV9zdXNwZW5kID0gdHJ1ZTsKPiArCQkJZGV2LT5yZXN1bWVfZGF0YSA9IGRhdGE7Cj4gKwkJCWRl di0+ZmluYWxfY2IgPSB1bmxvY2tfc3VzcGVuZF9maW5hbDsKPiArCQkJZGV2LT5maW5hbF9jYl9k YXRhID0gZGV2Owo+ICsJCQlkZXYtPmVycm9yX2NiID0gZW5kX29wYWxfc2Vzc2lvbl9lcnJvcjsK PiArCQkJZGV2LT5lcnJvcl9jYl9kYXRhID0gZGV2Owo+ICsJCQlkZXYtPnN0YXRlID0gMDsKPiAr CQkJaWYgKGRldi0+bGt1bC5hdXRob3JpdHkuU1VNKQo+ICsJCQkJZGV2LT5mdW5jcyA9IF91bmxv Y2tfZnVuY3NfU1VNOwo+ICsJCQllbHNlCj4gKwkJCQlkZXYtPmZ1bmNzID0gX3VubG9ja19mdW5j czsKPiArCQkJZGV2LT5UU04gPSAwOwo+ICsJCQlkZXYtPkhTTiA9IDA7Cj4gKwkJCWRldi0+ZnVu Y19kYXRhWzJdID0gJmRldi0+bGt1bDsKPiArCQkJZGV2LT5mdW5jX2RhdGFbMV0gPSAmZGV2LT5s a3VsLmF1dGhvcml0eTsKPiArCQkJY29tcGxldGlvbiA9IGRldi0+Y29tcGxldGlvbjsKPiArCQkJ bmV4dCgwLCBkZXYpOwo+ICsJCQl3YWl0X2Zvcl9jbWRfY29tcGxldGlvbihjb21wbGV0aW9uKTsK PiArCQl9Cj4gKwl9Cj4gKwlzcGluX3VubG9jaygmbGlzdF9zcGlubG9jayk7Cj4gKwo+ICsJaWYg KCFkZXYpCj4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICtFWFBPUlRf U1lNQk9MKG9wYWxfdW5sb2NrX2Zyb21fc3VzcGVuZCk7Cj4gZGlmZiAtLWdpdCBhL2xpYi9zZWQt b3BhbF9pbnRlcm5hbC5oIGIvbGliL3NlZC1vcGFsX2ludGVybmFsLmgKPiBuZXcgZmlsZSBtb2Rl IDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLmM5ZDM4ODMKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIv bGliL3NlZC1vcGFsX2ludGVybmFsLmgKPiBAQCAtMCwwICsxLDU4NiBAQAo+ICsvKgo+ICsgKiBD b3B5cmlnaHQgwqkgMjAxNiBJbnRlbCBDb3Jwb3JhdGlvbgo+ICsgKgo+ICsgKiBQZXJtaXNzaW9u IGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5p bmcgYQo+ICsgKiBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRh dGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLAo+ICsgKiB0byBkZWFsIGluIHRoZSBTb2Z0d2Fy ZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uCj4gKyAq IHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmli dXRlLCBzdWJsaWNlbnNlLAo+ICsgKiBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJl LCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUKPiArICogU29mdHdhcmUgaXMgZnVy bmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKPiAr ICoKPiArICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBu b3RpY2UgKGluY2x1ZGluZyB0aGUgbmV4dAo+ICsgKiBwYXJhZ3JhcGgpIHNoYWxsIGJlIGluY2x1 ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlCj4gKyAqIFNv ZnR3YXJlLgo+ICsgKgo+ICsgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lU SE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgo+ICsgKiBJTVBMSUVELCBJTkNM VURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElU WSwKPiArICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdF TUVOVC4gIElOIE5PIEVWRU5UIFNIQUxMCj4gKyAqIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBI T0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCj4gKyAqIExJ QUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJX SVNFLCBBUklTSU5HCj4gKyAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhF IFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MKPiArICogSU4gVEhFIFNPRlRX QVJFLgo+ICsgKgo+ICsgKiBBdXRob3I6Cj4gKyAqICAgIFJhZmFlbCBBbnRvZ25vbGxpIDxyYWZh ZWwuYW50b2dub2xsaUBpbnRlbC5jb20+Cj4gKyAqICAgIFNjb3R0ICBCYXVlciAgICAgIDxzY290 dC5iYXVlckBpbnRlbC5jb20+Cj4gKyAqLwo+ICsKPiArI2lmbmRlZiBfTlZNRV9PUEFMX0lOVEVS TkFMX0gKPiArI2RlZmluZSBfTlZNRV9PUEFMX0lOVEVSTkFMX0gKPiArCj4gKyNpbmNsdWRlIDxs aW51eC9rZXktdHlwZS5oPgo+ICsjaW5jbHVkZSA8a2V5cy91c2VyLXR5cGUuaD4KPiArCj4gKyNk ZWZpbmUgRFRBRVJST1JfTk9fTUVUSE9EX1NUQVRVUyAweDg5Cj4gKwo+ICtzdGF0aWMgY29uc3Qg Y2hhciAqb3BhbF9lcnJvcnNbMTldID0gewpSZW1vdmUgdGhlIDE5IHNvIGl0J3MganVzdCBvcGFs X2Vycm9yc1tdIChkb2VzbnQgc2lsZW50bHkgdHJ1bmNhdGUgYW55Cm5ldyBhZGRpdGlvbnMpCgoK PiArCSJTdWNjZXNzIiwKPiArCSJOb3QgQXV0aG9yaXplZCIsCj4gKwkiVW5rbm93biBFcnJvciIs Cj4gKwkiU1AgQnVzeSIsCj4gKwkiU1AgRmFpbGVkIiwKPiArCSJTUCBEaXNhYmxlZCIsCj4gKwki U1AgRnJvemVuIiwKPiArCSJObyBTZXNzaW9ucyBBdmFpbGFibGUiLAo+ICsJIlVuaXF1ZW5lc3Mg Q29uZmxpY3QiLAo+ICsJIkluc3VmZmljaWVudCBTcGFjZSIsCj4gKwkiSW5zdWZmaWNpZW50IFJv d3MiLAo+ICsJIkludmFsaWQgRnVuY3Rpb24iLAo+ICsJIkludmFsaWQgUGFyYW1ldGVyIiwKPiAr CSJJbnZhbGlkIFJlZmVyZW5jZSIsCj4gKwkiVW5rbm93biBFcnJvciIsCj4gKwkiVFBFUiBNYWxm dW5jdGlvbiIsCj4gKwkiVHJhbnNhY3Rpb24gRmFpbHVyZSIsCj4gKwkiUmVzcG9uc2UgT3ZlcmZs b3ciLAo+ICsJIkF1dGhvcml0eSBMb2NrZWQgT3V0IiwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25z dCBjaGFyICpvcGFsX2Vycm9yX3RvX2h1bWFuKGludCBlcnJvcikKPiArewo+ICsJaWYgKGVycm9y ID09IDB4M2YpCj4gKwkJcmV0dXJuICJGYWlsZWQiOwo+ICsKPiArCWlmIChlcnJvciA+PSBzaXpl b2Yob3BhbF9lcnJvcnMpIHx8IGVycm9yIDwgMCkKWW91IHdhbnQgc2l6ZW9mKG9wYWxfZXJyb3Jz KS9zaXplb2YoKm9wYWxfZXJyb3JzKSBoZXJlLCBidXQgeW91IGNhbiBqdXN0CnVzZSB0aGUgQVJS QVlfU0laRSBtYWNybyBpbnN0ZWFkCgoKPiArCQlyZXR1cm4gIlVua25vd24gRXJyb3IiOwo+ICsK PiArCXJldHVybiBvcGFsX2Vycm9yc1tlcnJvcl07Cj4gK30KPiArCj4gKy8qIFVzZXIgSURzIHVz ZWQgaW4gdGhlIFRDRyBzdG9yYWdlIFNTQ3MgKi8KPiArc3RhdGljIGNvbnN0IHU4IE9QQUxVSURb XVs4XSA9IHsKPiArCS8qIHVzZXJzICovCj4gKwo+ICsJLyogc2Vzc2lvbiBtYW5hZ2VtZW50ICAq Lwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweGZmfSwK PiArCS8qIHNwZWNpYWwgInRoaXNTUCIgc3ludGF4ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAs IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEgfSwKPiArCS8qIEFkbWluaXN0cmF0aXZlIFNQ ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDIsIDB4MDUsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDEg fSwKPiArCS8qIExvY2tpbmcgU1AgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMiwgMHgwNSwgMHgw MCwgMHgwMCwgMHgwMCwgMHgwMiB9LAo+ICsJLyogRU5URVJQUklTRSBMb2NraW5nIFNQICAqLwo+ ICsJeyAweDAwLCAweDAwLCAweDAyLCAweDA1LCAweDAwLCAweDAxLCAweDAwLCAweDAxIH0sCj4g KwkvKiBhbnlib2R5ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDAs IDB4MDAsIDB4MDEgfSwKPiArCS8qIFNJRCAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA5 LCAweDAwLCAweDAwLCAweDAwLCAweDA2IH0sCj4gKwkvKiBBRE1JTjEgKi8KPiArCXsgMHgwMCwg MHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMSwgMHgwMCwgMHgwMSB9LAo+ICsJLyogVVNFUjEg Ki8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgwMywgMHgwMCwgMHgwMSB9 LAo+ICsJLyogVVNFUjIgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgwMCwgMHgw MywgMHgwMCwgMHgwMiB9LAo+ICsJLyogUFNJRCB1c2VyICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4 MDAsIDB4MDksIDB4MDAsIDB4MDEsIDB4ZmYsIDB4MDEgfSwKPiArCS8qIEJhbmRNYXN0ZXIgMCAq Lwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA5LCAweDAwLCAweDAwLCAweDgwLCAweDAxIH0s Cj4gKwkgLyogRXJhc2VNYXN0ZXIgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwOSwgMHgw MCwgMHgwMCwgMHg4NCwgMHgwMSB9LAo+ICsKPiArCS8qIHRhYmxlcyAqLwo+ICsKPiArCS8qIExv Y2tpbmdfR2xvYmFsUmFuZ2UgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwOCwgMHgwMiwgMHgwMCwg MHgwMCwgMHgwMCwgMHgwMSB9LAo+ICsJLyogQUNFX0xvY2tpbmdfUmFuZ2VfU2V0X1JkTG9ja2Vk IFVJRCAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA4LCAweDAwLCAweDAzLCAweEUwLCAw eDAxIH0sCj4gKwkvKiBBQ0VfTG9ja2luZ19SYW5nZV9TZXRfV3JMb2NrZWQgVUlEICovCj4gKwl7 IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDgsIDB4MDAsIDB4MDMsIDB4RTgsIDB4MDEgfSwKPiArCS8q IE1CUiBDb250cm9sICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDgsIDB4MDMsIDB4MDAsIDB4MDAs IDB4MDAsIDB4MDEgfSwKPiArCS8qIFNoYWRvdyBNQlIgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgw OCwgMHgwNCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCB9LAo+ICsJLyogQVVUSE9SSVRZX1RBQkxF ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDksIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDB9 LAo+ICsJLyogQ19QSU5fVEFCTEUgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwQiwgMHgw MCwgMHgwMCwgMHgwMCwgMHgwMH0sCj4gKwkvKiBPUEFMIExvY2tpbmcgSW5mbyAqLwo+ICsJeyAw eDAwLCAweDAwLCAweDA4LCAweDAxLCAweDAwLCAweDAwLCAweDAwLCAweDAxIH0sCj4gKwkvKiBF bnRlcnByaXNlIExvY2tpbmcgSW5mbyAqLwo+ICsJeyAweDAwLCAweDAwLCAweDA4LCAweDAxLCAw eDAwLCAweDAwLCAweDAwLCAweDAwIH0sCj4gKwo+ICsJLyogQ19QSU5fVEFCTEUgb2JqZWN0IElE J3MgKi8KPiArCj4gKwkvKiBDX1BJTl9NU0lEICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4 MEIsIDB4MDAsIDB4MDAsIDB4ODQsIDB4MDJ9LAo+ICsJLyogQ19QSU5fU0lEICovCj4gKwl7IDB4 MDAsIDB4MDAsIDB4MDAsIDB4MEIsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDF9LAo+ICsJIC8qIENf UElOX0FETUlOMSAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDBCLCAweDAwLCAweDAxLCAw eDAwLCAweDAxfSwKPiArCj4gKwkvKiBoYWxmIFVJRCdzIChvbmx5IGZpcnN0IDQgYnl0ZXMgdXNl ZCkgKi8KPiArCj4gKwkvKiBIYWxmLVVJRCDigJMgQXV0aG9yaXR5X29iamVjdF9yZWYgKi8KPiAr CXsgMHgwMCwgMHgwMCwgMHgwQywgMHgwNSwgMHhmZiwgMHhmZiwgMHhmZiwgMHhmZiB9LAo+ICsJ LyogSGFsZi1VSUQg4oCTIEJvb2xlYW4gQUNFICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDQsIDB4 MEUsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYgfSwKPiArCj4gKwkvKiBzcGVjaWFsIHZhbHVlIGZv ciBvbWl0dGVkIG9wdGlvbmFsIHBhcmFtZXRlciAqLwo+ICsKPiArCS8qIEhFWEZGIGZvciBvbWl0 dGVkICovCj4gKwl7IDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4ZmYsIDB4 ZmZ9LAo+ICt9Owo+ICtzdGF0aWMgY29uc3Qgc2l6ZV90IE9QQUxfVUlEX0xFTkdUSCA9IDg7Cj4g K3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9NU0lEX0tFWUxFTiA9IDE1Owo+ICtzdGF0aWMgY29u c3Qgc2l6ZV90IE9QQUxfVUlEX0xFTkdUSF9IQUxGID0gNDsKPiArCj4gKwo+ICsvKiBFbnVtIHRv IGluZGV4IE9QQUxVSUQgYXJyYXkgKi8KPiArZW51bSBPUEFMX1VJRCB7Cj4gKwkvKiB1c2VycyAq Lwo+ICsJT1BBTF9TTVVJRF9VSUQsCj4gKwlPUEFMX1RISVNTUF9VSUQsCj4gKwlPUEFMX0FETUlO U1BfVUlELAo+ICsJT1BBTF9MT0NLSU5HU1BfVUlELAo+ICsJT1BBTF9FTlRFUlBSSVNFX0xPQ0tJ TkdTUF9VSUQsCj4gKwlPUEFMX0FOWUJPRFlfVUlELAo+ICsJT1BBTF9TSURfVUlELAo+ICsJT1BB TF9BRE1JTjFfVUlELAo+ICsJT1BBTF9VU0VSMV9VSUQsCj4gKwlPUEFMX1VTRVIyX1VJRCwKPiAr CU9QQUxfUFNJRF9VSUQsCj4gKwlPUEFMX0VOVEVSUFJJU0VfQkFORE1BU1RFUjBfVUlELAo+ICsJ T1BBTF9FTlRFUlBSSVNFX0VSQVNFTUFTVEVSX1VJRCwKPiArCS8qIHRhYmxlcyAqLwo+ICsJT1BB TF9MT0NLSU5HUkFOR0VfR0xPQkFMLAo+ICsJT1BBTF9MT0NLSU5HUkFOR0VfQUNFX1JETE9DS0VE LAo+ICsJT1BBTF9MT0NLSU5HUkFOR0VfQUNFX1dSTE9DS0VELAo+ICsJT1BBTF9NQlJDT05UUk9M LAo+ICsJT1BBTF9NQlIsCj4gKwlPUEFMX0FVVEhPUklUWV9UQUJMRSwKPiArCU9QQUxfQ19QSU5f VEFCTEUsCj4gKwlPUEFMX0xPQ0tJTkdfSU5GT19UQUJMRSwKPiArCU9QQUxfRU5URVJQUklTRV9M T0NLSU5HX0lORk9fVEFCTEUsCj4gKwkvKiBDX1BJTl9UQUJMRSBvYmplY3QgSUQncyAqLwo+ICsJ T1BBTF9DX1BJTl9NU0lELAo+ICsJT1BBTF9DX1BJTl9TSUQsCj4gKwlPUEFMX0NfUElOX0FETUlO MSwKPiArCS8qIGhhbGYgVUlEJ3MgKG9ubHkgZmlyc3QgNCBieXRlcyB1c2VkKSAqLwo+ICsJT1BB TF9IQUxGX1VJRF9BVVRIT1JJVFlfT0JKX1JFRiwKPiArCU9QQUxfSEFMRl9VSURfQk9PTEVBTl9B Q0UsCj4gKwkvKiBvbWl0dGVkIG9wdGlvbmFsIHBhcmFtZXRlciAqLwo+ICsJT1BBTF9VSURfSEVY RkYsCj4gK307Cj4gKwo+ICsvKgo+ICsgKiBUQ0cgU3RvcmFnZSBTU0MgTWV0aG9kcy4KPiArICov Cj4gK3N0YXRpYyBjb25zdCB1OCBPUEFMTUVUSE9EW11bOF0gPSB7Cj4gKwkvKiBQcm9wZXJ0aWVz ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MDAsIDB4ZmYsIDB4MDEg fSwKPiArCS8qIFNUQVJUU0VTU0lPTiAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw eDAwLCAweDAwLCAweGZmLCAweDAyIH0sCj4gKwkvKiBSZXZlcnQgKi8KPiArCXsgMHgwMCwgMHgw MCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMiwgMHgwMiB9LAo+ICsJLyogQWN0aXZhdGUg Ki8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMiwgMHgwMyB9 LAo+ICsJLyogRW50ZXJwcmlzZSBHZXQgKi8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwg MHgwMCwgMHgwMCwgMHgwMCwgMHgwNiB9LAo+ICsJLyogRW50ZXJwcmlzZSBTZXQgKi8KPiArCXsg MHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNyB9LAo+ICsJLyog TkVYVCAqLwo+ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAw eDA4IH0sCj4gKwkvKiBFbnRlcnByaXNlIEF1dGhlbnRpY2F0ZSAqLwo+ICsJeyAweDAwLCAweDAw LCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDBjIH0sCj4gKwkvKiBHZXRBQ0wgKi8K PiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwZCB9LAo+ ICsJLyogR2VuS2V5ICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4MDAsIDB4MDAs IDB4MDAsIDB4MTAgfSwKPiArCS8qIHJldmVydFNQICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAs IDB4MDYsIDB4MDAsIDB4MDAsIDB4MDAsIDB4MTEgfSwKPiArCS8qIEdldCAqLwo+ICsJeyAweDAw LCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDAwLCAweDE2IH0sCj4gKwkvKiBTZXQg Ki8KPiArCXsgMHgwMCwgMHgwMCwgMHgwMCwgMHgwNiwgMHgwMCwgMHgwMCwgMHgwMCwgMHgxNyB9 LAo+ICsJLyogQXV0aGVudGljYXRlICovCj4gKwl7IDB4MDAsIDB4MDAsIDB4MDAsIDB4MDYsIDB4 MDAsIDB4MDAsIDB4MDAsIDB4MWMgfSwKPiArCS8qIFJhbmRvbSAqLwo+ICsJeyAweDAwLCAweDAw LCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDA2LCAweDAxIH0sCj4gKwkvKiBFcmFzZSAqLwo+ ICsJeyAweDAwLCAweDAwLCAweDAwLCAweDA2LCAweDAwLCAweDAwLCAweDA4LCAweDAzIH0sCj4g K307Cj4gK3N0YXRpYyBjb25zdCBzaXplX3QgT1BBTF9NRVRIT0RfTEVOR1RIID0gODsKPiArCj4g Ky8qIEVudW0gZm9yIGluZGV4aW5nIHRoZSBPUEFMTUVUSE9EIGFycmF5ICovCj4gK2VudW0gT1BB TF9NRVRIT0Qgewo+ICsJT1BBTF9QUk9QRVJUSUVTLAo+ICsJT1BBTF9TVEFSVFNFU1NJT04sCj4g KwlPUEFMX1JFVkVSVCwKPiArCU9QQUxfQUNUSVZBVEUsCj4gKwlPUEFMX0VHRVQsCj4gKwlPUEFM X0VTRVQsCj4gKwlPUEFMX05FWFQsCj4gKwlPUEFMX0VBVVRIRU5USUNBVEUsCj4gKwlPUEFMX0dF VEFDTCwKPiArCU9QQUxfR0VOS0VZLAo+ICsJT1BBTF9SRVZFUlRTUCwKPiArCU9QQUxfR0VULAo+ ICsJT1BBTF9TRVQsCj4gKwlPUEFMX0FVVEhFTlRJQ0FURSwKPiArCU9QQUxfUkFORE9NLAo+ICsJ T1BBTF9FUkFTRSwKPiArfTsKPiArCj4gK2VudW0gT1BBTF9SRVNQT05TRV9UT0tFTiB7Cj4gKwlP UEFMX0RUQV9UT0tFTklEX0JZVEVTVFJJTkcgPSAweGUwLAo+ICsJT1BBTF9EVEFfVE9LRU5JRF9T SU5UID0gMHhlMSwKPiArCU9QQUxfRFRBX1RPS0VOSURfVUlOVCA9IDB4ZTIsCj4gKwlPUEFMX0RU QV9UT0tFTklEX1RPS0VOID0gMHhlMywgLyogYWN0dWFsIHRva2VuIGlzIHJldHVybmVkICovCj4g KwlPUEFMX0RUQV9UT0tFTklEX0lOVkFMSUQgPSAwWDAKPiArfTsKPiArCj4gK2VudW0gT1BBTF9U T0tFTiB7Cj4gKwkvKiBCb29sZWFuICovCj4gKwlPUEFMX1RSVUUgPSAweDAxLAo+ICsJT1BBTF9G QUxTRSA9IDB4MDAsCj4gKwlPUEFMX0JPT0xFQU5fRVhQUiA9IDB4MDMsCj4gKwkvKiBjZWxsYmxv Y2tzICovCj4gKwlPUEFMX1RBQkxFID0gMHgwMCwKPiArCU9QQUxfU1RBUlRST1cgPSAweDAxLAo+ ICsJT1BBTF9FTkRST1cgPSAweDAyLAo+ICsJT1BBTF9TVEFSVENPTFVNTiA9IDB4MDMsCj4gKwlP UEFMX0VORENPTFVNTiA9IDB4MDQsCj4gKwlPUEFMX1ZBTFVFUyA9IDB4MDEsCj4gKwkvKiBhdXRo b3JpdHkgdGFibGUgKi8KPiArCU9QQUxfUElOID0gMHgwMywKPiArCS8qIGxvY2tpbmcgdG9rZW5z ICovCj4gKwlPUEFMX1JBTkdFU1RBUlQgPSAweDAzLAo+ICsJT1BBTF9SQU5HRUxFTkdUSCA9IDB4 MDQsCj4gKwlPUEFMX1JFQURMT0NLRU5BQkxFRCA9IDB4MDUsCj4gKwlPUEFMX1dSSVRFTE9DS0VO QUJMRUQgPSAweDA2LAo+ICsJT1BBTF9SRUFETE9DS0VEID0gMHgwNywKPiArCU9QQUxfV1JJVEVM T0NLRUQgPSAweDA4LAo+ICsJT1BBTF9BQ1RJVkVLRVkgPSAweDBBLAo+ICsJLyogbG9ja2luZyBp bmZvIHRhYmxlICovCj4gKwlPUEFMX01BWFJBTkdFUyA9IDB4MDQsCj4gKwkgLyogbWJyIGNvbnRy b2wgKi8KPiArCU9QQUxfTUJSRU5BQkxFID0gMHgwMSwKPiArCU9QQUxfTUJSRE9ORSA9IDB4MDIs Cj4gKwkvKiBwcm9wZXJ0aWVzICovCj4gKwlPUEFMX0hPU1RQUk9QRVJUSUVTID0gMHgwMCwKPiAr CS8qIGF0b21zICovCj4gKwlPUEFMX1NUQVJUTElTVCA9IDB4ZjAsCj4gKwlPUEFMX0VORExJU1Qg PSAweGYxLAo+ICsJT1BBTF9TVEFSVE5BTUUgPSAweGYyLAo+ICsJT1BBTF9FTkROQU1FID0gMHhm MywKPiArCU9QQUxfQ0FMTCA9IDB4ZjgsCj4gKwlPUEFMX0VORE9GREFUQSA9IDB4ZjksCj4gKwlP UEFMX0VORE9GU0VTU0lPTiA9IDB4ZmEsCj4gKwlPUEFMX1NUQVJUVFJBTlNBQ1RPTiA9IDB4ZmIs Cj4gKwlPUEFMX0VORFRSQU5TQUNUT04gPSAweGZDLAo+ICsJT1BBTF9FTVBUWUFUT00gPSAweGZm LAo+ICsJT1BBTF9XSEVSRSA9IDB4MDAsCj4gK307Cj4gKwo+ICsvKiBVc2VmdWwgdGlueSBhdG9t cy4KPiArICogVXNlZnVsIGZvciB0YWJsZSBjb2x1bW5zIGV0Ywo+ICsgKi8KPiArZW51bSBPUEFM X1RJTllfQVRPTSB7Cj4gKwlPUEFMX1RJTllfVUlOVF8wMCA9IDB4MDAsCj4gKwlPUEFMX1RJTllf VUlOVF8wMSA9IDB4MDEsCj4gKwlPUEFMX1RJTllfVUlOVF8wMiA9IDB4MDIsCj4gKwlPUEFMX1RJ TllfVUlOVF8wMyA9IDB4MDMsCj4gKwlPUEFMX1RJTllfVUlOVF8wNCA9IDB4MDQsCj4gKwlPUEFM X1RJTllfVUlOVF8wNSA9IDB4MDUsCj4gKwlPUEFMX1RJTllfVUlOVF8wNiA9IDB4MDYsCj4gKwlP UEFMX1RJTllfVUlOVF8wNyA9IDB4MDcsCj4gKwlPUEFMX1RJTllfVUlOVF8wOCA9IDB4MDgsCj4g KwlPUEFMX1RJTllfVUlOVF8wOSA9IDB4MDksCj4gKwlPUEFMX1RJTllfVUlOVF8xMCA9IDB4MGEs Cj4gKwlPUEFMX1RJTllfVUlOVF8xMSA9IDB4MGIsCj4gKwlPUEFMX1RJTllfVUlOVF8xMiA9IDB4 MGMsCj4gKwlPUEFMX1RJTllfVUlOVF8xMyA9IDB4MGQsCj4gKwlPUEFMX1RJTllfVUlOVF8xNCA9 IDB4MGUsCj4gKwlPUEFMX1RJTllfVUlOVF8xNSA9IDB4MGYsCj4gK307Cj4gKwo+ICtlbnVtIE9Q QUxfQVRPTV9XSURUSCB7Cj4gKwlPUEFMX1dJRFRIX1RJTlksCj4gKwlPUEFMX1dJRFRIX1NIT1JU LAo+ICsJT1BBTF9XSURUSF9NRURJVU0sCj4gKwlPUEFMX1dJRFRIX0xPTkcsCj4gKwlPUEFMX1dJ RFRIX1RPS0VOCj4gK307Cj4gKwo+ICsvKiBMb2NraW5nIHN0YXRlIGZvciBhIGxvY2tpbmcgcmFu Z2UgKi8KPiArZW51bSBPUEFMX0xPQ0tJTkdTVEFURSB7Cj4gKwlPUEFMX0xPQ0tJTkdfUkVBRFdS SVRFID0gMHgwMSwKPiArCU9QQUxfTE9DS0lOR19SRUFET05MWSA9IDB4MDIsCj4gKwlPUEFMX0xP Q0tJTkdfTE9DS0VEID0gMHgwMywKPiArfTsKPiArCj4gKy8qCj4gKyAqIFN0cnVjdHVyZXMgdG8g YnVpbGQgYW5kIGRlY29kZSB0aGUgT3BhbCBTU0MgbWVzc2FnZXMKPiArICogZmllbGRzIHRoYXQg YXJlIE5PVCByZWFsbHkgbnVtZXJpYyBhcmUgZGVmaW5lZCBhcyB1OFtdIHRvCj4gKyAqIGhlbHAg cmVkdWNlIHRoZSBlbmRpYW5uZXNzIGlzc3Vlcwo+ICsgKi8KPiArCj4gKy8qIENvbW0gUGFja2V0 IChoZWFkZXIpIGZvciB0cmFuc21pc3Npb25zLiAqLwo+ICtzdHJ1Y3Qgb3BhbF9jb21wYWNrZXQg ewo+ICsJdTMyIHJlc2VydmVkMDsKPiArCXU4IGV4dGVuZGVkQ29tSURbNF07Cj4gKwl1MzIgb3V0 c3RhbmRpbmdEYXRhOwo+ICsJdTMyIG1pblRyYW5zZmVyOwo+ICsJdTMyIGxlbmd0aDsKPiArfTsK PiArCj4gKy8qIFBhY2tldCBzdHJ1Y3R1cmUuICovCj4gK3N0cnVjdCBvcGFsX3BhY2tldCB7Cj4g Kwl1MzIgVFNOOwo+ICsJdTMyIEhTTjsKPiArCXUzMiBzZXFfbnVtYmVyOwo+ICsJdTE2IHJlc2Vy dmVkMDsKPiArCXUxNiBhY2tfdHlwZTsKPiArCXUzMiBhY2tub3dsZWRnbWVudDsKPiArCXUzMiBs ZW5ndGg7Cj4gK307Cj4gKwo+ICsvKiBEYXRhIHN1YiBwYWNrZXQgaGVhZGVyICovCj4gK3N0cnVj dCBvcGFsX2RhdGFfc3VicGFja2V0IHsKPiArCXU4IHJlc2VydmVkMFs2XTsKPiArCXUxNiBraW5k Owo+ICsJdTMyIGxlbmd0aDsKPiArfTsKPiArCj4gKy8qIGhlYWRlciBvZiBhIHJlc3BvbnNlICov Cj4gK3N0cnVjdCBvcGFsX2hlYWRlciB7Cj4gKwlzdHJ1Y3Qgb3BhbF9jb21wYWNrZXQgY3A7Cj4g KwlzdHJ1Y3Qgb3BhbF9wYWNrZXQgcGt0Owo+ICsJc3RydWN0IG9wYWxfZGF0YV9zdWJwYWNrZXQg c3VicGt0Owo+ICt9Owo+ICsKPiArI2RlZmluZSBGQ19UUEVSICAgICAgIDB4MDAwMQo+ICsjZGVm aW5lIEZDX0xPQ0tJTkcgICAgMHgwMDAyCj4gKyNkZWZpbmUgRkNfR0VPTUVUUlkgICAweDAwMDMK PiArI2RlZmluZSBGQ19FTlRFUlBSSVNFIDB4MDEwMAo+ICsjZGVmaW5lIEZDX0RBVEFTVE9SRSAg MHgwMjAyCj4gKyNkZWZpbmUgRkNfU0lOR0xFVVNFUiAweDAyMDEKPiArI2RlZmluZSBGQ19PUEFM VjEwMCAgIDB4MDIwMAo+ICsjZGVmaW5lIEZDX09QQUxWMjAwICAgMHgwMjAzCj4gKwo+ICsvKgo+ ICsgKiBUaGUgRGlzY292ZXJ5IDAgSGVhZGVyLiBBcyBkZWZpbmVkIGluCj4gKyAqIE9wYWwgU1ND IERvY3VtZW50YXRpb24KPiArICovCj4gK3N0cnVjdCBkMF9oZWFkZXIgewo+ICsJdTMyIGxlbmd0 aDsgLyogdGhlIGxlbmd0aCBvZiB0aGUgaGVhZGVyIDQ4IGluIDIuMDAuMTAwICovCj4gKwl1MzIg cmV2aXNpb247IC8qKjwgcmV2aXNpb24gb2YgdGhlIGhlYWRlciAxIGluIDIuMDAuMTAwICovCj4g Kwl1MzIgcmVzZXJ2ZWQwMTsKPiArCXUzMiByZXNlcnZlZDAyOwo+ICsJLyoKPiArCSAqIHRoZSBy ZW1haW5kZXIgb2YgdGhlIHN0cnVjdHVyZSBpcyB2ZW5kb3Igc3BlY2lmaWMgYW5kIHdpbGwgbm90 IGJlCj4gKwkgKiBhZGRyZXNzZWQgbm93Cj4gKwkgKi8KPiArCXU4IGlnbm9yZWRbMzJdOwo+ICt9 Owo+ICsKPiArLyoKPiArICogVFBlciBGZWF0dXJlIERlc2NyaXB0b3IuIENvbnRhaW5zIGZsYWdz IGluZGljYXRpbmcgc3VwcG9ydCBmb3IgdGhlCj4gKyAqIFRQZXIgZmVhdHVyZXMgZGVzY3JpYmVk IGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRjaCB0aGUKPiArICogT1BB TCB0ZXJtaW5vbG9neQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDAxIGluIDIuMDAuMTAwCj4gKyAq Lwo+ICtzdHJ1Y3QgZDBfdHBlcl9mZWF0dXJlcyB7Cj4gKwkvKgo+ICsJICogc3VwcG9ydGVkX2Zl YXR1cmVzIGJpdHM6Cj4gKwkgKiBiaXQgNzogcmVzZXJ2ZWQKPiArCSAqIGJpdCA2OiBjb20gSUQg bWFuYWdlbWVudAo+ICsJICogYml0IDU6IHJlc2VydmVkCj4gKwkgKiBiaXQgNDogc3RyZWFtaW5n IHN1cHBvcnQKPiArCSAqIGJpdCAzOiBidWZmZXIgbWFuYWdlbWVudAo+ICsJICogYml0IDI6IEFD Sy9OQUNLCj4gKwkgKiBiaXQgMTogYXN5bmMKPiArCSAqIGJpdCAwOiBzeW5jCj4gKwkgKi8KPiAr CXU4IHN1cHBvcnRlZF9mZWF0dXJlczsKPiArCS8qCj4gKwkgKiBieXRlcyA1IHRocm91Z2ggMTUg YXJlIHJlc2VydmVkLCBidXQgd2UgcmVwcmVzZW50IHRoZSBmaXJzdCAzIGFzCj4gKwkgKiB1OCB0 byBrZWVwIHRoZSBvdGhlciB0d28gMzJiaXRzIGludGVnZXJzIGFsaWduZWQuCj4gKwkgKi8KPiAr CXU4IHJlc2VydmVkMDFbM107Cj4gKwl1MzIgcmVzZXJ2ZWQwMjsKPiArCXUzMiByZXNlcnZlZDAz Owo+ICt9Owo+ICsKPiArLyoKPiArICogTG9ja2luZyBGZWF0dXJlIERlc2NyaXB0b3IuIENvbnRh aW5zIGZsYWdzIGluZGljYXRpbmcgc3VwcG9ydCBmb3IgdGhlCj4gKyAqIGxvY2tpbmcgZmVhdHVy ZXMgZGVzY3JpYmVkIGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRjaCB0 aGUKPiArICogT1BBTCB0ZXJtaW5vbG9neQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDAwMiBpbiAy LjAwLjEwMAo+ICsgKi8KPiArc3RydWN0IGQwX2xvY2tpbmdfZmVhdHVyZXMgewo+ICsJLyoKPiAr CSAqIHN1cHBvcnRlZF9mZWF0dXJlcyBiaXRzOgo+ICsJICogYml0cyA2LTc6IHJlc2VydmVkCj4g KwkgKiBiaXQgNTogTUJSIGRvbmUKPiArCSAqIGJpdCA0OiBNQlIgZW5hYmxlZAo+ICsJICogYml0 IDM6IG1lZGlhIGVuY3J5cHRpb24KPiArCSAqIGJpdCAyOiBsb2NrZWQKPiArCSAqIGJpdCAxOiBs b2NraW5nIGVuYWJsZWQKPiArCSAqIGJpdCAwOiBsb2NraW5nIHN1cHBvcnRlZAo+ICsJICovCj4g Kwl1OCBzdXBwb3J0ZWRfZmVhdHVyZXM7Cj4gKwkvKgo+ICsJICogYnl0ZXMgNSB0aHJvdWdoIDE1 IGFyZSByZXNlcnZlZCwgYnV0IHdlIHJlcHJlc2VudCB0aGUgZmlyc3QgMyBhcwo+ICsJICogdTgg dG8ga2VlcCB0aGUgb3RoZXIgdHdvIDMyYml0cyBpbnRlZ2VycyBhbGlnbmVkLgo+ICsJICovCj4g Kwl1OCByZXNlcnZlZDAxWzNdOwo+ICsJdTMyIHJlc2VydmVkMDI7Cj4gKwl1MzIgcmVzZXJ2ZWQw MzsKPiArfTsKPiArCj4gKy8qCj4gKyAqIEdlb21ldHJ5IEZlYXR1cmUgRGVzY3JpcHRvci4gQ29u dGFpbnMgZmxhZ3MgaW5kaWNhdGluZyBzdXBwb3J0IGZvciB0aGUKPiArICogZ2VvbWV0cnkgZmVh dHVyZXMgZGVzY3JpYmVkIGluIHRoZSBPUEFMIHNwZWNpZmljYXRpb24uIFRoZSBuYW1lcyBtYXRj aCB0aGUKPiArICogT1BBTCB0ZXJtaW5vbG9neQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDAwMyBp biAyLjAwLjEwMAo+ICsgKi8KPiArc3RydWN0IGQwX2dlb21ldHJ5X2ZlYXR1cmVzIHsKPiArCS8q Cj4gKwkgKiBza2lwIDMyIGJpdHMgZnJvbSBoZWFkZXIsIG5lZWRlZCB0byBhbGlnbiB0aGUgc3Ry dWN0IHRvIDY0IGJpdHMuCj4gKwkgKi8KPiArCXU4IGhlYWRlcls0XTsKPiArCS8qCj4gKwkgKiBy ZXNlcnZlZDAxOgo+ICsJICogYml0cyAxLTY6IHJlc2VydmVkCj4gKwkgKiBiaXQgMDogYWxpZ24K PiArCSAqLwo+ICsJdTggcmVzZXJ2ZWQwMTsKPiArCXU4IHJlc2VydmVkMDJbN107Cj4gKwl1MzIg bG9naWNhbF9ibG9ja19zaXplOwo+ICsJdTY0IGFsaWdubWVudF9ncmFudWxhcml0eTsKPiArCXU2 NCBsb3dlc3RfYWxpZ25lZF9sYmE7Cj4gK307Cj4gKwo+ICsvKgo+ICsgKiBFbnRlcnByaXNlIFNT QyBGZWF0dXJlCj4gKyAqCj4gKyAqIGNvZGUgPT0gMHgwMTAwCj4gKyAqLwo+ICtzdHJ1Y3QgZDBf ZW50ZXJwcmlzZV9zc2Mgewo+ICsJdTE2IGJhc2VDb21JRDsKPiArCXUxNiBudW1Db21JRHM7Cj4g KwkvKiByYW5nZV9jcm9zc2luZzoKPiArCSAqIGJpdHMgMS02OiByZXNlcnZlZAo+ICsJICogYml0 IDA6IHJhbmdlIGNyb3NzaW5nCj4gKwkgKi8KPiArCXU4IHJhbmdlX2Nyb3NzaW5nOwo+ICsJdTgg cmVzZXJ2ZWQwMTsKPiArCXUxNiByZXNlcnZlZDAyOwo+ICsJdTMyIHJlc2VydmVkMDM7Cj4gKwl1 MzIgcmVzZXJ2ZWQwNDsKPiArfTsKPiArCj4gKy8qCj4gKyAqIE9wYWwgVjEgZmVhdHVyZQo+ICsg Kgo+ICsgKiBjb2RlID09IDB4MDIwMAo+ICsgKi8KPiArc3RydWN0IGQwX29wYWxfdjEwMCB7Cj4g Kwl1MTYgYmFzZUNvbUlEOwo+ICsJdTE2IG51bUNvbUlEczsKPiArfTsKPiArCj4gKy8qCj4gKyAq IFNpbmdsZSBVc2VyIE1vZGUgZmVhdHVyZQo+ICsgKgo+ICsgKiBjb2RlID09IDB4MDIwMQo+ICsg Ki8KPiArc3RydWN0IGQwX3NpbmdsZV91c2VyX21vZGUgewo+ICsJdTMyIG51bV9sb2NraW5nX29i amVjdHM7Cj4gKwkvKiByZXNlcnZlZDAxOgo+ICsJICogYml0IDA6IGFueQo+ICsJICogYml0IDE6 IGFsbAo+ICsJICogYml0IDI6IHBvbGljeQo+ICsJICogYml0cyAzLTc6IHJlc2VydmVkCj4gKwkg Ki8KPiArCXU4IHJlc2VydmVkMDE7Cj4gKwl1OCByZXNlcnZlZDAyOwo+ICsJdTE2IHJlc2VydmVk MDM7Cj4gKwl1MzIgcmVzZXJ2ZWQwNDsKPiArfTsKPiArCj4gKy8qCj4gKyAqIEFkZGl0b25hbCBE YXRhc3RvcmVzIGZlYXR1cmUKPiArICoKPiArICogY29kZSA9PSAweDAyMDIKPiArICovCj4gK3N0 cnVjdCBkMF9kYXRhc3RvcmVfdGFibGUgewo+ICsJdTE2IHJlc2VydmVkMDE7Cj4gKwl1MTYgbWF4 X3RhYmxlczsKPiArCXUzMiBtYXhfc2l6ZV90YWJsZXM7Cj4gKwl1MzIgdGFibGVfc2l6ZV9hbGln bm1lbnQ7Cj4gK307Cj4gKwo+ICsvKgo+ICsgKiBPUEFMIDIuMCBmZWF0dXJlCj4gKyAqCj4gKyAq IGNvZGUgPT0gMHgwMjAzCj4gKyAqLwo+ICtzdHJ1Y3QgZDBfb3BhbF92MjAwIHsKPiArCXUxNiBi YXNlQ29tSUQ7Cj4gKwl1MTYgbnVtQ29tSURzOwo+ICsJLyogcmFuZ2VfY3Jvc3Npbmc6Cj4gKwkg KiBiaXRzIDEtNjogcmVzZXJ2ZWQKPiArCSAqIGJpdCAwOiByYW5nZSBjcm9zc2luZwo+ICsJICov Cj4gKwl1OCByYW5nZV9jcm9zc2luZzsKPiArCS8qIG51bV9sb2NraW5nX2FkbWluX2F1dGg6Cj4g KwkgKiBub3QgYWxpZ25lZCB0byAxNiBiaXRzLCBzbyB1c2UgdHdvIHU4Lgo+ICsJICogc3RvcmVk IGluIGJpZyBlbmRpYW46Cj4gKwkgKiAwOiBNU0IKPiArCSAqIDE6IExTQgo+ICsJICovCj4gKwl1 OCBudW1fbG9ja2luZ19hZG1pbl9hdXRoWzJdOwo+ICsJLyogbnVtX2xvY2tpbmdfdXNlcl9hdXRo Ogo+ICsJICogbm90IGFsaWduZWQgdG8gMTYgYml0cywgc28gdXNlIHR3byB1OC4KPiArCSAqIHN0 b3JlZCBpbiBiaWcgZW5kaWFuOgo+ICsJICogMDogTVNCCj4gKwkgKiAxOiBMU0IKPiArCSAqLwo+ ICsJdTggbnVtX2xvY2tpbmdfdXNlcl9hdXRoWzJdOwo+ICsJdTggaW5pdGlhbFBJTjsKPiArCXU4 IHJldmVydGVkUElOOwo+ICsJdTggcmVzZXJ2ZWQwMTsKPiArCXUzMiByZXNlcnZlZDAyOwo+ICt9 Owo+ICsKPiArLyogVW5pb24gb2YgZmVhdHVyZXMgdXNlZCB0byBwYXJzZSB0aGUgZGlzY292ZXJ5 IDAgcmVzcG9uc2UgKi8KPiArc3RydWN0IGQwX2ZlYXR1cmVzIHsKPiArCXUxNiBjb2RlOwo+ICsJ LyoKPiArCSAqIHJfdmVyc2lvbiBiaXRzOgo+ICsJICogYml0cyA0LTc6IHZlcnNpb24KPiArCSAq IGJpdHMgMC0zOiByZXNlcnZlZAo+ICsJICovCj4gKwl1OCByX3ZlcnNpb247Cj4gKwl1OCBsZW5n dGg7Cj4gKwl1OCBmZWF0dXJlc1tdOwo+ICt9Owo+ICsKPiArc3RydWN0IGtleSAqcmVxdWVzdF91 c2VyX2tleShjb25zdCBjaGFyICptYXN0ZXJfZGVzYywgY29uc3QgdTggKiptYXN0ZXJfa2V5LAo+ ICsJCQkgICAgIHNpemVfdCAqbWFzdGVyX2tleWxlbik7Cj4gKwo+ICsjZW5kaWYgLyogX05WTUVf T1BBTF9JTlRFUk5BTF9IICovCj4gZGlmZiAtLWdpdCBhL2xpYi9zZWQtb3BhbF9rZXkuYyBiL2xp Yi9zZWQtb3BhbF9rZXkuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4u MGI0ZGUwMQo+IC0tLSAvZGV2L251bGwKPiArKysgYi9saWIvc2VkLW9wYWxfa2V5LmMKPiBAQCAt MCwwICsxLDQ2IEBACj4gKy8qCj4gKyAqIENvcHlyaWdodCDCqSAyMDE2IEludGVsIENvcnBvcmF0 aW9uCj4gKyAqCj4gKyAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hh cmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhCj4gKyAqIGNvcHkgb2YgdGhpcyBzb2Z0d2Fy ZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksCj4g KyAqIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGlu ZyB3aXRob3V0IGxpbWl0YXRpb24KPiArICogdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlm eSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsCj4gKyAqIGFuZC9vciBz ZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9t IHRoZQo+ICsgKiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhl IGZvbGxvd2luZyBjb25kaXRpb25zOgo+ICsgKgo+ICsgKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5v dGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSAoaW5jbHVkaW5nIHRoZSBuZXh0Cj4gKyAq IHBhcmFncmFwaCkgc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlh bCBwb3J0aW9ucyBvZiB0aGUKPiArICogU29mdHdhcmUuCj4gKyAqCj4gKyAqIFRIRSBTT0ZUV0FS RSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBS RVNTIE9SCj4gKyAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdB UlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAo+ICsgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VM QVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiAgSU4gTk8gRVZFTlQgU0hBTEwKPiArICog VEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0s IERBTUFHRVMgT1IgT1RIRVIKPiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBP RiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcKPiArICogRlJPTSwgT1VUIE9G IE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBE RUFMSU5HUwo+ICsgKiBJTiBUSEUgU09GVFdBUkUuCj4gKyAqCj4gKyAqIEF1dGhvcjoKPiArICog ICAgUmFmYWVsIEFudG9nbm9sbGkgPHJhZmFlbC5hbnRvZ25vbGxpQGludGVsLmNvbT4KPiArICov Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgva2V5Lmg+Cj4gKyNpbmNsdWRlICJzZWQtb3BhbF9pbnRl cm5hbC5oIgo+ICsKPiArc3RydWN0IGtleSAqcmVxdWVzdF91c2VyX2tleShjb25zdCBjaGFyICpt YXN0ZXJfZGVzYywgY29uc3QgdTggKiptYXN0ZXJfa2V5LAo+ICsJCQkgICAgIHNpemVfdCAqbWFz dGVyX2tleWxlbikKPiArewo+ICsJY29uc3Qgc3RydWN0IHVzZXJfa2V5X3BheWxvYWQgKnVwYXls b2FkOwo+ICsJc3RydWN0IGtleSAqdWtleTsKPiArCj4gKwl1a2V5ID0gcmVxdWVzdF9rZXkoJmtl eV90eXBlX3VzZXIsIG1hc3Rlcl9kZXNjLCBOVUxMKTsKPiArCWlmIChJU19FUlIodWtleSkpCj4g KwkJZ290byBlcnJvcjsKPiArCj4gKwlkb3duX3JlYWQoJnVrZXktPnNlbSk7Cj4gKwl1cGF5bG9h ZCA9IHVzZXJfa2V5X3BheWxvYWQodWtleSk7Cj4gKwkqbWFzdGVyX2tleSA9IHVwYXlsb2FkLT5k YXRhOwo+ICsJKm1hc3Rlcl9rZXlsZW4gPSB1cGF5bG9hZC0+ZGF0YWxlbjsKPiArZXJyb3I6Cj4g KwlyZXR1cm4gdWtleTsKPiArfQo+IGRpZmYgLS1naXQgYS9saWIvc2VkLmMgYi9saWIvc2VkLmMK PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLjA2Y2FjZDkKPiAtLS0gL2Rl di9udWxsCj4gKysrIGIvbGliL3NlZC5jCj4gQEAgLTAsMCArMSwzMDMgQEAKPiArI2luY2x1ZGUg PGxpbnV4L2Jsa2Rldi5oPgo+ICsjaW5jbHVkZSA8bGludXgvc2VkLmg+Cj4gKyNpbmNsdWRlIDxs aW51eC9zZWQtb3BhbC5oPgo+ICsKPiArI2lmbmRlZiBDT05GSUdfU0VEX09QQUwKPiArc3RhdGlj IGludCBzZWRfb3BhbF9zYXZlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf a2V5ICpzZWQpCj4gKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9v cGFsX2xvY2tfdW5sb2NrKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5 ICprZXkpCj4gKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9vcGFs X3Rha2Vfb3duZXJzaGlwKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5 ICprZXkpCj4gKwl7IHJldHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9vcGFs X2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAq a2V5KQo+ICsJeyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KPiArc3RhdGljIGludCBzZWRfb3BhbF9z ZXRfcHcoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiAr CXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9Cj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfYWN0aXZhdGVf dXNlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICsJ eyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KPiArc3RhdGljIGludCBzZWRfb3BhbF9yZXZlcnR0cGVy KHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gKwl7IHJl dHVybiAtRU9QTk9UU1VQUDsgfQo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3NldHVwX2xvY2tpbmdf cmFuZ2Uoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiAr CXsgcmV0dXJuIC1FT1BOT1RTVVBQOyB9Cj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfYWRkdXNlcl90 b19scihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICsJ eyByZXR1cm4gLUVPUE5PVFNVUFA7IH0KPiArc3RhdGljIGludCBzZWRfb3BhbF9kb19tYnIoc3Ry dWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArCXsgcmV0dXJu IC1FT1BOT1RTVVBQOyB9Cj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfZXJhc2VfbHIoc3RydWN0IGJs b2NrX2RldmljZSAqYmRldiwgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArCXsgcmV0dXJuIC1FT1BO T1RTVVBQOyB9Cj4gKwo+ICsjZWxzZQo+ICsKPiArc3RhdGljIGludCBzZWRfb3BhbF9zYXZlKHN0 cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sKPiArCj4g KwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwK PiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5P VFNVUFA7CllvdSBtaWdodCBjb25zaWRlciBwdWxsaW5nIHRoaXMgYm9pbGVycGxhdGUgb3V0IGlu dG8gc29tZXRoaW5nIGxpa2U6CnN0YXRpYyBpbmxpbmUgYm9vbCBiZGV2X3NlY19jYXBhYmxlKHN0 cnVjdCBibG9ja19kZXZpY2UgKmJkZXYpCnsKCXJldHVybiBiZGV2ICYmIGJkZXYtPmJkX2Rpc2sg JiYgYmRldi0+YmRfZGlzay0+Zm9wcyAmJgoJICAgICAgIGJkZXYtPmJkX2Rpc2stPmZvcHMtPnNl Y19vcHM7Cn0KCgo+ICsKPiArCXJldHVybiBvcGFsX3NhdmUoYmRldiwga2V5KTsKPiArfQo+ICsK PiArc3RhdGljIGludCBzZWRfb3BhbF9sb2NrX3VubG9jayhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpi ZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2 LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rp c2stPmZvcHMtPnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXJldHVy biBvcGFsX2xvY2tfdW5sb2NrKGJkZXYsIGtleSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgc2Vk X29wYWxfdGFrZV9vd25lcnNoaXAoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKPiArCQkJCSAg IHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sKPiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJk X2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+ Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9w YWxfdGFrZV9vd25lcnNoaXAoYmRldiwga2V5KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzZWRf b3BhbF9hY3RpdmF0ZV9sc3Aoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwKPiArCQkJCSBzdHJ1 Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNr IHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMt PnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXJldHVybiBvcGFsX2Fj dGl2YXRlX2xzcChiZGV2LCBrZXkpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3Nl dF9wdyhzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LAo+ICsJCQkgICBzdHJ1Y3Qgc2VkX2tleSAq a2V5KQo+ICt7Cj4gKwo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5i ZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCj4g KwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXJldHVybiBvcGFsX3NldF9uZXdfcHcoYmRl diwga2V5KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBzZWRfb3BhbF9hY3RpdmF0ZV91c2VyKHN0 cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsCj4gKwkJCQkgIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4g K3sKPiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2st PmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1 cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfYWN0aXZhdGVfdXNlcihiZGV2LCBr ZXkpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3JldmVydHRwZXIoc3RydWN0IGJs b2NrX2RldmljZSAqYmRldiwKPiArCQkJICAgICAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sK PiArCj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZv cHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4g LUVPUE5PVFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfcmV2ZXJ0dHBlcihiZGV2LCBrZXkpOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHNlZF9vcGFsX3NldHVwX2xyKHN0cnVjdCBibG9ja19kZXZp Y2UgKmJkZXYsCj4gKwkJCSAgICAgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsKPiArCWlm ICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAo+ICsJ ICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ICsJCXJldHVybiAtRU9QTk9UU1VQ UDsKPiArCj4gKwlyZXR1cm4gb3BhbF9zZXR1cF9sb2NraW5nX3JhbmdlKGJkZXYsIGtleSk7Cj4g K30KPiArCj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfYWRkdXNlcl90b19scihzdHJ1Y3QgYmxvY2tf ZGV2aWNlICpiZGV2LAo+ICsJCQkgICAgIHN0cnVjdCBzZWRfa2V5ICprZXkpCj4gK3sKPiArCj4g KwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwK PiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5P VFNVUFA7Cj4gKwo+ICsJcmV0dXJuIG9wYWxfYWRkX3VzZXJfdG9fbHIoYmRldiwga2V5KTsKPiAr fQo+ICsKPiArc3RhdGljIGludCBzZWRfb3BhbF9kb19tYnIoc3RydWN0IGJsb2NrX2RldmljZSAq YmRldiwKPiArCQkJICAgc3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsKPiArCWlmICghYmRl diB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFi ZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiAr Cj4gKwlyZXR1cm4gb3BhbF9lbmFibGVfZGlzYWJsZV9zaGFkb3dfbWJyKGJkZXYsIGtleSk7Cj4g K30KPiArCj4gK3N0YXRpYyBpbnQgc2VkX29wYWxfZXJhc2VfbHIoc3RydWN0IGJsb2NrX2Rldmlj ZSAqYmRldiwKPiArCQkJICAgICBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwo+ICsJaWYg KCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkg ICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQ Owo+ICsKPiArCXJldHVybiBvcGFsX2VyYXNlX2xvY2tpbmdfcmFuZ2UoYmRldiwga2V5KTsKPiAr fQo+ICsjZW5kaWYKPiArCj4gK2ludCBzZWRfc2F2ZShzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2 LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rp c2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9w cy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChrZXkt PnNlZF90eXBlKSB7Cj4gKwljYXNlIE9QQUxfTE9DS19VTkxPQ0s6Cj4gKwkJcmV0dXJuIHNlZF9v cGFsX3NhdmUoYmRldiwga2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4g K30KPiArCj4gK2ludCBzZWRfbG9ja191bmxvY2soc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwg c3RydWN0IHNlZF9rZXkgKmtleSkKPiArewo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNr IHx8ICFiZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMt PnNlY19vcHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXN3aXRjaCAoa2V5LT5z ZWRfdHlwZSkgewo+ICsJY2FzZSBPUEFMX0xPQ0tfVU5MT0NLOgo+ICsJCXJldHVybiBzZWRfb3Bh bF9sb2NrX3VubG9jayhiZGV2LCBrZXkpOwo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQ UDsKPiArfQo+ICsKPiAraW50IHNlZF90YWtlX293bmVyc2hpcChzdHJ1Y3QgYmxvY2tfZGV2aWNl ICpiZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYt PmJkX2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlz ay0+Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNo IChrZXktPnNlZF90eXBlKSB7Cj4gKwljYXNlIE9QQUw6Cj4gKwkJcmV0dXJuIHNlZF9vcGFsX3Rh a2Vfb3duZXJzaGlwKGJkZXYsIGtleSk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIC1FT1BOT1RTVVBQ Owo+ICt9Cj4gKwo+ICtpbnQgc2VkX2FjdGl2YXRlX2xzcChzdHJ1Y3QgYmxvY2tfZGV2aWNlICpi ZGV2LCBzdHJ1Y3Qgc2VkX2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJk X2Rpc2sgfHwgIWJkZXYtPmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+ Zm9wcy0+c2VjX29wcykKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChr ZXktPnNlZF90eXBlKSB7Cj4gKwljYXNlIE9QQUw6Cj4gKwkJcmV0dXJuIHNlZF9vcGFsX2FjdGl2 YXRlX2xzcChiZGV2LCBrZXkpOwo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQUDsKPiAr fQo+ICsKPiAraW50IHNlZF9zZXRfcHcoc3RydWN0IGJsb2NrX2RldmljZSAqYmRldiwgc3RydWN0 IHNlZF9rZXkgKmtleSkKPiArewo+ICsJaWYgKCFiZGV2IHx8ICFiZGV2LT5iZF9kaXNrIHx8ICFi ZGV2LT5iZF9kaXNrLT5mb3BzIHx8Cj4gKwkgICAgIWJkZXYtPmJkX2Rpc2stPmZvcHMtPnNlY19v cHMpCj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsKPiArCXN3aXRjaCAoa2V5LT5zZWRfdHlw ZSkgewo+ICsJY2FzZSBPUEFMX1BXOgo+ICsJCXJldHVybiBzZWRfb3BhbF9zZXRfcHcoYmRldiwg a2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30KPiArCj4gK2ludCBz ZWRfYWN0aXZhdGVfdXNlcihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2VkX2tl eSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYtPmJk X2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykKPiAr CQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7Cj4g KwljYXNlIE9QQUxfQUNUX1VTUjoKPiArCQlyZXR1cm4gc2VkX29wYWxfYWN0aXZhdGVfdXNlcihi ZGV2LCBrZXkpOwo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQUDsKPiArfQo+ICsKPiAr aW50IHNlZF9yZXZlcnR0cGVyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf a2V5ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+ YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsK PiArCWNhc2UgT1BBTDoKPiArCQlyZXR1cm4gc2VkX29wYWxfcmV2ZXJ0dHBlcihiZGV2LCBrZXkp Owo+ICsJfQo+ICsKPiArCXJldHVybiAtRU9QTk9UU1VQUDsKPiArfQo+ICsKPiAraW50IHNlZF9z ZXR1cF9sb2NraW5nX3JhbmdlKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRf a2V5ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+ YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsK PiArCWNhc2UgT1BBTF9MUl9TRVRVUDoKPiArCQlyZXR1cm4gc2VkX29wYWxfc2V0dXBfbHIoYmRl diwga2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30KPiArCj4gK2lu dCBzZWRfYWRkdXNlcl90b19scihzdHJ1Y3QgYmxvY2tfZGV2aWNlICpiZGV2LCBzdHJ1Y3Qgc2Vk X2tleSAqa2V5KQo+ICt7Cj4gKwlpZiAoIWJkZXYgfHwgIWJkZXYtPmJkX2Rpc2sgfHwgIWJkZXYt PmJkX2Rpc2stPmZvcHMgfHwKPiArCSAgICAhYmRldi0+YmRfZGlzay0+Zm9wcy0+c2VjX29wcykK PiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwo+ICsJc3dpdGNoIChrZXktPnNlZF90eXBlKSB7 Cj4gKwljYXNlIE9QQUxfTE9DS19VTkxPQ0s6Cj4gKwkJcmV0dXJuIHNlZF9vcGFsX2FkZHVzZXJf dG9fbHIoYmRldiwga2V5KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30K PiArCj4gK2ludCBzZWRfZG9fbWJyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBz ZWRfa2V5ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRl di0+YmRfZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3Bz KQo+ICsJCXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUp IHsKPiArCWNhc2UgT1BBTF9NQlJfREFUQToKPiArCQlyZXR1cm4gc2VkX29wYWxfZG9fbWJyKGJk ZXYsIGtleSk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICt9Cj4gKwo+ICtp bnQgc2VkX2VyYXNlX2xyKHN0cnVjdCBibG9ja19kZXZpY2UgKmJkZXYsIHN0cnVjdCBzZWRfa2V5 ICprZXkpCj4gK3sKPiArCWlmICghYmRldiB8fCAhYmRldi0+YmRfZGlzayB8fCAhYmRldi0+YmRf ZGlzay0+Zm9wcyB8fAo+ICsJICAgICFiZGV2LT5iZF9kaXNrLT5mb3BzLT5zZWNfb3BzKQo+ICsJ CXJldHVybiAtRU9QTk9UU1VQUDsKPiArCj4gKwlzd2l0Y2ggKGtleS0+c2VkX3R5cGUpIHsKPiAr CWNhc2UgT1BBTDoKPiArCQlyZXR1cm4gc2VkX29wYWxfZXJhc2VfbHIoYmRldiwga2V5KTsKPiAr CX0KPiArCj4gKwlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gK30KPiAtLSAKPiAyLjcuNAo+IAoKX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGludXgtbnZtZSBt YWlsaW5nIGxpc3QKTGludXgtbnZtZUBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5p bmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtbnZtZQo= ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 2/6] lib: Add Sed-opal library @ 2016-11-01 18:56 ` Jon Derrick 0 siblings, 0 replies; 32+ messages in thread From: Jon Derrick @ 2016-11-01 18:56 UTC (permalink / raw) Hi Rafael, Scott, First off, congrats on the set! It looks good so far. Just some small nits below since you have to respin it anyways :) On Mon, Oct 31, 2016@03:58:15PM -0600, Scott Bauer wrote: > This patch implements the necessary logic to bring an Opal > enabled drive out of a factory-enabled into a working > Opal state. > > This patch set also enables logic to save a password to > be replayed during a resume from suspend. The key can be > saved in the driver or in the Kernel's Key managment. > > Signed-off-by: Scott Bauer <scott.bauer at intel.com> > Signed-off-by: Rafael Antognolli <Rafael.Antognolli at intel.com> > --- > lib/sed-opal.c | 3337 +++++++++++++++++++++++++++++++++++++++++++++++ > lib/sed-opal_internal.h | 586 +++++++++ > lib/sed-opal_key.c | 46 + > lib/sed.c | 303 +++++ > 4 files changed, 4272 insertions(+) > create mode 100644 lib/sed-opal.c > create mode 100644 lib/sed-opal_internal.h > create mode 100644 lib/sed-opal_key.c > create mode 100644 lib/sed.c > > diff --git a/lib/sed-opal.c b/lib/sed-opal.c > new file mode 100644 > index 0000000..10b3348 > --- /dev/null > +++ b/lib/sed-opal.c > @@ -0,0 +1,3337 @@ > +/* > + * Copyright ? 2016 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + * > + * Authors: > + * Rafael Antognolli <rafael.antognolli at intel.com> > + * Scott Bauer <scott.bauer at intel.com> > + */ > + > +#define pr_fmt(fmt) KBUILD_MODNAME ":OPAL: " fmt > + > +#include <linux/delay.h> > +#include <linux/device.h> > +#include <linux/kernel.h> > +#include <linux/list.h> > +#include <linux/genhd.h> > +#include <linux/slab.h> > +#include <linux/uaccess.h> > +#include <uapi/linux/sed-opal.h> > +#include <linux/sed.h> > +#include <linux/sed-opal.h> > +#include <linux/string.h> > + > +#include "sed-opal_internal.h" > + > +#define IO_BUFFER_LENGTH 2048 > + > +#define MAX_TOKS 64 > + > +struct opal_cmd { > + struct block_device *bdev; > + sec_cb *cb; > + void *cb_data; > + > + size_t pos; > + u8 cmd_buf[IO_BUFFER_LENGTH * 2]; > + u8 resp_buf[IO_BUFFER_LENGTH * 2]; > + u8 *cmd; > + u8 *resp; > +}; > + > +/* > + * On the parsed response, we don't store again the toks that are already > + * stored in the response buffer. Instead, for each token, we just store a > + * pointer to the position in the buffer where the token starts, and the size > + * of the token in bytes. > + */ > +struct opal_resp_tok { > + const u8 *pos; > + size_t len; > + enum OPAL_RESPONSE_TOKEN type; > + enum OPAL_ATOM_WIDTH width; > + union { > + u64 u; > + s64 s; > + } stored; > +}; > + > +/* > + * From the response header it's not possible to know how many tokens there are > + * on the payload. So we hardcode that the maximum will be MAX_TOKS, and later > + * if we start dealing with messages that have more than that, we can increase > + * this number. This is done to avoid having to make two passes through the > + * response, the first one counting how many tokens we have and the second one > + * actually storing the positions. > + */ > +struct parsed_resp { > + int num; > + struct opal_resp_tok toks[MAX_TOKS]; > +}; > + > +struct opal_dev; > + > +typedef void (*opal_cb)(int error, struct opal_dev *dev); > + > +typedef int (*opal_step)(struct opal_dev *dev); > + > +struct opal_completion { > + struct completion cmd_completion; > + int completion_status; > +}; > + > +struct opal_dev { > + struct block_device *bdev; > + struct opal_completion *completion; > + struct opal_lock_unlock lkul; > + const opal_step *funcs; > + void **func_data; > + bool resume_from_suspend; > + struct opal_suspend_unlk *resume_data; > + size_t num_func_data; > + atomic_t in_use; > + sector_t start; > + sector_t length; > + u8 lr; > + u8 key_type; > + u8 key_name[OPAL_KEY_MAX]; > + size_t key_name_len; > + u8 key[OPAL_KEY_MAX]; > + size_t key_len; > + u16 comID; > + u32 HSN; > + u32 TSN; > + u64 align; > + u64 lowest_lba; > + struct list_head node; > + char disk_name[DISK_NAME_LEN]; > + int state; > + > + struct opal_cmd cmd; > + struct parsed_resp parsed; > + > + size_t prev_d_len; > + void *prev_data; > + > + sec_cb *final_cb; > + void *final_cb_data; > + opal_step error_cb; > + void *error_cb_data; > + opal_cb oper_cb; > +}; > + > +LIST_HEAD(opal_list); > +DEFINE_SPINLOCK(list_spinlock); > + > +static void print_buffer(const u8 *ptr, u32 length) > +{ > +#ifdef DEBUG > + print_hex_dump_bytes("OPAL: ", DUMP_PREFIX_OFFSET, ptr, length); > + pr_debug("\n"); > +#endif > +} > + > +#define TPER_SYNC_SUPPORTED BIT(0) > + > +static bool check_tper(const void *data) > +{ > + const struct d0_tper_features *tper = data; > + u8 flags = tper->supported_features; > + > + if (!(flags & TPER_SYNC_SUPPORTED)) { > + pr_err("TPer sync not supported. flags = %d\n", > + tper->supported_features); > + return false; > + } > + > + return true; > +} > + > +static bool check_SUM(const void *data) > +{ > + const struct d0_single_user_mode *sum = data; > + u32 nlo = be32_to_cpu(sum->num_locking_objects); > + > + if (nlo == 0) { > + pr_err("Need at least one locking object.\n"); > + return false; > + } > + > + pr_debug("Number of locking objects: %d\n", nlo); > + > + return true; > +} > + > +static u16 get_comID_v100(const void *data) > +{ > + const struct d0_opal_v100 *v100 = data; > + > + return be16_to_cpu(v100->baseComID); > +} > + > +static u16 get_comID_v200(const void *data) > +{ > + const struct d0_opal_v200 *v200 = data; > + > + return be16_to_cpu(v200->baseComID); > +} > + > +static int __opal_send_cmd(struct opal_suspend_unlk *data, u16 comID, > + void *buffer, size_t buflen, sec_cb *cb, > + void *cb_data) > +{ > + return data->ops.send(data->data, comID, TCG_SECP_01, buffer, buflen, > + cb, cb_data); > +} > +static int _opal_send_cmd(struct block_device *bdev, u16 comID, > + void *buffer, size_t buflen, > + sec_cb *cb, void *cb_data) > +{ > + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; > + > + return ops->send(bdev->bd_disk->private_data, comID, > + TCG_SECP_01, buffer, buflen, > + cb, cb_data); > +} > + > +static int __opal_recv_cmd(struct opal_suspend_unlk *data, u16 comID, > + void *buffer, size_t buflen, sec_cb *cb, > + void *cb_data) > +{ > + return data->ops.recv(data->data, comID, TCG_SECP_01, buffer, buflen, > + cb, cb_data); > +} > + > +static int _opal_recv_cmd(struct block_device *bdev, u16 comID, > + void *buffer, size_t buflen, > + sec_cb *cb, void *cb_data) > +{ > + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; > + > + return ops->recv(bdev->bd_disk->private_data, comID, > + TCG_SECP_01, buffer, buflen, > + cb, cb_data); > +} > + > +static void opal_send_cb_cont(int error, void *data) > +{ > + struct opal_dev *dev = data; > + size_t buflen = IO_BUFFER_LENGTH; > + void *buffer = dev->cmd.resp; > + struct opal_header *hdr = buffer; > + > + pr_debug("%s: Sent OPAL command: error=%d, outstanding=%d, minTransfer=%d\n", > + dev->disk_name, error, hdr->cp.outstandingData, > + hdr->cp.minTransfer); > + > + if (error || hdr->cp.outstandingData == 0 || > + hdr->cp.minTransfer != 0) { > + if (dev->cmd.cb) > + dev->cmd.cb(error, dev->cmd.cb_data); > + return; > + } > + > + memset(buffer, 0, buflen); > + if (dev->resume_from_suspend) > + __opal_recv_cmd(dev->resume_data, dev->comID, > + buffer, buflen, opal_send_cb_cont, dev); > + else > + _opal_recv_cmd(dev->bdev, dev->comID, buffer, buflen, > + opal_send_cb_cont, dev); > +} > + > +static void opal_send_cb(int error, void *data) > +{ > + struct opal_dev *dev = data; > + size_t buflen = IO_BUFFER_LENGTH; > + void *buffer = dev->cmd.resp; > + > + if (error) { > + if (dev->cmd.cb) > + dev->cmd.cb(error, dev->cmd.cb_data); > + return; > + } > + > + memset(buffer, 0, buflen); > + if (dev->resume_from_suspend) > + __opal_recv_cmd(dev->resume_data, dev->comID, > + buffer, buflen, opal_send_cb_cont, dev); > + else > + _opal_recv_cmd(dev->bdev, dev->comID, buffer, buflen, > + opal_send_cb_cont, dev); > +} > + > +static int opal_send_recv(struct opal_dev *dev, sec_cb *cb, void *cb_data) > +{ > + size_t buflen = IO_BUFFER_LENGTH; > + void *buffer = dev->cmd.cmd; > + int ret; > + > + dev->cmd.cb = cb; > + dev->cmd.cb_data = cb_data; > + if (dev->resume_from_suspend) > + ret = __opal_send_cmd(dev->resume_data, dev->comID, buffer, > + buflen, opal_send_cb, dev); > + else > + ret = _opal_send_cmd(dev->bdev, dev->comID, buffer, buflen, > + opal_send_cb, dev); > + > + return ret; > +} > + > +static void check_geometry(struct opal_dev *dev, const void *data) > +{ > + const struct d0_geometry_features *geo = data; > + > + dev->align = geo->alignment_granularity; > + dev->lowest_lba = geo->lowest_aligned_lba; > +} > + > +static void opal_discovery0_end(int error, void *data) > +{ > + bool foundComID = false, supported = true, single_user = false; > + struct opal_dev *dev = data; > + const struct d0_header *hdr; > + const u8 *epos, *cpos; > + u16 comID = 0; > + > + if (error) { > + pr_err("%s: Sending discovery0 failed\n", dev->disk_name); > + goto err_callback; > + } > + > + epos = dev->cmd.resp; > + cpos = dev->cmd.resp; > + hdr = (struct d0_header *)dev->cmd.resp; > + > + print_buffer(dev->cmd.resp, be32_to_cpu(hdr->length)); > + > + epos += be32_to_cpu(hdr->length); /* end of buffer */ > + cpos += sizeof(*hdr); /* current position on buffer */ > + > + while (cpos < epos && supported) { > + const struct d0_features *body = > + (const struct d0_features *)cpos; > + > + switch (be16_to_cpu(body->code)) { > + case FC_TPER: > + supported = check_tper(body->features); > + break; > + case FC_SINGLEUSER: > + single_user = check_SUM(body->features); > + break; > + case FC_GEOMETRY: > + check_geometry(dev, body); > + break; > + case FC_LOCKING: > + case FC_ENTERPRISE: > + case FC_DATASTORE: > + /* some ignored properties */ > + pr_debug("%s: Found OPAL feature description: %d\n", > + dev->disk_name, be16_to_cpu(body->code)); > + break; > + case FC_OPALV100: > + comID = get_comID_v100(body->features); > + foundComID = true; > + break; > + case FC_OPALV200: > + comID = get_comID_v200(body->features); > + foundComID = true; > + break; > + default: > + if (be16_to_cpu(body->code) > 0xbfff) { > + /* vendor specific, just ignore */ > + } else { > + pr_warn("%s: OPAL Unknown feature: %d\n", > + dev->disk_name, be16_to_cpu(body->code)); > + } Small nit, how about: case 0xbfff ... 0xffff: /* vendor specific, just ignore */ break; default: pr_warn(... > + } > + cpos += body->length + 4; > + } > + > + if (!supported) { > + pr_err("%s: Device not supported\n", dev->disk_name); > + goto err_callback; > + } > + > + if (!single_user) > + pr_warn("%s: Device doesn't support single user mode\n", > + dev->disk_name); > + > + if (!foundComID) { > + pr_warn("%s: Could not find OPAL comID for device. OPAL kernel unlocking will be disabled\n", > + dev->disk_name); > + goto err_callback; > + } > + > + dev->comID = comID; > + > +err_callback: > + if (dev->oper_cb) > + dev->oper_cb(error, dev); > +} > + > +static int opal_discovery0(struct opal_dev *dev) > +{ > + memset(dev->cmd.resp, 0, IO_BUFFER_LENGTH); > + > + if (dev->resume_from_suspend) > + return __opal_recv_cmd(dev->resume_data, 0x0001, > + dev->cmd.resp, IO_BUFFER_LENGTH, > + opal_discovery0_end, dev); > + > + return _opal_recv_cmd(dev->bdev, 0x0001, dev->cmd.resp, > + IO_BUFFER_LENGTH, opal_discovery0_end, > + dev); > +} > + > +static void add_token_u8(struct opal_cmd *cmd, u8 tok) > +{ > + cmd->cmd[cmd->pos++] = tok; > +} > + > +static ssize_t test_and_add_token_u8(struct opal_cmd *cmd, u8 tok) > +{ > + BUILD_BUG_ON(IO_BUFFER_LENGTH >= SIZE_MAX); > + > + if (cmd->pos >= IO_BUFFER_LENGTH - 1) { > + pr_err("Error adding u8: end of buffer.\n"); > + return -ERANGE; > + } > + > + add_token_u8(cmd, tok); > + > + return 1; > +} > + > +#define TINY_ATOM_DATA_MASK GENMASK(5, 0) > +#define TINY_ATOM_SIGNED BIT(6) > + > +#define SHORT_ATOM_ID BIT(7) > +#define SHORT_ATOM_BYTESTRING BIT(5) > +#define SHORT_ATOM_SIGNED BIT(4) > +#define SHORT_ATOM_LEN_MASK GENMASK(3, 0) > + > +static void add_short_atom_header(struct opal_cmd *cmd, bool bytestring, > + bool has_sign, int len) > +{ > + u8 atom; > + > + atom = SHORT_ATOM_ID; > + atom |= bytestring ? SHORT_ATOM_BYTESTRING : 0; > + atom |= has_sign ? SHORT_ATOM_SIGNED : 0; > + atom |= len & SHORT_ATOM_LEN_MASK; > + > + add_token_u8(cmd, atom); > +} > + > +#define MEDIUM_ATOM_ID (BIT(7) | BIT(6)) > +#define MEDIUM_ATOM_BYTESTRING BIT(4) > +#define MEDIUM_ATOM_SIGNED BIT(3) > +#define MEDIUM_ATOM_LEN_MASK GENMASK(2, 0) > + > +static void add_medium_atom_header(struct opal_cmd *cmd, bool bytestring, > + bool has_sign, int len) > +{ > + u8 header0; > + > + header0 = MEDIUM_ATOM_ID; > + header0 |= bytestring ? MEDIUM_ATOM_BYTESTRING : 0; > + header0 |= has_sign ? MEDIUM_ATOM_SIGNED : 0; > + header0 |= (len >> 8) & MEDIUM_ATOM_LEN_MASK; > + cmd->cmd[cmd->pos++] = header0; > + cmd->cmd[cmd->pos++] = len; > +} > + > +static void add_token_u64(struct opal_cmd *cmd, u64 number, size_t len) > +{ > + add_short_atom_header(cmd, false, false, len); > + > + while (len--) { > + u8 n = number >> (len * 8); > + > + add_token_u8(cmd, n); > + } > +} > + > +static ssize_t test_and_add_token_u64(struct opal_cmd *cmd, u64 number) > +{ > + int len; > + int msb; > + > + if (!(number & ~TINY_ATOM_DATA_MASK)) > + return test_and_add_token_u8(cmd, number); > + > + msb = fls(number); > + len = DIV_ROUND_UP(msb, 4); > + > + if (cmd->pos >= IO_BUFFER_LENGTH - len - 1) { > + pr_err("Error adding u64: end of buffer.\n"); > + return -ERANGE; > + } > + > + add_token_u64(cmd, number, len); > + > + /* return length of token plus atom */ > + return len + 1; > +} > + > +static void add_token_bytestring(struct opal_cmd *cmd, > + const u8 *bytestring, size_t len) > +{ > + memcpy(&cmd->cmd[cmd->pos], bytestring, len); > + cmd->pos += len; > +} > + > +static ssize_t test_and_add_token_bytestring(struct opal_cmd *cmd, > + const u8 *bytestring, size_t len) > +{ > + size_t header_len = 1; > + bool is_short_atom = true; > + > + if (len & ~SHORT_ATOM_LEN_MASK) { > + header_len = 2; > + is_short_atom = false; > + } > + > + if (cmd->pos >= IO_BUFFER_LENGTH - len - header_len) { > + pr_err("Error adding bytestring: end of buffer.\n"); > + return -ERANGE; > + } > + > + if (is_short_atom) > + add_short_atom_header(cmd, true, false, len); > + else > + add_medium_atom_header(cmd, true, false, len); > + > + add_token_bytestring(cmd, bytestring, len); > + > + return header_len + len; > +} > + > +#define LOCKING_RANGE_NON_GLOBAL 0x03 > + > +static int build_locking_range(u8 *buffer, size_t length, u8 lr) > +{ > + if (length < OPAL_UID_LENGTH) > + return -ERANGE; > + > + memcpy(buffer, OPALUID[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH); > + > + if (lr == 0) > + return 0; > + buffer[5] = LOCKING_RANGE_NON_GLOBAL; > + buffer[7] = lr; > + > + return 0; > +} > + > +static int build_locking_user(u8 *buffer, size_t length, u8 lr) > +{ > + if (length < OPAL_UID_LENGTH) > + return -ERANGE; > + > + memcpy(buffer, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH); > + > + buffer[7] = lr + 1; > + > + return 0; > +} > + > +/* > + * N = number of format specifiers (1-999) to be replicated > + * c = u8 > + * u = u64 > + * s = bytestring, length > + * > + * ret = test_and_add_token_va(cmd, "c", > + * u8_val1); > + * > + * ret = test_and_add_token_va(cmd, "2c2u", > + * u8_val1, u8_val2, u64_val1, u64_val2); > + * > + * ret = test_and_add_token_va(cmd, "3s", > + * bytestring1, length1, > + * bytestring2, length2, > + * bytestring3, length3); > + */ > +static int test_and_add_token_va(struct opal_cmd *cmd, > + const char *fmt, ...) > +{ > + const u8 *it = fmt, *tmp; > + int ret, num = 1, sum = 0; > + va_list ap; > + > + va_start(ap, fmt); > + > + while (*it != '\0') { > + u64 tok64 = 0; > + u8 tok, *bstr; > + size_t len; > + > + ret = 0; > + > + switch (*it) { > + case '1' ... '9': > + tmp = it; > + num = 0; > + while (*tmp >= '0' && *tmp <= '9') > + num = num * 10 + (*tmp++ - '0'); > + it = tmp; > + continue; > + case 'c': > + while (num--) { > + tok = va_arg(ap, unsigned int); > + ret = test_and_add_token_u8(cmd, tok); > + if (ret < 0) > + goto err; > + } > + num = 1; > + break; > + case 'u': > + while (num--) { > + tok64 = va_arg(ap, u64); > + ret = test_and_add_token_u64(cmd, tok64); > + if (ret < 0) > + goto err; > + } > + num = 1; > + break; > + case 's': > + while (num--) { > + bstr = va_arg(ap, u8 *); > + len = va_arg(ap, size_t); > + ret = test_and_add_token_bytestring(cmd, bstr, > + len); > + if (ret < 0) > + goto err; > + } > + num = 1; > + break; > + case ' ': > + case '\t': > + /* ignored */ > + break; > + default: > + pr_warn("Unrecognized type.\n"); > + } > + > + it++; > + sum += ret; > + } > + > + va_end(ap); > + > + return sum; > + > + err: > + pr_err("Token failed to be added.\n"); > + return ret; > +} > + > +static void set_comID(struct opal_cmd *cmd, u16 comID) > +{ > + struct opal_header *hdr = (struct opal_header *)cmd->cmd; > + > + hdr->cp.extendedComID[0] = comID >> 8; > + hdr->cp.extendedComID[1] = comID; > + hdr->cp.extendedComID[2] = 0; > + hdr->cp.extendedComID[3] = 0; > +} > + > +static int cmd_finalize(struct opal_cmd *cmd, u32 hsn, u32 tsn) > +{ > + struct opal_header *hdr; > + int ret; > + > + ret = test_and_add_token_va(cmd, "6c", > + OPAL_ENDOFDATA, OPAL_STARTLIST, > + 0, 0, 0, OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("Error finalizing command.\n"); > + return -EFAULT; > + } > + > + hdr = (struct opal_header *) cmd->cmd; > + > + hdr->pkt.TSN = cpu_to_be32(tsn); > + hdr->pkt.HSN = cpu_to_be32(hsn); > + > + hdr->subpkt.length = cpu_to_be32(cmd->pos - sizeof(*hdr)); > + while (cmd->pos % 4) { > + if (cmd->pos >= IO_BUFFER_LENGTH) { > + pr_err("Error: Buffer overrun\n"); > + return -ERANGE; > + } > + cmd->cmd[cmd->pos++] = 0; > + } > + hdr->pkt.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp) - > + sizeof(hdr->pkt)); > + hdr->cp.length = cpu_to_be32(cmd->pos - sizeof(hdr->cp)); > + > + return 0; > +} > + > +static enum OPAL_RESPONSE_TOKEN token_type(const struct parsed_resp *resp, > + int n) > +{ > + const struct opal_resp_tok *tok; > + > + if (n >= resp->num) { > + pr_err("Token number doesn't exist: %d, resp: %d\n", > + n, resp->num); > + return OPAL_DTA_TOKENID_INVALID; > + } > + > + tok = &resp->toks[n]; > + if (tok->len == 0) { > + pr_err("Token length must be non-zero\n"); > + return OPAL_DTA_TOKENID_INVALID; > + } > + > + return tok->type; > +} > + > +/* > + * This function returns 0 in case of invalid token. One should call > + * token_type() first to find out if the token is valid or not. > + */ > +static enum OPAL_TOKEN response_get_token(const struct parsed_resp *resp, > + int n) > +{ > + const struct opal_resp_tok *tok; > + > + if (n >= resp->num) { > + pr_err("Token number doesn't exist: %d, resp: %d\n", > + n, resp->num); > + return 0; > + } > + > + tok = &resp->toks[n]; > + if (tok->len == 0) { > + pr_err("Token length must be non-zero\n"); > + return 0; > + } > + > + return tok->pos[0]; > +} > + > +static size_t response_parse_tiny(struct opal_resp_tok *tok, > + const u8 *pos) > +{ > + tok->pos = pos; > + tok->len = 1; > + tok->width = OPAL_WIDTH_TINY; > + > + if (pos[0] & TINY_ATOM_SIGNED) { > + tok->type = OPAL_DTA_TOKENID_SINT; > + } else { > + tok->type = OPAL_DTA_TOKENID_UINT; > + tok->stored.u = pos[0] & 0x3f; > + } > + > + return tok->len; > +} > + > +static size_t response_parse_short(struct opal_resp_tok *tok, > + const u8 *pos) > +{ > + tok->pos = pos; > + tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1; > + tok->width = OPAL_WIDTH_SHORT; > + > + if (pos[0] & SHORT_ATOM_BYTESTRING) { > + tok->type = OPAL_DTA_TOKENID_BYTESTRING; > + } else if (pos[0] & SHORT_ATOM_SIGNED) { > + tok->type = OPAL_DTA_TOKENID_SINT; > + } else { > + u64 u_integer = 0; > + int i, b = 0; > + > + tok->type = OPAL_DTA_TOKENID_UINT; > + if (tok->len > 9) Should this be len > 8 or len >= 9 ? > + pr_warn("uint64 with more than 8 bytes\n"); > + for (i = tok->len - 1; i > 0; i--) { > + u_integer |= ((u64)pos[i] << (8 * b)); > + b++; > + } It doesn't look particularly safe to keep using this driver on a drive if it returns a len > 8. But the specs do allow 16-byte data in a short atom, so maybe we should bail on allowing the driver to manage the drive, or change the types to some 16-byte type? > + tok->stored.u = u_integer; > + } > + > + return tok->len; > +} > + > +static size_t response_parse_medium(struct opal_resp_tok *tok, > + const u8 *pos) > +{ > + tok->pos = pos; > + tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2; > + tok->width = OPAL_WIDTH_MEDIUM; > + > + if (pos[0] & MEDIUM_ATOM_BYTESTRING) > + tok->type = OPAL_DTA_TOKENID_BYTESTRING; > + else if (pos[0] & MEDIUM_ATOM_SIGNED) > + tok->type = OPAL_DTA_TOKENID_SINT; > + else > + tok->type = OPAL_DTA_TOKENID_UINT; > + > + return tok->len; > +} > + > +#define LONG_ATOM_ID (BIT(7) | BIT(6) | BIT(5)) > +#define LONG_ATOM_BYTESTRING BIT(1) > +#define LONG_ATOM_SIGNED BIT(0) > +static size_t response_parse_long(struct opal_resp_tok *tok, > + const u8 *pos) > +{ > + tok->pos = pos; > + tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4; > + tok->width = OPAL_WIDTH_LONG; > + > + if (pos[0] & LONG_ATOM_BYTESTRING) > + tok->type = OPAL_DTA_TOKENID_BYTESTRING; > + else if (pos[0] & LONG_ATOM_SIGNED) > + tok->type = OPAL_DTA_TOKENID_SINT; > + else > + tok->type = OPAL_DTA_TOKENID_UINT; > + > + return tok->len; > +} > + > +static size_t response_parse_token(struct opal_resp_tok *tok, > + const u8 *pos) > +{ > + tok->pos = pos; > + tok->len = 1; > + tok->type = OPAL_DTA_TOKENID_TOKEN; > + tok->width = OPAL_WIDTH_TOKEN; > + > + return tok->len; > +} > + > +static int response_parse(const u8 *buf, size_t length, > + struct parsed_resp *resp) > +{ > + const struct opal_header *hdr; > + struct opal_resp_tok *iter; > + int ret, num_entries = 0; > + u32 cpos = 0, total; > + size_t token_length; > + const u8 *pos; > + > + if (!buf) > + return -EFAULT; > + > + if (!resp) > + return -EFAULT; > + > + hdr = (struct opal_header *)buf; > + pos = buf; > + pos += sizeof(*hdr); > + > + pr_debug("Response size: cp: %d, pkt: %d, subpkt: %d\n", > + be32_to_cpu(hdr->cp.length), > + be32_to_cpu(hdr->pkt.length), > + be32_to_cpu(hdr->subpkt.length)); > + > + if ((hdr->cp.length == 0) > + || (hdr->pkt.length == 0) > + || (hdr->subpkt.length == 0)) { > + pr_err("Bad header length. cp: %d, pkt: %d, subpkt: %d\n", > + be32_to_cpu(hdr->cp.length), > + be32_to_cpu(hdr->pkt.length), > + be32_to_cpu(hdr->subpkt.length)); > + print_buffer(pos, sizeof(*hdr)); > + ret = -EINVAL; > + goto err; > + } > + > + if (pos > buf + length) { > + ret = -EFAULT; > + goto err; > + } > + > + iter = resp->toks; > + total = be32_to_cpu(hdr->subpkt.length); > + print_buffer(pos, total); > + while (cpos < total) { > + if (!(pos[0] & 0x80)) /* tiny atom */ > + token_length = response_parse_tiny(iter, pos); > + else if (!(pos[0] & 0x40)) /* short atom */ > + token_length = response_parse_short(iter, pos); > + else if (!(pos[0] & 0x20)) /* medium atom */ > + token_length = response_parse_medium(iter, pos); > + else if (!(pos[0] & 0x10)) /* long atom */ > + token_length = response_parse_long(iter, pos); > + else /* TOKEN */ > + token_length = response_parse_token(iter, pos); > + > + pos += token_length; > + cpos += token_length; > + iter++; > + num_entries++; > + } > + > + if (num_entries == 0) { > + pr_err("Couldn't parse response.\n"); > + ret = -EINVAL; > + goto err; > + } > + resp->num = num_entries; > + > + return 0; > +err: > + return ret; > +} > + > +static size_t response_get_string(const struct parsed_resp *resp, int n, > + const char **store) > +{ > + *store = NULL; > + if (!resp) { > + pr_err("Response is NULL\n"); > + return 0; > + } > + > + if (n > resp->num) { > + pr_err("Response has %d tokens. Can't access %d\n", > + resp->num, n); > + return 0; > + } > + > + if (resp->toks[n].type != OPAL_DTA_TOKENID_BYTESTRING) { > + pr_err("Token is not a byte string!\n"); > + return 0; > + } > + > + *store = resp->toks[n].pos + 1; > + return resp->toks[n].len - 1; > +} > + > +static u64 response_get_u64(const struct parsed_resp *resp, int n) > +{ > + if (!resp) { > + pr_err("Response is NULL\n"); > + return 0; > + } > + > + if (n > resp->num) { > + pr_err("Response has %d tokens. Can't access %d\n", > + resp->num, n); > + return 0; > + } > + > + if (resp->toks[n].type != OPAL_DTA_TOKENID_UINT) { > + pr_err("Token is not unsigned it: %d\n", > + resp->toks[n].type); > + return 0; > + } > + > + if (!((resp->toks[n].width == OPAL_WIDTH_TINY) || > + (resp->toks[n].width == OPAL_WIDTH_SHORT))) { > + pr_err("Atom is not short or tiny: %d\n", > + resp->toks[n].width); > + return 0; > + } > + > + return resp->toks[n].stored.u; > +} > + > +static u8 response_status(const struct parsed_resp *resp) > +{ > + if ((token_type(resp, 0) == OPAL_DTA_TOKENID_TOKEN) > + && (response_get_token(resp, 0) == OPAL_ENDOFSESSION)) { > + return 0; > + } > + > + if (resp->num < 5) > + return DTAERROR_NO_METHOD_STATUS; > + > + if ((token_type(resp, resp->num - 1) != OPAL_DTA_TOKENID_TOKEN) || > + (token_type(resp, resp->num - 5) != OPAL_DTA_TOKENID_TOKEN) || > + (response_get_token(resp, resp->num - 1) != OPAL_ENDLIST) || > + (response_get_token(resp, resp->num - 5) != OPAL_STARTLIST)) > + return DTAERROR_NO_METHOD_STATUS; > + > + return response_get_u64(resp, resp->num - 4); > +} > + > +/* Parses and checks for errors */ > +static int parse_and_check_status(struct opal_dev *dev) > +{ > + struct opal_cmd *cmd; > + int error; > + > + cmd = &dev->cmd; > + print_buffer(cmd->cmd, cmd->pos); > + > + error = response_parse(cmd->resp, IO_BUFFER_LENGTH, &dev->parsed); > + if (error) { > + pr_err("%s: Couldn't parse response.\n", dev->disk_name); > + goto err_return; > + } > + > + error = response_status(&dev->parsed); > + if (error) > + pr_err("%s: Response Status: %d\n", dev->disk_name, > + error); > + > + err_return: > + return error; > +} > + > +static void clear_opal_cmd(struct opal_cmd *cmd) > +{ > + cmd->pos = sizeof(struct opal_header); > + memset(cmd->cmd, 0, IO_BUFFER_LENGTH); > + cmd->cb = NULL; > + cmd->cb_data = NULL; > +} > + > +static void start_opal_session_cont(int error, void *data) > +{ > + struct opal_dev *dev = data; > + u32 HSN, TSN; > + > + if (error) > + goto err_return; > + > + error = parse_and_check_status(dev); > + if (error) > + goto err_return; > + > + HSN = response_get_u64(&dev->parsed, 4); > + TSN = response_get_u64(&dev->parsed, 5); > + > + if (HSN == 0 && TSN == 0) { > + pr_err("%s: Couldn't authenticate session\n", dev->disk_name); > + error = -EPERM; > + goto err_return; > + } > + > + dev->HSN = HSN; > + dev->TSN = TSN; > + > +err_return: > + if (dev->oper_cb) > + dev->oper_cb(error, dev); > +} > + > +static int get_opal_key(struct opal_dev *dev) > +{ > + struct key *ukey = NULL; > + const u8 *tmpkey = NULL; > + size_t tmplen; > + int ret = 0; > + > + if (dev->key_type == OPAL_KEY_PLAIN) { > + tmpkey = dev->key_name; > + tmplen = dev->key_name_len; > + } else if (dev->key_type == OPAL_KEY_KEYRING) { > + ukey = request_user_key(dev->key_name, &tmpkey, &tmplen); > + if (IS_ERR(ukey)) { > + pr_err("%s: Can't retrieve key: %ld\n", dev->disk_name, > + PTR_ERR(ukey)); > + return PTR_ERR(ukey); > + } > + } else { > + pr_err("Requested invalid key type: %d\n", dev->key_type); > + return -EINVAL; > + } > + > + if (tmplen > OPAL_KEY_MAX) { > + pr_err("Requested key with invalid size: %zd\n", tmplen); > + ret = -EINVAL; > + goto err_exit; > + } > + > + dev->key_len = tmplen; > + if (!memcpy(dev->key, tmpkey, tmplen)) { > + pr_err("Error when copying key"); > + ret = -EFAULT; > + goto err_exit; > + } > + > +err_exit: > + key_put(ukey); > + > + return 0; > +} > + > +static void clean_opal_key(struct opal_dev *dev) > +{ > + memset(dev->key, 0, OPAL_KEY_MAX); > + dev->key_len = 0; > +} > + > +static inline void clean_function_data(struct opal_dev *dev) > +{ > + dev->func_data = NULL; > + dev->num_func_data = 0; > +} > + > +/* This is a generic continue fn. > + * We use this when we don't care about the response data > + * and simply want to check the status and continue. > + */ > +static void generic_cont(int error, void *data) > +{ > + struct opal_dev *dev = data; > + > + if (error) > + goto err_return; > + > + error = parse_and_check_status(dev); > + > + err_return: > + if (dev->oper_cb) > + dev->oper_cb(error, dev); > +} How about: static void generic_cont(int error, void *data) { struct opal_dev *dev = data; if (!error) error = parse_and_check_status(dev); if (dev->oper_cb) dev->oper_cb(error, dev); } > + > +static void end_session_cont(int error, void *data) > +{ > + struct opal_dev *dev = data; > + > + dev->HSN = 0; > + dev->TSN = 0; > + generic_cont(error, data); > +} > + > +static int finalize_and_send(struct opal_dev *dev, struct opal_cmd *cmd, > + sec_cb cont) > +{ > + int ret; > + > + ret = cmd_finalize(cmd, dev->HSN, dev->TSN); > + if (ret) { > + pr_err("%s: Error finalizing command buffer: %d\n", > + dev->disk_name, ret); > + return ret; > + } > + > + print_buffer(cmd->cmd, cmd->pos); > + > + ret = opal_send_recv(dev, cont, dev); > + if (ret) > + pr_err("%s: Error running command: %d\n", > + dev->disk_name, ret); > + > + return ret; > +} > + > +static int wait_for_cmd_completion(struct opal_completion *completion) > +{ > + wait_for_completion_interruptible(&completion->cmd_completion); > + return completion->completion_status; > +} > + > +static int gen_key(struct opal_dev *dev) > +{ > + const u8 *method; > + u8 uid[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + int ret; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + memcpy(uid, dev->prev_data, min(sizeof(uid), dev->prev_d_len)); > + method = OPALMETHOD[OPAL_GENKEY]; > + kfree(dev->prev_data); > + dev->prev_data = NULL; > + > + ret = test_and_add_token_va(cmd, "c2s 2c", > + OPAL_CALL, > + uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_ENDLIST); > + if (ret < 0) { > + pr_err("%s: Error building gen key command\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static void get_active_key_cont(int error, void *data) > +{ > + struct opal_dev *dev = data; > + const char *activekey; > + size_t keylen; > + > + if (error) > + goto err_return; > + > + error = parse_and_check_status(dev); > + if (error) > + goto err_return; > + keylen = response_get_string(&dev->parsed, 4, &activekey); > + if (!activekey) { > + pr_err("%s: Couldn't extract the Activekey from the response\n", > + __func__); > + error = 0x0A; > + goto err_return; > + } > + dev->prev_data = kmemdup(activekey, keylen, GFP_KERNEL); > + > + if (!dev->prev_data) > + error = -ENOMEM; > + > + dev->prev_d_len = keylen; > + > +err_return: > + if (dev->oper_cb) > + dev->oper_cb(error, dev); > +} > + > +static int get_active_key(struct opal_dev *dev) > +{ > + const u8 *method; > + u8 uid[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + int ret; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + method = OPALMETHOD[OPAL_GET]; > + > + ret = build_locking_range(uid, sizeof(uid), dev->lr); > + if (ret < 0) { > + pr_err("%s: Can't build locking range\n", dev->disk_name); > + return -EINVAL; > + } > + > + ret = test_and_add_token_va(cmd, "c2s 6c 4c 2c", > + OPAL_CALL, > + uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_03, /* startCloumn */ > + OPAL_TINY_UINT_10, /* ActiveKey */ > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPAL_TINY_UINT_04, /* endColumn */ > + OPAL_TINY_UINT_10, /* ActiveKey */ > + OPAL_ENDNAME, > + > + OPAL_ENDLIST, > + OPAL_ENDLIST); > + if (ret < 0) { > + pr_err("%s: Error building get active key command\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, get_active_key_cont); > +} > + > +static int setup_locking_range(struct opal_dev *dev) > +{ > + const u8 *method; > + u8 uid[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + struct opal_user_lr_setup *setup; > + int ret; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + method = OPALMETHOD[OPAL_SET]; > + ret = build_locking_range(uid, sizeof(uid), dev->lr); > + if (ret < 0) { > + pr_err("%s: Can't build locking range\n", dev->disk_name); > + return -EINVAL; > + } > + setup = dev->func_data[dev->state - 1]; > + > + ret = test_and_add_token_va(cmd, "c2s 4c 2cuc 2cuc 2cuc 2cu 4c", > + OPAL_CALL, > + uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_VALUES, > + OPAL_STARTLIST, > + > + OPAL_STARTNAME, > + OPAL_TINY_UINT_03, /* Range Start */ > + setup->range_start, > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPAL_TINY_UINT_04, /* Range Length */ > + setup->range_length, > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPAL_TINY_UINT_05, /* ReadLockEnabled */ > + !!setup->RLE, > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPAL_TINY_UINT_06, /* WriteLockEnabled */ > + !!setup->WLE, > + > + OPAL_ENDNAME, > + OPAL_ENDLIST, > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + if (ret < 0) { > + pr_err("%s: Error building Setup Locking range command.\n", > + dev->disk_name); > + return ret; > + > + } > + > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static int start_adminsp_opal_session(struct opal_dev *dev, > + enum OPAL_UID auth, > + const char *key, > + u8 key_len) > +{ > + const u8 *method, *smuid, *admin_sp, *hsa; > + struct opal_cmd *cmd; > + u32 HSN; > + int ret; > + > + if (key == NULL && auth != OPAL_ANYBODY_UID) { > + pr_err("%s: Attempted to open ADMIN_SP Session without a Host" \ > + "Challenge, and not as the Anybody UID\n", __func__); > + return 1; > + } > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + > + set_comID(cmd, dev->comID); > + HSN = 0x41; > + > + smuid = OPALUID[OPAL_SMUID_UID]; > + method = OPALMETHOD[OPAL_STARTSESSION]; > + admin_sp = OPALUID[OPAL_ADMINSP_UID]; > + > + ret = test_and_add_token_va(cmd, "c2s cusc", > + OPAL_CALL, > + smuid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + OPAL_STARTLIST, > + HSN, > + admin_sp, OPAL_UID_LENGTH, > + OPAL_TINY_UINT_01); > + if (ret < 0) { > + pr_err("%s: Error building start adminsp session command.\n", > + dev->disk_name); > + return ret; > + } > + > + switch (auth) { > + case OPAL_ANYBODY_UID: > + /* nothing left to do for anybody, just end and finalize */ > + ret = test_and_add_token_va(cmd, "c", > + OPAL_ENDLIST); > + break; > + case OPAL_SID_UID: > + hsa = OPALUID[OPAL_SID_UID]; > + ret = test_and_add_token_va(cmd, "2c s 3c s 2c", > + OPAL_STARTNAME, > + OPAL_TINY_UINT_00, /* HostChallenge */ > + key, key_len, > + OPAL_ENDNAME, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_03, /* HostSignAuth */ > + hsa, OPAL_UID_LENGTH, > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + break; > + default: > + pr_err("Cannot start Admin SP session with auth %d\n", auth); > + return 1; > + } > + > + if (ret < 0) { > + pr_err("%s: Error building start adminsp session command.\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, start_opal_session_cont); > +} > + > +static int start_anybodyASP_opal_session(struct opal_dev *dev) > +{ > + return start_adminsp_opal_session(dev, OPAL_ANYBODY_UID, NULL, 0); > +} > + > +static int start_SIDASP_opal_session(struct opal_dev *dev) > +{ > + int ret; > + const u8 *key = dev->prev_data; > + > + if (!key) > + ret = start_adminsp_opal_session(dev, OPAL_SID_UID, dev->key, > + dev->key_len); > + else { > + ret = start_adminsp_opal_session(dev, OPAL_SID_UID, key, > + dev->prev_d_len); > + kfree(key); > + dev->prev_data = NULL; > + } > + return ret; > +} > + > +static int start_lockingsp_opal_session(struct opal_dev *dev, > + enum OPAL_UID auth, const u8 *key, > + u8 key_len) > +{ > + > + const u8 *method, *smuid, *locking_sp, *hsa; > + struct opal_cmd *cmd; > + size_t klen = key_len; > + u32 HSN; > + int ret; > + > + if (key == NULL) { > + pr_err("Cannot start Locking SP session without a key\n"); > + return -EINVAL; > + } > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + > + set_comID(cmd, dev->comID); > + HSN = 0x41; > + > + smuid = OPALUID[OPAL_SMUID_UID]; > + method = OPALMETHOD[OPAL_STARTSESSION]; > + locking_sp = OPALUID[OPAL_LOCKINGSP_UID]; > + hsa = OPALUID[auth]; > + > + ret = test_and_add_token_va(cmd, "c2s cusc 2csc 2csc c", > + OPAL_CALL, > + smuid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + HSN, > + locking_sp, OPAL_UID_LENGTH, > + OPAL_TINY_UINT_01, > + > + OPAL_STARTNAME, > + OPAL_TINY_UINT_00, /* HostChallenge */ > + key, klen, > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPAL_TINY_UINT_03, /* Host Sign Authority */ > + hsa, OPAL_UID_LENGTH, > + OPAL_ENDNAME, > + > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error building start adminsp session command.\n", > + dev->disk_name); > + return ret; > + } > + return finalize_and_send(dev, cmd, start_opal_session_cont); > +} > + > +static inline int start_admin1LSP_opal_session(struct opal_dev *dev) > +{ > + return start_lockingsp_opal_session(dev, OPAL_ADMIN1_UID, > + dev->key, dev->key_len); > +} > + > +static int start_auth_opal_session(struct opal_dev *dev) > +{ > + const u8 *method, *smuid, *locking_sp; > + u8 lk_ul_user[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + u32 HSN; > + int ret; > + struct opal_user_info *uinfo; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + > + set_comID(cmd, dev->comID); > + > + HSN = 0x41; Can we #define this; it's used a few other places and is magicky > + > + uinfo = dev->func_data[dev->state - 1]; > + > + smuid = OPALUID[OPAL_SMUID_UID]; > + method = OPALMETHOD[OPAL_STARTSESSION]; > + locking_sp = OPALUID[OPAL_LOCKINGSP_UID]; > + > + if (uinfo->SUM) { > + ret = build_locking_user(lk_ul_user, sizeof(lk_ul_user), > + dev->lr); > + if (ret < 0) { > + pr_err("%s: Can't build locking user\n", > + dev->disk_name); > + return ret; > + } > + } else if (uinfo->who != OPAL_ADMIN1 && !uinfo->SUM) { > + ret = build_locking_user(lk_ul_user, sizeof(lk_ul_user), > + uinfo->who - 1); > + if (ret < 0) { > + pr_err("%s: Can't build locking user\n", > + dev->disk_name); > + return ret; > + } > + } else > + memcpy(lk_ul_user, OPALUID[OPAL_ADMIN1_UID], OPAL_UID_LENGTH); > + > + > + ret = test_and_add_token_va(cmd, "c2s cus3cs3c s 2c", > + OPAL_CALL, > + smuid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + HSN, > + locking_sp, OPAL_UID_LENGTH, > + OPAL_TINY_UINT_01, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_00, > + dev->key, dev->key_len, > + OPAL_ENDNAME, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_03, > + > + lk_ul_user, OPAL_UID_LENGTH, > + > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error building STARTSESSION command.\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, start_opal_session_cont); > +} > + > +static int revert_tper(struct opal_dev *dev) > +{ > + const u8 *method, *smuid; > + struct opal_cmd *cmd; > + int ret; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + > + set_comID(cmd, dev->comID); > + > + smuid = OPALUID[OPAL_ADMINSP_UID]; > + method = OPALMETHOD[OPAL_REVERT]; > + > + ret = test_and_add_token_va(cmd, "c2s 2c", > + OPAL_CALL, > + smuid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + OPAL_STARTLIST, > + OPAL_ENDLIST); > + if (ret < 0) { > + pr_err("%s: Error building REVERT TPER command.\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static int internal_activate_user(struct opal_dev *dev) > +{ > + const u8 *method; > + u8 uid[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + int ret; > + struct opal_activate_user *act; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + act = dev->func_data[dev->state - 1]; > + > + memcpy(uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH); > + uid[7] = act->who.who; > + > + method = OPALMETHOD[OPAL_SET]; > + > + ret = test_and_add_token_va(cmd, "c2s 3c c 4c 3c", > + OPAL_CALL, > + uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_01, /* Values */ > + > + OPAL_STARTLIST, > + > + OPAL_STARTNAME, > + OPAL_TINY_UINT_05, /* Enabled */ > + OPAL_TINY_UINT_01, /* True */ > + OPAL_ENDNAME, > + > + OPAL_ENDLIST, > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error building Activate UserN command.\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static int erase_locking_range(struct opal_dev *dev) > +{ > + const u8 *method; > + u8 uid[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + int ret; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + method = OPALMETHOD[OPAL_ERASE]; > + > + if (build_locking_range(uid, sizeof(uid), dev->lr) < 0) { > + pr_err("%s: Can't build locking range\n", dev->disk_name); > + return -EINVAL; > + } > + > + ret = test_and_add_token_va(cmd, "c2s 2c", > + OPAL_CALL, > + uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error building Erase Locking Range Cmmand.\n", > + dev->disk_name); > + return ret; > + } > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static int set_mbr_done(struct opal_dev *dev) > +{ > + const u8 *method, *uid; > + struct opal_cmd *cmd; > + int ret; > + > + u8 mbr_done_tf = *(u8 *)dev->func_data[dev->state - 1]; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + method = OPALMETHOD[OPAL_SET]; > + uid = OPALUID[OPAL_MBRCONTROL]; > + > + ret = test_and_add_token_va(cmd, "c2s 3c 6c 2c", > + OPAL_CALL, > + uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_VALUES, > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_02, /* Done */ > + mbr_done_tf, /* Done T or F */ > + OPAL_ENDNAME, > + OPAL_ENDLIST, > + > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + if (ret < 0) { > + pr_err("%s: Error Building set MBR Dont/Not done command\n", s/Dont/Done/ ? > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static int set_mbr_enable_disable(struct opal_dev *dev) > +{ > + const u8 *method, *uid; > + struct opal_cmd *cmd; > + int ret; > + > + u8 mbr_en_dis = *(u8 *)dev->func_data[dev->state - 1]; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + method = OPALMETHOD[OPAL_SET]; > + uid = OPALUID[OPAL_MBRCONTROL]; > + > + ret = test_and_add_token_va(cmd, "c2s 3c 6c 2c", > + OPAL_CALL, > + uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_VALUES, > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_01, /* Enable */ > + mbr_en_dis, /* Enable or Disable */ > + OPAL_ENDNAME, > + OPAL_ENDLIST, > + > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + if (ret < 0) { > + pr_err("%s: Error Building set MBR Dont/Not done command\n", s/Dont/Done/ ? > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static int set_new_pw(struct opal_dev *dev) > +{ > + const u8 *method; > + u8 cpin_uid[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + int ret; > + struct opal_new_pw *pw; > + size_t key_len; > + u8 *key; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + pw = dev->func_data[dev->state - 1]; > + key = pw->new_pin.key; > + key_len = pw->new_pin.key_len; > + memcpy(cpin_uid, OPALUID[OPAL_C_PIN_ADMIN1], OPAL_UID_LENGTH); > + > + if (pw->user_for_pw != OPAL_ADMIN1) { > + cpin_uid[5] = 0x03; > + if (pw->who.SUM) > + cpin_uid[7] = pw->new_pin.lr + 1; > + else > + cpin_uid[7] = pw->user_for_pw; > + } > + > + method = OPALMETHOD[OPAL_SET]; > + > + ret = test_and_add_token_va(cmd, "c2s 3c 3cs2c 2c", > + OPAL_CALL, > + cpin_uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_01, /* Values */ > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_03, /* PIN */ > + key, key_len, > + OPAL_ENDNAME, > + OPAL_ENDLIST, > + > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error building SET AMIN1 PIN command.\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static int set_sid_cpin_pin(struct opal_dev *dev) > +{ > + const u8 *method, *cpin_uid; > + struct opal_cmd *cmd; > + int ret; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + cpin_uid = OPALUID[OPAL_C_PIN_SID]; > + method = OPALMETHOD[OPAL_SET]; > + > + ret = test_and_add_token_va(cmd, "c2s 2c 4cs2c 2c", > + OPAL_CALL, > + cpin_uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + > + OPAL_TINY_UINT_01, /* Values */ > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_03, /* PIN */ > + dev->key, dev->key_len, > + OPAL_ENDNAME, > + OPAL_ENDLIST, > + > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error building SET CPIN PIN command.\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static void query_locking_range_cont(int error, void *data) > +{ > + struct opal_dev *dev = data; > + > + if (error) > + goto err_return; > + > + error = parse_and_check_status(dev); > + if (error) > + goto err_return; > + > + dev->start = response_get_u64(&dev->parsed, 4); > + dev->length = response_get_u64(&dev->parsed, 8); > + > +err_return: > + if (dev->oper_cb) > + dev->oper_cb(error, dev); > +} > + > +static int query_locking_range(struct opal_dev *dev) > +{ > + u8 lr_buffer[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + const u8 *method; > + int ret; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + > + method = OPALMETHOD[OPAL_GET]; > + > + if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) { > + pr_err("%s: Can't build locking range\n", dev->disk_name); > + return -EINVAL; > + } > + > + set_comID(cmd, dev->comID); > + > + ret = test_and_add_token_va(cmd, "c2s 12c", > + OPAL_CALL, > + lr_buffer, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_STARTCOLUMN, > + OPAL_RANGESTART, > + OPAL_ENDNAME, > + OPAL_STARTNAME, > + OPAL_ENDCOLUMN, > + OPAL_RANGELENGTH, > + OPAL_ENDNAME, > + OPAL_ENDLIST, > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error building GET Locking Range command.\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, query_locking_range_cont); > +} > + > +static int add_user_to_lr(struct opal_dev *dev) > +{ > + u8 lr_buffer[OPAL_UID_LENGTH]; > + u8 user_uid[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + const u8 *method; > + struct opal_lock_unlock *lkul; > + int ret; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + method = OPALMETHOD[OPAL_SET]; > + > + lkul = dev->func_data[dev->state - 1]; > + > + memcpy(lr_buffer, OPALUID[OPAL_LOCKINGRANGE_ACE_RDLOCKED], > + OPAL_UID_LENGTH); > + > + if (lkul->l_state == OPAL_RW) > + memcpy(lr_buffer, OPALUID[OPAL_LOCKINGRANGE_ACE_WRLOCKED], > + OPAL_UID_LENGTH); > + > + lr_buffer[7] = dev->lr; > + > + memcpy(user_uid, OPALUID[OPAL_USER1_UID], OPAL_UID_LENGTH); > + user_uid[7] = lkul->authority.who; > + > + ret = test_and_add_token_va(cmd, "c2s 3c 3c 2c 2sc c2sc cs2c 5c", > + OPAL_CALL, > + lr_buffer, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_01, /* Values */ > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_03, /* BooleanExpr */ > + > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + > + OPALUID[OPAL_HALF_UID_AUTHORITY_OBJ_REF], > + OPAL_UID_LENGTH_HALF, > + user_uid, OPAL_UID_LENGTH, > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPALUID[OPAL_HALF_UID_AUTHORITY_OBJ_REF], > + OPAL_UID_LENGTH_HALF, > + user_uid, OPAL_UID_LENGTH, > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPALUID[OPAL_HALF_UID_BOOLEAN_ACE], > + OPAL_UID_LENGTH_HALF, > + OPAL_TINY_UINT_01, > + OPAL_ENDNAME, > + > + OPAL_ENDLIST, > + OPAL_ENDNAME, > + OPAL_ENDLIST, > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + if (ret < 0) { > + pr_err("%s: Error building add user to locking range command.\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static int lock_unlock_locking_range(struct opal_dev *dev) > +{ > + u8 lr_buffer[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + const u8 *method; > + struct opal_lock_unlock *lkul; > + int ret; > + u8 read_locked = 1, write_locked = 1; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + method = OPALMETHOD[OPAL_SET]; > + lkul = dev->func_data[dev->state - 1]; > + if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) { > + pr_err("%s: Can't build locking range\n", dev->disk_name); > + return -EINVAL; > + } > + > + switch (lkul->l_state) { > + case OPAL_RO: > + read_locked = 0; > + write_locked = 1; > + break; > + case OPAL_RW: > + read_locked = 0; > + write_locked = 0; > + break; > + case OPAL_LK: > + /* vars are initalized to locked */ > + break; > + default: > + pr_err("Tried to set an invalid locking state... returning to uland\n"); > + return 1; > + } > + > + ret = test_and_add_token_va(cmd, "c2sc 3c 4c 4c 3c", > + OPAL_CALL, > + lr_buffer, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + OPAL_STARTLIST, > + > + OPAL_STARTNAME, > + OPAL_VALUES, > + OPAL_STARTLIST, > + > + OPAL_STARTNAME, > + OPAL_READLOCKED, > + read_locked, > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPAL_WRITELOCKED, > + write_locked, > + OPAL_ENDNAME, > + > + OPAL_ENDLIST, > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error building SET command.\n", dev->disk_name); > + return ret; > + } > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > + > +static int lock_unlock_locking_range_SUM(struct opal_dev *dev) > +{ > + u8 lr_buffer[OPAL_UID_LENGTH]; > + struct opal_cmd *cmd; > + const u8 *method; > + struct opal_lock_unlock *lkul; > + int ret; > + u8 read_locked = 1, write_locked = 1; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + method = OPALMETHOD[OPAL_SET]; > + lkul = dev->func_data[dev->state - 1]; > + if (build_locking_range(lr_buffer, sizeof(lr_buffer), dev->lr) < 0) { > + pr_err("%s: Can't build locking range\n", dev->disk_name); > + return -EINVAL; > + } > + > + switch (lkul->l_state) { > + case OPAL_RO: > + read_locked = 0; > + write_locked = 1; > + break; > + case OPAL_RW: > + read_locked = 0; > + write_locked = 0; > + break; > + case OPAL_LK: > + /* vars are initalized to locked */ > + break; > + default: > + pr_err("Tried to set an invalid locking state.\n"); > + return 1; > + } > + > + ret = test_and_add_token_va(cmd, "c2sc 3c 4c 4c 4c 4c 3c", > + OPAL_CALL, > + lr_buffer, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + OPAL_STARTLIST, > + > + OPAL_STARTNAME, > + OPAL_VALUES, > + OPAL_STARTLIST, > + > + OPAL_STARTNAME, > + OPAL_READLOCKENABLED, > + OPAL_TRUE, > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPAL_WRITELOCKENABLED, > + OPAL_TRUE, > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPAL_READLOCKED, > + read_locked, > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPAL_WRITELOCKED, > + write_locked, > + OPAL_ENDNAME, > + > + OPAL_ENDLIST, > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + if (ret < 0) { > + pr_err("%s: Error building SET command.\n", dev->disk_name); > + return ret; > + } > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +int activate_lsp(struct opal_dev *dev) > +{ > + u8 user_lr[OPAL_UID_LENGTH]; > + const u8 *method, *uid; > + struct opal_cmd *cmd; > + int ret; > + size_t uint_3 = 0x83; > + > + cmd = &dev->cmd; > + > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + uid = OPALUID[OPAL_LOCKINGSP_UID]; > + method = OPALMETHOD[OPAL_ACTIVATE]; > + > + ret = test_and_add_token_va(cmd, "c2s", > + OPAL_CALL, > + uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH); > + if (ret < 0) { > + pr_err("%s: Error building Activate LockingSP command.\n", > + dev->disk_name); > + return ret; > + } > + /* Activating as SUM */ > + if (dev->lr > 0) { > + ret = build_locking_range(user_lr, sizeof(user_lr), dev->lr); > + if (ret < 0) { > + pr_err("%s: Can't build locking user\n", > + dev->disk_name); > + return ret; > + } > + test_and_add_token_va(cmd, "2c 4c csc 2c", > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + > + uint_3, > + OPAL_TINY_UINT_06, > + OPAL_TINY_UINT_00, > + OPAL_TINY_UINT_00, > + > + OPAL_STARTLIST, > + user_lr, OPAL_UID_LENGTH, > + OPAL_ENDLIST, > + > + OPAL_ENDNAME, > + OPAL_ENDLIST); > + } else /* Actiave Normal Mode */ > + ret = test_and_add_token_va(cmd, "2c", > + OPAL_STARTLIST, > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error building Activate LockingSP command.\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, generic_cont); > +} > + > +static void get_lsp_lifecycle_cont(int error, void *data) > +{ > + > + struct opal_dev *dev = data; > + u8 lc_status; > + > + if (error) > + goto err_return; > + > + error = parse_and_check_status(dev); > + if (error) > + goto err_return; > + > + lc_status = response_get_u64(&dev->parsed, 4); > + /* 0x08 is Manufacured Inactive */ > + /* 0x09 is Manufactured */ > + if (lc_status != 0x08) { > + pr_err("%s: Couldn't determine the status of the Lifcycle state\n", > + dev->disk_name); > + error = -ENODEV; > + } > + > +err_return: > + if (dev->oper_cb) > + dev->oper_cb(error, dev); > +} > + > +/* Determine if we're in the Manufactured Inactive or Active state */ > +int get_lsp_lifecycle(struct opal_dev *dev) > +{ > + struct opal_cmd *cmd; > + const u8 *method, *uid; > + int ret; > + > + cmd = &dev->cmd; > + > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + uid = OPALUID[OPAL_LOCKINGSP_UID]; > + method = OPALMETHOD[OPAL_GET]; > + > + ret = test_and_add_token_va(cmd, "c2s 2c 4c 4c 2c", > + OPAL_CALL, > + uid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTLIST, > + > + OPAL_STARTNAME, > + OPAL_TINY_UINT_03, /* Start Column */ > + OPAL_TINY_UINT_06, /* Lifcycle Column */ > + OPAL_ENDNAME, > + > + OPAL_STARTNAME, > + OPAL_TINY_UINT_04, /* End Column */ > + OPAL_TINY_UINT_06, /* Lifecycle Column */ > + OPAL_ENDNAME, > + > + OPAL_ENDLIST, > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error Building GET Lifecycle Status command\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, get_lsp_lifecycle_cont); > +} > + > +static void get_msid_cpin_pin_cont(int error, void *data) > +{ > + const char *msid_pin; > + struct opal_dev *dev = data; > + size_t strlen; > + > + if (error) > + goto err_return; > + > + error = parse_and_check_status(dev); > + if (error) > + goto err_return; > + > + strlen = response_get_string(&dev->parsed, 4, &msid_pin); > + if (!msid_pin) { > + pr_err("%s: Couldn't extract PIN from response\n", __func__); > + error = 1; > + goto err_return; > + } > + > + dev->prev_data = kmemdup(msid_pin, strlen, GFP_KERNEL); > + if (!dev->prev_data) > + error = -ENOMEM; > + > + dev->prev_d_len = strlen; > + > + err_return: > + if (dev->oper_cb) > + dev->oper_cb(error, dev); > +} > + > +static int get_msid_cpin_pin(struct opal_dev *dev) > +{ > + const u8 *method, *smuid; > + int ret; > + struct opal_cmd *cmd; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + set_comID(cmd, dev->comID); > + > + smuid = OPALUID[OPAL_C_PIN_MSID]; > + method = OPALMETHOD[OPAL_GET]; > + > + ret = test_and_add_token_va(cmd, "c 2s 12c", > + OPAL_CALL, > + > + smuid, OPAL_UID_LENGTH, > + method, OPAL_METHOD_LENGTH, > + > + OPAL_STARTLIST, > + OPAL_STARTLIST, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_03, /* Sart Column */ > + OPAL_TINY_UINT_03, /* PIN */ > + OPAL_ENDNAME, > + OPAL_STARTNAME, > + OPAL_TINY_UINT_04, /* End Column */ > + OPAL_TINY_UINT_03, /* PIN */ > + OPAL_ENDNAME, > + OPAL_ENDLIST, > + OPAL_ENDLIST); > + > + if (ret < 0) { > + pr_err("%s: Error building Get MSID CPIN PIN command.\n", > + dev->disk_name); > + return ret; > + } > + > + return finalize_and_send(dev, cmd, get_msid_cpin_pin_cont); > +} > + > +static void unlock_suspend_final(int error, void *data) > +{ > + struct opal_dev *dev = data; > + > + dev->resume_from_suspend = false; > + dev->resume_data = NULL; > + dev->func_data = NULL; > + dev->bdev = NULL; > +} > + > +static int build_end_opal_session(struct opal_dev *dev) > +{ > + struct opal_cmd *cmd; > + > + cmd = &dev->cmd; > + clear_opal_cmd(cmd); > + > + set_comID(cmd, dev->comID); > + return test_and_add_token_u8(cmd, OPAL_ENDOFSESSION); > +} > + > +static int end_opal_session(struct opal_dev *dev) > +{ > + if (build_end_opal_session(dev) < 0) > + return -1; > + return finalize_and_send(dev, &dev->cmd, end_session_cont); > +} Any reason we cant: int ret = build_... if (ret < 0) return ret; > + > +static struct opal_dev *find_opal_dev(struct block_device *bdev, u8 lr) > +{ > + struct opal_dev *iter, *opal_dev = NULL; > + > + list_for_each_entry(iter, &opal_list, node) { > + if (strncmp(iter->disk_name, bdev->bd_disk->disk_name, > + DISK_NAME_LEN)) > + continue; > + if (iter->lr == lr) { > + opal_dev = iter; > + break; > + } > + } > + > + return opal_dev; > +} > + > +static int update_opal_dev(struct opal_dev *old_dev, struct opal_dev *new_dev) > +{ > + if (!atomic_add_unless(&old_dev->in_use, 1, 1)) { > + pr_err("%s: dev was in use\n", __func__); > + return -EBUSY; > + } > + > + old_dev->key_name_len = new_dev->key_name_len; > + if (!memcpy(old_dev->key_name, new_dev->key_name, old_dev->key_name_len)) { > + pr_err("%s: Error updating device:\n", old_dev->disk_name); > + return -EFAULT; > + } > + > + if (!strncpy(old_dev->disk_name, new_dev->disk_name, DISK_NAME_LEN)) { > + pr_err("%s: Error registering device: copying disk name\n", > + old_dev->disk_name); > + return -EFAULT; > + } > + > + old_dev->comID = new_dev->comID; > + old_dev->start = new_dev->start; > + old_dev->length = new_dev->length; > + old_dev->align = new_dev->align; > + old_dev->lowest_lba = new_dev->lowest_lba; > + old_dev->bdev = NULL; > + old_dev->final_cb = new_dev->final_cb; > + old_dev->final_cb_data = new_dev->final_cb_data; > + old_dev->oper_cb = new_dev->oper_cb; > + old_dev->state = new_dev->state; > + old_dev->funcs = new_dev->funcs; > + > + kfree(old_dev->completion); > + clean_function_data(old_dev); > + > + old_dev->completion = new_dev->completion; > + > + /* > + * Won't be able to auto unlock this locking range based on block > + * requestes. > + */ > + if (old_dev->length == 0) > + pr_warn("%s: Missing block information for locking range %d\n", > + old_dev->disk_name, old_dev->lr); > + > + return 0; > +} > + > +int opal_register_cont(struct opal_dev *new_dev) > +{ > + struct opal_dev *old_dev; > + unsigned long flags; > + int error = 0; > + > + spin_lock_irqsave(&list_spinlock, flags); > + > + old_dev = find_opal_dev(new_dev->bdev, new_dev->lr); > + if (!old_dev) { > + list_add_tail(&new_dev->node, &opal_list); > + old_dev = new_dev; > + } else { > + if (old_dev == new_dev) > + error = 0; > + else { > + error = update_opal_dev(old_dev, new_dev); > + clean_opal_key(new_dev); > + kfree(new_dev); > + } > + } > + > + if (error) > + list_del(&old_dev->node); > + > + spin_unlock_irqrestore(&list_spinlock, flags); > + > + if (!error) > + pr_info("%s: Registered key for locking range: %d\n", > + old_dev->disk_name, old_dev->lr); > + > + if (old_dev->oper_cb) > + old_dev->oper_cb(error, old_dev); > + > + return 0; > +} > + > +static void next(int error, struct opal_dev *dev) > +{ > + opal_step func = dev->funcs[dev->state]; > + void *cb_data = dev->final_cb_data; > + sec_cb *cb = dev->final_cb; > + bool done = false; > + > + > + if (error || !func) { > + done = true; > + goto next_exit; > + } > + dev->state++; > + dev->oper_cb = next; > + error = func(dev); > + next_exit: > + if (error) { > + pr_err("%s: Error on step function: %d with error %d: %s\n", > + dev->disk_name, dev->state, error, > + opal_error_to_human(error)); > + > + > + atomic_dec(&dev->in_use); > + if (dev->error_cb) { > + dev->error_cb(dev->error_cb_data); > + return; > + } > + if (cb) > + cb(error, cb_data); > + > + dev->completion->completion_status = error; > + complete(&dev->completion->cmd_completion); > + } else if (!error && done) { > + atomic_dec(&dev->in_use); > + if (cb) > + cb(error, cb_data); > + dev->completion->completion_status = error; > + complete(&dev->completion->cmd_completion); > + } > +} > + > +const opal_step error_end_session[] = { > + end_opal_session, > + NULL, > +}; > +static int end_opal_session_error(struct opal_dev *dev) > +{ > + > + dev->funcs = error_end_session; > + dev->state = 0; > + dev->error_cb = NULL; > + next(0, dev); > + return 0; > +} > + > +static struct opal_dev *alloc_opal_dev(struct block_device *bdev, u8 lr) > +{ > + struct opal_dev *opal_dev; > + struct request_queue *q; > + unsigned long dma_align; > + const char *disk_name; > + struct opal_cmd *cmd; > + int ret; > + > + opal_dev = kzalloc(sizeof(*opal_dev), GFP_KERNEL); > + if (!opal_dev) > + return ERR_PTR(-ENOMEM); > + > + opal_dev->bdev = bdev; > + opal_dev->lr = lr; > + cmd = &opal_dev->cmd; > + cmd->cmd = cmd->cmd_buf; > + cmd->resp = cmd->resp_buf; > + > + disk_name = bdev->bd_disk->disk_name; > + if (!strncpy(opal_dev->disk_name, disk_name, DISK_NAME_LEN)) { > + pr_err("%s: Error registering device: copying disk name\n", > + disk_name); > + ret = -EFAULT; > + goto err_free_dev; > + } > + > + q = bdev->bd_queue; > + dma_align = (queue_dma_alignment(q) | q->dma_pad_mask) + 1; > + cmd->cmd = (u8 *)round_up((uintptr_t)cmd->cmd, dma_align); > + cmd->resp = (u8 *)round_up((uintptr_t)cmd->resp, dma_align); > + > + INIT_LIST_HEAD(&opal_dev->node); > + atomic_set(&opal_dev->in_use, 1); > + > + opal_dev->completion = kzalloc(sizeof(*opal_dev->completion), > + GFP_KERNEL); > + > + if (!opal_dev->completion) > + goto err_free_dev; > + > + init_completion(&opal_dev->completion->cmd_completion); > + opal_dev->completion->completion_status = 0; > + opal_dev->state = 0; > + > + return opal_dev; > + > +err_free_dev: > + kfree(opal_dev); > + return ERR_PTR(ret); > +} > + > +int opal_register(struct block_device *bdev, struct opal_key *key_cmd, > + const opal_step *funcs) > +{ > + struct opal_dev *new_dev = NULL; > + u8 key_len = key_cmd->key_len; > + u8 lr = key_cmd->lr; > + struct opal_completion *completion; > + int ret; > + > + new_dev = alloc_opal_dev(bdev, lr); > + if (IS_ERR(new_dev)) { > + pr_err("%s: Error registering device: allocation\n", > + bdev->bd_disk->disk_name); > + return PTR_ERR(new_dev); > + } > + > + if (!memcpy(new_dev->key_name, key_cmd->key, key_len)) { > + pr_err("%s: Error registering key: couldn't copy key\n", > + new_dev->disk_name); > + return -EFAULT; > + } > + > + new_dev->key_name_len = key_len; > + new_dev->key_type = key_cmd->key_type; > + ret = get_opal_key(new_dev); > + if (ret) { > + pr_err("%s: Couldn't get key: %d\n", new_dev->disk_name, ret); > + return ret; > + } > + > + new_dev->funcs = funcs; > + > + new_dev->state = 0; > + completion = new_dev->completion; > + next(0, new_dev); > + > + return wait_for_cmd_completion(completion); > +} > + > +static struct opal_dev *get_registered_opal_dev(struct block_device *bdev, > + u8 lr) > +{ > + const char *diskname = bdev->bd_disk->disk_name; > + struct opal_dev *iter, *dev = NULL; > + unsigned long flags; > + bool in_use = false; > + > + spin_lock_irqsave(&list_spinlock, flags); > + list_for_each_entry(iter, &opal_list, node) { > + if (strncmp(iter->disk_name, diskname, DISK_NAME_LEN)) > + continue; > + if (iter->lr == lr) { > + dev = iter; > + if (!atomic_add_unless(&iter->in_use, 1, 1)) { > + dev = NULL; > + in_use = true; > + } > + break; > + } > + } > + > + spin_unlock_irqrestore(&list_spinlock, flags); > + > + if (!dev) > + return NULL; > + > + dev->bdev = bdev; > + return dev; > +} > + > +/* Free up the Opal dev and its keys during two scenarios: > + * > + * 1) When a command is complete that no longer requires > + * the opal dev to be around. > + * 2) When a command, including Opal Save fails we clean > + * and free the opal dev. > + * > + * If we find the opal dev structure in the list of > + * saved passwords we will *not* remove it. > + */ > +static void remove_and_clean_opal_dev(struct opal_dev *dev) > +{ > + struct opal_dev *iter; > + bool found = false; > + > + spin_lock(&list_spinlock); > + list_for_each_entry(iter, &opal_list, node) { > + if (iter == dev) { > + found = true; > + break; > + } > + } > + > + spin_unlock(&list_spinlock); > + if (!found) { > + clean_opal_key(dev); > + clean_function_data(dev); > + kfree(dev); > + } > +} > + > +static struct opal_dev *get_or_create_opal_dev(struct block_device *bdev, > + u8 lr, bool use_new) > +{ > + struct opal_dev *dev; > + > + if (use_new) > + return alloc_opal_dev(bdev, lr); > + > + dev = get_registered_opal_dev(bdev, lr); > + if (!dev) { > + dev = alloc_opal_dev(bdev, lr); > + if (!dev) > + return NULL; No need for this check when you already return dev > + } > + return dev; > +} Instead, how about: static struct opal_dev *get_or_create_opal_dev(struct block_device *bdev, u8 lr, bool use_new) { struct opal_dev *dev = NULL; if (!use_new) dev = get_registered_opal_dev(bdev, lr); if (!dev) dev = alloc_opal_dev(bdev, lr); return dev; } > + > +static struct opal_completion *setup_opal_dev(struct block_device *bdev, > + struct opal_dev *dev, > + const opal_step *funcs, > + struct opal_key *key) > +{ > + int ret; > + > + dev->bdev = bdev; > + dev->state = 0; > + dev->funcs = funcs; > + dev->TSN = 0; > + dev->HSN = 0; > + dev->final_cb = NULL; > + dev->final_cb_data = NULL; > + dev->lr = key->lr; > + dev->error_cb = end_opal_session_error; > + dev->error_cb_data = dev; > + > + if (key) { > + memcpy(dev->key_name, key->key, key->key_len); > + dev->key_name_len = key->key_len; > + dev->key_type = key->key_type; > + > + ret = get_opal_key(dev); > + if (ret) { > + kfree(dev->completion); > + pr_err("%s: Couldn't get key: %d\n", > + dev->disk_name, ret); > + return ERR_PTR(ret); > + } > + } > + dev->func_data = NULL; > + dev->completion->completion_status = 0; > + > + return dev->completion; > +} > + > +static int internal_setup_lr(struct block_device *bdev, > + struct opal_user_lr_setup *setup) > +{ > + struct opal_dev *dev; > + struct opal_completion *completion; > + void *data[3] = { NULL }; > + const opal_step lr_funcs[] = { > + opal_discovery0, > + start_auth_opal_session, > + setup_locking_range, > + get_active_key, > + gen_key, > + end_opal_session, > + NULL, > + }; > + int ret; > + > + dev = get_or_create_opal_dev(bdev, setup->key.lr, true); > + if (!dev) > + return -ENOMEM; > + > + completion = setup_opal_dev(bdev, dev, lr_funcs, &setup->key); > + if (IS_ERR(completion)) { > + ret = PTR_ERR(completion); > + goto error_return; > + } > + > + dev->func_data = data; > + dev->num_func_data = 3; > + dev->func_data[1] = &setup->who; > + dev->func_data[2] = setup; > + > + next(0, dev); > + ret = wait_for_cmd_completion(completion); > + > + error_return: > + remove_and_clean_opal_dev(dev); > + return ret; > +} > + > +int opal_revert(struct block_device *bdev, struct opal_key *key) > +{ > + const opal_step revert_funcs[] = { > + opal_discovery0, > + start_SIDASP_opal_session, > + revert_tper, /* controller will terminate session */ > + NULL, > + }; > + > + return opal_register(bdev, key, revert_funcs); > +} > + > +int activate_user(struct block_device *bdev, struct opal_activate_user *act) > +{ > + const opal_step act_funcs[] = { > + opal_discovery0, > + start_admin1LSP_opal_session, > + internal_activate_user, > + end_opal_session, > + NULL > + }; > + struct opal_dev *dev; > + struct opal_completion *completion; > + void *data[3] = { NULL }; > + int ret; > + > + dev = get_or_create_opal_dev(bdev, act->key.lr, true); > + if (!dev) > + return -ENOMEM; > + > + completion = setup_opal_dev(bdev, dev, act_funcs, &act->key); > + if (IS_ERR(completion)) { > + ret = PTR_ERR(completion); > + goto error_return; > + } > + > + dev->num_func_data = 3; > + dev->func_data = data; > + dev->func_data[1] = act; > + dev->func_data[2] = act; > + > + next(0, dev); > + ret = wait_for_cmd_completion(completion); > + > + error_return: > + remove_and_clean_opal_dev(dev); > + return ret; > +} > + > +int opal_set_pw(struct block_device *bdev, struct opal_new_pw *pw) > + > +{ > + const opal_step pw_funcs[] = { > + opal_discovery0, > + start_auth_opal_session, > + set_new_pw, > + end_opal_session, > + NULL > + }; > + struct opal_dev *dev; > + struct opal_completion *completion; > + void *data[3] = { NULL }; > + int ret; > + > + dev = get_or_create_opal_dev(bdev, pw->current_pin.lr, true); > + if (!dev) > + return -ENOMEM; > + > + completion = setup_opal_dev(bdev, dev, pw_funcs, &pw->current_pin); > + if (IS_ERR(completion)) { > + ret = PTR_ERR(completion); > + goto error_return; > + } > + > + dev->num_func_data = 3; > + dev->func_data = data; > + dev->func_data[1] = (void *) &pw->who; > + dev->func_data[2] = (void *) pw; > + > + next(0, dev); > + ret = wait_for_cmd_completion(completion); > + > + error_return: > + remove_and_clean_opal_dev(dev); > + return ret; > +} > + > +int opal_act_lsp_int(struct block_device *bdev, struct opal_key *key, > + const opal_step *funcs) > +{ > + struct opal_dev *dev; > + struct opal_completion *completion; > + int ret; > + > + dev = get_or_create_opal_dev(bdev, key->lr, true); > + if (!dev) > + return -ENOMEM; > + completion = setup_opal_dev(bdev, dev, funcs, key); > + if (IS_ERR(completion)) { > + ret = PTR_ERR(completion); > + goto error_return; > + } > + > + next(0, dev); > + ret = wait_for_cmd_completion(completion); > + > + error_return: > + remove_and_clean_opal_dev(dev); > + return ret; > +} > + > + > +static int opal_save_internal(struct block_device *bdev, > + struct opal_lock_unlock *lk) > +{ > + void *func_data[3] = { NULL }; > + struct opal_dev *dev; > + struct opal_completion *completion; > + const opal_step _auth_funcs[] = { > + opal_discovery0, > + start_auth_opal_session, > + query_locking_range, > + end_opal_session, > + opal_register_cont, > + NULL > + }; > + int ret; > + > + dev = get_or_create_opal_dev(bdev, lk->key.lr, false); > + if (!dev) > + return -ENOMEM; > + completion = setup_opal_dev(bdev, dev, _auth_funcs, &lk->key); > + if (IS_ERR(completion)) { > + ret = PTR_ERR(completion); > + goto error_return; > + } > + > + dev->num_func_data = 3; > + dev->func_data = func_data; > + dev->func_data[1] = &lk->authority; > + dev->lkul = *lk; > + > + next(0, dev); > + ret = wait_for_cmd_completion(completion); > + > + error_return: > + remove_and_clean_opal_dev(dev); > + return ret; > +} > + > +static int add_user_lr_internal(struct block_device *bdev, > + struct opal_lock_unlock *lk) > +{ > + void *func_data[3] = { NULL }; > + struct opal_dev *dev; > + struct opal_completion *completion; > + const opal_step funcs[] = { > + opal_discovery0, > + start_admin1LSP_opal_session, > + add_user_to_lr, > + end_opal_session, > + NULL > + }; > + int ret; > + > + dev = get_or_create_opal_dev(bdev, lk->key.lr, true); > + if (!dev) > + return -ENOMEM; > + completion = setup_opal_dev(bdev, dev, funcs, &lk->key); > + if (IS_ERR(completion)) { > + ret = PTR_ERR(completion); > + goto error_return; > + } > + > + dev->num_func_data = 3; > + dev->func_data = func_data; > + dev->func_data[2] = lk; > + > + next(0, dev); > + ret = wait_for_cmd_completion(completion); > + > + error_return: > + remove_and_clean_opal_dev(dev); > + return ret; > +} > + > +static int lock_unlock_internal(struct block_device *bdev, > + struct opal_lock_unlock *lk) > +{ > + void *func_data[3] = { NULL }; > + struct opal_dev *dev; > + struct opal_completion *completion; > + > + const opal_step ulk_funcs_SUM[] = { > + opal_discovery0, > + start_auth_opal_session, > + lock_unlock_locking_range_SUM, > + end_opal_session, > + NULL > + }; > + const opal_step _unlock_funcs[] = { > + opal_discovery0, > + start_auth_opal_session, > + lock_unlock_locking_range, > + end_opal_session, > + NULL > + }; > + int ret; > + > + dev = get_or_create_opal_dev(bdev, lk->key.lr, true); > + if (!dev) > + return -ENOMEM; > + > + if (lk->authority.SUM) > + completion = setup_opal_dev(bdev, dev, ulk_funcs_SUM, &lk->key); > + else > + completion = setup_opal_dev(bdev, dev, _unlock_funcs, &lk->key); > + > + if (IS_ERR(completion)) { > + ret = PTR_ERR(completion); > + goto error_return; > + } > + > + dev->num_func_data = 3; > + dev->func_data = func_data; > + dev->func_data[1] = &lk->authority; > + dev->func_data[2] = lk; > + > + next(0, dev); > + ret = wait_for_cmd_completion(completion); > + > + error_return: > + remove_and_clean_opal_dev(dev); > + return ret; > +} > + > +int opal_erase_locking_range(struct block_device *bdev, struct sed_key *key) > +{ > + struct opal_dev *dev; > + struct opal_completion *completion; > + struct opal_key k; > + int ret; > + const opal_step erase_funcs[] = { > + opal_discovery0, > + start_admin1LSP_opal_session, > + erase_locking_range, > + end_opal_session, > + NULL, > + }; > + > + if (!bdev || !bdev->bd_disk) { > + pr_err("Can't save password for NULL block device.\n"); > + return -EINVAL; > + } > + > + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) > + return -EFAULT; > + > + dev = get_or_create_opal_dev(bdev, k.lr, true); > + if (!dev) > + return -ENOMEM; > + > + completion = setup_opal_dev(bdev, dev, erase_funcs, &k); > + if (IS_ERR(completion)) { > + ret = PTR_ERR(completion); > + goto error_return; > + } > + > + next(0, dev); > + ret = wait_for_cmd_completion(completion); > + > + error_return: > + remove_and_clean_opal_dev(dev); > + return ret; > +} > +EXPORT_SYMBOL(opal_erase_locking_range); > + > +int opal_enable_disable_shadow_mbr(struct block_device *bdev, > + struct sed_key *key) > +{ > + void *func_data[6] = { NULL }; > + struct opal_mbr_data mbr; > + struct opal_dev *dev; > + struct opal_completion *completion; > + const opal_step mbr_funcs[] = { > + opal_discovery0, > + start_admin1LSP_opal_session, > + set_mbr_done, > + end_opal_session, > + start_admin1LSP_opal_session, > + set_mbr_enable_disable, > + end_opal_session, > + NULL, > + }; > + int ret; > + > + if (!bdev || !bdev->bd_disk) { > + pr_err("Can't save password for NULL block device.\n"); > + return -EINVAL; > + } > + > + if (copy_from_user(&mbr, key->opal_mbr, sizeof(*key->opal_mbr))) > + return -EFAULT; > + > + if (mbr.enable_disable != OPAL_MBR_ENABLE && > + mbr.enable_disable != OPAL_MBR_DISABLE) > + return -EINVAL; > + > + dev = get_or_create_opal_dev(bdev, mbr.key.lr, true); > + if (!dev) > + return -ENOMEM; > + > + completion = setup_opal_dev(bdev, dev, mbr_funcs, &mbr.key); > + if (IS_ERR(completion)) { > + ret = PTR_ERR(completion); > + goto error_return; > + } > + > + dev->num_func_data = 6; > + dev->func_data = func_data; > + dev->func_data[2] = &mbr.enable_disable; > + dev->func_data[5] = &mbr.enable_disable; > + > + next(0, dev); > + ret = wait_for_cmd_completion(completion); > + > + error_return: > + remove_and_clean_opal_dev(dev); > + return ret; > + > +} > +EXPORT_SYMBOL(opal_enable_disable_shadow_mbr); > + > +int opal_save(struct block_device *bdev, struct sed_key *key) > +{ > + struct opal_lock_unlock lkul; > + > + if (!bdev || !bdev->bd_disk) { > + pr_err("Can't save password for NULL block device.\n"); > + return -EINVAL; > + } > + > + if (copy_from_user(&lkul, key->opal_lk_unlk, sizeof(*key->opal))) > + return -EFAULT; > + > + return opal_save_internal(bdev, &lkul); > +} > +EXPORT_SYMBOL(opal_save); > + > +int opal_add_user_to_lr(struct block_device *bdev, struct sed_key *key) > +{ > + struct opal_lock_unlock lkul; > + > + if (copy_from_user(&lkul, key->opal_lk_unlk, sizeof(lkul))) > + return -EFAULT; > + > + if (!bdev || !bdev->bd_disk) { > + pr_err("Can't assign user to LR without backing disk\n"); > + return -EFAULT; > + } > + if (lkul.l_state != OPAL_RO && lkul.l_state != OPAL_RW) { > + pr_err("Locking state was not RO or RW\n"); > + return -EINVAL; > + } > + if (lkul.authority.who < OPAL_USER1 && > + lkul.authority.who > OPAL_USER9) { > + pr_err("Authority was not within the range of users: %d\n", > + lkul.authority.who); > + return -EINVAL; > + } > + if (lkul.authority.SUM) { > + pr_err("%s not supported in SUM. Use setup locking range\n", > + __func__); > + return -EINVAL; > + } > + > + return add_user_lr_internal(bdev, &lkul); > +} > +EXPORT_SYMBOL(opal_add_user_to_lr); > + > +int opal_reverttper(struct block_device *bdev, struct sed_key *key) > +{ > + struct opal_key k; > + > + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) > + return -EFAULT; > + > + return opal_revert(bdev, &k); > +} > +EXPORT_SYMBOL(opal_reverttper); > + > +int opal_lock_unlock(struct block_device *bdev, struct sed_key *key) > +{ > + struct opal_lock_unlock k; > + > + if (copy_from_user(&k, key->opal_lk_unlk, sizeof(*key->opal_lk_unlk))) > + return -EFAULT; > + > + if (k.authority.who < OPAL_ADMIN1 || k.authority.who >= OPAL_USER9) Should this be > OPAL_USER9 ? > + return -EINVAL; > + > + return lock_unlock_internal(bdev, &k); > +} > +EXPORT_SYMBOL(opal_lock_unlock); > + > +int opal_take_ownership(struct block_device *bdev, struct sed_key *key) > +{ > + struct opal_key k; > + const opal_step owner_funcs[] = { > + opal_discovery0, > + start_anybodyASP_opal_session, > + get_msid_cpin_pin, > + end_opal_session, > + start_SIDASP_opal_session, > + set_sid_cpin_pin, > + end_opal_session, > + NULL > + }; > + > + if (!bdev || !bdev->bd_disk) { > + pr_err("Can't save password for NULL block device.\n"); > + return -EINVAL; > + } > + > + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) > + return -EFAULT; > + > + return opal_register(bdev, &k, owner_funcs); > +} > +EXPORT_SYMBOL(opal_take_ownership); > + > +int opal_activate_lsp(struct block_device *bdev, struct sed_key *key) > +{ > + struct opal_key k; > + const opal_step active_funcs[] = { > + opal_discovery0, > + start_SIDASP_opal_session, /* Open session as SID auth */ > + get_lsp_lifecycle, > + activate_lsp, > + end_opal_session, > + NULL > + }; > + > + if (!bdev || !bdev->bd_disk) { > + pr_err("Can't save password for NULL block device.\n"); > + return -EINVAL; > + } > + > + if (copy_from_user(&k, key->opal, sizeof(*key->opal))) > + return -EFAULT; > + > + return opal_act_lsp_int(bdev, &k, active_funcs); > +} > +EXPORT_SYMBOL(opal_activate_lsp); > + > +int opal_setup_locking_range(struct block_device *bdev, struct sed_key *pw) > +{ > + struct opal_user_lr_setup k; > + > + if (!bdev || !bdev->bd_disk) { > + pr_err("Can't save password for NULL block device.\n"); > + return -EINVAL; > + } > + > + if (copy_from_user(&k, pw->opal_lrs, sizeof(*pw->opal_lrs))) > + return -EFAULT; > + > + return internal_setup_lr(bdev, &k); > +} > + > +int opal_set_new_pw(struct block_device *bdev, struct sed_key *pw) > +{ > + struct opal_new_pw k; > + > + if (pw->sed_type != OPAL_PW) > + return -EINVAL; > + > + if (copy_from_user(&k, pw->opal_pw, sizeof(*pw->opal_pw))) > + return -EFAULT; > + > + if (k.who.who < OPAL_ADMIN1 || k.who.who > OPAL_USER9) > + return -EINVAL; > + > + return opal_set_pw(bdev, &k); > +} > +EXPORT_SYMBOL(opal_set_new_pw); > + > +int opal_activate_user(struct block_device *bdev, struct sed_key *pw) > +{ > + struct opal_activate_user k; > + > + if (pw->sed_type != OPAL_ACT_USR) { > + pr_err("Sed type was not act user\n"); > + return -EINVAL; > + } > + > + if (copy_from_user(&k, pw->opal_act, sizeof(*pw->opal_act))) { > + pr_err("copy from user error\n"); > + return -EFAULT; > + } > + > + /* We can't activate Admin1 it's active as manufactured */ > + if (k.who.who < OPAL_USER1 && k.who.who > OPAL_USER9) { > + pr_err("Who was not a valid user: %d \n", k.who.who); > + return -EINVAL; > + } > + > + return activate_user(bdev, &k); > + > +} > +EXPORT_SYMBOL(opal_activate_user); > + > +int opal_unlock_from_suspend(struct opal_suspend_unlk *data) > +{ > + const char *diskname = data->name; > + struct opal_dev *iter, *dev = NULL; > + struct opal_completion *completion; > + void *func_data[3] = { NULL }; > + const opal_step _unlock_funcs_SUM[] = { > + opal_discovery0, > + start_auth_opal_session, > + lock_unlock_locking_range, Did you mean to use lock_unlock_locking_range_SUM ? Can we pull these two arrays out since they are required for both this function and lock_unlock_internal ? > + end_opal_session, > + NULL > + }; > + const opal_step _unlock_funcs[] = { > + opal_discovery0, > + start_auth_opal_session, > + lock_unlock_locking_range, > + end_opal_session, > + NULL > + }; > + > + > + spin_lock(&list_spinlock); > + list_for_each_entry(iter, &opal_list, node) { > + if (strncmp(iter->disk_name, diskname, DISK_NAME_LEN)) { > + pr_err("iterdisk was %s and diskname is %s\n", > + iter->disk_name, diskname); > + continue; > + } > + if (atomic_add_unless(&iter->in_use, 1, 1)) { > + dev = iter; > + dev->func_data = func_data; > + dev->resume_from_suspend = true; > + dev->resume_data = data; > + dev->final_cb = unlock_suspend_final; > + dev->final_cb_data = dev; > + dev->error_cb = end_opal_session_error; > + dev->error_cb_data = dev; > + dev->state = 0; > + if (dev->lkul.authority.SUM) > + dev->funcs = _unlock_funcs_SUM; > + else > + dev->funcs = _unlock_funcs; > + dev->TSN = 0; > + dev->HSN = 0; > + dev->func_data[2] = &dev->lkul; > + dev->func_data[1] = &dev->lkul.authority; > + completion = dev->completion; > + next(0, dev); > + wait_for_cmd_completion(completion); > + } > + } > + spin_unlock(&list_spinlock); > + > + if (!dev) > + return -ENODEV; > + return 0; > +} > +EXPORT_SYMBOL(opal_unlock_from_suspend); > diff --git a/lib/sed-opal_internal.h b/lib/sed-opal_internal.h > new file mode 100644 > index 0000000..c9d3883 > --- /dev/null > +++ b/lib/sed-opal_internal.h > @@ -0,0 +1,586 @@ > +/* > + * Copyright ? 2016 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + * > + * Author: > + * Rafael Antognolli <rafael.antognolli at intel.com> > + * Scott Bauer <scott.bauer at intel.com> > + */ > + > +#ifndef _NVME_OPAL_INTERNAL_H > +#define _NVME_OPAL_INTERNAL_H > + > +#include <linux/key-type.h> > +#include <keys/user-type.h> > + > +#define DTAERROR_NO_METHOD_STATUS 0x89 > + > +static const char *opal_errors[19] = { Remove the 19 so it's just opal_errors[] (doesnt silently truncate any new additions) > + "Success", > + "Not Authorized", > + "Unknown Error", > + "SP Busy", > + "SP Failed", > + "SP Disabled", > + "SP Frozen", > + "No Sessions Available", > + "Uniqueness Conflict", > + "Insufficient Space", > + "Insufficient Rows", > + "Invalid Function", > + "Invalid Parameter", > + "Invalid Reference", > + "Unknown Error", > + "TPER Malfunction", > + "Transaction Failure", > + "Response Overflow", > + "Authority Locked Out", > +}; > + > +static const char *opal_error_to_human(int error) > +{ > + if (error == 0x3f) > + return "Failed"; > + > + if (error >= sizeof(opal_errors) || error < 0) You want sizeof(opal_errors)/sizeof(*opal_errors) here, but you can just use the ARRAY_SIZE macro instead > + return "Unknown Error"; > + > + return opal_errors[error]; > +} > + > +/* User IDs used in the TCG storage SSCs */ > +static const u8 OPALUID[][8] = { > + /* users */ > + > + /* session management */ > + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, > + /* special "thisSP" syntax */ > + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, > + /* Administrative SP */ > + { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 }, > + /* Locking SP */ > + { 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 }, > + /* ENTERPRISE Locking SP */ > + { 0x00, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, 0x01 }, > + /* anybody */ > + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 }, > + /* SID */ > + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 }, > + /* ADMIN1 */ > + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 }, > + /* USER1 */ > + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 }, > + /* USER2 */ > + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 }, > + /* PSID user */ > + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 }, > + /* BandMaster 0 */ > + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x01 }, > + /* EraseMaster */ > + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x84, 0x01 }, > + > + /* tables */ > + > + /* Locking_GlobalRange */ > + { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 }, > + /* ACE_Locking_Range_Set_RdLocked UID */ > + { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x01 }, > + /* ACE_Locking_Range_Set_WrLocked UID */ > + { 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x01 }, > + /* MBR Control */ > + { 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01 }, > + /* Shadow MBR */ > + { 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 }, > + /* AUTHORITY_TABLE */ > + { 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00}, > + /* C_PIN_TABLE */ > + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00}, > + /* OPAL Locking Info */ > + { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 }, > + /* Enterprise Locking Info */ > + { 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 }, > + > + /* C_PIN_TABLE object ID's */ > + > + /* C_PIN_MSID */ > + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02}, > + /* C_PIN_SID */ > + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01}, > + /* C_PIN_ADMIN1 */ > + { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01}, > + > + /* half UID's (only first 4 bytes used) */ > + > + /* Half-UID ? Authority_object_ref */ > + { 0x00, 0x00, 0x0C, 0x05, 0xff, 0xff, 0xff, 0xff }, > + /* Half-UID ? Boolean ACE */ > + { 0x00, 0x00, 0x04, 0x0E, 0xff, 0xff, 0xff, 0xff }, > + > + /* special value for omitted optional parameter */ > + > + /* HEXFF for omitted */ > + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, > +}; > +static const size_t OPAL_UID_LENGTH = 8; > +static const size_t OPAL_MSID_KEYLEN = 15; > +static const size_t OPAL_UID_LENGTH_HALF = 4; > + > + > +/* Enum to index OPALUID array */ > +enum OPAL_UID { > + /* users */ > + OPAL_SMUID_UID, > + OPAL_THISSP_UID, > + OPAL_ADMINSP_UID, > + OPAL_LOCKINGSP_UID, > + OPAL_ENTERPRISE_LOCKINGSP_UID, > + OPAL_ANYBODY_UID, > + OPAL_SID_UID, > + OPAL_ADMIN1_UID, > + OPAL_USER1_UID, > + OPAL_USER2_UID, > + OPAL_PSID_UID, > + OPAL_ENTERPRISE_BANDMASTER0_UID, > + OPAL_ENTERPRISE_ERASEMASTER_UID, > + /* tables */ > + OPAL_LOCKINGRANGE_GLOBAL, > + OPAL_LOCKINGRANGE_ACE_RDLOCKED, > + OPAL_LOCKINGRANGE_ACE_WRLOCKED, > + OPAL_MBRCONTROL, > + OPAL_MBR, > + OPAL_AUTHORITY_TABLE, > + OPAL_C_PIN_TABLE, > + OPAL_LOCKING_INFO_TABLE, > + OPAL_ENTERPRISE_LOCKING_INFO_TABLE, > + /* C_PIN_TABLE object ID's */ > + OPAL_C_PIN_MSID, > + OPAL_C_PIN_SID, > + OPAL_C_PIN_ADMIN1, > + /* half UID's (only first 4 bytes used) */ > + OPAL_HALF_UID_AUTHORITY_OBJ_REF, > + OPAL_HALF_UID_BOOLEAN_ACE, > + /* omitted optional parameter */ > + OPAL_UID_HEXFF, > +}; > + > +/* > + * TCG Storage SSC Methods. > + */ > +static const u8 OPALMETHOD[][8] = { > + /* Properties */ > + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01 }, > + /* STARTSESSION */ > + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02 }, > + /* Revert */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02 }, > + /* Activate */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03 }, > + /* Enterprise Get */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06 }, > + /* Enterprise Set */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07 }, > + /* NEXT */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08 }, > + /* Enterprise Authenticate */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c }, > + /* GetACL */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d }, > + /* GenKey */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10 }, > + /* revertSP */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11 }, > + /* Get */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16 }, > + /* Set */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17 }, > + /* Authenticate */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c }, > + /* Random */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 }, > + /* Erase */ > + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 }, > +}; > +static const size_t OPAL_METHOD_LENGTH = 8; > + > +/* Enum for indexing the OPALMETHOD array */ > +enum OPAL_METHOD { > + OPAL_PROPERTIES, > + OPAL_STARTSESSION, > + OPAL_REVERT, > + OPAL_ACTIVATE, > + OPAL_EGET, > + OPAL_ESET, > + OPAL_NEXT, > + OPAL_EAUTHENTICATE, > + OPAL_GETACL, > + OPAL_GENKEY, > + OPAL_REVERTSP, > + OPAL_GET, > + OPAL_SET, > + OPAL_AUTHENTICATE, > + OPAL_RANDOM, > + OPAL_ERASE, > +}; > + > +enum OPAL_RESPONSE_TOKEN { > + OPAL_DTA_TOKENID_BYTESTRING = 0xe0, > + OPAL_DTA_TOKENID_SINT = 0xe1, > + OPAL_DTA_TOKENID_UINT = 0xe2, > + OPAL_DTA_TOKENID_TOKEN = 0xe3, /* actual token is returned */ > + OPAL_DTA_TOKENID_INVALID = 0X0 > +}; > + > +enum OPAL_TOKEN { > + /* Boolean */ > + OPAL_TRUE = 0x01, > + OPAL_FALSE = 0x00, > + OPAL_BOOLEAN_EXPR = 0x03, > + /* cellblocks */ > + OPAL_TABLE = 0x00, > + OPAL_STARTROW = 0x01, > + OPAL_ENDROW = 0x02, > + OPAL_STARTCOLUMN = 0x03, > + OPAL_ENDCOLUMN = 0x04, > + OPAL_VALUES = 0x01, > + /* authority table */ > + OPAL_PIN = 0x03, > + /* locking tokens */ > + OPAL_RANGESTART = 0x03, > + OPAL_RANGELENGTH = 0x04, > + OPAL_READLOCKENABLED = 0x05, > + OPAL_WRITELOCKENABLED = 0x06, > + OPAL_READLOCKED = 0x07, > + OPAL_WRITELOCKED = 0x08, > + OPAL_ACTIVEKEY = 0x0A, > + /* locking info table */ > + OPAL_MAXRANGES = 0x04, > + /* mbr control */ > + OPAL_MBRENABLE = 0x01, > + OPAL_MBRDONE = 0x02, > + /* properties */ > + OPAL_HOSTPROPERTIES = 0x00, > + /* atoms */ > + OPAL_STARTLIST = 0xf0, > + OPAL_ENDLIST = 0xf1, > + OPAL_STARTNAME = 0xf2, > + OPAL_ENDNAME = 0xf3, > + OPAL_CALL = 0xf8, > + OPAL_ENDOFDATA = 0xf9, > + OPAL_ENDOFSESSION = 0xfa, > + OPAL_STARTTRANSACTON = 0xfb, > + OPAL_ENDTRANSACTON = 0xfC, > + OPAL_EMPTYATOM = 0xff, > + OPAL_WHERE = 0x00, > +}; > + > +/* Useful tiny atoms. > + * Useful for table columns etc > + */ > +enum OPAL_TINY_ATOM { > + OPAL_TINY_UINT_00 = 0x00, > + OPAL_TINY_UINT_01 = 0x01, > + OPAL_TINY_UINT_02 = 0x02, > + OPAL_TINY_UINT_03 = 0x03, > + OPAL_TINY_UINT_04 = 0x04, > + OPAL_TINY_UINT_05 = 0x05, > + OPAL_TINY_UINT_06 = 0x06, > + OPAL_TINY_UINT_07 = 0x07, > + OPAL_TINY_UINT_08 = 0x08, > + OPAL_TINY_UINT_09 = 0x09, > + OPAL_TINY_UINT_10 = 0x0a, > + OPAL_TINY_UINT_11 = 0x0b, > + OPAL_TINY_UINT_12 = 0x0c, > + OPAL_TINY_UINT_13 = 0x0d, > + OPAL_TINY_UINT_14 = 0x0e, > + OPAL_TINY_UINT_15 = 0x0f, > +}; > + > +enum OPAL_ATOM_WIDTH { > + OPAL_WIDTH_TINY, > + OPAL_WIDTH_SHORT, > + OPAL_WIDTH_MEDIUM, > + OPAL_WIDTH_LONG, > + OPAL_WIDTH_TOKEN > +}; > + > +/* Locking state for a locking range */ > +enum OPAL_LOCKINGSTATE { > + OPAL_LOCKING_READWRITE = 0x01, > + OPAL_LOCKING_READONLY = 0x02, > + OPAL_LOCKING_LOCKED = 0x03, > +}; > + > +/* > + * Structures to build and decode the Opal SSC messages > + * fields that are NOT really numeric are defined as u8[] to > + * help reduce the endianness issues > + */ > + > +/* Comm Packet (header) for transmissions. */ > +struct opal_compacket { > + u32 reserved0; > + u8 extendedComID[4]; > + u32 outstandingData; > + u32 minTransfer; > + u32 length; > +}; > + > +/* Packet structure. */ > +struct opal_packet { > + u32 TSN; > + u32 HSN; > + u32 seq_number; > + u16 reserved0; > + u16 ack_type; > + u32 acknowledgment; > + u32 length; > +}; > + > +/* Data sub packet header */ > +struct opal_data_subpacket { > + u8 reserved0[6]; > + u16 kind; > + u32 length; > +}; > + > +/* header of a response */ > +struct opal_header { > + struct opal_compacket cp; > + struct opal_packet pkt; > + struct opal_data_subpacket subpkt; > +}; > + > +#define FC_TPER 0x0001 > +#define FC_LOCKING 0x0002 > +#define FC_GEOMETRY 0x0003 > +#define FC_ENTERPRISE 0x0100 > +#define FC_DATASTORE 0x0202 > +#define FC_SINGLEUSER 0x0201 > +#define FC_OPALV100 0x0200 > +#define FC_OPALV200 0x0203 > + > +/* > + * The Discovery 0 Header. As defined in > + * Opal SSC Documentation > + */ > +struct d0_header { > + u32 length; /* the length of the header 48 in 2.00.100 */ > + u32 revision; /**< revision of the header 1 in 2.00.100 */ > + u32 reserved01; > + u32 reserved02; > + /* > + * the remainder of the structure is vendor specific and will not be > + * addressed now > + */ > + u8 ignored[32]; > +}; > + > +/* > + * TPer Feature Descriptor. Contains flags indicating support for the > + * TPer features described in the OPAL specification. The names match the > + * OPAL terminology > + * > + * code == 0x001 in 2.00.100 > + */ > +struct d0_tper_features { > + /* > + * supported_features bits: > + * bit 7: reserved > + * bit 6: com ID management > + * bit 5: reserved > + * bit 4: streaming support > + * bit 3: buffer management > + * bit 2: ACK/NACK > + * bit 1: async > + * bit 0: sync > + */ > + u8 supported_features; > + /* > + * bytes 5 through 15 are reserved, but we represent the first 3 as > + * u8 to keep the other two 32bits integers aligned. > + */ > + u8 reserved01[3]; > + u32 reserved02; > + u32 reserved03; > +}; > + > +/* > + * Locking Feature Descriptor. Contains flags indicating support for the > + * locking features described in the OPAL specification. The names match the > + * OPAL terminology > + * > + * code == 0x0002 in 2.00.100 > + */ > +struct d0_locking_features { > + /* > + * supported_features bits: > + * bits 6-7: reserved > + * bit 5: MBR done > + * bit 4: MBR enabled > + * bit 3: media encryption > + * bit 2: locked > + * bit 1: locking enabled > + * bit 0: locking supported > + */ > + u8 supported_features; > + /* > + * bytes 5 through 15 are reserved, but we represent the first 3 as > + * u8 to keep the other two 32bits integers aligned. > + */ > + u8 reserved01[3]; > + u32 reserved02; > + u32 reserved03; > +}; > + > +/* > + * Geometry Feature Descriptor. Contains flags indicating support for the > + * geometry features described in the OPAL specification. The names match the > + * OPAL terminology > + * > + * code == 0x0003 in 2.00.100 > + */ > +struct d0_geometry_features { > + /* > + * skip 32 bits from header, needed to align the struct to 64 bits. > + */ > + u8 header[4]; > + /* > + * reserved01: > + * bits 1-6: reserved > + * bit 0: align > + */ > + u8 reserved01; > + u8 reserved02[7]; > + u32 logical_block_size; > + u64 alignment_granularity; > + u64 lowest_aligned_lba; > +}; > + > +/* > + * Enterprise SSC Feature > + * > + * code == 0x0100 > + */ > +struct d0_enterprise_ssc { > + u16 baseComID; > + u16 numComIDs; > + /* range_crossing: > + * bits 1-6: reserved > + * bit 0: range crossing > + */ > + u8 range_crossing; > + u8 reserved01; > + u16 reserved02; > + u32 reserved03; > + u32 reserved04; > +}; > + > +/* > + * Opal V1 feature > + * > + * code == 0x0200 > + */ > +struct d0_opal_v100 { > + u16 baseComID; > + u16 numComIDs; > +}; > + > +/* > + * Single User Mode feature > + * > + * code == 0x0201 > + */ > +struct d0_single_user_mode { > + u32 num_locking_objects; > + /* reserved01: > + * bit 0: any > + * bit 1: all > + * bit 2: policy > + * bits 3-7: reserved > + */ > + u8 reserved01; > + u8 reserved02; > + u16 reserved03; > + u32 reserved04; > +}; > + > +/* > + * Additonal Datastores feature > + * > + * code == 0x0202 > + */ > +struct d0_datastore_table { > + u16 reserved01; > + u16 max_tables; > + u32 max_size_tables; > + u32 table_size_alignment; > +}; > + > +/* > + * OPAL 2.0 feature > + * > + * code == 0x0203 > + */ > +struct d0_opal_v200 { > + u16 baseComID; > + u16 numComIDs; > + /* range_crossing: > + * bits 1-6: reserved > + * bit 0: range crossing > + */ > + u8 range_crossing; > + /* num_locking_admin_auth: > + * not aligned to 16 bits, so use two u8. > + * stored in big endian: > + * 0: MSB > + * 1: LSB > + */ > + u8 num_locking_admin_auth[2]; > + /* num_locking_user_auth: > + * not aligned to 16 bits, so use two u8. > + * stored in big endian: > + * 0: MSB > + * 1: LSB > + */ > + u8 num_locking_user_auth[2]; > + u8 initialPIN; > + u8 revertedPIN; > + u8 reserved01; > + u32 reserved02; > +}; > + > +/* Union of features used to parse the discovery 0 response */ > +struct d0_features { > + u16 code; > + /* > + * r_version bits: > + * bits 4-7: version > + * bits 0-3: reserved > + */ > + u8 r_version; > + u8 length; > + u8 features[]; > +}; > + > +struct key *request_user_key(const char *master_desc, const u8 **master_key, > + size_t *master_keylen); > + > +#endif /* _NVME_OPAL_INTERNAL_H */ > diff --git a/lib/sed-opal_key.c b/lib/sed-opal_key.c > new file mode 100644 > index 0000000..0b4de01 > --- /dev/null > +++ b/lib/sed-opal_key.c > @@ -0,0 +1,46 @@ > +/* > + * Copyright ? 2016 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + * > + * Author: > + * Rafael Antognolli <rafael.antognolli at intel.com> > + */ > + > +#include <linux/key.h> > +#include "sed-opal_internal.h" > + > +struct key *request_user_key(const char *master_desc, const u8 **master_key, > + size_t *master_keylen) > +{ > + const struct user_key_payload *upayload; > + struct key *ukey; > + > + ukey = request_key(&key_type_user, master_desc, NULL); > + if (IS_ERR(ukey)) > + goto error; > + > + down_read(&ukey->sem); > + upayload = user_key_payload(ukey); > + *master_key = upayload->data; > + *master_keylen = upayload->datalen; > +error: > + return ukey; > +} > diff --git a/lib/sed.c b/lib/sed.c > new file mode 100644 > index 0000000..06cacd9 > --- /dev/null > +++ b/lib/sed.c > @@ -0,0 +1,303 @@ > +#include <linux/blkdev.h> > +#include <linux/sed.h> > +#include <linux/sed-opal.h> > + > +#ifndef CONFIG_SED_OPAL > +static int sed_opal_save(struct block_device *bdev, struct sed_key *sed) > + { return -EOPNOTSUPP; } > +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key) > + { return -EOPNOTSUPP; } > +static int sed_opal_take_ownership(struct block_device *bdev, struct sed_key *key) > + { return -EOPNOTSUPP; } > +static int sed_opal_activate_lsp(struct block_device *bdev, struct sed_key *key) > + { return -EOPNOTSUPP; } > +static int sed_opal_set_pw(struct block_device *bdev, struct sed_key *key) > + { return -EOPNOTSUPP; } > +static int sed_opal_activate_user(struct block_device *bdev, struct sed_key *key) > + { return -EOPNOTSUPP; } > +static int sed_opal_reverttper(struct block_device *bdev, struct sed_key *key) > + { return -EOPNOTSUPP; } > +static int sed_opal_setup_locking_range(struct block_device *bdev, struct sed_key *key) > + { return -EOPNOTSUPP; } > +static int sed_opal_adduser_to_lr(struct block_device *bdev, struct sed_key *key) > + { return -EOPNOTSUPP; } > +static int sed_opal_do_mbr(struct block_device *bdev, struct sed_key *key) > + { return -EOPNOTSUPP; } > +static int sed_opal_erase_lr(struct block_device *bdev, struct sed_key *key) > + { return -EOPNOTSUPP; } > + > +#else > + > +static int sed_opal_save(struct block_device *bdev, struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; You might consider pulling this boilerplate out into something like: static inline bool bdev_sec_capable(struct block_device *bdev) { return bdev && bdev->bd_disk && bdev->bd_disk->fops && bdev->bd_disk->fops->sec_ops; } > + > + return opal_save(bdev, key); > +} > + > +static int sed_opal_lock_unlock(struct block_device *bdev, struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + return opal_lock_unlock(bdev, key); > +} > + > +static int sed_opal_take_ownership(struct block_device *bdev, > + struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + return opal_take_ownership(bdev, key); > +} > + > +static int sed_opal_activate_lsp(struct block_device *bdev, > + struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + return opal_activate_lsp(bdev, key); > +} > + > +static int sed_opal_set_pw(struct block_device *bdev, > + struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + return opal_set_new_pw(bdev, key); > +} > + > +static int sed_opal_activate_user(struct block_device *bdev, > + struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + return opal_activate_user(bdev, key); > +} > + > +static int sed_opal_reverttper(struct block_device *bdev, > + struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + return opal_reverttper(bdev, key); > +} > + > +static int sed_opal_setup_lr(struct block_device *bdev, > + struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + return opal_setup_locking_range(bdev, key); > +} > + > +static int sed_opal_adduser_to_lr(struct block_device *bdev, > + struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + return opal_add_user_to_lr(bdev, key); > +} > + > +static int sed_opal_do_mbr(struct block_device *bdev, > + struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + return opal_enable_disable_shadow_mbr(bdev, key); > +} > + > +static int sed_opal_erase_lr(struct block_device *bdev, > + struct sed_key *key) > +{ > + > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + return opal_erase_locking_range(bdev, key); > +} > +#endif > + > +int sed_save(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL_LOCK_UNLOCK: > + return sed_opal_save(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > + > +int sed_lock_unlock(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL_LOCK_UNLOCK: > + return sed_opal_lock_unlock(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > + > +int sed_take_ownership(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL: > + return sed_opal_take_ownership(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > + > +int sed_activate_lsp(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL: > + return sed_opal_activate_lsp(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > + > +int sed_set_pw(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL_PW: > + return sed_opal_set_pw(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > + > +int sed_activate_user(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL_ACT_USR: > + return sed_opal_activate_user(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > + > +int sed_reverttper(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL: > + return sed_opal_reverttper(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > + > +int sed_setup_locking_range(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL_LR_SETUP: > + return sed_opal_setup_lr(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > + > +int sed_adduser_to_lr(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL_LOCK_UNLOCK: > + return sed_opal_adduser_to_lr(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > + > +int sed_do_mbr(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL_MBR_DATA: > + return sed_opal_do_mbr(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > + > +int sed_erase_lr(struct block_device *bdev, struct sed_key *key) > +{ > + if (!bdev || !bdev->bd_disk || !bdev->bd_disk->fops || > + !bdev->bd_disk->fops->sec_ops) > + return -EOPNOTSUPP; > + > + switch (key->sed_type) { > + case OPAL: > + return sed_opal_erase_lr(bdev, key); > + } > + > + return -EOPNOTSUPP; > +} > -- > 2.7.4 > ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 3/6] lib: Add Sed to Kconfig and Makefile 2016-10-31 21:58 ` Scott Bauer @ 2016-10-31 21:58 ` Scott Bauer -1 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) To: linux-nvme Cc: Rafael.Antognolli, axboe, keith.busch, jonathan.derrick, j.naumann, hch, linux-block, Scott Bauer Signed-off-by: Scott Bauer <scott.bauer@intel.com> Signed-off-by: Rafael Antognolli <Rafael.Antognolli@intel.com> --- lib/Kconfig | 12 ++++++++++++ lib/Makefile | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/lib/Kconfig b/lib/Kconfig index 260a80e..47c39ac 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -547,6 +547,18 @@ config STACKDEPOT bool select STACKTRACE +config SED + bool "Self-Encrypting Drive library" + help + Provides self-encrypting drive helpers + +config SED_OPAL + bool "Self-Encrypting Drive library - Opal implementation" + depends on SED + help + Provides self-encrypting drive helpers for drives that implement the + Opal spec. + config SBITMAP bool diff --git a/lib/Makefile b/lib/Makefile index 50144a3..976da7a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -229,4 +229,11 @@ obj-$(CONFIG_UBSAN) += ubsan.o UBSAN_SANITIZE_ubsan.o := n + +obj-$(CONFIG_SED) += sed.o + +obj-$(CONFIG_SED_OPAL) += sed-opal.o +obj-$(CONFIG_SED_OPAL) += sed-opal_key.o + obj-$(CONFIG_SBITMAP) += sbitmap.o + -- 2.7.4 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* [RFC PATCH 3/6] lib: Add Sed to Kconfig and Makefile @ 2016-10-31 21:58 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) Signed-off-by: Scott Bauer <scott.bauer at intel.com> Signed-off-by: Rafael Antognolli <Rafael.Antognolli at intel.com> --- lib/Kconfig | 12 ++++++++++++ lib/Makefile | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/lib/Kconfig b/lib/Kconfig index 260a80e..47c39ac 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -547,6 +547,18 @@ config STACKDEPOT bool select STACKTRACE +config SED + bool "Self-Encrypting Drive library" + help + Provides self-encrypting drive helpers + +config SED_OPAL + bool "Self-Encrypting Drive library - Opal implementation" + depends on SED + help + Provides self-encrypting drive helpers for drives that implement the + Opal spec. + config SBITMAP bool diff --git a/lib/Makefile b/lib/Makefile index 50144a3..976da7a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -229,4 +229,11 @@ obj-$(CONFIG_UBSAN) += ubsan.o UBSAN_SANITIZE_ubsan.o := n + +obj-$(CONFIG_SED) += sed.o + +obj-$(CONFIG_SED_OPAL) += sed-opal.o +obj-$(CONFIG_SED_OPAL) += sed-opal_key.o + obj-$(CONFIG_SBITMAP) += sbitmap.o + -- 2.7.4 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* [RFC PATCH 4/6] include: Add sec_ops to block device operations 2016-10-31 21:58 ` Scott Bauer @ 2016-10-31 21:58 ` Scott Bauer -1 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) To: linux-nvme Cc: Rafael.Antognolli, axboe, keith.busch, jonathan.derrick, j.naumann, hch, linux-block, Scott Bauer Signed-off-by: Scott Bauer <scott.bauer@intel.com> Signed-off-by: Rafael Antognolli <Rafael.Antognolli@intel.com> --- include/linux/blkdev.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index c47c358..6fceff1 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1690,6 +1690,7 @@ struct block_device_operations { void (*swap_slot_free_notify) (struct block_device *, unsigned long); struct module *owner; const struct pr_ops *pr_ops; + struct sec_ops *sec_ops; }; extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int, -- 2.7.4 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* [RFC PATCH 4/6] include: Add sec_ops to block device operations @ 2016-10-31 21:58 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) Signed-off-by: Scott Bauer <scott.bauer at intel.com> Signed-off-by: Rafael Antognolli <Rafael.Antognolli at intel.com> --- include/linux/blkdev.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index c47c358..6fceff1 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1690,6 +1690,7 @@ struct block_device_operations { void (*swap_slot_free_notify) (struct block_device *, unsigned long); struct module *owner; const struct pr_ops *pr_ops; + struct sec_ops *sec_ops; }; extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int, -- 2.7.4 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* [RFC PATCH 5/6] nvme: Add unlock_from_suspend 2016-10-31 21:58 ` Scott Bauer @ 2016-10-31 21:58 ` Scott Bauer -1 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) To: linux-nvme Cc: Rafael.Antognolli, axboe, keith.busch, jonathan.derrick, j.naumann, hch, linux-block, Scott Bauer This patch adds a new function unlock_from_suspend which is used to call into the Opal code to attempt to unlock Locking Ranges, after a suspend-to-RAM. The patch also modifies nvme_req_needs_retry to *not* retry a request that failed due to a NVME_SC_ACCESS_DENIED, which gets returned if a request is attempting to much with a locked range. The range won't magically unlock itself without user interaction so we shouldn't retry the request -- it will fail again. Signed-off-by: Scott Bauer <scott.bauer@intel.com> Signed-off-by: Rafael Antognolli <Rafael.Antognolli@intel.com> --- drivers/nvme/host/core.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/nvme/host/nvme.h | 4 +- drivers/nvme/host/pci.c | 19 ++++--- 3 files changed, 149 insertions(+), 8 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 79e679d..1321331 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" @@ -1067,6 +1069,137 @@ static const struct pr_ops nvme_pr_ops = { .pr_clear = nvme_pr_clear, }; +struct sed_cb_data { + sec_cb *cb; + void *cb_data; + struct nvme_command cmd; +}; + +static void sec_submit_endio(struct request *req, int error) +{ + struct sed_cb_data *sed_data = req->end_io_data; + + if (sed_data->cb) + sed_data->cb(error, sed_data->cb_data); + + kfree(sed_data); + blk_mq_free_request(req); +} + +static int nvme_insert_rq(struct request_queue *q, struct request *rq, + int at_head, rq_end_io_fn *done) +{ + WARN_ON(rq->cmd_type == REQ_TYPE_FS); + + rq->end_io = done; + + if (!q->mq_ops) + return -EINVAL; + + blk_mq_insert_request(rq, at_head, true, true); + + return 0; +} + +static int nvme_sec_submit(void *data, u8 opcode, u16 SPSP, + u8 SECP, void *buffer, size_t len, + sec_cb *cb, void *cb_data) +{ + struct request_queue *q; + struct request *req; + struct sed_cb_data *sed_data; + struct nvme_ns *ns; + struct nvme_command *cmd; + int ret; + + ns = data;//bdev->bd_disk->private_data; + + sed_data = kzalloc(sizeof(*sed_data), GFP_NOWAIT); + if (!sed_data) + return -ENOMEM; + sed_data->cb = cb; + sed_data->cb_data = cb_data; + cmd = &sed_data->cmd; + + cmd->common.opcode = opcode; + cmd->common.nsid = ns->ns_id; + cmd->common.cdw10[0] = SECP << 24 | SPSP << 8; + cmd->common.cdw10[1] = len; + + q = ns->ctrl->admin_q; + + req = nvme_alloc_request(q, cmd, 0, NVME_QID_ANY); + if (IS_ERR(req)) { + ret = PTR_ERR(req); + goto err_free; + } + + req->timeout = ADMIN_TIMEOUT; + req->special = NULL; + + if (buffer && len) { + ret = blk_rq_map_kern(q, req, buffer, len, GFP_NOWAIT); + if (ret) { + blk_mq_free_request(req); + goto err_free; + } + } + + req->end_io_data = sed_data; + //req->rq_disk = bdev->bd_disk; + + return nvme_insert_rq(q, req, 1, sec_submit_endio); + +err_free: + kfree(sed_data); + return ret; +} + +static int nvme_sec_recv(void *data, u16 SPSP, u8 SECP, + void *buffer, size_t len, + sec_cb *cb, void *cb_data) +{ + return nvme_sec_submit(data, nvme_admin_security_recv, SPSP, SECP, + buffer, len, cb, cb_data); +} + +static int nvme_sec_send(void *data, u16 SPSP, u8 SECP, + void *buffer, size_t len, + sec_cb *cb, void *cb_data) +{ + return nvme_sec_submit(data, nvme_admin_security_send, SPSP, SECP, + buffer, len, cb, cb_data); +} + +void nvme_unlock_from_suspend(struct nvme_ctrl *ctrl) +{ + struct opal_suspend_unlk ulk = { 0 }; + struct nvme_ns *ns; + char diskname[DISK_NAME_LEN]; + mutex_lock(&ctrl->namespaces_mutex); + if (list_empty(&ctrl->namespaces)) + goto out_no_namespace; + ulk.data = ns =list_first_entry(&ctrl->namespaces, struct nvme_ns, list); + mutex_unlock(&ctrl->namespaces_mutex); + snprintf(diskname, sizeof(diskname), "%sn%d", + dev_name(ctrl->device), ns->instance); + ulk.name = diskname; + + ulk.ops.send = nvme_sec_send; + ulk.ops.recv = nvme_sec_recv; + opal_unlock_from_suspend(&ulk); + + return; + out_no_namespace: + mutex_unlock(&ctrl->namespaces_mutex); +} +EXPORT_SYMBOL_GPL(nvme_unlock_from_suspend); + +static struct sec_ops nvme_sec_ops = { + .send = nvme_sec_send, + .recv = nvme_sec_recv, +}; + static const struct block_device_operations nvme_fops = { .owner = THIS_MODULE, .ioctl = nvme_ioctl, @@ -1076,6 +1209,7 @@ static const struct block_device_operations nvme_fops = { .getgeo = nvme_getgeo, .revalidate_disk= nvme_revalidate_disk, .pr_ops = &nvme_pr_ops, + .sec_ops = &nvme_sec_ops, }; static int nvme_wait_ready(struct nvme_ctrl *ctrl, u64 cap, bool enabled) 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 0248d0e..18fd878 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" @@ -582,6 +583,7 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, struct nvme_command cmnd; unsigned map_len; int ret = BLK_MQ_RQ_QUEUE_OK; + unsigned long flags; /* * If formated with metadata, require the block layer provide a buffer @@ -614,18 +616,18 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, cmnd.common.command_id = req->tag; blk_mq_start_request(req); - spin_lock_irq(&nvmeq->q_lock); + spin_lock_irqsave(&nvmeq->q_lock, flags); if (unlikely(nvmeq->cq_vector < 0)) { if (ns && !test_bit(NVME_NS_DEAD, &ns->flags)) ret = BLK_MQ_RQ_QUEUE_BUSY; else ret = BLK_MQ_RQ_QUEUE_ERROR; - spin_unlock_irq(&nvmeq->q_lock); + spin_unlock_irqrestore(&nvmeq->q_lock, flags); goto out; } __nvme_submit_cmd(nvmeq, &cmnd); nvme_process_cq(nvmeq); - spin_unlock_irq(&nvmeq->q_lock); + spin_unlock_irqrestore(&nvmeq->q_lock, flags); return BLK_MQ_RQ_QUEUE_OK; out: nvme_free_iod(dev, req); @@ -635,11 +637,11 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, static void nvme_complete_rq(struct request *req) { struct nvme_iod *iod = blk_mq_rq_to_pdu(req); - struct nvme_dev *dev = iod->nvmeq->dev; + struct nvme_queue *nvmeq = iod->nvmeq; + struct nvme_dev *dev = nvmeq->dev; int error = 0; nvme_unmap_data(dev, req); - if (unlikely(req->errors)) { if (nvme_req_needs_retry(req, req->errors)) { req->retries++; @@ -658,7 +660,6 @@ static void nvme_complete_rq(struct request *req) "completing aborted command with status: %04x\n", req->errors); } - blk_mq_end_request(req, error); } @@ -1758,10 +1759,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. @@ -1789,6 +1791,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] 32+ messages in thread
* [RFC PATCH 5/6] nvme: Add unlock_from_suspend @ 2016-10-31 21:58 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) This patch adds a new function unlock_from_suspend which is used to call into the Opal code to attempt to unlock Locking Ranges, after a suspend-to-RAM. The patch also modifies nvme_req_needs_retry to *not* retry a request that failed due to a NVME_SC_ACCESS_DENIED, which gets returned if a request is attempting to much with a locked range. The range won't magically unlock itself without user interaction so we shouldn't retry the request -- it will fail again. 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 | 134 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/nvme/host/nvme.h | 4 +- drivers/nvme/host/pci.c | 19 ++++--- 3 files changed, 149 insertions(+), 8 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 79e679d..1321331 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" @@ -1067,6 +1069,137 @@ static const struct pr_ops nvme_pr_ops = { .pr_clear = nvme_pr_clear, }; +struct sed_cb_data { + sec_cb *cb; + void *cb_data; + struct nvme_command cmd; +}; + +static void sec_submit_endio(struct request *req, int error) +{ + struct sed_cb_data *sed_data = req->end_io_data; + + if (sed_data->cb) + sed_data->cb(error, sed_data->cb_data); + + kfree(sed_data); + blk_mq_free_request(req); +} + +static int nvme_insert_rq(struct request_queue *q, struct request *rq, + int at_head, rq_end_io_fn *done) +{ + WARN_ON(rq->cmd_type == REQ_TYPE_FS); + + rq->end_io = done; + + if (!q->mq_ops) + return -EINVAL; + + blk_mq_insert_request(rq, at_head, true, true); + + return 0; +} + +static int nvme_sec_submit(void *data, u8 opcode, u16 SPSP, + u8 SECP, void *buffer, size_t len, + sec_cb *cb, void *cb_data) +{ + struct request_queue *q; + struct request *req; + struct sed_cb_data *sed_data; + struct nvme_ns *ns; + struct nvme_command *cmd; + int ret; + + ns = data;//bdev->bd_disk->private_data; + + sed_data = kzalloc(sizeof(*sed_data), GFP_NOWAIT); + if (!sed_data) + return -ENOMEM; + sed_data->cb = cb; + sed_data->cb_data = cb_data; + cmd = &sed_data->cmd; + + cmd->common.opcode = opcode; + cmd->common.nsid = ns->ns_id; + cmd->common.cdw10[0] = SECP << 24 | SPSP << 8; + cmd->common.cdw10[1] = len; + + q = ns->ctrl->admin_q; + + req = nvme_alloc_request(q, cmd, 0, NVME_QID_ANY); + if (IS_ERR(req)) { + ret = PTR_ERR(req); + goto err_free; + } + + req->timeout = ADMIN_TIMEOUT; + req->special = NULL; + + if (buffer && len) { + ret = blk_rq_map_kern(q, req, buffer, len, GFP_NOWAIT); + if (ret) { + blk_mq_free_request(req); + goto err_free; + } + } + + req->end_io_data = sed_data; + //req->rq_disk = bdev->bd_disk; + + return nvme_insert_rq(q, req, 1, sec_submit_endio); + +err_free: + kfree(sed_data); + return ret; +} + +static int nvme_sec_recv(void *data, u16 SPSP, u8 SECP, + void *buffer, size_t len, + sec_cb *cb, void *cb_data) +{ + return nvme_sec_submit(data, nvme_admin_security_recv, SPSP, SECP, + buffer, len, cb, cb_data); +} + +static int nvme_sec_send(void *data, u16 SPSP, u8 SECP, + void *buffer, size_t len, + sec_cb *cb, void *cb_data) +{ + return nvme_sec_submit(data, nvme_admin_security_send, SPSP, SECP, + buffer, len, cb, cb_data); +} + +void nvme_unlock_from_suspend(struct nvme_ctrl *ctrl) +{ + struct opal_suspend_unlk ulk = { 0 }; + struct nvme_ns *ns; + char diskname[DISK_NAME_LEN]; + mutex_lock(&ctrl->namespaces_mutex); + if (list_empty(&ctrl->namespaces)) + goto out_no_namespace; + ulk.data = ns =list_first_entry(&ctrl->namespaces, struct nvme_ns, list); + mutex_unlock(&ctrl->namespaces_mutex); + snprintf(diskname, sizeof(diskname), "%sn%d", + dev_name(ctrl->device), ns->instance); + ulk.name = diskname; + + ulk.ops.send = nvme_sec_send; + ulk.ops.recv = nvme_sec_recv; + opal_unlock_from_suspend(&ulk); + + return; + out_no_namespace: + mutex_unlock(&ctrl->namespaces_mutex); +} +EXPORT_SYMBOL_GPL(nvme_unlock_from_suspend); + +static struct sec_ops nvme_sec_ops = { + .send = nvme_sec_send, + .recv = nvme_sec_recv, +}; + static const struct block_device_operations nvme_fops = { .owner = THIS_MODULE, .ioctl = nvme_ioctl, @@ -1076,6 +1209,7 @@ static const struct block_device_operations nvme_fops = { .getgeo = nvme_getgeo, .revalidate_disk= nvme_revalidate_disk, .pr_ops = &nvme_pr_ops, + .sec_ops = &nvme_sec_ops, }; static int nvme_wait_ready(struct nvme_ctrl *ctrl, u64 cap, bool enabled) 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 0248d0e..18fd878 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" @@ -582,6 +583,7 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, struct nvme_command cmnd; unsigned map_len; int ret = BLK_MQ_RQ_QUEUE_OK; + unsigned long flags; /* * If formated with metadata, require the block layer provide a buffer @@ -614,18 +616,18 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, cmnd.common.command_id = req->tag; blk_mq_start_request(req); - spin_lock_irq(&nvmeq->q_lock); + spin_lock_irqsave(&nvmeq->q_lock, flags); if (unlikely(nvmeq->cq_vector < 0)) { if (ns && !test_bit(NVME_NS_DEAD, &ns->flags)) ret = BLK_MQ_RQ_QUEUE_BUSY; else ret = BLK_MQ_RQ_QUEUE_ERROR; - spin_unlock_irq(&nvmeq->q_lock); + spin_unlock_irqrestore(&nvmeq->q_lock, flags); goto out; } __nvme_submit_cmd(nvmeq, &cmnd); nvme_process_cq(nvmeq); - spin_unlock_irq(&nvmeq->q_lock); + spin_unlock_irqrestore(&nvmeq->q_lock, flags); return BLK_MQ_RQ_QUEUE_OK; out: nvme_free_iod(dev, req); @@ -635,11 +637,11 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, static void nvme_complete_rq(struct request *req) { struct nvme_iod *iod = blk_mq_rq_to_pdu(req); - struct nvme_dev *dev = iod->nvmeq->dev; + struct nvme_queue *nvmeq = iod->nvmeq; + struct nvme_dev *dev = nvmeq->dev; int error = 0; nvme_unmap_data(dev, req); - if (unlikely(req->errors)) { if (nvme_req_needs_retry(req, req->errors)) { req->retries++; @@ -658,7 +660,6 @@ static void nvme_complete_rq(struct request *req) "completing aborted command with status: %04x\n", req->errors); } - blk_mq_end_request(req, error); } @@ -1758,10 +1759,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. @@ -1789,6 +1791,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] 32+ messages in thread
* Re: [RFC PATCH 5/6] nvme: Add unlock_from_suspend 2016-10-31 21:58 ` Scott Bauer @ 2016-11-01 8:18 ` Sagi Grimberg -1 siblings, 0 replies; 32+ messages in thread From: Sagi Grimberg @ 2016-11-01 8:18 UTC (permalink / raw) To: Scott Bauer, linux-nvme Cc: Rafael.Antognolli, axboe, keith.busch, jonathan.derrick, j.naumann, hch, linux-block > +struct sed_cb_data { > + sec_cb *cb; > + void *cb_data; > + struct nvme_command cmd; > +}; > + > +static void sec_submit_endio(struct request *req, int error) > +{ > + struct sed_cb_data *sed_data = req->end_io_data; > + > + if (sed_data->cb) > + sed_data->cb(error, sed_data->cb_data); > + > + kfree(sed_data); > + blk_mq_free_request(req); > +} > + > +static int nvme_insert_rq(struct request_queue *q, struct request *rq, > + int at_head, rq_end_io_fn *done) > +{ > + WARN_ON(rq->cmd_type == REQ_TYPE_FS); > + > + rq->end_io = done; > + > + if (!q->mq_ops) > + return -EINVAL; > + > + blk_mq_insert_request(rq, at_head, true, true); > + > + return 0; > +} No need for this function... you control the call site... > + > +static int nvme_sec_submit(void *data, u8 opcode, u16 SPSP, > + u8 SECP, void *buffer, size_t len, > + sec_cb *cb, void *cb_data) > +{ > + struct request_queue *q; > + struct request *req; > + struct sed_cb_data *sed_data; > + struct nvme_ns *ns; > + struct nvme_command *cmd; > + int ret; > + > + ns = data;//bdev->bd_disk->private_data; ?? you don't even have data anywhere in here... > + > + sed_data = kzalloc(sizeof(*sed_data), GFP_NOWAIT); > + if (!sed_data) > + return -ENOMEM; > + sed_data->cb = cb; > + sed_data->cb_data = cb_data; > + cmd = &sed_data->cmd; > + > + cmd->common.opcode = opcode; > + cmd->common.nsid = ns->ns_id; > + cmd->common.cdw10[0] = SECP << 24 | SPSP << 8; > + cmd->common.cdw10[1] = len; > + > + q = ns->ctrl->admin_q; > + > + req = nvme_alloc_request(q, cmd, 0, NVME_QID_ANY); > + if (IS_ERR(req)) { > + ret = PTR_ERR(req); > + goto err_free; > + } > + > + req->timeout = ADMIN_TIMEOUT; > + req->special = NULL; > + > + if (buffer && len) { > + ret = blk_rq_map_kern(q, req, buffer, len, GFP_NOWAIT); > + if (ret) { > + blk_mq_free_request(req); > + goto err_free; > + } > + } > + > + req->end_io_data = sed_data; > + //req->rq_disk = bdev->bd_disk; ?? > + > + return nvme_insert_rq(q, req, 1, sec_submit_endio); No need to introduce nvme_insert_rq at all, just call blk_mq_insert_request (other examples call blk_execute_rq_nowait but its pretty much the same...) > @@ -582,6 +583,7 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, > struct nvme_command cmnd; > unsigned map_len; > int ret = BLK_MQ_RQ_QUEUE_OK; > + unsigned long flags; > > /* > * If formated with metadata, require the block layer provide a buffer > @@ -614,18 +616,18 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, > cmnd.common.command_id = req->tag; > blk_mq_start_request(req); > > - spin_lock_irq(&nvmeq->q_lock); > + spin_lock_irqsave(&nvmeq->q_lock, flags); > if (unlikely(nvmeq->cq_vector < 0)) { > if (ns && !test_bit(NVME_NS_DEAD, &ns->flags)) > ret = BLK_MQ_RQ_QUEUE_BUSY; > else > ret = BLK_MQ_RQ_QUEUE_ERROR; > - spin_unlock_irq(&nvmeq->q_lock); > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); > goto out; > } > __nvme_submit_cmd(nvmeq, &cmnd); > nvme_process_cq(nvmeq); > - spin_unlock_irq(&nvmeq->q_lock); > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); No documentation why this is needed... > return BLK_MQ_RQ_QUEUE_OK; > out: > nvme_free_iod(dev, req); > @@ -635,11 +637,11 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, > static void nvme_complete_rq(struct request *req) > { > struct nvme_iod *iod = blk_mq_rq_to_pdu(req); > - struct nvme_dev *dev = iod->nvmeq->dev; > + struct nvme_queue *nvmeq = iod->nvmeq; > + struct nvme_dev *dev = nvmeq->dev; This is a cleanup that should go in a different patch... > int error = 0; > > nvme_unmap_data(dev, req); > - Same here... > if (unlikely(req->errors)) { > if (nvme_req_needs_retry(req, req->errors)) { > req->retries++; > @@ -658,7 +660,6 @@ static void nvme_complete_rq(struct request *req) > "completing aborted command with status: %04x\n", > req->errors); > } > - Here... > blk_mq_end_request(req, error); > } > > @@ -1758,10 +1759,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. > @@ -1789,6 +1791,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; > ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 5/6] nvme: Add unlock_from_suspend @ 2016-11-01 8:18 ` Sagi Grimberg 0 siblings, 0 replies; 32+ messages in thread From: Sagi Grimberg @ 2016-11-01 8:18 UTC (permalink / raw) > +struct sed_cb_data { > + sec_cb *cb; > + void *cb_data; > + struct nvme_command cmd; > +}; > + > +static void sec_submit_endio(struct request *req, int error) > +{ > + struct sed_cb_data *sed_data = req->end_io_data; > + > + if (sed_data->cb) > + sed_data->cb(error, sed_data->cb_data); > + > + kfree(sed_data); > + blk_mq_free_request(req); > +} > + > +static int nvme_insert_rq(struct request_queue *q, struct request *rq, > + int at_head, rq_end_io_fn *done) > +{ > + WARN_ON(rq->cmd_type == REQ_TYPE_FS); > + > + rq->end_io = done; > + > + if (!q->mq_ops) > + return -EINVAL; > + > + blk_mq_insert_request(rq, at_head, true, true); > + > + return 0; > +} No need for this function... you control the call site... > + > +static int nvme_sec_submit(void *data, u8 opcode, u16 SPSP, > + u8 SECP, void *buffer, size_t len, > + sec_cb *cb, void *cb_data) > +{ > + struct request_queue *q; > + struct request *req; > + struct sed_cb_data *sed_data; > + struct nvme_ns *ns; > + struct nvme_command *cmd; > + int ret; > + > + ns = data;//bdev->bd_disk->private_data; ?? you don't even have data anywhere in here... > + > + sed_data = kzalloc(sizeof(*sed_data), GFP_NOWAIT); > + if (!sed_data) > + return -ENOMEM; > + sed_data->cb = cb; > + sed_data->cb_data = cb_data; > + cmd = &sed_data->cmd; > + > + cmd->common.opcode = opcode; > + cmd->common.nsid = ns->ns_id; > + cmd->common.cdw10[0] = SECP << 24 | SPSP << 8; > + cmd->common.cdw10[1] = len; > + > + q = ns->ctrl->admin_q; > + > + req = nvme_alloc_request(q, cmd, 0, NVME_QID_ANY); > + if (IS_ERR(req)) { > + ret = PTR_ERR(req); > + goto err_free; > + } > + > + req->timeout = ADMIN_TIMEOUT; > + req->special = NULL; > + > + if (buffer && len) { > + ret = blk_rq_map_kern(q, req, buffer, len, GFP_NOWAIT); > + if (ret) { > + blk_mq_free_request(req); > + goto err_free; > + } > + } > + > + req->end_io_data = sed_data; > + //req->rq_disk = bdev->bd_disk; ?? > + > + return nvme_insert_rq(q, req, 1, sec_submit_endio); No need to introduce nvme_insert_rq at all, just call blk_mq_insert_request (other examples call blk_execute_rq_nowait but its pretty much the same...) > @@ -582,6 +583,7 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, > struct nvme_command cmnd; > unsigned map_len; > int ret = BLK_MQ_RQ_QUEUE_OK; > + unsigned long flags; > > /* > * If formated with metadata, require the block layer provide a buffer > @@ -614,18 +616,18 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, > cmnd.common.command_id = req->tag; > blk_mq_start_request(req); > > - spin_lock_irq(&nvmeq->q_lock); > + spin_lock_irqsave(&nvmeq->q_lock, flags); > if (unlikely(nvmeq->cq_vector < 0)) { > if (ns && !test_bit(NVME_NS_DEAD, &ns->flags)) > ret = BLK_MQ_RQ_QUEUE_BUSY; > else > ret = BLK_MQ_RQ_QUEUE_ERROR; > - spin_unlock_irq(&nvmeq->q_lock); > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); > goto out; > } > __nvme_submit_cmd(nvmeq, &cmnd); > nvme_process_cq(nvmeq); > - spin_unlock_irq(&nvmeq->q_lock); > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); No documentation why this is needed... > return BLK_MQ_RQ_QUEUE_OK; > out: > nvme_free_iod(dev, req); > @@ -635,11 +637,11 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, > static void nvme_complete_rq(struct request *req) > { > struct nvme_iod *iod = blk_mq_rq_to_pdu(req); > - struct nvme_dev *dev = iod->nvmeq->dev; > + struct nvme_queue *nvmeq = iod->nvmeq; > + struct nvme_dev *dev = nvmeq->dev; This is a cleanup that should go in a different patch... > int error = 0; > > nvme_unmap_data(dev, req); > - Same here... > if (unlikely(req->errors)) { > if (nvme_req_needs_retry(req, req->errors)) { > req->retries++; > @@ -658,7 +660,6 @@ static void nvme_complete_rq(struct request *req) > "completing aborted command with status: %04x\n", > req->errors); > } > - Here... > blk_mq_end_request(req, error); > } > > @@ -1758,10 +1759,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. > @@ -1789,6 +1791,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; > ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [RFC PATCH 5/6] nvme: Add unlock_from_suspend 2016-11-01 8:18 ` Sagi Grimberg @ 2016-11-01 13:57 ` Christoph Hellwig -1 siblings, 0 replies; 32+ messages in thread From: Christoph Hellwig @ 2016-11-01 13:57 UTC (permalink / raw) To: Sagi Grimberg Cc: Scott Bauer, linux-nvme, keith.busch, hch, Rafael.Antognolli, axboe, linux-block, jonathan.derrick, j.naumann On Tue, Nov 01, 2016 at 10:18:13AM +0200, Sagi Grimberg wrote: > > + > > + return nvme_insert_rq(q, req, 1, sec_submit_endio); > > No need to introduce nvme_insert_rq at all, just call > blk_mq_insert_request (other examples call blk_execute_rq_nowait > but its pretty much the same...) blk_execute_rq_nowait is the API to use - blk_mq_insert_request isn't even exported. ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 5/6] nvme: Add unlock_from_suspend @ 2016-11-01 13:57 ` Christoph Hellwig 0 siblings, 0 replies; 32+ messages in thread From: Christoph Hellwig @ 2016-11-01 13:57 UTC (permalink / raw) On Tue, Nov 01, 2016@10:18:13AM +0200, Sagi Grimberg wrote: > > + > > + return nvme_insert_rq(q, req, 1, sec_submit_endio); > > No need to introduce nvme_insert_rq at all, just call > blk_mq_insert_request (other examples call blk_execute_rq_nowait > but its pretty much the same...) blk_execute_rq_nowait is the API to use - blk_mq_insert_request isn't even exported. ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [RFC PATCH 5/6] nvme: Add unlock_from_suspend 2016-11-01 13:57 ` Christoph Hellwig @ 2016-11-01 14:40 ` Scott Bauer -1 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-11-01 14:40 UTC (permalink / raw) To: Christoph Hellwig Cc: Sagi Grimberg, linux-nvme, keith.busch, Rafael.Antognolli, axboe, linux-block, jonathan.derrick, j.naumann On Tue, Nov 01, 2016 at 06:57:05AM -0700, Christoph Hellwig wrote: > On Tue, Nov 01, 2016 at 10:18:13AM +0200, Sagi Grimberg wrote: > > > + > > > + return nvme_insert_rq(q, req, 1, sec_submit_endio); > > > > No need to introduce nvme_insert_rq at all, just call > > blk_mq_insert_request (other examples call blk_execute_rq_nowait > > but its pretty much the same...) > > blk_execute_rq_nowait is the API to use - blk_mq_insert_request isn't > even exported. Thanks for the reviews. This patch needs to be separated into two patches. There is the addition of the nvme-suspend stuff and the addition of sec_ops. Most of the clutter and weird stuff is coming from the latter. I'll separate the patches, use the correct api and clean the clutter. Thanks ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 5/6] nvme: Add unlock_from_suspend @ 2016-11-01 14:40 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-11-01 14:40 UTC (permalink / raw) On Tue, Nov 01, 2016@06:57:05AM -0700, Christoph Hellwig wrote: > On Tue, Nov 01, 2016@10:18:13AM +0200, Sagi Grimberg wrote: > > > + > > > + return nvme_insert_rq(q, req, 1, sec_submit_endio); > > > > No need to introduce nvme_insert_rq at all, just call > > blk_mq_insert_request (other examples call blk_execute_rq_nowait > > but its pretty much the same...) > > blk_execute_rq_nowait is the API to use - blk_mq_insert_request isn't > even exported. Thanks for the reviews. This patch needs to be separated into two patches. There is the addition of the nvme-suspend stuff and the addition of sec_ops. Most of the clutter and weird stuff is coming from the latter. I'll separate the patches, use the correct api and clean the clutter. Thanks ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [RFC PATCH 5/6] nvme: Add unlock_from_suspend 2016-11-01 13:57 ` Christoph Hellwig @ 2016-11-10 23:01 ` Scott Bauer -1 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-11-10 23:01 UTC (permalink / raw) To: Christoph Hellwig Cc: Sagi Grimberg, linux-nvme, keith.busch, Rafael.Antognolli, axboe, linux-block, jonathan.derrick, j.naumann On Tue, Nov 01, 2016 at 06:57:05AM -0700, Christoph Hellwig wrote: > On Tue, Nov 01, 2016 at 10:18:13AM +0200, Sagi Grimberg wrote: > > > + > > > + return nvme_insert_rq(q, req, 1, sec_submit_endio); > > > > No need to introduce nvme_insert_rq at all, just call > > blk_mq_insert_request (other examples call blk_execute_rq_nowait > > but its pretty much the same...) > > blk_execute_rq_nowait is the API to use - blk_mq_insert_request isn't > even exported. I remember now, after I changed it to use rq_nowait, why we added this wrapper function and used blk_mq_insert_request. When we dispatch opal commands down to the controller we're doing so in an IRQ, so if we use rq_nowait, we lockup. Will there be pushback if we continue with the original patch idea, where we export blk_mq_insert_request (forgot to send that) and use it? I looked through the block API and I didn't see a execute_rq that was irq safe. Any suggestions? ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 5/6] nvme: Add unlock_from_suspend @ 2016-11-10 23:01 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-11-10 23:01 UTC (permalink / raw) On Tue, Nov 01, 2016@06:57:05AM -0700, Christoph Hellwig wrote: > On Tue, Nov 01, 2016@10:18:13AM +0200, Sagi Grimberg wrote: > > > + > > > + return nvme_insert_rq(q, req, 1, sec_submit_endio); > > > > No need to introduce nvme_insert_rq at all, just call > > blk_mq_insert_request (other examples call blk_execute_rq_nowait > > but its pretty much the same...) > > blk_execute_rq_nowait is the API to use - blk_mq_insert_request isn't > even exported. I remember now, after I changed it to use rq_nowait, why we added this wrapper function and used blk_mq_insert_request. When we dispatch opal commands down to the controller we're doing so in an IRQ, so if we use rq_nowait, we lockup. Will there be pushback if we continue with the original patch idea, where we export blk_mq_insert_request (forgot to send that) and use it? I looked through the block API and I didn't see a execute_rq that was irq safe. Any suggestions? ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [RFC PATCH 5/6] nvme: Add unlock_from_suspend 2016-11-10 23:01 ` Scott Bauer @ 2016-11-10 23:23 ` Keith Busch -1 siblings, 0 replies; 32+ messages in thread From: Keith Busch @ 2016-11-10 23:23 UTC (permalink / raw) To: Scott Bauer Cc: Christoph Hellwig, Sagi Grimberg, linux-nvme, Rafael.Antognolli, axboe, linux-block, jonathan.derrick, j.naumann On Thu, Nov 10, 2016 at 04:01:31PM -0700, Scott Bauer wrote: > On Tue, Nov 01, 2016 at 06:57:05AM -0700, Christoph Hellwig wrote: > > blk_execute_rq_nowait is the API to use - blk_mq_insert_request isn't > > even exported. > > I remember now, after I changed it to use rq_nowait, why we added this wrapper > function and used blk_mq_insert_request. > > When we dispatch opal commands down to the controller we're doing so in an IRQ, > so if we use rq_nowait, we lockup. In this case can we push the submission off to a work queue and use blk_mq_insert_rq_nowait? ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 5/6] nvme: Add unlock_from_suspend @ 2016-11-10 23:23 ` Keith Busch 0 siblings, 0 replies; 32+ messages in thread From: Keith Busch @ 2016-11-10 23:23 UTC (permalink / raw) On Thu, Nov 10, 2016@04:01:31PM -0700, Scott Bauer wrote: > On Tue, Nov 01, 2016@06:57:05AM -0700, Christoph Hellwig wrote: > > blk_execute_rq_nowait is the API to use - blk_mq_insert_request isn't > > even exported. > > I remember now, after I changed it to use rq_nowait, why we added this wrapper > function and used blk_mq_insert_request. > > When we dispatch opal commands down to the controller we're doing so in an IRQ, > so if we use rq_nowait, we lockup. In this case can we push the submission off to a work queue and use blk_mq_insert_rq_nowait? ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [RFC PATCH 5/6] nvme: Add unlock_from_suspend 2016-11-10 23:23 ` Keith Busch @ 2016-11-10 23:19 ` Christoph Hellwig -1 siblings, 0 replies; 32+ messages in thread From: Christoph Hellwig @ 2016-11-10 23:19 UTC (permalink / raw) To: Keith Busch Cc: Scott Bauer, Christoph Hellwig, Sagi Grimberg, linux-nvme, Rafael.Antognolli, axboe, linux-block, jonathan.derrick, j.naumann On Thu, Nov 10, 2016 at 06:23:12PM -0500, Keith Busch wrote: > On Thu, Nov 10, 2016 at 04:01:31PM -0700, Scott Bauer wrote: > > On Tue, Nov 01, 2016 at 06:57:05AM -0700, Christoph Hellwig wrote: > > > blk_execute_rq_nowait is the API to use - blk_mq_insert_request isn't > > > even exported. > > > > I remember now, after I changed it to use rq_nowait, why we added this wrapper > > function and used blk_mq_insert_request. > > > > When we dispatch opal commands down to the controller we're doing so in an IRQ, > > so if we use rq_nowait, we lockup. > > In this case can we push the submission off to a work queue and use > blk_mq_insert_rq_nowait? That's what we have to do anyway to avoid taking irqsafe locks. (and the function is blk_execute_rq_nowait) ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 5/6] nvme: Add unlock_from_suspend @ 2016-11-10 23:19 ` Christoph Hellwig 0 siblings, 0 replies; 32+ messages in thread From: Christoph Hellwig @ 2016-11-10 23:19 UTC (permalink / raw) On Thu, Nov 10, 2016@06:23:12PM -0500, Keith Busch wrote: > On Thu, Nov 10, 2016@04:01:31PM -0700, Scott Bauer wrote: > > On Tue, Nov 01, 2016@06:57:05AM -0700, Christoph Hellwig wrote: > > > blk_execute_rq_nowait is the API to use - blk_mq_insert_request isn't > > > even exported. > > > > I remember now, after I changed it to use rq_nowait, why we added this wrapper > > function and used blk_mq_insert_request. > > > > When we dispatch opal commands down to the controller we're doing so in an IRQ, > > so if we use rq_nowait, we lockup. > > In this case can we push the submission off to a work queue and use > blk_mq_insert_rq_nowait? That's what we have to do anyway to avoid taking irqsafe locks. (and the function is blk_execute_rq_nowait) ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [RFC PATCH 5/6] nvme: Add unlock_from_suspend 2016-11-01 8:18 ` Sagi Grimberg @ 2016-11-07 18:45 ` Keith Busch -1 siblings, 0 replies; 32+ messages in thread From: Keith Busch @ 2016-11-07 18:45 UTC (permalink / raw) To: Sagi Grimberg Cc: Scott Bauer, linux-nvme, Rafael.Antognolli, axboe, jonathan.derrick, j.naumann, hch, linux-block On Tue, Nov 01, 2016 at 10:18:13AM +0200, Sagi Grimberg wrote: > > - spin_lock_irq(&nvmeq->q_lock); > > + spin_lock_irqsave(&nvmeq->q_lock, flags); > > if (unlikely(nvmeq->cq_vector < 0)) { > > if (ns && !test_bit(NVME_NS_DEAD, &ns->flags)) > > ret = BLK_MQ_RQ_QUEUE_BUSY; > > else > > ret = BLK_MQ_RQ_QUEUE_ERROR; > > - spin_unlock_irq(&nvmeq->q_lock); > > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); > > goto out; > > } > > __nvme_submit_cmd(nvmeq, &cmnd); > > nvme_process_cq(nvmeq); > > - spin_unlock_irq(&nvmeq->q_lock); > > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); > > No documentation why this is needed... Let's forget documenting why it's needed; this solution should instead figure out a way to make it so it's not needed. ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 5/6] nvme: Add unlock_from_suspend @ 2016-11-07 18:45 ` Keith Busch 0 siblings, 0 replies; 32+ messages in thread From: Keith Busch @ 2016-11-07 18:45 UTC (permalink / raw) On Tue, Nov 01, 2016@10:18:13AM +0200, Sagi Grimberg wrote: > > - spin_lock_irq(&nvmeq->q_lock); > > + spin_lock_irqsave(&nvmeq->q_lock, flags); > > if (unlikely(nvmeq->cq_vector < 0)) { > > if (ns && !test_bit(NVME_NS_DEAD, &ns->flags)) > > ret = BLK_MQ_RQ_QUEUE_BUSY; > > else > > ret = BLK_MQ_RQ_QUEUE_ERROR; > > - spin_unlock_irq(&nvmeq->q_lock); > > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); > > goto out; > > } > > __nvme_submit_cmd(nvmeq, &cmnd); > > nvme_process_cq(nvmeq); > > - spin_unlock_irq(&nvmeq->q_lock); > > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); > > No documentation why this is needed... Let's forget documenting why it's needed; this solution should instead figure out a way to make it so it's not needed. ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [RFC PATCH 5/6] nvme: Add unlock_from_suspend 2016-11-07 18:45 ` Keith Busch @ 2016-11-07 18:33 ` Scott Bauer -1 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-11-07 18:33 UTC (permalink / raw) To: Keith Busch Cc: Sagi Grimberg, linux-nvme, Rafael.Antognolli, axboe, jonathan.derrick, j.naumann, hch, linux-block On Mon, Nov 07, 2016 at 01:45:42PM -0500, Keith Busch wrote: > On Tue, Nov 01, 2016 at 10:18:13AM +0200, Sagi Grimberg wrote: > > > - spin_lock_irq(&nvmeq->q_lock); > > > + spin_lock_irqsave(&nvmeq->q_lock, flags); > > > if (unlikely(nvmeq->cq_vector < 0)) { > > > if (ns && !test_bit(NVME_NS_DEAD, &ns->flags)) > > > ret = BLK_MQ_RQ_QUEUE_BUSY; > > > else > > > ret = BLK_MQ_RQ_QUEUE_ERROR; > > > - spin_unlock_irq(&nvmeq->q_lock); > > > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); > > > goto out; > > > } > > > __nvme_submit_cmd(nvmeq, &cmnd); > > > nvme_process_cq(nvmeq); > > > - spin_unlock_irq(&nvmeq->q_lock); > > > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); > > > > No documentation why this is needed... > > Let's forget documenting why it's needed; this solution should instead > figure out a way to make it so it's not needed. This is some code that was used for previous iterations while we were testing. We missed this and some other things in this patch set when we were cleaning up. It's gone from V2 as well as the other weirdness in the patch. ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 5/6] nvme: Add unlock_from_suspend @ 2016-11-07 18:33 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-11-07 18:33 UTC (permalink / raw) On Mon, Nov 07, 2016@01:45:42PM -0500, Keith Busch wrote: > On Tue, Nov 01, 2016@10:18:13AM +0200, Sagi Grimberg wrote: > > > - spin_lock_irq(&nvmeq->q_lock); > > > + spin_lock_irqsave(&nvmeq->q_lock, flags); > > > if (unlikely(nvmeq->cq_vector < 0)) { > > > if (ns && !test_bit(NVME_NS_DEAD, &ns->flags)) > > > ret = BLK_MQ_RQ_QUEUE_BUSY; > > > else > > > ret = BLK_MQ_RQ_QUEUE_ERROR; > > > - spin_unlock_irq(&nvmeq->q_lock); > > > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); > > > goto out; > > > } > > > __nvme_submit_cmd(nvmeq, &cmnd); > > > nvme_process_cq(nvmeq); > > > - spin_unlock_irq(&nvmeq->q_lock); > > > + spin_unlock_irqrestore(&nvmeq->q_lock, flags); > > > > No documentation why this is needed... > > Let's forget documenting why it's needed; this solution should instead > figure out a way to make it so it's not needed. This is some code that was used for previous iterations while we were testing. We missed this and some other things in this patch set when we were cleaning up. It's gone from V2 as well as the other weirdness in the patch. ^ permalink raw reply [flat|nested] 32+ messages in thread
* [RFC PATCH 6/6] block: ioctl: Wire up Sed to block ioctls 2016-10-31 21:58 ` Scott Bauer @ 2016-10-31 21:58 ` Scott Bauer -1 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) To: linux-nvme Cc: Rafael.Antognolli, axboe, keith.busch, jonathan.derrick, j.naumann, hch, linux-block, Scott Bauer Signed-off-by: Scott Bauer <scott.bauer@intel.com> Signed-off-by: Rafael Antognolli <Rafael.Antognolli@intel.com> --- block/compat_ioctl.c | 14 ++++ block/ioctl.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 213 insertions(+), 1 deletion(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 556826a..2b83019 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -10,6 +10,7 @@ #include <linux/syscalls.h> #include <linux/types.h> #include <linux/uaccess.h> +#include <linux/sed.h> static int compat_put_ushort(unsigned long arg, unsigned short val) { @@ -746,6 +747,19 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) case BLKTRACETEARDOWN: /* compatible */ ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); return ret; + case IOC_SED_SAVE: + case IOC_SED_LOCK_UNLOCK: + case IOC_SED_TAKE_OWNERSHIP: + case IOC_SED_ACTIVATE_LSP: + case IOC_SED_SET_PW: + case IOC_SED_ACTIVATE_USR: + case IOC_SED_REVERT_TPR: + case IOC_SED_LR_SETUP: + case IOC_SED_ADD_USR_TO_LR: + case IOC_SED_ENABLE_DISABLE_MBR: + case IOC_SED_ERASE_LR: + return blkdev_ioctl(bdev, mode, cmd, + (unsigned long)compat_ptr(arg)); default: if (disk->fops->compat_ioctl) ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); diff --git a/block/ioctl.c b/block/ioctl.c index 755119c..f5c971b 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -8,6 +8,7 @@ #include <linux/fs.h> #include <linux/blktrace_api.h> #include <linux/pr.h> +#include <linux/sed.h> #include <asm/uaccess.h> static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg) @@ -392,6 +393,181 @@ static int blkdev_pr_clear(struct block_device *bdev, return ops->pr_clear(bdev, c.key); } +static int blkdev_sed_save(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_save(bdev, &k); +} + +static int blkdev_sed_lock_unlock(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_lock_unlock(bdev, &k); +} + +static int blkdev_sed_take_ownership(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_take_ownership(bdev, &k); +} + +static int blkdev_sed_activate_lsp(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_activate_lsp(bdev, &k); +} + +static int blkdev_sed_set_pw(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_set_pw(bdev, &k); +} + +static int blkdev_sed_activate_user(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + return sed_activate_user(bdev, &k); +} + +static int blkdev_sed_reverttper(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_reverttper(bdev, &k); +} + +static int blkdev_sed_setuplr(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_setup_locking_range(bdev, &k); +} + +static int blkdev_sed_add_usr_to_lr(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_adduser_to_lr(bdev, &k); +} + +static int blkdev_sed_do_mbr(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_do_mbr(bdev, &k); +} + +static int blkdev_sed_erase_lr(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_erase_lr(bdev, &k); +} + /* * Is it an unrecognized ioctl? The correct returns are either * ENOTTY (final) or ENOIOCTLCMD ("I don't know this one, try a @@ -551,7 +727,7 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, return put_ushort(arg, !blk_queue_nonrot(bdev_get_queue(bdev))); case BLKRASET: case BLKFRASET: - if(!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN)) return -EACCES; bdi = blk_get_backing_dev_info(bdev); bdi->ra_pages = (arg * 512) / PAGE_SIZE; @@ -586,6 +762,28 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, return blkdev_pr_preempt(bdev, argp, true); case IOC_PR_CLEAR: return blkdev_pr_clear(bdev, argp); + case IOC_SED_SAVE: + return blkdev_sed_save(bdev, argp); + case IOC_SED_LOCK_UNLOCK: + return blkdev_sed_lock_unlock(bdev, argp); + case IOC_SED_TAKE_OWNERSHIP: + return blkdev_sed_take_ownership(bdev, argp); + case IOC_SED_ACTIVATE_LSP: + return blkdev_sed_activate_lsp(bdev, argp); + case IOC_SED_SET_PW: + return blkdev_sed_set_pw(bdev, argp); + case IOC_SED_ACTIVATE_USR: + return blkdev_sed_activate_user(bdev, argp); + case IOC_SED_REVERT_TPR: + return blkdev_sed_reverttper(bdev, argp); + case IOC_SED_LR_SETUP: + return blkdev_sed_setuplr(bdev, argp); + case IOC_SED_ADD_USR_TO_LR: + return blkdev_sed_add_usr_to_lr(bdev, argp); + case IOC_SED_ENABLE_DISABLE_MBR: + return blkdev_sed_do_mbr(bdev, argp); + case IOC_SED_ERASE_LR: + return blkdev_sed_erase_lr(bdev, argp); default: return __blkdev_driver_ioctl(bdev, mode, cmd, arg); } -- 2.7.4 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* [RFC PATCH 6/6] block: ioctl: Wire up Sed to block ioctls @ 2016-10-31 21:58 ` Scott Bauer 0 siblings, 0 replies; 32+ messages in thread From: Scott Bauer @ 2016-10-31 21:58 UTC (permalink / raw) Signed-off-by: Scott Bauer <scott.bauer at intel.com> Signed-off-by: Rafael Antognolli <Rafael.Antognolli at intel.com> --- block/compat_ioctl.c | 14 ++++ block/ioctl.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 213 insertions(+), 1 deletion(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 556826a..2b83019 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -10,6 +10,7 @@ #include <linux/syscalls.h> #include <linux/types.h> #include <linux/uaccess.h> +#include <linux/sed.h> static int compat_put_ushort(unsigned long arg, unsigned short val) { @@ -746,6 +747,19 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) case BLKTRACETEARDOWN: /* compatible */ ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); return ret; + case IOC_SED_SAVE: + case IOC_SED_LOCK_UNLOCK: + case IOC_SED_TAKE_OWNERSHIP: + case IOC_SED_ACTIVATE_LSP: + case IOC_SED_SET_PW: + case IOC_SED_ACTIVATE_USR: + case IOC_SED_REVERT_TPR: + case IOC_SED_LR_SETUP: + case IOC_SED_ADD_USR_TO_LR: + case IOC_SED_ENABLE_DISABLE_MBR: + case IOC_SED_ERASE_LR: + return blkdev_ioctl(bdev, mode, cmd, + (unsigned long)compat_ptr(arg)); default: if (disk->fops->compat_ioctl) ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); diff --git a/block/ioctl.c b/block/ioctl.c index 755119c..f5c971b 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -8,6 +8,7 @@ #include <linux/fs.h> #include <linux/blktrace_api.h> #include <linux/pr.h> +#include <linux/sed.h> #include <asm/uaccess.h> static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg) @@ -392,6 +393,181 @@ static int blkdev_pr_clear(struct block_device *bdev, return ops->pr_clear(bdev, c.key); } +static int blkdev_sed_save(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_save(bdev, &k); +} + +static int blkdev_sed_lock_unlock(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_lock_unlock(bdev, &k); +} + +static int blkdev_sed_take_ownership(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_take_ownership(bdev, &k); +} + +static int blkdev_sed_activate_lsp(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_activate_lsp(bdev, &k); +} + +static int blkdev_sed_set_pw(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_set_pw(bdev, &k); +} + +static int blkdev_sed_activate_user(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + return sed_activate_user(bdev, &k); +} + +static int blkdev_sed_reverttper(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_reverttper(bdev, &k); +} + +static int blkdev_sed_setuplr(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_setup_locking_range(bdev, &k); +} + +static int blkdev_sed_add_usr_to_lr(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_adduser_to_lr(bdev, &k); +} + +static int blkdev_sed_do_mbr(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_do_mbr(bdev, &k); +} + +static int blkdev_sed_erase_lr(struct block_device *bdev, + struct sed_key __user *arg) +{ + const struct sec_ops *ops = bdev->bd_disk->fops->sec_ops; + struct sed_key k; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!ops || !ops->send || !ops->recv) + return -EOPNOTSUPP; + if (copy_from_user(&k, arg, sizeof(k))) + return -EFAULT; + + return sed_erase_lr(bdev, &k); +} + /* * Is it an unrecognized ioctl? The correct returns are either * ENOTTY (final) or ENOIOCTLCMD ("I don't know this one, try a @@ -551,7 +727,7 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, return put_ushort(arg, !blk_queue_nonrot(bdev_get_queue(bdev))); case BLKRASET: case BLKFRASET: - if(!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN)) return -EACCES; bdi = blk_get_backing_dev_info(bdev); bdi->ra_pages = (arg * 512) / PAGE_SIZE; @@ -586,6 +762,28 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, return blkdev_pr_preempt(bdev, argp, true); case IOC_PR_CLEAR: return blkdev_pr_clear(bdev, argp); + case IOC_SED_SAVE: + return blkdev_sed_save(bdev, argp); + case IOC_SED_LOCK_UNLOCK: + return blkdev_sed_lock_unlock(bdev, argp); + case IOC_SED_TAKE_OWNERSHIP: + return blkdev_sed_take_ownership(bdev, argp); + case IOC_SED_ACTIVATE_LSP: + return blkdev_sed_activate_lsp(bdev, argp); + case IOC_SED_SET_PW: + return blkdev_sed_set_pw(bdev, argp); + case IOC_SED_ACTIVATE_USR: + return blkdev_sed_activate_user(bdev, argp); + case IOC_SED_REVERT_TPR: + return blkdev_sed_reverttper(bdev, argp); + case IOC_SED_LR_SETUP: + return blkdev_sed_setuplr(bdev, argp); + case IOC_SED_ADD_USR_TO_LR: + return blkdev_sed_add_usr_to_lr(bdev, argp); + case IOC_SED_ENABLE_DISABLE_MBR: + return blkdev_sed_do_mbr(bdev, argp); + case IOC_SED_ERASE_LR: + return blkdev_sed_erase_lr(bdev, argp); default: return __blkdev_driver_ioctl(bdev, mode, cmd, arg); } -- 2.7.4 ^ permalink raw reply related [flat|nested] 32+ messages in thread
end of thread, other threads:[~2016-11-10 23:23 UTC | newest] Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-10-31 21:58 [RFC PATCH 0/6] Sed Opal Scott Bauer 2016-10-31 21:58 ` Scott Bauer 2016-10-31 21:58 ` [RFC PATCH 1/6] Include: Add definitions for sed Scott Bauer 2016-10-31 21:58 ` Scott Bauer 2016-10-31 21:58 ` [RFC PATCH 2/6] lib: Add Sed-opal library Scott Bauer 2016-10-31 21:58 ` Scott Bauer 2016-11-01 18:56 ` Jon Derrick 2016-11-01 18:56 ` Jon Derrick 2016-10-31 21:58 ` [RFC PATCH 3/6] lib: Add Sed to Kconfig and Makefile Scott Bauer 2016-10-31 21:58 ` Scott Bauer 2016-10-31 21:58 ` [RFC PATCH 4/6] include: Add sec_ops to block device operations Scott Bauer 2016-10-31 21:58 ` Scott Bauer 2016-10-31 21:58 ` [RFC PATCH 5/6] nvme: Add unlock_from_suspend Scott Bauer 2016-10-31 21:58 ` Scott Bauer 2016-11-01 8:18 ` Sagi Grimberg 2016-11-01 8:18 ` Sagi Grimberg 2016-11-01 13:57 ` Christoph Hellwig 2016-11-01 13:57 ` Christoph Hellwig 2016-11-01 14:40 ` Scott Bauer 2016-11-01 14:40 ` Scott Bauer 2016-11-10 23:01 ` Scott Bauer 2016-11-10 23:01 ` Scott Bauer 2016-11-10 23:23 ` Keith Busch 2016-11-10 23:23 ` Keith Busch 2016-11-10 23:19 ` Christoph Hellwig 2016-11-10 23:19 ` Christoph Hellwig 2016-11-07 18:45 ` Keith Busch 2016-11-07 18:45 ` Keith Busch 2016-11-07 18:33 ` Scott Bauer 2016-11-07 18:33 ` Scott Bauer 2016-10-31 21:58 ` [RFC PATCH 6/6] block: ioctl: Wire up Sed to block ioctls Scott Bauer 2016-10-31 21:58 ` Scott Bauer
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.