From a7c0c27a6be0653774b9b99985aaa769f71b6e57 Mon Sep 17 00:00:00 2001 From: Qi Zhang Date: Fri, 18 Sep 2020 13:07:11 +0800 Subject: [PATCH] net/ice/base: read security revision The main NVM module and the Option ROM module contain a security revision in their CSS header. This security revision is used to determine whether or not the signed module should be loaded at bootup. If the module security revision is lower than the associated minimum security revision, it will not be loaded. The CSS header does not have a module id associated with it, and thus requires flat NVM reads in order to access it. To do this, take advantage of the cached bank information. Introduce a new "ice_read_flash_module" function that takes the module and bank to read. Implement both ice_read_active_nvm_module and ice_read_active_orom_module. These functions will use the cached values to determine the active bank and calculate the appropriate offset. Using these new access functions, extract the security revision for both the main NVM bank and the Option ROM into the associated info structure. Signed-off-by: Jacob Keller Signed-off-by: Qi Zhang Acked-by: Qiming Yang --- drivers/net/ice/base/ice_nvm.c | 174 ++++++++++++++++++++++++++++++++ drivers/net/ice/base/ice_type.h | 9 ++ 2 files changed, 183 insertions(+) diff --git a/drivers/net/ice/base/ice_nvm.c b/drivers/net/ice/base/ice_nvm.c index 61af767edd..7b76af7b6f 100644 --- a/drivers/net/ice/base/ice_nvm.c +++ b/drivers/net/ice/base/ice_nvm.c @@ -212,6 +212,107 @@ void ice_release_nvm(struct ice_hw *hw) ice_release_res(hw, ICE_NVM_RES_ID); } +/** + * ice_read_flash_module - Read a word from one of the main NVM modules + * @hw: pointer to the HW structure + * @bank: which bank of the module to read + * @module: the module to read + * @offset: the offset into the module in words + * @data: storage for the word read from the flash + * + * Read a word from the specified bank of the module. The bank must be either + * the 1st or 2nd bank. The word will be read using flat NVM access, and + * relies on the hw->flash.banks data being setup by + * ice_determine_active_flash_banks() during initialization. + */ +static enum ice_status +ice_read_flash_module(struct ice_hw *hw, enum ice_flash_bank bank, u16 module, + u32 offset, u16 *data) +{ + struct ice_bank_info *banks = &hw->flash.banks; + u32 bytes = sizeof(u16); + enum ice_status status; + __le16 data_local; + bool second_bank; + u32 start; + + ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); + + switch (bank) { + case ICE_1ST_FLASH_BANK: + second_bank = false; + break; + case ICE_2ND_FLASH_BANK: + second_bank = true; + break; + case ICE_INVALID_FLASH_BANK: + default: + ice_debug(hw, ICE_DBG_NVM, "Unexpected flash bank %u\n", bank); + return ICE_ERR_PARAM; + } + + switch (module) { + case ICE_SR_1ST_NVM_BANK_PTR: + start = banks->nvm_ptr + (second_bank ? banks->nvm_size : 0); + break; + case ICE_SR_1ST_OROM_BANK_PTR: + start = banks->orom_ptr + (second_bank ? banks->orom_size : 0); + break; + case ICE_SR_NETLIST_BANK_PTR: + start = banks->netlist_ptr + (second_bank ? banks->netlist_size : 0); + break; + default: + ice_debug(hw, ICE_DBG_NVM, "Unexpected flash module 0x%04x\n", module); + return ICE_ERR_PARAM; + } + + status = ice_acquire_nvm(hw, ICE_RES_READ); + if (status) + return status; + + status = ice_read_flat_nvm(hw, start + offset * sizeof(u16), &bytes, + (_FORCE_ u8 *)&data_local, false); + if (!status) + *data = LE16_TO_CPU(data_local); + + ice_release_nvm(hw); + + return status; +} + +/** + * ice_read_active_nvm_module - Read from the active main NVM module + * @hw: pointer to the HW structure + * @offset: offset into the NVM module to read, in words + * @data: storage for returned word value + * + * Read the specified word from the active NVM module. This includes the CSS + * header at the start of the NVM module. + */ +static enum ice_status +ice_read_active_nvm_module(struct ice_hw *hw, u32 offset, u16 *data) +{ + return ice_read_flash_module(hw, hw->flash.banks.nvm_bank, + ICE_SR_1ST_NVM_BANK_PTR, offset, data); +} + +/** + * ice_read_active_orom_module - Read from the active Option ROM module + * @hw: pointer to the HW structure + * @offset: offset into the OROM module to read, in words + * @data: storage for returned word value + * + * Read the specified word from the active Option ROM module of the flash. + * Note that unlike the NVM module, the CSS data is stored at the end of the + * module instead of at the beginning. + */ +static enum ice_status +ice_read_active_orom_module(struct ice_hw *hw, u32 offset, u16 *data) +{ + return ice_read_flash_module(hw, hw->flash.banks.orom_bank, + ICE_SR_1ST_OROM_BANK_PTR, offset, data); +} + /** * ice_read_sr_word - Reads Shadow RAM word and acquire NVM if necessary * @hw: pointer to the HW structure @@ -358,6 +459,32 @@ ice_read_pba_string(struct ice_hw *hw, u8 *pba_num, u32 pba_num_size) return status; } +/** + * ice_get_nvm_srev - Read the security revision from the NVM CSS header + * @hw: pointer to the HW struct + * @srev: storage for security revision + * + * Read the security revision out of the CSS header of the active NVM module + * bank. + */ +static enum ice_status ice_get_nvm_srev(struct ice_hw *hw, u32 *srev) +{ + enum ice_status status; + u16 srev_l, srev_h; + + status = ice_read_active_nvm_module(hw, ICE_NVM_CSS_SREV_L, &srev_l); + if (status) + return status; + + status = ice_read_active_nvm_module(hw, ICE_NVM_CSS_SREV_H, &srev_h); + if (status) + return status; + + *srev = srev_h << 16 | srev_l; + + return ICE_SUCCESS; +} + /** * ice_get_nvm_ver_info - Read NVM version information * @hw: pointer to the HW struct @@ -393,6 +520,49 @@ ice_get_nvm_ver_info(struct ice_hw *hw, struct ice_nvm_info *nvm) nvm->eetrack = (eetrack_hi << 16) | eetrack_lo; + status = ice_get_nvm_srev(hw, &nvm->srev); + if (status) + ice_debug(hw, ICE_DBG_NVM, "Failed to read NVM security revision.\n"); + + return ICE_SUCCESS; +} + +/** + * ice_get_orom_srev - Read the security revision from the OROM CSS header + * @hw: pointer to the HW struct + * @srev: storage for security revision + * + * Read the security revision out of the CSS header of the active OROM module + * bank. + */ +static enum ice_status ice_get_orom_srev(struct ice_hw *hw, u32 *srev) +{ + enum ice_status status; + u16 srev_l, srev_h; + u32 css_start; + + if (hw->flash.banks.orom_size < ICE_NVM_OROM_TRAILER_LENGTH) { + ice_debug(hw, ICE_DBG_NVM, "Unexpected Option ROM Size of %u\n", + hw->flash.banks.orom_size); + return ICE_ERR_CFG; + } + + /* calculate how far into the Option ROM the CSS header starts. Note + * that ice_read_active_orom_module takes a word offset so we need to + * divide by 2 here. + */ + css_start = (hw->flash.banks.orom_size - ICE_NVM_OROM_TRAILER_LENGTH) / 2; + + status = ice_read_active_orom_module(hw, css_start + ICE_NVM_CSS_SREV_L, &srev_l); + if (status) + return status; + + status = ice_read_active_orom_module(hw, css_start + ICE_NVM_CSS_SREV_H, &srev_h); + if (status) + return status; + + *srev = srev_h << 16 | srev_l; + return ICE_SUCCESS; } @@ -448,6 +618,10 @@ ice_get_orom_ver_info(struct ice_hw *hw, struct ice_orom_info *orom) orom->build = (u16)((combo_ver & ICE_OROM_VER_BUILD_MASK) >> ICE_OROM_VER_BUILD_SHIFT); + status = ice_get_orom_srev(hw, &orom->srev); + if (status) + ice_debug(hw, ICE_DBG_NVM, "Failed to read Option ROM security revision.\n"); + return ICE_SUCCESS; } diff --git a/drivers/net/ice/base/ice_type.h b/drivers/net/ice/base/ice_type.h index 1e1c672cbd..fb350faa60 100644 --- a/drivers/net/ice/base/ice_type.h +++ b/drivers/net/ice/base/ice_type.h @@ -509,11 +509,13 @@ struct ice_orom_info { u8 major; /* Major version of OROM */ u8 patch; /* Patch version of OROM */ u16 build; /* Build version of OROM */ + u32 srev; /* Security revision */ }; /* NVM version information */ struct ice_nvm_info { u32 eetrack; + u32 srev; u8 major; u8 minor; }; @@ -1117,6 +1119,13 @@ enum ice_sw_fwd_act_type { #define ICE_SR_LINK_DEFAULT_OVERRIDE_PTR 0x134 #define ICE_SR_POR_REGISTERS_AUTOLOAD_PTR 0x118 +/* CSS Header words */ +#define ICE_NVM_CSS_SREV_L 0x14 +#define ICE_NVM_CSS_SREV_H 0x15 + +/* Size in bytes of Option ROM trailer */ +#define ICE_NVM_OROM_TRAILER_LENGTH 660 + /* Auxiliary field, mask and shift definition for Shadow RAM and NVM Flash */ #define ICE_SR_VPD_SIZE_WORDS 512 #define ICE_SR_PCIE_ALT_SIZE_WORDS 512 -- 2.20.1