Opal: Add Opal library
First submission. Implemented part of the Opal library and "scan" function. Can be invoked by nvme_manage. Change-Id: Iba86d86dd3af06a06b6805120ee5005af8183459 Signed-off-by: Chunyang Hui <chunyang.hui@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/439335 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: yidong0635 <dongx.yi@intel.com> Reviewed-by: GangCao <gang.cao@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
aeb3dc9d2e
commit
55f5b205c5
@ -77,6 +77,11 @@ New `get_spdk_version` RPC method is introduced to get version info of the runni
|
|||||||
The `start_nbd_disk` RPC method now take nbd_device as an optional parameter. If nbd_device
|
The `start_nbd_disk` RPC method now take nbd_device as an optional parameter. If nbd_device
|
||||||
is specified, use that specified nbd device. If it's not specified, pick available one.
|
is specified, use that specified nbd device. If it's not specified, pick available one.
|
||||||
|
|
||||||
|
### Opal
|
||||||
|
|
||||||
|
Add Opal scan support for NVMe to check whether it supports SED Opal and dump
|
||||||
|
device info. nvme_manage tool can be used to invoke this.
|
||||||
|
|
||||||
## v19.01:
|
## v19.01:
|
||||||
|
|
||||||
### ocf bdev
|
### ocf bdev
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "spdk/env.h"
|
#include "spdk/env.h"
|
||||||
#include "spdk/string.h"
|
#include "spdk/string.h"
|
||||||
#include "spdk/util.h"
|
#include "spdk/util.h"
|
||||||
|
#include "spdk/opal.h"
|
||||||
|
|
||||||
#define MAX_DEVS 64
|
#define MAX_DEVS 64
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ struct dev {
|
|||||||
const struct spdk_nvme_ctrlr_data *cdata;
|
const struct spdk_nvme_ctrlr_data *cdata;
|
||||||
struct spdk_nvme_ns_data *common_ns_data;
|
struct spdk_nvme_ns_data *common_ns_data;
|
||||||
int outstanding_admin_cmds;
|
int outstanding_admin_cmds;
|
||||||
|
struct spdk_opal_dev *opal_dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dev devs[MAX_DEVS];
|
static struct dev devs[MAX_DEVS];
|
||||||
@ -140,7 +142,8 @@ static void usage(void)
|
|||||||
printf("\t[5: detach namespace from controller]\n");
|
printf("\t[5: detach namespace from controller]\n");
|
||||||
printf("\t[6: format namespace or controller]\n");
|
printf("\t[6: format namespace or controller]\n");
|
||||||
printf("\t[7: firmware update]\n");
|
printf("\t[7: firmware update]\n");
|
||||||
printf("\t[8: quit]\n");
|
printf("\t[8: opal scan]\n");
|
||||||
|
printf("\t[9: quit]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -850,6 +853,108 @@ update_firmware_image(void)
|
|||||||
spdk_dma_free(fw_image);
|
spdk_dma_free(fw_image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void spdk_dump_opal_info(struct spdk_opal_info *opal)
|
||||||
|
{
|
||||||
|
if (!opal->opal_ssc_dev) {
|
||||||
|
SPDK_ERRLOG("This device is not Opal enabled. Not Supported!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opal->tper) {
|
||||||
|
printf("\nOpal TPer feature:\n");
|
||||||
|
printf("ACKNACK = %s", (opal->tper_acknack ? "Y, " : "N, "));
|
||||||
|
printf("ASYNC = %s", (opal->tper_async ? "Y, " : "N, "));
|
||||||
|
printf("BufferManagement = %s\n", (opal->tper_buffer_mgt ? "Y, " : "N, "));
|
||||||
|
printf("ComIDManagement = %s", (opal->tper_comid_mgt ? "Y, " : "N, "));
|
||||||
|
printf("Streaming = %s", (opal->tper_streaming ? "Y, " : "N, "));
|
||||||
|
printf("Sync = %s\n", (opal->tper_sync ? "Y" : "N"));
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opal->locking) {
|
||||||
|
printf("Opal Locking feature:\n");
|
||||||
|
printf("Locked = %s", (opal->locking_locked ? "Y, " : "N, "));
|
||||||
|
printf("Locking Enabled = %s", (opal->locking_locking_enabled ? "Y, " : "N, "));
|
||||||
|
printf("Locking supported = %s\n", (opal->locking_locking_supported ? "Y" : "N"));
|
||||||
|
|
||||||
|
printf("MBR done = %s", (opal->locking_mbr_done ? "Y, " : "N, "));
|
||||||
|
printf("MBR enabled = %s", (opal->locking_mbr_enabled ? "Y, " : "N, "));
|
||||||
|
printf("Media encrypt = %s\n", (opal->locking_media_encrypt ? "Y" : "N"));
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opal->geometry) {
|
||||||
|
printf("Opal Geometry feature:\n");
|
||||||
|
printf("Align = %s", (opal->geometry_align ? "Y, " : "N, "));
|
||||||
|
printf("Logical block size = %d, ", opal->geometry_logical_block_size);
|
||||||
|
printf("Lowest aligned LBA = %ld\n", opal->geometry_lowest_aligned_lba);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opal->single_user_mode) {
|
||||||
|
printf("Opal Single User Mode feature:\n");
|
||||||
|
printf("Any in SUM = %s", (opal->single_user_any ? "Y, " : "N, "));
|
||||||
|
printf("All in SUM = %s", (opal->single_user_all ? "Y, " : "N, "));
|
||||||
|
printf("Policy: %s Authority,\n", (opal->single_user_policy ? "Admin" : "Users"));
|
||||||
|
printf("Number of locking objects = %d\n ", opal->single_user_locking_objects);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opal->datastore) {
|
||||||
|
printf("Opal DataStore feature:\n");
|
||||||
|
printf("Table alignment = %d, ", opal->datastore_alignment);
|
||||||
|
printf("Max number of tables = %d, ", opal->datastore_max_tables);
|
||||||
|
printf("Max size of tables = %d\n", opal->datastore_max_table_size);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opal->opal_v100) {
|
||||||
|
printf("Opal V100 feature:\n");
|
||||||
|
printf("Base comID = %d, ", opal->opal_v100_base_comid);
|
||||||
|
printf("Number of comIDs = %d, ", opal->opal_v100_num_comid);
|
||||||
|
printf("Range crossing = %s\n", (opal->opal_v100_range_crossing ? "N" : "Y"));
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opal->opal_v200) {
|
||||||
|
printf("Opal V200 feature:\n");
|
||||||
|
printf("Base comID = %d, ", opal->opal_v200_base_comid);
|
||||||
|
printf("Number of comIDs = %d, ", opal->opal_v200_num_comid);
|
||||||
|
printf("Initial PIN = %d,\n", opal->opal_v200_initial_pin);
|
||||||
|
printf("Reverted PIN = %d, ", opal->opal_v200_reverted_pin);
|
||||||
|
printf("Number of admins = %d, ", opal->opal_v200_num_admin);
|
||||||
|
printf("Number of users = %d\n", opal->opal_v200_num_user);
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_opal(void)
|
||||||
|
{
|
||||||
|
struct dev *iter;
|
||||||
|
|
||||||
|
foreach_dev(iter) {
|
||||||
|
if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
|
||||||
|
iter->opal_dev = spdk_opal_init_dev(iter->ctrlr);
|
||||||
|
if (iter->opal_dev == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (spdk_opal_supported(iter->opal_dev)) {
|
||||||
|
printf("\n\nOpal Supported:\n");
|
||||||
|
display_controller(iter, CONTROLLER_DISPLAY_SIMPLISTIC);
|
||||||
|
spdk_opal_scan(iter->opal_dev);
|
||||||
|
spdk_dump_opal_info(spdk_opal_get_info(iter->opal_dev));
|
||||||
|
}
|
||||||
|
spdk_opal_close(iter->opal_dev);
|
||||||
|
} else {
|
||||||
|
printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\n",
|
||||||
|
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
|
||||||
|
printf("%04x:%02x:%02x.%02x: Opal Not Supported\n\n\n",
|
||||||
|
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
args_usage(const char *program_name)
|
args_usage(const char *program_name)
|
||||||
{
|
{
|
||||||
@ -943,6 +1048,9 @@ int main(int argc, char **argv)
|
|||||||
update_firmware_image();
|
update_firmware_image();
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
|
test_opal();
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
exit_flag = true;
|
exit_flag = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
145
include/spdk/opal.h
Normal file
145
include/spdk/opal.h
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright (c) Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPDK_OPAL_H
|
||||||
|
#define SPDK_OPAL_H
|
||||||
|
|
||||||
|
#include "spdk/stdinc.h"
|
||||||
|
#include "spdk/nvme.h"
|
||||||
|
#include "spdk/log.h"
|
||||||
|
#include "spdk/endian.h"
|
||||||
|
#include "spdk/string.h"
|
||||||
|
|
||||||
|
#define SPDK_OPAL_NOT_SUPPORTED 0xFF
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Architecture Core Spec v2.01 r1.00
|
||||||
|
* 5.1.5 Method Status Codes
|
||||||
|
*/
|
||||||
|
#define SPDK_OPAL_FAILED 0x3F
|
||||||
|
|
||||||
|
static const char *const spdk_opal_errors[] = {
|
||||||
|
"SUCCESS",
|
||||||
|
"NOT AUTHORIZED",
|
||||||
|
"OBSOLETE/UNKNOWN ERROR",
|
||||||
|
"SP BUSY",
|
||||||
|
"SP FAILED",
|
||||||
|
"SP DISABLED",
|
||||||
|
"SP FROZEN",
|
||||||
|
"NO SESSIONS AVAILABLE",
|
||||||
|
"UNIQUENESS CONFLICT",
|
||||||
|
"INSUFFICIENT SPACE",
|
||||||
|
"INSUFFICIENT ROWS",
|
||||||
|
"UNKNOWN ERROR",
|
||||||
|
"INVALID PARAMETER",
|
||||||
|
"OBSOLETE/UNKNOWN ERROR",
|
||||||
|
"UNKNOWN ERROR",
|
||||||
|
"TPER MALFUNCTION",
|
||||||
|
"TRANSACTION FAILURE",
|
||||||
|
"RESPONSE OVERFLOW",
|
||||||
|
"AUTHORITY LOCKED OUT",
|
||||||
|
};
|
||||||
|
|
||||||
|
enum spdk_opal_cmd {
|
||||||
|
OPAL_CMD_SAVE,
|
||||||
|
OPAL_CMD_LOCK_UNLOCK,
|
||||||
|
OPAL_CMD_TAKE_OWNERSHIP,
|
||||||
|
OPAL_CMD_ACTIVATE_LSP, /* locking sp */
|
||||||
|
OPAL_CMD_SET_NEW_PASSWD,
|
||||||
|
OPAL_CMD_ACTIVATE_USER,
|
||||||
|
OPAL_CMD_REVERT_TPER,
|
||||||
|
OPAL_CMD_SETUP_LOCKING_RANGE,
|
||||||
|
OPAL_CMD_ADD_USER_TO_LOCKING_RANGE,
|
||||||
|
OPAL_CMD_ENABLE_DISABLE_SHADOW_MBR,
|
||||||
|
OPAL_CMD_ERASE_LOCKING_RANGE,
|
||||||
|
OPAL_CMD_SECURE_ERASE_LOCKING_RANGE,
|
||||||
|
OPAL_CMD_INITIAL_SETUP,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_info {
|
||||||
|
uint8_t tper : 1;
|
||||||
|
uint8_t locking : 1;
|
||||||
|
uint8_t geometry : 1;
|
||||||
|
uint8_t single_user_mode : 1;
|
||||||
|
uint8_t datastore : 1;
|
||||||
|
uint8_t opal_v200 : 1;
|
||||||
|
uint8_t opal_v100 : 1;
|
||||||
|
uint8_t vendor_specific : 1;
|
||||||
|
uint8_t opal_ssc_dev : 1;
|
||||||
|
uint8_t tper_acknack : 1;
|
||||||
|
uint8_t tper_async : 1;
|
||||||
|
uint8_t tper_buffer_mgt : 1;
|
||||||
|
uint8_t tper_comid_mgt : 1;
|
||||||
|
uint8_t tper_streaming : 1;
|
||||||
|
uint8_t tper_sync : 1;
|
||||||
|
uint8_t locking_locked : 1;
|
||||||
|
uint8_t locking_locking_enabled : 1;
|
||||||
|
uint8_t locking_locking_supported : 1;
|
||||||
|
uint8_t locking_mbr_done : 1;
|
||||||
|
uint8_t locking_mbr_enabled : 1;
|
||||||
|
uint8_t locking_media_encrypt : 1;
|
||||||
|
uint8_t geometry_align : 1;
|
||||||
|
uint64_t geometry_alignment_granularity;
|
||||||
|
uint32_t geometry_logical_block_size;
|
||||||
|
uint64_t geometry_lowest_aligned_lba;
|
||||||
|
uint8_t single_user_any : 1;
|
||||||
|
uint8_t single_user_all : 1;
|
||||||
|
uint8_t single_user_policy : 1;
|
||||||
|
uint32_t single_user_locking_objects;
|
||||||
|
uint16_t datastore_max_tables;
|
||||||
|
uint32_t datastore_max_table_size;
|
||||||
|
uint32_t datastore_alignment;
|
||||||
|
uint16_t opal_v100_base_comid;
|
||||||
|
uint16_t opal_v100_num_comid;
|
||||||
|
uint8_t opal_v100_range_crossing : 1;
|
||||||
|
uint16_t opal_v200_base_comid;
|
||||||
|
uint16_t opal_v200_num_comid;
|
||||||
|
uint8_t opal_v200_initial_pin;
|
||||||
|
uint8_t opal_v200_reverted_pin;
|
||||||
|
uint16_t opal_v200_num_admin;
|
||||||
|
uint16_t opal_v200_num_user;
|
||||||
|
uint8_t opal_v200_range_crossing : 1;
|
||||||
|
uint16_t vu_feature_code; /* vendor specific feature */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_dev;
|
||||||
|
|
||||||
|
struct spdk_opal_dev *spdk_opal_init_dev(void *dev_handler);
|
||||||
|
|
||||||
|
void spdk_opal_scan(struct spdk_opal_dev *dev);
|
||||||
|
void spdk_opal_close(struct spdk_opal_dev *dev);
|
||||||
|
struct spdk_opal_info *spdk_opal_get_info(struct spdk_opal_dev *dev);
|
||||||
|
|
||||||
|
bool spdk_opal_supported(struct spdk_opal_dev *dev);
|
||||||
|
|
||||||
|
#endif
|
376
include/spdk/opal_spec.h
Normal file
376
include/spdk/opal_spec.h
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright (c) Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPDK_OPAL_SPEC_H
|
||||||
|
#define SPDK_OPAL_SPEC_H
|
||||||
|
|
||||||
|
#include "spdk/stdinc.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Architecture Core Spec v2.01 r1.00
|
||||||
|
* 3.2.2.3 Tokens
|
||||||
|
*/
|
||||||
|
#define SPDK_TINY_ATOM_TYPE_MAX 0x7F
|
||||||
|
#define SPDK_SHORT_ATOM_TYPE_MAX 0xBF
|
||||||
|
#define SPDK_MEDIUM_ATOM_TYPE_MAX 0xDF
|
||||||
|
#define SPDK_LONG_ATOM_TYPE_MAX 0xE3
|
||||||
|
|
||||||
|
#define SPDK_TINY_ATOM_SIGN_FLAG 0x40
|
||||||
|
|
||||||
|
#define SPDK_TINY_ATOM_DATA_MASK 0x3F
|
||||||
|
|
||||||
|
#define SPDK_SHORT_ATOM_ID 0x80
|
||||||
|
#define SPDK_SHORT_ATOM_BYTESTRING_FLAG 0x20
|
||||||
|
#define SPDK_SHORT_ATOM_SIGN_FLAG 0x10
|
||||||
|
#define SPDK_SHORT_ATOM_LEN_MASK 0x0F
|
||||||
|
|
||||||
|
#define SPDK_MEDIUM_ATOM_ID 0xC0
|
||||||
|
#define SPDK_MEDIUM_ATOM_BYTESTRING_FLAG 0x10
|
||||||
|
|
||||||
|
#define SPDK_MEDIUM_ATOM_SIGN_FLAG 0x08
|
||||||
|
#define SPDK_MEDIUM_ATOM_LEN_MASK 0x07
|
||||||
|
|
||||||
|
#define SPDK_LONG_ATOM_ID 0xE0
|
||||||
|
#define SPDK_LONG_ATOM_BYTESTRING_FLAG 0x02
|
||||||
|
#define SPDK_LONG_ATOM_SIGN_FLAG 0x01
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Architecture Core Spec v2.01 r1.00
|
||||||
|
* Table-26 ComID management
|
||||||
|
*/
|
||||||
|
#define LV0_DISCOVERY_COMID 0x01
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Opal v2.01 r1.00
|
||||||
|
* 5.2.3 Type Table Modification
|
||||||
|
*/
|
||||||
|
#define OPAL_MANUFACTURED_INACTIVE 0x08
|
||||||
|
|
||||||
|
#define LOCKING_RANGE_NON_GLOBAL 0x03
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Feature Code
|
||||||
|
*/
|
||||||
|
enum spdk_lv0_discovery_feature_code {
|
||||||
|
/*
|
||||||
|
* TCG Storage Architecture Core Spec v2.01 r1.00
|
||||||
|
* 3.3.6 Level 0 Discovery
|
||||||
|
*/
|
||||||
|
FEATURECODE_TPER = 0x0001,
|
||||||
|
FEATURECODE_LOCKING = 0x0002,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Opal SSC 1.00 r3.00 Final
|
||||||
|
* 3.1.1.4 Opal SSC Feature
|
||||||
|
*/
|
||||||
|
FEATURECODE_OPALV100 = 0x0200,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Opal v2.01 r1.00
|
||||||
|
* 3.1.1.4 Geometry Reporting Feature
|
||||||
|
* 3.1.1.5 Opal SSC V2.00 Feature
|
||||||
|
*/
|
||||||
|
FEATURECODE_OPALV200 = 0x0203,
|
||||||
|
FEATURECODE_GEOMETRY = 0x0003,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Opal Feature Set Single User Mode v1.00 r2.00
|
||||||
|
* 4.2.1 Single User Mode Feature Descriptor
|
||||||
|
*/
|
||||||
|
FEATURECODE_SINGLEUSER = 0x0201,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Opal Feature Set Additional DataStore Tables v1.00 r1.00
|
||||||
|
* 4.1.1 DataStore Table Feature Descriptor
|
||||||
|
*/
|
||||||
|
FEATURECODE_DATASTORE = 0x0202,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Architecture Core Spec v2.01 r1.00
|
||||||
|
* 5.1.4 Abstract Type
|
||||||
|
*/
|
||||||
|
enum spdk_opal_token {
|
||||||
|
/* boolean */
|
||||||
|
SPDK_OPAL_TRUE = 0x01,
|
||||||
|
SPDK_OPAL_FALSE = 0x00,
|
||||||
|
|
||||||
|
/* cell_block
|
||||||
|
* 5.1.4.2.3 */
|
||||||
|
SPDK_OPAL_TABLE = 0x00,
|
||||||
|
SPDK_OPAL_STARTROW = 0x01,
|
||||||
|
SPDK_OPAL_ENDROW = 0x02,
|
||||||
|
SPDK_OPAL_STARTCOLUMN = 0x03,
|
||||||
|
SPDK_OPAL_ENDCOLUMN = 0x04,
|
||||||
|
SPDK_OPAL_VALUES = 0x01,
|
||||||
|
|
||||||
|
/* C_PIN table
|
||||||
|
* 5.3.2.12 */
|
||||||
|
SPDK_OPAL_PIN = 0x03,
|
||||||
|
|
||||||
|
/* locking table
|
||||||
|
* 5.7.2.2 */
|
||||||
|
SPDK_OPAL_RANGESTART = 0x03,
|
||||||
|
SPDK_OPAL_RANGELENGTH = 0x04,
|
||||||
|
SPDK_OPAL_READLOCKENABLED = 0x05,
|
||||||
|
SPDK_OPAL_WRITELOCKENABLED = 0x06,
|
||||||
|
SPDK_OPAL_READLOCKED = 0x07,
|
||||||
|
SPDK_OPAL_WRITELOCKED = 0x08,
|
||||||
|
SPDK_OPAL_ACTIVEKEY = 0x0A,
|
||||||
|
|
||||||
|
/* locking info table */
|
||||||
|
SPDK_OPAL_MAXRANGES = 0x04,
|
||||||
|
|
||||||
|
/* mbr control */
|
||||||
|
SPDK_OPAL_MBRENABLE = 0x01,
|
||||||
|
SPDK_OPAL_MBRDONE = 0x02,
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
SPDK_OPAL_HOSTPROPERTIES = 0x00,
|
||||||
|
|
||||||
|
/* control tokens */
|
||||||
|
SPDK_OPAL_STARTLIST = 0xF0,
|
||||||
|
SPDK_OPAL_ENDLIST = 0xF1,
|
||||||
|
SPDK_OPAL_STARTNAME = 0xF2,
|
||||||
|
SPDK_OPAL_ENDNAME = 0xF3,
|
||||||
|
SPDK_OPAL_CALL = 0xF8,
|
||||||
|
SPDK_OPAL_ENDOFDATA = 0xF9,
|
||||||
|
SPDK_OPAL_ENDOFSESSION = 0xFA,
|
||||||
|
SPDK_OPAL_STARTTRANSACTON = 0xFB,
|
||||||
|
SPDK_OPAL_ENDTRANSACTON = 0xFC,
|
||||||
|
SPDK_OPAL_EMPTYATOM = 0xFF,
|
||||||
|
SPDK_OPAL_WHERE = 0x00,
|
||||||
|
|
||||||
|
/* life cycle */
|
||||||
|
SPDK_OPAL_LIFECYCLE = 0x06,
|
||||||
|
|
||||||
|
/* Autority table */
|
||||||
|
SPDK_OPAL_AUTH_ENABLE = 0x05,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Architecture Core Spec v2.01 r1.00
|
||||||
|
* Table-39 Level0 Discovery Header Format
|
||||||
|
*/
|
||||||
|
struct spdk_d0_header {
|
||||||
|
uint32_t length;
|
||||||
|
uint32_t revision;
|
||||||
|
uint32_t reserved_0;
|
||||||
|
uint32_t reserved_1;
|
||||||
|
uint8_t vendor_specfic[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Architecture Core Spec v2.01 r1.00
|
||||||
|
* Table-42 TPer Feature Descriptor
|
||||||
|
*/
|
||||||
|
struct spdk_d0_tper_features {
|
||||||
|
uint16_t feature_code;
|
||||||
|
uint8_t reserved_0 : 4;
|
||||||
|
uint8_t version : 4;
|
||||||
|
uint8_t length;
|
||||||
|
uint8_t sync : 1;
|
||||||
|
uint8_t async : 1;
|
||||||
|
uint8_t acknack : 1;
|
||||||
|
uint8_t buffer_management : 1;
|
||||||
|
uint8_t streaming : 1;
|
||||||
|
uint8_t reserved_1 : 1;
|
||||||
|
uint8_t comid_management : 1;
|
||||||
|
uint8_t reserved_2 : 1;
|
||||||
|
|
||||||
|
uint32_t reserved_3;
|
||||||
|
uint32_t reserved_4;
|
||||||
|
uint32_t reserved_5;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Architecture Core Spec v2.01 r1.00
|
||||||
|
* Table-43 Locking Feature Descriptor
|
||||||
|
*/
|
||||||
|
struct spdk_d0_locking_features {
|
||||||
|
uint16_t feature_code;
|
||||||
|
uint8_t reserved_0 : 4;
|
||||||
|
uint8_t version : 4;
|
||||||
|
uint8_t length;
|
||||||
|
|
||||||
|
uint8_t locking_supported : 1;
|
||||||
|
uint8_t locking_enabled : 1;
|
||||||
|
uint8_t locked : 1;
|
||||||
|
uint8_t media_encryption : 1;
|
||||||
|
uint8_t mbr_enabled : 1;
|
||||||
|
uint8_t mbr_done : 1;
|
||||||
|
uint8_t reserved_1 : 1;
|
||||||
|
uint8_t reserved_2 : 1;
|
||||||
|
|
||||||
|
uint32_t reserved_3;
|
||||||
|
uint32_t reserved_4;
|
||||||
|
uint32_t reserved_5;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Opal Feature Set Single User Mode v1.00 r2.00
|
||||||
|
* 4.2.1 Single User Mode Feature Descriptor
|
||||||
|
*/
|
||||||
|
struct spdk_d0_sum {
|
||||||
|
uint16_t feature_code;
|
||||||
|
uint8_t reserved_0 : 4;
|
||||||
|
uint8_t version : 4;
|
||||||
|
uint8_t length;
|
||||||
|
uint32_t num_locking_objects;
|
||||||
|
|
||||||
|
uint8_t any : 1;
|
||||||
|
uint8_t all : 1;
|
||||||
|
uint8_t policy : 1;
|
||||||
|
uint8_t reserved_1 : 5;
|
||||||
|
|
||||||
|
uint8_t reserved_2;
|
||||||
|
uint16_t reserved_3;
|
||||||
|
uint32_t reserved_4;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Opal v2.01 r1.00
|
||||||
|
* 3.1.1.4 Geometry Reporting Feature
|
||||||
|
*/
|
||||||
|
struct spdk_d0_geo_features {
|
||||||
|
uint16_t feature_code;
|
||||||
|
uint8_t reserved_0 : 4;
|
||||||
|
uint8_t version : 4;
|
||||||
|
uint8_t length;
|
||||||
|
|
||||||
|
uint8_t align : 1;
|
||||||
|
uint8_t reserved_1 : 7;
|
||||||
|
uint8_t reserved_2[7];
|
||||||
|
uint32_t logical_block_size;
|
||||||
|
uint64_t alignment_granularity;
|
||||||
|
uint64_t lowest_aligned_lba;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Opal Feature Set Additional DataStore Tables v1.00 r1.00
|
||||||
|
* 4.1.1 DataStore Table Feature Descriptor
|
||||||
|
*/
|
||||||
|
struct spdk_d0_datastore_features {
|
||||||
|
uint16_t feature_code;
|
||||||
|
uint8_t reserved_0 : 4;
|
||||||
|
uint8_t version : 4;
|
||||||
|
uint8_t length;
|
||||||
|
|
||||||
|
uint16_t reserved_1;
|
||||||
|
uint16_t max_tables;
|
||||||
|
uint32_t max_table_size;
|
||||||
|
uint32_t alignment;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Opal SSC 1.00 r3.00 Final
|
||||||
|
* 3.1.1.4 Opal SSC Feature
|
||||||
|
*/
|
||||||
|
struct spdk_d0_opal_v100 {
|
||||||
|
uint16_t feature_code;
|
||||||
|
uint8_t reserved_0 : 4;
|
||||||
|
uint8_t version : 4;
|
||||||
|
uint8_t length;
|
||||||
|
uint16_t base_comid;
|
||||||
|
uint16_t number_comids;
|
||||||
|
uint8_t range_crossing : 1;
|
||||||
|
|
||||||
|
uint8_t reserved_1 : 7;
|
||||||
|
uint8_t reserved_2;
|
||||||
|
uint16_t reserved_3;
|
||||||
|
uint32_t reserved_4;
|
||||||
|
uint32_t reserved_5;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Opal v2.01 r1.00
|
||||||
|
* 3.1.1.4 Geometry Reporting Feature
|
||||||
|
* 3.1.1.5 Opal SSC V2.00 Feature
|
||||||
|
*/
|
||||||
|
struct spdk_d0_opal_v200 {
|
||||||
|
uint16_t featureCode;
|
||||||
|
uint8_t reserved_0 : 4;
|
||||||
|
uint8_t version : 4;
|
||||||
|
uint8_t length;
|
||||||
|
uint16_t base_comid;
|
||||||
|
uint16_t num_comids;
|
||||||
|
|
||||||
|
uint8_t range_crossing : 1;
|
||||||
|
uint8_t reserved_1 : 7;
|
||||||
|
|
||||||
|
uint16_t num_locking_admin_auth; /* Number of Locking SP Admin Authorities Supported */
|
||||||
|
uint16_t num_locking_user_auth;
|
||||||
|
uint8_t initial_pin;
|
||||||
|
uint8_t reverted_pin;
|
||||||
|
uint8_t reserved_2;
|
||||||
|
uint32_t reserved_3;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage Architecture Core Spec v2.01 r1.00
|
||||||
|
* 3.2.3 ComPackets, Packets & Subpackets
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* CommPacket header format
|
||||||
|
* (big-endian)
|
||||||
|
*/
|
||||||
|
struct spdk_opal_compacket {
|
||||||
|
uint32_t reserved;
|
||||||
|
uint8_t comid[2];
|
||||||
|
uint8_t extended_comid[2];
|
||||||
|
|
||||||
|
uint32_t outstanding_data;
|
||||||
|
uint32_t min_transfer;
|
||||||
|
uint32_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* packet header format */
|
||||||
|
struct spdk_opal_packet {
|
||||||
|
uint32_t session_tsn;
|
||||||
|
uint32_t session_hsn;
|
||||||
|
uint32_t seq_number;
|
||||||
|
|
||||||
|
uint16_t reserved;
|
||||||
|
uint16_t ack_type;
|
||||||
|
uint32_t acknowledgment;
|
||||||
|
uint32_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* data subpacket header */
|
||||||
|
struct spdk_opal_data_subpacket {
|
||||||
|
uint8_t reserved[6];
|
||||||
|
uint16_t kind;
|
||||||
|
uint32_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -724,6 +724,13 @@ struct spdk_scsi_pr_out_reg_and_move_param_list {
|
|||||||
};
|
};
|
||||||
SPDK_STATIC_ASSERT(sizeof(struct spdk_scsi_pr_out_reg_and_move_param_list) == 24, "Incorrect size");
|
SPDK_STATIC_ASSERT(sizeof(struct spdk_scsi_pr_out_reg_and_move_param_list) == 24, "Incorrect size");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SPC-4
|
||||||
|
* Table-258 SECURITY PROTOCOL field in SECURITY PROTOCOL IN command
|
||||||
|
*/
|
||||||
|
#define SPDK_SCSI_SECP_INFO 0x00
|
||||||
|
#define SPDK_SCSI_SECP_TCG 0x01
|
||||||
|
|
||||||
#define SPDK_SCSI_UNMAP_LBPU 1 << 7
|
#define SPDK_SCSI_UNMAP_LBPU 1 << 7
|
||||||
#define SPDK_SCSI_UNMAP_LBPWS 1 << 6
|
#define SPDK_SCSI_UNMAP_LBPWS 1 << 6
|
||||||
#define SPDK_SCSI_UNMAP_LBPWS10 1 << 5
|
#define SPDK_SCSI_UNMAP_LBPWS10 1 << 5
|
||||||
|
@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
|
|||||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||||
|
|
||||||
C_SRCS = nvme_ctrlr_cmd.c nvme_ctrlr.c nvme_fabric.c nvme_ns_cmd.c nvme_ns.c nvme_pcie.c nvme_qpair.c nvme.c nvme_quirks.c nvme_transport.c nvme_uevent.c nvme_ctrlr_ocssd_cmd.c \
|
C_SRCS = nvme_ctrlr_cmd.c nvme_ctrlr.c nvme_fabric.c nvme_ns_cmd.c nvme_ns.c nvme_pcie.c nvme_qpair.c nvme.c nvme_quirks.c nvme_transport.c nvme_uevent.c nvme_ctrlr_ocssd_cmd.c \
|
||||||
nvme_ns_ocssd_cmd.c nvme_tcp.c
|
nvme_ns_ocssd_cmd.c nvme_tcp.c nvme_opal.c
|
||||||
C_SRCS-$(CONFIG_RDMA) += nvme_rdma.c
|
C_SRCS-$(CONFIG_RDMA) += nvme_rdma.c
|
||||||
LIBNAME = nvme
|
LIBNAME = nvme
|
||||||
LOCAL_SYS_LIBS = -luuid
|
LOCAL_SYS_LIBS = -luuid
|
||||||
|
573
lib/nvme/nvme_opal.c
Normal file
573
lib/nvme/nvme_opal.c
Normal file
@ -0,0 +1,573 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright (c) Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include "spdk/opal.h"
|
||||||
|
#include "spdk_internal/event.h"
|
||||||
|
#include "spdk_internal/log.h"
|
||||||
|
#include "spdk/util.h"
|
||||||
|
|
||||||
|
#include "nvme_opal_internal.h"
|
||||||
|
|
||||||
|
typedef int (spdk_opal_cb)(struct spdk_opal_dev *dev);
|
||||||
|
|
||||||
|
static int opal_end_session_error(struct spdk_opal_dev *dev);
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
opal_error_to_human(int error)
|
||||||
|
{
|
||||||
|
if (error == SPDK_OPAL_FAILED) {
|
||||||
|
return "FAILED";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((size_t)error >= SPDK_COUNTOF(spdk_opal_errors) || error < 0) {
|
||||||
|
return "UNKNOWN ERROR";
|
||||||
|
}
|
||||||
|
|
||||||
|
return spdk_opal_errors[error];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_send_cmd(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
return spdk_nvme_ctrlr_security_send(dev->dev_handler, SPDK_SCSI_SECP_TCG, dev->comid,
|
||||||
|
0, dev->cmd, IO_BUFFER_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_recv_cmd(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
void *response = dev->resp;
|
||||||
|
struct spdk_opal_header *header = response;
|
||||||
|
int ret = 0;
|
||||||
|
uint64_t start = spdk_get_ticks();
|
||||||
|
uint64_t now;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = spdk_nvme_ctrlr_security_receive(dev->dev_handler, SPDK_SCSI_SECP_TCG, dev->comid,
|
||||||
|
0, dev->resp, IO_BUFFER_LENGTH);
|
||||||
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("Security Receive Error on dev = %p\n", dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
SPDK_DEBUGLOG(SPDK_LOG_OPAL, "outstanding_data=%d, minTransfer=%d\n",
|
||||||
|
header->com_packet.outstanding_data,
|
||||||
|
header->com_packet.min_transfer);
|
||||||
|
|
||||||
|
if (header->com_packet.outstanding_data == 0 &&
|
||||||
|
header->com_packet.min_transfer == 0) {
|
||||||
|
return 0; /* return if all the response data are ready by tper and received by host */
|
||||||
|
} else { /* check timeout */
|
||||||
|
now = spdk_get_ticks();
|
||||||
|
if (now - start > dev->timeout * spdk_get_ticks_hz()) {
|
||||||
|
SPDK_ERRLOG("Secutiy Receive Timeout on dev = %p\n", dev);
|
||||||
|
return 0x0F; /* TPer Malfunction */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(response, 0, IO_BUFFER_LENGTH);
|
||||||
|
} while (!ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_send_recv(struct spdk_opal_dev *dev, spdk_opal_cb *cb)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = opal_send_cmd(dev);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = opal_recv_cmd(dev);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return cb(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
opal_add_token_u8(int *err, struct spdk_opal_dev *dev, uint8_t token)
|
||||||
|
{
|
||||||
|
if (*err) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dev->cmd_pos >= IO_BUFFER_LENGTH - 1) {
|
||||||
|
SPDK_ERRLOG("Error adding u8: end of buffer.\n");
|
||||||
|
*err = -ERANGE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dev->cmd[dev->cmd_pos++] = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_cmd_finalize(struct spdk_opal_dev *dev, uint32_t hsn, uint32_t tsn, bool eod)
|
||||||
|
{
|
||||||
|
struct spdk_opal_header *hdr;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (eod) {
|
||||||
|
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDOFDATA);
|
||||||
|
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
|
||||||
|
opal_add_token_u8(&err, dev, 0);
|
||||||
|
opal_add_token_u8(&err, dev, 0);
|
||||||
|
opal_add_token_u8(&err, dev, 0);
|
||||||
|
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
SPDK_ERRLOG("Error finalizing command.\n");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr = (struct spdk_opal_header *)dev->cmd;
|
||||||
|
|
||||||
|
to_be32(&hdr->packet.session_tsn, tsn);
|
||||||
|
to_be32(&hdr->packet.session_hsn, hsn);
|
||||||
|
|
||||||
|
to_be32(&hdr->sub_packet.length, dev->cmd_pos - sizeof(*hdr));
|
||||||
|
while (dev->cmd_pos % 4) {
|
||||||
|
if (dev->cmd_pos >= IO_BUFFER_LENGTH) {
|
||||||
|
SPDK_ERRLOG("Error: Buffer overrun\n");
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
dev->cmd[dev->cmd_pos++] = 0;
|
||||||
|
}
|
||||||
|
to_be32(&hdr->packet.length, dev->cmd_pos - sizeof(hdr->com_packet) -
|
||||||
|
sizeof(hdr->packet));
|
||||||
|
to_be32(&hdr->com_packet.length, dev->cmd_pos - sizeof(hdr->com_packet));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_finalize_and_send(struct spdk_opal_dev *dev, bool eod, spdk_opal_cb cb)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = opal_cmd_finalize(dev, dev->hsn, dev->tsn, eod);
|
||||||
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("Error finalizing command buffer: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return opal_send_recv(dev, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
opal_clear_cmd(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
dev->cmd_pos = sizeof(struct spdk_opal_header);
|
||||||
|
memset(dev->cmd, 0, IO_BUFFER_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
opal_set_comid(struct spdk_opal_dev *dev, uint16_t comid)
|
||||||
|
{
|
||||||
|
struct spdk_opal_header *hdr = (struct spdk_opal_header *)dev->cmd;
|
||||||
|
|
||||||
|
hdr->com_packet.comid[0] = comid >> 8;
|
||||||
|
hdr->com_packet.comid[1] = comid;
|
||||||
|
hdr->com_packet.extended_comid[0] = 0;
|
||||||
|
hdr->com_packet.extended_comid[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_next(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
const struct spdk_opal_step *step;
|
||||||
|
int state = 0, error = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
step = &dev->steps[state];
|
||||||
|
if (!step->opal_fn) {
|
||||||
|
if (state != 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
SPDK_ERRLOG("First step is NULL\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error = step->opal_fn(dev, step->data);
|
||||||
|
if (error) {
|
||||||
|
SPDK_ERRLOG("Error on step function: %d with error %d: %s\n",
|
||||||
|
state, error,
|
||||||
|
opal_error_to_human(error));
|
||||||
|
if (state > 1) {
|
||||||
|
opal_end_session_error(dev);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state++;
|
||||||
|
} while (!error);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
opal_check_tper(struct spdk_opal_dev *dev, const void *data)
|
||||||
|
{
|
||||||
|
const struct spdk_d0_tper_features *tper = data;
|
||||||
|
struct spdk_opal_info *opal_info = dev->opal_info;
|
||||||
|
|
||||||
|
opal_info->opal_ssc_dev = 1;
|
||||||
|
opal_info->tper = 1;
|
||||||
|
opal_info->tper_acknack = tper->acknack;
|
||||||
|
opal_info->tper_async = tper->async;
|
||||||
|
opal_info->tper_buffer_mgt = tper->buffer_management;
|
||||||
|
opal_info->tper_comid_mgt = tper->comid_management;
|
||||||
|
opal_info->tper_streaming = tper->streaming;
|
||||||
|
opal_info->tper_sync = tper->sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check single user mode
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
opal_check_sum(struct spdk_opal_dev *dev, const void *data)
|
||||||
|
{
|
||||||
|
const struct spdk_d0_sum *sum = data;
|
||||||
|
uint32_t num_locking_objects = from_be32(&sum->num_locking_objects);
|
||||||
|
struct spdk_opal_info *opal_info = dev->opal_info;
|
||||||
|
|
||||||
|
if (num_locking_objects == 0) {
|
||||||
|
SPDK_NOTICELOG("Need at least one locking object.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
opal_info->single_user_mode = 1;
|
||||||
|
opal_info->single_user_locking_objects = num_locking_objects;
|
||||||
|
opal_info->single_user_any = sum->any;
|
||||||
|
opal_info->single_user_all = sum->all;
|
||||||
|
opal_info->single_user_policy = sum->policy;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
opal_check_lock(struct spdk_opal_dev *dev, const void *data)
|
||||||
|
{
|
||||||
|
const struct spdk_d0_locking_features *lock = data;
|
||||||
|
struct spdk_opal_info *opal_info = dev->opal_info;
|
||||||
|
|
||||||
|
opal_info->locking = 1;
|
||||||
|
opal_info->locking_locked = lock->locked;
|
||||||
|
opal_info->locking_locking_enabled = lock->locking_enabled;
|
||||||
|
opal_info->locking_locking_supported = lock->locking_supported;
|
||||||
|
opal_info->locking_mbr_done = lock->mbr_done;
|
||||||
|
opal_info->locking_mbr_enabled = lock->mbr_enabled;
|
||||||
|
opal_info->locking_media_encrypt = lock->media_encryption;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
opal_check_geometry(struct spdk_opal_dev *dev, const void *data)
|
||||||
|
{
|
||||||
|
const struct spdk_d0_geo_features *geo = data;
|
||||||
|
struct spdk_opal_info *opal_info = dev->opal_info;
|
||||||
|
uint64_t align = from_be64(&geo->alignment_granularity);
|
||||||
|
uint64_t lowest_lba = from_be64(&geo->lowest_aligned_lba);
|
||||||
|
|
||||||
|
dev->align = align;
|
||||||
|
dev->lowest_lba = lowest_lba;
|
||||||
|
|
||||||
|
opal_info->geometry = 1;
|
||||||
|
opal_info->geometry_align = geo->align;
|
||||||
|
opal_info->geometry_logical_block_size = from_be64(&geo->logical_block_size);
|
||||||
|
opal_info->geometry_lowest_aligned_lba = lowest_lba;
|
||||||
|
opal_info->geometry_alignment_granularity = align;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
opal_check_datastore(struct spdk_opal_dev *dev, const void *data)
|
||||||
|
{
|
||||||
|
const struct spdk_d0_datastore_features *datastore = data;
|
||||||
|
struct spdk_opal_info *opal_info = dev->opal_info;
|
||||||
|
|
||||||
|
opal_info->datastore = 1;
|
||||||
|
opal_info->datastore_max_tables = from_be16(&datastore->max_tables);
|
||||||
|
opal_info->datastore_max_table_size = from_be32(&datastore->max_table_size);
|
||||||
|
opal_info->datastore_alignment = from_be32(&datastore->alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t
|
||||||
|
opal_get_comid_v100(struct spdk_opal_dev *dev, const void *data)
|
||||||
|
{
|
||||||
|
const struct spdk_d0_opal_v100 *v100 = data;
|
||||||
|
struct spdk_opal_info *opal_info = dev->opal_info;
|
||||||
|
uint16_t base_comid = from_be16(&v100->base_comid);
|
||||||
|
|
||||||
|
opal_info->opal_v100 = 1;
|
||||||
|
opal_info->opal_v100_base_comid = base_comid;
|
||||||
|
opal_info->opal_v100_num_comid = from_be16(&v100->number_comids);
|
||||||
|
opal_info->opal_v100_range_crossing = v100->range_crossing;
|
||||||
|
|
||||||
|
return base_comid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t
|
||||||
|
opal_get_comid_v200(struct spdk_opal_dev *dev, const void *data)
|
||||||
|
{
|
||||||
|
const struct spdk_d0_opal_v200 *v200 = data;
|
||||||
|
struct spdk_opal_info *opal_info = dev->opal_info;
|
||||||
|
uint16_t base_comid = from_be16(&v200->base_comid);
|
||||||
|
|
||||||
|
opal_info->opal_v200 = 1;
|
||||||
|
opal_info->opal_v200_base_comid = base_comid;
|
||||||
|
opal_info->opal_v200_num_comid = from_be16(&v200->num_comids);
|
||||||
|
opal_info->opal_v200_range_crossing = v200->range_crossing;
|
||||||
|
opal_info->opal_v200_num_admin = from_be16(&v200->num_locking_admin_auth);
|
||||||
|
opal_info->opal_v200_num_user = from_be16(&v200->num_locking_user_auth);
|
||||||
|
|
||||||
|
opal_info->opal_v200_initial_pin = v200->initial_pin;
|
||||||
|
opal_info->opal_v200_reverted_pin = v200->reverted_pin;
|
||||||
|
|
||||||
|
return base_comid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_discovery0_end(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
bool found_com_id = false, supported = false, single_user = false;
|
||||||
|
const struct spdk_d0_header *hdr = (struct spdk_d0_header *)dev->resp;
|
||||||
|
const uint8_t *epos = dev->resp, *cpos = dev->resp;
|
||||||
|
uint16_t comid = 0;
|
||||||
|
uint32_t hlen = from_be32(&(hdr->length));
|
||||||
|
|
||||||
|
if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
|
||||||
|
SPDK_ERRLOG("Discovery length overflows buffer (%zu+%u)/%u\n",
|
||||||
|
sizeof(*hdr), hlen, IO_BUFFER_LENGTH);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
epos += hlen; /* end of buffer */
|
||||||
|
cpos += sizeof(*hdr); /* current position on buffer */
|
||||||
|
|
||||||
|
while (cpos < epos) {
|
||||||
|
const union spdk_discovery0_features *body =
|
||||||
|
(const union spdk_discovery0_features *)cpos;
|
||||||
|
uint16_t feature_code = from_be16(&(body->tper.feature_code));
|
||||||
|
|
||||||
|
switch (feature_code) {
|
||||||
|
case FEATURECODE_TPER:
|
||||||
|
opal_check_tper(dev, body);
|
||||||
|
break;
|
||||||
|
case FEATURECODE_SINGLEUSER:
|
||||||
|
single_user = opal_check_sum(dev, body);
|
||||||
|
break;
|
||||||
|
case FEATURECODE_GEOMETRY:
|
||||||
|
opal_check_geometry(dev, body);
|
||||||
|
break;
|
||||||
|
case FEATURECODE_LOCKING:
|
||||||
|
opal_check_lock(dev, body);
|
||||||
|
break;
|
||||||
|
case FEATURECODE_DATASTORE:
|
||||||
|
opal_check_datastore(dev, body);
|
||||||
|
break;
|
||||||
|
case FEATURECODE_OPALV100:
|
||||||
|
comid = opal_get_comid_v100(dev, body);
|
||||||
|
found_com_id = true;
|
||||||
|
supported = true;
|
||||||
|
break;
|
||||||
|
case FEATURECODE_OPALV200:
|
||||||
|
comid = opal_get_comid_v200(dev, body);
|
||||||
|
found_com_id = true;
|
||||||
|
supported = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SPDK_NOTICELOG("Unknow feature code: %d\n", feature_code);
|
||||||
|
}
|
||||||
|
cpos += body->tper.length + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supported == false) {
|
||||||
|
SPDK_ERRLOG("Opal Not Supported.\n");
|
||||||
|
return SPDK_OPAL_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (single_user == false) {
|
||||||
|
SPDK_NOTICELOG("Single User Mode Not Supported\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_com_id == false) {
|
||||||
|
SPDK_ERRLOG("Could not find OPAL comid for device. Returning early\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->comid = comid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_discovery0(struct spdk_opal_dev *dev, void *data)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memset(dev->resp, 0, IO_BUFFER_LENGTH);
|
||||||
|
dev->comid = LV0_DISCOVERY_COMID;
|
||||||
|
ret = opal_recv_cmd(dev);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return opal_discovery0_end(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
opal_setup_dev(struct spdk_opal_dev *dev,
|
||||||
|
const struct spdk_opal_step *steps)
|
||||||
|
{
|
||||||
|
dev->steps = steps;
|
||||||
|
dev->tsn = 0;
|
||||||
|
dev->hsn = 0;
|
||||||
|
dev->prev_data = NULL;
|
||||||
|
dev->timeout = SPDK_OPAL_TPER_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_end_session_cb(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
dev->hsn = 0;
|
||||||
|
dev->tsn = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_end_session(struct spdk_opal_dev *dev, void *data)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
bool eod = 0;
|
||||||
|
|
||||||
|
opal_clear_cmd(dev);
|
||||||
|
opal_set_comid(dev, dev->comid);
|
||||||
|
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDOFSESSION);
|
||||||
|
|
||||||
|
if (err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return opal_finalize_and_send(dev, eod, opal_end_session_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_end_session_error(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
const struct spdk_opal_step error_end_session[] = {
|
||||||
|
{ opal_end_session, },
|
||||||
|
{ NULL, }
|
||||||
|
};
|
||||||
|
dev->steps = error_end_session;
|
||||||
|
return opal_next(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_check_support(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
const struct spdk_opal_step steps[] = {
|
||||||
|
{ opal_discovery0, },
|
||||||
|
{ NULL, }
|
||||||
|
};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
opal_setup_dev(dev, steps);
|
||||||
|
ret = opal_next(dev);
|
||||||
|
if (ret == 0) {
|
||||||
|
dev->supported = true;
|
||||||
|
} else {
|
||||||
|
dev->supported = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_opal_close(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
free(dev->opal_info);
|
||||||
|
free(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct spdk_opal_dev *
|
||||||
|
spdk_opal_init_dev(void *dev_handler)
|
||||||
|
{
|
||||||
|
struct spdk_opal_dev *dev;
|
||||||
|
struct spdk_opal_info *info;
|
||||||
|
|
||||||
|
dev = calloc(1, sizeof(*dev));
|
||||||
|
if (!dev) {
|
||||||
|
SPDK_ERRLOG("Memory allocation failed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->dev_handler = dev_handler;
|
||||||
|
|
||||||
|
info = calloc(1, sizeof(struct spdk_opal_info));
|
||||||
|
if (info == NULL) {
|
||||||
|
free(dev);
|
||||||
|
SPDK_ERRLOG("Memory allocation failed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->opal_info = info;
|
||||||
|
if (opal_check_support(dev) != 0) {
|
||||||
|
SPDK_INFOLOG(SPDK_LOG_OPAL, "Opal is not supported on this device\n");
|
||||||
|
dev->supported = false;
|
||||||
|
}
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_opal_scan(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = opal_check_support(dev);
|
||||||
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("check opal support failed: %d\n", ret);
|
||||||
|
spdk_opal_close(dev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct spdk_opal_info *
|
||||||
|
spdk_opal_get_info(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
return dev->opal_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
spdk_opal_supported(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
return dev->supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log component for opal submodule */
|
||||||
|
SPDK_LOG_REGISTER_COMPONENT("opal", SPDK_LOG_OPAL)
|
337
lib/nvme/nvme_opal_internal.h
Normal file
337
lib/nvme/nvme_opal_internal.h
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright (c) Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPDK_OPAL_INTERNAL_H
|
||||||
|
#define SPDK_OPAL_INTERNAL_H
|
||||||
|
|
||||||
|
#include "spdk/opal_spec.h"
|
||||||
|
#include "spdk/opal.h"
|
||||||
|
#include "spdk/scsi_spec.h"
|
||||||
|
|
||||||
|
#define IO_BUFFER_LENGTH 2048
|
||||||
|
#define MAX_TOKS 64
|
||||||
|
#define OPAL_KEY_MAX 256
|
||||||
|
#define OPAL_UID_LENGTH 8
|
||||||
|
#define OPAL_MAX_LRS 8 /* minimum 8 defined by spec */
|
||||||
|
|
||||||
|
#define SPDK_OPAL_TPER_TIMEOUT 30 /* seconds */
|
||||||
|
|
||||||
|
#define GENERIC_HOST_SESSION_NUM 0x69
|
||||||
|
|
||||||
|
#define OPAL_INVAL_PARAM 12
|
||||||
|
|
||||||
|
#define SPDK_DTAERROR_NO_METHOD_STATUS 0x89
|
||||||
|
|
||||||
|
enum opal_token_type {
|
||||||
|
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_atom_width {
|
||||||
|
OPAL_WIDTH_TINY, /* 1 byte in length */
|
||||||
|
OPAL_WIDTH_SHORT, /* a 1-byte header and contain up to 15 bytes of data */
|
||||||
|
OPAL_WIDTH_MEDIUM, /* a 2-byte header and contain up to 2047 bytes of data */
|
||||||
|
OPAL_WIDTH_LONG, /* a 4-byte header and which contain up to 16,777,215 bytes of data */
|
||||||
|
OPAL_WIDTH_TOKEN
|
||||||
|
};
|
||||||
|
|
||||||
|
enum opal_uid_enum {
|
||||||
|
/* users */
|
||||||
|
UID_SMUID,
|
||||||
|
UID_THISSP,
|
||||||
|
UID_ADMINSP,
|
||||||
|
UID_LOCKINGSP,
|
||||||
|
UID_ANYBODY,
|
||||||
|
UID_SID,
|
||||||
|
UID_ADMIN1,
|
||||||
|
UID_USER1,
|
||||||
|
UID_USER2,
|
||||||
|
|
||||||
|
/* tables */
|
||||||
|
UID_LOCKINGRANGE_GLOBAL,
|
||||||
|
UID_LOCKINGRANGE_ACE_RDLOCKED,
|
||||||
|
UID_LOCKINGRANGE_ACE_WRLOCKED,
|
||||||
|
UID_MBRCONTROL,
|
||||||
|
UID_MBR,
|
||||||
|
UID_AUTHORITY_TABLE,
|
||||||
|
UID_C_PIN_TABLE,
|
||||||
|
UID_LOCKING_INFO_TABLE,
|
||||||
|
UID_PSID,
|
||||||
|
|
||||||
|
/* C_PIN_TABLE object ID's */
|
||||||
|
UID_C_PIN_MSID,
|
||||||
|
UID_C_PIN_SID,
|
||||||
|
UID_C_PIN_ADMIN1,
|
||||||
|
UID_C_PIN_USER1,
|
||||||
|
|
||||||
|
/* half UID's (only first 4 bytes used) */
|
||||||
|
UID_HALF_AUTHORITY_OBJ_REF,
|
||||||
|
UID_HALF_BOOLEAN_ACE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* enum for indexing the spdk_opal_method array */
|
||||||
|
enum opal_method_enum {
|
||||||
|
PROPERTIES_METHOD,
|
||||||
|
STARTSESSION_METHOD,
|
||||||
|
REVERT_METHOD,
|
||||||
|
ACTIVATE_METHOD,
|
||||||
|
NEXT_METHOD,
|
||||||
|
GETACL_METHOD,
|
||||||
|
GENKEY_METHOD,
|
||||||
|
REVERTSP_METHOD,
|
||||||
|
GET_METHOD,
|
||||||
|
SET_METHOD,
|
||||||
|
AUTHENTICATE_METHOD,
|
||||||
|
RANDOM_METHOD,
|
||||||
|
};
|
||||||
|
|
||||||
|
union spdk_discovery0_features {
|
||||||
|
struct spdk_d0_tper_features tper;
|
||||||
|
struct spdk_d0_locking_features locking;
|
||||||
|
struct spdk_d0_geo_features geometry;
|
||||||
|
struct spdk_d0_datastore_features datastore;
|
||||||
|
struct spdk_d0_sum sumode;
|
||||||
|
struct spdk_d0_opal_v200 opalv200;
|
||||||
|
struct spdk_d0_opal_v100 opalv100;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_session {
|
||||||
|
uint32_t sum; /* single user mode */
|
||||||
|
uint32_t who;
|
||||||
|
struct spdk_opal_key *opal_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_lock_unlock {
|
||||||
|
struct spdk_opal_session session;
|
||||||
|
uint32_t l_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_new_pw {
|
||||||
|
struct spdk_opal_session session_start;
|
||||||
|
struct spdk_opal_session new_user_pw;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t spdk_opal_uid[][OPAL_UID_LENGTH] = {
|
||||||
|
/* users */
|
||||||
|
[UID_SMUID] = /* Session Manager UID */
|
||||||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff },
|
||||||
|
[UID_THISSP] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
|
||||||
|
[UID_ADMINSP] =
|
||||||
|
{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01 },
|
||||||
|
[UID_LOCKINGSP] =
|
||||||
|
{ 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02 },
|
||||||
|
[UID_ANYBODY] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01 },
|
||||||
|
[UID_SID] = /* Security Identifier UID */
|
||||||
|
{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06 },
|
||||||
|
[UID_ADMIN1] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01 },
|
||||||
|
[UID_USER1] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01 },
|
||||||
|
[UID_USER2] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x02 },
|
||||||
|
|
||||||
|
/* tables */
|
||||||
|
[UID_LOCKINGRANGE_GLOBAL] =
|
||||||
|
{ 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 },
|
||||||
|
[UID_LOCKINGRANGE_ACE_RDLOCKED] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x01 },
|
||||||
|
[UID_LOCKINGRANGE_ACE_WRLOCKED] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x01 },
|
||||||
|
[UID_MBRCONTROL] =
|
||||||
|
{ 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01 },
|
||||||
|
[UID_MBR] =
|
||||||
|
{ 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 },
|
||||||
|
[UID_AUTHORITY_TABLE] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
[UID_C_PIN_TABLE] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
[UID_LOCKING_INFO_TABLE] =
|
||||||
|
{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 },
|
||||||
|
[UID_PSID] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xff, 0x01 },
|
||||||
|
|
||||||
|
/* C_PIN_TABLE object ID's */
|
||||||
|
[UID_C_PIN_MSID] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02},
|
||||||
|
[UID_C_PIN_SID] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01},
|
||||||
|
[UID_C_PIN_ADMIN1] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01},
|
||||||
|
[UID_C_PIN_USER1] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x03, 0x00, 0x01},
|
||||||
|
|
||||||
|
/* half UID's (only first 4 bytes used) */
|
||||||
|
[UID_HALF_AUTHORITY_OBJ_REF] =
|
||||||
|
{ 0x00, 0x00, 0x0C, 0x05, 0xff, 0xff, 0xff, 0xff },
|
||||||
|
[UID_HALF_BOOLEAN_ACE] =
|
||||||
|
{ 0x00, 0x00, 0x04, 0x0E, 0xff, 0xff, 0xff, 0xff },
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCG Storage SSC Methods.
|
||||||
|
*/
|
||||||
|
static const uint8_t spdk_opal_method[][OPAL_UID_LENGTH] = {
|
||||||
|
[PROPERTIES_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01 },
|
||||||
|
[STARTSESSION_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02 },
|
||||||
|
[REVERT_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02 },
|
||||||
|
[ACTIVATE_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03 },
|
||||||
|
[NEXT_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08 },
|
||||||
|
[GETACL_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d },
|
||||||
|
[GENKEY_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10 },
|
||||||
|
[REVERTSP_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11 },
|
||||||
|
[GET_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16 },
|
||||||
|
[SET_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17 },
|
||||||
|
[AUTHENTICATE_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c },
|
||||||
|
[RANDOM_METHOD] =
|
||||||
|
{ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 },
|
||||||
|
};
|
||||||
|
|
||||||
|
enum spdk_opal_user {
|
||||||
|
OPAL_ADMIN1 = 0x0,
|
||||||
|
OPAL_USER1 = 0x01,
|
||||||
|
OPAL_USER2 = 0x02,
|
||||||
|
OPAL_USER3 = 0x03,
|
||||||
|
OPAL_USER4 = 0x04,
|
||||||
|
OPAL_USER5 = 0x05,
|
||||||
|
OPAL_USER6 = 0x06,
|
||||||
|
OPAL_USER7 = 0x07,
|
||||||
|
OPAL_USER8 = 0x08,
|
||||||
|
OPAL_USER9 = 0x09,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response token
|
||||||
|
*/
|
||||||
|
struct spdk_opal_resp_token {
|
||||||
|
const uint8_t *pos;
|
||||||
|
uint8_t _padding[7];
|
||||||
|
union {
|
||||||
|
uint64_t unsigned_num;
|
||||||
|
int64_t signed_num;
|
||||||
|
} stored;
|
||||||
|
size_t len;
|
||||||
|
enum opal_token_type type;
|
||||||
|
enum opal_atom_width width;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_resp_parsed {
|
||||||
|
int num;
|
||||||
|
struct spdk_opal_resp_token resp_tokens[MAX_TOKS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_step {
|
||||||
|
int (*opal_fn)(struct spdk_opal_dev *dev, void *data);
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_key {
|
||||||
|
uint8_t locking_range;
|
||||||
|
uint8_t key_len;
|
||||||
|
uint8_t _padding[6];
|
||||||
|
uint8_t key[OPAL_KEY_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_locking_range_activate {
|
||||||
|
struct spdk_opal_key key;
|
||||||
|
uint32_t sum; /* single user mode */
|
||||||
|
uint8_t lockingrange_num;
|
||||||
|
uint8_t lockingrange[OPAL_MAX_LRS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_locking_range_setup {
|
||||||
|
uint8_t id;
|
||||||
|
uint8_t _padding[7];
|
||||||
|
uint64_t range_start;
|
||||||
|
uint64_t range_length;
|
||||||
|
bool RLE; /* Read Lock enabled */
|
||||||
|
bool WLE; /* Write Lock Enabled */
|
||||||
|
struct spdk_opal_session session;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* header of a response */
|
||||||
|
struct spdk_opal_header {
|
||||||
|
struct spdk_opal_compacket com_packet;
|
||||||
|
struct spdk_opal_packet packet;
|
||||||
|
struct spdk_opal_data_subpacket sub_packet;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spdk_opal_dev {
|
||||||
|
bool supported;
|
||||||
|
void *dev_handler;
|
||||||
|
|
||||||
|
const struct spdk_opal_step *steps;
|
||||||
|
uint16_t comid;
|
||||||
|
uint32_t hsn;
|
||||||
|
uint32_t tsn;
|
||||||
|
uint64_t align;
|
||||||
|
uint64_t lowest_lba;
|
||||||
|
|
||||||
|
size_t cmd_pos;
|
||||||
|
uint8_t cmd[IO_BUFFER_LENGTH];
|
||||||
|
uint8_t resp[IO_BUFFER_LENGTH];
|
||||||
|
|
||||||
|
struct spdk_opal_resp_parsed parsed_resp;
|
||||||
|
size_t prev_d_len;
|
||||||
|
void *prev_data;
|
||||||
|
|
||||||
|
struct spdk_opal_key *dev_key;
|
||||||
|
|
||||||
|
struct spdk_opal_info *opal_info;
|
||||||
|
|
||||||
|
uint64_t timeout; /* seconds */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum opal_lock_state {
|
||||||
|
OPAL_LS_DISALBELOCKING = 0x00,
|
||||||
|
OPAL_LS_READLOCK_ENABLE = 0x01,
|
||||||
|
OPAL_LS_WRITELOCK_ENABLE = 0x02,
|
||||||
|
OPAL_LS_RWLOCK_ENABLE = 0x04,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user