diff options
-rw-r--r-- | src/include/usr/sbe/sbe_update.H | 23 | ||||
-rw-r--r-- | src/include/usr/sbeio/sbe_psudd.H | 33 | ||||
-rw-r--r-- | src/include/usr/sbeio/sbeioif.H | 22 | ||||
-rw-r--r-- | src/usr/sbe/sbe_update.C | 383 | ||||
-rw-r--r-- | src/usr/sbeio/makefile | 1 | ||||
-rw-r--r-- | src/usr/sbeio/sbe_psuReadSeeprom.C | 108 |
6 files changed, 467 insertions, 103 deletions
diff --git a/src/include/usr/sbe/sbe_update.H b/src/include/usr/sbe/sbe_update.H index 25d7448af..45e295c2d 100644 --- a/src/include/usr/sbe/sbe_update.H +++ b/src/include/usr/sbe/sbe_update.H @@ -77,12 +77,17 @@ namespace SBE const uint64_t SBE_VERSION_SPACE_WITH_ECC = (256 * 9) / 8; // 256B + ECC const uint64_t SBE_SEEPROM_SIZE = 64*KILOBYTE; // 64KB const uint64_t SBE_SEEPROM_ECC_PAD = SBE_SEEPROM_SIZE % 9; + const uint64_t SBE_SEEPROM_SIZE_WO_ECC = ((64*KILOBYTE - SBE_SEEPROM_ECC_PAD) / 9) * 8 ; // SBE Version (with ECC) kept at end of fourth 64KB memory // Adjust end of usable memory with ECC to be a multiple of 9 bytes const uint64_t SBE_VERSION_SEEPROM_ADDRESS = 4*SBE_SEEPROM_SIZE - SBE_SEEPROM_ECC_PAD - SBE_VERSION_SPACE_WITH_ECC; + const uint64_t SBE_SEEPROM_VERSION_READ_SIZE = 0x100; // 128 Bytes * 2 (256 decimal) + const uint64_t END_OF_SEEPROM_MINUS_READ_SIZE = 4*SBE_SEEPROM_SIZE_WO_ECC + - SBE_SEEPROM_VERSION_READ_SIZE; + // Used to read SBE Boot Side from processor // (PERV_SB_CS_SCOM 0x00050008 or PERV_SB_CS_FSI 0x2808) const uint64_t SBE_BOOT_SELECT_MASK = 0x0000400000000000; @@ -478,7 +483,7 @@ namespace SBE sbeSeepromSide_t& o_bootSide); /** - * @brief Collects Version information from a specific SEEPROM + * @brief Collects Version information from a specific SEEPROM using I2C * * @param[in] i_target Target processor to customize * @@ -492,10 +497,24 @@ namespace SBE * * @return errlHndl_t Error log handle on failure. */ - errlHndl_t getSeepromSideVersion(TARGETING::Target* i_target, + errlHndl_t getSeepromSideVersionViaI2c(TARGETING::Target* i_target, EEPROM::eeprom_chip_types_t i_seepromSide, sbeSeepromVersionInfo_t& o_info, bool& o_seeprom_ver_ECC_fail); + /** + * @brief Collects Version information from a specific SEEPROM using PSU ChipOp + * + * @param[in] i_target Target processor to customize + * + * @param[out] o_info Struct containing the SBE Version Information + * + * @param[out] o_opSupported output if sbe supports seeprom read chip op or not + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getSeepromSideVersionViaChipOp(TARGETING::Target* i_target, + sbeSeepromVersionInfo_t& o_info, + bool& o_opSupported); /** * @brief Updates a specific SEEPROM diff --git a/src/include/usr/sbeio/sbe_psudd.H b/src/include/usr/sbeio/sbe_psudd.H index 5b2983c39..76603859f 100644 --- a/src/include/usr/sbeio/sbe_psudd.H +++ b/src/include/usr/sbeio/sbe_psudd.H @@ -102,6 +102,7 @@ class SbePsu //BYTE 7 options enum psuGenericMessageCommands { + SBE_PSU_READ_SEEPROM = 0x03, SBE_PSU_SET_FFDC_ADDRESS = 0x04, SBE_PSU_GENERIC_MSG_QUIESCE = 0x05, SBE_CMD_CONTROL_SYSTEM_CONFIG = 0x06, @@ -226,6 +227,25 @@ class SbePsu * 0x4 - Reg 2 is non-reserved (read or write this reg) * 0x8 - Reg 3 is non-reserved (read or write this reg) */ + enum psuReadSeepromMsgs + { + SBE_READ_SEEPROM_REQ_USED_REGS = 0x07, + SBE_READ_SEEPROM_RSP_USED_REGS = 0x01, + }; + + /** + * @brief non reserved word enums + * + * Shows which of the request and response msg registers are + * not reserved. Reserved registers do not need to be written + * or read. + * + * This is a 4 bit field: + * 0x1 - Reg 0 is non-reserved (read or write this reg) + * 0x2 - Reg 1 is non-reserved (read or write this reg) + * 0x4 - Reg 2 is non-reserved (read or write this reg) + * 0x8 - Reg 3 is non-reserved (read or write this reg) + */ enum psuStashKeyAddrNonReservedMsgs { SBE_STASH_KEY_ADDR_REQ_USED_REGS = 0x07, @@ -413,6 +433,19 @@ class SbePsu uint64_t cd7_setFFDCAddr_CommAddr; // mbxReg3 } PACKED; + struct //readSeeprom + { + uint16_t cd7_readSeeprom_Reserved; + uint16_t cd7_readSeeprom_ControlFlags; + uint16_t cd7_readSeeprom_SeqId; + uint8_t cd7_readSeeprom_CommandClass; + uint8_t cd7_readSeeprom_Command; + uint32_t cd7_readSeeprom_SeepromOffset; // mbxReg1 + uint32_t cd7_readSeeprom_ReadSize; // mbxReg1 + uint64_t cd7_readSeeprom_DestinationAddr; // mbxReg2 + uint64_t cd7_readSeeprom_MbxReg3Reserved; // mbxReg3 + } PACKED; + psuCommand(uint16_t i_controlFlags, //Mbx Reg 0 input uint8_t i_commandClass, //Mbx Reg 0 input uint8_t i_command) : //Mbx Reg 0 input diff --git a/src/include/usr/sbeio/sbeioif.H b/src/include/usr/sbeio/sbeioif.H index a951fe4a4..12881c939 100644 --- a/src/include/usr/sbeio/sbeioif.H +++ b/src/include/usr/sbeio/sbeioif.H @@ -285,6 +285,28 @@ namespace SBEIO uint64_t i_dataSize, const char * i_hwpName); + /** + * @brief Sends a PSU chipOp to request Seeprom read from SBE + * + * @param[in] i_target Target with SBE to send read request to + * @param[in] i_seepromOffset Offset in the seeprom image where we want + * to start copying from (ignores ECC) + * @param[in] i_readSize Amount of bytes we want to copy (ignores ECC) + * @param[in] i_destAddr Address that hostboot has prepared which the + * sbe will write too + * @param[out] o_opSupported Bool which tells us if the sbe supports the + * chipOp or not + * + * @return errlHndl_t Error log handle on failure. + * + */ + errlHndl_t sendPsuReadSeeprom(TARGETING::Target * i_target, + uint32_t i_seepromOffset, + uint32_t i_readSize, + uint64_t i_destAddr, + bool & o_opSupported); + + } //end namespace SBEIO diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C index 822a6912f..c22d84f08 100644 --- a/src/usr/sbe/sbe_update.C +++ b/src/usr/sbe/sbe_update.C @@ -1804,8 +1804,11 @@ namespace SBE TARGETING::get_huid(io_sbeState.target)); - errlHndl_t err = NULL; - void *sbeHbblImgPtr = NULL; + errlHndl_t err = nullptr; + void *sbeHbblImgPtr = nullptr; + bool l_sideZeroIsActive = true; + bool l_sbeSupportedSeepromReadOp = true; + bool l_errFoundDuringChipOp = false; // Clear build information io_sbeState.new_imageBuild.buildDate = 0; @@ -1816,6 +1819,62 @@ namespace SBE do{ + /***********************************************/ + /* Determine which SEEPROM System Booted On */ + /***********************************************/ + //Get Current (boot) Side + sbeSeepromSide_t tmp_cur_side = SBE_SEEPROM_INVALID; + err = getSbeBootSeeprom(io_sbeState.target, tmp_cur_side); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - " + "Error returned from getSbeBootSeeprom(), " + "RC=0x%X, PLID=0x%lX", + ERRL_GETRC_SAFE(err), + ERRL_GETPLID_SAFE(err)); + break; + } + + io_sbeState.cur_seeprom_side = tmp_cur_side; + if (io_sbeState.cur_seeprom_side == SBE_SEEPROM0) + { + io_sbeState.alt_seeprom_side = SBE_SEEPROM1; + } + else if ( io_sbeState.cur_seeprom_side == SBE_SEEPROM1) + { + io_sbeState.alt_seeprom_side = SBE_SEEPROM0; + l_sideZeroIsActive = false; + } + else + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error: " + "Unexpected cur_seeprom_side value = 0x%X, ", + io_sbeState.cur_seeprom_side); + + /*@ + * @errortype + * @moduleid SBE_GET_TARGET_INFO_STATE + * @reasoncode SBE_INVALID_SEEPROM_SIDE + * @userdata1 Temporary Current Side + * @userdata2 SBE State Current Side + * @devdesc Invalid Boot SEEPROM Side Found + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_GET_TARGET_INFO_STATE, + SBE_INVALID_SEEPROM_SIDE, + tmp_cur_side, + io_sbeState.cur_seeprom_side); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + + break; + } + + TRACUCOMP( g_trac_sbe,"getSbeInfoState() - cur=0x%X, alt=0x%X", + io_sbeState.cur_seeprom_side, + io_sbeState.alt_seeprom_side); + /************************************************************/ /* Set Target Properties (target_is_master previously set) */ /************************************************************/ @@ -1823,51 +1882,138 @@ namespace SBE /*******************************************/ - /* Get SEEPROM A SBE Version Information */ + /* Get SEEPROM 0 SBE Version Information */ /*******************************************/ - err = getSeepromSideVersion(io_sbeState.target, - EEPROM::SBE_PRIMARY, - io_sbeState.seeprom_0_ver, - io_sbeState.seeprom_0_ver_ECC_fail); - if(err) + // If the current seeprom is side 0 and is on master proc, + // then attempt read via chipOp + if (l_sideZeroIsActive && io_sbeState.target_is_master) { - TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " - "getting SBE Information from SEEPROM A (0x%X), " - "RC=0x%X, PLID=0x%lX", - EEPROM::SBE_PRIMARY, - ERRL_GETRC_SAFE(err), - ERRL_GETPLID_SAFE(err)); - break; + err = getSeepromSideVersionViaChipOp(io_sbeState.target, + io_sbeState.seeprom_0_ver, + l_sbeSupportedSeepromReadOp); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " + "getting SBE Information from SEEPROM 0 (Primary) via ChipOp " + "RC=0x%X, PLID=0x%lX, will attempt I2C read instead", + ERRL_GETRC_SAFE(err), + ERRL_GETPLID_SAFE(err)); + //Commit error as informational and attempt reading via i2c + l_errFoundDuringChipOp = true; + err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); + err->collectTrace(SBE_COMP_NAME, 256); + err->collectTrace(SBEIO_COMP_NAME, 256); + errlCommit( err, SBEIO_COMP_ID ); + } + else if(!l_sbeSupportedSeepromReadOp) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " + "getting SBE Information from SEEPROM 0 (Primary) via ChipOp. The " + "SBE firmware level does not support readSeeprom Op, will attempt I2C read instead"); + } + else + { + TRACDBIN(g_trac_sbe, "getSbeInfoState found via ChipOp -spA", + &(io_sbeState.seeprom_0_ver), + sizeof(sbeSeepromVersionInfo_t)); + } } - TRACDBIN(g_trac_sbe, "getSbeInfoState-spA", - &(io_sbeState.seeprom_0_ver), - sizeof(sbeSeepromVersionInfo_t)); + //If side 0 is not active, or this is a slave proc, or there was + //an error trying to read the primary via chipOp, then try reading via I2C + if(!l_sideZeroIsActive || !l_sbeSupportedSeepromReadOp || + l_errFoundDuringChipOp|| !io_sbeState.target_is_master) + { + + err = getSeepromSideVersionViaI2c(io_sbeState.target, + EEPROM::SBE_PRIMARY, + io_sbeState.seeprom_0_ver, + io_sbeState.seeprom_0_ver_ECC_fail); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " + "getting SBE Information from SEEPROM 0 (Primary) via I2C, " + "RC=0x%X, PLID=0x%lX", + ERRL_GETRC_SAFE(err), + ERRL_GETPLID_SAFE(err)); + break; + } + + TRACDBIN(g_trac_sbe, "getSbeInfoState found via I2C -spA", + &(io_sbeState.seeprom_0_ver), + sizeof(sbeSeepromVersionInfo_t)); + } /*******************************************/ - /* Get SEEPROM B SBE Version Information */ + /* Get SEEPROM 1 SBE Version Information */ /*******************************************/ - err = getSeepromSideVersion(io_sbeState.target, - EEPROM::SBE_BACKUP, - io_sbeState.seeprom_1_ver, - io_sbeState.seeprom_1_ver_ECC_fail); - if(err) + //If side 1 is active and this is master, then attempt read via chipOp + //Note that there is no reason to attempt chipOp on backup if it failed + //on the primary. + if (!l_sideZeroIsActive && l_sbeSupportedSeepromReadOp && + !l_errFoundDuringChipOp && io_sbeState.target_is_master) { - TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " - "getting SBE Information from SEEPROM B (0x%X), " - "RC=0x%X, PLID=0x%lX", - EEPROM::SBE_BACKUP, - ERRL_GETRC_SAFE(err), - ERRL_GETPLID_SAFE(err)); - break; + err = getSeepromSideVersionViaChipOp(io_sbeState.target, + io_sbeState.seeprom_1_ver, + l_sbeSupportedSeepromReadOp); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " + "getting SBE Information from SEEPROM 1 (Backup) via Chipop, " + "RC=0x%X, PLID=0x%lX, will attempt I2C read instead", + ERRL_GETRC_SAFE(err), + ERRL_GETPLID_SAFE(err)); + //Commit error as informational and attempt reading via i2c + l_errFoundDuringChipOp = true; + err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); + err->collectTrace(SBE_COMP_NAME, 256); + err->collectTrace(SBEIO_COMP_NAME, 256); + errlCommit( err, SBEIO_COMP_ID ); + } + else if(!l_sbeSupportedSeepromReadOp) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " + "getting SBE Information from SEEPROM 1 (Backup) via ChipOp. The " + "SBE firmware level does not support readSeeprom Op, will attempt I2C read instead"); + } + else + { + TRACDBIN(g_trac_sbe, "getSbeInfoState found via Chipop -spB", + &(io_sbeState.seeprom_1_ver), + sizeof(sbeSeepromVersionInfo_t)); + } } - TRACDBIN(g_trac_sbe, "getSbeInfoState-spB", - &(io_sbeState.seeprom_1_ver), - sizeof(sbeSeepromVersionInfo_t)); + //If side 1 is not active, or this is a slave proc, or there was + //an error trying to read the primary via chipOp, then try reading via I2C + if(l_sideZeroIsActive || !l_sbeSupportedSeepromReadOp || + l_errFoundDuringChipOp || !io_sbeState.target_is_master) + { + err = getSeepromSideVersionViaI2c(io_sbeState.target, + EEPROM::SBE_BACKUP, + io_sbeState.seeprom_1_ver, + io_sbeState.seeprom_1_ver_ECC_fail); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " + "getting SBE Information from SEEPROM 1 (Backup) via I2C, " + "RC=0x%X, PLID=0x%lX", + ERRL_GETRC_SAFE(err), + ERRL_GETPLID_SAFE(err)); + break; + } + + TRACDBIN(g_trac_sbe, "getSbeInfoState-spB found via I2C", + &(io_sbeState.seeprom_1_ver), + sizeof(sbeSeepromVersionInfo_t)); + } /*******************************************/ @@ -2201,62 +2347,6 @@ namespace SBE io_sbeState.permanent_seeprom_side = SBE_SEEPROM1; } - - /***********************************************/ - /* Determine which SEEPROM System Booted On */ - /***********************************************/ - //Get Current (boot) Side - sbeSeepromSide_t tmp_cur_side = SBE_SEEPROM_INVALID; - err = getSbeBootSeeprom(io_sbeState.target, tmp_cur_side); - if(err) - { - TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - " - "Error returned from getSbeBootSeeprom(), " - "RC=0x%X, PLID=0x%lX", - ERRL_GETRC_SAFE(err), - ERRL_GETPLID_SAFE(err)); - break; - } - - io_sbeState.cur_seeprom_side = tmp_cur_side; - if (io_sbeState.cur_seeprom_side == SBE_SEEPROM0) - { - io_sbeState.alt_seeprom_side = SBE_SEEPROM1; - } - else if ( io_sbeState.cur_seeprom_side == SBE_SEEPROM1) - { - io_sbeState.alt_seeprom_side = SBE_SEEPROM0; - } - else - { - TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error: " - "Unexpected cur_seeprom_side value = 0x%X, ", - io_sbeState.cur_seeprom_side); - - /*@ - * @errortype - * @moduleid SBE_GET_TARGET_INFO_STATE - * @reasoncode SBE_INVALID_SEEPROM_SIDE - * @userdata1 Temporary Current Side - * @userdata2 SBE State Current Side - * @devdesc Invalid Boot SEEPROM Side Found - */ - err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, - SBE_GET_TARGET_INFO_STATE, - SBE_INVALID_SEEPROM_SIDE, - tmp_cur_side, - io_sbeState.cur_seeprom_side); - err->collectTrace(SBE_COMP_NAME); - err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, - HWAS::SRCI_PRIORITY_HIGH ); - - break; - } - - TRACUCOMP( g_trac_sbe,"getSbeInfoState() - cur=0x%X, alt=0x%X", - io_sbeState.cur_seeprom_side, - io_sbeState.alt_seeprom_side); - }while(0); if(err && (io_sbeState.new_imageBuild.buildDate != 0) && @@ -2276,13 +2366,13 @@ namespace SBE ///////////////////////////////////////////////////////////////////// - errlHndl_t getSeepromSideVersion(TARGETING::Target* i_target, + errlHndl_t getSeepromSideVersionViaI2c(TARGETING::Target* i_target, EEPROM::eeprom_chip_types_t i_seepromSide, sbeSeepromVersionInfo_t& o_info, bool& o_seeprom_ver_ECC_fail) { TRACUCOMP( g_trac_sbe, - ENTER_MRK"getSeepromSideVersion(): HUID=0x%.8X, side:%d", + ENTER_MRK"getSeepromSideVersionViaI2c(): HUID=0x%.8X, side:%d", TARGETING::get_huid(i_target), i_seepromSide); errlHndl_t err = NULL; @@ -2314,7 +2404,7 @@ namespace SBE if(err) { - TRACFCOMP( g_trac_sbe, ERR_MRK"getSeepromSideVersion() - " + TRACFCOMP( g_trac_sbe, ERR_MRK"getSeepromSideVersionViaI2c() - " "Error reading SBE Version from Seeprom 0x%X, " "HUID=0x%.8X, RC=0x%X, PLID=0x%lX", i_seepromSide, TARGETING::get_huid(i_target), @@ -2324,7 +2414,7 @@ namespace SBE } TRACDBIN(g_trac_sbe, - "getSeepromSideVersion() - tmp_data_ECC", + "getSeepromSideVersionViaI2c() - tmp_data_ECC", tmp_data_ECC, sbeInfoSize_ECC); @@ -2342,7 +2432,7 @@ namespace SBE SBE_VERSION_SEEPROM_ADDRESS, SBE_SEEPROM_SIZE); - TRACUCOMP( g_trac_sbe, "getSeepromSideVersion(): First 8-Bytes: " + TRACUCOMP( g_trac_sbe, "getSeepromSideVersionViaI2c(): First 8-Bytes: " "eccStatus=%d, version=0x%X, data_crc=0x%X", eccStatus, o_info.struct_version, o_info.data_crc); @@ -2357,7 +2447,7 @@ namespace SBE else { // Unsupported versions - ignoring any ECC errors - TRACFCOMP( g_trac_sbe, "getSeepromSideVersion(): Unsupported " + TRACFCOMP( g_trac_sbe, "getSeepromSideVersionViaI2c(): Unsupported " "Struct Version=0x%X, ignoring any eccStatus=%d", o_info.struct_version, eccStatus); @@ -2372,7 +2462,7 @@ namespace SBE SBE_VERSION_SEEPROM_ADDRESS, SBE_SEEPROM_SIZE); - TRACFCOMP( g_trac_sbe, "getSeepromSideVersion(): eccStatus=%d, " + TRACFCOMP( g_trac_sbe, "getSeepromSideVersionViaI2c(): eccStatus=%d, " "sizeof o_info/sI=%d, sI_ECC=%d, origin golden=%i", eccStatus, sbeInfoSize, sbeInfoSize_ECC, o_info.origin); @@ -2380,7 +2470,7 @@ namespace SBE // clear data and set o_seeprom_ver_ECC_fail=true if ( eccStatus == PNOR::ECC::UNCORRECTABLE ) { - TRACFCOMP( g_trac_sbe, ERR_MRK"getSeepromSideVersion() - ECC " + TRACFCOMP( g_trac_sbe, ERR_MRK"getSeepromSideVersionViaI2c() - ECC " "ERROR: Handled. eccStatus=%d, side=%d, sizeof " "o_info/sI=%d, sI_ECC=%d", eccStatus, i_seepromSide, sbeInfoSize, @@ -2389,14 +2479,14 @@ namespace SBE memset( &o_info, 0, sizeof(o_info)); o_seeprom_ver_ECC_fail = true; - TRACUCOMP( g_trac_sbe, "getSeepromSideVersion(): clearing out " + TRACUCOMP( g_trac_sbe, "getSeepromSideVersionViaI2c(): clearing out " "version data (o_info) for side %d and returning " "o_seeprom_ver_ECC_fail as true (%d)", i_seepromSide, o_seeprom_ver_ECC_fail); } TRACDBIN(g_trac_sbe, - "getSeepromSideVersion: data (no ECC)", + "getSeepromSideVersionViaI2c: data (no ECC)", &o_info, sizeof(o_info)); @@ -2407,12 +2497,103 @@ namespace SBE TRACUCOMP( g_trac_sbe, - EXIT_MRK"getSeepromSideVersion: o_seeprom_ver_ECC_fail=%d", + EXIT_MRK"getSeepromSideVersionViaI2c: o_seeprom_ver_ECC_fail=%d", o_seeprom_ver_ECC_fail ); return err; } +errlHndl_t getSeepromSideVersionViaChipOp(TARGETING::Target* i_target, + sbeSeepromVersionInfo_t& o_info, + bool& o_opSupported) + { + errlHndl_t l_err = nullptr; + + // Set these variables to the read out the max struct size + // Supported version 1 is a subset of supported version 2 + size_t sbeInfoSize = sizeof(sbeSeepromVersionInfo_t); + + //Set up the buffer which the SBE will copy the version info to + //Add 127 bytes to the buffer length so we can guarantee a 128 byte aligned addr + //Note that the SBE_SEEPROM_VERSION_READ_SIZE is 3 * 128 Bytes to be cacheline aligned + uint8_t * l_seepromReadBuffer = static_cast<uint8_t*>( + malloc(SBE_SEEPROM_VERSION_READ_SIZE + 127 )); + + uint64_t l_seepromReadBufferAligned = ALIGN_X(reinterpret_cast<uint64_t>(l_seepromReadBuffer), + 128); + + do{ + + /***********************************************/ + /* Read SBE Version SBE Version Information */ + /***********************************************/ + // Clear Buffer + memset( reinterpret_cast<uint8_t*>(l_seepromReadBufferAligned), + 0, + SBE_SEEPROM_VERSION_READ_SIZE ); + + // Clear destination + memset( &o_info, 0, sizeof(o_info) ); + + l_err = SBEIO::sendPsuReadSeeprom(i_target, + END_OF_SEEPROM_MINUS_READ_SIZE, + SBE_SEEPROM_VERSION_READ_SIZE, + mm_virt_to_phys(reinterpret_cast<void*>(l_seepromReadBufferAligned)), + o_opSupported); + + if(!l_err && o_opSupported) + { + + TRACDBIN(g_trac_sbe, + "getSeepromSideVersionViaChipOp() - l_seepromReadBufferAligned", + reinterpret_cast<uint8_t*>(l_seepromReadBufferAligned), + SBE_SEEPROM_VERSION_READ_SIZE); + + // Initially only look at the first 8-Bytes which should include + // the struct version value + memcpy ( &o_info, reinterpret_cast<void*>(l_seepromReadBufferAligned), 8); + + if ( STRUCT_VERSION_CHECK(o_info.struct_version) ) + { + // Supported Versions - set size variable + sbeInfoSize = SBE_SEEPROM_STRUCT_SIZES[o_info.struct_version]; + } + else + { + // Unsupported versions + TRACFCOMP( g_trac_sbe, "getSeepromSideVersion(): Unsupported " + "Struct Version=0x%X", + o_info.struct_version); + + break; + } + + //Copy the sbeInfo data into the struct that was passed into the function + memcpy ( &o_info, reinterpret_cast<void*>(l_seepromReadBufferAligned), sbeInfoSize); + + TRACDBIN(g_trac_sbe, + "getSeepromSideVersionViaChipOp: data (no ECC)", + &o_info, + sizeof(o_info)); + } + else + { + TRACFCOMP( g_trac_sbe, + "Error reading seeprom via chipOp, either the Op isnt supported by SBE or" + " something else went wrong, not going to attempt to parse results"); + } + + }while(0); + + //Free up the buffer before returning no matter what + free(l_seepromReadBuffer); + l_seepromReadBuffer = nullptr; + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"getSeepromSideVersionViaChipOp" ); + return l_err; + } + ///////////////////////////////////////////////////////////////////// errlHndl_t updateSeepromSide(sbeTargetState_t& io_sbeState) diff --git a/src/usr/sbeio/makefile b/src/usr/sbeio/makefile index 9d5710c7c..5f8af1adc 100644 --- a/src/usr/sbeio/makefile +++ b/src/usr/sbeio/makefile @@ -40,6 +40,7 @@ OBJS += sbe_psudd.o OBJS += sbe_utils.o OBJS += sbe_secureHwp.o OBJS += sbe_coreStateControl.o +OBJS += sbe_psuReadSeeprom.o OBJS += sbe_psuQuiesce.o OBJS += sbe_stashKeyAddr.o OBJS += sbe_continueMpipl.o diff --git a/src/usr/sbeio/sbe_psuReadSeeprom.C b/src/usr/sbeio/sbe_psuReadSeeprom.C new file mode 100644 index 000000000..9550b0cdd --- /dev/null +++ b/src/usr/sbeio/sbe_psuReadSeeprom.C @@ -0,0 +1,108 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbeio/sbe_psuReadSeeprom.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/** +* @file sbe_psuReadSeeprom.C +* @brief Send command to request Seeprom read on SBE +*/ + +#include <config.h> +#include <trace/interface.H> +#include <errl/errlmanager.H> +#include <sbeio/sbeioif.H> +#include <sbeio/sbe_psudd.H> + +extern trace_desc_t* g_trac_sbeio; + +#define SBE_TRACD(printf_string,args...) \ +TRACDCOMP(g_trac_sbeio,"psuReadSeeprom: " printf_string,##args) + +#define SBE_TRACF(printf_string,args...) \ +TRACFCOMP(g_trac_sbeio,"psuReadSeeprom: " printf_string,##args) + +namespace SBEIO +{ + + /** + * @brief Sends a PSU chipOp to request Seeprom read from SBE + * + * @param[in] i_target Target with SBE to send read request to + * @param[in] i_seepromOffset Offset in the seeprom image where we want + * to start copying from (ignores ECC) + * @param[in] i_readSize Amount of bytes we want to copy (ignores ECC) + * @param[in] i_destAddr Address that hostboot has prepared which the + * sbe will write too + * @param[out] o_opSupported Bool which tells us if the sbe supports the + * chipOp or not + * + * @return errlHndl_t Error log handle on failure. + * + */ + errlHndl_t sendPsuReadSeeprom(TARGETING::Target * i_target, + uint32_t i_seepromOffset, + uint32_t i_readSize, + uint64_t i_destAddr, + bool & o_opSupported) + { + errlHndl_t errl = nullptr; + + SBE_TRACD(ENTER_MRK "sending psu seeprom read request command from HB -> SBE"); + + // set up PSU command message + SbePsu::psuCommand l_psuCommand( + SbePsu::SBE_REQUIRE_RESPONSE | + SbePsu::SBE_REQUIRE_ACK, //control flags + SbePsu::SBE_PSU_GENERIC_MESSAGE, //command class + SbePsu::SBE_PSU_READ_SEEPROM); //command + SbePsu::psuResponse l_psuResponse; + + l_psuCommand.cd7_readSeeprom_SeepromOffset = i_seepromOffset; + l_psuCommand.cd7_readSeeprom_ReadSize = i_readSize; + l_psuCommand.cd7_readSeeprom_DestinationAddr = i_destAddr; + + + errl = SBEIO::SbePsu::getTheInstance().performPsuChipOp(i_target, + &l_psuCommand, + &l_psuResponse, + SbePsu::MAX_PSU_SHORT_TIMEOUT_NS, + SbePsu::SBE_READ_SEEPROM_REQ_USED_REGS, + SbePsu::SBE_READ_SEEPROM_RSP_USED_REGS); + + if(l_psuResponse.primaryStatus == SBE_PRI_INVALID_COMMAND && + l_psuResponse.secondaryStatus == SBE_SEC_COMMAND_NOT_SUPPORTED) + { + SBE_TRACF(ENTER_MRK "SBE firmware level does not support PSU Seeprom Read Requests"); + //Make sure we aren't passing out any errors if the command isn't supported + delete errl; + errl = nullptr; + o_opSupported = false; + } + + SBE_TRACD(EXIT_MRK "sendPsuReadSeeprom"); + + return errl; + }; + +} //end namespace SBEIO + |