diff options
-rw-r--r-- | src/include/usr/pnor/pnor_reasoncodes.H | 10 | ||||
-rw-r--r-- | src/include/usr/pnor/pnorif.H | 49 | ||||
-rw-r--r-- | src/usr/hwas/hwasPlatDeconfigGard.C | 32 | ||||
-rw-r--r-- | src/usr/pnor/pnor_common.C | 7 | ||||
-rw-r--r-- | src/usr/pnor/pnor_common.H | 4 | ||||
-rw-r--r-- | src/usr/pnor/pnorrp.C | 204 | ||||
-rw-r--r-- | src/usr/pnor/pnorrp.H | 38 |
7 files changed, 292 insertions, 52 deletions
diff --git a/src/include/usr/pnor/pnor_reasoncodes.H b/src/include/usr/pnor/pnor_reasoncodes.H index 823f439e8..148f916f2 100644 --- a/src/include/usr/pnor/pnor_reasoncodes.H +++ b/src/include/usr/pnor/pnor_reasoncodes.H @@ -43,8 +43,10 @@ namespace PNOR MOD_PNORRP_WRITETODEVICE = 0x08, /**< PnorRP::writeToDevice */ MOD_PNORRP_DIDSTARTUPFAIL = 0x09, /**< didStartupFail(rc) */ MOD_PNORRP_FLUSH = 0x0A, /**< mm_remove_pages */ - MOD_PNORRP_FIXECC = 0x0B, /**< fixECC */ - MOD_PNORRP_FINDTOC = 0x0C, /**< findTOC */ + MOD_PNORRP_FIXECC = 0x0B, /**< PnorRP::fixECC */ + MOD_PNORRP_FINDTOC = 0x0C, /**< PnorRP::findTOC */ + MOD_PNORRP_GETSIDEINFO = 0x0D, /**< PnorRP::getSideInfo */ + MOD_PNORRP_SETSIDEINFO = 0x0E, /**< PnorRP::setSideInfo */ // pnorvalid.C MOD_PNORVALID_MAIN = 0x0E, /**< validateAltMaster */ @@ -145,6 +147,10 @@ namespace PNOR RC_PARTITION_TABLE_CORRUPTED = PNOR_COMP_ID | 0x25, //termination_rc RC_FINDTOC_FAILED = PNOR_COMP_ID | 0x26, + RC_INVALID_PNOR_SIDE = PNOR_COMP_ID | 0x27, + //termination_rc + RC_INVALID_WORKING_TOC = PNOR_COMP_ID | 0x28, + RC_INVALID_TOC = PNOR_COMP_ID | 0x29, }; enum UserDetailsTypes diff --git a/src/include/usr/pnor/pnorif.H b/src/include/usr/pnor/pnorif.H index 722946628..e12ccf122 100644 --- a/src/include/usr/pnor/pnorif.H +++ b/src/include/usr/pnor/pnorif.H @@ -30,6 +30,7 @@ #include <builtins.h> #include <errl/errlentry.H> #include <utility> +#include <config.h> namespace PNOR { @@ -90,6 +91,46 @@ struct SectionInfo_t }; /** + * PNOR Sides + */ +enum SideId +{ + WORKING = 0, +#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT + ALTERNATE = 1, +#endif + NUM_SIDES, + INVALID_SIDE = NUM_SIDES, + FIRST_SIDE = WORKING, +}; + +/** + * Information about a side of PNOR + */ +struct SideInfo_t +{ + SideId id; /**< Side ID */ + char side; /**< name of the side either A or B */ + bool isGolden; /**< True if side is golden */ + bool isGuardPresent; /**< True if guard section is present */ + bool hasOtherSide; /**< True if a valid alternate side exists*/ + uint64_t primaryTOC; /**< Address of the primary TOC */ + uint64_t backupTOC; /**< Address of the backup TOC */ + uint64_t hbbAddress; /**< HBB Address associated with this side */ + uint64_t hbbMmioOffset; /**< HBB MMIO Offset associated with hbbAddress*/ +}; + +/** + * @brief Returns information about a given side of pnor + * + * @param[in] i_side PNOR side + * @param[out] o_info side information + * + * @return errlHndl_t Error log if request was invalid + */ +errlHndl_t getSideInfo (SideId i_side, SideInfo_t& o_info); + +/** * @brief Return the size and address of a given section of PNOR data * * @param[in] i_section PNOR section @@ -144,14 +185,6 @@ errlHndl_t clearSection(PNOR::SectionId i_section); */ errlHndl_t validateAltMaster( void ); -//@ TODO RTC: 120061 add golden info -//@ TODO RTC: 109703 make golden changes for informing OPAL -struct TocInfo_t -{ - std::pair<uint64_t, uint64_t> activeTocOffsets; - std::pair<uint64_t, uint64_t> altTocOffsets; -}; - /** @brief PNOR::TEST section offsets for test cases to prevent * concurrency problems */ diff --git a/src/usr/hwas/hwasPlatDeconfigGard.C b/src/usr/hwas/hwasPlatDeconfigGard.C index 52eb1b04c..452a9e7aa 100644 --- a/src/usr/hwas/hwasPlatDeconfigGard.C +++ b/src/usr/hwas/hwasPlatDeconfigGard.C @@ -270,7 +270,7 @@ errlHndl_t DeconfigGard::platCreateGardRecord( } l_pErr = _GardRecordIdSetup(iv_platDeconfigGard); - if (l_pErr && iv_platDeconfigGard) + if (l_pErr || !iv_platDeconfigGard) { break; } @@ -490,16 +490,26 @@ errlHndl_t getGardSectionInfo(PNOR::SectionInfo_t& o_sectionInfo) 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_PNOR_TWO_SIDE_SUPPORT - HWAS_INF("getGardSectionInfo: No guard section disabling guard support"); - delete l_errl; - l_errl = NULL; -#else - HWAS_ERR("getGardSectionInfo:getSectionInfo failed"); -#endif + + PNOR::SideInfo_t l_sideInfo; + errlHndl_t l_tempErr = PNOR::getSideInfo(PNOR::WORKING,l_sideInfo); + if (l_tempErr) + { + HWAS_ERR("getGardSectionInfo: getSideInfo failed"); + errlCommit (l_errl,HWAS_COMP_ID); + l_errl = l_tempErr; + } + if (!l_sideInfo.isGuardPresent) + { + HWAS_INF("getGardSectionInfo: No guard section disabling guard" + " support"); + delete l_errl; + l_errl = NULL; + } + else + { + HWAS_ERR("getGardSectionInfo:getSectionInfo failed"); + } } else { diff --git a/src/usr/pnor/pnor_common.C b/src/usr/pnor/pnor_common.C index 6844984e5..c14e41b6c 100644 --- a/src/usr/pnor/pnor_common.C +++ b/src/usr/pnor/pnor_common.C @@ -148,8 +148,11 @@ errlHndl_t PNOR::mmioToPhysicalOffset(uint64_t& o_hbbAddress) void PNOR::physicalToMmioOffset(uint64_t i_hbbAddress, uint64_t& o_mmioOffset) { - o_mmioOffset = (PNOR::LPC_SFC_MMIO_OFFSET + i_hbbAddress + - ((PNOR::PNOR_SIZE - i_hbbAddress)/9)) & 0xFFFFFFF; + //Left shifting 32-bits because SCOMS store a 64-bit value + //and HBB Offset is stored in the higher 32-bits + o_mmioOffset = ((PNOR::LPC_SFC_MMIO_OFFSET + i_hbbAddress + + ((PNOR::PNOR_SIZE - i_hbbAddress)/9)) | + PNOR::LPC_FW_SPACE) << 32; } /* diff --git a/src/usr/pnor/pnor_common.H b/src/usr/pnor/pnor_common.H index b1106237a..dd7ab2ea1 100644 --- a/src/usr/pnor/pnor_common.H +++ b/src/usr/pnor/pnor_common.H @@ -131,6 +131,10 @@ namespace PNOR { // for the SBE to work so we can rely on that same assertion /**< Offset to direct read space, from FW base */ LPC_SFC_MMIO_OFFSET = LPC_TOP_OF_FLASH_OFFSET-PNOR_SIZE+1, + + //@TODO: RTC:124503 - delete the following line and call the LPC + //interface instead + LPC_FW_SPACE = 0xF0000000, }; } diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C index aad312b38..8c8f9a407 100644 --- a/src/usr/pnor/pnorrp.C +++ b/src/usr/pnor/pnorrp.C @@ -45,6 +45,7 @@ #include <util/align.H> #include <config.h> #include "pnor_common.H" +#include <hwas/common/hwasCallout.H> extern trace_desc_t* g_trac_pnor; @@ -70,6 +71,15 @@ TASK_ENTRY_MACRO( PnorRP::init ); ********************/ /** + * @brief Returns information about a given side of PNOR + */ +errlHndl_t PNOR::getSideInfo( PNOR::SideId i_side, + PNOR::SideInfo_t& o_info) +{ + return Singleton<PnorRP>::instance().getSideInfo(i_side,o_info); +} + +/** * @brief Return the size and address of a given section of PNOR data */ errlHndl_t PNOR::getSectionInfo( PNOR::SectionId i_section, @@ -280,6 +290,12 @@ void PnorRP::initDaemon() TRACFCOMP(g_trac_pnor, ERR_MRK"PnorRP::initDaemon: Failed to readTOC"); break; } + l_errhdl = PnorRP::setSideInfo (); + if(l_errhdl) + { + TRACFCOMP(g_trac_pnor, "PnorRP::initDaemon> setSideInfo failed"); + break; + } // start task to wait on the queue task_create( wait_for_message, NULL ); @@ -301,6 +317,39 @@ void PnorRP::initDaemon() TRACUCOMP(g_trac_pnor, "< PnorRP::initDaemon" ); } +errlHndl_t PnorRP::getSideInfo( PNOR::SideId i_side, + PNOR::SideInfo_t& o_info) +{ + errlHndl_t l_err = NULL; + do + { + //check to make sure side id is valid + if (i_side != PNOR::INVALID_SIDE) + { + memcpy (&o_info, &iv_side[i_side], sizeof(SideInfo_t)); + } + else + { + TRACFCOMP(g_trac_pnor, "Side:%d is currently not supported", + (int)i_side); + /*@ + * @errortype + * @moduleid PNOR::MOD_PNORRP_GETSIDEINFO + * @reasoncode PNOR::RC_INVALID_PNOR_SIDE + * @userdata1 Requested SIDE + * @userdata2 0 + * @devdesc PnorRP::getSideInfo> Side not supported + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + PNOR::MOD_PNORRP_GETSIDEINFO, + PNOR::RC_INVALID_PNOR_SIDE, + TO_UINT64(i_side), + 0,true); + break; + } + } while (0); + return l_err; +} /** * @brief Return the size and address of a given section of PNOR data @@ -591,17 +640,17 @@ errlHndl_t PnorRP::findTOC() if (l_isActiveTOC) { - iv_activeTocOffsets.first = l_toc; - iv_activeTocOffsets.second = l_backupTOC; - iv_altTocOffsets.first = l_otherPrimaryTOC; - iv_altTocOffsets.second = l_otherBackupTOC; + iv_TocOffset[WORKING].first = l_toc; + iv_TocOffset[WORKING].second = l_backupTOC; + iv_TocOffset[ALTERNATE].first = l_otherPrimaryTOC; + iv_TocOffset[ALTERNATE].second = l_otherBackupTOC; } else if (l_isOtherActiveTOC) { - iv_activeTocOffsets.first = l_otherPrimaryTOC; - iv_activeTocOffsets.second = l_otherBackupTOC; - iv_altTocOffsets.first = l_toc; - iv_altTocOffsets.second = l_backupTOC; + iv_TocOffset[WORKING].first = l_otherPrimaryTOC; + iv_TocOffset[WORKING].second = l_otherBackupTOC; + iv_TocOffset[ALTERNATE].first = l_toc; + iv_TocOffset[ALTERNATE].second = l_backupTOC; } else { @@ -611,16 +660,17 @@ errlHndl_t PnorRP::findTOC() INITSERVICE::doShutdown(PNOR::RC_PARTITION_TABLE_CORRUPTED); } TRACFCOMP(g_trac_pnor,"findTOC>activePrimary:0x%X,activeBackup:0x%X" - "altPrimary:0x%X, altBackup:0x%X",iv_activeTocOffsets.first, - iv_activeTocOffsets.second, iv_altTocOffsets.first, - iv_altTocOffsets.second); + "altPrimary:0x%X, altBackup:0x%X",iv_TocOffset[WORKING].first, + iv_TocOffset[WORKING].second, iv_TocOffset[ALTERNATE].first, + iv_TocOffset[ALTERNATE].second); #else if (l_isActiveTOC) { - iv_activeTocOffsets.first = l_toc; - iv_activeTocOffsets.second = l_backupTOC; - TRACFCOMP(g_trac_pnor, "findTOC> activePrimary:0x%X, activeBackup:0x%X", - iv_activeTocOffsets.first, iv_activeTocOffsets.second); + iv_TocOffset[WORKING].first = l_toc; + iv_TocOffset[WORKING].second = l_backupTOC; + TRACFCOMP(g_trac_pnor, "findTOC> activePrimary:0x%X, " + "activeBackup:0x%X", iv_TocOffset[WORKING].first, + iv_TocOffset[WORKING].second); } else { @@ -665,9 +715,9 @@ errlHndl_t PnorRP::readTOC() memset(toc0Buffer, 0xFF, PAGESIZE); memset(toc1Buffer, 0xFF, PAGESIZE); - if (iv_activeTocOffsets.first != INVALID_OFFSET) + if (iv_TocOffset[WORKING].first != INVALID_OFFSET) { - l_errhdl = readFromDevice(iv_activeTocOffsets.first, 0, false, + l_errhdl = readFromDevice(iv_TocOffset[WORKING].first, 0, false, toc0Buffer, fatal_error ); if (l_errhdl) { @@ -676,9 +726,9 @@ errlHndl_t PnorRP::readTOC() } } - if (iv_activeTocOffsets.second != INVALID_OFFSET) + if (iv_TocOffset[WORKING].second != INVALID_OFFSET) { - l_errhdl = readFromDevice(iv_activeTocOffsets.second, 0, false, + l_errhdl = readFromDevice(iv_TocOffset[WORKING].second, 0, false, toc1Buffer, fatal_error ); if (l_errhdl) { @@ -710,6 +760,118 @@ errlHndl_t PnorRP::readTOC() return l_errhdl; } +errlHndl_t PnorRP::setSideInfo () +{ + uint64_t l_chip = 0; + uint64_t l_fatalError = 0; + uint8_t* l_tocBuffer = new uint8_t [PAGESIZE]; + ffs_hdr* l_ffs_hdr = 0; + errlHndl_t l_err = NULL; + for (SideId i = FIRST_SIDE; i < NUM_SIDES; i = (SideId)(i+1)) + { + //id + iv_side[i].id = (SideId)i; + + //get a valid TOC + uint64_t l_primaryTOC = iv_TocOffset[i].first; + uint64_t l_backupTOC = iv_TocOffset[i].second; + + uint64_t l_validTOC = (l_primaryTOC != INVALID_OFFSET) ? l_primaryTOC : + ((l_backupTOC != INVALID_OFFSET) ? l_backupTOC : + INVALID_OFFSET); + if(l_validTOC == INVALID_OFFSET) + { + if (i == WORKING) + { + TRACFCOMP(g_trac_pnor, "setSideInfo: No valid TOC found for" + "working side"); + INITSERVICE::doShutdown(PNOR::RC_INVALID_WORKING_TOC); + } + else + { + TRACFCOMP(g_trac_pnor,"setSideInfo: No valid TOC found for" + " side: %d", i); + /*@ + * @errortype + * @moduleid PNOR::MOD_PNORRP_SETSIDEINFO + * @reasoncode PNOR::RC_INVALID_TOC + * @userdata1 Side Id + * @userdata2[00:31] primary toc + * @userdata2[32:63] backup toc + * @devdesc PnorRP::setSideInfo> No valid TOCs found + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + PNOR::MOD_PNORRP_SETSIDEINFO, + PNOR::RC_INVALID_TOC, + i,TWO_UINT32_TO_UINT64(l_primaryTOC,l_backupTOC), + true); + l_err->addPartCallout( + TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL, + HWAS::PNOR_PART_TYPE, + HWAS::SRCI_PRIORITY_LOW, + HWAS::NO_DECONFIG, + HWAS::GARD_NULL); + break; + } + } + + iv_side[i].primaryTOC = l_primaryTOC; + iv_side[i].backupTOC = l_backupTOC; + + l_err = readFromDevice(l_validTOC,l_chip, + false, l_tocBuffer,l_fatalError); + if(l_err) + { + TRACFCOMP(g_trac_pnor, "setSideInfo: readFromDevice failed" + " while reading a valid TOC"); + break; + } + l_ffs_hdr = (ffs_hdr*)l_tocBuffer; + + //isGolden + //Entry 0 is the "part" partition + //Need to read from the ffs hdr instead of the TOC because + //TOC has no knowledge of other side + ffs_entry* cur_entry = (&l_ffs_hdr->entries[0]); + ffs_hb_user_t* ffsUserData = (ffs_hb_user_t*)&(cur_entry->user); + iv_side[i].isGolden = (ffsUserData->miscFlags & FFS_MISC_GOLDEN); + + //isGuardPresent + uint64_t l_secOffset = INVALID_OFFSET; + findPhysicalOffset (l_ffs_hdr, "GUARD", l_secOffset); + iv_side[i].isGuardPresent = (l_secOffset != INVALID_OFFSET); + + //isOtherSide + iv_side[i].hasOtherSide = false; +#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT + iv_side[i].hasOtherSide = + ((iv_TocOffset[(i+1)%NUM_SIDES].first != INVALID_OFFSET) || + (iv_TocOffset[(i+1)%NUM_SIDES].second != INVALID_OFFSET)); +#endif + + //hbbAddress + l_secOffset = INVALID_OFFSET; + findPhysicalOffset (l_ffs_hdr, "HBB", l_secOffset); + iv_side[i].hbbAddress = l_secOffset; + + //mmioOffset + uint64_t l_mmioOffset; + physicalToMmioOffset(l_secOffset, l_mmioOffset); + iv_side[i].hbbMmioOffset = l_mmioOffset; + + //char side + iv_side[i].side =(ALIGN_DOWN_X(l_secOffset,32*MEGABYTE) == 0) ? 'A':'B'; + + TRACFCOMP(g_trac_pnor, "setSideInfo: sideId:%d, isGolden:%d, " + "isGuardPresent:%d, hasOtherSide:%d, primaryTOC: 0x%x, backupTOC" + ":0x%X, HBB:0x%X, MMIO:0x%X",i, iv_side[i].isGolden, + iv_side[i].isGuardPresent,iv_side[i].hasOtherSide, + iv_side[i].primaryTOC, iv_side[i].backupTOC, + iv_side[i].hbbAddress, iv_side[i].hbbMmioOffset); + } + return l_err; +} /** * @brief Message receiver */ @@ -1271,6 +1433,6 @@ errlHndl_t PnorRP::fixECC (PNOR::SectionId i_section) 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; + return (i_toc == TOC_0) ? iv_TocOffset[WORKING].first : + iv_TocOffset[WORKING].second; } diff --git a/src/usr/pnor/pnorrp.H b/src/usr/pnor/pnorrp.H index 27e52732f..1a9b04ff6 100644 --- a/src/usr/pnor/pnorrp.H +++ b/src/usr/pnor/pnorrp.H @@ -48,6 +48,16 @@ class PnorRP static void init( errlHndl_t &io_rtaskRetErrl ); /** + * @brief Returns information about a given side of pnor + * (Called by an external interface PNOR::getSideInfo()) + * @param[in] i_side PNOR side + * @param[out] o_info side information + * + * @return errlHndl_t Error log if request was invalid + */ + errlHndl_t getSideInfo (PNOR::SideId i_side, PNOR::SideInfo_t& o_info); + + /** * @brief Return the size and address of a given section of PNOR data * Called by external PNOR::getSectionInfo() * @@ -78,9 +88,9 @@ class PnorRP errlHndl_t fixECC(PNOR::SectionId i_section); /** - * @brief Get TOC offset of specified TOC on active side + * @brief Get TOC offset of specified TOC and side * - * @param[in] i_toc TOC offset desired on active side + * @param[in] i_toc TOC id of the TOC requested * * @return uint64_t TOC offset */ @@ -100,12 +110,12 @@ 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<uint64_t, uint64_t> iv_activeTocOffsets; -#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT - std::pair<uint64_t, uint64_t> iv_altTocOffsets; -#endif + /* + * Stores primary and backup TOCs for each side of PNOR + */ + typedef std::pair<uint64_t, uint64_t> TocOffsets_t; + TocOffsets_t iv_TocOffset [PNOR::NUM_SIDES]; + enum { BASE_VADDR = VMM_VADDR_PNOR_RP, /**< 2GB = 0x80000000*/ @@ -127,6 +137,11 @@ class PnorRP }; /** + * Stores information about all sides of PNOR + */ + PNOR::SideInfo_t iv_side[PNOR::NUM_SIDES]; + + /** * Cached copy of section data */ PNOR::SectionData_t iv_TOC[PNOR::NUM_SECTIONS+1]; @@ -161,6 +176,13 @@ class PnorRP */ errlHndl_t findTOC(); + /* + * @brief determines the sides information and fills the class variable + * iv_side + * @return Error + */ + errlHndl_t setSideInfo(); + /** * @brief Verify both TOC's and store section information from one of the * verified TOC's. Additionally set each section permissions |