summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bootloader/bl_pnorAccess.C189
-rw-r--r--src/include/bootloader/bl_pnorAccess.H104
-rw-r--r--src/include/usr/lpc/lpc_const.H48
-rw-r--r--src/include/usr/pnor/pnor_const.H122
-rw-r--r--src/include/usr/pnor/pnor_reasoncodes.H6
-rw-r--r--src/include/usr/pnor/pnorif.H98
-rw-r--r--src/usr/lpc/lpcdd.C18
-rw-r--r--src/usr/lpc/lpcdd.H11
-rw-r--r--src/usr/pnor/makefile6
-rw-r--r--src/usr/pnor/pnor_common.C632
-rw-r--r--src/usr/pnor/pnor_common.H92
-rw-r--r--src/usr/pnor/pnor_utils.C357
-rw-r--r--src/usr/pnor/pnor_utils.H224
-rw-r--r--src/usr/pnor/pnordd.H6
-rw-r--r--src/usr/pnor/pnorrp.C152
-rw-r--r--src/usr/pnor/pnorrp.H9
-rw-r--r--src/usr/pnor/runtime/makefile3
-rw-r--r--src/usr/pnor/runtime/rt_pnor.C11
-rw-r--r--src/usr/pnor/runtime/test/makefile2
-rw-r--r--src/usr/pnor/runtime/test/testpnor_rt.H3
-rw-r--r--src/usr/pnor/test/makefile6
-rw-r--r--src/usr/pnor/test/pnorUtilsTestResources.H56
-rw-r--r--src/usr/pnor/test/pnorddtest.H45
-rw-r--r--src/usr/pnor/test/pnorutilsTest.H341
24 files changed, 1860 insertions, 681 deletions
diff --git a/src/bootloader/bl_pnorAccess.C b/src/bootloader/bl_pnorAccess.C
new file mode 100644
index 000000000..046a4bf0a
--- /dev/null
+++ b/src/bootloader/bl_pnorAccess.C
@@ -0,0 +1,189 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/bootloader/bl_pnorAccess.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] 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 */
+
+#include <bootloader/bl_pnorAccess.H>
+#include <bootloader/bootloader_trace.H>
+#include <util/singleton.H>
+#include <bootloader/bootloader.H>
+#ifdef PNORUTILSTEST_H
+#define BOOTLOADER_TRACE(args) TRACFCOMP(g_trac_pnor,"##args")
+#define BOOTLOADER_TRACE_W_BRK(args) TRACFCOMP(g_trac_pnor,"##args")
+#endif
+
+
+extern const char* cv_EYECATCHER[];
+/**
+* @brief Takes in a buffer containing a ToC, as well as a base address
+ Returns out a boolean whether or not this toc was valid
+ also returns a SectionData_t struct if the toc was valid
+*/
+void bl_pnorAccess::readTOC(uint8_t i_tocBuffer[PNOR::TOC_SIZE],
+ uint32_t & o_errCode,
+ PNOR::SectionData_t * o_TOC,
+ uint64_t i_baseAddr)
+{
+ do
+ {
+ o_errCode = PNOR::NO_ERROR;
+
+ ffs_hdr* l_ffs_hdr = NULL;
+ //zero out the section data for each section
+ PNOR::initializeSections(o_TOC);
+
+ BOOTLOADER_TRACE(BTLDR_TRC_PA_READTOC_ZEROSECTION_RTN);
+
+ //make sure that the buffer is not null
+ PNOR::checkForNullBuffer(i_tocBuffer, o_errCode, l_ffs_hdr);
+
+ if(o_errCode != PNOR::NO_ERROR)
+ {
+ BOOTLOADER_TRACE_W_BRK(BTLDR_TRC_PA_READTOC_CHKNULLBUFFER_NULL);
+ break;
+ }
+
+ BOOTLOADER_TRACE(BTLDR_TRC_PA_READTOC_CHECKNULLBUFFER_RTN);
+
+ //Do a checksum on the header
+ if(PNOR::pnor_ffs_checksum(l_ffs_hdr, FFS_HDR_SIZE) != 0)
+ {
+ o_errCode |= PNOR::CHECKSUM_ERR;
+ }
+
+ if(o_errCode != PNOR::NO_ERROR)
+ {
+ BOOTLOADER_TRACE_W_BRK(BTLDR_TRC_PA_READTOC_HDRCHECKSUM_ERR);
+ break;
+ }
+
+ BOOTLOADER_TRACE(BTLDR_TRC_PA_READTOC_HDRCHECKSUM_RTN);
+
+ //Check out the header to make sure its all valid
+ PNOR::checkHeader(l_ffs_hdr, o_errCode);
+
+ if(o_errCode != PNOR::NO_ERROR)
+ {
+ BOOTLOADER_TRACE_W_BRK(BTLDR_TRC_PA_READTOC_CHECKHEADER_ERR);
+ break;
+ }
+ BOOTLOADER_TRACE(BTLDR_TRC_PA_READTOC_CHECKHEADER_RTN);
+
+
+ //if an error is found with an entry we use this variable to hold
+ //the value of the entry. That way we can record which entry is causing
+ //an issue.
+ ffs_entry* l_err_entry = NULL;
+
+ //parse through the entries and check for any errors
+ PNOR::parseEntries(l_ffs_hdr, o_errCode, o_TOC, l_err_entry);
+
+ if(o_errCode != PNOR::NO_ERROR)
+ {
+ BOOTLOADER_TRACE_W_BRK(BTLDR_TRC_PA_READTOC_PARSEENTRIES_ERR);
+ break;
+ }
+ BOOTLOADER_TRACE(BTLDR_TRC_PA_READTOC_PARSEENTRIES_RTN);
+
+
+ } while(0);
+}
+
+void bl_pnorAccess::findTOC(uint64_t i_pnorBase, PNOR::SectionData_t * o_TOC,
+ uint32_t& o_errCode, uint8_t& o_tocUsed)
+{
+ uint8_t *l_tocBuffer = Bootloader::g_blScratchSpace;
+ do
+ {
+ //@TODO RTC:138268 Set up multiple side of PNOR for bootloader
+ o_errCode = 0;
+ o_tocUsed = 0;
+ //Copy Table of Contents from PNOR flash to a local buffer
+ Bootloader::handleMMIO(i_pnorBase,
+ reinterpret_cast<uint64_t>(l_tocBuffer),
+ (PNOR::TOC_SIZE),
+ Bootloader::BYTESIZE);
+
+ BOOTLOADER_TRACE(BTLDR_TRC_PA_FINDTOC_TOC1_HANDLEMMIO_RTN);
+
+ readTOC(l_tocBuffer, o_errCode, o_TOC, i_pnorBase);
+
+ if(o_errCode == PNOR::NO_ERROR)
+ {
+ BOOTLOADER_TRACE(BTLDR_TRC_PA_FINDTOC_TOC1_READTOC_RTN);
+ o_tocUsed = 0;
+ break;
+ }
+ else
+ {
+ Bootloader::handleMMIO(i_pnorBase + PNOR::BACKUP_TOC_OFFSET,
+ reinterpret_cast<uint64_t>(l_tocBuffer),
+ (PNOR::TOC_SIZE),
+ Bootloader::BYTESIZE);
+
+ o_errCode = 0;
+ readTOC(l_tocBuffer, o_errCode, o_TOC, i_pnorBase);
+ if(o_errCode == PNOR::NO_ERROR)
+ {
+ o_tocUsed = 1;
+ break;
+ }
+ BOOTLOADER_TRACE_W_BRK(BTLDR_TRC_PA_FINDTOC_READTOC_ERR);
+ }
+
+ break;
+ }while(0);
+}
+
+/**
+ * @brief Get the hostboot base image
+ */
+void bl_pnorAccess::getHBBSection(uint64_t i_pnorStart,
+ PNOR::SectionData_t& o_hbbSection,
+ uint32_t& o_errCode,
+ uint8_t& o_tocUsed)
+{
+ BOOTLOADER_TRACE(BTLDR_TRC_PA_GETHBBSECTION_START);
+ do
+ {
+ PNOR::SectionData_t l_TOC[PNOR::NUM_SECTIONS];
+
+ findTOC(i_pnorStart, l_TOC, o_errCode, o_tocUsed);
+ if(o_errCode != PNOR::NO_ERROR)
+ {
+ BOOTLOADER_TRACE_W_BRK(BTLDR_TRC_PA_GETHBBSECTION_FINDTOC_ERR);
+ break;
+ }
+ o_hbbSection = l_TOC[PNOR::HB_BASE_CODE];
+
+ if(o_hbbSection.flashAddr == PNOR::INVALID_FLASH_OFFSET)
+ {
+ o_errCode = PNOR::NO_HBB_SECTION;
+ BOOTLOADER_TRACE_W_BRK(BTLDR_TRC_PA_GETHBBSECTION_FINDTOC_NOHBB);
+ break;
+ }
+ } while(0);
+ BOOTLOADER_TRACE(BTLDR_TRC_PA_GETHBBSECTION_FINDTOC_RTN);
+
+}
+
diff --git a/src/include/bootloader/bl_pnorAccess.H b/src/include/bootloader/bl_pnorAccess.H
new file mode 100644
index 000000000..bc19a4dc2
--- /dev/null
+++ b/src/include/bootloader/bl_pnorAccess.H
@@ -0,0 +1,104 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/bootloader/bl_pnorAccess.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] 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 __BL_PNORACCESS_H
+#define __BL_PNORACCESS_H
+
+
+#include <pnor_const.H>
+#include <pnor_utils.H>
+#include <ffs.h>
+
+/** @file bl_pnorAccess.H
+ * @brief Provides interface to the PNOR flash for bootloader
+ */
+
+/**
+ * @brief bootloader PNOR access class
+ * Provide interfaces for the bootloader to look through pnor and find toc
+ */
+
+class bl_pnorAccess
+{
+
+ friend class pnorutilsTest;
+ public:
+
+/**
+ * @brief Get the hostboot base image
+ *
+ * @param[in] i_pnorStart MMIO address to access the start of pnor flash
+ *
+ * @param[out] o_hbbSection Struct that holds information about the
+ * Hostboot Base Image Section
+ *
+ * @param[out] o_errCode Anything besides PNOR:NO_ERROR is an error
+ *
+ * @param[out] o_tocUsed Tells you which table of contents was used
+ *
+ * @return void
+ */
+static void getHBBSection(uint64_t i_pnorStart,
+ PNOR::SectionData_t& o_hbbSection,
+ uint32_t& o_errCode,
+ uint8_t& o_tocUsed);
+
+ private:
+/**
+ * @brief Read in the toc and get information about each section
+ *
+ * @param[in] i_tocBuffer Buffer containing a single TOC
+ *
+ * @param[out] o_errCode Anything besides PNOR:NO_ERROR is an error
+ *
+ * @param[out] o_TOC Array of section data describing contents of pnor
+ *
+ * @param[in] i_baseAddr MMIO address to access the start of pnor flash
+ *
+ * @return void
+ */
+static void readTOC(uint8_t i_tocBuffer[PNOR::TOC_SIZE], uint32_t & o_errCode,
+ PNOR::SectionData_t * o_TOC, uint64_t i_baseAddr);
+
+/**
+ * @brief Find a valid TOC within specified side of pnor flash
+ side is determined by the base mmio address passed in
+ *
+ * @param[in] i_pnorBase MMIO address to access the start of pnor flash
+ *
+ * @param[out] o_TOC Array of section data describing contents of pnor
+ *
+ * @param[out] o_errCode Anything besides PNOR:NO_ERROR is an error
+ *
+ * @param[out] o_tocUsed Tells you which table of contents was used
+ *
+ * @return void
+ */
+static void findTOC(uint64_t i_pnorBase, PNOR::SectionData_t * o_TOC,
+ uint32_t& o_errCode, uint8_t& o_tocUsed);
+
+};
+
+#endif \ No newline at end of file
diff --git a/src/include/usr/lpc/lpc_const.H b/src/include/usr/lpc/lpc_const.H
new file mode 100644
index 000000000..a7857e707
--- /dev/null
+++ b/src/include/usr/lpc/lpc_const.H
@@ -0,0 +1,48 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/lpc/lpc_const.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] 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 LPC_CONST_H
+#define LPC_CONST_H
+
+#include <stdint.h>
+#include <builtins.h>
+
+namespace LPC
+{
+ /**
+ * @brief Some general constants
+ *
+ */
+ enum {
+ LPCHC_FW_SPACE = 0xF0000000, /**< LPC Host Controller FW Space */
+ LPCHC_MEM_SPACE = 0xE0000000, /**< LPC Host Controller Mem Space */
+ LPCHC_IO_SPACE = 0xD0010000, /**< LPC Host Controller I/O Space */
+ LPCHC_REG_SPACE = 0xC0012000, /**< LPC Host Ctlr Register Space */
+
+ /** Physical addr of the start of LPC address space*/
+ LPC_PHYS_BASE = 0x6030000000000,
+ };
+}
+
+#endif \ No newline at end of file
diff --git a/src/include/usr/pnor/pnor_const.H b/src/include/usr/pnor/pnor_const.H
new file mode 100644
index 000000000..1f0b08574
--- /dev/null
+++ b/src/include/usr/pnor/pnor_const.H
@@ -0,0 +1,122 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/pnor/pnor_const.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] 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 __PNOR_PNOR_CONST_H
+#define __PNOR_PNOR_CONST_H
+
+#include <stdint.h>
+#include <builtins.h>
+
+namespace PNOR
+{
+
+/**
+ * PNOR Sections
+ */
+enum SectionId
+{
+ TOC, /**< Table of Contents */
+ // Value of HB_EXT_CODE must be 1 for debug framework.
+ HB_EXT_CODE, /**< Hostboot Extended Image */
+ GLOBAL_DATA, /**< Global Data */
+ HB_BASE_CODE, /**< Hostboot Base Image */
+ CENTAUR_SBE, /**< Centaur Self-Boot Engine image */
+ SBE_IPL, /**< Self-Boot Engine IPL image */
+ WINK, /**< Sleep Winkle Reference image */
+ PAYLOAD, /**< HAL/OPAL */
+ HB_RUNTIME, /**< Hostboot Runtime (for Sapphire) */
+ HB_DATA, /**< Hostboot Data */
+ GUARD_DATA, /**< Guard Data */
+ HB_ERRLOGS, /**< Hostboot Error log Repository */
+ DIMM_JEDEC_VPD, /**< DIMM JEDEC VPD */
+ MODULE_VPD, /**< Module VPD */
+ CENTAUR_VPD, /**< Centaur VPD */
+ NVRAM, /**< Opal NVRAM */
+ OCC, /**< OCC lid */
+ FIRDATA, /**< FIRDATA */
+ ATTR_TMP, /**< Temporary Attribute Override */
+ ATTR_PERM, /**< Permanent Attribute Override */
+ CAPP, /**< CAPP lid */
+ VERSION, /**< PNOR version string section */
+ HB_BOOTLOADER, /**< Hostboot Bootloader image */
+ TEST, /**< Scratch space for PNOR test cases */
+ TESTRO, /**< Scratch space for PNOR ReadOnly test cases */
+ BACKUP_PART, /**< Backup of TOC*/
+ NUM_SECTIONS, /**< Number of defined sections */
+
+ FIRST_SECTION = TOC, /**< First section (for looping) */
+ /**< Used for error cases, initialization */
+ INVALID_SECTION = NUM_SECTIONS,
+};
+
+/**
+ * Information about a section of PNOR
+ */
+ // Size and layout of this structure must be maintained for debug framework.
+struct SectionInfo_t
+{
+ SectionId id; /**< Identifier for this section */
+ const char* name; /**< Name of the section */
+ uint64_t vaddr; /**< Virtual address of the start of the section */
+ uint32_t flashAddr; /**< Flash address of the start of the section*/
+ uint64_t size; /**< Size of partition in bytes */
+ bool eccProtected; /**< Section is ECC protected */
+ bool sha512Version; /**< Version Checking */
+ bool sha512perEC; /**< Version Checking perEC */
+ bool readOnly; /**< Section is read only */
+};
+
+/**
+ * PNOR Sides
+ */
+enum SideId
+{
+ WORKING = 0,
+#ifdef CONFIG_PNOR_TWO_SIDE_SUPPORT
+ ALTERNATE = 1,
+#endif
+ NUM_SIDES,
+ INVALID_SIDE = NUM_SIDES,
+ FIRST_SIDE = WORKING,
+};
+
+enum
+{
+ INVALID_OFFSET = 0xFFFFFFF, // Invalid primary or alternate TOC
+ BACKUP_TOC_OFFSET = 0x8000,
+ INVALID_FLASH_OFFSET = 0xFFFFFFFF,
+};
+
+/** @brief PNOR::TEST section offsets for test cases to prevent
+ * concurrency problems
+ */
+enum TestSectionOffset{
+ pnorTestSec_readwrite_offset = 0x100,
+ pnorTestSec_smartwrite_offset = 0x120,
+ pnorTestSec_rt_readwrite_offset = 0x6000,
+};
+
+}
+
+#endif \ No newline at end of file
diff --git a/src/include/usr/pnor/pnor_reasoncodes.H b/src/include/usr/pnor/pnor_reasoncodes.H
index 4133c8a0f..d10cd44c6 100644
--- a/src/include/usr/pnor/pnor_reasoncodes.H
+++ b/src/include/usr/pnor/pnor_reasoncodes.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -153,6 +153,10 @@ namespace PNOR
RC_INVALID_WORKING_TOC = PNOR_COMP_ID | 0x28,
RC_INVALID_TOC = PNOR_COMP_ID | 0x29,
RC_WRONG_SIZE_FROM_READ = PNOR_COMP_ID | 0x2A,
+ RC_NULL_TOC_BUFFER = PNOR_COMP_ID | 0x2B,
+ RC_TOC_HDR_CHECKSUM_ERR = PNOR_COMP_ID | 0x2C,
+ RC_PNOR_PARSE_ENTRIES_ERR = PNOR_COMP_ID | 0x2D,
+ RC_PNOR_SET_VADDR_FAILED = PNOR_COMP_ID | 0x2E,
//@fixme-RTC:131607-Temporary value to allow HWSV compile
//termination_rc
diff --git a/src/include/usr/pnor/pnorif.H b/src/include/usr/pnor/pnorif.H
index 79a9a0f62..1a18750b5 100644
--- a/src/include/usr/pnor/pnorif.H
+++ b/src/include/usr/pnor/pnorif.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -28,6 +28,7 @@
#include <stdint.h>
#include <builtins.h>
+#include <pnor/pnor_const.H>
#include <errl/errlentry.H>
#include <utility>
#include <config.h>
@@ -36,75 +37,6 @@ namespace PNOR
{
/**
- * PNOR Sections
- */
-enum SectionId
-{
- TOC, /**< Table of Contents */
- // Value of HB_EXT_CODE must be 1 for debug framework.
- HB_EXT_CODE, /**< Hostboot Extended Image */
- GLOBAL_DATA, /**< Global Data */
- HB_BASE_CODE, /**< Hostboot Base Image */
- CENTAUR_SBE, /**< Centaur Self-Boot Engine image */
- SBE_IPL, /**< Self-Boot Engine IPL image */
- WINK, /**< Sleep Winkle Reference image */
- PAYLOAD, /**< HAL/OPAL */
- HB_RUNTIME, /**< Hostboot Runtime (for Sapphire) */
- HB_DATA, /**< Hostboot Data */
- GUARD_DATA, /**< Guard Data */
- HB_ERRLOGS, /**< Hostboot Error log Repository */
- DIMM_JEDEC_VPD, /**< DIMM JEDEC VPD */
- MODULE_VPD, /**< Module VPD */
- CENTAUR_VPD, /**< Centaur VPD */
- NVRAM, /**< Opal NVRAM */
- OCC, /**< OCC lid */
- FIRDATA, /**< FIRDATA */
- ATTR_TMP, /**< Temporary Attribute Override */
- ATTR_PERM, /**< Permanent Attribute Override */
- CAPP, /**< CAPP lid */
- VERSION, /**< PNOR version string section */
- TEST, /**< Scratch space for PNOR test cases */
- TESTRO, /**< Scratch space for PNOR ReadOnly test cases */
-
- NUM_SECTIONS, /**< Number of defined sections */
-
- FIRST_SECTION = TOC, /**< First section (for looping) */
- LAST_SECTION = TEST, /**< Last section (for looping) */
- INVALID_SECTION = NUM_SECTIONS, /**< Used for error cases, initialization */
-};
-
-/**
- * Information about a section of PNOR
- */
- // Size and layout of this structure must be maintained for debug framework.
-struct SectionInfo_t
-{
- SectionId id; /**< Identifier for this section */
- const char* name; /**< Name of the section */
- uint64_t vaddr; /**< Virtual address of the start of the section */
- uint32_t flashAddr; /**< Flash address of the start of the section*/
- uint64_t size; /**< Size of partition in bytes */
- bool eccProtected; /**< Section is ECC protected */
- bool sha512Version; /**< Version Checking */
- bool sha512perEC; /**< Version Checking perEC */
- bool readOnly; /**< Section is read only */
-};
-
-/**
- * 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
@@ -120,9 +52,12 @@ struct SideInfo_t
uint64_t hbbMmioOffset; /**< HBB MMIO Offset associated with hbbAddress*/
};
-enum
+/** Information about PNOR Layout */
+struct PnorInfo_t
{
- INVALID_OFFSET = 0xFFFFFFF, // Invalid primary or alternate TOC
+ uint32_t mmioOffset; //< Address of MMIO access
+ uint32_t norWorkarounds; //< NOR flash workarounds
+ uint32_t flashSize; //< Size of PNOR in bytes
};
/**
@@ -190,23 +125,6 @@ errlHndl_t clearSection(PNOR::SectionId i_section);
*/
errlHndl_t validateAltMaster( void );
-/** @brief PNOR::TEST section offsets for test cases to prevent
- * concurrency problems
- */
-enum TestSectionOffset{
- pnorTestSec_readwrite_offset = 0x100,
- pnorTestSec_smartwrite_offset = 0x120,
- pnorTestSec_rt_readwrite_offset = 0x6000,
-};
-
-/** Information about PNOR Layout */
-struct PnorInfo_t
-{
- uint32_t mmioOffset; //< Address of MMIO access
- uint32_t norWorkarounds; //< NOR flash workarounds
- uint32_t flashSize; //< Size of PNOR in bytes
-};
-
/**
* @brief Retrieve some information about the PNOR/SFC hardware
*
@@ -214,6 +132,6 @@ struct PnorInfo_t
*/
void getPnorInfo( PnorInfo_t& o_pnorInfo );
-}
+} // PNOR
#endif
diff --git a/src/usr/lpc/lpcdd.C b/src/usr/lpc/lpcdd.C
index 45bc2354f..3b8a2cd5a 100644
--- a/src/usr/lpc/lpcdd.C
+++ b/src/usr/lpc/lpcdd.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* Contributors Listed Below - COPYRIGHT 2014,2016 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -39,6 +39,7 @@
#include <targeting/common/targetservice.H>
#include <errl/errlmanager.H>
#include "lpcdd.H"
+#include <lpc/lpc_const.H>
#include <sys/time.h>
#include <lpc/lpc_reasoncodes.H>
#include <initservice/initserviceif.H>
@@ -379,7 +380,7 @@ LpcDD::LpcDD( TARGETING::Target* i_proc )
{
TRACFCOMP(g_trac_lpc, "LpcDD::LpcDD> " );
mutex_init( &iv_mutex );
- LPCBase_t baseAddr = LPC_PHYS_BASE + LPC_ADDR_START;
+ LPCBase_t baseAddr = LPC::LPC_PHYS_BASE + LPC_ADDR_START;
setLPCBaseAddr( static_cast<uint64_t *>(
@@ -635,7 +636,8 @@ errlHndl_t LpcDD::checkAddr(LPC::TransType i_type,
invalid_address = true;
break;
}
- *o_addr = getLPCBaseAddr()+ i_addr+ LPCHC_IO_SPACE- LPC_ADDR_START;
+ *o_addr =
+ getLPCBaseAddr()+ i_addr+ LPC::LPCHC_IO_SPACE- LPC_ADDR_START;
break;
case LPC::TRANS_MEM:
if( i_addr >= 0x10000000 )
@@ -643,8 +645,8 @@ errlHndl_t LpcDD::checkAddr(LPC::TransType i_type,
invalid_address = true;
break;
}
-
- *o_addr = getLPCBaseAddr()+ i_addr+ LPCHC_MEM_SPACE- LPC_ADDR_START;
+ *o_addr =
+ getLPCBaseAddr()+ i_addr+ LPC::LPCHC_MEM_SPACE- LPC_ADDR_START;
break;
case LPC::TRANS_FW:
if( i_addr >= 0x10000000 )
@@ -652,7 +654,8 @@ errlHndl_t LpcDD::checkAddr(LPC::TransType i_type,
invalid_address = true;
break;
}
- *o_addr = getLPCBaseAddr()+ i_addr + LPCHC_FW_SPACE- LPC_ADDR_START;
+ *o_addr =
+ getLPCBaseAddr()+ i_addr + LPC::LPCHC_FW_SPACE- LPC_ADDR_START;
break;
case LPC::TRANS_REG:
if( i_addr >= 0x100 )
@@ -660,7 +663,8 @@ errlHndl_t LpcDD::checkAddr(LPC::TransType i_type,
invalid_address = true;
break;
}
- *o_addr =getLPCBaseAddr()+ i_addr + LPCHC_REG_SPACE- LPC_ADDR_START;
+ *o_addr =
+ getLPCBaseAddr()+ i_addr + LPC::LPCHC_REG_SPACE- LPC_ADDR_START;
break;
case LPC::TRANS_ABS:
//Just use the address as given
diff --git a/src/usr/lpc/lpcdd.H b/src/usr/lpc/lpcdd.H
index 48fefa64c..1b4e3c5bd 100644
--- a/src/usr/lpc/lpcdd.H
+++ b/src/usr/lpc/lpcdd.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* Contributors Listed Below - COPYRIGHT 2014,2016 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -152,20 +152,11 @@ class LpcDD
*
*/
enum {
- LPCHC_FW_SPACE = 0xF0000000, /**< LPC Host Controller FW Space */
- LPCHC_MEM_SPACE = 0xE0000000, /**< LPC Host Controller Mem Space */
- LPCHC_IO_SPACE = 0xD0010000, /**< LPC Host Controller I/O Space */
- LPCHC_REG_SPACE = 0xC0012000, /**< LPC Host Ctlr Register Space */
/** Start of LPC Addr within the memory mapped space*/
LPC_ADDR_START = 0xC0000000,
/** Size that LPC takes up (0xC0000000 to 0xFFFFFFFF)*/
LPC_SPACE_SIZE = 0x40000000,
- /** Physical addr of the start of LPC address space*/
- LPC_PHYS_BASE = 0x6030000000000,
-
-
-
/**< OPB LPCM Sync FIR Reg - used to read the FIR*/
OPB_LPCM_FIR_REG = 0x01010C00,
diff --git a/src/usr/pnor/makefile b/src/usr/pnor/makefile
index 31087a4b2..fc6a34b7e 100644
--- a/src/usr/pnor/makefile
+++ b/src/usr/pnor/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2011,2015
+# Contributors Listed Below - COPYRIGHT 2011,2016
# [+] Google Inc.
# [+] International Business Machines Corp.
#
@@ -24,8 +24,10 @@
#
# IBM_PROLOG_END_TAG
ROOTPATH = ../../..
-MODULE = pnor
+
+MODULE = pnor
+OBJS += pnor_utils.o
OBJS += pnorrp.o
OBJS += pnordd.o
OBJS += pnor_common.o
diff --git a/src/usr/pnor/pnor_common.C b/src/usr/pnor/pnor_common.C
index 47eb670e8..f74392e6e 100644
--- a/src/usr/pnor/pnor_common.C
+++ b/src/usr/pnor/pnor_common.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* Contributors Listed Below - COPYRIGHT 2014,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -46,51 +46,8 @@ 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 */
- "ATTR_TMP", /**< PNOR::ATTR_TMP : Temporary Attribute Overrides */
- "ATTR_PERM", /**< PNOR::ATTR_PERM : Permanent Attribute Overrides */
- "CAPP", /**< PNOR::CAPP : CAPP LID */
- "VERSION", /**< PNOR::VERSION : PNOR Version string */
- "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 */
-};
+extern const char* cv_EYECATCHER[];
-/**
- * @brief calculates the checksum on data(ffs header/entry) and will return
- * 0 if the checksums match
- */
-uint32_t PNOR::pnor_ffs_checksum(void* data, size_t size)
-{
- uint32_t checksum = 0;
-
- for (size_t i = 0; i < (size/4); i++)
- {
- checksum ^= ((uint32_t*)data)[i];
- }
-
- checksum = htobe32(checksum);
- return checksum;
-}
/*
* @brief determine the physical offset of the ffs entry
@@ -120,7 +77,7 @@ errlHndl_t PNOR::mmioToPhysicalOffset(uint64_t& o_hbbAddress)
errlHndl_t l_err = NULL;
do
{
-#ifndef CONFIG_SFC_IS_FAKE // @FIXME RTC 132398
+#if 0 // @FIXME RTC 132398
uint64_t l_hbbMMIO = 0;
size_t l_size = sizeof(uint64_t);
TARGETING::Target* l_masterProc =
@@ -142,7 +99,7 @@ errlHndl_t PNOR::mmioToPhysicalOffset(uint64_t& o_hbbAddress)
- PNOR::PNOR_SIZE) /8;
#else // @FIXME RTC 132398
o_hbbAddress = 1; // @FIXME RTC 132398
-#endif // @FIXME RTC 132398
+#endif
} while (0);
return l_err;
}
@@ -164,446 +121,191 @@ void PNOR::physicalToMmioOffset(uint64_t i_hbbAddress,
* @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)
+errlHndl_t PNOR::parseTOC( uint8_t* i_tocBuffer,SectionData_t * o_TOC)
{
TRACUCOMP(g_trac_pnor,"PNOR::parseTOC>");
errlHndl_t l_errhdl = NULL;
- bool TOC_0_failed = false;
-
do{
- o_TOC_used = TOC_0;
+ // Zero out my table
+ PNOR::initializeSections(o_TOC);
+
+ uint32_t l_errCode = 0;
+ ffs_hdr* l_ffs_hdr = NULL;
- for (TOCS cur_TOC = TOC_0; cur_TOC < NUM_TOCS;
- cur_TOC = (TOCS)(cur_TOC+1))
+ TRACFCOMP(g_trac_pnor, "PNOR::parseTOC verifying TOC");
+
+ PNOR::checkForNullBuffer(i_tocBuffer, l_errCode, l_ffs_hdr);
+ //Check if the buffer is null
+ if(l_errCode != NO_ERROR)
{
- TRACFCOMP(g_trac_pnor, "PNOR::parseTOC verifying TOC: %d",cur_TOC);
- uint64_t nextVAddr = i_baseVAddr;
+ TRACFCOMP(g_trac_pnor, "Null TOC Buffer found while checking TOC" );
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORRP_READTOC
+ * @reasoncode PNOR::RC_NULL_TOC_BUFFER
+ * @userdata1 Address of toc buffer
+ * @userdata2 Error code
+ * @devdesc Expected buffer to have contents of TOC,
+ * instead was NULL
+ * @custdesc A problem occurred while reading PNOR
+ * partition table
+ */
+ l_errhdl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_READTOC,
+ PNOR::RC_NULL_TOC_BUFFER,
+ reinterpret_cast<uint64_t>(&i_tocBuffer),
+ l_errCode,
+ true /*Add HB SW Callout*/);
+ l_errhdl->collectTrace(PNOR_COMP_NAME);
+ break;
+ }
- // Zero out my table
- for( size_t id = PNOR::FIRST_SECTION;
- id <= PNOR::NUM_SECTIONS; //include extra entry for error paths
- ++id )
- {
- o_TOC[id].id = (PNOR::SectionId)id;
- //everything else should default to zero
- }
- // Read TOC information from TOC 0 and then TOC 1
- ffs_hdr* l_ffs_hdr;
- if (cur_TOC == 0)
- {
- if( !i_toc0Buffer )
- {
- TRACFCOMP(g_trac_pnor, "TOC0 buffer is NULL");
- TOC_0_failed = true;
- o_TOC_used = TOC_1;
- continue;
- }
- l_ffs_hdr = (ffs_hdr*) i_toc0Buffer;
- }
- else if (cur_TOC == 1)
- {
- if( !i_toc1Buffer )
- {
- TRACFCOMP(g_trac_pnor, "TOC1 buffer is NULL");
- continue;
- }
- l_ffs_hdr = (ffs_hdr*) i_toc1Buffer;
- }
- // ffs entry check, 0 if checksums match
- if( PNOR::pnor_ffs_checksum(l_ffs_hdr, FFS_HDR_SIZE) != 0)
- {
- //@TODO - RTC:90780 - May need to handle this differently
- // in SP-less config
- TRACFCOMP(g_trac_pnor,"PNOR::parseTOC pnor_ffs_checksum header"
- " checksums do not match.");
- if (cur_TOC == 0)
- {
- TRACFCOMP(g_trac_pnor, "PNOR::parseTOC TOC 0 failed header checksum");
- TOC_0_failed = true;
- o_TOC_used = TOC_1;
- continue;
- }
- else if (cur_TOC == TOC_1 && TOC_0_failed)
- {
- // Both TOC's failed
- TRACFCOMP(g_trac_pnor, "PNOR::parseTOC both TOCs are corrupted");
- /*@
- * @errortype
- * @moduleid PNOR::MOD_PNORCOMMON_PARSETOC
- * @reasoncode PNOR::RC_CORRUPTED_TOCS
- * @devdesc Both TOCs are corruputed
- */
- //@todo Add PNOR callout RTC:116145
- l_errhdl = new ERRORLOG::ErrlEntry
- (ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- PNOR::MOD_PNORCOMMON_PARSETOC,
- PNOR::RC_CORRUPTED_TOCS,
- 0, 0, true);
- break;
- }
- else
- {
- // TOC 1 failed
- TRACFCOMP(g_trac_pnor, "PNOR::parseTOC TOC 1 failed header checksum");
- break;
- }
- }
+ if(PNOR::pnor_ffs_checksum(l_ffs_hdr, FFS_HDR_SIZE) != 0)
+ {
+ l_errCode |= CHECKSUM_ERR;
+ }
+
+ //Checksum on header
+ if (l_errCode != NO_ERROR)
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::parseTOC Checksum error in TOC's header");
+ /* @errortype
+ * @moduleid PNOR::MOD_PNORRP_READTOC
+ * @reasoncode PNOR::RC_TOC_HDR_CHECKSUM_ERR
+ * @userdata1 Address of toc buffer
+ * @userdata2 Error Code
+ * @devdesc Hdr of TOC of PNOR failed checksum
+ * @custdesc A problem occurred while reading PNOR
+ * partition table
+ */
+ l_errhdl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_READTOC,
+ PNOR::RC_TOC_HDR_CHECKSUM_ERR,
+ reinterpret_cast<uint64_t>(&i_tocBuffer),
+ l_errCode,
+ false );
+ l_errhdl->addPartCallout(
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ HWAS::PNOR_PART_TYPE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ l_errhdl->collectTrace(PNOR_COMP_NAME);
+ break;
+ }
+
+ PNOR::checkHeader(l_ffs_hdr, l_errCode);
+ if(l_errCode != NO_ERROR)
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::parseTOC Error found parsing hdr of TOC " );
+ /* @errortype
+ * @moduleid PNOR::MOD_PNORRP_READTOC
+ * @reasoncode PNOR::RC_BAD_TOC_HEADER
+ * @userdata1 Address of toc buffer
+ * @userdata2 Error Code
+ * @devdesc Hdr of TOC of PNOR failed series of tests
+ * @custdesc A problem occurred while reading PNOR
+ * partition table
+ */
+ l_errhdl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_READTOC,
+ PNOR::RC_BAD_TOC_HEADER,
+ reinterpret_cast<uint64_t>(&i_tocBuffer),
+ l_errCode,
+ false );
+ l_errhdl->addPartCallout(
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ HWAS::PNOR_PART_TYPE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ l_errhdl->collectTrace(PNOR_COMP_NAME);
+ break;
+ }
+
+ TRACFCOMP(g_trac_pnor, "PNOR::parseTOC: FFS Block size=0x%.8X,"
+ " Partition Table Size = 0x%.8x, entry_count=%d",
+ l_ffs_hdr->block_size,l_ffs_hdr->size,l_ffs_hdr->entry_count);
+
+ ffs_entry* l_err_entry = NULL;
- // Only check header if on first TOC or the first TOC failed
- if (cur_TOC == TOC_0 || TOC_0_failed)
+ PNOR::parseEntries(l_ffs_hdr, l_errCode, o_TOC, l_err_entry);
+
+ if(l_errCode != NO_ERROR)
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::parseTOC parseEntries"
+ " parse entries returned an error");
+ o_TOC = NULL;
+ /* @errortype
+ * @moduleid PNOR::MOD_PNORRP_READTOC
+ * @reasoncode PNOR::RC_PNOR_PARSE_ENTRIES_ERR
+ * @userdata1 Address of toc buffer
+ * @userdata2 Error Code
+ * @devdesc Error while parsing pnor TOC entries
+ * @custdesc A problem occurred while reading PNOR
+ * partition table
+ */
+ l_errhdl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_READTOC,
+ PNOR::RC_PNOR_PARSE_ENTRIES_ERR,
+ reinterpret_cast<uint64_t>(&i_tocBuffer),
+ l_errCode,
+ true /*Add HB SW Callout*/);
+ l_errhdl->addPartCallout(
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ HWAS::PNOR_PART_TYPE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ l_errhdl->collectTrace(PNOR_COMP_NAME);
+ TRACFBIN(g_trac_pnor, "Entry in TOC that caused error during parsing", l_err_entry, FFS_ENTRY_SIZE);
+ break;
+ }
+
+
+ //Walk through all the entries in the table and record some info
+ for(uint32_t i=0; i<l_ffs_hdr->entry_count; i++)
+ {
+ uint32_t l_secId = PNOR::INVALID_SECTION;
+ ffs_entry* cur_entry = &(l_ffs_hdr->entries[i]);
+ TRACUCOMP(g_trac_pnor, "PNOR::parseTOC: TOC %d, Entry %d, name=%s, pointer=0x%X",l_tocBeingChecked, i,cur_entry->name, (uint64_t)cur_entry);
+
+ //Figure out section enum
+ PNOR::getSectionEnum(cur_entry, &l_secId);
+ if(l_secId == PNOR::INVALID_SECTION)
{
- TRACFCOMP(g_trac_pnor, "PNOR::parseTOC: FFS Block size=0x%.8X,"
- " Partition Table Size = 0x%.8x, entry_count=%d",
- l_ffs_hdr->block_size,l_ffs_hdr->size,l_ffs_hdr->entry_count);
-
- uint64_t spaceUsed = (sizeof(ffs_entry))*l_ffs_hdr->entry_count;
-
- /* Checking FFS Header to make sure it looks valid */
- bool header_good = true;
- if(l_ffs_hdr->magic != FFS_MAGIC)
- {
- TRACFCOMP(g_trac_pnor, "E>PNOR::parseTOC: Invalid magic"
- " number in FFS header: 0x%.4X",l_ffs_hdr->magic);
- header_good = false;
- }
- else if(l_ffs_hdr->version != SUPPORTED_FFS_VERSION)
- {
- TRACFCOMP(g_trac_pnor, "E>PNOR::parseTOC:Unsupported FFS"
- " Header version: 0x%.4X", l_ffs_hdr->version);
- header_good = false;
- }
- else if(l_ffs_hdr->entry_size != sizeof(ffs_entry))
- {
- TRACFCOMP(g_trac_pnor, "E>PNOR::parseTOC: Unexpected"
- " entry_size(0x%.8x) in FFS header: 0x%.4X",
- l_ffs_hdr->entry_size);
- header_good = false;
- }
- else if(l_ffs_hdr->entries == NULL)
- {
- TRACFCOMP(g_trac_pnor, "E>PNOR::parseTOC:"
- " FFS Header pointer to entries is NULL.");
- header_good = false;
- }
- else if(l_ffs_hdr->block_size != PAGESIZE)
- {
- TRACFCOMP(g_trac_pnor, "E>PNOR::parseTOC: Unsupported"
- " Block Size(0x%.4X). PNOR Blocks must be 4k",
- l_ffs_hdr->block_size);
- header_good = false;
- }
- else if(l_ffs_hdr->block_count == 0)
- {
- TRACFCOMP(g_trac_pnor, "E>PNOR::parseTOC: Unsupported"
- " Block COunt(0x%.4X). Device cannot be zero"
- " blocks in length.",l_ffs_hdr->block_count);
- header_good = false;
- }
- //Make sure all the entries fit in specified partition
- //table size
- else if(spaceUsed >
- ((l_ffs_hdr->block_size*l_ffs_hdr->size)-sizeof(ffs_hdr)))
- {
- TRACFCOMP(g_trac_pnor, "E>PNOR::parseTOC: FFS Entries"
- " (0x%.16X) go past end of FFS Table.",spaceUsed);
- header_good = false;
- }
-
- if(!header_good)
- {
- //Shutdown if we detected a partition table issue
- //for any reason
- if (TOC_0_failed)
- {
- /*@
- * @errortype
- * @moduleid PNOR::MOD_PNORCOMMON_PARSETOC
- * @reasoncode PNOR::RC_BAD_TOC_HEADER
- * @devdesc TOC 0 doesn't have a good header
- */
- l_errhdl = new ERRORLOG::ErrlEntry
- (ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- PNOR::MOD_PNORCOMMON_PARSETOC,
- PNOR::RC_BAD_TOC_HEADER,
- 0, 0, true);
- break;
- }
- else
- {
- TOC_0_failed = true;
- }
- //Try TOC1
- continue;
- }
+ TRACFCOMP(g_trac_pnor, "PNOR::parseTOC: Unrecognized Section name(%s), skipping",cur_entry->name);
+ continue;
}
- ffs_hb_user_t* ffsUserData = NULL;
+ TRACFCOMP(g_trac_pnor,"PNOR::parseTOC: User Data %s",
+ cur_entry->name);
- //Walk through all the entries in the table and parse the data.
- for(uint32_t i=0; i<l_ffs_hdr->entry_count; i++)
- {
- ffs_entry* cur_entry = (&l_ffs_hdr->entries[i]);
-
- TRACUCOMP(g_trac_pnor, "PNOR::parseTOC: Entry %d, name=%s, "
- "pointer=0x%X",i,cur_entry->name, (uint64_t)cur_entry);
-
- uint32_t secId = PNOR::INVALID_SECTION;
-
- // ffs entry check, 0 if checksums match
- if( PNOR::pnor_ffs_checksum(cur_entry, FFS_ENTRY_SIZE) != 0)
- {
- //@TODO - RTC:90780 - May need to handle this differently
- // in SP-less config
- TRACFCOMP(g_trac_pnor, "PNOR::parseTOC pnor_ffs_checksum"
- " entry checksums do not match");
- if (cur_TOC == TOC_0)
- {
- TRACFCOMP(g_trac_pnor,"PNOR::parseTOC TOC 0 entry"
- " checksum failed");
- TOC_0_failed = true;
- o_TOC_used = TOC_1;
- break;
- }
- else if (cur_TOC == TOC_1 && TOC_0_failed)
- {
- // Both TOC's failed
- TRACFCOMP(g_trac_pnor, "PNOR::parseTOC both TOC's are"
- " corrupted");
- /*@
- * @errortype
- * @moduleid PNOR::MOD_PNORCOMMON_PARSETOC
- * @reasoncode PNOR::RC_PARTITION_TABLE_INVALID
- * @devdesc Both TOCs are corrupted
- */
- l_errhdl = new ERRORLOG::ErrlEntry
- (ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- PNOR::MOD_PNORCOMMON_PARSETOC,
- PNOR::RC_PARTITION_TABLE_INVALID,
- 0, 0, true);
- break;
- }
- else
- {
- // TOC 1 failed
- TRACFCOMP(g_trac_pnor, "PNOR::parseTOC TOC 1 entry"
- " checksum failed");
- break;
- }
- }
-
- // Only set data if on first TOC or the first TOC failed
- if (cur_TOC == TOC_0 || TOC_0_failed)
- {
- //Figure out section enum
- for(uint32_t eyeIndex=PNOR::TOC;eyeIndex<PNOR::NUM_SECTIONS;
- eyeIndex++)
- {
- if(strcmp(cv_EYECATCHER[eyeIndex],cur_entry->name) == 0)
- {
- secId = eyeIndex;
- TRACUCOMP(g_trac_pnor, "PNOR::parseTOC: sectionId=%d", secId);
- break;
- }
- }
-
- if(secId == PNOR::INVALID_SECTION)
- {
- TRACFCOMP(g_trac_pnor, "PNOR::parseTOC: Unrecognized"
- " Section name(%s), skipping",cur_entry->name);
- continue;
- }
-
- ffsUserData = (ffs_hb_user_t*)&(cur_entry->user);
-
- //size
- o_TOC[secId].size = ((uint64_t)cur_entry->size)*PAGESIZE;
-
- //virtAddr
- o_TOC[secId].virtAddr = nextVAddr;
- nextVAddr += o_TOC[secId].size;
-
- //flashAddr
- o_TOC[secId].flashAddr=((uint64_t)cur_entry->base)*PAGESIZE;
-
- //chipSelect
- o_TOC[secId].chip = ffsUserData->chip;
-
- //user data
- o_TOC[secId].integrity = ffsUserData->dataInteg;
- o_TOC[secId].version = ffsUserData->verCheck;
- o_TOC[secId].misc = ffsUserData->miscFlags;
-
- TRACFCOMP(g_trac_pnor,"PNOR::parseTOC: User Data %s",
- cur_entry->name);
-
- if (o_TOC[secId].integrity == FFS_INTEG_ECC_PROTECT)
- {
- TRACFCOMP(g_trac_pnor, "PNOR::TOC: ECC enabled for %s",
- cur_entry->name);
- o_TOC[secId].size = ALIGN_PAGE_DOWN
- ((o_TOC[secId].size * 8 ) / 9);
- }
-
- // TODO RTC:96009 handle version header w/secureboot
- if (o_TOC[secId].version == FFS_VERS_SHA512)
- {
- TRACFCOMP(g_trac_pnor, "PNOR::parseTOC: Incrementing"
- " Flash Address for SHA Header");
- if (o_TOC[secId].integrity == FFS_INTEG_ECC_PROTECT)
- {
- o_TOC[secId].flashAddr += PAGESIZE_PLUS_ECC;
- }
- else
- {
- o_TOC[secId].flashAddr += PAGESIZE;
- }
- }
-
- if((o_TOC[secId].flashAddr + o_TOC[secId].size) >
- (l_ffs_hdr->block_count*PAGESIZE))
- {
- TRACFCOMP(g_trac_pnor, "E>PNOR::parseTOC:Partition(%s)"
- " at base address (0x%.8x) extends past end of"
- " flash device",cur_entry->name,
- o_TOC[secId].flashAddr);
- /*@
- * @errortype
- * @moduleid PNOR::MOD_PNORCOMMON_PARSETOC
- * @reasoncode PNOR::RC_SECTION_SIZE_IS_BIG
- * @devdesc Invalid partition table
- */
- l_errhdl = new ERRORLOG::ErrlEntry
- (ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- PNOR::MOD_PNORCOMMON_PARSETOC,
- PNOR::RC_SECTION_SIZE_IS_BIG,
- 0, 0, true);
- break;
- }
-
-#ifndef __HOSTBOOT_RUNTIME
- // Handle section permissions
- if (o_TOC[secId].misc & FFS_MISC_READ_ONLY)
- {
- // Need to set permissions to allow writing to virtual
- // addresses, but prevents the kernel from ejecting
- // dirty pages (no WRITE_TRACKED).
- int rc = mm_set_permission(
- (void*)o_TOC[secId].virtAddr,
- o_TOC[secId].size,
- WRITABLE);
- if (rc)
- {
- TRACFCOMP(g_trac_pnor, "E>PnorRP::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)
+ if (o_TOC[l_secId].integrity == FFS_INTEG_ECC_PROTECT)
{
- break;
+ TRACFCOMP(g_trac_pnor, "PNOR::TOC: ECC enabled for %s",
+ cur_entry->name);
+
}
- if (!TOC_0_failed)
+
+ // TODO RTC:96009 handle version header w/secureboot
+ if (o_TOC[l_secId].version == FFS_VERS_SHA512)
{
- //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;
+ TRACFCOMP(g_trac_pnor, "PNOR::parseTOC: Incrementing"
+ " Flash Address for SHA Header");
}
- } // For TOC's
- if (l_errhdl)
+ }
+ for(int tmpId = 0;
+ tmpId < PNOR::NUM_SECTIONS;
+ tmpId ++ )
{
- break;
+ TRACFCOMP(g_trac_pnor, "%s: size=0x%.8X flash=0x%.8X ",
+ cv_EYECATCHER[tmpId], o_TOC[tmpId].size,
+ o_TOC[tmpId].flashAddr);
}
- } 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 );
- }
+ } while (0);
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 7213add40..3bf6022d7 100644
--- a/src/usr/pnor/pnor_common.H
+++ b/src/usr/pnor/pnor_common.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* Contributors Listed Below - COPYRIGHT 2014,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -26,71 +26,24 @@
#define PNOR_COMMON_H
#include <pnor/pnorif.H>
+#include "pnor_utils.H"
#include "ffs.h"
-#include <devicefw/driverif.H>
-#include <initservice/mboxRegs.H>
+/************************************************************
+* Provides common functions for Hostboot IPL and runtime
+* code access to PNOR
+************************************************************/
namespace PNOR {
/**
- * Internal information to deal with the sections of PNOR
- */
- struct SectionData_t {
- PNOR::SectionId id; /**< Identifier for this section */
- uint64_t virtAddr; /**< Virtual address for the start of the section */
- uint32_t flashAddr; /**< Address in flash */
- uint32_t size;/**< Actual size of content in bytes (not including ECC)*/
- uint8_t chip; /**< Chip Select */
- uint8_t version; /**< Version Checking */
- uint16_t integrity; /**< Data Integrity */
- 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
- {
- /** 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,
- };
-
- /**
- * @brief Creates a 4-byte Cyclic Redundancy Check (CRC) on the data
- * provided. The last iteration of the for-loop includes the ffs
- * checksum itself. Therefore if the 4-byte CRC created matches
- * the ffs checksum, the resulting CRC will be 0
- *
- * @param[in] ptr Pointer to the data
- *
- * @param[in] size Size of the data
- *
- * @return uint32_t return 4-byte CRC, 0 if checksums match
- */
- uint32_t pnor_ffs_checksum(void* data, size_t size);
-
- /**
- * @brief parse the TOCs read from memory and store section
- * 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
+ * @brief parse the TOC read from memory and store section
+ * information if the TOC is valid
+ * @param[in] i_tocBuffer Pointer to buffer containing a TOC
* @param[out] o_TOC sectionInformation of the TOC used
- * @param[in] i_baseVAddr base virtual address of the TOC
* @return Error
*/
- errlHndl_t parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer,
- TOCS & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr);
+ errlHndl_t parseTOC(uint8_t* i_tocBuffer, PNOR::SectionData_t * o_TOC);
- /*
+ /**
* @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
@@ -101,7 +54,7 @@ namespace PNOR {
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
@@ -110,7 +63,8 @@ namespace PNOR {
*/
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
@@ -118,24 +72,6 @@ namespace PNOR {
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,
-
- //@TODO: RTC:124503 - delete the following line and call the LPC
- //interface instead
- LPC_FW_SPACE = 0xF0000000,
- };
-
}
#endif
diff --git a/src/usr/pnor/pnor_utils.C b/src/usr/pnor/pnor_utils.C
new file mode 100644
index 000000000..ead1be810
--- /dev/null
+++ b/src/usr/pnor/pnor_utils.C
@@ -0,0 +1,357 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/pnor_utils.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
+/* [+] 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 */
+
+
+/****************** Description *****************************************/
+//This file provides a variety of utility functions primarily interacting
+//with the table of contents(TOC) of pnor flash. This code is shared by HB
+//with the bootloader code (/src/bootloader) so traces can be tricky,
+//use the PNOR_UTIL macros to record logs.
+/************************************************************************/
+
+#include "pnor_utils.H"
+#include <pnor/pnor_const.H>
+
+#if !defined(__BOOT_LOADER_H)
+#include <errl/errlmanager.H>
+extern trace_desc_t* g_trac_pnor;
+#define PNOR_UTIL_TRACE(arg0, args...) TRACFCOMP(g_trac_pnor, args)
+#define PNOR_UTIL_TRACE_W_BRK(arg0, args...) TRACFCOMP(g_trac_pnor, args)
+#else
+#include <bootloader/bootloader_trace.H>
+#define PNOR_UTIL_TRACE(arg0, args...) BOOTLOADER_TRACE(arg0)
+#define PNOR_UTIL_TRACE_W_BRK(arg0, args...) BOOTLOADER_TRACE_W_BRK(arg0)
+#endif
+
+
+#include "common/ffs_hb.H"
+#include <util/align.H>
+
+/**
+ * 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 */
+ "ATTR_TMP", /**< PNOR::ATTR_TMP : Temporary Attribute Overrides */
+ "ATTR_PERM", /**< PNOR::ATTR_PERM : Permanent Attribute Overrides */
+ "CAPP", /**< PNOR::CAPP : CAPP LID */
+ "VERSION", /**< PNOR::VERSION : PNOR Version string */
+ "HBBL", /**<PNOR::HB_BOOTLOADER : Hostboot Bootloader image */
+ "TEST", /**< PNOR::TEST : Test space for PNOR*/
+ "TESTRO", /**< PNOR::TESTRO : ReadOnly Test space for PNOR */
+ "BACKUP_PART", /**PNOR::BACKUP_PART : Backup of PART*/
+};
+
+/**
+ * @brief calculates the checksum on data(ffs header/entry) and will return
+ * 0 if the checksums match
+ */
+uint32_t PNOR::pnor_ffs_checksum(void* i_data, size_t i_size)
+{
+ uint32_t checksum = 0;
+ for (size_t i = 0; i < (i_size/4); i++)
+ {
+ checksum ^= ((uint32_t*)i_data)[i];
+ }
+ checksum = htobe32(checksum);
+
+ return checksum;
+}
+
+//RTC: 147939 Refactor Local Memset
+void * localMemset(void *i_dest, int8_t i_value, uint8_t i_size)
+{
+ unsigned char *buf = (unsigned char *)i_dest;
+ while (i_size--)
+ {
+ *(buf++) = (unsigned char)i_value;
+ }
+ return i_dest;
+}
+
+/**
+* @brief Set up some initial information about the sections of the TOC.
+* The section's ID and flashAddr are set to specific values while
+* the rest of the data for the struct is set to 0.
+*/
+void PNOR::initializeSections(PNOR::SectionData_t io_toc[NUM_SECTIONS])
+{
+ for( size_t id = PNOR::FIRST_SECTION;
+ id <= PNOR::NUM_SECTIONS; //include extra entry for error paths
+ ++id )
+ {
+ localMemset(&io_toc[id], 0, sizeof(io_toc[id]));
+
+ //Set the id to be the name corresponding to this section
+ io_toc[id].id = (PNOR::SectionId)id;
+
+ //All sections are initially set to INVALID_FLASH_OFFSET
+ //this is large value that is not in the valid addressing range.
+ //We chose a large value instead of 0 because the first section
+ //has a flash addr of 0 and we want to avoid confusion.
+ io_toc[id].flashAddr = INVALID_FLASH_OFFSET;
+
+ }
+}
+
+
+
+/**
+ * @brief Ensure the buffer is not NULL, if it is, then return
+ * the appropriate err code from the o_errCode param.
+ * if the buffer is not NULL then cast it to a ffs_hdr
+ * and return that out through the respective o_param
+ */
+void PNOR::checkForNullBuffer(uint8_t* i_tocBuffer,
+ uint32_t& o_errCode,
+ ffs_hdr*& o_ffs_hdr)
+{
+ if(!i_tocBuffer)
+ {
+ o_errCode |= BUFF_IS_NULL;
+ o_ffs_hdr = NULL;
+ }
+ else
+ {
+ o_ffs_hdr = (ffs_hdr*)i_tocBuffer;
+ }
+}
+
+
+/**
+ * @brief Perform a series of checks on the header of the table of contents
+ * These checks include: looking for valid magic #, valid block size,
+ * valid block count, valid entry size, valid entry count, version and
+ * total size.
+ *
+ */
+void PNOR::checkHeader (ffs_hdr* i_ffs_hdr,
+ uint32_t& io_errCode)
+{
+ uint64_t spaceUsed = (sizeof(ffs_entry))*i_ffs_hdr->entry_count;
+
+ // Checking FFS Header to make sure it looks valid
+ // Not breaking after one error, want to collect them all
+ if(i_ffs_hdr->magic != FFS_MAGIC)
+ {
+ PNOR_UTIL_TRACE_W_BRK(BTLDR_TRC_UTILS_CHECKHEADER_MAGIC,
+ "E>PNOR::parseTOC: Invalid magic"
+ " number in FFS header: 0x%.4X",i_ffs_hdr->magic);
+ io_errCode |= INVALID_MAGIC;
+ }
+ if(i_ffs_hdr->version != SUPPORTED_FFS_VERSION)
+ {
+ PNOR_UTIL_TRACE_W_BRK(BTLDR_TRC_UTILS_CHECKHEADER_VERSION,
+ "E>PNOR::parseTOC:Unsupported FFS"
+ " Header version: 0x%.4X", i_ffs_hdr->version);
+ io_errCode |= UNSUPPORTED_FFS;
+ }
+ if(i_ffs_hdr->entry_size != sizeof(ffs_entry))
+ {
+ PNOR_UTIL_TRACE_W_BRK(BTLDR_TRC_UTILS_CHECKHEADER_ENTRYSIZE,
+ "E>PNOR::parseTOC: Unexpected"
+ " entry_size(0x%.8x) in FFS header: 0x%.4X",
+ i_ffs_hdr->entry_size);
+ io_errCode |= INVALID_ENTRY_SIZE;
+ }
+ if(i_ffs_hdr->entry_count == 0)
+ {
+ PNOR_UTIL_TRACE_W_BRK(BTLDR_TRC_UTILS_CHECKHEADER_ENTRYCNT,
+ "E>PNOR::parseTOC:"
+ " FFS Header pointer to entries is NULL.");
+ io_errCode |= NO_ENTRIES;
+ }
+ if(i_ffs_hdr->block_size != PAGESIZE)
+ {
+ PNOR_UTIL_TRACE_W_BRK(BTLDR_TRC_UTILS_CHECKHEADER_BLOCKSIZE,
+ "E>PNOR::parseTOC: Unsupported"
+ " Block Size(0x%.4X). PNOR Blocks must be 4k",
+ i_ffs_hdr->block_size);
+ io_errCode |= INVALID_BLOCK_SIZE;
+ }
+ if(i_ffs_hdr->block_count == 0)
+ {
+ PNOR_UTIL_TRACE_W_BRK(BTLDR_TRC_UTILS_CHECKHEADER_BLOCKCNT,
+ "E>PNOR::parseTOC: Unsupported"
+ " Block COunt(0x%.4X). Device cannot be zero"
+ " blocks in length.",i_ffs_hdr->block_count);
+ io_errCode |= INVALID_BLOCK_COUNT;
+ }
+ //Make sure all the entries fit in specified partition
+ //table size
+ if(spaceUsed >
+ ((i_ffs_hdr->block_size*i_ffs_hdr->size)-sizeof(ffs_hdr)))
+ {
+ PNOR_UTIL_TRACE_W_BRK(BTLDR_TRC_UTILS_CHECKHEADER_HDRSIZE,
+ "E>PNOR::parseTOC: FFS Entries"
+ " (0x%.16X) go past end of FFS Table.",spaceUsed);
+ io_errCode |= INVALID_HEADER_SIZE;
+
+ }
+ if(io_errCode != NO_ERROR)
+ {
+ io_errCode |= HEADER_ERR;
+ }
+}
+
+/**
+ * @brief Takes in an ffs_entry and returns the enum version of the section
+ * title.
+ */
+void PNOR::getSectionEnum (ffs_entry* i_entry,
+ uint32_t* o_secId)
+{
+ *o_secId = PNOR::INVALID_SECTION;
+ //Figure out section enum
+ for(uint32_t eyeIndex=PNOR::TOC;eyeIndex<PNOR::NUM_SECTIONS;
+ eyeIndex++)
+ {
+ if(strcmp(cv_EYECATCHER[eyeIndex],i_entry->name) == 0)
+ {
+ *o_secId = eyeIndex;
+ break;
+ }
+ }
+}
+
+/**
+ * @brief Iterate through the entries, each which represent a section in pnor.
+ * During the iteration we are checking that the entries are valid
+ * and we set the sectionData_t for each section in the TOC.
+ */
+void PNOR::parseEntries (ffs_hdr* i_ffs_hdr,
+ uint32_t& io_errCode,
+ SectionData_t *& io_TOC,
+ ffs_entry*& o_err_entry)
+{
+ //Walk through all the entries in the table and parse the data.
+ for(uint32_t i=0; i<i_ffs_hdr->entry_count; i++)
+ {
+ ffs_entry* cur_entry = (&i_ffs_hdr->entries[i]);
+ uint32_t secId = PNOR::INVALID_SECTION;
+
+ // ffs entry check, 0 if checksums match
+ if( PNOR::pnor_ffs_checksum(cur_entry, FFS_ENTRY_SIZE) != 0)
+ {
+ PNOR_UTIL_TRACE_W_BRK(BTLDR_TRC_UTILS_PARSE_CHECKSUM_ERROR,
+ "E>PNOR::parseTOC: "
+ "Check sum error while parseing entry ",
+ "%d in TOC", i);
+ io_errCode |= ENTRY_ERR;
+ io_errCode |= ENTRY_CHECKSUM_ERR;
+ //note the entry we failed on
+ o_err_entry = cur_entry;
+ //break beacuse we are going to waste time checking other entries
+ break;
+ }
+ //Figure out section enum
+ getSectionEnum(cur_entry, &secId);
+
+ if(secId == PNOR::INVALID_SECTION)
+ {
+ PNOR_UTIL_TRACE(BTLDR_TRC_UTILS_PARSE_INVALID_SECTION,
+ "PNOR::parseTOC: "
+ "Unsupported section found while parsing entry ",
+ "%d in TOC \n Entry name is \"%s\"", i,
+ cur_entry->name);
+ //continue to skip invalid section
+ continue;
+ }
+ ffs_hb_user_t* ffsUserData = NULL;
+ ffsUserData = (ffs_hb_user_t*)&(cur_entry->user);
+
+ //size
+ io_TOC[secId].size =
+ ((uint64_t)cur_entry->size)*(i_ffs_hdr->block_size);
+
+ //flashAddr
+ io_TOC[secId].flashAddr=
+ ((uint64_t)cur_entry->base)*(i_ffs_hdr->block_size);
+
+ //chipSelect
+ io_TOC[secId].chip = ffsUserData->chip;
+
+ //user data
+ io_TOC[secId].integrity = ffsUserData->dataInteg;
+ io_TOC[secId].version = ffsUserData->verCheck;
+ io_TOC[secId].misc = ffsUserData->miscFlags;
+ if((io_TOC[secId].flashAddr + io_TOC[secId].size) >
+ (i_ffs_hdr->block_count*PAGESIZE))
+ {
+ PNOR_UTIL_TRACE_W_BRK(BTLDR_TRC_UTILS_PARSE_EXCEEDS_FLASH,
+ "E>PNOR::parseTOC: "
+ "Exceeded flash while parsing entry ",
+ "%d in TOC \n Entry name is \"%s\"", i,
+ cur_entry->name);
+ io_errCode |= ENTRY_ERR;
+ io_errCode |= ENTRY_EXTENDS_BEYOND_FLASH;
+ //note the entry we failed on
+ o_err_entry = cur_entry;
+ break;
+ }
+
+ if (io_TOC[secId].integrity == FFS_INTEG_ECC_PROTECT)
+ {
+ io_TOC[secId].size = ALIGN_PAGE_DOWN
+ ((io_TOC[secId].size * 8 ) / 9);
+ }
+
+ // TODO RTC:96009 handle version header w/secureboot
+ if (io_TOC[secId].version == FFS_VERS_SHA512)
+ {
+ //increment flash addr for sha header
+ if (io_TOC[secId].integrity == FFS_INTEG_ECC_PROTECT)
+ {
+ io_TOC[secId].flashAddr += PAGESIZE_PLUS_ECC ;
+ }
+ else
+ {
+ io_TOC[secId].flashAddr += PAGESIZE ;
+ }
+ io_TOC[secId].size -= PAGESIZE;
+ }
+
+ } // For TOC Entries
+}
+
+
+
diff --git a/src/usr/pnor/pnor_utils.H b/src/usr/pnor/pnor_utils.H
new file mode 100644
index 000000000..e0027d349
--- /dev/null
+++ b/src/usr/pnor/pnor_utils.H
@@ -0,0 +1,224 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/pnor_utils.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
+/* [+] 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 PNOR_UTILS_H
+#define PNOR_UTILS_H
+
+#include <pnor/pnor_const.H>
+#include "limits.h"
+#include "ffs.h"
+
+
+/** @file pnor_utils.H
+ * @brief Provides the utility functions used by different PNOR
+ * classes.
+ */
+
+namespace PNOR
+{
+
+
+// Simple enum of TOC's per PNOR side
+enum TOCS
+{
+ TOC_0 = 0,
+ TOC_1 = 1,
+ NUM_TOCS,
+};
+
+
+enum
+{
+ /** 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 */
+ TOC_SIZE = 0x8000,
+};
+
+
+/**
+* These error codes represent all the errors that can arise while
+* parsing the table of contents for pnor flash. Note that they
+* can be mixed up together.
+* (example 0x30000001 is a invalid header with a bad magic number)
+*/
+
+enum pnorUtilErrorCodes
+{
+ NO_ERROR = 0x00000000,
+ INVALID_MAGIC = 0x00000001,
+ UNSUPPORTED_FFS = 0x00000002,
+ INVALID_ENTRY_SIZE = 0x00000004,
+ NO_ENTRIES = 0x00000008,
+ INVALID_BLOCK_SIZE = 0x00000010,
+ INVALID_BLOCK_COUNT = 0x00000020,
+ INVALID_HEADER_SIZE = 0x00000040,
+ ENTRY_CHECKSUM_ERR = 0x00000080,
+ ENTRY_EXTENDS_BEYOND_FLASH = 0x00000100,
+ BUFF_IS_NULL = 0x00000200,
+ CHECKSUM_ERR = 0x00000400,
+ HEADER_ERR = 0x00000800,
+ ENTRY_ERR = 0x00001000,
+ NO_HBB_SECTION = 0x00002000,
+};
+
+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 = PNOR::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,
+};
+
+
+
+/**
+ * Internal information to deal with the sections of PNOR
+ */
+struct SectionData_t {
+ PNOR::SectionId id; /**< Identifier for this section */
+ uint64_t virtAddr; /**< Virtual address for the start of the section */
+ uint32_t flashAddr; /**< Address in flash */
+ uint32_t size;/**< Actual size of content in bytes (not including ECC)*/
+ uint8_t chip; /**< Chip Select */
+ uint8_t version; /**< Version Checking */
+ uint16_t integrity; /**< Data Integrity */
+ uint8_t misc; /**< Misc Flags */
+} PACKED;
+
+/**
+ * @brief Creates a 4-byte Cyclic Redundancy Check (CRC) on the data
+ * provided. The last iteration of the for-loop includes the ffs
+ * checksum itself. Therefore if the 4-byte CRC created matches
+ * the ffs checksum, the resulting CRC will be 0
+ *
+ * @param[in] i_data Pointer to the data
+ *
+ * @param[in] i_size Size of the data
+ *
+ * @return uint32_t return 4-byte CRC, 0 if checksums match
+ */
+uint32_t pnor_ffs_checksum(void* i_data,
+ size_t i_size);
+
+/**
+ * @brief Initialize each section by giving it an id and setting
+ * its initial flashAddr to be the INVALID_FLASH_OFFSET value
+ *
+ * @param[in/out] io_toc TOC that we want to initialize
+ *
+ * @return void
+ */
+void initializeSections(SectionData_t io_toc[NUM_SECTIONS]);
+
+
+/**
+ * @brief Ensure the buffer is not NULL, if it is, then return
+ * the appropriate err code from the o_errCode param.
+ * if the buffer is not NULL then cast it to a ffs_hdr
+ * and return that out through the respective o_param
+ *
+ * @param[in] i_tocBuffer Buffer holding subsection of pnor flash
+ * believed to hold a copy of the table of contents
+ *
+ * @param[out] o_errCode Error code to inform the caller that the
+ * buffer is null
+ *
+ * @param[out] o_ffs_hdr version of the original input buffer
+ * casted as an ffs_hdr
+ */
+void checkForNullBuffer(uint8_t* i_tocBuffer,
+ uint32_t& o_errCode,
+ ffs_hdr*& );
+
+
+/**
+ * @brief Perform a series of checks on the header of the table of contents
+ * These checks include: looking for valid magic #, valid block size,
+ * valid block count, valid entry size, valid entry count, version and
+ * total size.
+ *
+ * @param[in] i_ffs_hdr struct containing information about the hdr
+ * of the table of contents of pnor flash
+ *
+ * @param[out] io_errCode Error code to inform the caller that
+ * the checks on the hdr failed. A single error code
+ * can describe multiple errors, so this function DOES
+ * NOT quit after the first error it finds.
+ *
+*/
+void checkHeader (ffs_hdr* i_ffs_hdr,
+ uint32_t& io_errCode);
+
+/**
+ * @brief Takes in an ffs_entry and returns the enum version of the section
+ * title.
+ *
+ * @param[in] i_entry struct containing information about an entry
+ * coming from pnor flash's table of contents
+ *
+ * @param[out] o_secId This number represents a section name in the
+ * enums found in include/usr/pnor/pnor_const.H
+ *
+*/
+void getSectionEnum (ffs_entry* i_entry,
+ uint32_t* o_secId);
+/**
+ * @brief Iterate through the entries, each which represent a section in pnor.
+ * During the iteration we are checking that the entries are valid
+ * and we set the sectionData_t for each section in the TOC.
+ *
+ * @param[in] i_ffs_hdr struct containing information about the hdr
+ * of the table of contents of pnor flash
+ *
+ * @param[out] io_errCode Error code to inform the caller that
+ * the check on the entries in TOC failed
+ *
+ * @param[in/out] io_TOC Array of section data that make up the TOC
+ * of pnor flash.
+ *
+ * @param[out] o_err_entry Pass out bad entry so user can know which
+ * entry has errors
+ *
+*/
+void parseEntries (ffs_hdr* i_ffs_hdr,
+ uint32_t& io_errCode,
+ SectionData_t*& io_TOC,
+ ffs_entry*& o_err_entry);
+
+} // End namespace PNOR
+
+
+#endif \ No newline at end of file
diff --git a/src/usr/pnor/pnordd.H b/src/usr/pnor/pnordd.H
index 94c393b76..437a0c10e 100644
--- a/src/usr/pnor/pnordd.H
+++ b/src/usr/pnor/pnordd.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -141,10 +141,6 @@ class PnorDD
* @brief Some general constants
*/
enum {
- LPCHC_FW_SPACE = 0xF0000000, /**< LPC Host Controller FW Space */
- LPCHC_MEM_SPACE = 0xE0000000, /**< LPC Host Controller Mem Space */
- LPCHC_IO_SPACE = 0xD0010000, /**< LPC Host Controller I/O Space */
- LPCHC_REG_SPACE = 0xC0012000, /**< LPC Host Ctlr Register Space */
LPC_SFC_CMDREG_OFFSET = 0xF0000C00, /** LPC Offest to SFC Cmd Regs */
LPC_SFC_CMDBUF_OFFSET = 0xF0000D00, /** LPC Off to SFC Cmd Buf space */
diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C
index ef47de7c4..b2b67a86d 100644
--- a/src/usr/pnor/pnorrp.C
+++ b/src/usr/pnor/pnorrp.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -296,7 +296,7 @@ void PnorRP::initDaemon()
TRACFCOMP(g_trac_pnor, ERR_MRK"PnorRP::initDaemon: Failed to readTOC");
break;
}
- l_errhdl = PnorRP::setSideInfo ();
+ l_errhdl = setSideInfo ();
if(l_errhdl)
{
TRACFCOMP(g_trac_pnor, "PnorRP::initDaemon> setSideInfo failed");
@@ -716,6 +716,7 @@ errlHndl_t PnorRP::readTOC()
{
TRACUCOMP(g_trac_pnor, "PnorRP::readTOC>" );
errlHndl_t l_errhdl = NULL;
+ errlHndl_t l_secondary_errhdl = NULL;
uint8_t* toc0Buffer = new uint8_t[PAGESIZE];
uint8_t* toc1Buffer = new uint8_t[PAGESIZE];
uint64_t fatal_error = 0;
@@ -748,14 +749,56 @@ errlHndl_t PnorRP::readTOC()
}
}
- l_errhdl = PNOR::parseTOC(toc0Buffer, toc1Buffer, iv_TOC_used, iv_TOC,
- BASE_VADDR);
- if (l_errhdl)
+ //In order to track errors we will always parse both TOCs
+ l_errhdl = PNOR::parseTOC(toc0Buffer, iv_TOC);
+ PNOR::SectionData_t l_secondary_TOC[PNOR::NUM_SECTIONS+1];
+ l_secondary_errhdl = PNOR::parseTOC(toc1Buffer, l_secondary_TOC);
+
+ //If there is no error in the primary TOC
+ if(!l_errhdl)
{
- TRACFCOMP(g_trac_pnor, "readTOC: parseTOC failed");
+ //Then we use the primary TOC
+ iv_TOC_used = TOC_0;
+ //If we found an error in the secondary TOC
+ if(l_secondary_errhdl)
+ {
+ //@TODO RTC:144079 Try to fix PNOR for detected TOC failures
+ //Set the error severity to INFORMATIONAL and commit it
+ l_secondary_errhdl->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL);
+ errlCommit(l_secondary_errhdl, PNOR_COMP_ID);
+ }
+ }
+ //Otherwise if the secondary TOC has no error
+ else if(!l_secondary_errhdl)
+ {
+ //then we will use the secondary TOC instead
+ iv_TOC_used = TOC_1;
+ memcpy(iv_TOC, l_secondary_TOC, (sizeof(l_secondary_TOC)));
+ //Set the error severity to INFORMATIONAL for the primaryTOC error
+ // and commit it
+ //@TODO RTC:144079: Try to fix PNOR for detected TOC failures
+ l_errhdl->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL);
+ errlCommit(l_errhdl, PNOR_COMP_ID);
+ }
+ //In the case that both TOCs, have errors shut down the system
+ else
+ {
+ //commit both error logs for each corrupted TOC
+ l_errhdl->setSev(ERRORLOG::ERRL_SEV_UNRECOVERABLE);
errlCommit(l_errhdl, PNOR_COMP_ID);
+ l_secondary_errhdl->setSev(ERRORLOG::ERRL_SEV_UNRECOVERABLE);
+ errlCommit(l_secondary_errhdl, PNOR_COMP_ID);
+ TRACFCOMP(g_trac_pnor, "readTOC: parseTOC failed");
+ //With invalid pnor we cannot do anything, time to shut down
INITSERVICE::doShutdown(PNOR::RC_PARTITION_TABLE_INVALID);
}
+
+ l_errhdl = setVirtAddrs();
+ if (l_errhdl)
+ {
+ TRACFCOMP(g_trac_pnor, "readTOC: Failed to set vaddr in TOC");
+ INITSERVICE::doShutdown(PNOR::RC_PNOR_SET_VADDR_FAILED);
+ }
} while (0);
if(toc0Buffer != NULL)
@@ -1476,3 +1519,100 @@ uint64_t PnorRP::getTocOffset(TOCS i_toc) const
return (i_toc == TOC_0) ? iv_TocOffset[WORKING].first :
iv_TocOffset[WORKING].second;
}
+
+errlHndl_t PnorRP::setVirtAddrs(void)
+{
+ errlHndl_t l_errhdl = NULL;
+ //Start out with the "next v addr" being the base of pnor
+ //(this will increment in the loop below)
+ uint64_t l_next_vAddr = BASE_VADDR;
+
+ //Loop through each section in the TOC Buffer
+ for(uint32_t i=0; i<PNOR::NUM_SECTIONS; i++)
+ {
+
+ if(iv_TOC[i].flashAddr == INVALID_FLASH_OFFSET)
+ {
+ //all flashAddrs are initialized to INVALID_FLASH_OFFSET
+ //if the section's flashAddr does not get set, it doesnt exist
+ // in this TOC
+ continue;
+ }
+ //Set virtAddr for the current section
+ iv_TOC[i].virtAddr = l_next_vAddr;
+ l_next_vAddr += iv_TOC[i].size;
+
+ // Handle section permissions
+ if (iv_TOC[i].misc & FFS_MISC_READ_ONLY)
+ {
+ // Need to set permissions to allow writing to virtual
+ // addresses, but prevents the kernel from ejecting
+ // dirty pages (no WRITE_TRACKED).
+ int rc = mm_set_permission(
+ (void*)iv_TOC[i].virtAddr,
+ iv_TOC[i].size,
+ WRITABLE);
+ if (rc)
+ {
+ TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC: Failed to set block permissions to WRITABLE for section %s.",
+ cv_EYECATCHER[i]);
+ /*@
+ * @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,
+ i,
+ iv_TOC[i].virtAddr,
+ true /*Add HB SW Callout*/);
+ l_errhdl->collectTrace(PNOR_COMP_NAME);
+ break;
+ }
+ }
+ else
+ {
+ // Need to set permissions to R/W
+ int rc = mm_set_permission(
+ (void*)iv_TOC[i].virtAddr,
+ iv_TOC[i].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[i]);
+ /*@
+ * @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,
+ i,
+ iv_TOC[i].virtAddr,
+ true /*Add HB SW Callout*/);
+ l_errhdl->collectTrace(PNOR_COMP_NAME);
+ break;
+ }
+ }
+ }
+
+ return l_errhdl;
+}
diff --git a/src/usr/pnor/pnorrp.H b/src/usr/pnor/pnorrp.H
index d6cefdd60..582ad77af 100644
--- a/src/usr/pnor/pnorrp.H
+++ b/src/usr/pnor/pnorrp.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -214,6 +214,13 @@ class PnorRP
void waitForMessage();
/**
+ * @brief Set the virtual addresses in the iv_TOC
+ *
+ * @return Any errors found while setting Virtual Addresses
+ */
+ errlHndl_t setVirtAddrs(void);
+
+ /**
* @brief Retrieve 1 logical page of data from the PNOR device
*
* @param[in] i_offset Offset into PNOR chip
diff --git a/src/usr/pnor/runtime/makefile b/src/usr/pnor/runtime/makefile
index 0556af9e4..708d39abb 100644
--- a/src/usr/pnor/runtime/makefile
+++ b/src/usr/pnor/runtime/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2014,2015
+# Contributors Listed Below - COPYRIGHT 2014,2016
# [+] International Business Machines Corp.
#
#
@@ -27,6 +27,7 @@ ROOTPATH = ../../../..
MODULE = pnor_rt
OBJS += rt_pnor.o
+OBJS += pnor_utils.o
OBJS += pnor_common.o
OBJS += ecc.o
diff --git a/src/usr/pnor/runtime/rt_pnor.C b/src/usr/pnor/runtime/rt_pnor.C
index 28281f4b2..33c1a2439 100644
--- a/src/usr/pnor/runtime/rt_pnor.C
+++ b/src/usr/pnor/runtime/rt_pnor.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* Contributors Listed Below - COPYRIGHT 2014,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -652,11 +652,10 @@ errlHndl_t RtPnor::readTOC ()
break;
}
- // 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);
+ //Pass along TOC buffer to be parsed, parseTOC will parse through
+ // the buffer and store needed information in iv_TOC
+ // Note: that Opal should always return a valid TOC
+ l_err = PNOR::parseTOC(l_toc0Buffer, iv_TOC);
if (l_err)
{
TRACFCOMP(g_trac_pnor, "RtPnor::readTOC: parseTOC failed");
diff --git a/src/usr/pnor/runtime/test/makefile b/src/usr/pnor/runtime/test/makefile
index e53d87f15..70c7d5276 100644
--- a/src/usr/pnor/runtime/test/makefile
+++ b/src/usr/pnor/runtime/test/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2014,2015
+# Contributors Listed Below - COPYRIGHT 2014,2016
# [+] International Business Machines Corp.
#
#
diff --git a/src/usr/pnor/runtime/test/testpnor_rt.H b/src/usr/pnor/runtime/test/testpnor_rt.H
index 5a81ea9ac..a1a8777e4 100644
--- a/src/usr/pnor/runtime/test/testpnor_rt.H
+++ b/src/usr/pnor/runtime/test/testpnor_rt.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* Contributors Listed Below - COPYRIGHT 2014,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -162,7 +162,6 @@ class PnorRtTest : public CxxTest::TestSuite
TS_FAIL("PnorRtTest::testTOC: writeToDevice failed");
}
}
-
delete tocHeader;
delete tocEntry;
delete corruptBuffer;
diff --git a/src/usr/pnor/test/makefile b/src/usr/pnor/test/makefile
index 35af02afc..098ea84a9 100644
--- a/src/usr/pnor/test/makefile
+++ b/src/usr/pnor/test/makefile
@@ -25,11 +25,11 @@
# IBM_PROLOG_END_TAG
ROOTPATH = ../../../..
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pnor/
+
MODULE = testpnor
-TESTS = pnorddtest.H
-TESTS += ecctest.H
-TESTS += pnorrptest.H
+TESTS = pnorddtest.H ecctest.H pnorrptest.H pnorutilsTest.H
#SFC Implementations
TESTS += $(if $(CONFIG_SFC_IS_IBM_DPSS),sfc_ibmtest.H)
diff --git a/src/usr/pnor/test/pnorUtilsTestResources.H b/src/usr/pnor/test/pnorUtilsTestResources.H
new file mode 100644
index 000000000..5cab8f227
--- /dev/null
+++ b/src/usr/pnor/test/pnorUtilsTestResources.H
@@ -0,0 +1,56 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/test/pnorUtilsTestResources.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2016 */
+/* [+] 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 BOOTLOADERTESTRESOURCES_H
+#define BOOTLOADERTESTRESOURCES_H
+
+//This data is used to test some of the parsing code that handles
+// the Table of Contents of PNOR flash. Do not modify this data
+// unless you are working with the pnor parsing test cases.
+static uint8_t testTOC[] =
+{0x50, 0x41, 0x52, 0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x41, 0x02, 0xC6,
+0x70, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
+0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x9E, 0x9D, 0x89,
+0x48, 0x42, 0x45, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xBF, 0x7A, 0x84,
+};
+
+
+#endif
diff --git a/src/usr/pnor/test/pnorddtest.H b/src/usr/pnor/test/pnorddtest.H
index 3a38e88a6..3cf3ef350 100644
--- a/src/usr/pnor/test/pnorddtest.H
+++ b/src/usr/pnor/test/pnorddtest.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -133,9 +133,48 @@ class PnorDdTest : public CxxTest::TestSuite
break;
}
+ // Perform PnorDD read 1
+ uint64_t l_address =
+ base_address + PNOR::pnorTestSec_readwrite_offset;
+ uint64_t l_readData = 0;
+ l_size = sizeof(uint64_t);
+ l_err = deviceRead(l_testTarget,
+ &l_readData,
+ l_size,
+ DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_readwrite: PNORDD read 1: deviceRead() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+
+ TRACFCOMP(g_trac_pnor, "Original value in read 1: %lx", l_readData);
+
+ // Perform PnorDD read 2
+ l_address = base_address + PNOR::pnorTestSec_readwrite_offset + 0x8;
+ l_size = sizeof(uint64_t);
+ l_err = deviceRead(l_testTarget,
+ &l_readData,
+ l_size,
+ DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_readwrite: PNORDD read 2: deviceRead() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+
+ TRACFCOMP(g_trac_pnor, "Original value in read 2: %lx", l_readData);
+
+
// Perform PnorDD Write 1
- uint64_t l_address = base_address +
+ l_address = base_address +
PNOR::pnorTestSec_readwrite_offset;
uint64_t l_writeData = 0x12345678FEEDB0B0;
l_size = sizeof(uint64_t);
@@ -183,7 +222,7 @@ class PnorDdTest : public CxxTest::TestSuite
// Perform PnorDD read 1
l_address = base_address + PNOR::pnorTestSec_readwrite_offset;
- uint64_t l_readData = 0;
+ l_readData = 0;
l_size = sizeof(uint64_t);
l_err = deviceRead(l_testTarget,
&l_readData,
diff --git a/src/usr/pnor/test/pnorutilsTest.H b/src/usr/pnor/test/pnorutilsTest.H
new file mode 100644
index 000000000..937d59b85
--- /dev/null
+++ b/src/usr/pnor/test/pnorutilsTest.H
@@ -0,0 +1,341 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/test/pnorutilsTest.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2016 */
+/* [+] 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 PNORUTILSTEST_H
+#define PNORUTILSTEST_H
+
+#include <cxxtest/TestSuite.H>
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include "pnorUtilsTestResources.H"
+#include <usr/vmmconst.h>
+#include <pnor/pnor_const.H>
+#include <pnor/pnorif.H>
+#include <pnor_utils.H>
+
+/**
+ * @file pnorutilsTest.H
+ *
+ * @brief unit tests for pnor utils
+*/
+extern const char* cv_EYECATCHER[];
+extern trace_desc_t* g_trac_pnor;
+class pnorutilsTest : public CxxTest::TestSuite
+{
+ public:
+
+
+ void test_invalidMagicWord(void)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidMagicWord: starting");
+
+ uint8_t l_tocBuffer[PNOR::TOC_SIZE];
+ uint32_t l_errCode = 0;
+ bool l_failed = false;
+ memcpy(l_tocBuffer, testTOC, sizeof(testTOC));
+
+ //mess up the magic word while maintaining checksum
+ l_tocBuffer[0] = 0;
+ l_tocBuffer[1] = 0;
+ l_tocBuffer[16] = 0x50;
+ l_tocBuffer[17] = 0x41;
+
+ ffs_hdr* l_ffs_hdr = NULL;
+ PNOR::checkForNullBuffer(l_tocBuffer, l_errCode, l_ffs_hdr);
+ PNOR::checkHeader(l_ffs_hdr, l_errCode);
+
+ if((l_errCode & PNOR::INVALID_MAGIC) == PNOR::INVALID_MAGIC)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidMagicWord: Successfully found error with magic number");
+ }
+ else
+ {
+ TS_FAIL("pnorutilsTest::test_invalidMagicWord: Failed to find error with magic word ERR CODE: 0x%x", l_errCode);
+ l_failed = true;
+ }
+
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidMagicWord: complete, Failed = %d", l_failed);
+ }
+
+ void test_invalidFFSVersion(void)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidFFSVersion: starting");
+ uint8_t l_tocBuffer[PNOR::TOC_SIZE];
+ uint32_t l_errCode = 0;
+ bool l_failed = false;
+
+ memcpy(l_tocBuffer, testTOC, sizeof(testTOC));
+
+ //mess up the FFS version while maintaining checksum
+ l_tocBuffer[23] = 0x1;
+ l_tocBuffer[7] = 0x0;
+
+ ffs_hdr* l_ffs_hdr = NULL;
+ PNOR::checkForNullBuffer(l_tocBuffer, l_errCode, l_ffs_hdr);
+ PNOR::checkHeader(l_ffs_hdr, l_errCode);
+
+
+ if((l_errCode & PNOR::UNSUPPORTED_FFS) == PNOR::UNSUPPORTED_FFS)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidFFSVersion: Successfully found error with version");
+ }
+ else
+ {
+ TS_FAIL("pnorutilsTest::test_invalidFFSVersion: failed to find error with version. ERR CODE: 0x%x", l_errCode);
+ l_failed = true;
+ }
+
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidFFSVersion: complete, Failed = %d", l_failed);
+ }
+
+ void test_invalidEntrySize(void)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidEntrySize: starting");
+ uint8_t l_tocBuffer[PNOR::TOC_SIZE];
+ uint32_t l_errCode = 0;
+ bool l_failed = false;
+ memcpy(l_tocBuffer, testTOC, sizeof(testTOC));
+
+ //Make the entry size 0 while maintaining checksum
+ l_tocBuffer[15] = 0x0;
+ l_tocBuffer[31] = 0x80;
+
+ ffs_hdr* l_ffs_hdr = NULL;
+ PNOR::checkForNullBuffer(l_tocBuffer, l_errCode, l_ffs_hdr);
+ PNOR::checkHeader(l_ffs_hdr, l_errCode);
+
+
+ if((l_errCode & PNOR::INVALID_ENTRY_SIZE)
+ == PNOR::INVALID_ENTRY_SIZE)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidEntrySize: Successfully found error with entry size");
+ }
+ else
+ {
+ TS_FAIL("pnorutilsTest::test_invalidEntrySize: failed to find error with entry size. ERR CODE: 0x%x", l_errCode);
+ l_failed = true;
+ }
+
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidEntrySize: complete, Failed = %d", l_failed);
+ }
+
+ void test_invalidEntryCount(void)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidEntryCount: starting");
+ uint8_t l_tocBuffer[PNOR::TOC_SIZE];
+ uint32_t l_errCode = 0;
+ bool l_failed = false;
+ memcpy(l_tocBuffer, testTOC, sizeof(testTOC));
+
+ //make the entry count 0 while maintaining checksum
+ l_tocBuffer[19] = 0x00;
+ l_tocBuffer[35] = 0x12;
+
+ ffs_hdr* l_ffs_hdr = NULL;
+ PNOR::checkForNullBuffer(l_tocBuffer, l_errCode, l_ffs_hdr);
+ PNOR::checkHeader(l_ffs_hdr, l_errCode);
+
+
+ if((l_errCode & PNOR::NO_ENTRIES)== PNOR::NO_ENTRIES)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidEntryCount: Successfully found error with entry count");
+ }
+ else
+ {
+ TS_FAIL("pnorutilsTest::test_invalidEntryCount: Failed to find error with entry count. ERR CODE: 0x%x", l_errCode);
+ l_failed = true;
+ }
+
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidEntryCount: complete, Failed = %d", l_failed);
+ }
+
+ void test_invalidBlockSize(void)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidBlockSize: starting");
+ uint8_t l_tocBuffer[PNOR::TOC_SIZE];
+ uint32_t l_errCode = 0;
+ bool l_failed = false;
+ memcpy(l_tocBuffer, testTOC, sizeof(testTOC));
+
+ //make the block size 0 while maintaining checksum
+ l_tocBuffer[22] = 0x00;
+ l_tocBuffer[38] = 0x10;
+
+ ffs_hdr* l_ffs_hdr = NULL;
+ PNOR::checkForNullBuffer(l_tocBuffer, l_errCode, l_ffs_hdr);
+ PNOR::checkHeader(l_ffs_hdr, l_errCode);
+
+
+ if((l_errCode & PNOR::INVALID_BLOCK_SIZE) == PNOR::INVALID_BLOCK_SIZE)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidBlockSize: Successfully found error with block size");
+ }
+ else
+ {
+ TS_FAIL("pnorutilsTest::test_invalidBlockSize: Failed to find error with the block size. ERR CODE: 0x%x", l_errCode);
+ l_failed = true;
+ }
+
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidBlockSize: complete, Failed = %d", l_failed);
+ }
+
+ void test_invalidBlockCount(void)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidBlockCount: starting");
+ uint8_t l_tocBuffer[PNOR::TOC_SIZE];
+ uint32_t l_errCode = 0;
+ bool l_failed = false;
+ memcpy(l_tocBuffer, testTOC, sizeof(testTOC));
+
+ //make the block count 0 while maintaining checksum
+ l_tocBuffer[26] = 0x00;
+ l_tocBuffer[42] = 0x40;
+
+ ffs_hdr* l_ffs_hdr = NULL;
+ PNOR::checkForNullBuffer(l_tocBuffer, l_errCode, l_ffs_hdr);
+ PNOR::checkHeader(l_ffs_hdr, l_errCode);
+
+
+ if((l_errCode & PNOR::INVALID_BLOCK_COUNT)
+ == PNOR::INVALID_BLOCK_COUNT)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidBlockCount: Successfully found error with block count");
+ }
+ else
+ {
+ TS_FAIL("pnorutilsTest::test_invalidBlockCount: Failed to find error with block count. ERR CODE: 0x%x", l_errCode);
+ l_failed = true;
+ }
+
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidBlockCount: complete, Failed = %d", l_failed);
+ }
+
+ void test_invalidHdrSize(void)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidHdrSize: starting");
+ uint8_t l_tocBuffer[PNOR::TOC_SIZE];
+ uint32_t l_errCode = 0;
+ bool l_failed = false;
+ memcpy(l_tocBuffer, testTOC, sizeof(testTOC));
+
+ //Shrink block size to 51 while maintaining checksum
+ l_tocBuffer[22] = 0x00;
+ l_tocBuffer[38] = 0x10;
+ l_tocBuffer[23] = 0x33;
+ l_tocBuffer[39] = 0x33;
+
+ ffs_hdr* l_ffs_hdr = NULL;
+ PNOR::checkForNullBuffer(l_tocBuffer, l_errCode, l_ffs_hdr);
+ PNOR::checkHeader(l_ffs_hdr, l_errCode);
+
+
+ if((l_errCode & PNOR::INVALID_HEADER_SIZE)
+ == PNOR::INVALID_HEADER_SIZE)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidHdrSize: Successfully found error with hdr size");
+ }
+ else
+ {
+ TS_FAIL("pnorutilsTest::test_invalidHdrSize: Failed to find error with hdr size. ERR CODE: 0x%x", l_errCode);
+ l_failed = true;
+ }
+
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidHdrSize: complete, Failed = %d", l_failed);
+ }
+
+ void test_invalidEntryChecksum(void)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidEntryChecksum: starting");
+ uint8_t l_tocBuffer[PNOR::TOC_SIZE];
+ uint32_t l_errCode = 0;
+ bool l_failed = false;
+ memcpy(l_tocBuffer, testTOC, sizeof(testTOC));
+
+ //Mess up the checksum of an entry
+ l_tocBuffer[208] = 0xFF;
+ PNOR::SectionData_t * l_TOC;
+ ffs_hdr* l_ffs_hdr = NULL;
+ PNOR::checkForNullBuffer(l_tocBuffer, l_errCode, l_ffs_hdr);
+ PNOR::checkHeader(l_ffs_hdr, l_errCode);
+ //parse through the entries and check for any errors
+ ffs_entry* l_err_entry = NULL;
+ PNOR::parseEntries(l_ffs_hdr, l_errCode, l_TOC, l_err_entry);
+
+ if((l_errCode & PNOR::ENTRY_CHECKSUM_ERR)
+ == PNOR::ENTRY_CHECKSUM_ERR)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidEntryChecksum: Successfully found error with entry checksum");
+ }
+ else
+ {
+ TS_FAIL("pnorutilsTest::test_invalidEntryChecksum: Failed to find error the checksum for an entry. ERR CODE: 0x%x", l_errCode);
+ l_failed = true;
+ }
+
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_invalidEntryChecksum: complete, Failed = %d", l_failed);
+ }
+
+ void test_entryExtendsBeyondFlash(void)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_entryExtendsBeyondFlash: starting");
+ uint8_t l_tocBuffer[PNOR::TOC_SIZE];
+ uint32_t l_errCode = 0;
+ bool l_failed = false;
+ memcpy(l_tocBuffer, testTOC, sizeof(testTOC));
+
+ //make the block count 1
+ l_tocBuffer[26] = 0x01;
+ //make the size of the entry 0xFFFFFF24 (the 24 is in there)
+ l_tocBuffer[196] = 0xFF;
+ l_tocBuffer[197] = 0xFF;
+ l_tocBuffer[198] = 0xFF;
+ //Make sure you don't mess up the checksum
+ l_tocBuffer[212] = 0xFF;
+ l_tocBuffer[213] = 0xFF;
+ l_tocBuffer[214] = 0xFF;
+
+ PNOR::SectionData_t * l_TOC;
+ ffs_hdr* l_ffs_hdr = NULL;
+ PNOR::checkForNullBuffer(l_tocBuffer, l_errCode, l_ffs_hdr);
+ PNOR::checkHeader(l_ffs_hdr, l_errCode);
+ //parse through the entries and check for any errors
+ ffs_entry* l_err_entry = NULL;
+ PNOR::parseEntries(l_ffs_hdr, l_errCode, l_TOC, l_err_entry);
+
+ if((l_errCode & PNOR::ENTRY_EXTENDS_BEYOND_FLASH)
+ == PNOR::ENTRY_EXTENDS_BEYOND_FLASH)
+ {
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_entryExtendsBeyondFlash: Successfully found error with size of all entries");
+ }
+ else
+ {
+ TS_FAIL("pnorutilsTest::test_entryExtendsBeyondFlash: Failed to find error about entries extending beyond flash. ERR CODE: 0x%x", l_errCode);
+ l_failed = true;
+ }
+
+ TRACFCOMP(g_trac_pnor, "pnorutilsTest::test_entryExtendsBeyondFlash: complete, Failed = %d", l_failed);
+ }
+};
+
+#endif \ No newline at end of file
OpenPOWER on IntegriCloud