From ad497d1c5b3645eb19447772412437491e6bdd5e Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 12 Nov 2024 15:22:42 +0530 Subject: [PATCH] LF-13910-3: firmware: imx: additional changes to the upstream driver. additional changes to the upstream driver. - construct se_name from se_type_id and instance id - move soc_register to info_list - move fetch soc info function pointer to info_list - ele soc fetch generalization - ele debug dump Signed-off-by: Pankaj Gupta Acked-by: Rahul Kumar Yadav Acked-by: Vabhav Sharma Acked-by: Meenakshi Aggarwal Acked-by: Jason Liu --- drivers/firmware/imx/ele_base_msg.c | 144 +++++++++++++- drivers/firmware/imx/ele_base_msg.h | 8 +- drivers/firmware/imx/ele_common.c | 12 +- drivers/firmware/imx/se_ctrl.c | 283 +++++++++++++++------------- drivers/firmware/imx/se_ctrl.h | 4 +- include/uapi/linux/se_ioctl.h | 17 ++ 6 files changed, 325 insertions(+), 143 deletions(-) diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c index 29a18a449340..51436cdd9138 100644 --- a/drivers/firmware/imx/ele_base_msg.c +++ b/drivers/firmware/imx/ele_base_msg.c @@ -12,6 +12,8 @@ #include "ele_base_msg.h" #include "ele_common.h" +#define FW_DBG_DUMP_FIXED_STR "\nELEX: " + int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info) { struct se_api_msg *tx_msg __free(kfree) = NULL; @@ -95,20 +97,14 @@ exit: return ret; } -int ele_fetch_soc_info(struct se_if_priv *priv, u16 *soc_rev, u64 *serial_num) +int ele_fetch_soc_info(struct se_if_priv *priv, void *data) { - struct ele_dev_info s_info = {0}; int err; - err = ele_get_info(priv, &s_info); + err = ele_get_info(priv, data); if (err < 0) return err; - if (soc_rev) - *soc_rev = s_info.d_info.soc_rev; - if (serial_num) - *serial_num = GET_SERIAL_NUM_FROM_UID(s_info.d_info.uid, MAX_UID_SIZE >> 2); - return err; } @@ -276,3 +272,135 @@ int ele_fw_authenticate(struct se_if_priv *priv, phys_addr_t addr) exit: return ret; } + +int ele_debug_dump(struct se_if_priv *priv) +{ + struct se_api_msg *tx_msg __free(kfree) = NULL; + struct se_api_msg *rx_msg __free(kfree) = NULL; + bool keep_logging; + u8 dump_data[408]; + u8 fmt_str[256]; + int fmt_str_idx; + int rcv_dbg_wd_ct; + int msg_ex_cnt; + int ret = 0; + int w_ct; + + if (!priv) { + ret = -EINVAL; + goto exit; + } + + tx_msg = kzalloc(ELE_DEBUG_DUMP_REQ_SZ, GFP_KERNEL); + if (!tx_msg) { + ret = -ENOMEM; + goto exit; + } + + rx_msg = kzalloc(ELE_DEBUG_DUMP_RSP_SZ, GFP_KERNEL); + if (!rx_msg) { + ret = -ENOMEM; + goto exit; + } + + ret = se_fill_cmd_msg_hdr(priv, + &tx_msg->header, + ELE_DEBUG_DUMP_REQ, + ELE_DEBUG_DUMP_REQ_SZ, + true); + if (ret) + goto exit; + + msg_ex_cnt = 0; + do { + w_ct = 0; + fmt_str_idx = 0; + memset(rx_msg, 0xCC, ELE_DEBUG_DUMP_RSP_SZ); + + ret = ele_msg_send_rcv(priv->priv_dev_ctx, + tx_msg, + ELE_DEBUG_DUMP_REQ_SZ, + rx_msg, + ELE_DEBUG_DUMP_RSP_SZ); + if (ret < 0) + goto exit; + + ret = se_val_rsp_hdr_n_status(priv, + rx_msg, + ELE_DEBUG_DUMP_REQ, + ELE_DEBUG_DUMP_RSP_SZ, + true); + if (!ret) { + rcv_dbg_wd_ct = rx_msg->header.size - ELE_NON_DUMP_BUFFER_SZ; + memcpy(fmt_str, FW_DBG_DUMP_FIXED_STR, strlen(FW_DBG_DUMP_FIXED_STR)); + fmt_str_idx += strlen(FW_DBG_DUMP_FIXED_STR); + for (w_ct = 0; w_ct < rcv_dbg_wd_ct; w_ct++) { + fmt_str[fmt_str_idx] = '0'; + fmt_str_idx++; + fmt_str[fmt_str_idx] = 'x'; + fmt_str_idx++; + fmt_str[fmt_str_idx] = '%'; + fmt_str_idx++; + fmt_str[fmt_str_idx] = '0'; + fmt_str_idx++; + fmt_str[fmt_str_idx] = '8'; + fmt_str_idx++; + fmt_str[fmt_str_idx] = 'x'; + fmt_str_idx++; + fmt_str[fmt_str_idx] = ' '; + fmt_str_idx++; + if (w_ct % 2) { + memcpy(fmt_str + fmt_str_idx, + FW_DBG_DUMP_FIXED_STR, + strlen(FW_DBG_DUMP_FIXED_STR)); + fmt_str_idx += strlen(FW_DBG_DUMP_FIXED_STR); + } + } + keep_logging = (rx_msg->header.size < (ELE_DEBUG_DUMP_RSP_SZ >> 2)) ? + false : true; + keep_logging = keep_logging ? + (msg_ex_cnt > ELE_MAX_DBG_DMP_PKT ? false : true) : + false; + /* + * Number of spaces = rcv_dbg_wd_ct + * DBG dump length in bytes = rcv_dbg_wd_ct * 4 + * + * Since, one byte is represented as 2 character, + * DBG Dump string-length = rcv_dbg_wd_ct * 8 + * Fixed string's string-length = + * strlen(FW_DBG_DUMP_FIXED_STR) * rcv_dbg_wd_ct + * + * Total dump_data length = Number of spaces + + * DBG Dump string' string-length + + * Fixed string's string-length + * + * Total dump_data length = rcv_dbg_wd_ct + (rcv_dbg_wd_ct * 8) + + * strlen(FW_DBG_DUMP_FIXED_STR) * rcv_dbg_wd_ct + */ + + snprintf(dump_data, + ((rcv_dbg_wd_ct * 9) + + (strlen(FW_DBG_DUMP_FIXED_STR) * rcv_dbg_wd_ct)), + fmt_str, + rx_msg->data[1], rx_msg->data[2], + rx_msg->data[3], rx_msg->data[4], + rx_msg->data[5], rx_msg->data[6], + rx_msg->data[7], rx_msg->data[8], + rx_msg->data[9], rx_msg->data[10], + rx_msg->data[11], rx_msg->data[12], + rx_msg->data[13], rx_msg->data[14], + rx_msg->data[15], rx_msg->data[16], + rx_msg->data[17], rx_msg->data[18], + rx_msg->data[19], rx_msg->data[20]); + + dev_err(priv->dev, "%s", dump_data); + } else { + dev_err(priv->dev, "Dump_Debug_Buffer Error: %x.", ret); + break; + } + msg_ex_cnt++; + } while (keep_logging); + +exit: + return ret; +} diff --git a/drivers/firmware/imx/ele_base_msg.h b/drivers/firmware/imx/ele_base_msg.h index f6e3b87b1a85..e8b8e513ddb2 100644 --- a/drivers/firmware/imx/ele_base_msg.h +++ b/drivers/firmware/imx/ele_base_msg.h @@ -62,8 +62,11 @@ struct ele_dev_info { #define GET_SERIAL_NUM_FROM_UID(x, uid_word_sz) \ (((u64)(((u32 *)(x))[(uid_word_sz) - 1]) << 32) | ((u32 *)(x))[0]) +#define ELE_MAX_DBG_DMP_PKT 30 +#define ELE_NON_DUMP_BUFFER_SZ 3 #define ELE_DEBUG_DUMP_REQ 0x21 -#define ELE_DEBUG_DUMP_RSP_SZ 0x17 +#define ELE_DEBUG_DUMP_REQ_SZ 0x4 +#define ELE_DEBUG_DUMP_RSP_SZ 0x5c #define ELE_PING_REQ 0x01 #define ELE_PING_REQ_SZ 0x04 @@ -85,10 +88,11 @@ struct ele_dev_info { #define ELE_FW_AUTH_RSP_MSG_SZ 0x08 int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info); -int ele_fetch_soc_info(struct se_if_priv *priv, u16 *soc_rev, u64 *serial_num); +int ele_fetch_soc_info(struct se_if_priv *priv, void *data); int ele_ping(struct se_if_priv *priv); int ele_service_swap(struct se_if_priv *priv, phys_addr_t addr, u32 addr_size, u16 flag); int ele_fw_authenticate(struct se_if_priv *priv, phys_addr_t addr); +int ele_debug_dump(struct se_if_priv *priv); #endif diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c index 9911a1057462..d8dea9849abc 100644 --- a/drivers/firmware/imx/ele_common.c +++ b/drivers/firmware/imx/ele_common.c @@ -86,13 +86,12 @@ int ele_msg_send(struct se_if_device_ctx *dev_ctx, * carried in the message. */ if (header->size << 2 != tx_msg_sz) { - err = -EINVAL; dev_err(priv->dev, "%s: User buf hdr: 0x%x, sz mismatced with input-sz (%d != %d).", dev_ctx->devname, *(u32 *)header, header->size << 2, tx_msg_sz); - goto exit; + return -EINVAL; } err = mbox_send_message(priv->tx_chan, tx_msg); @@ -104,7 +103,6 @@ int ele_msg_send(struct se_if_device_ctx *dev_ctx, } err = tx_msg_sz; -exit: return err; } @@ -320,7 +318,7 @@ int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem) imem->size = ret; } - return ret; + return ret > 0 ? 0 : -1; } int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem) @@ -336,8 +334,10 @@ int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem) } imem->state = s_info.d_addn_info.imem_state; - /* Get IMEM state, if 0xFE then import IMEM */ - if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_BAD) { + /* Get IMEM state, if 0xFE and saved/exported IMEM buffer size is non-zero, + * then import IMEM + */ + if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_BAD && imem->size) { /* IMPORT command will restore IMEM from the given * address, here size is the actual size returned by ELE * during the export operation diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c index 6f09d8f9c77c..09da3c701c56 100644 --- a/drivers/firmware/imx/se_ctrl.c +++ b/drivers/firmware/imx/se_ctrl.c @@ -29,22 +29,24 @@ #include "ele_common.h" #include "se_ctrl.h" +#define MAX_SOC_INFO_DATA_SZ 256 #define MBOX_TX_NAME "tx" #define MBOX_RX_NAME "rx" -#define SE_TYPE_HSM "hsm" #define SE_RCV_MSG_DEFAULT_TIMEOUT 5000 #define SE_RCV_MSG_LONG_TIMEOUT 5000000 u32 se_rcv_msg_timeout = SE_RCV_MSG_DEFAULT_TIMEOUT; -struct se_fw_load_info { +struct se_fw_img_name { const u8 *prim_fw_nm_in_rfs; const u8 *seco_fw_nm_in_rfs; - /* Mutex to prevent two parallel FW loading. */ - struct mutex se_fw_load; +}; + +struct se_fw_load_info { + const struct se_fw_img_name *se_fw_img_nm; bool is_fw_loaded; - bool handle_susp_resm; + bool imem_mgmt; struct se_imem_buf imem; }; @@ -52,51 +54,63 @@ struct se_if_node_info { u8 se_if_id; u8 se_if_did; struct se_if_defines if_defs; - u8 *se_name; u8 *pool_name; - bool soc_register; bool reserved_dma_ranges; - int (*se_fetch_soc_info)(struct se_if_priv *priv, u16 *soc_rev, u64 *serial_num); }; +/* contains fixed information */ struct se_if_node_info_list { const u8 num_mu; const u16 soc_id; - struct se_fw_load_info load_hsm_fw; + bool soc_register; + int (*se_fetch_soc_info)(struct se_if_priv *priv, void *data); + const struct se_fw_img_name se_fw_img_nm; const struct se_if_node_info info[]; }; -static u16 se_soc_rev; +struct se_var_info { + u8 board_type; + u16 soc_id; + u16 soc_rev; + struct se_fw_load_info load_fw; +}; + +static struct se_var_info var_se_info = { + .board_type = 0, + .soc_id = 0, + .soc_rev = 0, + .load_fw = { + .is_fw_loaded = true, + .imem_mgmt = false, + }, +}; + static struct se_if_node_info_list imx8ulp_info = { .num_mu = 1, .soc_id = SOC_ID_OF_IMX8ULP, - .load_hsm_fw = { + .soc_register = true, + .se_fetch_soc_info = ele_fetch_soc_info, + .se_fw_img_nm = { .prim_fw_nm_in_rfs = IMX_ELE_FW_DIR "mx8ulpa2-ahab-container.img", .seco_fw_nm_in_rfs = IMX_ELE_FW_DIR "mx8ulpa2ext-ahab-container.img", - .is_fw_loaded = false, - .handle_susp_resm = true, - .imem = { - .state = ELE_IMEM_STATE_OK, - }, }, .info = { { .se_if_id = 0, .se_if_did = 7, .if_defs = { + .se_if_type = SE_TYPE_ID_HSM, + .se_instance_id = 0, .cmd_tag = 0x17, .rsp_tag = 0xe1, .success_tag = ELE_SUCCESS_IND, .base_api_ver = MESSAGING_VERSION_6, .fw_api_ver = MESSAGING_VERSION_7, }, - .se_name = SE_TYPE_HSM "1", .pool_name = "sram", - .soc_register = true, .reserved_dma_ranges = true, - .se_fetch_soc_info = ele_fetch_soc_info, }, }, }; @@ -104,26 +118,26 @@ static struct se_if_node_info_list imx8ulp_info = { static struct se_if_node_info_list imx93_info = { .num_mu = 1, .soc_id = SOC_ID_OF_IMX93, - .load_hsm_fw = { + .soc_register = false, + .se_fetch_soc_info = ele_fetch_soc_info, + .se_fw_img_nm = { .prim_fw_nm_in_rfs = NULL, .seco_fw_nm_in_rfs = NULL, - .is_fw_loaded = true, - .handle_susp_resm = false, }, .info = { { .se_if_id = 2, .se_if_did = 3, .if_defs = { + .se_if_type = SE_TYPE_ID_HSM, + .se_instance_id = 0, .cmd_tag = 0x17, .rsp_tag = 0xe1, .success_tag = ELE_SUCCESS_IND, .base_api_ver = MESSAGING_VERSION_6, .fw_api_ver = MESSAGING_VERSION_7, }, - .se_name = SE_TYPE_HSM "1", .reserved_dma_ranges = true, - .soc_register = true, }, }, }; @@ -134,62 +148,101 @@ static const struct of_device_id se_match[] = { {}, }; -static const struct se_if_node_info - *get_se_if_node_info(const struct se_if_node_info_list *info_list, - const u32 idx) +char *get_se_if_name(u8 se_if_id) { - return &info_list->info[idx]; + switch (se_if_id) { + case SE_TYPE_ID_DBG: return SE_TYPE_STR_DBG; + case SE_TYPE_ID_HSM: return SE_TYPE_STR_HSM; + case SE_TYPE_ID_SHE: return SE_TYPE_STR_SHE; + case SE_TYPE_ID_V2X_DBG: return SE_TYPE_STR_V2X_DBG; + case SE_TYPE_ID_V2X_SHE: return SE_TYPE_STR_V2X_SHE; + case SE_TYPE_ID_V2X_SV: return SE_TYPE_STR_V2X_SV; + case SE_TYPE_ID_V2X_SG: return SE_TYPE_STR_V2X_SG; + } + + return NULL; +} + +/* + * get_se_soc_id() - to fetch the soc_id of the platform + * + * @priv : reference to the private data per SE MU interface. + * + * This function returns the SoC ID. + * + * Context: Other module, requiring to access the secure services based on SoC Id. + * + * Return: SoC Id of the device. + */ +uint32_t get_se_soc_id(struct se_if_priv *priv) +{ + const struct se_if_node_info_list *info_list = + device_get_match_data(priv->dev); + + if (var_se_info.soc_rev) + return var_se_info.soc_id; + else + return info_list->soc_id; +} + +static struct se_fw_load_info *get_load_fw_instance(struct se_if_priv *priv) +{ + return &var_se_info.load_fw; } static int se_soc_info(struct se_if_priv *priv) { - const struct se_if_node_info *info; - struct se_if_node_info_list *info_list; + const struct se_if_node_info_list *info_list = device_get_match_data(priv->dev); + struct se_fw_load_info *load_fw = get_load_fw_instance(priv); struct soc_device_attribute *attr; + struct ele_dev_info *s_info; struct soc_device *sdev; - u64 serial_num; + u8 data[MAX_SOC_INFO_DATA_SZ]; int err = 0; - info = container_of(priv->if_defs, typeof(*info), if_defs); - info_list = container_of(info, typeof(*info_list), info[info->se_if_id]); - /* This function should be called once. * Check if the se_soc_rev is zero to continue. */ - if (se_soc_rev) + if (var_se_info.soc_rev) return err; - if (info->se_fetch_soc_info) { - err = info->se_fetch_soc_info(priv, &se_soc_rev, &serial_num); + if (info_list->se_fetch_soc_info) { + err = info_list->se_fetch_soc_info(priv, &data); if (err < 0) { dev_err(priv->dev, "Failed to fetch SoC Info."); return err; } + + s_info = (void *)data; + var_se_info.board_type = 0; + var_se_info.soc_id = info_list->soc_id; + var_se_info.soc_rev = s_info->d_info.soc_rev; + load_fw->imem.state = s_info->d_addn_info.imem_state; } else { dev_err(priv->dev, "Failed to fetch SoC revision."); - if (info->soc_register) + if (info_list->soc_register) dev_err(priv->dev, "Failed to do SoC registration."); err = -EINVAL; return err; } - if (!info->soc_register) + if (!info_list->soc_register) return 0; attr = devm_kzalloc(priv->dev, sizeof(*attr), GFP_KERNEL); if (!attr) return -ENOMEM; - if (FIELD_GET(DEV_GETINFO_MIN_VER_MASK, se_soc_rev)) + if (FIELD_GET(DEV_GETINFO_MIN_VER_MASK, var_se_info.soc_rev)) attr->revision = devm_kasprintf(priv->dev, GFP_KERNEL, "%x.%x", FIELD_GET(DEV_GETINFO_MIN_VER_MASK, - se_soc_rev), + var_se_info.soc_rev), FIELD_GET(DEV_GETINFO_MAJ_VER_MASK, - se_soc_rev)); + var_se_info.soc_rev)); else attr->revision = devm_kasprintf(priv->dev, GFP_KERNEL, "%x", FIELD_GET(DEV_GETINFO_MAJ_VER_MASK, - se_soc_rev)); + var_se_info.soc_rev)); switch (info_list->soc_id) { case SOC_ID_OF_IMX8ULP: @@ -210,7 +263,8 @@ static int se_soc_info(struct se_if_priv *priv) attr->family = devm_kasprintf(priv->dev, GFP_KERNEL, "Freescale i.MX"); attr->serial_number = devm_kasprintf(priv->dev, GFP_KERNEL, "%016llX", - serial_num); + GET_SERIAL_NUM_FROM_UID(s_info->d_info.uid, + MAX_UID_SIZE >> 2)); sdev = soc_device_register(attr); if (IS_ERR(sdev)) @@ -219,24 +273,6 @@ static int se_soc_info(struct se_if_priv *priv) return 0; } -static struct se_fw_load_info *get_load_fw_instance(struct se_if_priv *priv) -{ - const struct se_if_node_info *info = container_of(priv->if_defs, - typeof(*info), - if_defs); - struct se_if_node_info_list *info_list; - struct se_fw_load_info *load_fw = NULL; - - info_list = container_of(info, typeof(*info_list), info[info->se_if_id]); - - if (!memcmp(SE_TYPE_HSM, info->se_name, strlen(SE_TYPE_HSM))) - load_fw = &info_list->load_hsm_fw; - else - dev_err(priv->dev, "Invalid load fw configuration."); - - return load_fw; -} - static int se_load_firmware(struct se_if_priv *priv) { struct se_fw_load_info *load_fw = get_load_fw_instance(priv); @@ -246,25 +282,13 @@ static int se_load_firmware(struct se_if_priv *priv) u8 *se_fw_buf; int ret; - guard(mutex)(&load_fw->se_fw_load); if (load_fw->is_fw_loaded) return 0; - se_img_file_to_load = load_fw->seco_fw_nm_in_rfs; - if (load_fw->prim_fw_nm_in_rfs) { - /* allocate buffer where SE store encrypted IMEM */ - load_fw->imem.buf = dmam_alloc_coherent(priv->dev, ELE_IMEM_SIZE, - &load_fw->imem.phyaddr, - GFP_KERNEL); - if (!load_fw->imem.buf) { - dev_err(priv->dev, - "dmam-alloc-failed: To store encr-IMEM.\n"); - ret = -ENOMEM; - goto exit; - } - if (load_fw->imem.state == ELE_IMEM_STATE_BAD) - se_img_file_to_load = load_fw->prim_fw_nm_in_rfs; - } + se_img_file_to_load = load_fw->se_fw_img_nm->seco_fw_nm_in_rfs; + if (load_fw->se_fw_img_nm->prim_fw_nm_in_rfs && + load_fw->imem.state == ELE_IMEM_STATE_BAD) + se_img_file_to_load = load_fw->se_fw_img_nm->prim_fw_nm_in_rfs; do { ret = request_firmware(&fw, se_img_file_to_load, priv->dev); @@ -300,8 +324,8 @@ static int se_load_firmware(struct se_if_priv *priv) fw = NULL; if (!ret && load_fw->imem.state == ELE_IMEM_STATE_BAD && - se_img_file_to_load == load_fw->prim_fw_nm_in_rfs) - se_img_file_to_load = load_fw->seco_fw_nm_in_rfs; + se_img_file_to_load == load_fw->se_fw_img_nm->prim_fw_nm_in_rfs) + se_img_file_to_load = load_fw->se_fw_img_nm->seco_fw_nm_in_rfs; else se_img_file_to_load = NULL; @@ -470,9 +494,6 @@ static int init_device_context(struct se_if_priv *priv, int ch_id, struct se_if_device_ctx **new_dev_ctx, const struct file_operations *se_if_fops) { - const struct se_if_node_info *info = container_of(priv->if_defs, - typeof(*info), - if_defs); struct se_if_device_ctx *dev_ctx; int ret = 0; @@ -489,12 +510,13 @@ static int init_device_context(struct se_if_priv *priv, int ch_id, dev_ctx->priv = priv; if (ch_id) - dev_ctx->devname = kasprintf(GFP_KERNEL, "%s_ch%d", - info->se_name, ch_id); + dev_ctx->devname = kasprintf(GFP_KERNEL, "%s%d_ch%d", + get_se_if_name(priv->if_defs->se_if_type), + priv->if_defs->se_instance_id, ch_id); else - dev_ctx->devname = devm_kasprintf(priv->dev, - GFP_KERNEL, "%s_ch%d", - info->se_name, ch_id); + dev_ctx->devname = devm_kasprintf(priv->dev, GFP_KERNEL, "%s%d_ch%d", + get_se_if_name(priv->if_defs->se_if_type), + priv->if_defs->se_instance_id, ch_id); if (!dev_ctx->devname) { ret = -ENOMEM; if (ch_id) @@ -559,12 +581,7 @@ static int init_device_context(struct se_if_priv *priv, int ch_id, static int se_ioctl_cmd_snd_rcv_rsp_handler(struct se_if_device_ctx *dev_ctx, u64 arg) { - const struct se_if_node_info *info = container_of(dev_ctx->priv->if_defs, - typeof(*info), - if_defs); struct se_ioctl_cmd_snd_rcv_rsp_info cmd_snd_rcv_rsp_info = {0}; - struct se_if_node_info_list *info_list = container_of(info, typeof(*info_list), - info[info->se_if_id]); struct se_if_priv *priv = dev_ctx->priv; struct se_api_msg *tx_msg __free(kfree) = NULL; struct se_api_msg *rx_msg __free(kfree) = NULL; @@ -608,7 +625,7 @@ static int se_ioctl_cmd_snd_rcv_rsp_handler(struct se_if_device_ctx *dev_ctx, } if (tx_msg->header.ver == priv->if_defs->fw_api_ver && - !info_list->load_hsm_fw.is_fw_loaded) { + !get_load_fw_instance(priv)->is_fw_loaded) { err = se_load_firmware(priv); if (err) { dev_err(priv->dev, "Could not send the message as FW is not loaded."); @@ -679,7 +696,7 @@ static int se_ioctl_get_mu_info(struct se_if_device_ctx *dev_ctx, info = container_of(priv->if_defs, typeof(*info), if_defs); - if_info.se_if_id = info->se_if_id; + if_info.se_if_id = 0; if_info.interrupt_idx = 0; if_info.tz = 0; if_info.did = info->se_if_did; @@ -711,7 +728,8 @@ exit: * Copy a buffer of data to/from the user and return the address to use in * messages */ -static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx, u64 arg) +static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx, + u64 arg) { struct se_shared_mem *shared_mem = NULL; struct se_ioctl_setup_iobuf io = {0}; @@ -746,6 +764,12 @@ static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx, u64 ar shared_mem = &dev_ctx->se_shared_mem_mgmt.non_secure_mem; /* Check there is enough space in the shared memory. */ + dev_dbg(dev_ctx->priv->dev, + "%s: req_size = %d, max_size= %d, curr_pos = %d", + dev_ctx->devname, + round_up(io.length, 8u), + shared_mem->size, shared_mem->pos); + if (shared_mem->size < shared_mem->pos || round_up(io.length, 8u) > (shared_mem->size - shared_mem->pos)) { dev_err(dev_ctx->priv->dev, @@ -802,16 +826,12 @@ exit: static int se_ioctl_get_se_soc_info_handler(struct se_if_device_ctx *dev_ctx, u64 arg) { - const struct se_if_node_info_list *info_list; struct se_ioctl_get_soc_info soc_info; int err = -EINVAL; - info_list = device_get_match_data(dev_ctx->priv->dev); - if (!info_list) - goto exit; - - soc_info.soc_id = info_list->soc_id; - soc_info.soc_rev = se_soc_rev; + soc_info.soc_id = var_se_info.soc_id; + soc_info.soc_rev = var_se_info.soc_rev; + soc_info.board_type = var_se_info.board_type; err = (int)copy_to_user((u8 __user *)arg, (u8 *)(&soc_info), sizeof(soc_info)); if (err) { @@ -1167,7 +1187,7 @@ static int se_if_probe(struct platform_device *pdev) return ret; } - info = get_se_if_node_info(info_list, idx); + info = &info_list->info[idx]; if (!info) { ret = -EINVAL; goto exit; @@ -1238,24 +1258,39 @@ static int se_if_probe(struct platform_device *pdev) goto exit; } - ret = se_soc_info(priv); - if (ret) { - dev_err(dev, - "failed[%pe] to fetch SoC Info\n", ERR_PTR(ret)); - goto exit; + if (info->if_defs.se_if_type == SE_TYPE_ID_HSM) { + ret = se_soc_info(priv); + if (ret) { + dev_err(dev, + "failed[%pe] to fetch SoC Info\n", ERR_PTR(ret)); + goto exit; + } } - load_fw = get_load_fw_instance(priv); /* By default, there is no pending FW to be loaded.*/ - if (load_fw->is_fw_loaded) { - mutex_init(&load_fw->se_fw_load); - ret = se_load_firmware(priv); - if (ret) - dev_warn(dev, "Failed to load firmware."); - ret = 0; + if (info_list->se_fw_img_nm.prim_fw_nm_in_rfs || + info_list->se_fw_img_nm.seco_fw_nm_in_rfs) { + load_fw = get_load_fw_instance(priv); + load_fw->se_fw_img_nm = &info_list->se_fw_img_nm; + load_fw->is_fw_loaded = false; + + if (info_list->se_fw_img_nm.prim_fw_nm_in_rfs) { + /* allocate buffer where SE store encrypted IMEM */ + load_fw->imem.buf = dmam_alloc_coherent(priv->dev, ELE_IMEM_SIZE, + &load_fw->imem.phyaddr, + GFP_KERNEL); + if (!load_fw->imem.buf) { + dev_err(priv->dev, + "dmam-alloc-failed: To store encr-IMEM.\n"); + ret = -ENOMEM; + goto exit; + } + load_fw->imem_mgmt = true; + } } - dev_info(dev, "i.MX secure-enclave: %s interface to firmware, configured.\n", - info->se_name); + dev_info(dev, "i.MX secure-enclave: %s%d interface to firmware, configured.\n", + get_se_if_name(priv->if_defs->se_if_type), + priv->if_defs->se_instance_id); return ret; exit: @@ -1280,13 +1315,9 @@ static int se_suspend(struct device *dev) se_rcv_msg_timeout = SE_RCV_MSG_DEFAULT_TIMEOUT; load_fw = get_load_fw_instance(priv); - if (load_fw->handle_susp_resm) { + if (load_fw->imem_mgmt) ret = se_save_imem_state(priv, &load_fw->imem); - if (ret < 0) - goto exit; - load_fw->imem.size = ret; - } -exit: + return ret; } @@ -1297,7 +1328,7 @@ static int se_resume(struct device *dev) load_fw = get_load_fw_instance(priv); - if (load_fw->handle_susp_resm) + if (load_fw->imem_mgmt) se_restore_imem_state(priv, &load_fw->imem); return 0; @@ -1309,7 +1340,7 @@ static const struct dev_pm_ops se_pm = { static struct platform_driver se_driver = { .driver = { - .name = "fsl-se-fw", + .name = "fsl-se", .of_match_table = se_match, .pm = &se_pm, }, diff --git a/drivers/firmware/imx/se_ctrl.h b/drivers/firmware/imx/se_ctrl.h index 9eb4d5601699..815222d40df0 100644 --- a/drivers/firmware/imx/se_ctrl.h +++ b/drivers/firmware/imx/se_ctrl.h @@ -98,7 +98,8 @@ struct se_api_msg { }; struct se_if_defines { - const void *info; + const u8 se_if_type; + const u8 se_instance_id; u8 cmd_tag; u8 rsp_tag; u8 success_tag; @@ -132,4 +133,5 @@ struct se_if_priv { u32 dev_ctx_mono_count; }; +char *get_se_if_name(u8 se_if_id); #endif diff --git a/include/uapi/linux/se_ioctl.h b/include/uapi/linux/se_ioctl.h index 939c461210f3..d31941e521c1 100644 --- a/include/uapi/linux/se_ioctl.h +++ b/include/uapi/linux/se_ioctl.h @@ -8,6 +8,23 @@ #include +#define SE_TYPE_STR_DBG "dbg" +#define SE_TYPE_STR_HSM "hsm" +#define SE_TYPE_STR_SHE "she" +#define SE_TYPE_STR_V2X_SV "v2x_sv" +#define SE_TYPE_STR_V2X_SG "v2x_sg" +#define SE_TYPE_STR_V2X_SHE "v2x_she" +#define SE_TYPE_STR_V2X_DBG "v2x_dbg" + +#define SE_TYPE_ID_UNKWN 0x0 +#define SE_TYPE_ID_DBG 0x1 +#define SE_TYPE_ID_HSM 0x2 +#define SE_TYPE_ID_SHE 0x3 +#define SE_TYPE_ID_V2X_DBG 0x4 +#define SE_TYPE_ID_V2X_SHE 0x5 +#define SE_TYPE_ID_V2X_SV 0x6 +#define SE_TYPE_ID_V2X_SG 0x7 + /* IOCTL definitions. */ struct se_ioctl_setup_iobuf {