From 67c5a1ebe73f81bca1bb6608bbb8f204f0f37fa8 Mon Sep 17 00:00:00 2001 From: Stephen Cprek Date: Fri, 14 Nov 2014 14:39:53 -0600 Subject: Support for Redundant Copy of HB code in PNOR - 2 TOC's per side - side, sideless, preserved, and readOnly tags - Determine which SEEPROM side HB booted from - Modify gaurd code to not run when gaurd section DNE Change-Id: I62dd27c9aa79c3111d27e647f1b66a7c938ad6e8 RTC:109398 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14629 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III --- src/usr/hwas/hwasPlatDeconfigGard.C | 89 +++++++++++++----- src/usr/pnor/HBconfig | 5 + src/usr/pnor/common/ffs_hb.H | 7 +- src/usr/pnor/makefile | 1 + src/usr/pnor/pnor_common.C | 182 +++++++++++++++++++++++++++--------- src/usr/pnor/pnor_common.H | 19 +++- src/usr/pnor/pnorrp.C | 152 ++++++++++++++++++------------ src/usr/pnor/pnorrp.H | 26 +++++- src/usr/pnor/pnorsbe.C | 87 +++++++++++++++++ src/usr/pnor/pnorvalid.C | 5 +- src/usr/pnor/runtime/rt_pnor.C | 11 ++- src/usr/pnor/runtime/rt_pnor.H | 2 +- src/usr/pnor/test/pnorrptest.H | 104 +++++++++++++++++++-- src/usr/sbe/sbe_update.C | 95 ++++++------------- src/usr/sbe/sbe_update.H | 38 ++------ src/usr/sbe/test/sbeupdatetest.H | 24 ++--- 16 files changed, 588 insertions(+), 259 deletions(-) create mode 100644 src/usr/pnor/pnorsbe.C (limited to 'src/usr') diff --git a/src/usr/hwas/hwasPlatDeconfigGard.C b/src/usr/hwas/hwasPlatDeconfigGard.C index 912f7d410..2911cf3c1 100644 --- a/src/usr/hwas/hwasPlatDeconfigGard.C +++ b/src/usr/hwas/hwasPlatDeconfigGard.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -52,6 +52,15 @@ using namespace HWAS::COMMON; using namespace TARGETING; const uint32_t EMPTY_GARD_RECORDID = 0xFFFFFFFF; +/** + * @brief Guard PNOR section info, obtained once for efficiency + */ +static PNOR::SectionInfo_t g_GardSectionInfo; + +/** + * @brief Flag indicating if getGardSectionInfo() was called previously + */ +static bool getGardSectionInfoCalled; void _flush(void *i_addr); errlHndl_t _GardRecordIdSetup(void *&io_platDeconfigGard); @@ -90,7 +99,7 @@ errlHndl_t DeconfigGard::platClearGardRecords( HWAS_MUTEX_LOCK(iv_mutex); l_pErr = _GardRecordIdSetup(iv_platDeconfigGard); - if (!l_pErr) + if (!l_pErr && iv_platDeconfigGard) { uint32_t l_gardRecordsCleared = 0; HBDeconfigGard *l_hbDeconfigGard = @@ -127,10 +136,6 @@ errlHndl_t DeconfigGard::platClearGardRecords( HWAS_INF("GARD Records Cleared: %d", l_gardRecordsCleared); } - else - { - HWAS_ERR("Error from _GardRecordIdSetup"); - } HWAS_MUTEX_UNLOCK(iv_mutex); #endif // CONFIG_NO_GARD_SUPPORT @@ -153,7 +158,7 @@ errlHndl_t DeconfigGard::platGetGardRecords( HWAS_MUTEX_LOCK(iv_mutex); l_pErr = _GardRecordIdSetup(iv_platDeconfigGard); - if (!l_pErr) + if (!l_pErr && iv_platDeconfigGard) { HBDeconfigGard *l_hbDeconfigGard = (HBDeconfigGard *)iv_platDeconfigGard; @@ -183,10 +188,6 @@ errlHndl_t DeconfigGard::platGetGardRecords( } } // for } - else - { - HWAS_ERR("Error from _GardRecordIdSetup"); - } HWAS_MUTEX_UNLOCK(iv_mutex); HWAS_INF("Get returning %d GARD Records", o_records.size()); @@ -269,9 +270,8 @@ errlHndl_t DeconfigGard::platCreateGardRecord( } l_pErr = _GardRecordIdSetup(iv_platDeconfigGard); - if (l_pErr) + if (l_pErr && iv_platDeconfigGard) { - HWAS_ERR("Error from _GardRecordIdSetup"); break; } @@ -394,20 +394,27 @@ errlHndl_t _GardRecordIdSetup( void *&io_platDeconfigGard) break; } - // allocate our memory and set things up - io_platDeconfigGard = malloc(sizeof(HBDeconfigGard)); - HBDeconfigGard *l_hbDeconfigGard = - (HBDeconfigGard *)io_platDeconfigGard; - - // get the PNOR address. + // Get the PNOR Guard information PNOR::SectionInfo_t l_section; - l_pErr = PNOR::getSectionInfo(PNOR::GUARD_DATA, l_section); + l_pErr = getGardSectionInfo(l_section); if (l_pErr) { - HWAS_ERR("PNOR::getSectionInfo failed!!!"); + HWAS_ERR("_GardRecordIdSetup: getGardSectionInfo failed!!!"); // no support for GARD in this configuration. break; } + // Check if guard section exists, as certain configs ignore the above + // error (e.g. golden side has no GARD section) + if (l_section.size == 0) + { + HWAS_ERR("_GardRecordIdSetup: No guard section skipping function"); + break; + } + + // allocate our memory and set things up + io_platDeconfigGard = malloc(sizeof(HBDeconfigGard)); + HBDeconfigGard *l_hbDeconfigGard = + (HBDeconfigGard *)io_platDeconfigGard; l_hbDeconfigGard->iv_pGardRecords = reinterpret_cast (l_section.vaddr); @@ -466,4 +473,44 @@ void _flush(void *i_addr) } } +errlHndl_t getGardSectionInfo(PNOR::SectionInfo_t& o_sectionInfo) +{ + errlHndl_t l_errl = NULL; + do + { + // getSectionInfo has already been called for GUARD_DATA + if(getGardSectionInfoCalled) + { + o_sectionInfo = g_GardSectionInfo; + break; + } + + // Get Guard Section Info and set gardSectionInfo + l_errl = PNOR::getSectionInfo(PNOR::GUARD_DATA, g_GardSectionInfo); + if (l_errl) + { + g_GardSectionInfo.size = 0; +// @TODO RTC: 120061 - replace config flag with a pnor interface call to say if +// there is a guard section on the current (active) side +// of pnor +#ifdef CONFIG_TWO_SIDE_SUPPORT + HWAS_INF("getGardSectionInfo: No guard section disabling guard support"); + l_errl = NULL; +#else + HWAS_ERR("getGardSectionInfo:getSectionInfo failed"); +#endif + } + else + { + HWAS_INF("getGardSectionInfo: Section %s found, size %d", + g_GardSectionInfo.name, g_GardSectionInfo.size); + } + + o_sectionInfo = g_GardSectionInfo; + getGardSectionInfoCalled = true; + } while(0); + + return l_errl; +} + } // namespace HWAS diff --git a/src/usr/pnor/HBconfig b/src/usr/pnor/HBconfig index 298144c8a..21082f4ea 100644 --- a/src/usr/pnor/HBconfig +++ b/src/usr/pnor/HBconfig @@ -37,3 +37,8 @@ config PNOR_IS_32MB default n help Size of the attached flash chip is 32MB, if not set then 64MB is default + +config TWO_SIDE_SUPPORT + default n + help + This is used to turn on/off two sided pnor support diff --git a/src/usr/pnor/common/ffs_hb.H b/src/usr/pnor/common/ffs_hb.H index b63802158..c96911b3f 100644 --- a/src/usr/pnor/common/ffs_hb.H +++ b/src/usr/pnor/common/ffs_hb.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ +/* Contributors Listed Below - COPYRIGHT 2012,2015 */ +/* [+] 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. */ @@ -25,7 +27,7 @@ /* * FSP Destination: src/hbfw/fsp/pnor/common/ffs_hb.H - * + * * NOTE: Do NOT modify this file in CMVC directly! It comes from the Hostboot * repository and will be overwritten. */ @@ -63,6 +65,7 @@ enum /* Miscellaneous Bits : 1 byte */ FFS_MISC_PRESERVED = 0x80, /**< Preserved across code updates */ + FFS_MISC_READ_ONLY = 0x40, /**< Read only section */ FFS_MISC_UNUSED = 0x1F, /**< Unused MISC Flags */ }; diff --git a/src/usr/pnor/makefile b/src/usr/pnor/makefile index 31087a4b2..2f0a4e19b 100644 --- a/src/usr/pnor/makefile +++ b/src/usr/pnor/makefile @@ -32,6 +32,7 @@ OBJS += pnor_common.o OBJS += pnorvalid.o OBJS += ecc.o OBJS += sfcdd.o +OBJS += pnorsbe.o #SFC Implementations OBJS += $(if $(CONFIG_SFC_IS_IBM_DPSS),sfc_ibm.o) diff --git a/src/usr/pnor/pnor_common.C b/src/usr/pnor/pnor_common.C index e8972e2c4..00931ec64 100644 --- a/src/usr/pnor/pnor_common.C +++ b/src/usr/pnor/pnor_common.C @@ -24,14 +24,15 @@ /* IBM_PROLOG_END_TAG */ #include "pnor_common.H" -#include #include #include "ffs.h" //Common header file with BuildingBlock. #include "common/ffs_hb.H" //Hostboot def of user data in ffs_entry struct +#include #include #include +#include // Trace definition trace_desc_t* g_trac_pnor = NULL; @@ -45,28 +46,29 @@ TRAC_INIT(&g_trac_pnor, PNOR_COMP_NAME, 4*KILOBYTE, TRACE::BUFFER_SLOW); //4K * Eyecatcher strings for PNOR TOC entries */ const char* cv_EYECATCHER[] = { - "part", /**< PNOR::TOC : Table of Contents */ - "HBI", /**< PNOR::HB_EXT_CODE : Hostboot Extended Image */ - "GLOBAL", /**< PNOR::GLOBAL_DATA : Global Data */ - "HBB", /**< PNOR::HB_BASE_CODE : Hostboot Base Image */ - "SBEC", /**< PNOR::CENTAUR_SBE : Centaur Self-Boot Engine image */ - "SBE", /**< PNOR::SBE_IPL : Self-Boot Enginer IPL image */ - "WINK", /**< PNOR::WINK : Sleep Winkle Reference image */ - "PAYLOAD", /**< PNOR::PAYLOAD : HAL/OPAL */ - "HBRT", /**< PNOR::HB_RUNTIME : Hostboot Runtime (for Sapphire) */ - "HBD", /**< PNOR::HB_DATA : Hostboot Data */ - "GUARD", /**< PNOR::GUARD_DATA : Hostboot Data */ - "HBEL", /**< PNOR::HB_ERRLOGS : Hostboot Error log Repository */ - "DJVPD", /**< PNOR::DIMM_JEDEC_VPD : Dimm JEDEC VPD */ - "MVPD", /**< PNOR::MODULE_VPD : Module VPD */ - "CVPD", /**< PNOR::CENTAUR_VPD : Centaur VPD */ - "NVRAM", /**< PNOR::NVRAM : OPAL Storage */ - "OCC", /**< PNOR::OCC : OCC LID */ - "FIRDATA", /**< PNOR::FIRDATA : FIRDATA */ + "part", /**< PNOR::TOC : Table of Contents */ + "HBI", /**< PNOR::HB_EXT_CODE : Hostboot Extended Image */ + "GLOBAL", /**< PNOR::GLOBAL_DATA : Global Data */ + "HBB", /**< PNOR::HB_BASE_CODE : Hostboot Base Image */ + "SBEC", /**< PNOR::CENTAUR_SBE : Centaur Self-Boot Engine image */ + "SBE", /**< PNOR::SBE_IPL : Self-Boot Enginer IPL image */ + "WINK", /**< PNOR::WINK : Sleep Winkle Reference image */ + "PAYLOAD", /**< PNOR::PAYLOAD : HAL/OPAL */ + "HBRT", /**< PNOR::HB_RUNTIME : Hostboot Runtime (for Sapphire) */ + "HBD", /**< PNOR::HB_DATA : Hostboot Data */ + "GUARD", /**< PNOR::GUARD_DATA : Hostboot Data */ + "HBEL", /**< PNOR::HB_ERRLOGS : Hostboot Error log Repository */ + "DJVPD", /**< PNOR::DIMM_JEDEC_VPD : Dimm JEDEC VPD */ + "MVPD", /**< PNOR::MODULE_VPD : Module VPD */ + "CVPD", /**< PNOR::CENTAUR_VPD : Centaur VPD */ + "NVRAM", /**< PNOR::NVRAM : OPAL Storage */ + "OCC", /**< PNOR::OCC : OCC LID */ + "FIRDATA", /**< PNOR::FIRDATA : FIRDATA */ "ATTR_TMP", /**< PNOR::ATTR_TMP : Temporary Attribute Overrides */ "ATTR_PERM", /**< PNOR::ATTR_PERM : Permanent Attribute Overrides */ - "CAPP", /**< PNOR::CAPP : CAPP LID */ - "TEST", /**< PNOR::TEST : Test space for PNOR*/ + "CAPP", /**< PNOR::CAPP : CAPP LID */ + "TEST", /**< PNOR::TEST : Test space for PNOR*/ + "TESTRO", /**< PNOR::TESTRO : ReadOnly Test space for PNOR */ //Not currently used // "XXX", /**< NUM_SECTIONS : Used as invalid entry */ }; @@ -89,7 +91,7 @@ uint32_t PNOR::pnor_ffs_checksum(void* data, size_t size) } errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, - uint32_t & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr) + TOCS & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr) { TRACUCOMP(g_trac_pnor,"PNOR::parseTOC>"); errlHndl_t l_errhdl = NULL; @@ -97,9 +99,10 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, bool TOC_0_failed = false; do{ - o_TOC_used = 0; + o_TOC_used = TOC_0; - for (uint32_t cur_TOC = 0; cur_TOC < NUM_TOCS; ++cur_TOC) + for (TOCS cur_TOC = TOC_0; cur_TOC < NUM_TOCS; + cur_TOC = (TOCS)(cur_TOC+1)) { TRACFCOMP(g_trac_pnor, "PNOR::parseTOC verifying TOC: %d",cur_TOC); uint64_t nextVAddr = i_baseVAddr; @@ -134,10 +137,10 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, { TRACFCOMP(g_trac_pnor, "PNOR::parseTOC TOC 0 failed header checksum"); TOC_0_failed = true; - o_TOC_used = 1; + o_TOC_used = TOC_1; continue; } - else if (cur_TOC == 1 && TOC_0_failed) + else if (cur_TOC == TOC_1 && TOC_0_failed) { // Both TOC's failed TRACFCOMP(g_trac_pnor, "PNOR::parseTOC both TOCs are corrupted"); @@ -164,7 +167,7 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, } // Only check header if on first TOC or the first TOC failed - if (cur_TOC == 0 || TOC_0_failed) + if (cur_TOC == TOC_0 || TOC_0_failed) { TRACFCOMP(g_trac_pnor, "PNOR::parseTOC: FFS Block size=0x%.8X," " Partition Table Size = 0x%.8x, entry_count=%d", @@ -270,15 +273,15 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, // in SP-less config TRACFCOMP(g_trac_pnor, "PNOR::parseTOC pnor_ffs_checksum" " entry checksums do not match"); - if (cur_TOC == 0) + if (cur_TOC == TOC_0) { TRACFCOMP(g_trac_pnor,"PNOR::parseTOC TOC 0 entry" " checksum failed"); TOC_0_failed = true; - o_TOC_used = 1; + o_TOC_used = TOC_1; break; } - else if (cur_TOC == 1 && TOC_0_failed) + else if (cur_TOC == TOC_1 && TOC_0_failed) { // Both TOC's failed TRACFCOMP(g_trac_pnor, "PNOR::parseTOC both TOC's are" @@ -306,7 +309,7 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, } // Only set data if on first TOC or the first TOC failed - if (cur_TOC == 0 || TOC_0_failed) + if (cur_TOC == TOC_0 || TOC_0_failed) { //Figure out section enum for(uint32_t eyeIndex=PNOR::TOC;eyeIndexPnorRP::readTOC: Failed to set block permissions to WRITABLE for section %s.", + cv_EYECATCHER[secId]); + /*@ + * @errortype + * @moduleid PNOR::MOD_PNORRP_READTOC + * @reasoncode PNOR::RC_WRITABLE_PERM_FAIL + * @userdata1 PNOR section id + * @userdata2 PNOR section vaddr + * @devdesc Could not set permissions of the + * given PNOR section to WRITABLE + * @custdesc A problem occurred while reading PNOR partition table + */ + l_errhdl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + PNOR::MOD_PNORRP_READTOC, + PNOR::RC_WRITABLE_PERM_FAIL, + secId, + o_TOC[secId].virtAddr, + true /*Add HB SW Callout*/); + l_errhdl->collectTrace(PNOR_COMP_NAME); + } + } + else + { + // Need to set permissions to R/W + int rc = mm_set_permission( + (void*)o_TOC[secId].virtAddr, + o_TOC[secId].size, + WRITABLE | WRITE_TRACKED); + if (rc) + { + TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC: Failed to set block permissions to WRITABLE/WRITE_TRACKED for section %s.", + cv_EYECATCHER[secId]); + /*@ + * @errortype + * @moduleid PNOR::MOD_PNORRP_READTOC + * @reasoncode PNOR::RC_WRITE_TRACKED_PERM_FAIL + * @userdata1 PNOR section id + * @userdata2 PNOR section vaddr + * @devdesc Could not set permissions of the + * given PNOR section to + * WRITABLE/WRITE_TRACKED + * @custdesc A problem occurred while reading + * PNOR partition table + */ + l_errhdl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + PNOR::MOD_PNORRP_READTOC, + PNOR::RC_WRITE_TRACKED_PERM_FAIL, + secId, + o_TOC[secId].virtAddr, + true /*Add HB SW Callout*/); + l_errhdl->collectTrace(PNOR_COMP_NAME); + } + } +#endif + if( l_errhdl ) + { + // If both toc0 and toc1 fail break and return the error + if ( (cur_TOC == TOC_1) && (TOC_0_failed) ) + { + TRACFCOMP(g_trac_pnor, "PNOR::parseTOC readFromDevice Failed on both TOCs"); + break; + } + + // Toc 1 has not been read yet or Toc 0 was read + // successfully + // Commit error and break to continue checking the next + // TOC + else + { + TRACFCOMP(g_trac_pnor, "PNOR::parseTOC readFromDevice Failed on TOC %d, commit error", + cur_TOC); + errlCommit(l_errhdl,PNOR_COMP_ID); + l_errhdl = NULL; + break; + } + } } - } + } // For TOC Entries if (l_errhdl) { - TRACFCOMP(g_trac_pnor, ERR_MRK"PNOR::parseTOC: error parsing"); break; } - - for(PNOR::SectionId tmpId = PNOR::FIRST_SECTION; - tmpId < PNOR::NUM_SECTIONS; - tmpId = (PNOR::SectionId) (tmpId + 1) ) - { - TRACFCOMP(g_trac_pnor, "%s: size=0x%.8X flash=0x%.8X " - "virt=0x%.16X", cv_EYECATCHER[tmpId], o_TOC[tmpId].size, - o_TOC[tmpId].flashAddr, o_TOC[tmpId].virtAddr ); - } + } // For TOC's + if (l_errhdl) + { + break; } } while(0); + for(PNOR::SectionId tmpId = PNOR::FIRST_SECTION; + tmpId < PNOR::NUM_SECTIONS; + tmpId = (PNOR::SectionId) (tmpId + 1) ) + { + TRACFCOMP(g_trac_pnor, "%s: size=0x%.8X flash=0x%.8X " + "virt=0x%.16X", cv_EYECATCHER[tmpId], o_TOC[tmpId].size, + o_TOC[tmpId].flashAddr, o_TOC[tmpId].virtAddr ); + } + TRACUCOMP(g_trac_pnor, "< PNOR::parseTOC" ); return l_errhdl; } diff --git a/src/usr/pnor/pnor_common.H b/src/usr/pnor/pnor_common.H index 3944e27fa..5eb893412 100644 --- a/src/usr/pnor/pnor_common.H +++ b/src/usr/pnor/pnor_common.H @@ -41,11 +41,22 @@ namespace PNOR { uint8_t misc; /**< Misc Flags */ } PACKED; + // Simple enum of TOC's per PNOR side + enum TOCS + { + TOC_0 = 0, + TOC_1 = 1, + NUM_TOCS, + }; + enum { - NUM_TOCS = 2, - TOC_0_OFFSET = 0, - TOC_1_OFFSET = 0x8000, + // @TODO RTC: 120061 - Determine TOC locations + // TOC offsets based on pnor layout + SIDE_A_TOC_0_OFFSET = 0, + SIDE_A_TOC_1_OFFSET = 0x8000, + SIDE_B_TOC_0_OFFSET = 0x2000000, + SIDE_B_TOC_1_OFFSET = 0x2008000, /** Real number of bytes required to read 1 logical page */ PAGESIZE_PLUS_ECC = ((PAGESIZE * 9)/8), // 8B data + 1B of ECC @@ -79,7 +90,7 @@ namespace PNOR { * @return Error */ errlHndl_t parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, - uint32_t & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr); + TOCS & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr); } #endif diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C index 299a063f4..aeaeb222a 100644 --- a/src/usr/pnor/pnorrp.C +++ b/src/usr/pnor/pnorrp.C @@ -44,6 +44,7 @@ #include #include #include +#include "pnor_common.H" extern trace_desc_t* g_trac_pnor; @@ -192,7 +193,9 @@ void* wait_for_message( void* unused ) * @brief Constructor */ PnorRP::PnorRP() -: iv_TOC_used(0) +: iv_activeTocOffsets(SIDE_A_TOC_0_OFFSET,SIDE_A_TOC_1_OFFSET) +,iv_altTocOffsets(SIDE_B_TOC_0_OFFSET,SIDE_B_TOC_1_OFFSET) +,iv_TOC_used(TOC_0) ,iv_msgQ(NULL) ,iv_startupRC(0) { @@ -231,12 +234,28 @@ void PnorRP::initDaemon() do { - // read the TOC in the PNOR to compute the sections - l_errhdl = readTOC(); - if( l_errhdl ) + // @TODO RTC: 120062 - Determine which side is Golden + // Default TOC offsets set to side A. If two side support is enabled, + // check which SEEPROM hostboot booted from +#ifdef CONFIG_TWO_SIDE_SUPPORT + TARGETING::Target* pnor_target = TARGETING:: + MASTER_PROCESSOR_CHIP_TARGET_SENTINEL; + // Get correct TOC + PNOR::sbeSeepromSide_t l_bootSide; + PNOR::getSbeBootSeeprom(pnor_target, l_bootSide); + if (l_bootSide == PNOR::SBE_SEEPROM1) { - break; + TRACFCOMP( g_trac_pnor, "PnorRP::initDaemon> Booting from Side B"); + iv_activeTocOffsets.first = SIDE_B_TOC_0_OFFSET; + iv_activeTocOffsets.second = SIDE_B_TOC_1_OFFSET; + iv_altTocOffsets.first = SIDE_A_TOC_0_OFFSET; + iv_altTocOffsets.second = SIDE_A_TOC_0_OFFSET; } + else + { + TRACFCOMP( g_trac_pnor, "PnorRP::initDaemon> Booting from Side A"); + } +#endif // create a message queue iv_msgQ = msg_q_create(); @@ -253,7 +272,7 @@ void PnorRP::initDaemon() * @userdata1 Requested Address * @userdata2 rc from mm_alloc_block * @devdesc PnorRP::initDaemon> Error from mm_alloc_block - * @custdesc A problem occurred while accessing the boot flash. + * @custdesc A problem occurred while accessing the boot flash. */ l_errhdl = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, @@ -270,9 +289,14 @@ void PnorRP::initDaemon() INITSERVICE::registerBlock(reinterpret_cast(BASE_VADDR), TOTAL_SIZE,PNOR_PRIORITY); - // Need to set permissions to R/W - rc = mm_set_permission((void*) BASE_VADDR,TOTAL_SIZE, - WRITABLE | WRITE_TRACKED); + // Read the TOC in the PNOR to compute the sections and set their + // correct permissions + l_errhdl = readTOC(); + if( l_errhdl ) + { + TRACFCOMP(g_trac_pnor, ERR_MRK"PnorRP::initDaemon: Failed to readTOC"); + break; + } // start task to wait on the queue task_create( wait_for_message, NULL ); @@ -319,7 +343,7 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section, * @userdata1 Requested Section * @userdata2 Startup RC * @devdesc PnorRP::getSectionInfo> RP not properly initialized - * @custdesc A problem occurred while accessing the boot flash. + * @custdesc A problem occurred while accessing the boot flash. */ l_errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_PNORRP_GETSECTIONINFO, @@ -346,7 +370,7 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section, * @userdata1 Requested Section * @userdata2 TOC used * @devdesc PnorRP::getSectionInfo> Invalid Address for read/write - * @custdesc A problem occurred while accessing the boot flash. + * @custdesc A problem occurred while accessing the boot flash. */ l_errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_PNORRP_GETSECTIONINFO, @@ -378,12 +402,13 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section, != 0) ? true : false; o_info.sha512perEC = ((iv_TOC[id].version & FFS_VERS_SHA512_PER_EC) != 0) ? true : false; + o_info.readOnly = ((iv_TOC[id].misc & FFS_MISC_READ_ONLY) + != 0) ? true : false; } return l_errhdl; } - /** * @brief Read the TOC and store section information */ @@ -395,7 +420,7 @@ errlHndl_t PnorRP::readTOC() uint8_t* toc1Buffer = new uint8_t[PAGESIZE]; uint64_t fatal_error = 0; do { - l_errhdl = readFromDevice( TOC_0_OFFSET, 0, false, + l_errhdl = readFromDevice( iv_activeTocOffsets.first, 0, false, toc0Buffer, fatal_error ); if (l_errhdl) { @@ -403,7 +428,7 @@ errlHndl_t PnorRP::readTOC() break; } - l_errhdl = readFromDevice( TOC_1_OFFSET, 0, false, + l_errhdl = readFromDevice( iv_activeTocOffsets.second, 0, false, toc1Buffer, fatal_error ); if (l_errhdl) { @@ -412,7 +437,7 @@ errlHndl_t PnorRP::readTOC() } l_errhdl = PNOR::parseTOC(toc0Buffer, toc1Buffer, iv_TOC_used, iv_TOC, - BASE_VADDR); + BASE_VADDR); if (l_errhdl) { TRACFCOMP(g_trac_pnor, "readTOC: parseTOC failed"); @@ -737,59 +762,63 @@ errlHndl_t PnorRP::computeDeviceAddr( void* i_vaddr, o_chip = 99; uint64_t l_vaddr = (uint64_t)i_vaddr; - // make sure this is one of our addresses - if( !((l_vaddr >= BASE_VADDR) - && (l_vaddr < LAST_VADDR)) ) + do { - TRACFCOMP( g_trac_pnor, "PnorRP::computeDeviceAddr> Virtual Address outside known PNOR range : i_vaddr=%p", i_vaddr ); - /*@ - * @errortype - * @moduleid PNOR::MOD_PNORRP_WAITFORMESSAGE - * @reasoncode PNOR::RC_INVALID_ADDRESS - * @userdata1 Virtual Address - * @userdata2 Base PNOR Address - * @devdesc PnorRP::computeDeviceAddr> Virtual Address outside - * known PNOR range - * @custdesc A problem occurred while accessing the boot flash. - */ - l_errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - PNOR::MOD_PNORRP_COMPUTEDEVICEADDR, - PNOR::RC_INVALID_ADDRESS, - l_vaddr, - BASE_VADDR, - true /*Add HB SW Callout*/); - l_errhdl->collectTrace(PNOR_COMP_NAME); - return l_errhdl; - } + // make sure this is one of our addresses + if( !((l_vaddr >= BASE_VADDR) + && (l_vaddr < LAST_VADDR)) ) + { + TRACFCOMP( g_trac_pnor, "PnorRP::computeDeviceAddr> Virtual Address outside known PNOR range : i_vaddr=%p", i_vaddr ); + /*@ + * @errortype + * @moduleid PNOR::MOD_PNORRP_WAITFORMESSAGE + * @reasoncode PNOR::RC_INVALID_ADDRESS + * @userdata1 Virtual Address + * @userdata2 Base PNOR Address + * @devdesc PnorRP::computeDeviceAddr> Virtual Address outside + * known PNOR range + * @custdesc A problem occurred while accessing the boot flash. + */ + l_errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + PNOR::MOD_PNORRP_COMPUTEDEVICEADDR, + PNOR::RC_INVALID_ADDRESS, + l_vaddr, + BASE_VADDR, + true /*Add HB SW Callout*/); + l_errhdl->collectTrace(PNOR_COMP_NAME); + break; + } - // find the matching section - PNOR::SectionId id = PNOR::INVALID_SECTION; - l_errhdl = computeSection( l_vaddr, id ); - if( l_errhdl ) - { - return l_errhdl; - } + // find the matching section + PNOR::SectionId id = PNOR::INVALID_SECTION; + l_errhdl = computeSection( l_vaddr, id ); + if( l_errhdl ) + { + TRACFCOMP( g_trac_pnor, "PnorRP::computeDeviceAddr> Virtual address does not match any pnor sections : i_vaddr=%p", i_vaddr ); + break; + } - // pull out the information we need to return from our global copy - o_chip = iv_TOC[id].chip; - o_ecc = (bool)(iv_TOC[id].integrity & FFS_INTEG_ECC_PROTECT); - o_offset = l_vaddr - iv_TOC[id].virtAddr; //offset into section + // pull out the information we need to return from our global copy + o_chip = iv_TOC[id].chip; + o_ecc = (bool)(iv_TOC[id].integrity & FFS_INTEG_ECC_PROTECT); + o_offset = l_vaddr - iv_TOC[id].virtAddr; //offset into section - // for ECC we need to figure out where the ECC-enhanced offset is - // before tacking on the offset to the section - if( o_ecc ) - { - o_offset = (o_offset * 9) / 8; - } - // add on the offset of the section itself - o_offset += iv_TOC[id].flashAddr; + // for ECC we need to figure out where the ECC-enhanced offset is + // before tacking on the offset to the section + if( o_ecc ) + { + o_offset = (o_offset * 9) / 8; + } + // add on the offset of the section itself + o_offset += iv_TOC[id].flashAddr; + } while(0); TRACUCOMP( g_trac_pnor, "< PnorRP::computeDeviceAddr: i_vaddr=%X, o_offset=0x%X, o_chip=%d", l_vaddr, o_offset, o_chip ); return l_errhdl; } /** - * @brief Static instance function for testcase only + * @brief Static instance function */ PnorRP& PnorRP::getInstance() { @@ -987,3 +1016,10 @@ errlHndl_t PnorRP::fixECC (PNOR::SectionId i_section) TRACFCOMP(g_trac_pnor, EXIT_MRK"PnorRP::fixECC"); return l_err; } + +uint64_t PnorRP::getTocOffset(TOCS i_toc) const +{ + // Can use a ternary operator because there are only 2 TOCs per side + return (i_toc == TOC_0) ? iv_activeTocOffsets.first : + iv_activeTocOffsets.second; +} diff --git a/src/usr/pnor/pnorrp.H b/src/usr/pnor/pnorrp.H index 3703afe8a..509cf1436 100644 --- a/src/usr/pnor/pnorrp.H +++ b/src/usr/pnor/pnorrp.H @@ -76,9 +76,18 @@ class PnorRP */ errlHndl_t fixECC(PNOR::SectionId i_section); + /** + * @brief Get TOC offset of specified TOC on active side + * + * @param[in] i_toc TOC offset desired on active side + * + * @return uint64_t TOC offset + */ + uint64_t getTocOffset(PNOR::TOCS i_toc) const; + protected: /** - * @brief Constructor + * @brief Constructor, default TOC offsets to side A */ PnorRP(); @@ -89,16 +98,23 @@ class PnorRP private: + + // TOC 0 and 1 offsets of both PNOR sides. The active PNOR side determined + // by the Seeprom the SBE booted from + std::pair iv_activeTocOffsets; + std::pair iv_altTocOffsets; + enum { BASE_VADDR = VMM_VADDR_PNOR_RP, /**< 2GB = 0x80000000*/ TOTAL_SIZE = 64*MEGABYTE, /**< Allocate 64 MB (0x4000000)*/ LAST_VADDR = BASE_VADDR + TOTAL_SIZE, /**< End of our VA range */ }; + /** * Which TOC (0 or 1) is used after verifying both. */ - uint32_t iv_TOC_used; + PNOR::TOCS iv_TOC_used; /** * Flash statistics @@ -138,7 +154,8 @@ class PnorRP /** * @brief Verify both TOC's and store section information from one of the - * verified TOC's + * verified TOC's. Additionally set each section permissions + * (e.g. readOnly) * * @return Error from device */ @@ -224,7 +241,6 @@ class PnorRP return false; }; - // allow local helper function to call private methods friend void* wait_for_message( void* unused ); @@ -237,7 +253,7 @@ class PnorRP friend errlHndl_t PNOR::validateAltMaster( void ); /** - * @brief Static instance function for testcase only + * @brief Static instance function */ static PnorRP& getInstance(); }; diff --git a/src/usr/pnor/pnorsbe.C b/src/usr/pnor/pnorsbe.C new file mode 100644 index 000000000..0b6117313 --- /dev/null +++ b/src/usr/pnor/pnorsbe.C @@ -0,0 +1,87 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/pnor/pnorsbe.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* [+] 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 pnorsbe.C + * + * @brief Implements PNOR::getSbeBootSeeprom(), which Determines which + * Seeprom was used to boot the SB + */ + +#include +#include +#include +#include +#include + +extern trace_desc_t* g_trac_pnor; + +namespace PNOR +{ + +//Used to read SBE Boot Side from processor +const uint64_t SBE_VITAL_REG_0x0005001C = 0x005001C; +const uint64_t SBE_BOOT_SELECT_MASK = 0x0080000000000000; + +errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target, + sbeSeepromSide_t& o_bootSide) +{ + TRACFCOMP( g_trac_pnor, ENTER_MRK"PNOR::getSbeBootSeeprom()" ); + + errlHndl_t err = NULL; + uint64_t scomData = 0x0; + + o_bootSide = SBE_SEEPROM0; + + do{ + + size_t op_size = sizeof(scomData); + err = deviceRead( i_target, + &scomData, + op_size, + DEVICE_SCOM_ADDRESS(SBE_VITAL_REG_0x0005001C) ); + if( err ) + { + TRACFCOMP( g_trac_pnor, ERR_MRK"PNOR::getSbeBootSeeprom() -Error " + "reading SBE VITAL REG (0x%.8X) from Target :" + "HUID=0x%.8X", + SBE_VITAL_REG_0x0005001C, + TARGETING::get_huid(i_target)); + break; + } + if(scomData & SBE_BOOT_SELECT_MASK) + { + o_bootSide = SBE_SEEPROM1; + } + + }while(0); + + TRACFCOMP( g_trac_pnor, + EXIT_MRK"PNOR::getSbeBootSeeprom(): o_bootSide=0x%X (reg=0x%X)", + o_bootSide, scomData ); + + return err; +} + +} // end namespace \ No newline at end of file diff --git a/src/usr/pnor/pnorvalid.C b/src/usr/pnor/pnorvalid.C index 1bc09a2fa..46204caac 100644 --- a/src/usr/pnor/pnorvalid.C +++ b/src/usr/pnor/pnorvalid.C @@ -102,7 +102,7 @@ errlHndl_t validateAltMaster( void ) // When reading PNOR TOC assume a single page and no ECC uint8_t* tocBuffer = new uint8_t[PAGESIZE]; size_t read_size = PAGESIZE; - const uint64_t toc0_offset = PNOR::TOC_0_OFFSET; + const uint64_t toc0_offset = PnorRP::getInstance().getTocOffset(TOC_0); do{ @@ -176,8 +176,7 @@ errlHndl_t validateAltMaster( void ) pnordd = new PnorDD(procList[i]); // Read Flash - l_err = pnordd->readFlash(tocBuffer, read_size, - PNOR::TOC_0_OFFSET); + l_err = pnordd->readFlash(tocBuffer, read_size, toc0_offset); if ( l_err ) { // Commit Error Log, but continue the test diff --git a/src/usr/pnor/runtime/rt_pnor.C b/src/usr/pnor/runtime/rt_pnor.C index c43160f44..c61aa1d2d 100644 --- a/src/usr/pnor/runtime/rt_pnor.C +++ b/src/usr/pnor/runtime/rt_pnor.C @@ -297,7 +297,7 @@ errlHndl_t RtPnor::flush( PNOR::SectionId i_section) } /*******Protected Methods**************/ RtPnor::RtPnor() -:iv_TOC_used(0) +:iv_TOC_used(PNOR::TOC_0) { errlHndl_t l_err = readTOC(); if (l_err) @@ -588,7 +588,10 @@ errlHndl_t RtPnor::readTOC () break; } - l_err = readFromDevice (l_procId, PNOR::TOC, PNOR::TOC_0_OFFSET, + // @TODO RTC:120733 + // RT code needs a way to get the active side tocs vs just defaulting + // to SIDE_A + l_err = readFromDevice (l_procId, PNOR::TOC, PNOR::SIDE_A_TOC_0_OFFSET, PAGESIZE,false,toc0Buffer); if (l_err) { @@ -596,7 +599,7 @@ errlHndl_t RtPnor::readTOC () " for TOC0"); break; } - l_err = readFromDevice (l_procId, PNOR::TOC, PNOR::TOC_1_OFFSET, + l_err = readFromDevice (l_procId, PNOR::TOC, PNOR::SIDE_A_TOC_1_OFFSET, PAGESIZE, false,toc1Buffer); if (l_err) { @@ -605,7 +608,7 @@ errlHndl_t RtPnor::readTOC () break; } - l_err = PNOR::parseTOC(toc0Buffer, toc1Buffer, iv_TOC_used, iv_TOC,0); + l_err = PNOR::parseTOC(toc0Buffer, toc1Buffer, iv_TOC_used, iv_TOC, 0); if (l_err) { TRACFCOMP(g_trac_pnor, "RtPnor::readTOC: parseTOC failed"); diff --git a/src/usr/pnor/runtime/rt_pnor.H b/src/usr/pnor/runtime/rt_pnor.H index 43041fc3f..f3a03a5ec 100644 --- a/src/usr/pnor/runtime/rt_pnor.H +++ b/src/usr/pnor/runtime/rt_pnor.H @@ -81,7 +81,7 @@ class RtPnor /** * Which TOC (0 or 1) is used after verifying both. */ - uint32_t iv_TOC_used; + PNOR::TOCS iv_TOC_used; /** * Cached copy of section data diff --git a/src/usr/pnor/test/pnorrptest.H b/src/usr/pnor/test/pnorrptest.H index 04ca72916..427227bf7 100644 --- a/src/usr/pnor/test/pnorrptest.H +++ b/src/usr/pnor/test/pnorrptest.H @@ -517,22 +517,30 @@ class PnorRpTest : public CxxTest::TestSuite uint8_t* corruptBuffer = new uint8_t[PAGESIZE]; // Corrupt both ffs header and first entry for each TOC - for (uint32_t cur_TOC = 0; cur_TOC < PNOR::NUM_TOCS; ++cur_TOC) + for (PNOR::TOCS cur_TOC = PNOR::TOC_0; cur_TOC < PNOR::NUM_TOCS; + cur_TOC = (PNOR::TOCS)(cur_TOC+1)) { - uint32_t TOC_used = cur_TOC; + PNOR::TOCS TOC_used = cur_TOC; if (cur_TOC == 0) { - offset = PNOR::TOC_0_OFFSET; + offset = PnorRP::getInstance().getTocOffset(PNOR::TOC_0); } else { - offset = PNOR::TOC_1_OFFSET; + offset = PnorRP::getInstance().getTocOffset(PNOR::TOC_1); } // Read cur_TOC header data - PnorRP::getInstance().readFromDevice( offset, 0, false, tocHeader, - fatal_error ); + PnorRP::getInstance().readFromDevice( offset, 0, false, + tocHeader, fatal_error ); + if (fatal_error) + { + TRACFCOMP(g_trac_pnor, "PnorRpTest::test_TOC> ERROR : Could not read TOC header data at offset 0x%X RC=%X", + offset, fatal_error); + TS_FAIL("PnorRpTest::test_TOC> ERROR : Could not read TOC header data at offset 0x%X RC=%X", + offset, fatal_error); + } // Corrupt cur_TOC header data memcpy(corruptBuffer, tocHeader, PAGESIZE); @@ -559,6 +567,13 @@ class PnorRpTest : public CxxTest::TestSuite PnorRP::getInstance().readFromDevice( offset + FFS_HDR_SIZE, 0, false, tocEntry, fatal_error ); + if (fatal_error) + { + TRACFCOMP(g_trac_pnor, "PnorRpTest::test_TOC> ERROR : Could not read first TOC entry data at offset 0x%X RC=%X", + offset, fatal_error); + TS_FAIL("PnorRpTest::test_TOC> ERROR : Could not read first TOC entry data at offset 0x%X RC=%X", + offset, fatal_error); + } // Corrupt cur_TOC header data memcpy(corruptBuffer, tocEntry, PAGESIZE); @@ -591,6 +606,83 @@ class PnorRpTest : public CxxTest::TestSuite TRACFCOMP(g_trac_pnor, "PnorRpTest::test_TOC End"); } + /** + * @brief PNOR RP test - ReadOnlyTag + * Tests if readOnly tag on a section is being processed correctly + * + */ + void test_ReadOnlyTag(void) + { + TRACFCOMP(g_trac_pnor, "PnorRpTest::test_ReadOnlyTag Start" ); + PNOR::SectionInfo_t l_info; + errlHndl_t l_errhdl = NULL; + uint64_t chip_select = 0xF; + bool needs_ecc = false; + + l_errhdl = PNOR::getSectionInfo(PNOR::TESTRO, l_info); + if( l_errhdl ) + { + TRACFCOMP(g_trac_pnor, "PnorRpTest::test_ReadOnlyTag> ERROR : getSectionInfo returned error for %d : RC=%X", + PNOR::TESTRO, l_errhdl->reasonCode()); + ERRORLOG::errlCommit(l_errhdl, PNOR_COMP_ID); + TS_FAIL( "PnorRpTest::test_ReadOnlyTag> ERROR : could not read pnor section %d", PNOR::TESTRO); + } + + // Write some data + const uint64_t l_writeData = 0x1122334455667788; + uint64_t* l_dataptr = reinterpret_cast (l_info.vaddr); + l_dataptr[0] = l_writeData; + + // Flush the page to make sure it gets out to the device + // Due to ReadOnly permissions set on TESTRO should be a no-op + int rc = mm_remove_pages( RELEASE, l_dataptr, PAGESIZE ); + if( rc ) + { + TRACFCOMP( g_trac_pnor, "PnorRpTest::test_ReadOnlyTag> ERROR : error on RELEASE : rc=%X", rc ); + TS_FAIL( "PnorRpTest::test_ReadOnlyTag> ERROR : error on RELEASE" ); + } + + // Get physical address of pnor section + uint64_t l_address = 0; + l_errhdl = PnorRP::getInstance().computeDeviceAddr((void*)l_info.vaddr, + l_address, + chip_select, + needs_ecc); + if(l_errhdl) + { + TRACFCOMP(g_trac_pnor, "PnorRpTest::test_ReadOnlyTag> ERROR : computeDeviceAddr vaddr = 0x%X",l_info.vaddr); + errlCommit(l_errhdl,PNOR_COMP_ID); + TS_FAIL( "PnorRpTest::test_ReadOnlyTag> ERROR : computeDeviceAddr vaddr = 0x%X",l_info.vaddr); + } + + // Read pnor section and check if write did not occur + uint64_t l_readData = 0; + size_t l_size = sizeof(uint64_t); + l_errhdl = deviceRead(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL, + &l_readData, + l_size, + DEVICE_PNOR_ADDRESS(0, l_address)); + TRACFCOMP(g_trac_pnor, "PnorRpTest::test_ReadOnlyTag> Read Data = 0x%X",l_readData); + if(l_errhdl) + { + TS_FAIL("PnorRpTest::test_ReadOnlyTag: deviceRead() failed! Error committed."); + ERRORLOG::errlCommit(l_errhdl, PNOR_COMP_ID); + } + if(l_readData == l_writeData) + { + TS_FAIL("PnorRpTest::test_ReadOnlyTag: Data was written to readOnly section = %s", + l_info.name); + } + if(l_size != sizeof(uint64_t)) + { + TS_FAIL("PnorRpTest::test_ReadOnlyTag: deviceRead() Read length not expected value. Addr: 0x%llx, Exp: %d, Act: %d", + l_address, sizeof(uint64_t), l_size); + } + + TRACFCOMP(g_trac_pnor, "PnorRpTest::test_ReadOnlyTag End"); + } + + //@todo - import config data from build and compare to section info /** diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C index 9dd9e0a6f..698d41a8c 100644 --- a/src/usr/sbe/sbe_update.C +++ b/src/usr/sbe/sbe_update.C @@ -1213,49 +1213,6 @@ namespace SBE return err; } -///////////////////////////////////////////////////////////////////// - errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target, - sbeSeepromSide_t& o_bootSide) - { - TRACUCOMP( g_trac_sbe, - ENTER_MRK"getSbeBootSeeprom()" ); - - errlHndl_t err = NULL; - uint64_t scomData = 0x0; - - o_bootSide = SBE_SEEPROM0; - - do{ - - size_t op_size = sizeof(scomData); - err = deviceRead( i_target, - &scomData, - op_size, - DEVICE_SCOM_ADDRESS(SBE_VITAL_REG_0x0005001C) ); - if( err ) - { - TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeBootSeeprom() -Error " - "reading SBE VITAL REG (0x%.8X) from Target :" - "HUID=0x%.8X", - SBE_VITAL_REG_0x0005001C, - TARGETING::get_huid(i_target)); - break; - } - if(scomData & SBE_BOOT_SELECT_MASK) - { - o_bootSide = SBE_SEEPROM1; - } - - }while(0); - - TRACUCOMP( g_trac_sbe, - EXIT_MRK"getSbeBootSeeprom(): o_bootSide=0x%X (reg=0x%X)", - o_bootSide, scomData ); - - return err; - } - - ///////////////////////////////////////////////////////////////////// errlHndl_t getSbeInfoState(sbeTargetState_t& io_sbeState) { @@ -1351,11 +1308,11 @@ namespace SBE if(SEEPROM_0_PERMANENT_VALUE == (io_sbeState.mvpdSbKeyword.flags & PERMANENT_FLAG_MASK)) { - io_sbeState.permanent_seeprom_side = SBE_SEEPROM0; + io_sbeState.permanent_seeprom_side = PNOR::SBE_SEEPROM0; } else // Side 1 must be permanent { - io_sbeState.permanent_seeprom_side = SBE_SEEPROM1; + io_sbeState.permanent_seeprom_side = PNOR::SBE_SEEPROM1; } @@ -1404,21 +1361,21 @@ namespace SBE /* 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); + PNOR::sbeSeepromSide_t tmp_cur_side = PNOR::SBE_SEEPROM_INVALID; + err = PNOR::getSbeBootSeeprom(io_sbeState.target, tmp_cur_side); if(err) { TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error returned from getSbeBootSeeprom()"); break; } io_sbeState.cur_seeprom_side = tmp_cur_side; - if (io_sbeState.cur_seeprom_side == SBE_SEEPROM0) + if (io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM0) { - io_sbeState.alt_seeprom_side = SBE_SEEPROM1; + io_sbeState.alt_seeprom_side = PNOR::SBE_SEEPROM1; } - else if ( io_sbeState.cur_seeprom_side == SBE_SEEPROM1) + else if ( io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM1) { - io_sbeState.alt_seeprom_side = SBE_SEEPROM0; + io_sbeState.alt_seeprom_side = PNOR::SBE_SEEPROM0; } else { @@ -2055,7 +2012,7 @@ namespace SBE /* Determine what side to update */ /**************************************************************/ // Set cur and alt isDirty values - if( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) + if( io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM0 ) { current_side_isDirty = seeprom_0_isDirty; alt_side_isDirty = seeprom_1_isDirty; @@ -2222,14 +2179,14 @@ namespace SBE io_sbeState.seeprom_side_to_update = EEPROM::SBE_PRIMARY; // Update MVPD PERMANENT flag: make cur=perm - ( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) ? + ( io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM0 ) ? // clear bit 0 io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK : //set bit 0 io_sbeState.mvpdSbKeyword.flags |= PERMANENT_FLAG_MASK; // Update MVPD RE-IPL SEEPROM flag: re-IPL on ALT: - ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) ? + ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ? // clear bit 1 io_sbeState.mvpdSbKeyword.flags &= ~REIPL_SEEPROM_MASK : //set bit 1 @@ -2295,18 +2252,18 @@ namespace SBE // Set Update side to alt io_sbeState.seeprom_side_to_update = - ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; // Update MVPD PERMANENT flag: make cur=perm - ( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) ? + ( io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM0 ) ? // clear bit 0 io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK : //set bit 0 io_sbeState.mvpdSbKeyword.flags |= PERMANENT_FLAG_MASK; // Update MVPD RE-IPL SEEPROM flag: re-IPL on ALT: - ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) ? + ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ? // clear bit 1 io_sbeState.mvpdSbKeyword.flags &= ~REIPL_SEEPROM_MASK : //set bit 1 @@ -2341,13 +2298,13 @@ namespace SBE // Set Update side to alt io_sbeState.seeprom_side_to_update = - ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; // MVPD flag Update // Update MVPD flag make cur=perm - ( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) ? + ( io_sbeState.cur_seeprom_side == PNOR::SBE_SEEPROM0 ) ? // clear bit 0 io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK : // set bit 0 @@ -2401,11 +2358,11 @@ namespace SBE // Set Update side to alt io_sbeState.seeprom_side_to_update = - ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; // Update MVPD RE-IPL SEEPROM flag: re-IPL on ALT: - ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) ? + ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ? // clear bit 1 io_sbeState.mvpdSbKeyword.flags &= ~REIPL_SEEPROM_MASK : // set bit 1 @@ -2416,7 +2373,7 @@ namespace SBE if ( g_istep_mode ) { // Update MVPD PERMANENT flag: make alt=perm - (io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) ? + (io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ? // clear bit 0 io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK : //set bit 0 @@ -2498,11 +2455,11 @@ namespace SBE // Set Update side to alt io_sbeState.seeprom_side_to_update = - ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; // Update MVPD RE-IPL SEEPROM flag: re-IPL on ALT: - ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) ? + ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ? // clear bit 1 io_sbeState.mvpdSbKeyword.flags &= ~REIPL_SEEPROM_MASK : // set bit 1 @@ -2534,7 +2491,7 @@ namespace SBE // Set Update side to alt io_sbeState.seeprom_side_to_update = - ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ( io_sbeState.alt_seeprom_side == PNOR::SBE_SEEPROM0 ) ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; TRACFCOMP( g_trac_sbe, INFO_MRK"SBE Update tgt=0x%X: " @@ -3244,12 +3201,12 @@ namespace SBE // Compare against 'current' Master side in case there is // an issue with the other side - if (io_sbeStates_v[i].cur_seeprom_side == SBE_SEEPROM0) + if (io_sbeStates_v[i].cur_seeprom_side == PNOR::SBE_SEEPROM0) { ver_ptr = &(io_sbeStates_v[i].seeprom_0_ver.image_version); } - else // SBE_SEEPROM1 + else // PNOR::SBE_SEEPROM1 { ver_ptr = &(io_sbeStates_v[i].seeprom_1_ver.image_version); @@ -3389,12 +3346,12 @@ namespace SBE else { // Not Master, so get 'current' version - if (io_sbeStates_v[i].cur_seeprom_side == SBE_SEEPROM0) + if (io_sbeStates_v[i].cur_seeprom_side == PNOR::SBE_SEEPROM0) { ver_ptr = &(io_sbeStates_v[i].seeprom_0_ver.image_version); } - else // SBE_SEEPROM1 + else // PNOR::SBE_SEEPROM1 { ver_ptr = &(io_sbeStates_v[i].seeprom_1_ver.image_version); diff --git a/src/usr/sbe/sbe_update.H b/src/usr/sbe/sbe_update.H index aa880b2d4..e49c58289 100644 --- a/src/usr/sbe/sbe_update.H +++ b/src/usr/sbe/sbe_update.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ +/* [+] 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. */ @@ -53,10 +55,6 @@ namespace SBE const uint64_t SBE_IMAGE_SEEPROM_ADDRESS = 0x400; // 1KB const uint64_t SBE_VERSION_SEEPROM_ADDRESS = 0x300; // 1KB - 256B - //Used to read SBE Boot Side from processor - const uint64_t SBE_VITAL_REG_0x0005001C = 0x005001C; - const uint64_t SBE_BOOT_SELECT_MASK = 0x0080000000000000; - // PNOR SBE and SBEC Partition constants const uint32_t MAX_SBE_ENTRIES = 9; const uint32_t SBETOC_EYECATCH = 0x53424500; //'SBE\0' @@ -106,14 +104,6 @@ namespace SBE MVPDOP_WRITE, // Write version data to MVPD }; - // Used to keep track of perm/temp, and cur/alt - enum sbeSeepromSide_t - { - SBE_SEEPROM0 = 0x00, // corresponds to EEPROM::SBE_PRIMARY - SBE_SEEPROM1 = 0x01, // corresponts to EEPROM::SBE_BACKUP - SBE_SEEPROM_INVALID = 0xFF, - }; - // Actions can be combined enum sbeUpdateActions_t { @@ -127,7 +117,6 @@ namespace SBE UNSUPPORTED_SITUATION = 0x80000000, }; - /******************************************/ /* Structs */ /******************************************/ @@ -207,9 +196,9 @@ namespace SBE bool seeprom_0_ver_ECC_fail; bool seeprom_1_ver_ECC_fail; - sbeSeepromSide_t cur_seeprom_side; // aka 'booted' side - sbeSeepromSide_t alt_seeprom_side; - sbeSeepromSide_t permanent_seeprom_side; + PNOR::sbeSeepromSide_t cur_seeprom_side; // aka 'booted' side + PNOR::sbeSeepromSide_t alt_seeprom_side; + PNOR::sbeSeepromSide_t permanent_seeprom_side; // Customized Image Information for this Target size_t customizedImage_size; @@ -329,21 +318,6 @@ namespace SBE void* io_imgPtr, size_t& o_actImgSize); - - /** - * @brief Determines which Seeprom was used to boot the SBE - * - * @param[in] i_target Target processor to customize - * - * @param[out] o_bootSide The Seeprom the SBE booted from - * - * @return errlHndl_t Error log handle on failure. - */ - - errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target, - sbeSeepromSide_t& o_bootSide); - - /** * @brief Collects Version information from a specific SEEPROM * diff --git a/src/usr/sbe/test/sbeupdatetest.H b/src/usr/sbe/test/sbeupdatetest.H index d2351418b..5e2570631 100644 --- a/src/usr/sbe/test/sbeupdatetest.H +++ b/src/usr/sbe/test/sbeupdatetest.H @@ -580,7 +580,7 @@ class SBEUpdateTest: public CxxTest::TestSuite { // Inputs uint8_t i_situation; - sbeSeepromSide_t i_cur; // current_seeprom_side + PNOR::sbeSeepromSide_t i_cur; // current_seeprom_side uint8_t i_flags; // mvpdSbKeyword.flags // Expected Output @@ -596,7 +596,7 @@ class SBEUpdateTest: public CxxTest::TestSuite // - update alt=1 // - make cur=perm // - re-IPL - { 0xE0, SBE_SEEPROM0, 0x80, + { 0xE0, PNOR::SBE_SEEPROM0, 0x80, static_cast (DO_UPDATE|IPL_RESTART|UPDATE_MVPD|UPDATE_SBE), EEPROM::SBE_BACKUP, 0x40 }, @@ -606,7 +606,7 @@ class SBEUpdateTest: public CxxTest::TestSuite // - update alt=0 // - make cur=perm // - re-IPL - { 0xC0, SBE_SEEPROM1, 0x00, + { 0xC0, PNOR::SBE_SEEPROM1, 0x00, static_cast (DO_UPDATE|IPL_RESTART|UPDATE_MVPD|UPDATE_SBE), EEPROM::SBE_PRIMARY, 0x80 }, @@ -616,7 +616,7 @@ class SBEUpdateTest: public CxxTest::TestSuite // - update alt=0 // - make cur=perm // - Continue IPL - { 0xA0, SBE_SEEPROM1, 0x00, + { 0xA0, PNOR::SBE_SEEPROM1, 0x00, static_cast (DO_UPDATE|UPDATE_MVPD|UPDATE_SBE), EEPROM::SBE_PRIMARY, 0x80 }, @@ -625,7 +625,7 @@ class SBEUpdateTest: public CxxTest::TestSuite // Arbitrarily set cur side to 1 (therefore perm set to 0) // - No updates // - Continue IPL - { 0x80, SBE_SEEPROM1, 0x00, + { 0x80, PNOR::SBE_SEEPROM1, 0x00, static_cast(CLEAR_ACTIONS), EEPROM::LAST_CHIP_TYPE, 0x00 }, @@ -633,7 +633,7 @@ class SBEUpdateTest: public CxxTest::TestSuite // Arbitrarily set cur side to 0 (therefore perm set to 0) // - update alt=1 // - re-IPL - { 0x60, SBE_SEEPROM0, 0x00, + { 0x60, PNOR::SBE_SEEPROM0, 0x00, static_cast (DO_UPDATE|IPL_RESTART|UPDATE_MVPD|UPDATE_SBE), EEPROM::SBE_BACKUP, 0x40 }, @@ -644,14 +644,14 @@ class SBEUpdateTest: public CxxTest::TestSuite // Arbitrarily set cur side to 1 (therefore perm set to 1) // - update alt=0 // - re-IPL - { 0x40, SBE_SEEPROM1, 0x80, + { 0x40, PNOR::SBE_SEEPROM1, 0x80, static_cast (DO_UPDATE|IPL_RESTART|UPDATE_MVPD|UPDATE_SBE), EEPROM::SBE_PRIMARY, 0x80 }, // Repeat previous case to make sure global variables are used // correctly to save MBOX value - { 0x40, SBE_SEEPROM1, 0x80, + { 0x40, PNOR::SBE_SEEPROM1, 0x80, static_cast (DO_UPDATE|IPL_RESTART|UPDATE_MVPD|UPDATE_SBE), EEPROM::SBE_PRIMARY, 0x80 }, @@ -660,7 +660,7 @@ class SBEUpdateTest: public CxxTest::TestSuite // Arbitrarily set cur side to 0 (therefore perm set to 0) // - update alt=1 // - Continue IPL - { 0x20, SBE_SEEPROM0, 0x00, + { 0x20, PNOR::SBE_SEEPROM0, 0x00, static_cast(DO_UPDATE|UPDATE_SBE), EEPROM::SBE_BACKUP, 0x00 }, @@ -670,7 +670,7 @@ class SBEUpdateTest: public CxxTest::TestSuite // - Continue IPL // NOTE: this will test that right-most-bit is ignored: // so techincally case 0x01, which should be = case 0x00 - { 0x01, SBE_SEEPROM0, 0x00, + { 0x01, PNOR::SBE_SEEPROM0, 0x00, static_cast(CLEAR_ACTIONS), EEPROM::LAST_CHIP_TYPE, 0x00 }, #endif // SBE_UPDATE_SEQUENTIAL @@ -708,8 +708,8 @@ class SBEUpdateTest: public CxxTest::TestSuite sbeState.cur_seeprom_side = testData[i].i_cur; sbeState.alt_seeprom_side = - ( ( testData[i].i_cur == SBE_SEEPROM0 ) - ? SBE_SEEPROM1 : SBE_SEEPROM0 ); + ( ( testData[i].i_cur == PNOR::SBE_SEEPROM0 ) + ? PNOR::SBE_SEEPROM1 : PNOR::SBE_SEEPROM0 ); sbeState.mvpdSbKeyword.flags = testData[i].i_flags; -- cgit v1.2.1