summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorPrachi Gupta <pragupta@us.ibm.com>2014-10-28 15:41:49 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2015-01-16 12:34:43 -0600
commitc068f50829ec46e4e5b056064dcbe9d786d549a4 (patch)
tree36c5fd8f2f6b5d420644ed83b877f6d0d8657f42 /src/usr
parent5412ba2270945edcfb23f60c34de01dccd44c098 (diff)
downloadtalos-hostboot-c068f50829ec46e4e5b056064dcbe9d786d549a4.tar.gz
talos-hostboot-c068f50829ec46e4e5b056064dcbe9d786d549a4.zip
hbrt interface for PNOR access
RTC:108836 Change-Id: I49e568e7f4fcad13fcd75dfdfa4aee8a263c5001 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14307 Reviewed-by: STEPHEN M. CPREK <smcprek@us.ibm.com> Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/pnor/makefile4
-rw-r--r--src/usr/pnor/pnor_common.C417
-rw-r--r--src/usr/pnor/pnor_common.H85
-rw-r--r--src/usr/pnor/pnorrp.C373
-rw-r--r--src/usr/pnor/pnorrp.H55
-rw-r--r--src/usr/pnor/pnorvalid.C6
-rw-r--r--src/usr/pnor/runtime/makefile36
-rw-r--r--src/usr/pnor/runtime/rt_pnor.C634
-rw-r--r--src/usr/pnor/runtime/rt_pnor.H153
-rw-r--r--src/usr/pnor/runtime/test/makefile31
-rw-r--r--src/usr/pnor/runtime/test/testpnor_rt.H257
-rw-r--r--src/usr/pnor/test/pnorrptest.H8
-rw-r--r--src/usr/testcore/rtloader/loader.H161
13 files changed, 1856 insertions, 364 deletions
diff --git a/src/usr/pnor/makefile b/src/usr/pnor/makefile
index e6585c123..31087a4b2 100644
--- a/src/usr/pnor/makefile
+++ b/src/usr/pnor/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2011,2014
+# Contributors Listed Below - COPYRIGHT 2011,2015
# [+] Google Inc.
# [+] International Business Machines Corp.
#
@@ -28,6 +28,7 @@ MODULE = pnor
OBJS += pnorrp.o
OBJS += pnordd.o
+OBJS += pnor_common.o
OBJS += pnorvalid.o
OBJS += ecc.o
OBJS += sfcdd.o
@@ -42,5 +43,6 @@ OBJS += $(if $(CONFIG_ALLOW_MICRON_PNOR),nor_micron.o)
SUBDIRS += test.d
+SUBDIRS += runtime.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/pnor/pnor_common.C b/src/usr/pnor/pnor_common.C
new file mode 100644
index 000000000..e92ce56c8
--- /dev/null
+++ b/src/usr/pnor/pnor_common.C
@@ -0,0 +1,417 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/pnor_common.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include "pnor_common.H"
+#include <pnor/pnorif.H>
+#include <pnor/pnor_reasoncodes.H>
+
+#include "ffs.h" //Common header file with BuildingBlock.
+#include "common/ffs_hb.H" //Hostboot def of user data in ffs_entry struct
+
+#include <initservice/initserviceif.H>
+#include <util/align.H>
+
+// Trace definition
+trace_desc_t* g_trac_pnor = NULL;
+TRAC_INIT(&g_trac_pnor, PNOR_COMP_NAME, 4*KILOBYTE, TRACE::BUFFER_SLOW); //4K
+
+// Easy macro replace for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+
+/**
+ * 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 */
+ "TEST", /**< PNOR::TEST : Test space for PNOR*/
+ //Not currently used
+// "XXX", /**< NUM_SECTIONS : Used as invalid entry */
+};
+
+/**
+ * @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;
+}
+
+errlHndl_t PNOR::parseTOC(uint8_t* i_toc0Buffer, uint8_t* i_toc1Buffer,
+ uint32_t & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr)
+{
+ TRACUCOMP(g_trac_pnor,"PNOR::parseTOC>");
+ errlHndl_t l_errhdl = NULL;
+
+ bool TOC_0_failed = false;
+
+ do{
+ o_TOC_used = 0;
+
+ for (uint32_t cur_TOC = 0; cur_TOC < NUM_TOCS; ++cur_TOC)
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::parseTOC verifying TOC: %d",cur_TOC);
+ uint64_t nextVAddr = i_baseVAddr;
+
+ // 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)
+ {
+ l_ffs_hdr = (ffs_hdr*) i_toc0Buffer;
+ }
+ else if (cur_TOC == 1)
+ {
+ 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 = 1;
+ continue;
+ }
+ else if (cur_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;
+ }
+ }
+
+ // Only check header if on first TOC or the first TOC failed
+ if (cur_TOC == 0 || TOC_0_failed)
+ {
+ 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;
+ }
+ }
+
+ ffs_hb_user_t* ffsUserData = NULL;
+
+ //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 == 0)
+ {
+ TRACFCOMP(g_trac_pnor,"PNOR::parseTOC TOC 0 entry"
+ " checksum failed");
+ TOC_0_failed = true;
+ o_TOC_used = 1;
+ break;
+ }
+ else if (cur_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 == 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;
+ }
+ }
+ }
+ if (l_errhdl)
+ {
+ TRACFCOMP(g_trac_pnor, ERR_MRK"PNOR::parseTOC: error parsing");
+ break;
+ }
+
+ 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
new file mode 100644
index 000000000..3944e27fa
--- /dev/null
+++ b/src/usr/pnor/pnor_common.H
@@ -0,0 +1,85 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/pnor_common.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef PNOR_COMMON_H
+#define PNOR_COMMON_H
+
+#include <pnor/pnorif.H>
+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;
+
+ enum
+ {
+ NUM_TOCS = 2,
+ TOC_0_OFFSET = 0,
+ TOC_1_OFFSET = 0x8000,
+
+ /** 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 */
+ };
+
+ /**
+ * @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 TOC's
+ * @param[in] i_toc0Buffer Pointer to toc0
+ * @param[in] i_toc1Buffer Pointer to toc1
+ * @param[out] o_TOC_used which TOC is used
+ * @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,
+ uint32_t & o_TOC_used, SectionData_t * o_TOC, uint64_t i_baseVAddr);
+}
+
+#endif
diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C
index a8ad0fb7a..3c1ce4a99 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,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,2015 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -45,43 +45,19 @@
#include <util/align.H>
#include <config.h>
-// Trace definition
-trace_desc_t* g_trac_pnor = NULL;
-TRAC_INIT(&g_trac_pnor, PNOR_COMP_NAME, 4*KILOBYTE, TRACE::BUFFER_SLOW); //2K
+
+extern trace_desc_t* g_trac_pnor;
// Easy macro replace for unit testing
//#define TRACUCOMP(args...) TRACFCOMP(args)
#define TRACUCOMP(args...)
+using namespace PNOR;
+
/**
* 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 */
- "TEST", /**< PNOR::TEST : Test space for PNOR*/
-
- //Not currently used
-// "XXX", /**< NUM_SECTIONS : Used as invalid entry */
-};
+extern const char* cv_EYECATCHER[];
/**
* @brief set up _start() task entry procedure for PNOR daemon
@@ -102,28 +78,44 @@ errlHndl_t PNOR::getSectionInfo( PNOR::SectionId i_section,
return Singleton<PnorRP>::instance().getSectionInfo(i_section,o_info);
}
-namespace PNOR
-{
-
/**
- * @brief calculates the checksum on data(ffs header/entry) and will return
- * 0 if the checksums match
+ * @brief Write the data for a given sectino into PNOR
*/
-uint32_t pnor_ffs_checksum(void* data, size_t size)
+errlHndl_t PNOR::flush( PNOR::SectionId i_section)
{
- uint32_t checksum = 0;
-
- for (size_t i = 0; i < (size/4); i++)
- {
- checksum ^= ((uint32_t*)data)[i];
- }
-
- checksum = htobe32(checksum);
- return checksum;
+ errlHndl_t l_err = NULL;
+ do {
+ PNOR::SectionInfo_t l_info;
+ l_err = getSectionInfo(i_section, l_info);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::flush: getSectionInfo errored,"
+ " secId: %d", (int)i_section);
+ break;
+ }
+ int l_rc = mm_remove_pages (RELEASE,
+ reinterpret_cast<void*>(l_info.vaddr), l_info.size);
+ if (l_rc)
+ {
+ TRACFCOMP(g_trac_pnor, "PNOR::flush: mm_remove_pages errored,"
+ " secId: %d, rc: %d", (int)i_section, l_rc);
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORRP_FLUSH
+ * @reasoncode PNOR::RC_MM_REMOVE_PAGES_FAILED
+ * @userdata1 section Id
+ * @userdata2 RC
+ * @devdesc mm_remove_pages failed
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_FLUSH,
+ PNOR::RC_MM_REMOVE_PAGES_FAILED,
+ i_section, l_rc, true);
+ break;
+ }
+ } while (0);
+ return l_err;
}
-
-};
-
/**
* STATIC
* @brief Static Initializer
@@ -147,7 +139,7 @@ void PnorRP::init( errlHndl_t &io_rtaskRetErrl )
* @custdesc A problem occurred while accessing the boot flash.
*/
l_errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
PNOR::MOD_PNORRP_DIDSTARTUPFAIL,
PNOR::RC_BAD_STARTUP_RC,
rc,
@@ -363,6 +355,7 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section,
o_info.id = iv_TOC[id].id;
o_info.name = cv_EYECATCHER[id];
o_info.vaddr = iv_TOC[id].virtAddr;
+ o_info.flashAddr = iv_TOC[id].flashAddr;
o_info.size = iv_TOC[id].size;
o_info.eccProtected = ((iv_TOC[id].integrity & FFS_INTEG_ECC_PROTECT)
!= 0) ? true : false;
@@ -383,267 +376,45 @@ errlHndl_t PnorRP::readTOC()
{
TRACUCOMP(g_trac_pnor, "PnorRP::readTOC>" );
errlHndl_t l_errhdl = NULL;
- uint8_t* tocBuffer = NULL;
+ uint8_t* toc0Buffer = new uint8_t[PAGESIZE];
+ uint8_t* toc1Buffer = new uint8_t[PAGESIZE];
uint64_t fatal_error = 0;
- bool TOC_0_failed = false;
-
- do{
- iv_TOC_used = 0;
-
- for (uint32_t cur_TOC = 0; cur_TOC < NUM_TOCS; ++cur_TOC)
+ do {
+ l_errhdl = readFromDevice( TOC_0_OFFSET, 0, false,
+ toc0Buffer, fatal_error );
+ if (l_errhdl)
{
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC verifying TOC: %d",cur_TOC);
- uint64_t nextVAddr = BASE_VADDR;
-
- // Zero out my table
- for( size_t id = PNOR::FIRST_SECTION;
- id <= PNOR::NUM_SECTIONS; //include extra entry for error paths
- ++id )
- {
- iv_TOC[id].id = (PNOR::SectionId)id;
- //everything else should default to zero
- }
-
- // Read TOC information from TOC 0 and then TOC 1
- tocBuffer = new uint8_t[PAGESIZE];
- if (cur_TOC == 0)
- {
- l_errhdl = readFromDevice( TOC_0_OFFSET, 0, false,
- tocBuffer, fatal_error );
- }
- else if (cur_TOC == 1)
- {
- l_errhdl = readFromDevice( TOC_1_OFFSET, 0, false,
- tocBuffer, fatal_error );
- }
-
- if( l_errhdl )
- {
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC readFromDevice Failed.");
- break;
- }
-
- ffs_hdr* l_ffs_hdr = (ffs_hdr*) tocBuffer;
-
- // 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, "PnorRP::readTOC pnor_ffs_checksum header checksums do not match.");
- if (cur_TOC == 0)
- {
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC TOC 0 failed header checksum");
- TOC_0_failed = true;
- iv_TOC_used = 1;
- continue;
- }
- else if (cur_TOC == 1 && TOC_0_failed)
- {
- // Both TOC's failed
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC both TOC's are corrupted");
- INITSERVICE::doShutdown( PNOR::RC_PARTITION_TABLE_INVALID);
- }
- else
- {
- // TOC 1 failed
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC TOC 1 failed header checksum");
- break;
- }
- }
-
- // Only check header if on first TOC or the first TOC failed
- if (cur_TOC == 0 || TOC_0_failed)
- {
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC: 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>PnorRP::readTOC: 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>PnorRP::readTOC: 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>PnorRP::readTOC: 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>PnorRP::readTOC: FFS Header pointer to entries is NULL.");
- header_good = false;
- }
- else if(l_ffs_hdr->block_size != PAGESIZE)
- {
- TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC: 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>PnorRP::readTOC: 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>PnorRP::readTOC: 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)
- {
- INITSERVICE::doShutdown( PNOR::RC_PARTITION_TABLE_INVALID);
- }
- else
- {
- TOC_0_failed = true;
- }
- //Try TOC1
- continue;
- }
- }
-
- ffs_hb_user_t* ffsUserData = NULL;
-
- //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, "PnorRP::readTOC: 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, "PnorRP::readTOC pnor_ffs_checksum entry checksums do not match.");
- if (cur_TOC == 0)
- {
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC TOC 0 entry checksum failed");
- TOC_0_failed = true;
- iv_TOC_used = 1;
- break;
- }
- else if (cur_TOC == 1 && TOC_0_failed)
- {
- // Both TOC's failed
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC both TOC's are corrupted");
- INITSERVICE::doShutdown( PNOR::RC_PARTITION_TABLE_INVALID);
- }
- else
- {
- // TOC 1 failed
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC TOC 1 entry checksum failed");
- break;
- }
- }
-
- // Only set data if on first TOC or the first TOC failed
- if (cur_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, "PnorRP::readTOC: sectionId=%d", secId);
- break;
- }
- }
-
- if(secId == PNOR::INVALID_SECTION)
- {
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC: Unrecognized Section name(%s), skipping", cur_entry->name);
- continue;
- }
-
- ffsUserData = (ffs_hb_user_t*)&(cur_entry->user);
-
- //size
- iv_TOC[secId].size = ((uint64_t)cur_entry->size)*PAGESIZE;
-
- //virtAddr
- iv_TOC[secId].virtAddr = nextVAddr;
- nextVAddr += iv_TOC[secId].size;
-
- //flashAddr
- iv_TOC[secId].flashAddr = ((uint64_t)cur_entry->base)*PAGESIZE;
-
- //chipSelect
- iv_TOC[secId].chip = ffsUserData->chip;
-
- //user data
- iv_TOC[secId].integrity = ffsUserData->dataInteg;
- iv_TOC[secId].version = ffsUserData->verCheck;
- iv_TOC[secId].misc = ffsUserData->miscFlags;
-
- TRACFCOMP(g_trac_pnor, "PnorRp::readTOC: User Data %s", cur_entry->name);
-
- if (iv_TOC[secId].integrity == FFS_INTEG_ECC_PROTECT)
- {
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC: ECC enabled for %s", cur_entry->name);
- iv_TOC[secId].size = ALIGN_PAGE_DOWN((iv_TOC[secId].size * 8 ) / 9);
- }
+ TRACFCOMP(g_trac_pnor, "readTOC: readFromDevice failed for TOC0");
+ break;
+ }
- // TODO RTC:96009 handle version header w/secureboot
- if (iv_TOC[secId].version == FFS_VERS_SHA512)
- {
- TRACFCOMP(g_trac_pnor, "PnorRP::readTOC: Incrementing Flash Address for SHA Header");
- if (iv_TOC[secId].integrity == FFS_INTEG_ECC_PROTECT)
- {
- iv_TOC[secId].flashAddr += PAGESIZE_PLUS_ECC;
- }
- else
- {
- iv_TOC[secId].flashAddr += PAGESIZE;
- }
- }
-
- if((iv_TOC[secId].flashAddr + iv_TOC[secId].size) > (l_ffs_hdr->block_count*PAGESIZE))
- {
- TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC: Partition(%s) at base address (0x%.8x) extends past end of flash device",
- cur_entry->name, iv_TOC[secId].flashAddr);
- INITSERVICE::doShutdown( PNOR::RC_PARTITION_TABLE_INVALID);
- }
- }
- }
+ l_errhdl = readFromDevice( TOC_1_OFFSET, 0, false,
+ toc1Buffer, fatal_error );
+ if (l_errhdl)
+ {
+ TRACFCOMP(g_trac_pnor, "readTOC: readFromDevice failed for TOC1");
+ break;
+ }
- //keep these traces here until PNOR is rock-solid
- 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], iv_TOC[tmpId].size, iv_TOC[tmpId].flashAddr, iv_TOC[tmpId].virtAddr );
- }
+ l_errhdl = PNOR::parseTOC(toc0Buffer, toc1Buffer, iv_TOC_used, iv_TOC,
+ BASE_VADDR);
+ if (l_errhdl)
+ {
+ TRACFCOMP(g_trac_pnor, "readTOC: parseTOC failed");
+ errlCommit(l_errhdl, PNOR_COMP_ID);
+ INITSERVICE::doShutdown(PNOR::RC_PARTITION_TABLE_INVALID);
}
- }while(0);
+ } while (0);
- if(tocBuffer != NULL)
+ if(toc0Buffer != NULL)
{
- TRACUCOMP(g_trac_pnor, "Deleting tocBuffer");
- delete[] tocBuffer;
+ delete[] toc0Buffer;
}
+ if(toc1Buffer != NULL)
+ {
+ delete[] toc1Buffer;
+ }
TRACUCOMP(g_trac_pnor, "< PnorRP::readTOC" );
return l_errhdl;
}
diff --git a/src/usr/pnor/pnorrp.H b/src/usr/pnor/pnorrp.H
index f11a2644d..54f3e364e 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,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,2015 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -25,7 +25,6 @@
/* IBM_PROLOG_END_TAG */
#ifndef __PNOR_PNORRP_H
#define __PNOR_PNORRP_H
-
#include <pnor/pnorif.H>
#include <sys/msg.h>
#include <stdint.h>
@@ -33,25 +32,7 @@
#include <errl/errlentry.H>
#include <vmmconst.h>
#include <map>
-
-namespace PNOR
-{
-
- /**
- * @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);
-
-}; //namespace PNOR
+#include "pnor_common.H"
/**
* PNOR Resource Provider
@@ -90,47 +71,18 @@ class PnorRP
private:
- /**
- * PNOR Constants
- */
- static const uint32_t NUM_TOCS = 2;
- static const uint64_t TOC_0_OFFSET = 0;
- static const uint64_t TOC_1_OFFSET = 0x8000;
-
enum
{
BASE_VADDR = VMM_VADDR_PNOR_RP, /**< 2GB = 0x80000000*/
TOTAL_SIZE = 64*MEGABYTE, /**< Allocate 64 MB (0x4000000)*/
-
LAST_VADDR = BASE_VADDR + TOTAL_SIZE, /**< End of our VA range */
-
- /** 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 */
};
-
/**
* Which TOC (0 or 1) is used after verifying both.
*/
uint32_t iv_TOC_used;
/**
- * 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;
-
- /**
* Flash statistics
*/
struct FlashStats_t {
@@ -141,7 +93,7 @@ class PnorRP
/**
* Cached copy of section data
*/
- SectionData_t iv_TOC[PNOR::NUM_SECTIONS+1];
+ PNOR::SectionData_t iv_TOC[PNOR::NUM_SECTIONS+1];
/**
* Pointer to the message queue where we receive messages
@@ -263,7 +215,6 @@ class PnorRP
friend class PnorDdTest;
friend class SfcIBMTest;
friend class SfcAST2400Test;
-
// allow this function to use constant(s)
friend errlHndl_t PNOR::validateAltMaster( void );
diff --git a/src/usr/pnor/pnorvalid.C b/src/usr/pnor/pnorvalid.C
index 048078c93..1bc09a2fa 100644
--- a/src/usr/pnor/pnorvalid.C
+++ b/src/usr/pnor/pnorvalid.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2015 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -102,7 +102,7 @@ errlHndl_t validateAltMaster( void )
// When reading PNOR TOC assume a single page and no ECC
uint8_t* tocBuffer = new uint8_t[PAGESIZE];
size_t read_size = PAGESIZE;
- const uint64_t toc0_offset = PnorRP::TOC_0_OFFSET;
+ const uint64_t toc0_offset = PNOR::TOC_0_OFFSET;
do{
@@ -177,7 +177,7 @@ errlHndl_t validateAltMaster( void )
// Read Flash
l_err = pnordd->readFlash(tocBuffer, read_size,
- PnorRP::TOC_0_OFFSET);
+ PNOR::TOC_0_OFFSET);
if ( l_err )
{
// Commit Error Log, but continue the test
diff --git a/src/usr/pnor/runtime/makefile b/src/usr/pnor/runtime/makefile
new file mode 100644
index 000000000..0556af9e4
--- /dev/null
+++ b/src/usr/pnor/runtime/makefile
@@ -0,0 +1,36 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/pnor/runtime/makefile $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2014,2015
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+HOSTBOOT_RUNTIME = 1
+ROOTPATH = ../../../..
+MODULE = pnor_rt
+
+OBJS += rt_pnor.o
+OBJS += pnor_common.o
+OBJS += ecc.o
+
+SUBDIRS += test.d
+
+VPATH += ../
+include $(ROOTPATH)/config.mk
diff --git a/src/usr/pnor/runtime/rt_pnor.C b/src/usr/pnor/runtime/rt_pnor.C
new file mode 100644
index 000000000..c43160f44
--- /dev/null
+++ b/src/usr/pnor/runtime/rt_pnor.C
@@ -0,0 +1,634 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/runtime/rt_pnor.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include <stdlib.h>
+#include <targeting/common/targetservice.H>
+#include <initservice/taskargs.H>
+
+#include <runtime/rt_targeting.H>
+#include <runtime/interface.h>
+
+#include <pnor/pnorif.H>
+#include <pnor/ecc.H>
+#include <pnor/pnor_reasoncodes.H>
+#include "rt_pnor.H"
+
+#include "../ffs.h"
+#include "../common/ffs_hb.H"
+
+// Trace definition
+extern trace_desc_t* g_trac_pnor;
+
+/**
+ * Eyecatcher strings for PNOR TOC entries
+ */
+extern const char* cv_EYECATCHER[];
+
+/**
+ * @brief set up _start() task entry procedure for PNOR daemon
+ */
+TASK_ENTRY_MACRO( RtPnor::init );
+
+
+/**
+ * @brief Return the size and address of a given section of PNOR data
+ */
+errlHndl_t PNOR::getSectionInfo( PNOR::SectionId i_section,
+ PNOR::SectionInfo_t& o_info )
+{
+ return Singleton<RtPnor>::instance().getSectionInfo(i_section,o_info);
+}
+
+/**
+ * @brief Write the data for a given sectino into PNOR
+ */
+errlHndl_t PNOR::flush( PNOR::SectionId i_section)
+{
+ return Singleton<RtPnor>::instance().flush(i_section);
+}
+
+/****************Public Methods***************************/
+/**
+ * STATIC
+ * @brief Static Initializer
+ */
+void RtPnor::init(errlHndl_t &io_taskRetErrl)
+{
+ TRACFCOMP(g_trac_pnor, "RtPnor::init> " );
+ io_taskRetErrl = Singleton<RtPnor>::instance().readTOC();
+ TRACFCOMP(g_trac_pnor, "<RtPnor::init" );
+}
+/**************************************************************/
+errlHndl_t RtPnor::getSectionInfo(PNOR::SectionId i_section,
+ PNOR::SectionInfo_t& o_info)
+{
+ TRACFCOMP(g_trac_pnor, ENTER_MRK"RtPnor::getSectionInfo");
+ errlHndl_t l_err = NULL;
+ do
+ {
+ if (i_section == PNOR::INVALID_SECTION)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::getSectionInfo: Invalid Section"
+ " %d", (int)i_section);
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_RTPNOR_GETSECTIONINFO
+ * @reasoncode PNOR::RC_RTPNOR_INVALID_SECTION
+ * @userdata1 PNOR::SectionId
+ * @devdesc invalid section passed to getSectionInfo
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_RTPNOR_GETSECTIONINFO,
+ PNOR::RC_RTPNOR_INVALID_SECTION,
+ i_section, 0,true);
+ break;
+ }
+
+ //size of the section
+ uint64_t l_sizeBytes = iv_TOC[i_section].size;
+ if (l_sizeBytes == 0)
+ {
+ TRACFCOMP(g_trac_pnor,"RtPnor::getSectionInfo: Section %d"
+ " size is 0", (int)i_section);
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_RTPNOR_GETSECTIONINFO
+ * @reasoncode PNOR::RC_SECTION_SIZE_IS_ZERO
+ * @userdata1 PNOR::SectionId
+ * @devdesc section size is zero
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_RTPNOR_GETSECTIONINFO,
+ PNOR::RC_SECTION_SIZE_IS_ZERO,
+ i_section, 0,true);
+ break;
+ }
+ //find proc id
+ uint64_t l_procId;
+ TARGETING::Target* l_masterProc = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle( l_masterProc );
+ l_err = RT_TARG::getRtTarget (l_masterProc, l_procId);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::getSectionInfo: getRtTarget failed");
+ break;
+ }
+
+ //ecc
+ bool l_ecc = (iv_TOC[i_section].integrity&FFS_INTEG_ECC_PROTECT) ?
+ true : false;
+
+ void* l_pWorking = NULL;
+ void* l_pClean = NULL;
+
+ //find the section in the map first
+ if(iv_pnorMap.find(i_section) != iv_pnorMap.end())
+ {
+ //get the addresses from the map
+ PnorAddrPair_t l_addrPair = iv_pnorMap[i_section];
+ l_pWorking = l_addrPair.first;
+ l_pClean = l_addrPair.second;
+ }
+ else
+ {
+ //malloc twice -- one working copy and one clean copy
+ //So, we can diff and write only the dirty bytes
+ l_pWorking = malloc(l_sizeBytes);
+ l_pClean = malloc(l_sizeBytes);
+
+ //offset = 0 : read the entire section
+ l_err = readFromDevice(l_procId, i_section, 0, l_sizeBytes, l_ecc,
+ l_pWorking);
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::getSectionInfo:readFromDevice"
+ " failed");
+ break;
+ }
+
+ //copy data to another pointer to save a clean copy of data
+ memcpy(l_pClean, l_pWorking, l_sizeBytes);
+
+ //save it in the map
+ iv_pnorMap [i_section] = PnorAddrPair_t(l_pWorking, l_pClean);
+ }
+ //return the data in the struct
+ o_info.id = i_section;
+ o_info.name = cv_EYECATCHER[i_section];
+ o_info.vaddr = (uint64_t)l_pWorking;
+ o_info.flashAddr = iv_TOC[i_section].flashAddr;
+ o_info.size = l_sizeBytes;
+ o_info.eccProtected = l_ecc;
+ o_info.sha512Version=
+ (iv_TOC[i_section].version & FFS_VERS_SHA512) ? true : false;
+ o_info.sha512perEC =
+ (iv_TOC[i_section].version & FFS_VERS_SHA512_PER_EC) ? true : false;
+ } while (0);
+
+ TRACFCOMP(g_trac_pnor, EXIT_MRK"RtPnor::getSectionInfo");
+ return l_err;
+}
+
+/**************************************************************/
+errlHndl_t RtPnor::flush( PNOR::SectionId i_section)
+{
+ TRACFCOMP(g_trac_pnor, ENTER_MRK"RtPnor::flush");
+ errlHndl_t l_err = NULL;
+ do
+ {
+ if (i_section == PNOR::INVALID_SECTION)
+ {
+ TRACFCOMP(g_trac_pnor,"RtPnor::flush: Invalid Section: %d",
+ (int)i_section);
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_RTPNOR_FLUSH
+ * @reasoncode PNOR::RC_INVALID_SECTION
+ * @userdata1 PNOR::SectionId
+ * @devdesc invalid section passed to flush
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_RTPNOR_FLUSH,
+ PNOR::RC_INVALID_SECTION,
+ i_section, 0,true);
+ break;
+ }
+ size_t l_sizeBytes = iv_TOC[i_section].size;
+ if (l_sizeBytes == 0)
+ {
+ TRACFCOMP(g_trac_pnor,"RtPnor::flush: Section %d"
+ " size is 0", (int)i_section);
+
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_RTPNOR_FLUSH
+ * @reasoncode PNOR::RC_SECTION_SIZE_IS_ZERO
+ * @userdata1 PNOR::SectionId
+ * @devdesc section size is zero
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_RTPNOR_FLUSH,
+ PNOR::RC_SECTION_SIZE_IS_ZERO,
+ i_section, 0,true);
+ break;
+ }
+
+ //get the saved pointers for the partitionName
+ PnorAddrMap_t::iterator l_it = iv_pnorMap.find(i_section);
+ if(l_it == iv_pnorMap.end())
+ {
+ TRACFCOMP(g_trac_pnor,"RtPnor::flush: section %d has not been read before",
+ i_section);
+ break;
+ }
+ PnorAddrPair_t l_addrPair = l_it->second;
+ uint8_t* l_pWorking = reinterpret_cast<uint8_t*>(l_addrPair.first);
+ uint8_t* l_pClean = reinterpret_cast<uint8_t*>(l_addrPair.second);
+
+ //ecc
+ bool l_ecc = (iv_TOC[i_section].integrity&FFS_INTEG_ECC_PROTECT) ?
+ true : false;
+ //find proc id
+ uint64_t l_procId;
+ TARGETING::Target* l_masterProc = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle( l_masterProc );
+ l_err = RT_TARG::getRtTarget (l_masterProc, l_procId);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::flush: getRtTarget failed");
+ break;
+ }
+
+ //find the diff between each pointer
+ //write back to pnor what doesn't match
+ TRACFCOMP(g_trac_pnor, "finding diff between working and clean copy...");
+ for (uint64_t i = 0; i < (l_sizeBytes/PAGESIZE); i++)
+ {
+ if (0 != memcmp(l_pWorking, l_pClean, PAGESIZE))
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::flush: page %d is different,"
+ " writing back to pnor", i);
+ l_err = writeToDevice(l_procId, i_section, i*PAGESIZE,PAGESIZE,
+ l_ecc,l_pWorking);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::flush: writeToDevice failed");
+ break;
+ }
+ //update the clean copy
+ memcpy(l_pClean, l_pWorking, PAGESIZE);
+ }
+ l_pWorking += PAGESIZE;
+ l_pClean += PAGESIZE;
+ }
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor,"RtPnor::flush: error writing section %d"
+ " back to pnor",(int)i_section);
+ break;
+ }
+ } while (0);
+
+ TRACFCOMP(g_trac_pnor, EXIT_MRK"RtPnor::flush");
+ return l_err;
+}
+/*******Protected Methods**************/
+RtPnor::RtPnor()
+:iv_TOC_used(0)
+{
+ errlHndl_t l_err = readTOC();
+ if (l_err)
+ {
+ errlCommit(l_err, PNOR_COMP_ID);
+ }
+}
+
+/*************************/
+RtPnor::~RtPnor()
+{
+
+}
+
+/*******************Private Methods*********************/
+errlHndl_t RtPnor::readFromDevice (uint64_t i_procId,
+ PNOR::SectionId i_section,
+ uint64_t i_offset,
+ size_t i_size,
+ bool i_ecc,
+ void* o_data)
+{
+ TRACFCOMP(g_trac_pnor, ENTER_MRK"RtPnor::readFromDevice: i_offset=0x%X, "
+ "i_procId=%d sec=%d size=0x%X ecc=%d", i_offset, i_procId, i_section,
+ i_size, i_ecc);
+ errlHndl_t l_err = NULL;
+ uint8_t* l_eccBuffer = NULL;
+ do
+ {
+
+ const char* l_partitionName = cv_EYECATCHER[i_section];
+ void* l_dataToRead = o_data;
+ size_t l_readSize = i_size;
+ size_t l_readSizePlusECC = (i_size * 9)/8;
+ uint64_t l_offset = i_offset;
+
+ // if we need to handle ECC, we need to read more
+ if( i_ecc )
+ {
+ l_eccBuffer = new uint8_t[l_readSizePlusECC]();
+ l_dataToRead = l_eccBuffer;
+ l_readSize = l_readSizePlusECC;
+ l_offset = (i_offset * 9)/8;
+ }
+
+ if (g_hostInterfaces && g_hostInterfaces->pnor_read)
+ {
+ // get the data from OPAL
+ int l_rc = g_hostInterfaces->pnor_read(i_procId, l_partitionName,
+ l_offset, l_dataToRead, l_readSize);
+ if (l_rc)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::readFromDevice: pnor_read"
+ " failed proc:%d, part:%s, offset:0x%X, size:0x%X,"
+ " dataPt:0x%X, rc:%d", i_procId, l_partitionName,
+ l_offset, l_readSize, l_dataToRead, l_rc);
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE
+ * @reasoncode PNOR::RC_PNOR_READ_FAILED
+ * @userdata1[00:31] rc returned from pnor_read
+ * @userdata1[32:63] section ID
+ * @userdata2[00:31] offset within the section
+ * @userdata2[32:63] size of data read in bytes
+ * @devdesc g_hostInterfaces->pnor_read failed
+ * @custdesc Error accessing system firmware flash
+ */
+ //@todo Add PNOR callout RTC:116145
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_RTPNOR_READFROMDEVICE,
+ PNOR::RC_PNOR_READ_FAILED,
+ TWO_UINT32_TO_UINT64(l_rc, i_section),
+ TWO_UINT32_TO_UINT64(l_offset, l_readSize),
+ true);
+ break;
+ }
+ }
+ else
+ {
+ TRACFCOMP(g_trac_pnor,"RtPnor::readFromDevice: This version of"
+ " OPAL does not support pnor_read");
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE
+ * @reasoncode PNOR::RC_PNOR_READ_NOT_SUPPORTED
+ * @devdesc g_hostInterfaces->pnor_read not supported
+ * @custdesc Error accessing system firmware flash
+ */
+ //@todo Add PNOR callout RTC:116145
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_RTPNOR_READFROMDEVICE,
+ PNOR::RC_PNOR_READ_NOT_SUPPORTED,
+ 0,0,true);
+ break;
+ }
+ // remove the ECC data
+ if( i_ecc )
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::readFromDevice: removing ECC...");
+ // remove the ECC and fix the original data if it is broken
+ PNOR::ECC::eccStatus ecc_stat =
+ PNOR::ECC::removeECC(reinterpret_cast<uint8_t*>(l_dataToRead),
+ reinterpret_cast<uint8_t*>(o_data),
+ i_size);
+
+ // create an error if we couldn't correct things
+ if( ecc_stat == PNOR::ECC::UNCORRECTABLE )
+ {
+ TRACFCOMP(g_trac_pnor,"RtPnor::readFromDevice>"
+ " Uncorrectable ECC error : chip=%d,offset=0x%.X",
+ i_procId, i_offset );
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE
+ * @reasoncode PNOR::RC_UNCORRECTABLE_ECC
+ * @devdesc UNCORRECTABLE ECC
+ */
+ //@todo Add PNOR callout RTC:116145
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_RTPNOR_READFROMDEVICE,
+ PNOR::RC_UNCORRECTABLE_ECC,
+ 0, 0, true);
+ break;
+ }
+
+ // found an error so we need to fix something
+ else if( ecc_stat != PNOR::ECC::CLEAN )
+ {
+ TRACFCOMP(g_trac_pnor,"RtPnor::readFromDevice>"
+ "Correctable ECC error : chip=%d, offset=0x%.X",
+ i_procId, i_offset );
+ if (g_hostInterfaces && g_hostInterfaces->pnor_write)
+ {
+
+ //need to write good data back to PNOR
+ int l_rc = g_hostInterfaces->pnor_write(i_procId,
+ l_partitionName,l_offset, l_dataToRead,l_readSize);
+ if (l_rc)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::readFromDevice> Error"
+ " writing corrected data back to device");
+
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE
+ * @reasoncode PNOR::RC_PNOR_WRITE_FAILED
+ * @userdata1 rc returned from pnor_write
+ * @devdesc error writing corrected data back to PNOR
+ * @custdesc Error accessing system firmware flash
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_RTPNOR_READFROMDEVICE,
+ PNOR::RC_PNOR_WRITE_FAILED,
+ l_rc, 0, true);
+ errlCommit(l_err, PNOR_COMP_ID);
+ }
+ }
+ }
+ }
+ } while(0);
+
+ if( l_eccBuffer )
+ {
+ delete[] l_eccBuffer;
+ }
+
+ TRACFCOMP(g_trac_pnor, EXIT_MRK"RtPnor::readFromDevice" );
+ return l_err;
+}
+
+/*********************************************************************/
+errlHndl_t RtPnor::writeToDevice( uint64_t i_procId,
+ PNOR::SectionId i_section,
+ uint64_t i_offset,
+ size_t i_size,
+ bool i_ecc,
+ void* i_src )
+{
+ TRACFCOMP(g_trac_pnor, ENTER_MRK"RtPnor::writeToDevice: i_offset=0x%X, "
+ "i_procId=%d sec=%d size=0x%X ecc=%d", i_offset, i_procId, i_section,
+ i_size, i_ecc);
+ errlHndl_t l_err = NULL;
+ uint8_t* l_eccBuffer = NULL;
+
+ do
+ {
+ void* l_dataToWrite = i_src;
+ size_t l_writeSize = i_size;
+ size_t l_writeSizePlusECC = (i_size * 9)/8;
+ uint64_t l_offset = i_offset;
+
+ // apply ECC to data if needed
+ if( i_ecc )
+ {
+ l_eccBuffer = new uint8_t[l_writeSizePlusECC];
+ PNOR::ECC::injectECC( reinterpret_cast<uint8_t*>(i_src),
+ l_writeSize,
+ reinterpret_cast<uint8_t*>(l_eccBuffer) );
+ l_dataToWrite = reinterpret_cast<void*>(l_eccBuffer);
+ l_writeSize = l_writeSizePlusECC;
+ l_offset = (i_offset * 9)/8;
+ }
+
+ const char* l_partitionName = cv_EYECATCHER[i_section];
+ if (g_hostInterfaces && g_hostInterfaces->pnor_write)
+ {
+ //make call into opal to write the data
+ int l_rc = g_hostInterfaces->pnor_write(i_procId,
+ l_partitionName,l_offset,l_dataToWrite,l_writeSize);
+ if (l_rc)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::writeToDevice: pnor_write failed "
+ "proc:%d, part:%s, offset:0x%X, size:0x%X, dataPt:0x%X,"
+ " rc:%d", i_procId, l_partitionName, l_offset, l_writeSize,
+ l_dataToWrite, l_rc);
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_RTPNOR_WRITETODEVICE
+ * @reasoncode PNOR::RC_PNOR_WRITE_FAILED
+ * @userdata1[00:31] rc returned from pnor_write
+ * @userdata1[32:63] section ID
+ * @userdata2[00:31] offset within the section
+ * @userdata2[32:63] size of data written in bytes
+ * @devdesc g_hostInterfaces->pnor_write failed
+ * @custdesc Error accessing system firmware flash
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_RTPNOR_WRITETODEVICE,
+ PNOR::RC_PNOR_WRITE_FAILED,
+ TWO_UINT32_TO_UINT64(l_rc, i_section),
+ TWO_UINT32_TO_UINT64(l_offset, l_writeSize),
+ true);
+ break;
+ }
+ }
+ else
+ {
+ TRACFCOMP(g_trac_pnor,"RtPnor::writeToDevice: This version of"
+ " OPAL does not support pnor_write");
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_RTPNOR_WRITETODEVICE
+ * @reasoncode PNOR::RC_PNOR_WRITE_NOT_SUPPORTED
+ * @devdesc g_hostInterfaces->pnor_write not supported
+ * @custdesc Error accessing system firmware flash
+ */
+ //@todo Add PNOR callout RTC:116145
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_RTPNOR_WRITETODEVICE,
+ PNOR::RC_PNOR_WRITE_NOT_SUPPORTED,
+ 0,0,true);
+ break;
+
+ }
+ } while(0);
+
+ if( l_eccBuffer )
+ {
+ delete[] l_eccBuffer;
+ }
+
+ TRACFCOMP(g_trac_pnor, EXIT_MRK"RtPnor::writeToDevice" );
+ return l_err;
+}
+
+/*****************************************************************/
+errlHndl_t RtPnor::readTOC ()
+{
+ TRACFCOMP(g_trac_pnor, ENTER_MRK"RtPnor::readTOC" );
+ errlHndl_t l_err = NULL;
+ uint8_t* toc0Buffer = new uint8_t[PAGESIZE];
+ uint8_t* toc1Buffer = new uint8_t[PAGESIZE];
+ do {
+ //find proc id
+ uint64_t l_procId;
+ TARGETING::Target* l_masterProc = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle( l_masterProc );
+ l_err = RT_TARG::getRtTarget (l_masterProc, l_procId);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::readTOC: getRtTarget failed");
+ break;
+ }
+
+ l_err = readFromDevice (l_procId, PNOR::TOC, PNOR::TOC_0_OFFSET,
+ PAGESIZE,false,toc0Buffer);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor,"RtPnor::readTOC:readFromDevice failed"
+ " for TOC0");
+ break;
+ }
+ l_err = readFromDevice (l_procId, PNOR::TOC, PNOR::TOC_1_OFFSET,
+ PAGESIZE, false,toc1Buffer);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::readTOC:readFromDevice failed"
+ " for TOC1");
+ break;
+ }
+
+ l_err = PNOR::parseTOC(toc0Buffer, toc1Buffer, iv_TOC_used, iv_TOC,0);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "RtPnor::readTOC: parseTOC failed");
+ break;
+ }
+ } while (0);
+
+ if(toc0Buffer != NULL)
+ {
+ delete[] toc0Buffer;
+ }
+
+ if(toc1Buffer != NULL)
+ {
+ delete[] toc1Buffer;
+ }
+
+ TRACFCOMP(g_trac_pnor, EXIT_MRK"RtPnor::readTOC" );
+ return l_err;
+}
+
+/***********************************************************/
+RtPnor& RtPnor::getInstance()
+{
+ return Singleton<RtPnor>::instance();
+}
diff --git a/src/usr/pnor/runtime/rt_pnor.H b/src/usr/pnor/runtime/rt_pnor.H
new file mode 100644
index 000000000..43041fc3f
--- /dev/null
+++ b/src/usr/pnor/runtime/rt_pnor.H
@@ -0,0 +1,153 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/runtime/rt_pnor.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef _RT_PNOR_H_
+#define _RT_PNOR_H_
+
+#include <pnor/pnorif.H>
+#include "../pnor_common.H"
+#include <errl/errlentry.H>
+#include <map>
+
+typedef std::pair<void*, void*> PnorAddrPair_t;
+typedef std::map<PNOR::SectionId, PnorAddrPair_t> PnorAddrMap_t;
+
+class RtPnor
+{
+ public:
+
+ /**
+ * @brief Static Initializer
+ * @param[in] ref to errlHndl_t
+ */
+ static void init ( errlHndl_t &io_rtaskRetErrl );
+
+ /**
+ * @brief Return the size and address of a given section
+ * of PNOR data at runtime
+ * Called by external PNOR::getSectionInfo()
+ *
+ * @param[in] i_section PNOR section
+ * @param[out] o_info Location and size information
+ *
+ * @return errlHndl_t Error log if request was invalid
+ */
+ errlHndl_t getSectionInfo ( PNOR::SectionId i_section,
+ PNOR::SectionInfo_t& o_info);
+
+ /**
+ * @brief Writes the data back to PNOR of a given section
+ * of PNOR at runtime
+ * Called by external PNOR::flush()
+ *
+ * @param[in] i_section PNOR section
+ * @return errlHndl_t Error log if request was invalid
+ */
+ errlHndl_t flush (PNOR::SectionId i_section);
+
+ protected:
+ /**
+ * @brief Constructor
+ */
+ RtPnor();
+
+ /**
+ * @brief Destructor
+ */
+ ~RtPnor();
+
+ private:
+ /**
+ * Which TOC (0 or 1) is used after verifying both.
+ */
+ uint32_t iv_TOC_used;
+
+ /**
+ * Cached copy of section data
+ */
+ PNOR::SectionData_t iv_TOC[PNOR::NUM_SECTIONS+1];
+
+ /**
+ * Keeps track of the data pointers for different sections in the PNOR
+ */
+ PnorAddrMap_t iv_pnorMap;
+
+ /**
+ * @brief Reads data from the PNOR device
+ * and removes ecc if necessary
+ *
+ * @param[in] i_procId processor id
+ * @param[in] i_section section of the pnor to write back
+ * @param[in] i_offset offset into the pnor
+ * @param[in] i_size size of data to read in bytes
+ * @param[in] i_ecc true=verify and strip ECC after reading
+ * @param[in] o_data Buffer to copy data into
+ *
+ * @return Error from device
+ */
+ errlHndl_t readFromDevice (uint64_t i_procId,
+ PNOR::SectionId i_section,
+ uint64_t i_offset,
+ size_t i_size,
+ bool i_ecc,
+ void* o_data);
+
+ /**
+ * @brief Write data back to the PNOR device
+ * and injects ecc if necessary
+ *
+ * @param[in] i_procId processor id
+ * @param[in] i_section section of the pnor to write back
+ * @param[in] i_offset offset into the pnor
+ * @param[in] i_size size of data to read in bytes
+ * @param[in] i_ecc true=apply ECC before writing
+ * @param[in] i_src Buffer to copy data from
+ *
+ * @return Error from device
+ */
+ errlHndl_t writeToDevice( uint64_t i_procId,
+ PNOR::SectionId i_section,
+ uint64_t i_offset,
+ size_t i_size,
+ bool i_ecc,
+ void* i_src );
+
+ /**
+ * @brief Verify both TOC's and store section information from one of
+ * the verified TOC's
+ *
+ * @return Error from device
+ */
+ errlHndl_t readTOC();
+
+ //allow testcases to see inside the class
+ friend class PnorRtTest;
+
+ /**
+ * @brief Static instance function for testcase only
+ */
+ static RtPnor& getInstance();
+};
+
+#endif
diff --git a/src/usr/pnor/runtime/test/makefile b/src/usr/pnor/runtime/test/makefile
new file mode 100644
index 000000000..e53d87f15
--- /dev/null
+++ b/src/usr/pnor/runtime/test/makefile
@@ -0,0 +1,31 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/pnor/runtime/test/makefile $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2014,2015
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+HOSTBOOT_RUNTIME = 1
+ROOTPATH = ../../../../..
+
+MODULE = testpnor_rt
+TESTS = *.H
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/pnor/runtime/test/testpnor_rt.H b/src/usr/pnor/runtime/test/testpnor_rt.H
new file mode 100644
index 000000000..5a81ea9ac
--- /dev/null
+++ b/src/usr/pnor/runtime/test/testpnor_rt.H
@@ -0,0 +1,257 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/runtime/test/testpnor_rt.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2015 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include <cxxtest/TestSuite.H>
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include <devicefw/userif.H>
+
+#include <pnor/pnorif.H>
+#include "../../pnor_common.H"
+#include "../rt_pnor.H"
+
+#include <runtime/interface.h>
+#include <trace/interface.H>
+
+#include "../../ffs.h" //Common header file with BuildingBlock.
+#include "../../common/ffs_hb.H" //Hostboot def of user data in ffs_entry struct
+
+extern trace_desc_t* g_trac_pnor;
+using namespace TARGETING;
+
+/*
+ * these taest cases are turned off as they have dependency on pnorddtest cases
+ */
+class PnorRtTest : public CxxTest::TestSuite
+{
+ public:
+ /**
+ * @brief: testTOC
+ * tests that the TOC is read/parsed properly during runtime
+ */
+ void testTOC (void)
+ {
+#if 1
+ TRACFCOMP(g_trac_pnor, "PnorRtTest::testTOC - skipping - as it"
+ " adversly affects pnorddtests");
+#else
+ TRACFCOMP(g_trac_pnor, "PnorRtTest::testTOC Start" );
+ errlHndl_t l_err = NULL;
+ uint32_t l_proc = 0;
+ uint64_t offset = 0;
+ uint8_t* tocHeader = new uint8_t[PAGESIZE];
+ uint8_t* tocEntry = new uint8_t[PAGESIZE];
+ uint8_t* corruptBuffer = new uint8_t[PAGESIZE];
+
+ // Corrupt both ffs header and first entry for each TOC
+ for (uint32_t cur_TOC = 0; cur_TOC < PNOR::NUM_TOCS; ++cur_TOC)
+ {
+ uint32_t TOC_used = cur_TOC;
+ offset = (cur_TOC == 0) ? PNOR::TOC_0_OFFSET : PNOR::TOC_1_OFFSET;
+
+ // Read cur_TOC header data
+ l_err = RtPnor::getInstance().readFromDevice(l_proc,PNOR::TOC,
+ offset,PAGESIZE,false,tocHeader);
+ if (l_err)
+ {
+ TS_FAIL("PnorRtTest::testTOC: readFromDevice failed");
+ break;
+ }
+
+ // Corrupt cur_TOC header data
+ memcpy(corruptBuffer, tocHeader, PAGESIZE);
+ corruptBuffer[0] = 0xFF;
+ corruptBuffer[1] = 0xFF;
+
+ l_err = RtPnor::getInstance().writeToDevice(l_proc,PNOR::TOC,
+ offset,PAGESIZE,false,corruptBuffer);
+ if (l_err)
+ {
+ TS_FAIL("PnorRtTest::testTOC: writeToDevice failed");
+ }
+
+ // Check if cur_TOC failed that other TOC is used
+ l_err = RtPnor::getInstance().readTOC();
+ if (l_err)
+ {
+ TS_FAIL("PnorRtTest::testTOC: readTOC failed");
+ }
+
+ TOC_used = RtPnor::getInstance().iv_TOC_used;
+ TRACFCOMP(g_trac_pnor, "PnorRtTest::testTOC : TOC %d Corrupt"
+ " Header, Toc_used = %d", cur_TOC, TOC_used);
+
+ if (TOC_used == cur_TOC)
+ {
+ TS_FAIL("PnorRtTest::testTOC>ERROR:TOC %d header is corrupted,"
+ " did not use other TOC");
+ break;
+ }
+ // Fix cur_TOC header
+ l_err = RtPnor::getInstance().writeToDevice(l_proc,PNOR::TOC,
+ offset,PAGESIZE,false,tocHeader);
+ if (l_err)
+ {
+ TS_FAIL("PnorRtTest::testTOC: writeToDevice failed");
+ }
+
+ // Read cur_TOC first entry data
+ l_err = RtPnor::getInstance().readFromDevice(l_proc,PNOR::TOC,
+ offset+FFS_HDR_SIZE,PAGESIZE,false,tocEntry);
+ if (l_err)
+ {
+ TS_FAIL("PnorRtTest::testTOC: readTOC failed");
+ break;
+ }
+
+ // Corrupt cur_TOC header data
+ memcpy(corruptBuffer, tocEntry, PAGESIZE);
+ corruptBuffer[0] = 0xFF;
+ corruptBuffer[1] = 0xFF;
+
+ l_err = RtPnor::getInstance().writeToDevice(l_proc,PNOR::TOC,
+ offset+FFS_HDR_SIZE,PAGESIZE,false,corruptBuffer);
+ if (l_err)
+ {
+ TS_FAIL("PnorRtTest::testTOC: writeToDevice failed");
+ }
+
+ // Check if cur_TOC failed that other TOC is used
+ TOC_used = cur_TOC;
+ l_err = RtPnor::getInstance().readTOC();
+ if (l_err)
+ {
+ TS_FAIL("PnorRtTest::testTOC: readTOC failed");
+ }
+ TOC_used = RtPnor::getInstance().iv_TOC_used;
+ TRACFCOMP(g_trac_pnor,"PnorRtTest::testTOC:TOC %d Corrupt"
+ " Entry, Toc_used = %d", cur_TOC, TOC_used);
+
+ if (TOC_used == cur_TOC)
+ {
+ TS_FAIL("PnorRtTest::testTOC>ERROR: TOC %d entry is corrupted,"
+ " did not use other TOC", cur_TOC);
+ }
+
+ // Fix cur_TOC first entry
+ l_err = RtPnor::getInstance().writeToDevice(l_proc,PNOR::TOC,
+ offset+FFS_HDR_SIZE,PAGESIZE,false,tocEntry);
+ if (l_err)
+ {
+ TS_FAIL("PnorRtTest::testTOC: writeToDevice failed");
+ }
+ }
+
+ delete tocHeader;
+ delete tocEntry;
+ delete corruptBuffer;
+
+ TRACFCOMP(g_trac_pnor, "PnorRtTest::testTOC End");
+#endif
+ }
+
+ /**
+ * @brief RtPnor::testPnorReadWrite
+ * Compares the values read and written by runtime interfaces and
+ * IPL interfaces
+ */
+ void testPnorReadWrite(void)
+ {
+ TRACFCOMP(g_trac_pnor, ENTER_MRK"testPnorReadWrite");
+ do {
+ errlHndl_t l_err = NULL;
+ uint32_t l_proc = 0;
+ uint64_t l_offset = PNOR::pnorTestSec_rt_readwrite_offset;
+ uint64_t l_writeData = 0x0123456789ABCDEF;
+ PNOR::SectionId l_id = PNOR::TEST;
+ PNOR::SectionInfo_t l_info;
+
+ size_t l_sizeBytes = (RtPnor::getInstance().iv_TOC[l_id].size) -
+ l_offset;
+ void* l_readData = malloc (l_sizeBytes);
+
+ //read via hostInterfaces
+ l_err = RtPnor::getInstance().readFromDevice(l_proc,l_id,l_offset,
+ l_sizeBytes,true,l_readData);
+ if(l_err)
+ {
+ TS_FAIL("testPnorReadWrite: readFromDevice failed");
+ break;
+ }
+
+ //read using getSectionInfo
+ l_err = PNOR::getSectionInfo(l_id, l_info);
+ if (l_err)
+ {
+ TS_FAIL("testPnorReadWrite: getSectionInfo failed");
+ break;
+ }
+
+ void* l_gData = reinterpret_cast<void*> (l_info.vaddr);
+
+ //verify that data is read correctly
+ if (0 != memcmp (l_readData, l_gData, l_sizeBytes))
+ {
+ TS_FAIL("testPnorReadWrite: read failed");
+ break;
+ }
+ TRACFCOMP(g_trac_pnor, "testPnorReadWrite: read successfull");
+
+ /***********************************************************/
+ //make changes to the getSectionInfo pointer and call flush
+ uint8_t* l_vaddr = reinterpret_cast<uint8_t*>(l_info.vaddr);
+
+ memcpy(l_vaddr, &l_writeData, 4);
+ memcpy(l_vaddr+PAGESIZE+20, &l_writeData, 4);
+
+ l_err = PNOR::flush(l_id);
+ if (l_err)
+ {
+ TS_FAIL("testPnorReadWrite: flush failed");
+ break;
+ }
+
+ /***********************************************************/
+ //calling read again to make sure data was written properly
+ //using pnor_wirte
+ l_err = RtPnor::getInstance().readFromDevice(l_proc,l_id,l_offset,
+ l_sizeBytes,true,l_readData);
+ if(l_err)
+ {
+ TS_FAIL("testPnorReadWrite: readFromDevice failed");
+ break;
+ }
+
+ if (0 != memcmp (l_readData, l_gData, l_sizeBytes))
+ {
+ TS_FAIL("testPnorReadWrite: flush failed");
+ break;
+ }
+ TRACFCOMP(g_trac_pnor, "testPnorReadWrite: flush passed");
+
+ } while (0);
+ TRACFCOMP(g_trac_pnor, EXIT_MRK"testPnorReadWrite");
+ }
+
+};
diff --git a/src/usr/pnor/test/pnorrptest.H b/src/usr/pnor/test/pnorrptest.H
index 6c43f9d4a..0a8bc4945 100644
--- a/src/usr/pnor/test/pnorrptest.H
+++ b/src/usr/pnor/test/pnorrptest.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,2015 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -518,17 +518,17 @@ class PnorRpTest : public CxxTest::TestSuite
uint8_t* corruptBuffer = new uint8_t[PAGESIZE];
// Corrupt both ffs header and first entry for each TOC
- for (uint32_t cur_TOC = 0; cur_TOC < PnorRP::NUM_TOCS; ++cur_TOC)
+ for (uint32_t cur_TOC = 0; cur_TOC < PNOR::NUM_TOCS; ++cur_TOC)
{
uint32_t TOC_used = cur_TOC;
if (cur_TOC == 0)
{
- offset = PnorRP::TOC_0_OFFSET;
+ offset = PNOR::TOC_0_OFFSET;
}
else
{
- offset = PnorRP::TOC_1_OFFSET;
+ offset = PNOR::TOC_1_OFFSET;
}
// Read cur_TOC header data
diff --git a/src/usr/testcore/rtloader/loader.H b/src/usr/testcore/rtloader/loader.H
index b5d8aaa37..041337118 100644
--- a/src/usr/testcore/rtloader/loader.H
+++ b/src/usr/testcore/rtloader/loader.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -23,7 +25,6 @@
#ifndef __TESTCORE_RTLOADER_LOADER_H
#define __TESTCORE_RTLOADER_LOADER_H
-#include <pnor/pnorif.H>
#include <util/align.H>
#include <sys/mm.h>
#include <targeting/common/targetservice.H>
@@ -36,10 +37,14 @@
#include <sys/time.h>
#include <runtime/interface.h>
#include <vpd/vpd_if.H>
-
+#include <pnor/pnorif.H>
+#include <string.h>
+#include <devicefw/userif.H>
+#include <pnor/ecc.H>
trace_desc_t* g_trac_hbrt = NULL;
TRAC_INIT(&g_trac_hbrt, "HBRT_TEST", 2*KILOBYTE);
+extern const char* cv_EYECATCHER[];
class RuntimeLoaderTest : public CxxTest::TestSuite
{
@@ -115,6 +120,8 @@ class RuntimeLoaderTest : public CxxTest::TestSuite
intf->lid_load = rt_lid_load;
intf->lid_unload = rt_lid_unload;
intf->get_reserved_mem = rt_get_reserved_mem;
+ intf->pnor_read = rt_pnor_read;
+ intf->pnor_write= rt_pnor_write;
// Call init.
runtimeInterfaces_t* rtInterface =
@@ -310,6 +317,154 @@ class RuntimeLoaderTest : public CxxTest::TestSuite
return 0;
}
+
+ static PNOR::SectionId find_sectionId (const char* i_partitionName)
+ {
+ PNOR::SectionId l_id = PNOR::INVALID_SECTION;
+ for (size_t i=PNOR::FIRST_SECTION; i<=PNOR::NUM_SECTIONS;
+ ++i)
+ {
+ if (0 == strcmp(cv_EYECATCHER[i], i_partitionName))
+ {
+ l_id = (PNOR::SectionId)i;
+ break;
+ }
+ }
+ return l_id;
+ }
+
+ static int rt_pnor_read (uint32_t i_proc, const char* i_partitionName,
+ uint64_t i_offset, void* o_data, size_t i_sizeBytes)
+ {
+ TRACFCOMP(g_trac_hbrt, ENTER_MRK"rt_pnor_read: proc:%d, part:%s,"
+ " offset:0x%X, dataPtr:0x%X, size:0x%X",i_proc,
+ i_partitionName, i_offset, o_data, i_sizeBytes);
+
+ PNOR::SectionId l_id = PNOR::INVALID_SECTION;
+ PNOR::SectionInfo_t l_info;
+ errlHndl_t l_err = NULL;
+ uint32_t l_plid = 0;
+
+ do
+ {
+ TARGETING::Target* pnor_target =
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+
+ //search cv_EYECATHCER for partitionname
+ l_id = find_sectionId(i_partitionName);
+ if (l_id == PNOR::INVALID_SECTION)
+ {
+ TRACFCOMP(g_trac_hbrt, "rt_pnor_read: Invalid Section");
+ break;
+ }
+
+ //getSectionInfo -- this is PnorRP::getSectionInfo
+ l_err = PNOR::getSectionInfo(l_id, l_info);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_hbrt, "rt_pnor_read: getSectionInfo errored");
+ break;
+ }
+
+ // read far enough in the section so it doesn't collide
+ // with other test cases
+ if (l_id == PNOR::TEST)
+ {
+ //adjust the size of data if we are reading the entire sec
+ i_sizeBytes = (i_offset == 0)? (((l_info.size -
+ PNOR::pnorTestSec_rt_readwrite_offset)*9)/8) :
+ i_sizeBytes;
+ i_offset = ((PNOR::pnorTestSec_rt_readwrite_offset*9)/8);
+ }
+
+ uint32_t l_flashAddr= l_info.flashAddr + i_offset;
+
+ TRACFCOMP(g_trac_hbrt,"rt_pnor_read: calling"
+ " deviceRead: offset:0x%X, flashAddr:0x%X, size:0x%X",
+ i_offset, l_flashAddr, i_sizeBytes);
+
+ l_err = DeviceFW::deviceRead (pnor_target, o_data, i_sizeBytes,
+ DEVICE_PNOR_ADDRESS(i_proc, l_flashAddr));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_hbrt, "rt_pnor_read: deviceRead errored");
+ break;
+ }
+ } while (0);
+
+ //commit the error
+ if (l_err)
+ {
+ l_plid = l_err -> plid();
+ errlCommit(l_err,CXXTEST_COMP_ID);
+ }
+ TRACFCOMP(g_trac_hbrt, EXIT_MRK"rt_pnor_read");
+ return l_plid;
+ }
+
+
+ static int rt_pnor_write(uint32_t i_proc, const char* i_partitionName,
+ uint64_t i_offset, void* i_data, size_t i_sizeBytes)
+ {
+ TRACFCOMP(g_trac_hbrt, ENTER_MRK"rt_pnor_write: proc:%d, part:%s,"
+ " offset:0x%X, dataPtr:0x%X, size:0x%X",i_proc,
+ i_partitionName, i_offset, i_data, i_sizeBytes);
+
+ PNOR::SectionId l_id = PNOR::INVALID_SECTION;
+ PNOR::SectionInfo_t l_info;
+ errlHndl_t l_err = NULL;
+ uint32_t l_plid = 0;
+ do {
+
+ TARGETING::Target* pnor_target =
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+
+ //search cv_EYECATHCER for partitionname
+ l_id = find_sectionId(i_partitionName);
+ if (l_id == PNOR::INVALID_SECTION)
+ {
+ TRACFCOMP(g_trac_hbrt, "rt_pnor_write: Invalid section");
+ break;
+ }
+
+ //getSectionInfo - this is PnorRP::getSectionInfo
+ l_err = PNOR::getSectionInfo(l_id, l_info);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_hbrt, "rt_pnor_write: getSectionInfo errored");
+ break;
+ }
+
+ //fix the offset for the TEST section so that the testcases
+ //don't collide
+ i_offset = (PNOR::TEST) ? (i_offset+
+ ((PNOR::pnorTestSec_rt_readwrite_offset*9)/8)):i_offset;
+
+ uint32_t l_flashAddr = l_info.flashAddr + i_offset;
+
+ TRACFCOMP(g_trac_hbrt,"rt_pnor_write: calling"
+ " deviceWrite: offset:0x%X, flashAddr:0x%X, size:0x%X",
+ i_offset, l_flashAddr, i_sizeBytes);
+
+ l_err = DeviceFW::deviceWrite (pnor_target, i_data, i_sizeBytes,
+ DEVICE_PNOR_ADDRESS(i_proc, l_flashAddr));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_hbrt, "rt_pnor_write: deviceWrite errored");
+ break;
+ }
+ } while (0);
+
+ //commit the error
+ if (l_err)
+ {
+ l_plid = l_err -> plid();
+ errlCommit (l_err, CXXTEST_COMP_ID);
+ }
+ TRACFCOMP(g_trac_hbrt, EXIT_MRK"rt_pnor_write");
+ return l_plid;
+ }
+
//--------------------------------------------------------------------
static uint64_t rt_get_vpd()
{
OpenPOWER on IntegriCloud