summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPrachi Gupta <pragupta@us.ibm.com>2015-01-23 14:18:43 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2015-02-24 15:36:10 -0600
commitb908135a569ed584b12262a020664d0150e4d933 (patch)
tree695a74c1598415beefc984d27f8a7fd9713ccf2f
parentb03dc1b8e4b20a8039775e474bd9ebf2503bf48c (diff)
downloadtalos-hostboot-b908135a569ed584b12262a020664d0150e4d933.tar.gz
talos-hostboot-b908135a569ed584b12262a020664d0150e4d933.zip
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 <smcprek@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r--src/include/usr/initservice/mboxRegs.H36
-rw-r--r--src/include/usr/pnor/pnor_reasoncodes.H7
-rw-r--r--src/usr/hwas/hwasPlatDeconfigGard.C3
-rw-r--r--src/usr/initservice/istepdispatcher/splesscommon.C6
-rw-r--r--src/usr/initservice/istepdispatcher/splesscommon.H10
-rw-r--r--src/usr/pnor/HBconfig2
-rw-r--r--src/usr/pnor/pnor_common.C74
-rw-r--r--src/usr/pnor/pnor_common.H58
-rw-r--r--src/usr/pnor/pnorrp.C329
-rw-r--r--src/usr/pnor/pnorrp.H13
-rw-r--r--src/usr/pnor/runtime/rt_pnor.C56
-rw-r--r--src/usr/pnor/runtime/rt_pnor.H5
-rw-r--r--src/usr/pnor/sfc_ast2400.C19
-rw-r--r--src/usr/pnor/sfc_ast2400.H13
-rw-r--r--src/usr/sbe/HBconfig2
-rw-r--r--src/usr/sbe/sbe_update.C2
16 files changed, 512 insertions, 123 deletions
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 <stdint.h>
#include <stdio.h>
#include <string.h>
-
+#include <initservice/mboxRegs.H>
// $$$$$$$ 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 <pnor/pnorif.H>
+#include "ffs.h"
+#include <devicefw/driverif.H>
+#include <initservice/mboxRegs.H>
+
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 <top of flash>-<pnor size>+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 <config.h>
#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<void*>(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 <vmmconst.h>
#include <map>
#include "pnor_common.H"
-
+#include "ffs.h"
+#include <config.h>
/**
* 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<uint64_t, uint64_t> iv_activeTocOffsets;
+#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT
std::pair<uint64_t, uint64_t> iv_altTocOffsets;
-
+#endif
enum
{
BASE_VADDR = VMM_VADDR_PNOR_RP, /**< 2GB = 0x80000000*/
@@ -153,6 +155,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
* (e.g. readOnly)
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 <util/align.H>
// 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
@@ -79,11 +79,6 @@ class RtPnor
private:
/**
- * Which TOC (0 or 1) is used after verifying both.
- */
- PNOR::TOCS iv_TOC_used;
-
- /**
* Cached copy of section data
*/
PNOR::SectionData_t iv_TOC[PNOR::NUM_SECTIONS+1];
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 <util/align.H>
-
+#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 <top of flash>-<pnor size>+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
OpenPOWER on IntegriCloud