From b908135a569ed584b12262a020664d0150e4d933 Mon Sep 17 00:00:00 2001 From: Prachi Gupta Date: Fri, 23 Jan 2015 14:18:43 -0600 Subject: determine the toc locations in pnorrp and rt_pnor code RTC: 120733 Change-Id: I5372a102ce9761a514a6f7245ca206a2226f1f3b Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15456 Tested-by: Jenkins Server Reviewed-by: STEPHEN M. CPREK Reviewed-by: Daniel M. Crowell Reviewed-by: A. Patrick Williams III --- src/include/usr/initservice/mboxRegs.H | 36 +++ src/include/usr/pnor/pnor_reasoncodes.H | 7 + src/usr/hwas/hwasPlatDeconfigGard.C | 3 +- src/usr/initservice/istepdispatcher/splesscommon.C | 6 +- src/usr/initservice/istepdispatcher/splesscommon.H | 10 +- src/usr/pnor/HBconfig | 2 +- src/usr/pnor/pnor_common.C | 74 ++++- src/usr/pnor/pnor_common.H | 58 +++- src/usr/pnor/pnorrp.C | 329 ++++++++++++++++++--- src/usr/pnor/pnorrp.H | 13 +- src/usr/pnor/runtime/rt_pnor.C | 56 ++-- src/usr/pnor/runtime/rt_pnor.H | 5 - src/usr/pnor/sfc_ast2400.C | 19 +- src/usr/pnor/sfc_ast2400.H | 13 +- src/usr/sbe/HBconfig | 2 +- src/usr/sbe/sbe_update.C | 2 +- 16 files changed, 512 insertions(+), 123 deletions(-) create mode 100644 src/include/usr/initservice/mboxRegs.H diff --git a/src/include/usr/initservice/mboxRegs.H b/src/include/usr/initservice/mboxRegs.H new file mode 100644 index 000000000..cabb4f050 --- /dev/null +++ b/src/include/usr/initservice/mboxRegs.H @@ -0,0 +1,36 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/initservice/mboxRegs.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +#ifndef MBOXREGS_H_ +#define MBOXREGS_H_ + +namespace SPLESS +{ + const uint32_t MBOX_SCRATCH_REG0 = 0x00050038; + const uint32_t MBOX_SCRATCH_REG1 = 0x00050039; + const uint32_t MBOX_SCRATCH_REG2 = 0x0005003a; + const uint32_t MBOX_SCRATCH_REG3 = 0x0005003b; +}; + +#endif diff --git a/src/include/usr/pnor/pnor_reasoncodes.H b/src/include/usr/pnor/pnor_reasoncodes.H index 4857c1b2c..823f439e8 100644 --- a/src/include/usr/pnor/pnor_reasoncodes.H +++ b/src/include/usr/pnor/pnor_reasoncodes.H @@ -44,6 +44,7 @@ namespace PNOR MOD_PNORRP_DIDSTARTUPFAIL = 0x09, /**< didStartupFail(rc) */ MOD_PNORRP_FLUSH = 0x0A, /**< mm_remove_pages */ MOD_PNORRP_FIXECC = 0x0B, /**< fixECC */ + MOD_PNORRP_FINDTOC = 0x0C, /**< findTOC */ // pnorvalid.C MOD_PNORVALID_MAIN = 0x0E, /**< validateAltMaster */ @@ -138,6 +139,12 @@ namespace PNOR RC_NON_ECC_PROTECTED_SECTION = PNOR_COMP_ID | 0x21, RC_WRITABLE_PERM_FAIL = PNOR_COMP_ID | 0x22, RC_WRITE_TRACKED_PERM_FAIL = PNOR_COMP_ID | 0x23, + //termination_rc + RC_PARTITION_TABLE_NOT_FOUND = PNOR_COMP_ID | 0x24, + //termination_rc + RC_PARTITION_TABLE_CORRUPTED = PNOR_COMP_ID | 0x25, + //termination_rc + RC_FINDTOC_FAILED = PNOR_COMP_ID | 0x26, }; enum UserDetailsTypes diff --git a/src/usr/hwas/hwasPlatDeconfigGard.C b/src/usr/hwas/hwasPlatDeconfigGard.C index 2911cf3c1..52eb1b04c 100644 --- a/src/usr/hwas/hwasPlatDeconfigGard.C +++ b/src/usr/hwas/hwasPlatDeconfigGard.C @@ -493,8 +493,9 @@ errlHndl_t getGardSectionInfo(PNOR::SectionInfo_t& o_sectionInfo) // @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 +#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"); diff --git a/src/usr/initservice/istepdispatcher/splesscommon.C b/src/usr/initservice/istepdispatcher/splesscommon.C index 424fdf2cc..5c5d8d4d6 100644 --- a/src/usr/initservice/istepdispatcher/splesscommon.C +++ b/src/usr/initservice/istepdispatcher/splesscommon.C @@ -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. */ @@ -37,7 +39,7 @@ #include #include #include - +#include // $$$$$$$ undefine this before checking in.... // #define SPLESS_DEBUG 1 diff --git a/src/usr/initservice/istepdispatcher/splesscommon.H b/src/usr/initservice/istepdispatcher/splesscommon.H index a8b1af942..71dbef763 100644 --- a/src/usr/initservice/istepdispatcher/splesscommon.H +++ b/src/usr/initservice/istepdispatcher/splesscommon.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,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. */ @@ -60,12 +62,6 @@ namespace SPLESS { -const uint32_t MBOX_SCRATCH_REG0 = 0x00050038; -const uint32_t MBOX_SCRATCH_REG1 = 0x00050039; -const uint32_t MBOX_SCRATCH_REG2 = 0x0005003a; -const uint32_t MBOX_SCRATCH_REG3 = 0x0005003b; - - /** * @enum * SPLess Task return codes diff --git a/src/usr/pnor/HBconfig b/src/usr/pnor/HBconfig index 21082f4ea..55f16db8a 100644 --- a/src/usr/pnor/HBconfig +++ b/src/usr/pnor/HBconfig @@ -38,7 +38,7 @@ config PNOR_IS_32MB help Size of the attached flash chip is 32MB, if not set then 64MB is default -config TWO_SIDE_SUPPORT +config PNOR_TWO_SIDE_SUPPORT default n help This is used to turn on/off two sided pnor support diff --git a/src/usr/pnor/pnor_common.C b/src/usr/pnor/pnor_common.C index c8c1e14b3..6844984e5 100644 --- a/src/usr/pnor/pnor_common.C +++ b/src/usr/pnor/pnor_common.C @@ -91,6 +91,71 @@ uint32_t PNOR::pnor_ffs_checksum(void* data, size_t size) return checksum; } +/* + * @brief determine the physical offset of the ffs entry + * (to be used before readTOC is called) + */ +void PNOR::findPhysicalOffset(ffs_hdr* i_tocAddress, + const char* i_entryName, + uint64_t & o_offset) +{ + for(uint32_t i = 0; i < i_tocAddress->entry_count; i++) + { + ffs_entry* l_curEntry = (&i_tocAddress->entries[i]); + if(strcmp(i_entryName,l_curEntry->name) == 0) + { + o_offset = ((uint64_t)l_curEntry->base)*PAGESIZE; + break; + } + } +} + +/* + * @brief used to translate mmio offset stored in mbox scratch 2 + * to physical offset of HBB Image + */ +errlHndl_t PNOR::mmioToPhysicalOffset(uint64_t& o_hbbAddress) +{ + errlHndl_t l_err = NULL; + do + { + uint64_t l_hbbMMIO = 0; + size_t l_size = sizeof(uint64_t); + TARGETING::Target* l_masterProc = + TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL; + + //MBOX_SCRATCH_REG2 = 0x5003A + l_err = DeviceFW::deviceRead(l_masterProc, &l_hbbMMIO,l_size, + DEVICE_SCOM_ADDRESS(SPLESS::MBOX_SCRATCH_REG2)); + if (l_err) + { + TRACFCOMP(g_trac_pnor,"PNOR::mmioToPhysicalOffset: Failed to read" + " HB MMIO offset"); + break; + } + //All SCOMS are 64-bit, HB MMIO is stored in higher 32-bits. + //ANDing with TOP_OF_FLASH to maskout anything in the higher bits + l_hbbMMIO = (l_hbbMMIO >> 32) & PNOR::LPC_TOP_OF_FLASH_OFFSET; + o_hbbAddress = ((9*l_hbbMMIO) - (9*PNOR::LPC_SFC_MMIO_OFFSET) + - PNOR::PNOR_SIZE) /8; + } while (0); + return l_err; +} + +/* + * @brief used to translate HBB Address to MMIO offset + */ +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; +} + +/* + * @brief: parse the TOCs read from memory and store section information + * from one of the verified TOCs + */ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, TOCS & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr) { @@ -398,7 +463,7 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, break; } -# ifndef __HOSTBOOT_RUNTIME +#ifndef __HOSTBOOT_RUNTIME // Handle section permissions if (o_TOC[secId].misc & FFS_MISC_READ_ONLY) { @@ -495,6 +560,13 @@ errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, { break; } + if (!TOC_0_failed) + { + //if we find a working TOC we don't need to loop again. + //In runtime case, OPAL returns a working TOC. + //So, we don't want to look at the second one. + break; + } } // For TOC's if (l_errhdl) { diff --git a/src/usr/pnor/pnor_common.H b/src/usr/pnor/pnor_common.H index 5eb893412..b1106237a 100644 --- a/src/usr/pnor/pnor_common.H +++ b/src/usr/pnor/pnor_common.H @@ -26,6 +26,10 @@ #define PNOR_COMMON_H #include +#include "ffs.h" +#include +#include + namespace PNOR { /** * Internal information to deal with the sections of PNOR @@ -51,18 +55,13 @@ namespace PNOR { enum { - // @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 SUPPORTED_FFS_VERSION = 0x1, /**< Supported FFS Version */ FFS_TABLE_BASE_ADDR = 0x0, /**< Currently only have FFS table */ + TOC_SIZE = 0x8000, + INVALID_OFFSET = 0xFFFFFFF, }; /** @@ -81,7 +80,7 @@ namespace PNOR { /** * @brief parse the TOCs read from memory and store section - * information from one of the verified TOC's + * information from one of the verified TOCs * @param[in] i_toc0Buffer Pointer to toc0 * @param[in] i_toc1Buffer Pointer to toc1 * @param[out] o_TOC_used which TOC is used @@ -91,6 +90,49 @@ namespace PNOR { */ errlHndl_t parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer, TOCS & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr); + + /* + * @brief: determine the physical offset of ffs entry + * (to be used before readTOC is called) + * @param[in] i_tocAddress - ffs hdr pointing to a valid TOC + * @param[in] i_entryName - Name of the ffs entry to find the offset of + * @param[out] o_offset - physical offset of the ffs entry + */ + void findPhysicalOffset(ffs_hdr* i_tocAddress, + const char* i_entryName, + uint64_t & o_offset); + + /* + * @brief used to translate mmio offset stored in mbox scratch 2 + * to physical offset of HBB Image + * @param[out] o_hbbAddress Physical Offset of HB Base Image + * associated with the current boot + * @return Error + */ + errlHndl_t mmioToPhysicalOffset(uint64_t& o_hbbAddress); + + /* + * @brief used to translate HBB Address to MMIO offset + * @param[in] i_hbbAddress - Physical Offset of the HB Base image + * @param[out] o_mmioOffest - MMIO Offset of the HB Base image + */ + void physicalToMmioOffset(uint64_t i_hbbAddress, + uint64_t& o_mmioOffset); + + enum + { + LPC_TOP_OF_FLASH_OFFSET = 0x0FFFFFFF, +#ifdef CONFIG_PNOR_IS_32MB + PNOR_SIZE = 32*MEGABYTE, +#else //default to 64MB + PNOR_SIZE = 64*MEGABYTE, +#endif + //The direct offset value must be equal to -+1 + // 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, + }; + } #endif diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C index aeaeb222a..aad312b38 100644 --- a/src/usr/pnor/pnorrp.C +++ b/src/usr/pnor/pnorrp.C @@ -46,7 +46,6 @@ #include #include "pnor_common.H" - extern trace_desc_t* g_trac_pnor; // Easy macro replace for unit testing @@ -193,9 +192,8 @@ void* wait_for_message( void* unused ) * @brief Constructor */ PnorRP::PnorRP() -: 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_TOC_used(TOC_0) ,iv_msgQ(NULL) ,iv_startupRC(0) { @@ -234,29 +232,6 @@ void PnorRP::initDaemon() do { - // @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) - { - 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(); @@ -289,8 +264,16 @@ void PnorRP::initDaemon() INITSERVICE::registerBlock(reinterpret_cast(BASE_VADDR), TOTAL_SIZE,PNOR_PRIORITY); - // Read the TOC in the PNOR to compute the sections and set their - // correct permissions + //Find and read the TOC in the PNOR to compute the sections and set + //their correct permissions + l_errhdl = findTOC(); + if( l_errhdl ) + { + TRACFCOMP(g_trac_pnor, ERR_MRK"PnorRP::initDaemon: Failed to findTOC"); + errlCommit(l_errhdl, PNOR_COMP_ID); + INITSERVICE::doShutdown(PNOR::RC_FINDTOC_FAILED); + } + l_errhdl = readTOC(); if( l_errhdl ) { @@ -409,6 +392,262 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section, return l_errhdl; } +/* + * @brief Finds the toc locations based on hostboot base address + */ +errlHndl_t PnorRP::findTOC() +{ + TRACFCOMP(g_trac_pnor, ENTER_MRK"PnorRP::findTOC..."); + errlHndl_t l_err = NULL; + do { + const uint32_t l_shiftAmount = 32; + uint64_t l_chip = 0; + uint64_t l_fatalError = 0; + bool l_foundTOC = false; + uint64_t l_toc = PNOR::PNOR_SIZE - 1; + ffs_hdr* l_ffs_hdr = 0; + uint64_t l_hbbAddr = 0; + uint8_t l_tocBuffer [PAGESIZE]; + + //get the HBB Address we booted from + l_err = PNOR::mmioToPhysicalOffset(l_hbbAddr); + if (l_err) + { + TRACFCOMP(g_trac_pnor, "PnorRP::findTOC> mmioToPhysicalOffset failed"); + break; + } + + //if we booted from a lower address, then we need to increment + //sides as we find tocs, otherwise decrement. + bool l_inc = (ALIGN_DOWN_X(l_hbbAddr, l_shiftAmount*MEGABYTE) == 0); + uint64_t l_tempHBB = l_hbbAddr; + + //while TOC not found and we are within the flash size + while((!l_foundTOC) && (l_tempHBB > 0) && (l_tempHBB < PNOR_SIZE)) + { + //Align HBB down -- looking at 0x0 or 0x2000000 + l_toc = ALIGN_DOWN_X(l_tempHBB, l_shiftAmount*MEGABYTE); + l_err = readFromDevice(l_toc, l_chip, false, l_tocBuffer, + l_fatalError); + if(l_err) + { + TRACFCOMP(g_trac_pnor,"findTOC: readFromDevice failed " + "searching for primaryTOC"); + break; + } + + l_ffs_hdr = (ffs_hdr*)l_tocBuffer; + l_foundTOC = ((l_ffs_hdr->magic == FFS_MAGIC) && + (PNOR::pnor_ffs_checksum(l_ffs_hdr,FFS_HDR_SIZE) == 0)); + if (!l_foundTOC) + { + //If TOC not found at 0x0 or 0x2000000 + //Align HBB down + 8000 -- looking at 0x8000 or 0x2008000 + l_toc += TOC_SIZE; + l_err = readFromDevice(l_toc, l_chip, false, l_tocBuffer, + l_fatalError); + if(l_err) + { + TRACFCOMP(g_trac_pnor,"findTOC: readFromDevice failed " + "searching for backupTOC for A-B-D arrangement"); + break; + } + + l_ffs_hdr = (ffs_hdr*)l_tocBuffer; + l_foundTOC = + ((l_ffs_hdr->magic == FFS_MAGIC) && + (PNOR::pnor_ffs_checksum(l_ffs_hdr, FFS_HDR_SIZE) == 0)); + } + + if (!l_foundTOC) + { + //If toc not found at 0x8000 or 0x2008000 + //Align HBB up (l_shiftAmount) - 8000 + // -- looking at 0x1FF8000 or 0x3FF8000 + l_toc = ALIGN_X(l_tempHBB, l_shiftAmount*MEGABYTE); + l_toc -= TOC_SIZE; + l_err = readFromDevice(l_toc, l_chip, false, l_tocBuffer, + l_fatalError); + if(l_err) + { + TRACFCOMP(g_trac_pnor,"findTOC: readFromDevice failed" + "searching for backupTOC for A-D-B arrangement"); + break; + } + + l_ffs_hdr = (ffs_hdr*)l_tocBuffer; + l_foundTOC = + ((l_ffs_hdr->magic == FFS_MAGIC) && + (PNOR::pnor_ffs_checksum(l_ffs_hdr, FFS_HDR_SIZE) == 0)); + } + + //Setup for next time -- look for the other side + l_tempHBB = (l_inc) ? (l_tempHBB + l_shiftAmount*MEGABYTE) : + (l_tempHBB - l_shiftAmount*MEGABYTE); + } + + if(l_err) + { + break; + } + + //found at least one TOC + if(l_foundTOC) + { + TRACFCOMP(g_trac_pnor, "findTOC> found at least one toc at 0x%X", l_toc); + + //look for BACKUP_PART and read it + uint64_t l_backupTOC = INVALID_OFFSET; + PNOR::findPhysicalOffset(l_ffs_hdr,"BACKUP_PART",l_backupTOC); + + //figure out if the toc found belongs to the side we booted from + //or if it belongs to the other side + uint64_t l_foundHBB; + PNOR::findPhysicalOffset(l_ffs_hdr, "HBB", l_foundHBB); + bool l_isActiveTOC = (l_foundHBB == l_hbbAddr); + +#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT + uint64_t l_otherPrimaryTOC = INVALID_OFFSET; + uint64_t l_otherBackupTOC = INVALID_OFFSET; + uint8_t l_otherPrimaryTOCBuff [PAGESIZE]; + uint8_t l_otherBackupTOCBuff [PAGESIZE]; + uint8_t l_backupTOCBuffer [PAGESIZE]; + + //look for OTHER_SIDE + PNOR::findPhysicalOffset(l_ffs_hdr, "OTHER_SIDE",l_otherPrimaryTOC); + + //reading to look for OTHER_SIDE's backup + bool l_foundOtherBackup = false; + bool l_foundOtherPrimary = false; + + if (l_otherPrimaryTOC != INVALID_OFFSET) + { + l_err = readFromDevice(l_otherPrimaryTOC,l_chip, + false, l_otherPrimaryTOCBuff,l_fatalError); + l_ffs_hdr = (ffs_hdr*)l_otherPrimaryTOCBuff; + if(l_err) + { + TRACFCOMP(g_trac_pnor, "findTOC: readFromDevice failed" + " while looking for other side's primary TOC"); + errlCommit(l_err, PNOR_COMP_ID); + } + else if ((l_ffs_hdr->magic == FFS_MAGIC) && + (PNOR::pnor_ffs_checksum(l_ffs_hdr, FFS_HDR_SIZE)==0)) + { + //if otherPrimaryTOC is valid, + //then we can find it's backup + PNOR::findPhysicalOffset(l_ffs_hdr, "BACKUP_PART", + l_otherBackupTOC); + l_foundOtherPrimary = true; + } + } + if ((!l_foundOtherPrimary) && (l_backupTOC != INVALID_OFFSET)) + { + //if otherPrimaryTOC is not valid, find the other backup + //through BACKUP_PART's OTHER_SIDE + l_err = readFromDevice (l_backupTOC, l_chip, false, + l_backupTOCBuffer, l_fatalError); + l_ffs_hdr = (ffs_hdr*)l_backupTOCBuffer; + if (l_err) + { + TRACFCOMP(g_trac_pnor, "findTOC: readFromDevice failed" + " while reading for backup TOC"); + errlCommit(l_err, PNOR_COMP_ID); + } + else if ((l_ffs_hdr->magic == FFS_MAGIC) + && (PNOR::pnor_ffs_checksum(l_ffs_hdr,FFS_HDR_SIZE)==0)) + { + PNOR::findPhysicalOffset(l_ffs_hdr,"OTHER_SIDE", + l_otherBackupTOC); + l_foundOtherBackup = true; + } + } + + //figure out if other side's toc belongs to the side we booted from + if(l_foundOtherPrimary) + { + PNOR::findPhysicalOffset((ffs_hdr*)l_otherPrimaryTOCBuff, "HBB", + l_foundHBB); + } + else if (l_foundOtherBackup) + { + l_err = readFromDevice (l_otherBackupTOC, l_chip, false, + l_otherBackupTOCBuff, l_fatalError); + l_ffs_hdr = (ffs_hdr*)l_backupTOCBuffer; + if (l_err) + { + TRACFCOMP(g_trac_pnor, "findTOC: readFromDevice failed" + " while reading other side's backup TOC"); + errlCommit(l_err, PNOR_COMP_ID); + } + else if ((l_ffs_hdr->magic == FFS_MAGIC) && + (PNOR::pnor_ffs_checksum(l_ffs_hdr,FFS_HDR_SIZE)==0)) + { + PNOR::findPhysicalOffset(l_ffs_hdr,"HBB", + l_foundHBB); + } + } + bool l_isOtherActiveTOC = (l_foundHBB == l_hbbAddr); + + if (l_isActiveTOC) + { + iv_activeTocOffsets.first = l_toc; + iv_activeTocOffsets.second = l_backupTOC; + iv_altTocOffsets.first = l_otherPrimaryTOC; + iv_altTocOffsets.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; + } + else + { + TRACFCOMP(g_trac_pnor,"findTOC>No valid TOC found, looked" + "at following addresses PrimaryTOC:0x%08X, BackupTOC:" + "0x%08X", l_toc, l_backupTOC); + 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); +#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); + } + else + { + TRACFCOMP(g_trac_pnor,"findTOC>No valid TOC found, looked" + "at following addresses PrimaryTOC:0x%08X, BackupTOC:" + "0x%08X", l_toc, l_backupTOC); + INITSERVICE::doShutdown(PNOR::RC_PARTITION_TABLE_CORRUPTED); + } + +#endif + } + else + { + //no valid TOC found + TRACFCOMP(g_trac_pnor, "No valid TOC found"); + if (l_err) + { + errlCommit(l_err, PNOR_COMP_ID); + } + INITSERVICE::doShutdown(PNOR::RC_PARTITION_TABLE_NOT_FOUND); + } + } while (0); + + TRACFCOMP(g_trac_pnor, EXIT_MRK"findTOC"); + return l_err; +} + /** * @brief Read the TOC and store section information */ @@ -420,20 +659,32 @@ errlHndl_t PnorRP::readTOC() uint8_t* toc1Buffer = new uint8_t[PAGESIZE]; uint64_t fatal_error = 0; do { - l_errhdl = readFromDevice( iv_activeTocOffsets.first, 0, false, - toc0Buffer, fatal_error ); - if (l_errhdl) + //Initialize toc bufferes to invalid value + //If these buffers are not read from device, + //then parseTOC will see invalid data + memset(toc0Buffer, 0xFF, PAGESIZE); + memset(toc1Buffer, 0xFF, PAGESIZE); + + if (iv_activeTocOffsets.first != INVALID_OFFSET) { - TRACFCOMP(g_trac_pnor, "readTOC: readFromDevice failed for TOC0"); - break; + l_errhdl = readFromDevice(iv_activeTocOffsets.first, 0, false, + toc0Buffer, fatal_error ); + if (l_errhdl) + { + TRACFCOMP(g_trac_pnor,"readTOC:readFromDevice failed for TOC0"); + break; + } } - l_errhdl = readFromDevice( iv_activeTocOffsets.second, 0, false, - toc1Buffer, fatal_error ); - if (l_errhdl) + if (iv_activeTocOffsets.second != INVALID_OFFSET) { - TRACFCOMP(g_trac_pnor, "readTOC: readFromDevice failed for TOC1"); - break; + l_errhdl = readFromDevice(iv_activeTocOffsets.second, 0, false, + toc1Buffer, fatal_error ); + if (l_errhdl) + { + TRACFCOMP(g_trac_pnor,"readTOC:readFromDevice failed for TOC1"); + break; + } } l_errhdl = PNOR::parseTOC(toc0Buffer, toc1Buffer, iv_TOC_used, iv_TOC, diff --git a/src/usr/pnor/pnorrp.H b/src/usr/pnor/pnorrp.H index 509cf1436..27e52732f 100644 --- a/src/usr/pnor/pnorrp.H +++ b/src/usr/pnor/pnorrp.H @@ -33,7 +33,8 @@ #include #include #include "pnor_common.H" - +#include "ffs.h" +#include /** * PNOR Resource Provider */ @@ -102,8 +103,9 @@ class PnorRP // 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; +#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT std::pair iv_altTocOffsets; - +#endif enum { BASE_VADDR = VMM_VADDR_PNOR_RP, /**< 2GB = 0x80000000*/ @@ -152,6 +154,13 @@ class PnorRP */ void initDaemon(); + /** + * @brief Determine the TOC offsets based on the HBB address + * System does a shutdown if any errors detected + * @return Error from device + */ + errlHndl_t findTOC(); + /** * @brief Verify both TOC's and store section information from one of the * verified TOC's. Additionally set each section permissions diff --git a/src/usr/pnor/runtime/rt_pnor.C b/src/usr/pnor/runtime/rt_pnor.C index f616e9874..0afb7fea9 100644 --- a/src/usr/pnor/runtime/rt_pnor.C +++ b/src/usr/pnor/runtime/rt_pnor.C @@ -37,6 +37,7 @@ #include "../ffs.h" #include "../common/ffs_hb.H" +#include // Trace definition extern trace_desc_t* g_trac_pnor; @@ -297,7 +298,6 @@ errlHndl_t RtPnor::flush( PNOR::SectionId i_section) } /*******Protected Methods**************/ RtPnor::RtPnor() -:iv_TOC_used(PNOR::TOC_0) { errlHndl_t l_err = readTOC(); if (l_err) @@ -574,44 +574,37 @@ errlHndl_t RtPnor::readTOC () { TRACFCOMP(g_trac_pnor, ENTER_MRK"RtPnor::readTOC" ); errlHndl_t l_err = NULL; - uint8_t* toc0Buffer = new uint8_t[PAGESIZE]; - uint8_t* toc1Buffer = new uint8_t[PAGESIZE]; + uint8_t* l_toc0Buffer = new uint8_t[PNOR::TOC_SIZE]; do { - //find proc id - uint64_t l_procId; - TARGETING::Target* l_masterProc = NULL; - TARGETING::targetService().masterProcChipTargetHandle( l_masterProc ); - l_err = RT_TARG::getRtTarget (l_masterProc, l_procId); - if (l_err) - { - TRACFCOMP(g_trac_pnor, "RtPnor::readTOC: getRtTarget failed"); - break; - } - if (g_hostInterfaces && g_hostInterfaces->pnor_read) { - //@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); + //find proc id + uint64_t l_procId; + TARGETING::Target* l_masterProc = NULL; + TARGETING::targetService().masterProcChipTargetHandle(l_masterProc); + l_err = RT_TARG::getRtTarget (l_masterProc, l_procId); if (l_err) { - TRACFCOMP(g_trac_pnor,"RtPnor::readTOC:readFromDevice failed" - " for TOC0"); + TRACFCOMP(g_trac_pnor, "RtPnor::readTOC: getRtTarget failed"); break; } - - l_err = readFromDevice(l_procId,PNOR::TOC,PNOR::SIDE_A_TOC_1_OFFSET, - PAGESIZE, false,toc1Buffer); + // offset = 0 means read the entire PNOR::TOC partition + // This offset is offset into the partition, not offset from the + // beginning of the flash + l_err = readFromDevice (l_procId, PNOR::TOC, 0, + PNOR::TOC_SIZE, false, l_toc0Buffer); if (l_err) { - TRACFCOMP(g_trac_pnor, "RtPnor::readTOC:readFromDevice failed" - " for TOC1"); + TRACFCOMP(g_trac_pnor,"RtPnor::readTOC:readFromDevice failed" + " for TOC0"); break; } - l_err = PNOR::parseTOC(toc0Buffer,toc1Buffer,iv_TOC_used,iv_TOC,0); + // When we ask for TOC partition, Opal returns a valid TOC. + // So, we don't need to verify the second TOC in parseTOC + // Therefore, sending invalid value for second toc + PNOR::TOCS l_tocUsed; + l_err = PNOR::parseTOC(l_toc0Buffer, 0, l_tocUsed, iv_TOC, 0); if (l_err) { TRACFCOMP(g_trac_pnor, "RtPnor::readTOC: parseTOC failed"); @@ -620,14 +613,9 @@ errlHndl_t RtPnor::readTOC () } } while (0); - if(toc0Buffer != NULL) - { - delete[] toc0Buffer; - } - - if(toc1Buffer != NULL) + if(l_toc0Buffer != NULL) { - delete[] toc1Buffer; + delete[] l_toc0Buffer; } TRACFCOMP(g_trac_pnor, EXIT_MRK"RtPnor::readTOC" ); diff --git a/src/usr/pnor/runtime/rt_pnor.H b/src/usr/pnor/runtime/rt_pnor.H index f3a03a5ec..a888d046d 100644 --- a/src/usr/pnor/runtime/rt_pnor.H +++ b/src/usr/pnor/runtime/rt_pnor.H @@ -78,11 +78,6 @@ class RtPnor ~RtPnor(); private: - /** - * Which TOC (0 or 1) is used after verifying both. - */ - PNOR::TOCS iv_TOC_used; - /** * Cached copy of section data */ diff --git a/src/usr/pnor/sfc_ast2400.C b/src/usr/pnor/sfc_ast2400.C index 20f2aa7fe..8ceb391cc 100644 --- a/src/usr/pnor/sfc_ast2400.C +++ b/src/usr/pnor/sfc_ast2400.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2015 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -43,7 +43,7 @@ #include "sfc_ast2400.H" #include "norflash.H" #include - +#include "pnor_common.H" /*****************************************************************************/ // C o n s t a n t s @@ -108,7 +108,8 @@ errlHndl_t SfcAST2400::readFlash( uint32_t i_addr, words_read ++ ) { //Read directly from MMIO space - uint32_t lpc_addr = LPC_SFC_MMIO_OFFSET | (i_addr + words_read*4); + uint32_t lpc_addr = PNOR::LPC_SFC_MMIO_OFFSET | + (i_addr + words_read*4); size_t reg_size = sizeof(uint32_t); l_err = deviceOp( DeviceFW::READ, @@ -358,7 +359,7 @@ errlHndl_t SfcAST2400::sendSpiCmd( uint8_t i_opCode, &i_opCode, opsize, //just send opcode DEVICE_LPC_ADDRESS(LPC::TRANS_FW, - LPC_SFC_MMIO_OFFSET) ); + PNOR::LPC_SFC_MMIO_OFFSET) ); if( l_err ) { break; } // Send address if there is one @@ -371,7 +372,7 @@ errlHndl_t SfcAST2400::sendSpiCmd( uint8_t i_opCode, &i_address, opsize, //only supporting 4-byte addresses DEVICE_LPC_ADDRESS(LPC::TRANS_FW, - LPC_SFC_MMIO_OFFSET) ); + PNOR::LPC_SFC_MMIO_OFFSET) ); if( l_err ) { break; } } @@ -391,7 +392,7 @@ errlHndl_t SfcAST2400::sendSpiCmd( uint8_t i_opCode, curptr, opsize, DEVICE_LPC_ADDRESS(LPC::TRANS_FW, - LPC_SFC_MMIO_OFFSET) ); + PNOR::LPC_SFC_MMIO_OFFSET) ); break; } @@ -405,7 +406,7 @@ errlHndl_t SfcAST2400::sendSpiCmd( uint8_t i_opCode, curptr, opsize, DEVICE_LPC_ADDRESS(LPC::TRANS_FW, - LPC_SFC_MMIO_OFFSET) ); + PNOR::LPC_SFC_MMIO_OFFSET)); if( l_err ) { break; } curptr += 4; @@ -430,7 +431,7 @@ errlHndl_t SfcAST2400::sendSpiCmd( uint8_t i_opCode, curptr, opsize, DEVICE_LPC_ADDRESS(LPC::TRANS_FW, - LPC_SFC_MMIO_OFFSET) ); + PNOR::LPC_SFC_MMIO_OFFSET) ); break; } @@ -444,7 +445,7 @@ errlHndl_t SfcAST2400::sendSpiCmd( uint8_t i_opCode, curptr, opsize, DEVICE_LPC_ADDRESS(LPC::TRANS_FW, - LPC_SFC_MMIO_OFFSET) ); + PNOR::LPC_SFC_MMIO_OFFSET)); if( l_err ) { break; } curptr += 4; diff --git a/src/usr/pnor/sfc_ast2400.H b/src/usr/pnor/sfc_ast2400.H index 3d087cfb6..79d18c1ba 100644 --- a/src/usr/pnor/sfc_ast2400.H +++ b/src/usr/pnor/sfc_ast2400.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2015 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -265,17 +265,6 @@ class SfcAST2400 : public SfcDD /** @brief General Constants */ enum { - LPC_TOP_OF_FLASH_OFFSET = 0x0FFFFFFF, -#ifdef CONFIG_PNOR_IS_32MB - PNOR_SIZE = 32*MEGABYTE, -#else //default to 64MB - PNOR_SIZE = 64*MEGABYTE, -#endif - //The direct offset value must be equal to -+1 - // 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, - /**< Offset to SPI Controller Register Space */ LPC_SFC_CTLR_BASE = 0x1E789000, diff --git a/src/usr/sbe/HBconfig b/src/usr/sbe/HBconfig index 952baf852..0fa24413d 100644 --- a/src/usr/sbe/HBconfig +++ b/src/usr/sbe/HBconfig @@ -16,7 +16,7 @@ config SBE_UPDATE_SIMULTANEOUS result is that both SBE SEEPROMs will contain the same code. config SBE_UPDATE_INDEPENDENT - default y if TWO_SIDE_SUPPORT + default y if PNOR_TWO_SIDE_SUPPORT depends on !SBE_UPDATE_SEQUENTIAL && !SBE_UPDATE_SIMULTANEOUS help If an update is necessary, and if the "current" SBE SEEPROM of this diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C index a2fad1ee9..97a048426 100644 --- a/src/usr/sbe/sbe_update.C +++ b/src/usr/sbe/sbe_update.C @@ -2156,7 +2156,7 @@ namespace SBE // Determine if PNOR is 1- or 2-sided and if there is a // GOLDEN boot involved -#ifdef CONFIG_TWO_SIDE_SUPPORT +#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT // @todo RTC 120734 - ask PNOR if we are in "GOLDEN" mode, // which would mean that we are booting off the the GOLDEN -- cgit v1.2.1