From: Qi Zhang Date: Thu, 29 Apr 2021 00:41:42 +0000 (+0800) Subject: net/ice/base: sign external device package programming X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=2913bc4155d2;p=dpdk.git net/ice/base: sign external device package programming External topology devices (e.g. PHYs) connected to 100G or to SoC that includes 100G IP might have a firmware engine within the device and the firmware is usually loaded from NVM connected to the topology device. The topology device NVM images can be updated using SW tools but such solution poses a security risk if there is no validation of the integrity of an image before programming it to the device NVM. In order to prevent security risk, the topology device NVM image might be included as part of 100G NVM image. When the topology device NVM image is present in the 100G NVM image, it is authenticated and might be loaded to the topology device at startup or on command of SW using dedicated AQ. This patch provides support for this functionality. Signed-off-by: Stefan Wegrzyn Signed-off-by: Qi Zhang Acked-by: Qi Zhang --- diff --git a/drivers/net/ice/base/ice_adminq_cmd.h b/drivers/net/ice/base/ice_adminq_cmd.h index 6b662b3889..3805fc9c5c 100644 --- a/drivers/net/ice/base/ice_adminq_cmd.h +++ b/drivers/net/ice/base/ice_adminq_cmd.h @@ -113,6 +113,10 @@ struct ice_aqc_list_caps_elem { #define ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE 0x0076 #define ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT 0x0077 #define ICE_AQC_CAPS_NVM_MGMT 0x0080 +#define ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0 0x0081 +#define ICE_AQC_CAPS_EXT_TOPO_DEV_IMG1 0x0082 +#define ICE_AQC_CAPS_EXT_TOPO_DEV_IMG2 0x0083 +#define ICE_AQC_CAPS_EXT_TOPO_DEV_IMG3 0x0084 u8 major_ver; u8 minor_ver; @@ -1614,7 +1618,7 @@ struct ice_aqc_set_mac_lb { u8 reserved[15]; }; -struct ice_aqc_link_topo_addr { +struct ice_aqc_link_topo_params { u8 lport_num; u8 lport_num_valid; #define ICE_AQC_LINK_TOPO_PORT_NUM_VALID BIT(0) @@ -1640,6 +1644,10 @@ struct ice_aqc_link_topo_addr { #define ICE_AQC_LINK_TOPO_NODE_CTX_PROVIDED 4 #define ICE_AQC_LINK_TOPO_NODE_CTX_OVERRIDE 5 u8 index; +}; + +struct ice_aqc_link_topo_addr { + struct ice_aqc_link_topo_params topo_params; __le16 handle; #define ICE_AQC_LINK_TOPO_HANDLE_S 0 #define ICE_AQC_LINK_TOPO_HANDLE_M (0x3FF << ICE_AQC_LINK_TOPO_HANDLE_S) @@ -1754,23 +1762,18 @@ struct ice_aqc_sw_gpio { u8 rsvd[12]; }; -/* Program topology device NVM (direct, 0x06F2) */ -struct ice_aqc_program_topology_device_nvm { - u8 lport_num; - u8 lport_num_valid; - u8 node_type_ctx; - u8 index; +/* Program Topology Device NVM (direct, 0x06F2) */ +struct ice_aqc_prog_topo_dev_nvm { + struct ice_aqc_link_topo_params topo_params; u8 rsvd[12]; }; -/* Read topology device NVM (indirect, 0x06F3) */ -struct ice_aqc_read_topology_device_nvm { - u8 lport_num; - u8 lport_num_valid; - u8 node_type_ctx; - u8 index; +/* Read Topology Device NVM (direct, 0x06F3) */ +struct ice_aqc_read_topo_dev_nvm { + struct ice_aqc_link_topo_params topo_params; __le32 start_address; - u8 data_read[8]; +#define ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE 8 + u8 data_read[ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE]; }; /* NVM Read command (indirect 0x0701) @@ -2744,6 +2747,8 @@ struct ice_aqc_set_health_status_config { #define ICE_AQC_HEALTH_STATUS_ERR_LINK_HW_ACCESS 0x115 #define ICE_AQC_HEALTH_STATUS_ERR_LINK_RUNTIME 0x116 #define ICE_AQC_HEALTH_STATUS_ERR_DNL_INIT 0x117 +#define ICE_AQC_HEALTH_STATUS_ERR_PHY_NVM_PROG 0x120 +#define ICE_AQC_HEALTH_STATUS_ERR_PHY_FW_LOAD 0x121 #define ICE_AQC_HEALTH_STATUS_INFO_RECOVERY 0x500 #define ICE_AQC_HEALTH_STATUS_ERR_FLASH_ACCESS 0x501 #define ICE_AQC_HEALTH_STATUS_ERR_NVM_AUTH 0x502 @@ -2946,6 +2951,8 @@ struct ice_aq_desc { get_supported_health_status_codes; struct ice_aqc_get_health_status get_health_status; struct ice_aqc_clear_health_status clear_health_status; + struct ice_aqc_prog_topo_dev_nvm prog_topo_dev_nvm; + struct ice_aqc_read_topo_dev_nvm read_topo_dev_nvm; } params; }; @@ -3122,8 +3129,8 @@ enum ice_adminq_opc { ice_aqc_opc_sff_eeprom = 0x06EE, ice_aqc_opc_sw_set_gpio = 0x06EF, ice_aqc_opc_sw_get_gpio = 0x06F0, - ice_aqc_opc_program_topology_device_nvm = 0x06F2, - ice_aqc_opc_read_topology_device_nvm = 0x06F3, + ice_aqc_opc_prog_topo_dev_nvm = 0x06F2, + ice_aqc_opc_read_topo_dev_nvm = 0x06F3, /* NVM commands */ ice_aqc_opc_nvm_read = 0x0701, diff --git a/drivers/net/ice/base/ice_common.c b/drivers/net/ice/base/ice_common.c index 2424f3b4b3..ac412a1aa7 100644 --- a/drivers/net/ice/base/ice_common.c +++ b/drivers/net/ice/base/ice_common.c @@ -237,11 +237,13 @@ ice_aq_get_link_topo_handle(struct ice_port_info *pi, u8 node_type, ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo); - cmd->addr.node_type_ctx = (ICE_AQC_LINK_TOPO_NODE_CTX_PORT << - ICE_AQC_LINK_TOPO_NODE_CTX_S); + cmd->addr.topo_params.node_type_ctx = + (ICE_AQC_LINK_TOPO_NODE_CTX_PORT << + ICE_AQC_LINK_TOPO_NODE_CTX_S); /* set node type */ - cmd->addr.node_type_ctx |= (ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type); + cmd->addr.topo_params.node_type_ctx |= + (ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type); return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd); } @@ -2000,6 +2002,47 @@ ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps, ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n", prefix, caps->max_mtu); break; + case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0: + case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG1: + case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG2: + case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG3: + { + u8 index = cap - ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0; + + if (index >= ICE_EXT_TOPO_DEV_IMG_COUNT) + break; + + caps->ext_topo_dev_img_ver_high[index] = number; + caps->ext_topo_dev_img_ver_low[index] = logical_id; + caps->ext_topo_dev_img_part_num[index] = + (phys_id & ICE_EXT_TOPO_DEV_IMG_PART_NUM_M) >> + ICE_EXT_TOPO_DEV_IMG_PART_NUM_S; + caps->ext_topo_dev_img_load_en[index] = + (phys_id & ICE_EXT_TOPO_DEV_IMG_LOAD_EN) != 0; + caps->ext_topo_dev_img_prog_en[index] = + (phys_id & ICE_EXT_TOPO_DEV_IMG_PROG_EN) != 0; + ice_debug(hw, ICE_DBG_INIT, + "%s: ext_topo_dev_img_ver_high[%d] = %d\n", + prefix, index, + caps->ext_topo_dev_img_ver_high[index]); + ice_debug(hw, ICE_DBG_INIT, + "%s: ext_topo_dev_img_ver_low[%d] = %d\n", + prefix, index, + caps->ext_topo_dev_img_ver_low[index]); + ice_debug(hw, ICE_DBG_INIT, + "%s: ext_topo_dev_img_part_num[%d] = %d\n", + prefix, index, + caps->ext_topo_dev_img_part_num[index]); + ice_debug(hw, ICE_DBG_INIT, + "%s: ext_topo_dev_img_load_en[%d] = %d\n", + prefix, index, + caps->ext_topo_dev_img_load_en[index]); + ice_debug(hw, ICE_DBG_INIT, + "%s: ext_topo_dev_img_prog_en[%d] = %d\n", + prefix, index, + caps->ext_topo_dev_img_prog_en[index]); + break; + } default: /* Not one of the recognized common capabilities */ found = false; @@ -3364,6 +3407,76 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr, return status; } +/** + * ice_aq_prog_topo_dev_nvm + * @hw: pointer to the hardware structure + * @topo_params: pointer to structure storing topology parameters for a device + * @cd: pointer to command details structure or NULL + * + * Program Topology Device NVM (0x06F2) + * + */ +enum ice_status +ice_aq_prog_topo_dev_nvm(struct ice_hw *hw, + struct ice_aqc_link_topo_params *topo_params, + struct ice_sq_cd *cd) +{ + struct ice_aqc_prog_topo_dev_nvm *cmd; + struct ice_aq_desc desc; + + cmd = &desc.params.prog_topo_dev_nvm; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_prog_topo_dev_nvm); + + ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params), + ICE_NONDMA_TO_NONDMA); + + return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); +} + +/** + * ice_aq_read_topo_dev_nvm + * @hw: pointer to the hardware structure + * @topo_params: pointer to structure storing topology parameters for a device + * @start_address: byte offset in the topology device NVM + * @data: pointer to data buffer + * @data_size: number of bytes to be read from the topology device NVM + * @cd: pointer to command details structure or NULL + * Read Topology Device NVM (0x06F3) + * + */ +enum ice_status +ice_aq_read_topo_dev_nvm(struct ice_hw *hw, + struct ice_aqc_link_topo_params *topo_params, + u32 start_address, u8 *data, u8 data_size, + struct ice_sq_cd *cd) +{ + struct ice_aqc_read_topo_dev_nvm *cmd; + struct ice_aq_desc desc; + enum ice_status status; + + if (!data || data_size == 0 || + data_size > ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE) + return ICE_ERR_PARAM; + + cmd = &desc.params.read_topo_dev_nvm; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_topo_dev_nvm); + + desc.datalen = data_size; + ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params), + ICE_NONDMA_TO_NONDMA); + cmd->start_address = CPU_TO_LE32(start_address); + + status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); + if (status) + return status; + + ice_memcpy(data, cmd->data_read, data_size, ICE_NONDMA_TO_NONDMA); + + return ICE_SUCCESS; +} + /** * __ice_aq_get_set_rss_lut * @hw: pointer to the hardware structure diff --git a/drivers/net/ice/base/ice_common.h b/drivers/net/ice/base/ice_common.h index 62b5052797..22ea89cbbb 100644 --- a/drivers/net/ice/base/ice_common.h +++ b/drivers/net/ice/base/ice_common.h @@ -187,6 +187,16 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr, u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length, bool write, struct ice_sq_cd *cd); +enum ice_status +ice_aq_prog_topo_dev_nvm(struct ice_hw *hw, + struct ice_aqc_link_topo_params *topo_params, + struct ice_sq_cd *cd); +enum ice_status +ice_aq_read_topo_dev_nvm(struct ice_hw *hw, + struct ice_aqc_link_topo_params *topo_params, + u32 start_address, u8 *buf, u8 buf_size, + struct ice_sq_cd *cd); + enum ice_status ice_get_ctx(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info); enum ice_status diff --git a/drivers/net/ice/base/ice_type.h b/drivers/net/ice/base/ice_type.h index 637dd306d4..f64f215528 100644 --- a/drivers/net/ice/base/ice_type.h +++ b/drivers/net/ice/base/ice_type.h @@ -449,6 +449,19 @@ struct ice_hw_common_caps { #define ICE_NVM_MGMT_SEC_REV_DISABLED BIT(0) #define ICE_NVM_MGMT_UPDATE_DISABLED BIT(1) #define ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT BIT(3) + + /* External topology device images within the NVM */ +#define ICE_EXT_TOPO_DEV_IMG_COUNT 4 + u32 ext_topo_dev_img_ver_high[ICE_EXT_TOPO_DEV_IMG_COUNT]; + u32 ext_topo_dev_img_ver_low[ICE_EXT_TOPO_DEV_IMG_COUNT]; + u8 ext_topo_dev_img_part_num[ICE_EXT_TOPO_DEV_IMG_COUNT]; +#define ICE_EXT_TOPO_DEV_IMG_PART_NUM_S 8 +#define ICE_EXT_TOPO_DEV_IMG_PART_NUM_M \ + MAKEMASK(0xFF, ICE_EXT_TOPO_DEV_IMG_PART_NUM_S) + bool ext_topo_dev_img_load_en[ICE_EXT_TOPO_DEV_IMG_COUNT]; +#define ICE_EXT_TOPO_DEV_IMG_LOAD_EN BIT(0) + bool ext_topo_dev_img_prog_en[ICE_EXT_TOPO_DEV_IMG_COUNT]; +#define ICE_EXT_TOPO_DEV_IMG_PROG_EN BIT(1) }; /* Function specific capabilities */