]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge patch series "Add OP-TEE based RPMB driver for UFS devices"
authorMartin K. Petersen <martin.petersen@oracle.com>
Thu, 20 Nov 2025 15:26:13 +0000 (10:26 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 20 Nov 2025 15:26:13 +0000 (10:26 -0500)
Bean Huo <beanhuo@iokpp.de> says:

This patch series introduces OP-TEE based RPMB (Replay Protected
Memory Block) support for UFS devices, extending the kernel-level
secure storage capabilities that are currently available for eMMC
devices.

Previously, OP-TEE required a userspace supplicant to access RPMB
partitions, which created complex dependencies and reliability issues,
especially during early boot scenarios. Recent work by Linaro has
moved core supplicant functionality directly into the Linux kernel for
eMMC devices, eliminating userspace dependencies and enabling
immediate secure storage access. This series extends the same approach
to UFS devices, which are used in enterprise and mobile applications
that require secure storage capabilities.

Benefits:

 - Eliminates dependency on userspace supplicant for UFS RPMB access

 - Enables early boot secure storage access (e.g., fTPM, secure UEFI
   variables)

 - Provides kernel-level RPMB access as soon as UFS driver is
   initialized

 - Removes complex initramfs dependencies and boot ordering
   requirements

 - Ensures reliable and deterministic secure storage operations

 - Supports both built-in and modular fTPM configurations.

Prerequisites:
--------------

This patch series depends on commit 7e8242405b94 ("rpmb: move struct
rpmb_frame to common header") which has been merged into mainline
v6.18-rc2.

Link: https://patch.msgid.link/20251107230518.4060231-1-beanhuo@iokpp.de
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1  2 
MAINTAINERS
drivers/ata/libata-core.c
drivers/ufs/core/ufshcd-priv.h
drivers/ufs/core/ufshcd.c
include/ufs/ufshcd.h

diff --cc MAINTAINERS
Simple merge
Simple merge
index 676ebb02db8bd3c2847c80adc54e5744e6b5db55,9ed2587bc4e8a3f250d40b51ef0ca79fa57a06a2..4259f499382fae904a4a737d56be3e2eb2b15fb8
@@@ -77,13 -75,20 +77,19 @@@ bool ufshcd_cmd_inflight(struct scsi_cm
  int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag);
  int ufshcd_mcq_abort(struct scsi_cmnd *cmd);
  int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag);
 -void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
 -                           struct ufshcd_lrb *lrbp);
 +void ufshcd_release_scsi_cmd(struct ufs_hba *hba, struct scsi_cmnd *cmd);
  
- #define SD_ASCII_STD true
- #define SD_RAW false
- int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
-                           u8 **buf, bool ascii);
+ /**
+  * enum ufs_descr_fmt - UFS string descriptor format
+  * @SD_RAW: Raw UTF-16 format
+  * @SD_ASCII_STD: Convert to null-terminated ASCII string
+  */
+ enum ufs_descr_fmt {
+       SD_RAW = 0,
+       SD_ASCII_STD = 1,
+ };
  
+ int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, u8 **buf, enum ufs_descr_fmt fmt);
  int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
  int ufshcd_send_bsg_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
  
index 8f68e305e83c3092acb3e47652e24a4cbd5a0f74,1a402b1ae37f59a2f506f9221ae8f43640e07798..040a0ceb170a7f0019bb1c63f3dd1326dfdfea0f
@@@ -8489,10 -8464,69 +8495,71 @@@ static void ufs_init_rtc(struct ufs_hb
        dev_info->rtc_update_period = 0;
  }
  
+ /**
+  * ufshcd_create_device_id - Generate unique device identifier string
+  * @hba: per-adapter instance
+  * @desc_buf: device descriptor buffer
+  *
+  * Creates a unique device ID string combining manufacturer ID, spec version,
+  * model name, serial number (as hex), device version, and manufacture date.
+  *
+  * Returns: Allocated device ID string on success, NULL on failure
+  */
+ static char *ufshcd_create_device_id(struct ufs_hba *hba, u8 *desc_buf)
+ {
+       struct ufs_dev_info *dev_info = &hba->dev_info;
+       u16 manufacture_date;
+       u16 device_version;
+       u8 *serial_number;
+       char *serial_hex;
+       char *device_id;
+       u8 serial_index;
+       int serial_len;
+       int ret;
+       serial_index = desc_buf[DEVICE_DESC_PARAM_SN];
+       ret = ufshcd_read_string_desc(hba, serial_index, &serial_number, SD_RAW);
+       if (ret < 0) {
+               dev_err(hba->dev, "Failed reading Serial Number. err = %d\n", ret);
+               return NULL;
+       }
+       device_version = get_unaligned_be16(&desc_buf[DEVICE_DESC_PARAM_DEV_VER]);
+       manufacture_date = get_unaligned_be16(&desc_buf[DEVICE_DESC_PARAM_MANF_DATE]);
+       serial_len = ret;
+       /* Allocate buffer for hex string: 2 chars per byte + null terminator */
+       serial_hex = kzalloc(serial_len * 2 + 1, GFP_KERNEL);
+       if (!serial_hex) {
+               kfree(serial_number);
+               return NULL;
+       }
+       bin2hex(serial_hex, serial_number, serial_len);
+       /*
+        * Device ID format is ABI with secure world - do not change without firmware
+        * coordination.
+        */
+       device_id = kasprintf(GFP_KERNEL, "%04X-%04X-%s-%s-%04X-%04X",
+                             dev_info->wmanufacturerid, dev_info->wspecversion,
+                             dev_info->model, serial_hex, device_version,
+                             manufacture_date);
+       kfree(serial_hex);
+       kfree(serial_number);
+       if (!device_id)
+               dev_warn(hba->dev, "Failed to allocate unique device ID\n");
+       return device_id;
+ }
  static int ufs_get_device_desc(struct ufs_hba *hba)
  {
 +      struct ufs_dev_info *dev_info = &hba->dev_info;
 +      struct Scsi_Host *shost = hba->host;
        int err;
        u8 model_index;
        u8 *desc_buf;
index 37b443d48528ec3ae0d6047eccb19497234e84a1,7efef792c2699af1d6d2f99f8a14e76ddb572b0e..19154228780b22c3bb3e07396acc1fdbcc347a3b
@@@ -1112,8 -1119,7 +1114,8 @@@ struct ufs_hba 
        int critical_health_count;
        atomic_t dev_lvl_exception_count;
        u64 dev_lvl_exception_id;
 +      u32 vcc_off_delay_us;
+       struct list_head rpmbs;
  };
  
  /**