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
