net/ice/base: sign external device package programming
authorQi Zhang <qi.z.zhang@intel.com>
Thu, 29 Apr 2021 00:41:42 +0000 (08:41 +0800)
committerQi Zhang <qi.z.zhang@intel.com>
Fri, 30 Apr 2021 13:48:05 +0000 (15:48 +0200)
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 <stefan.wegrzyn@intel.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
drivers/net/ice/base/ice_adminq_cmd.h
drivers/net/ice/base/ice_common.c
drivers/net/ice/base/ice_common.h
drivers/net/ice/base/ice_type.h

index 6b662b3..3805fc9 100644 (file)
@@ -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,
index 2424f3b..ac412a1 100644 (file)
@@ -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
index 62b5052..22ea89c 100644 (file)
@@ -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
index 637dd30..f64f215 100644 (file)
@@ -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 */