UFS Replay Protected Memory Block (RPMB) accesses are transported over
SCSI SECURITY PROTOCOL IN (0xa2) and SECURITY PROTOCOL OUT (0xb5)
commands directed to the RPMB well-known logical unit (W-LUN 0xc4).

Add SECURITY_PROTOCOL_IN and SECURITY_PROTOCOL_OUT in numeric order to
include/scsi/constants.h, update RpmbUnitDescriptor to expose
bRPMBRegionEnable and bRPMBRegion0Size..bRPMBRegion3Size per JESD220H
Table 14.15 while preserving its 35-byte packed layout, and define the
512-byte UfsRpmbFrame structure, geometry constants, request/response
types, and operation result codes from JESD220H Section 12.4.

Signed-off-by: Stanley Jhu <[email protected]>
---
 include/block/ufs.h      | 58 +++++++++++++++++++++++++++++++++++++---
 include/scsi/constants.h |  2 ++
 2 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/include/block/ufs.h b/include/block/ufs.h
index a0bbe873d6..339c3bf5b4 100644
--- a/include/block/ufs.h
+++ b/include/block/ufs.h
@@ -387,6 +387,10 @@ typedef struct QEMU_PACKED UnitDescriptor {
     uint32_t lu_num_write_booster_buffer_alloc_units;
 } UnitDescriptor;
 
+#define UFS_RPMB_MAX_REGIONS            4
+#define UFS_RPMB_LOGICAL_BLOCK_SIZE     8 /* 2^8 = 256 bytes */
+#define UFS_RPMB_BLOCKS_PER_UNIT        512 /* 128 KiB / 256 B */
+
 typedef struct QEMU_PACKED RpmbUnitDescriptor {
     uint8_t length;
     uint8_t descriptor_idn;
@@ -397,15 +401,62 @@ typedef struct QEMU_PACKED RpmbUnitDescriptor {
     uint8_t lu_queue_depth;
     uint8_t psa_sensitive;
     uint8_t memory_type;
-    uint8_t reserved;
+    uint8_t rpmb_region_enable;
     uint8_t logical_block_size;
     uint64_t logical_block_count;
-    uint32_t erase_block_size;
+    uint8_t rpmb_region_size[UFS_RPMB_MAX_REGIONS];
     uint8_t provisioning_type;
     uint64_t phy_mem_resource_count;
-    uint8_t reserved2[3];
+    uint8_t reserved[3];
 } RpmbUnitDescriptor;
 
+#define UFS_RPMB_FRAME_LEN      512
+#define UFS_RPMB_DATA_LEN       256
+#define UFS_RPMB_KEY_MAC_LEN    32
+#define UFS_RPMB_NONCE_LEN      16
+#define UFS_RPMB_HASH_OFFSET    228
+#define UFS_RPMB_HASH_LEN       (UFS_RPMB_FRAME_LEN - UFS_RPMB_HASH_OFFSET)
+
+#define UFS_RPMB_SEC_PROTOCOL       0xec
+#define UFS_RPMB_SEC_PROTOCOL_ID    0x01
+
+enum UfsRpmbRequest {
+    UFS_RPMB_REQ_PROGRAM_KEY        = 0x0001,
+    UFS_RPMB_REQ_READ_COUNTER       = 0x0002,
+    UFS_RPMB_REQ_AUTH_DATA_WRITE    = 0x0003,
+    UFS_RPMB_REQ_AUTH_DATA_READ     = 0x0004,
+    UFS_RPMB_REQ_READ_RESULT        = 0x0005,
+
+    UFS_RPMB_RESP_PROGRAM_KEY       = 0x0100,
+    UFS_RPMB_RESP_READ_COUNTER      = 0x0200,
+    UFS_RPMB_RESP_AUTH_DATA_WRITE   = 0x0300,
+    UFS_RPMB_RESP_AUTH_DATA_READ    = 0x0400,
+};
+
+enum UfsRpmbResult {
+    UFS_RPMB_RES_OK                 = 0x0000,
+    UFS_RPMB_RES_GENERAL_FAILURE    = 0x0001,
+    UFS_RPMB_RES_AUTH_FAILURE       = 0x0002,
+    UFS_RPMB_RES_COUNT_FAILURE      = 0x0003,
+    UFS_RPMB_RES_ADDR_FAILURE       = 0x0004,
+    UFS_RPMB_RES_WRITE_FAILURE      = 0x0005,
+    UFS_RPMB_RES_READ_FAILURE       = 0x0006,
+    UFS_RPMB_RES_NO_AUTH_KEY        = 0x0007,
+    UFS_RPMB_RES_COUNT_EXPIRED      = 0x0080,
+};
+
+typedef struct QEMU_PACKED UfsRpmbFrame {
+    uint8_t stuff[196];
+    uint8_t key_mac[UFS_RPMB_KEY_MAC_LEN];
+    uint8_t data[UFS_RPMB_DATA_LEN];
+    uint8_t nonce[UFS_RPMB_NONCE_LEN];
+    uint32_t write_counter;
+    uint16_t addr;
+    uint16_t block_count;
+    uint16_t result;
+    uint16_t req_resp;
+} UfsRpmbFrame;
+
 typedef struct QEMU_PACKED PowerParametersDescriptor {
     uint8_t length;
     uint8_t descriptor_idn;
@@ -1397,6 +1448,7 @@ static inline void _ufs_check_size(void)
     QEMU_BUILD_BUG_ON(sizeof(GeometryDescriptor) != 105);
     QEMU_BUILD_BUG_ON(sizeof(UnitDescriptor) != 45);
     QEMU_BUILD_BUG_ON(sizeof(RpmbUnitDescriptor) != 35);
+    QEMU_BUILD_BUG_ON(sizeof(UfsRpmbFrame) != UFS_RPMB_FRAME_LEN);
     QEMU_BUILD_BUG_ON(sizeof(PowerParametersDescriptor) != 98);
     QEMU_BUILD_BUG_ON(sizeof(InterconnectDescriptor) != 6);
     QEMU_BUILD_BUG_ON(sizeof(StringDescriptor) != 254);
diff --git a/include/scsi/constants.h b/include/scsi/constants.h
index bb3981a779..5a738e89bf 100644
--- a/include/scsi/constants.h
+++ b/include/scsi/constants.h
@@ -127,6 +127,7 @@
 #define WRITE_LONG_16         0x9f
 #define REPORT_LUNS           0xa0
 #define ATA_PASSTHROUGH_12    0xa1
+#define SECURITY_PROTOCOL_IN  0xa2
 #define MAINTENANCE_IN        0xa3
 #define MAINTENANCE_OUT       0xa4
 #define MOVE_MEDIUM           0xa5
@@ -142,6 +143,7 @@
 #define SEARCH_HIGH_12        0xb0
 #define SEARCH_EQUAL_12       0xb1
 #define SEARCH_LOW_12         0xb2
+#define SECURITY_PROTOCOL_OUT 0xb5
 #define READ_ELEMENT_STATUS   0xb8
 #define SEND_VOLUME_TAG       0xb6
 #define READ_DEFECT_DATA_12   0xb7
-- 
2.56.0.307.g5fe7bd680c-goog


Reply via email to