diff options
author | crgeddes <crgeddes@us.ibm.com> | 2015-08-26 13:50:30 -0500 |
---|---|---|
committer | William G. Hoffa <wghoffa@us.ibm.com> | 2016-03-03 16:17:52 -0500 |
commit | c73c1d03450fb1dfa0ef9c98485999aeaa0257d7 (patch) | |
tree | 70056c4a6b064db49d7419d2d5040f6569ea51fc | |
parent | 8f30c7db00a3ce2940900ec2ba67838bcf432b98 (diff) | |
download | talos-hostboot-c73c1d03450fb1dfa0ef9c98485999aeaa0257d7.tar.gz talos-hostboot-c73c1d03450fb1dfa0ef9c98485999aeaa0257d7.zip |
FFS Support for Bootloader
This commit moves functionality out of pnor_common.C and puts it in
a new file pnor_utils.C this file will be shared with bootloader and
hostboot code. Quite a few files were pulled apart in order to make
includes easier across modules. These are lpc_const.H and pnor_const.H.
bl_pnorAccess leverages the new pnor_utils.C file that will help the
bootloader parse pnor TOC
Change-Id: I740f6f8a707760756a261535e62e2d0a849324f8
RTC:134064
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/696
Tested-by: Jenkins Server
Reviewed-by: Martin Gloff <mgloff@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
-rw-r--r-- | src/bootloader/bl_pnorAccess.C | 189 | ||||
-rw-r--r-- | src/include/bootloader/bl_pnorAccess.H | 104 | ||||
-rw-r--r-- | src/include/usr/lpc/lpc_const.H | 48 | ||||
-rw-r--r-- | src/include/usr/pnor/pnor_const.H | 122 | ||||
-rw-r--r-- | src/include/usr/pnor/pnor_reasoncodes.H | 6 | ||||
-rw-r--r-- | src/include/usr/pnor/pnorif.H | 98 | ||||
-rw-r--r-- | src/usr/lpc/lpcdd.C | 18 | ||||
-rw-r--r-- | src/usr/lpc/lpcdd.H | 11 | ||||
-rw-r--r-- | src/usr/pnor/makefile | 6 | ||||
-rw-r--r-- | src/usr/pnor/pnor_common.C | 632 | ||||
-rw-r--r-- | src/usr/pnor/pnor_common.H | 92 | ||||
-rw-r--r-- | src/usr/pnor/pnor_utils.C | 357 | ||||
-rw-r--r-- | src/usr/pnor/pnor_utils.H | 224 | ||||
-rw-r--r-- | src/usr/pnor/pnordd.H | 6 | ||||
-rw-r--r-- | src/usr/pnor/pnorrp.C | 152 | ||||
-rw-r--r-- | src/usr/pnor/pnorrp.H | 9 | ||||
-rw-r--r-- | src/usr/pnor/runtime/makefile | 3 | ||||
-rw-r--r-- | src/usr/pnor/runtime/rt_pnor.C | 11 | ||||
-rw-r--r-- | src/usr/pnor/runtime/test/makefile | 2 | ||||
-rw-r--r-- | src/usr/pnor/runtime/test/testpnor_rt.H | 3 | ||||
-rw-r--r-- | src/usr/pnor/test/makefile | 6 | ||||
-rw-r--r-- | src/usr/pnor/test/pnorUtilsTestResources.H | 56 | ||||
-rw-r--r-- | src/usr/pnor/test/pnorddtest.H | 45 | ||||
-rw-r--r-- | src/usr/pnor/test/pnorutilsTest.H | 341 |
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 |