summaryrefslogtreecommitdiffstats
path: root/src/usr/hdat
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/hdat')
-rw-r--r--src/usr/hdat/HBconfig5
-rwxr-xr-xsrc/usr/hdat/hdatbldda.C307
-rwxr-xr-xsrc/usr/hdat/hdatbldda.H151
-rw-r--r--src/usr/hdat/hdathbrt.C256
-rw-r--r--src/usr/hdat/hdathbrt.H272
-rwxr-xr-xsrc/usr/hdat/hdathdif.C542
-rwxr-xr-xsrc/usr/hdat/hdathdif.H398
-rwxr-xr-xsrc/usr/hdat/hdathostservices.C308
-rwxr-xr-xsrc/usr/hdat/hdathostservices.H243
-rwxr-xr-xsrc/usr/hdat/hdathostslcadata.C901
-rw-r--r--src/usr/hdat/hdathostslcadata.H144
-rw-r--r--src/usr/hdat/hdatiohub.C899
-rwxr-xr-xsrc/usr/hdat/hdatiohub.H500
-rwxr-xr-xsrc/usr/hdat/hdatiplparms.C1148
-rwxr-xr-xsrc/usr/hdat/hdatiplparms.H475
-rwxr-xr-xsrc/usr/hdat/hdatmsarea.C720
-rwxr-xr-xsrc/usr/hdat/hdatmsarea.H609
-rwxr-xr-xsrc/usr/hdat/hdatmsvpd.C2015
-rwxr-xr-xsrc/usr/hdat/hdatmsvpd.H936
-rw-r--r--src/usr/hdat/hdatnaca.C228
-rwxr-xr-xsrc/usr/hdat/hdatnodedata.C144
-rwxr-xr-xsrc/usr/hdat/hdatnodedata.H179
-rw-r--r--src/usr/hdat/hdatpcia.C626
-rwxr-xr-xsrc/usr/hdat/hdatpcia.H356
-rw-r--r--src/usr/hdat/hdatpcrd.C645
-rw-r--r--src/usr/hdat/hdatpcrd.H267
-rwxr-xr-xsrc/usr/hdat/hdatram.C194
-rwxr-xr-xsrc/usr/hdat/hdatram.H257
-rwxr-xr-xsrc/usr/hdat/hdatspiraH.C377
-rwxr-xr-xsrc/usr/hdat/hdatspiraH.H247
-rwxr-xr-xsrc/usr/hdat/hdatspiraS.C694
-rwxr-xr-xsrc/usr/hdat/hdatspiraS.H293
-rwxr-xr-xsrc/usr/hdat/hdatspsubsys.C521
-rwxr-xr-xsrc/usr/hdat/hdatspsubsys.H291
-rw-r--r--src/usr/hdat/hdatutil.C1351
-rwxr-xr-xsrc/usr/hdat/hdatutil.H396
-rwxr-xr-xsrc/usr/hdat/hdatvpd.C239
-rwxr-xr-xsrc/usr/hdat/hdatvpd.H248
-rw-r--r--src/usr/hdat/makefile51
39 files changed, 18433 insertions, 0 deletions
diff --git a/src/usr/hdat/HBconfig b/src/usr/hdat/HBconfig
new file mode 100644
index 000000000..7aa42ad40
--- /dev/null
+++ b/src/usr/hdat/HBconfig
@@ -0,0 +1,5 @@
+
+config ENABLE_HDAT_IN_HOSTBOOT
+ default y
+ help
+ Enable Initialization of Hypervisor Memory Space
diff --git a/src/usr/hdat/hdatbldda.C b/src/usr/hdat/hdatbldda.C
new file mode 100755
index 000000000..4f940cf91
--- /dev/null
+++ b/src/usr/hdat/hdatbldda.C
@@ -0,0 +1,307 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatbldda.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+
+/**
+ * @file hdatbldda.C
+ *
+ * @brief This file contains the implementation of functions which drive the
+ * building of hypervisor data areas.
+ */
+
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include "hdatbldda.H" // function prototypes and structures
+#include <vpd/pvpdenums.H>
+#include "hdatutil.H"
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include <assert.h>
+#include <attributeenums.H>
+#include <util/align.H>
+#include <limits.h>
+
+namespace HDAT
+{
+/*----------------------------------------------------------------------------*/
+/* Global variables */
+/*----------------------------------------------------------------------------*/
+
+
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+// Backplane keyword and record details
+static vpdData pvpdData[] =
+{
+ { PVPD::VINI, PVPD::DR },
+ { PVPD::VINI, PVPD::CE },
+ { PVPD::VINI, PVPD::VZ },
+ { PVPD::VINI, PVPD::FN },
+ { PVPD::VINI, PVPD::SN },
+ { PVPD::VINI, PVPD::CC },
+ { PVPD::VINI, PVPD::HE },
+ { PVPD::VINI, PVPD::CT },
+ { PVPD::VINI, PVPD::B3 },
+ { PVPD::VINI, PVPD::B4 },
+ { PVPD::VINI, PVPD::B7 },
+ { PVPD::VINI, PVPD::PF },
+ { PVPD::OPFR, PVPD::VP },
+ { PVPD::OPFR, PVPD::VS },
+ { PVPD::OPFR, PVPD::DR },
+ { PVPD::OPFR, PVPD::VN },
+ { PVPD::OSYS, PVPD::MM },
+ { PVPD::OSYS, PVPD::SS },
+};
+const HdatKeywordInfo l_pvpdKeywords[] =
+{
+ { PVPD::DR, "DR" },
+ { PVPD::CE, "CE" },
+ { PVPD::VZ, "VZ" },
+ { PVPD::FN, "FN" },
+ { PVPD::SN, "SN" },
+ { PVPD::CC, "CC" },
+ { PVPD::HE, "HE" },
+ { PVPD::CT, "CT" },
+ { PVPD::B3, "B3" },
+ { PVPD::B4, "B4" },
+ { PVPD::B7, "B7" },
+ { PVPD::PF, "PF" },
+ { PVPD::VP, "VP" },
+ { PVPD::VS, "VS" },
+ { PVPD::DR, "DR" },
+ { PVPD::VN, "VN" },
+ { PVPD::MM, "MM" },
+ { PVPD::SS, "SS" },
+};
+
+
+
+/**
+ * @brief See the prologue in hdatbldda.H
+ */
+errlHndl_t hdatProcessFru(const hdatMsAddr_t &i_msAddr,
+ const hdatSpiraDataAreas i_dataArea,
+ struct vpdData i_fetchVpd[],
+ const uint8_t i_size,
+ vpdType i_vpdtype,
+ uint32_t &o_count,
+ uint32_t &o_size)
+{
+ HDAT_ENTER();
+ errlHndl_t l_errlHndl = NULL;
+ HdatVpd *l_vpdObj;
+ const char *l_strName;
+ TARGETING::TargetHandleList l_targList;
+ TARGETING::ATTR_SLCA_RID_type l_hdatRID = 0;
+
+ // Get all the resource ids associated with this FRU type
+ hdatGetTarget(i_dataArea, l_targList);
+
+ uint8_t l_cnt = 0;
+ o_count = 0;
+ o_size = 0;
+
+ if (l_targList.size() == 0)
+ {
+ HDAT_DBG("got target list size as NULL");
+ return NULL;
+ }
+
+
+ uint64_t l_base_addr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo;
+ uint64_t l_base_addr_down = ALIGN_PAGE_DOWN(l_base_addr);
+ // As we dont know the exact size,
+ //hence updating random size which is bigger
+ //than actual we write to MS memory.
+ void *l_virt_addr = mm_block_map ( reinterpret_cast<void*>(l_base_addr_down),
+ (ALIGN_PAGE(2048) + PAGESIZE));
+
+ //TODO HdatVpd and HdatHdif class should provide the total size
+ o_size = 2048;
+ o_count = 1;
+
+ uint64_t l_final_addr = reinterpret_cast<uint64_t>(l_virt_addr);
+
+ l_final_addr += l_base_addr - l_base_addr_down;
+
+ l_virt_addr = reinterpret_cast<void *> (l_final_addr);
+
+ uint8_t *l_addr = static_cast <uint8_t*>( l_virt_addr);
+
+ if (HDAT_SYS_VPD == i_dataArea)
+ {
+ l_strName = HDAT_SYS_VPD_STRUCT_NAME;
+ }
+ else
+ {
+ l_strName = HDAT_FRU_VPD_STRUCT_NAME;
+ }
+
+ // Build a VPD object for each FRU
+ while (l_cnt < l_targList.size())
+ {
+ l_vpdObj = NULL;
+
+ if (NULL == l_errlHndl)
+ {
+ uint32_t l_num = i_size/sizeof (i_fetchVpd[0]);
+
+ assert((l_targList[l_cnt]->tryGetAttr<TARGETING::ATTR_SLCA_RID>
+ (l_hdatRID)));
+
+ // Construct the VPD object and write the flat data to a file
+ l_vpdObj = new HdatVpd(l_errlHndl,
+ l_hdatRID,
+ l_targList[l_cnt],
+ l_strName,
+ l_cnt,
+ i_vpdtype,
+ i_fetchVpd,
+ l_num,l_pvpdKeywords);
+
+
+ if (NULL == l_errlHndl)
+ {
+ l_addr = l_vpdObj->setVpd(l_addr);
+ }
+ else
+ {
+ delete l_vpdObj;
+ break;
+ }
+ delete l_vpdObj;
+ }
+ l_cnt++;
+ }
+
+ uint64_t l_addrData = reinterpret_cast<uint64_t> (l_virt_addr);
+ l_addrData = ALIGN_PAGE_DOWN(l_addrData);
+
+ l_virt_addr = reinterpret_cast<void*>(l_addrData);
+ int rc = mm_block_unmap(l_virt_addr);
+ if( rc != 0)
+ {
+ errlHndl_t l_errl = NULL;
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_PROCESS_FRU
+ * @reasoncode HDAT::RC_DEV_UNMAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PROCESS_FRU,
+ RC_DEV_UNMAP_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+
+ HDAT_EXIT();
+ return l_errlHndl;
+}
+
+
+/**
+ * @brief See the prologue in hdatbldda.H
+ */
+errlHndl_t hdatBldSpecificVpd(hdatSpiraDataAreas i_dataArea,
+ const hdatMsAddr_t &i_msAddr,
+ uint32_t &o_count,
+ uint32_t &o_size)
+{
+ HDAT_ENTER();
+
+ errlHndl_t l_errlHndl = NULL;
+ struct vpdData *l_data = NULL;
+ vpdType l_type = BP;
+ uint8_t l_size = 0;
+
+ // Determine which VPD structure to build. This assumes that i_dataArea
+ // is always a valid value. This is done to avoid more code bloat with
+ // a default leg to build an error log which should never occur.
+ switch (i_dataArea)
+ {
+ case HDAT_BACKPLANE_VPD:
+ case HDAT_SYS_VPD:
+ l_data = pvpdData;
+ l_size = sizeof(pvpdData);
+ l_type = BP;
+ break;
+
+ case HDAT_CLOCK_VPD:
+ l_type = CLOCK;
+ break;
+
+ case HDAT_ENCLOSURE_VPD:
+ l_type = ENCLOSURE;
+ break;
+
+ case HDAT_ANCHOR_VPD:
+ l_type = ANCHOR;
+ break;
+
+ case HDAT_MISC_CEC_VPD:
+ l_type = BP_EXT;
+ break;
+
+ default:
+ break;
+ }
+
+ // Build the VPD structure
+ l_errlHndl = hdatProcessFru(i_msAddr, i_dataArea,l_data,l_size,l_type,
+ o_count,o_size);
+
+ if (NULL != l_errlHndl)
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_BUILD_SPECIFIED_VPD
+ * @reasoncode HDAT::RC_PROCESS_FRU_FAIL
+ * @userdata1 Spira data area
+ * @userdata2 Hdat fru type
+ * @devdesc process fru funciton failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errlHndl,
+ MOD_BUILD_SPECIFIED_VPD,
+ RC_PROCESS_FRU_FAIL,
+ i_dataArea,l_type,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+
+ return l_errlHndl;
+}
+
+}
+
diff --git a/src/usr/hdat/hdatbldda.H b/src/usr/hdat/hdatbldda.H
new file mode 100755
index 000000000..84dc6a649
--- /dev/null
+++ b/src/usr/hdat/hdatbldda.H
@@ -0,0 +1,151 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatbldda.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATBLDDA_H
+#define HDATBLDDA_H
+
+
+/**
+ * @file hdatbldda.H
+ *
+ * @brief This file contains the interfaces for building hypervisor data
+ * areas.
+ */
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <stdint.h> // standard types
+#include <hdat/hdat.H> // HDAT header type definitions
+#include "hdatvpd.H"
+#include <errl/errlentry.H> // ErrlEntry class definition
+#include <hdat/hdat_reasoncodes.H>
+
+namespace HDAT
+{
+
+/** @brief Constant for the eye catcher for VPD structures
+ */
+const char HDAT_FRU_VPD_STRUCT_NAME[] = "FRUVPD";
+const char HDAT_SYS_VPD_STRUCT_NAME[] = "SYSVPD";
+
+
+/** @enum hdatSpiraDataAreas
+ * This enumeration defines the various data areas that must be built
+ T_MISC_VPD_FILE_NAME
+ * processor.
+ * This list must be kept in the same order as the 5-tuple entries in
+ * the SPIRA.
+ *
+ * If the order is changed, entries are added, or entries are deleted,
+ * update the HDAT_STR_NAME array in hdatPrtSpira().
+ */
+enum hdatSpiraDataAreas
+{
+ HDAT_SPIRA_DA_FIRST = 0,
+ HDAT_SP_SUBSYS = 0, // service processor subsystem
+ HDAT_IPL_PARAMS = 1, // IPL parameters
+ HDAT_ENCLOSURE_VPD = 2, // enclosure vital product data
+ HDAT_SLCA = 3, // slot location code array
+ HDAT_BACKPLANE_VPD = 4, // backplane vital product data
+ HDAT_SYS_VPD = 5, // system vital product data
+ HDAT_CHIP_TOD = 6, // chip time-of-day
+ HDAT_PROC_INIT = 7, // phyp-supplied processor init data
+ HDAT_CLOCK_VPD = 8, // clock vital product data
+ HDAT_ANCHOR_VPD = 9, // anchor card vital product data
+ HDAT_OP_PNL_VPD = 10, // operator panel vital product data
+ HDAT_L3_VPD = 11, // level 3 cache vital product data
+ HDAT_MISC_CEC_VPD = 12, // miscellaneous FRU vital product data
+ HDAT_PACA = 13, // processor address communication area
+ HDAT_MDT = 14, // memory description tree
+ HDAT_IO_HUB = 15, // I/O hub FRU array
+ HDAT_CPU_CTRL = 16, // CPU controls
+ HDAT_MS_DUMP_SRC_TBL = 17, // mainstore dump source table (can change at run time)
+ HDAT_MS_DUMP_DST_TBL = 18, // mainstore dump destination table (can change at run time)
+ HDAT_MS_DUMP_RSLT_TBL = 19, // mainstore dump results table
+ HDAT_SPIRA_DA_GA1LAST = 20, // End of list for 1st eclipz release
+ HDAT_HEAP = 20, // Phyp allocated storage location for most of the data
+ HDAT_SPIRA_OLDPACA_LAST = 21, // This was last entry for old PACA format. //bs01a
+
+ HDAT_PCIA = 21, // PCIA (Core information area) starting out on P7+ //bs01a
+ HDAT_PCRD = 22, // PCRD (Chip related data area) starting out on P7+ //bs01a
+ HDAT_HOSTSR = 23, // HOSTSR (Host service data) starting out on P8 //rij01A
+ HDAT_SPIRA_DA_LAST = 24 //bs01c
+};
+
+/**
+ * @brief The routines in this file drive the building of the various hypervisor
+ * data areas
+ *
+ * @pre
+ *
+ * @post
+ *
+ * @param[in] i_dataArea - An identifier for the specific data area
+ * @param[in] i_msAddr - The main store address where this data area
+ * will be written to.
+ * @param[out] o_count - number of instance of each area
+ * @param[out] o_size - actual size wrote to memory
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ */
+
+/* Build the specific VPD data areas */
+errlHndl_t hdatBldSpecificVpd(hdatSpiraDataAreas i_dataArea,
+ const hdatMsAddr_t &i_msAddr,
+ uint32_t &o_count,
+ uint32_t &o_size);
+
+/**
+ * @brief This function build vpd structure and write the data to MS memory.
+ *
+ * @pre
+ *
+ * @post
+ *
+ * @param[in] i_msAddr - The main store address where this data area
+ * @param[in] i_dataArea - An identifier for the specific data area
+ * will be written to.
+ * @param[in] i_fetchVpd - VPD record and keyword details
+ * @param[in] i_size - number of entries in VPD table
+ * @param[in] i_vpdtype - type of fru
+ * @param[out] o_count - number of instance of each area
+ * @param[out] o_size - actual size wrote to memory
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ */
+errlHndl_t hdatProcessFru(const hdatMsAddr_t &i_msAddr,
+ const hdatSpiraDataAreas i_dataArea,
+ struct vpdData i_fetchVpd[],
+ const uint8_t i_size,
+ vpdType i_vpdtype,
+ uint32_t &o_count,
+ uint32_t &o_size);
+};
+#endif //HDATBLDDA_H
diff --git a/src/usr/hdat/hdathbrt.C b/src/usr/hdat/hdathbrt.C
new file mode 100644
index 000000000..257fdce93
--- /dev/null
+++ b/src/usr/hdat/hdathbrt.C
@@ -0,0 +1,256 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdathbrt.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 <hdat/hdat.H>
+#include "hdathbrt.H"
+#include <targeting/common/util.H>
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include <util/align.H>
+
+using namespace TARGETING;
+
+
+namespace HDAT
+{
+
+
+ errlHndl_t loadHbrt(const hdatMsAddr_t &i_msAddr,
+ uint32_t &o_size , uint32_t &o_count)
+ {
+ HDAT_ENTER();
+ errlHndl_t l_err = NULL;
+ HdatHbrt *l_hbrt = NULL;
+
+
+ //fetch the target attributes
+ do {
+ TARGETING::Target *l_pSysTarget = NULL;
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSysTarget);
+
+ if ( NULL == l_pSysTarget )
+ {
+ HDAT_ERR("Error in getting Top Level Target");
+ assert (l_pSysTarget != NULL);
+ }
+ TARGETING::ATTR_HDAT_HBRT_NUM_SECTIONS_type
+ l_numHbRuntimeDataSections =
+ l_pSysTarget->getAttr<TARGETING::ATTR_HDAT_HBRT_NUM_SECTIONS>();
+
+ TARGETING::ATTR_HDAT_HBRT_SECTION_SIZE_type
+ l_sizeHbRuntimeDataSections= {};
+
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_HDAT_HBRT_SECTION_SIZE>(
+ l_sizeHbRuntimeDataSections) == false )
+ {
+ HDAT_ERR ("tryGetAttr of ATTR_HDAT_HBRT_SECTION_SIZE returned"
+ "false");
+
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_HBRT_LOAD_DATA
+ * @reasoncode HDAT::RC_TGT_ATTR_NOTFOUND
+ * @devdesc The target attribute not found
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_err,
+ MOD_HBRT_LOAD_DATA,
+ RC_TGT_ATTR_NOTFOUND,
+ 0,0,0,0);
+ break;
+ }
+
+
+ l_hbrt = new HdatHbrt(l_err,i_msAddr,
+ (uint32_t)l_numHbRuntimeDataSections,
+ l_sizeHbRuntimeDataSections);
+
+
+ o_size = l_hbrt->size();
+ o_count = HBRT_INSTANCE + 1;
+
+
+ l_err = l_hbrt->setHbrt(l_sizeHbRuntimeDataSections,o_size);
+
+ HDAT_DBG("done building hbrt data, size = 0x%x, count= 0x%x",
+ o_size,o_count);
+
+
+ }while(0);
+
+
+ if ( l_hbrt )
+ {
+ delete l_hbrt;
+ }
+
+ HDAT_EXIT();
+ return l_err;
+ }//end loadHbrt
+
+
+HdatHbrt::HdatHbrt(errlHndl_t &o_errlHndl,const hdatMsAddr_t &i_msAddr,
+ const uint32_t i_numHbrtSections,uint64_t i_sizeHbrtSections[])
+:HdatHdif(o_errlHndl,HDAT_HBRT_STRUCT_NAME, i_numHbrtSections,
+ HBRT_INSTANCE, HDAT_HBRT_CHILD_COUNT, HDAT_HBRT_VERSION)
+{
+ HDAT_ENTER();
+
+ memcpy(&iv_msAddr, &i_msAddr, sizeof(hdatMsAddr_t));
+ iv_numHbrtSections = i_numHbrtSections;
+
+ for ( uint32_t l_loopCnt = 0; l_loopCnt < iv_numHbrtSections; l_loopCnt++ )
+ {
+ this->addData(l_loopCnt,
+ (sizeof(hdatHbrtData_t) + i_sizeHbrtSections[l_loopCnt]));
+ }
+ this->align();
+
+ HDAT_EXIT();
+}//end constructor
+
+
+HdatHbrt::~HdatHbrt()
+{
+ //free heap storage if any
+}
+
+
+errlHndl_t HdatHbrt::setHbrt( uint64_t i_sizeHbrtSections[],uint32_t i_size)
+{
+ errlHndl_t l_err = NULL;
+ hdatHbrtData_t *l_hdatHbrtData_t = NULL;
+ HDAT_ENTER();
+
+
+ //first do block map
+ //total size reqd is size of hdif + (size of hbrt * number of hbrt sections)
+ uint64_t i_base_addr = ((uint64_t) iv_msAddr.hi << 32) | iv_msAddr.lo;
+ uint64_t i_base_addr_down = ALIGN_PAGE_DOWN(i_base_addr);
+
+
+
+ void *l_virt_addr = mm_block_map (
+ reinterpret_cast<void*>(i_base_addr_down),
+ ALIGN_PAGE(i_size) + PAGESIZE);
+
+
+ uint64_t l_vaddr = reinterpret_cast<uint64_t>(l_virt_addr);
+ l_vaddr += i_base_addr-i_base_addr_down;
+
+ l_virt_addr = reinterpret_cast<void *>(l_vaddr);
+
+ memset(l_virt_addr ,0x0, i_size);
+ uint8_t* io_virt_addr = reinterpret_cast<uint8_t *>(l_virt_addr);
+
+ uint8_t* l_startAddr = io_virt_addr;
+ HDAT_DBG("io_virt_addr=0x%016llX, l_virt_addr=0x%016llX",
+ (uint64_t)io_virt_addr,(uint64_t)l_virt_addr);
+
+ io_virt_addr = this->setHdif(io_virt_addr);
+
+ HDAT_DBG("after writing HDIF header address now 0x%016llX",
+ (uint64_t)io_virt_addr);
+
+ //now write the hbrt struct iv_numHbrtSections times
+
+ uint32_t l_commonOffset = sizeof(hdatHDIF_t) +
+ (iv_numHbrtSections * sizeof(hdatHDIFDataHdr_t))+
+ sizeof(hdatHbrtData_t);
+
+ HDAT_DBG("common offset added to each is 0x%x",l_commonOffset);
+
+ for (uint32_t i =0; i< iv_numHbrtSections; i++)
+ {
+ l_hdatHbrtData_t = reinterpret_cast<hdatHbrtData_t *>
+ (io_virt_addr);
+ l_hdatHbrtData_t->hdatHbrtBlobData.hdatSize =
+ i_sizeHbrtSections[i];
+
+ l_hdatHbrtData_t->hdatHbrtBlobData.hdatOffset = l_commonOffset;
+
+ HDAT_DBG("hdatSize=0x%x, offset=0x%x",i_sizeHbrtSections[i],
+ l_hdatHbrtData_t->hdatHbrtBlobData.hdatOffset);
+
+ l_commonOffset += i_sizeHbrtSections[i] + sizeof(hdatHbrtData_t);
+
+ HDAT_DBG("next offset is 0x%x+0x%x=0x%x more",i_sizeHbrtSections[i],
+ sizeof(hdatHbrtData_t),(i_sizeHbrtSections[i]+sizeof(hdatHbrtData_t)));
+
+
+ io_virt_addr = reinterpret_cast<uint8_t *>(l_hdatHbrtData_t);
+
+ io_virt_addr += sizeof(hdatHbrtData_t) + i_sizeHbrtSections[i];
+
+ }//end for
+
+
+ //add the pad after writing all the hbrt objects
+ uint32_t l_rem = i_size % 128;
+ uint32_t l_pad = l_rem ? (128 - l_rem) : 0;
+
+ for (uint32_t i=0; i < l_pad; i++)
+ {
+ io_virt_addr[i] = '\0';
+ }
+ HDAT_DBG("wrote pad of 0x%x size after hbrt object",l_pad);
+
+ //unmap the region
+ int rc = 0;
+
+ rc = mm_block_unmap(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(
+ reinterpret_cast<uint64_t>(l_startAddr))));
+
+ if ( rc != 0 )
+ {
+ HDAT_ERR("unmap of hbrt region failed");
+ hdatMsAddr_t l_tmpaddr = {0};
+
+ if ( l_startAddr )
+ {
+ memcpy(&l_tmpaddr,(void*)l_startAddr,sizeof(hdatMsAddr_t));
+ }
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_HBRT_LOAD_DATA
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_err,
+ MOD_HBRT_LOAD_DATA,
+ RC_DEV_MAP_FAIL,
+ l_tmpaddr.hi,l_tmpaddr.lo,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+
+ }
+
+
+ HDAT_EXIT();
+ return l_err;
+}//end setHbrt
+
+}//end namespace
diff --git a/src/usr/hdat/hdathbrt.H b/src/usr/hdat/hdathbrt.H
new file mode 100644
index 000000000..46d7b165e
--- /dev/null
+++ b/src/usr/hdat/hdathbrt.H
@@ -0,0 +1,272 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdathbrt.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATHBRT_H
+#define HDATHBRT_H
+
+/**
+ * @file hdathbrt.H
+ *
+ * @brief This file contains the class definition for the Host boot runtime
+ * data object.
+ *
+ */
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+
+#include <stdint.h>
+#include <errl/errlentry.H>
+#include <hdat/hdat.H>
+#include <hdat/hdat_reasoncodes.H>
+#include "hdatutil.H"
+#include "hdathdif.H"
+
+namespace HDAT
+{
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/** @brief eye catcher for the HDIF header for the Host boot runtime data
+ */
+const char HDAT_HBRT_STRUCT_NAME[] = "HBRT ";
+
+/** @enum hdatHbrtDataPtrs
+ * Constants for the internal data pointers that are added to the base
+ * class
+ */
+enum hdatHBrtDataPtrs
+{
+ HDAT_HBRT_ATTRIBUTE = 0
+};
+
+/** @enum hdatHbrtChildPtrs
+ * Constants for the child structure pointers that are added to the base
+ * class
+ */
+enum hdatHbrtChildPtrs
+{
+ HDAT_HBRT_CHILD_COUNT = 0
+};
+
+/** @brief Host boot runtime version number
+ *
+ */
+const uint16_t HDAT_HBRT_VERSION = 0x0010;
+
+/** @brief Host boot runtime string lablel size
+ *
+ */
+#define HDAT_HBRT_STRING_LABEL_SIZE 24
+
+/** @brief HBRT structure instance
+ * */
+#define HBRT_INSTANCE 0
+
+
+/*----------------------------------------------------------------------------*/
+/* Type definitions */
+/*----------------------------------------------------------------------------*/
+
+
+/** @brief Host boot runtime data section. Host boot data updated will be
+ * populated in this structure format.
+ *
+ */
+struct hdatHbrtData_t
+{
+ uint8_t hdatHbrtStringLabel[HDAT_HBRT_STRING_LABEL_SIZE];
+ //0x0000 : String Label
+ uint32_t hdatHbrtInstanceNum; //0x0018 : Instance Number
+ hdatHDIFDataHdr_t hdatHbrtBlobData; //0x001C : Pointer to Data Blob
+ uint32_t hdatHbrtReserved1; //0x0024 : Reserved1
+ uint32_t hdatHbrtReserved2; //0x0028 : Reserved2
+ uint32_t hdatHbrtReserved3; //0x002C : Reserved3
+} __attribute__ ((packed));
+
+
+/*----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatHbrt class is used to construct Host boot runtime data
+ * objects.
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that any component can create an object of this type. In
+ * particular, the object is built only in the CEC Server process
+ * when requested by the hdat component.
+ *
+ * The real purpose of the object is to create the Host boot
+ * runtime data as defined by the PHYP Initialization
+ * architecture and is written to
+ * main memory. The class is not defined to be a general purpose
+ * interface for building this object by anyone other than the
+ * CEC Server process.
+ *
+ * Thread safety: An HdatHbrt object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by multiple
+ * threads at the same time.
+ *
+ * Signal handler usage: This class is not intended to be used in a signal
+ * handler and nothing has been done to try and make it
+ * safe to use in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatHbrt : public HdatHdif
+{
+ public:
+
+
+ /**
+ * @brief Construct an HdatHbrt object.
+ *
+ * This is the constructor for the HdatHbrt object when that Host
+ * boot runtime data is not currently plugged but has been reserved
+ * for concurrent maintenance.
+ *
+ * If you are constructing this object on the heap by using new,
+ * then you must check the pointer returned from new to see if it
+ * is null. If it is null, new failed to allocate storage and the
+ * constructor was not called. If it is not null, then you must
+ * check o_errlHndl to see if the constructor ran successfully. If
+ * o_errlHndl indicates an error was reported by the constructor,
+ * new has already allocated heap storage and the object must be
+ * deleted in order to free the heap storage.
+ *
+ * @pre None
+ *
+ * @post An HdatHbrt object has been constructed. Heap storage has
+ * been allocated.
+ *
+ * @param[out] o_errlHndl
+ * If any errors occur, the HdatHbrt object is NOT constructed and
+ * errors are returned in this parameter
+ * @param[in] i_msAddr
+ * The main memory address that the Host boot runtime data that
+ * will be written to
+ * @param[in] i_numHbrtSections
+ * Number of host boot runtime sections
+ * @param[in] i_sizeHbrtSections
+ * HBRT section blob size array
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl contains one of retval
+ *
+ * @retval HDAT_ALLOC_ERROR
+ */
+ HdatHbrt(errlHndl_t &o_errlHndl, const hdatMsAddr_t &i_msAddr,
+ const uint32_t i_numHbrtSections,uint64_t i_sizeHbrtSections[]);
+
+
+ /**
+ * @brief HdatHbrt object destructor
+ *
+ * This is the destructor for an HdatHbrt object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatHbrt object has been destroyed and can no longer be
+ * used.
+ *
+ */
+ virtual ~HdatHbrt();
+
+
+ /**
+ * @brief write an HdatHbrt object.
+ *
+ * This method must be called when the HdatHbrt object has been
+ * completed. That is, the object was constructed and all data has
+ * been added to object.
+ *
+ *
+ * @pre All informaton that is needed in the object must have been put
+ * there by the constructor or other methods.
+ *
+ * @post The object data is written to main memory
+ *
+ * @param[in] i_sizeHbrtSections
+ * Size of each of the host boot runtime sections
+ * @param[in] i_size
+ * The size of this and all previous objects.Needed to calculate
+ * the memory size which will be allocated.
+ * @param[out] o_count
+ * The count of all objects which have been committed. This value
+ * from the last object which is committed must be returned to the
+ * hdat component
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by errlHndl_t contains one of the retval
+ *
+ */
+ errlHndl_t setHbrt(uint64_t i_sizeHbrtSections[],uint32_t i_size);
+
+ private:
+
+ /** Object Instance Data
+ *
+ * @li iv_msAddr - main memory address the final data structure
+ * is written to
+ * @li iv_numHbrtSections - number of hbrt data sections
+ */
+ hdatMsAddr_t iv_msAddr;
+ uint32_t iv_numHbrtSections;
+
+
+}; // end of HdatHbrt class
+
+
+/*
+ * @brief main function to load an hbrt object into main memory. This
+ * function is called from Spiras while loading all the data areas.
+ *
+ * @pre All the previous data areas have been loaded to main memory
+ *
+ * @post HBRT is written to main memory
+ *
+ * @param[in] i_msAddr
+ * The main memory address where HBRT is written to
+ *
+ * @param[out] o_size
+ * Total size written
+ *
+ * @param[out] o_count
+ * Number of HBRT data structures
+ */
+
+errlHndl_t loadHbrt(const hdatMsAddr_t &i_msAddr,
+ uint32_t &o_size , uint32_t &o_count);
+
+
+}//end namespace
+
+#endif // HDATHBRT_H
+
diff --git a/src/usr/hdat/hdathdif.C b/src/usr/hdat/hdathdif.C
new file mode 100755
index 000000000..1533ddbe2
--- /dev/null
+++ b/src/usr/hdat/hdathdif.C
@@ -0,0 +1,542 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdathdif.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+/**
+ * @file hdathdif.C
+ *
+ * @brief This file contains the implementation of the HdatHdif class.
+ *
+ */
+
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include "hdathdif.H"
+#include "hdatutil.H"
+
+
+namespace HDAT
+{
+
+/*----------------------------------------------------------------------------*/
+/* Global variables */
+/*----------------------------------------------------------------------------*/
+extern trace_desc_t * g_hdatTraceDesc;
+
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+const uint32_t HDAT_BOUNDARY = 16; // Pad structures to a 16 byte boundary
+const char HDAT_PAD[15] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
+
+
+/** @brief See the prologue in hdathdif.H
+ */
+HdatHdif::HdatHdif()
+{
+}
+
+
+/** @brief See the prologue in hdathdif.H
+ */
+HdatHdif::HdatHdif(errlHndl_t &o_errlHndl,
+ const char i_eyeCatcher[],
+ uint32_t i_dataPtrCnt,
+ uint32_t i_instance,
+ uint32_t i_childCnt,
+ uint32_t i_ver)
+:iv_totalSize(0), iv_padSize(0),iv_siblingPadSize(0),iv_dataPtrSize(0),
+iv_childPtrSize(0),iv_dataPtrs(NULL), iv_childPtrs(NULL)
+{
+ HDAT_ENTER();
+
+ const uint32_t HDAT_MULTIPLE = 16;
+ uint32_t l_mod;
+
+ o_errlHndl = NULL;
+
+ iv_hdr.hdatStructId = HDAT_HDIF_STRUCT_ID;
+ iv_hdr.hdatInstance = i_instance;
+ iv_hdr.hdatVersion = i_ver;
+ iv_hdr.hdatSize = sizeof(hdatHDIF_t);
+ iv_hdr.hdatHdrSize = sizeof(hdatHDIF_t);
+ iv_hdr.hdatDataPtrOffset = 0;
+ iv_hdr.hdatDataPtrCnt = 0;
+ iv_hdr.hdatChildStrOffset = 0;
+ iv_hdr.hdatChildStrCnt = 0;
+
+ memcpy(iv_hdr.hdatStructName, i_eyeCatcher, sizeof(iv_hdr.hdatStructName));
+
+ if (i_dataPtrCnt > 0)
+ {
+ iv_hdr.hdatDataPtrOffset = iv_hdr.hdatSize;
+ iv_dataPtrSize = i_dataPtrCnt * sizeof(hdatHDIFDataHdr_t);
+ iv_dataPtrs = reinterpret_cast<hdatHDIFDataHdr_t *>(calloc(i_dataPtrCnt,
+ sizeof(hdatHDIFDataHdr_t)));
+ iv_hdr.hdatSize += iv_dataPtrSize;
+ }
+
+ if (NULL == o_errlHndl && i_childCnt > 0)
+ {
+ iv_hdr.hdatChildStrOffset = iv_hdr.hdatSize;
+
+ iv_childPtrSize = i_childCnt * sizeof(hdatHDIFChildHdr_t);
+ l_mod = iv_childPtrSize % HDAT_MULTIPLE;
+ if (l_mod > 0)
+ {
+ iv_childPtrSize += HDAT_MULTIPLE - l_mod;
+ }
+
+ iv_childPtrs = reinterpret_cast<hdatHDIFChildHdr_t *>
+ (calloc(iv_childPtrSize, 1));
+ iv_hdr.hdatSize += iv_childPtrSize;
+ }
+
+ iv_totalSize = iv_hdr.hdatSize;
+ HDAT_EXIT();
+}//end constructor
+
+/** @brief See the prologue in hdathdif.H
+ */
+HdatHdif::~HdatHdif()
+{
+ HDAT_ENTER();
+ free(iv_dataPtrs);
+ free(iv_childPtrs);
+ HDAT_EXIT();
+}
+
+
+/** @brief See the prologue in hdathdif.H
+ */
+uint32_t HdatHdif::size()
+{
+ return iv_hdr.hdatSize;
+}
+uint32_t HdatHdif::getSize()
+{
+ uint32_t l_size = 0;
+
+ l_size += sizeof(iv_hdr);
+
+ if (NULL != iv_dataPtrs)
+ {
+ l_size += iv_dataPtrSize;
+ }
+
+ if (NULL != iv_childPtrs)
+ {
+ l_size += iv_childPtrSize;
+ }
+ return l_size;
+}
+/** @brief See the prologue in hdathdif.H
+ */
+void HdatHdif::chgChildOffset(uint32_t i_whichChildEntry,
+ uint32_t i_offset)
+{
+ hdatHDIFChildHdr_t *l_hdr;
+
+ // If there are child structures, change the offset of the selected triple
+ // entry
+ if (iv_hdr.hdatChildStrCnt > 0)
+ {
+ l_hdr = reinterpret_cast<hdatHDIFChildHdr_t *>(reinterpret_cast<char *>
+ (iv_childPtrs) + sizeof(hdatHDIFChildHdr_t) *
+ i_whichChildEntry);
+ l_hdr->hdatOffset = i_offset;
+ }
+
+ return;
+}
+
+
+
+/** @brief See the prologue in hdathdif.H
+ */
+void HdatHdif::addChild(uint32_t i_whichChildEntry,
+ uint32_t i_size,
+ uint32_t i_numChildStr)
+{
+ HDAT_ENTER();
+
+ hdatHDIFChildHdr_t *l_childHdr;
+
+ iv_hdr.hdatChildStrCnt = i_whichChildEntry + 1; //(0 based index plus 1)
+
+ // Address the child entry
+ l_childHdr = reinterpret_cast<hdatHDIFChildHdr_t *>(reinterpret_cast<char *>
+ (iv_childPtrs) +
+ sizeof(hdatHDIFChildHdr_t) * i_whichChildEntry);
+
+ // Update child entry information
+
+ // If not yet done, set offset to first child structure. Child structures
+ // are contiguous after the first and are all the same size.
+ if (0 == l_childHdr->hdatOffset)
+ {
+ l_childHdr->hdatOffset = iv_totalSize;
+ l_childHdr->hdatSize = i_size;
+ }
+ l_childHdr->hdatCnt++;
+
+ // Increment total object size by child's size
+ iv_totalSize += i_size;
+
+ HDAT_EXIT();
+ return;
+}
+
+
+/** @brief See the prologue in hdathdif.H
+ */
+void HdatHdif::addGrandChild(uint32_t i_size)
+{
+
+ // Increment total object size by the grandchild's size
+ iv_totalSize += i_size;
+
+ return;
+}
+
+
+/** @brief See the prologue in hdathdif.H
+ */
+void HdatHdif::addData(uint32_t i_whichDataEntry,
+ uint32_t i_size)
+{
+ HDAT_ENTER();
+
+ hdatHDIFDataHdr_t *l_dataHdr;
+
+ l_dataHdr = reinterpret_cast<hdatHDIFDataHdr_t *>(reinterpret_cast<char *>
+ (iv_dataPtrs) +
+ sizeof(hdatHDIFDataHdr_t) * i_whichDataEntry);
+
+ // Update data entry information if there is any data
+ if (i_size > 0)
+ {
+ l_dataHdr->hdatOffset = iv_hdr.hdatSize;
+ l_dataHdr->hdatSize = i_size;
+ }
+ // Increment total object size by data's size and increment
+ // count of data entries
+ iv_hdr.hdatSize += i_size;
+ iv_totalSize += i_size;
+ iv_hdr.hdatDataPtrCnt++;
+
+ HDAT_EXIT();
+ return;
+}
+
+
+/** @brief See the prologue in hdathdif.H
+ */
+void HdatHdif::maxSiblingSize(uint32_t i_numBytes)
+{
+
+ if (i_numBytes > iv_hdr.hdatSize)
+ {
+ iv_siblingPadSize = i_numBytes - iv_hdr.hdatSize;
+ iv_hdr.hdatSize += iv_siblingPadSize;
+ iv_totalSize += iv_siblingPadSize;
+ }
+
+}
+
+
+
+
+/** @brief See the prologue in hdathdif.H
+ */
+void HdatHdif::align()
+{
+ uint32_t l_rem;
+
+ // If the structure length is not a multiple of the boundary
+ // requirement, compute the number of pad bytes needed
+ l_rem = iv_hdr.hdatSize % HDAT_BOUNDARY;
+
+ if (l_rem > 0)
+ {
+ iv_padSize = HDAT_BOUNDARY - l_rem;
+ iv_hdr.hdatSize += iv_padSize;
+ iv_totalSize += iv_padSize;
+ }
+
+ return;
+}
+
+uint8_t * HdatHdif::setHdif(uint8_t * io_virt_addr)
+{
+ HDAT_DBG("virtual address=0x%016llX",
+ (uint64_t)io_virt_addr);
+
+ uint8_t *l_temp = NULL;
+
+ // If no children were ever added, ensure offset to child pointers is 0
+ if (0 == this->iv_hdr.hdatChildStrCnt)
+ {
+ HDAT_DBG(" no child information were addded");
+ this->iv_hdr.hdatChildStrOffset = 0;
+ }
+
+ //first write the hdatHDIF_t iv_hdr
+ hdatHDIF_t * l_hdatHDIF= reinterpret_cast<hdatHDIF_t *>(io_virt_addr);
+
+
+ l_hdatHDIF->hdatStructId = this->iv_hdr.hdatStructId;
+ l_hdatHDIF->hdatInstance = this->iv_hdr.hdatInstance;
+ l_hdatHDIF->hdatVersion = this->iv_hdr.hdatVersion;
+ l_hdatHDIF->hdatSize = this->iv_hdr.hdatSize;
+ l_hdatHDIF->hdatHdrSize = this->iv_hdr.hdatHdrSize;
+ l_hdatHDIF->hdatDataPtrOffset = this->iv_hdr.hdatDataPtrOffset;
+ l_hdatHDIF->hdatDataPtrCnt = this->iv_hdr.hdatDataPtrCnt;
+ l_hdatHDIF->hdatChildStrCnt = this->iv_hdr.hdatChildStrCnt;
+ l_hdatHDIF->hdatChildStrOffset = this->iv_hdr.hdatChildStrOffset;
+
+ memcpy(l_hdatHDIF->hdatStructName,iv_hdr.hdatStructName,
+ sizeof(iv_hdr.hdatStructName));
+
+ //cast back to uint8_t and increment the pointer by size of
+ //hdatHDIF_t to point the next
+
+ l_temp = reinterpret_cast<uint8_t *>(l_hdatHDIF);
+ l_temp += this->iv_hdr.hdatDataPtrOffset;
+
+ HDAT_DBG("sizeof HDIF header=%x",sizeof(hdatHDIF_t));
+
+ //write data pointer array hdatHDIFDataHdr_t *iv_dataPtrs
+ hdatHDIFDataHdr_t *l_hdatHDIFDataHdr =
+ reinterpret_cast<hdatHDIFDataHdr_t *>(l_temp);
+
+ HDAT_DBG("writing Data pointers array from address=0x%016llX",
+ (uint64_t)l_hdatHDIFDataHdr);
+
+ //total number of data pointer header is HDAT_PARENT_LAST,
+ //actual filled up number is
+ //this->iv_hdr.hdatDataPtrCnt, but we should loop through the total number
+ //to fillup the memory and increment the pointer
+
+ uint8_t l_totdataHdrCnt = this->iv_dataPtrSize / sizeof(hdatHDIFDataHdr_t);
+
+ for (uint8_t l_cnt=0; l_cnt < l_totdataHdrCnt; l_cnt++)
+ {
+ l_hdatHDIFDataHdr->hdatOffset = this->iv_dataPtrs[l_cnt].hdatOffset;
+ l_hdatHDIFDataHdr->hdatSize = this->iv_dataPtrs[l_cnt].hdatSize;
+
+ HDAT_DBG("wrote data array %d, at address 0x%016llX",
+ l_cnt,(uint64_t)l_hdatHDIFDataHdr);
+ l_hdatHDIFDataHdr++;
+ }
+
+
+ //write Child pointers array
+ hdatHDIFChildHdr_t *l_hdatHDIFChildHdr =
+ reinterpret_cast<hdatHDIFChildHdr_t *>(l_hdatHDIFDataHdr);
+
+ //saving the start value
+ uint8_t *l_tempChildHdr = reinterpret_cast<uint8_t *>(l_hdatHDIFChildHdr);
+
+ HDAT_DBG("writing Child pointers array from address=0x%016llX",
+ (uint64_t)l_hdatHDIFChildHdr);
+ //total count is HDAT_CHILD_LAST but actual data is hdatChildStrCnt
+ //but we need to copy the full to increase the memory pointer
+ uint8_t l_totChldHdrCnt =
+ this->iv_childPtrSize / sizeof(hdatHDIFChildHdr_t);
+
+
+ for(uint8_t l_cnt = 0; l_cnt < l_totChldHdrCnt; l_cnt++)
+ {
+ l_hdatHDIFChildHdr->hdatOffset = this->iv_childPtrs[l_cnt].hdatOffset;
+ l_hdatHDIFChildHdr->hdatSize = this->iv_childPtrs[l_cnt].hdatSize;
+ l_hdatHDIFChildHdr->hdatCnt = this->iv_childPtrs[l_cnt].hdatCnt;
+
+ HDAT_DBG("wrote child array %d, at address 0x%016llX",
+ l_cnt,(uint64_t)l_hdatHDIFChildHdr);
+ l_hdatHDIFChildHdr++;
+ }
+
+
+ l_tempChildHdr += iv_childPtrSize;
+
+ io_virt_addr = reinterpret_cast<uint8_t *>(l_tempChildHdr);
+
+ return io_virt_addr;
+
+}//end setHdif
+
+
+uint8_t * HdatHdif::setpadding(uint8_t * io_virt_addr,
+ uint32_t &o_size)
+{
+
+ HDAT_DBG("address=0x%016llX",
+ (uint64_t)io_virt_addr);
+ uint32_t i = 0;
+
+ if (this->iv_padSize > 0)
+ {
+ HDAT_DBG("adding iv_padSize=0x%x",iv_padSize);
+ for ( i = 0; i < iv_padSize; i++)
+ {
+ io_virt_addr[i] = '\0';
+ }
+ }
+
+
+ if (iv_siblingPadSize > 0)
+ {
+ HDAT_DBG("adding iv_siblingPadSize=0x%x",
+ iv_siblingPadSize);
+ for ( i = 0; i < iv_siblingPadSize; i++)
+ {
+ io_virt_addr[i] = '\0';
+ }
+ }
+
+ io_virt_addr += iv_padSize + iv_siblingPadSize;
+ o_size = iv_totalSize;
+
+ HDAT_DBG("exit address=0x%016llX",
+ (uint64_t)io_virt_addr);
+
+ return io_virt_addr;
+}
+
+
+
+
+uint32_t HdatHdif::getChildOffset()
+{
+ if ( this->iv_childPtrs )
+ {
+ return this->iv_childPtrs[0].hdatOffset;
+ }
+ else
+ {
+ return 0;
+ }
+
+}//end getChildOffset
+/** @brief See the prologue in hdathdif.H
+ */
+void HdatHdif::startCommit(UtilMem &i_data)
+{
+
+ // If no children were ever added, ensure offset to child pointers
+ // is 0.
+ if (0 == iv_hdr.hdatChildStrCnt)
+ {
+ iv_hdr.hdatChildStrOffset = 0;
+ }
+ i_data.write(&iv_hdr,sizeof(iv_hdr));
+
+ if ( NULL != iv_dataPtrs)
+ {
+ i_data.write(iv_dataPtrs ,iv_dataPtrSize);
+ }
+
+ // Write the child pointers section.
+ if (NULL != iv_childPtrs)
+ {
+ i_data.write(iv_childPtrs,iv_childPtrSize);
+ }
+}
+void HdatHdif::print()
+{
+ HDAT_INF("****** HdatHdif base object ******");
+
+ HDAT_INF(" iv_totalSize = %u", iv_totalSize);
+ HDAT_INF(" iv_padSize = %u", iv_padSize);
+ HDAT_INF(" iv_dataPtrSize = %u", iv_dataPtrSize);
+ HDAT_INF(" iv_childPtrSize = %u", iv_childPtrSize);
+
+ hdatPrintHdrs(&iv_hdr,
+ (const hdatHDIFDataHdr_t *)iv_dataPtrs,
+ NULL,
+ (const hdatHDIFChildHdr_t *)iv_childPtrs);
+
+
+ return;
+}
+
+/** @brief See the prologue in hdathdif.H
+ */
+uint32_t HdatHdif::endCommitSize()
+{
+ uint32_t l_size = 0;
+
+ // Write pad bytes if needed
+ if (iv_padSize > 0)
+ {
+ l_size += iv_padSize;
+ }
+
+ if (iv_siblingPadSize > 0)
+ {
+ if (iv_siblingPadSize <= sizeof(HDAT_PAD))
+ {
+ l_size += iv_siblingPadSize;
+ }
+ else
+ {
+ l_size += iv_siblingPadSize;
+ }
+ }
+ return l_size;
+
+}
+void HdatHdif::endCommit(UtilMem &i_data)
+{
+
+ char *l_buffer = NULL;
+
+ // Write pad bytes if needed
+ if (iv_padSize > 0)
+ {
+ i_data.write(HDAT_PAD,iv_padSize);
+ }
+
+ if (iv_siblingPadSize > 0)
+ {
+ if (iv_siblingPadSize <= sizeof(HDAT_PAD))
+ {
+ i_data.write(HDAT_PAD,iv_siblingPadSize);
+ }
+ else
+ {
+ l_buffer = new char[iv_siblingPadSize]();
+ i_data.write(l_buffer,iv_siblingPadSize);
+ delete[] l_buffer;
+ }
+ }
+
+}
+
+
+} //namespace HDAT
diff --git a/src/usr/hdat/hdathdif.H b/src/usr/hdat/hdathdif.H
new file mode 100755
index 000000000..a02f9a634
--- /dev/null
+++ b/src/usr/hdat/hdathdif.H
@@ -0,0 +1,398 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdathdif.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATHDIF_H
+#define HDATHDIF_H
+
+/**
+ * @file hdathdif.H
+ *
+ * @brief This file contains the class definition for the object provding the
+ * HDIF header for most hypervisor data structures.
+ *
+ */
+
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <stdint.h>
+#include <hdat/hdat.H>
+#include <hdat/hdat_reasoncodes.H>
+#include <errl/errlentry.H>
+#include <util/utilmem.H>
+
+
+
+namespace HDAT
+{
+
+/*----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatHdif class provides the base class for hypervisor data areas
+ * that have an HDIF header. Other C++ classes that build specific
+ * hypervisor data area structures are derived from this class.
+ *
+ * Description: This object is not intended to be constructed directly. Rather,
+ * it provides the base class upon which other derived classes are
+ * built.
+ *
+ * Thread safety: An HdatHdif object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by
+ * multiple threads at the same time. An object can be used by
+ * multiple threads if the threads serialize access. And of
+ * course, each thread can use its own object with no concerns
+ * about what other threads are doing.
+ *
+ * Signal handler usage:
+ * This class is not intended to be used in a signal handler
+ * and nothing has been done to try and make it safe to use
+ * in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatHdif
+{
+ public:
+
+ /**
+ * @brief Construct an HdatHdif base object.
+ *
+ * This is the constructor for the HdatHdif object
+ *
+ * If you are constructing this object on the heap by using new,
+ * you must check the pointer returned from new null value.
+ * If null, new failed to allocate storage and the constructor
+ * was not called. If not null, then you must check o_errlHndl
+ * to see if the constructor ran successfully.If o_errlHndl
+ * indicates an error was reported by the constructor, new has
+ * already allocated heap storage and the object must be deleted in
+ * order to free the heap storage.
+ *
+ * @pre None
+ * @param o_errlHndl output error handle
+ *
+ * @param i_eyeCatcher input the eyecatcher string
+ * @param i_dataPtrCnt input data array pointer count
+ * @param i_instance input object instance
+ * @param i_childCnt input child count
+ * @param i_ver input version number
+ *
+ * @post An HdatHdif object has been constructed. Heap storage has been
+ * allocated.
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ */
+ HdatHdif();
+
+ HdatHdif(errlHndl_t &o_errlHndl,
+ const char i_eyeCatcher[],
+ uint32_t i_dataPtrCnt,
+ uint32_t i_instance = 0,
+ uint32_t i_childCnt = 0,
+ uint32_t i_ver = 1);
+
+
+ /**
+ * @brief HdatHdif object destructor
+ *
+ * @pre None
+ *
+ * @post Heap storage is deallocated
+ *
+ */
+ virtual ~HdatHdif();
+
+
+ /**
+ * @brief Change the offset to the beginning of a set of children
+ *
+ * @pre i_childCnt from ctor must be greater than 0 (not checked)
+ *
+ * @post Total object size is updated. Child structure pointer entry is
+ * updated
+ *
+ * @param i_whichChildEntry -
+ * input parameter - An array index for the children being added.
+ * This is a 0 based array index so the first entry being added
+ * would specify 0 for this parameter.
+ * i_whichChildEntry < i_childCnt from ctor (not checked)
+ * @param i_size -
+ * input parameter - The size of the child structure(s)
+ * @param i_numChildStr -
+ * input parameter - The number of children being added.
+ *
+ */
+ void addChild(uint32_t i_whichChildEntry,
+ uint32_t i_size,
+ uint32_t i_numChildStr);
+
+
+ /**
+ * @brief Add a grandchild structure entry to the base object.
+ *
+ * @pre None
+ *
+ * @post Total object size is updated.
+ *
+ * @param i_size - input parameter - The size of the grandchild structure
+ *
+ */
+ void addGrandChild(uint32_t i_size);
+
+
+ /**
+ * @brief Add internal data pointer entry to the base object.
+ * When a hypervisor data structure has internal data , an array
+ * of data pointers(hdatHDIFDataHdr_t) is maintained to address
+ * the internal data areas. This method is used to maintain the
+ * array of data pointers.
+ *
+ * @pre i_dataPtrCnt from ctor must be greater than 0 (not checked)
+ *
+ * @post Total object size is updated. Internal data pointer entry is
+ * updated
+ *
+ * @param i_whichDataEntry -
+ * input parameter - An array index for the data entry being added
+ * This is a 0 based array index so the first entry being added
+ * would specify 0 for this parameter.
+ * i_whichDataEntry < i_dataPtrCnt from ctor (not checked)
+ * @param i_size -
+ * input parameter - The size of the internal data
+ *
+ */
+ void addData(uint32_t i_whichDataEntry,
+ uint32_t i_size);
+
+ /**
+ * @brief Some objects which have siblings must all be the same size
+ * so thatPHYP can traverse through them as elements of an array. Since
+ * the size of all the siblings is not known until the last sibling has
+ * been built, this method is used to ensure all objects are padded
+ * to the same size
+ *
+ * @pre None
+ * @post Total object size is updated. Pad size computed
+ * @param i_numBytes - input parameter - size, in bytes, of the
+ * maximum sized object
+ */
+
+ void maxSiblingSize(uint32_t i_numBytes);
+
+
+
+ /**
+ * @brief After the derived object is constructed, all data pointers have
+ * been added,and the maximum number of child structures have been
+ * computed, this method must be called to "pad" the object to a
+ * nice byte boundary (currently 16 byte boundaries are used).
+ *
+ * @pre actual or maximum number of child structures were provided on
+ * the constructor
+ * all calls to addData() have been completed
+ *
+ * @post Total object size is updated. Pad size computed.
+ *
+ */
+ void align();
+
+ /**
+ * @brief The current object size is returned. This is the size of
+ * an HDIF object. It does NOT include sizes of children or
+ * grandchildren
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @return Object size
+ */
+ uint32_t size();
+
+ /*
+ * @brief write Hdif header to memory
+ *
+ * @pre the object must have been constructed
+ *
+ * @param io_virt_addr input virtual address to write at
+ *
+ * @post data is written to host memory
+ *
+ * @return the next address to write at
+ *
+ */
+ uint8_t * setHdif(uint8_t * io_virt_addr);
+
+
+ /*
+ * @brief write the required padding
+ *
+ * @pre the object must have been constructed
+ *
+ * @param io_virt_addr input virtual address to write at
+ * @param o_size output size of the object
+ * @post pad is written to host memory
+ *
+ * @return the next address to write at
+ */
+
+ uint8_t *setpadding(uint8_t * io_virt_addr,
+ uint32_t& o_size );
+
+
+ /*
+ * @brief get the child offset
+ *
+ * daughter data must have been constructed
+ *
+ * return uint32_t offset value
+ */
+
+ uint32_t getChildOffset ();
+ /**
+ * @brief Update the offset to the beginning of a child structure(s)
+ *
+ * Complex strcutures which can have grandchilren (such as the
+ * HdatVpd object) may not be able to build the object pieces in
+ * the desired order. Thus offsets to chilren structures can be
+ * in error. When the objects are complete and are ready to be
+ * commited, they can be done so in the correct order but the
+ * offsets will have to be updated first.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[in] i_whichChildEntry - An array index for the child triple
+ * entry.This is a 0 based array index so the first entry would
+ * specify 0 for this parameter. i_whichChildEntry < i_childCnt
+ * from ctor (not checked)
+ * @param[in] i_offset - new offset value
+ *
+ * @return None
+ *
+ */
+ void chgChildOffset(uint32_t i_whichChildEntry,
+ uint32_t i_offset);
+ /**
+ * @brief The object data is written to ms memory
+ *
+ *
+ * @pre The derived object must be complete.
+ *
+ * @post The base class data is flattened and written to a ms area
+ *
+ * @param[in]i_data - input memory that contains data
+ *
+ */
+ void startCommit(UtilMem &i_data);
+
+ /**
+ * @brief print out the HdatHdif object data
+ *
+ * @pre None
+ *
+ * @post output sent to stdout
+ *
+ */
+ void print();
+
+ /**
+ * @brief Any padding that must be done to make the structure align
+ * properly is performed and the msarea containing the data structure is
+ * not closed.
+ *
+ * @pre None
+ *
+ * @post
+ *
+ * @param[in]i_data - input memory that contains data
+ *
+ */
+ void endCommit(UtilMem &i_data);
+
+ /**
+ * @brief Get endCommit size if there is any padding applied
+ * @pre None
+ *
+ * @post
+ *
+ * @return - size
+ */
+ uint32_t endCommitSize();
+
+ /**
+ * @brief Get the complete size of base object that needs to be written
+ * to MS memory
+ * @pre None
+ *
+ * @post
+ *
+ * @return - size
+ */
+ uint32_t getSize();
+
+
+
+ private:
+
+
+ /** Object Instance Data
+ *
+ * @li iv_totalSize - total number of bytes of structure and all
+ * its children and grandchildren
+ * @li iv_padSize - number of bytes to pad structure to a
+ * boundary (such as a nice 16 byte boundary)
+ * @li iv_siblingPadSize - the padding to be added
+ * @li iv_dataPtrSize - size of the internal data pointers array
+ * section
+ * @li iv_childPtrSize - size of the child pointers section
+ * @li iv_hdr - the basic HDIF header
+ * @li iv_dataPtrs - heap storage for the internal data pointers
+ * section
+ * @li iv_childPtrs - heap storage for the internal child structure
+ * pointers section
+ */
+ uint32_t iv_totalSize;
+ uint32_t iv_padSize;
+ uint32_t iv_siblingPadSize;
+ uint32_t iv_dataPtrSize;
+ uint32_t iv_childPtrSize;
+ hdatHDIF_t iv_hdr;
+ hdatHDIFDataHdr_t *iv_dataPtrs;
+ hdatHDIFChildHdr_t *iv_childPtrs;
+
+}; // end of HdatHdif class
+
+}//end namespace
+
+#endif // HDATHDIF_H
diff --git a/src/usr/hdat/hdathostservices.C b/src/usr/hdat/hdathostservices.C
new file mode 100755
index 000000000..e96e863de
--- /dev/null
+++ b/src/usr/hdat/hdathostservices.C
@@ -0,0 +1,308 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdathostservices.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+
+
+/**
+ * @file hdathostservices.C
+ *
+ * @brief This file contains the implementation of the HdatHostsr class.
+ *
+ */
+
+
+/*-----------------------------------------------------------------------------*/
+/* Includes */
+/*-----------------------------------------------------------------------------*/
+#include <stdlib.h> // malloc & free
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include <util/align.H>
+#include "hdathostservices.H"
+#include "hdatnodedata.H" // HdatNodedata class definition
+#include "hdathdif.H"
+#include "hdatutil.H"
+#include "hdatvpd.H"
+#include <targeting/common/util.H>
+
+using namespace TARGETING;
+namespace HDAT
+{
+/*-----------------------------------------------------------------------------*/
+/* Global variables */
+/*-----------------------------------------------------------------------------*/
+extern trace_desc_t *g_trac_hdat;
+uint32_t HdatHostsr::cv_actualCnt;
+
+/** @brief See the prologue in hdathostservices.H
+ */
+HdatHostsr::HdatHostsr(errlHndl_t &o_errlHndl,
+ const hdatMsAddr_t &i_msAddr,
+ uint32_t &o_hostServiceTotalSize,
+ uint32_t &o_hostServiceTotalCnt)
+: HdatHdif(o_errlHndl, HDAT_STRUCT_NAME, HDAT_HOSTSR_LAST, cv_actualCnt++,
+ HDAT_CHILD_LAST, HDAT_HOSTSR_VERSION),iv_actNodeCnt(0),iv_NodePtrs(NULL),
+ iv_virt_addr(NULL)
+{
+ HDAT_ENTER();
+
+ // Copy the passedin mainstore address in the local object variable
+ memcpy(&iv_msAddr, &i_msAddr, sizeof(hdatMsAddr_t));
+
+ // Total size for Host Service Data Structure
+ // including its internal data pointer size.
+ iv_size = sizeof(hdatHDIF_t) +
+ ( sizeof(hdatHDIFDataHdr_t) *
+ HDAT_HOSTSR_LAST)+
+ ( HDAT_CHILD_LAST * sizeof(hdatHDIFChildHdr_t))+
+ HDAT_HOSTSR_SIZE + 0x10; // Padding as per spec
+ // Find the virtual address to copy all the host service struct
+ uint64_t l_base_addr_down = ALIGN_PAGE_DOWN( iv_msAddr );
+ iv_virt_addr = (uint8_t *) mm_block_map (
+ reinterpret_cast<void*>(l_base_addr_down),
+ (ALIGN_PAGE(iv_size) + PAGESIZE));
+ iv_hostServiceData = iv_virt_addr + (iv_msAddr - ALIGN_PAGE_DOWN(iv_msAddr));
+
+ // Add up the Service Data structure size to o/p var
+ o_hostServiceTotalSize += iv_size;
+ o_hostServiceTotalCnt = 1; // Only one host service Data structure
+
+ // Calling the hdatHostServiceBuild
+ o_errlHndl= this->hdatHostServiceBuild(o_hostServiceTotalSize);
+
+ HDAT_EXIT();
+ return;
+}
+
+
+
+/** @brief See the prologues in hdathostservices.H
+*/
+errlHndl_t HdatHostsr::hdatHostServiceBuild(uint32_t &o_hostServiceTotalSize)
+{
+ errlHndl_t l_errlHndl = NULL;
+ HDAT_ENTER();
+
+ do{
+
+ /*** Add the parent Data pointer first ***/
+
+ this->addData(HDAT_SYSTEM_ATTRIBUTE, HDAT_HOSTSR_SIZE);
+ this->align();
+
+ /*** Create and Set the children ***/
+
+ // Lets build the node data child structures
+ // by looping into all nodes in bldNodeDataStruct
+
+ uint32_t l_NodeDataSize = 0;
+ l_errlHndl = this->bldNodeDataStruct(l_NodeDataSize);
+ if(l_errlHndl == NULL)
+ {
+ // Done with node data.Add up the node data size to o/p var
+ o_hostServiceTotalSize += l_NodeDataSize;
+ }
+ else
+ {
+ HDAT_ERR("bldNodeDataStruct returned error");
+ break;
+ }
+ /**** Creation of children done ******/
+
+ /*** Commit the Parent ***/
+
+ // set the header section of host services in the constructed memory space
+ iv_hostServiceData = this->setHdif(iv_hostServiceData);
+
+ //Set the internal Data pointer Data of (parent) host services
+ memset(iv_hostServiceData,0, HDAT_HOSTSR_SIZE);
+ iv_hostServiceData += HDAT_HOSTSR_SIZE;
+
+ /*** Parent commiting Done ***/
+
+ /*** Commit the children ***/
+
+ // Now lets commit the child structures.
+ l_errlHndl=this->setChildPtrs();
+
+ /*** Children commiting Done ***/
+
+ }while(0);
+
+ HDAT_EXIT();
+ return l_errlHndl;
+}
+
+HdatHostsr::~HdatHostsr()
+{
+ errlHndl_t l_errlHndl = NULL;
+ HDAT_ENTER();
+
+ /*** Unmap the virtual address of parent ***/
+
+ uint32_t rc = mm_block_unmap(reinterpret_cast<void*>(
+ ALIGN_PAGE_DOWN((uint64_t)iv_virt_addr)));
+ if( rc != 0)
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_HDAT_SERVICEDATA_CTOR
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errlHndl,
+ HDAT::MOD_HDAT_SERVICEDATA_CTOR,
+ RC_DEV_MAP_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+ /*** Unmap of parent addr done ***/
+
+ /*** Unmap the virtual address of children ***/
+
+ uint32_t l_cnt;
+ HdatNodedata *l_nodeDataObj, **l_curPtr;
+
+ l_curPtr = iv_NodePtrs;
+
+ for (l_cnt = 0; l_cnt < iv_actNodeCnt; l_cnt++)
+ {
+ l_nodeDataObj = *l_curPtr;
+ delete l_nodeDataObj;
+ l_curPtr = reinterpret_cast<HdatNodedata **>(reinterpret_cast<char *>
+ (l_curPtr) + sizeof(HdatNodedata *));
+ }
+
+ // Free heap storage
+ free(iv_NodePtrs);
+
+ /*** Unmap of children addrresses done ***/
+
+ HDAT_EXIT();
+}
+/** @brief See the prologue in hdathostservices.H
+ */
+
+errlHndl_t HdatHostsr::bldNodeDataStruct(uint32_t &o_NodeDataSize)
+{
+ HDAT_ENTER();
+
+ errlHndl_t l_errlHndl = NULL;
+
+ // Find the number of nodes on this machine
+ TARGETING::PredicateCTM l_nodeFilter(CLASS_ENC, TYPE_NODE);
+ TARGETING::PredicateHwas l_pred;
+ l_pred.present(true);
+ TARGETING::PredicatePostfixExpr l_presentNode;
+ l_presentNode.push(&l_nodeFilter).push(&l_pred).And();
+
+ TARGETING::TargetRangeFilter l_filter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentNode);
+ for( ; l_filter ; ++l_filter )
+ {
+ iv_actNodeCnt++;
+ }
+
+ // Looping and building the children
+ HdatNodedata *l_nodeDataObj, **l_arrayEntry;
+ const char HDAT_KID_STRUCT_NAME[] = "HS KID";
+ uint32_t l_NodeStructSize = 0;
+
+ if(iv_actNodeCnt > 0)
+ {
+ iv_NodePtrs = reinterpret_cast<HdatNodedata **>(calloc(iv_actNodeCnt,
+ sizeof(HdatNodedata *)));
+ }
+ else
+ {
+ HDAT_ERR("hdatHostsr : Hdat node data failed");
+ }
+
+ iv_msAddr += iv_size; // Leave a space for parent before creating children
+
+ for(uint32_t l_nodeID = 0 ; l_nodeID < iv_actNodeCnt ; l_nodeID++)
+ {
+ l_NodeStructSize = 0;
+ l_nodeDataObj = new HdatNodedata(l_errlHndl ,iv_msAddr,
+ HDAT_KID_STRUCT_NAME,l_NodeStructSize);
+
+ // Sum up the sizes for all the node data
+ o_NodeDataSize+= l_NodeStructSize;
+
+ l_arrayEntry = reinterpret_cast<HdatNodedata **>(
+ reinterpret_cast<char *>(iv_NodePtrs) +
+ l_nodeID * sizeof(HdatNodedata *));
+
+ *l_arrayEntry = l_nodeDataObj;
+
+ // Tell the base class about child structures and adjust size
+ if (NULL == l_errlHndl)
+ {
+ // 1st parm is 0 based
+ this->addChild(HDAT_CHILD_NODE_ATTRIBUTE, l_NodeStructSize, 0);
+ }
+ }
+
+ HDAT_DBG("HdatHostSr::bldNodeDataStruct Done. Commit pending.");
+
+ HDAT_EXIT();
+ return l_errlHndl;
+}
+
+/** @brief See the prologue in hdathostservices.H
+ */
+
+errlHndl_t HdatHostsr::setChildPtrs()
+{
+ HDAT_ENTER();
+ uint32_t l_cnt;
+ errlHndl_t l_errlHndl = NULL;
+ HdatNodedata *l_nodeDataObj, **l_curPtr;
+
+ l_curPtr = iv_NodePtrs;
+
+ for (l_cnt = 0; l_cnt < iv_actNodeCnt; l_cnt++)
+ {
+ l_nodeDataObj = *l_curPtr;
+ l_errlHndl = l_nodeDataObj->setNodeData();
+ if(l_errlHndl)
+ {
+ HDAT_ERR(" Setting Node data failed");
+ break;
+ }
+ }
+
+ HDAT_EXIT();
+ return l_errlHndl;
+
+}
+
+
+
+}// HDAT namespace
diff --git a/src/usr/hdat/hdathostservices.H b/src/usr/hdat/hdathostservices.H
new file mode 100755
index 000000000..e7bbce2d6
--- /dev/null
+++ b/src/usr/hdat/hdathostservices.H
@@ -0,0 +1,243 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdathostservices.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATHOSTSR_H
+#define HDATHOSTSR_H
+
+/**
+ * @file hdathostservices.H
+ *
+ * @brief This file contains the class definition for the Host service data object.
+ *
+ */
+
+/*-----------------------------------------------------------------------------*/
+/* Includes */
+/*-----------------------------------------------------------------------------*/
+#include <stdint.h> // standard types
+#include <hdat/hdat.H> // HDAT header type definitions
+#include "hdathdif.H" // HdatHdif base class definition
+#include "hdatnodedata.H" //Host service node data
+
+/*-----------------------------------------------------------------------------*/
+/* Constants */
+/*-----------------------------------------------------------------------------*/
+
+/** @brief eye catcher for the HDIF header for the Host service data
+ */
+const char HDAT_STRUCT_NAME[] = "HOSTSR";
+
+
+/** @enum hdatDataPtrs
+ * Constants for the internal data pointers that are added to the base
+ * class
+ */
+enum hdatHSDataPtrs
+{
+ HDAT_SYSTEM_ATTRIBUTE = 0,
+ HDAT_HOSTSR_LAST = 1
+};
+
+/** @enum hdatChildPtrs
+ * Constants for the child structure pointers that are added to the base
+ * class
+ */
+enum hdatChildPtrs
+{
+ HDAT_CHILD_NODE_ATTRIBUTE = 0,
+ HDAT_CHILD_RESERVED1 = 1,
+ HDAT_CHILD_LAST = 2
+};
+
+const uint16_t HDAT_HOSTSR_VERSION = 0x0010;
+
+const uint32_t HDAT_HOSTSR_SIZE = 4096;
+
+
+/*-----------------------------------------------------------------------------*/
+/* Type definitions */
+/*-----------------------------------------------------------------------------*/
+
+
+namespace HDAT
+{
+/*-----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*-----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatHostsr class is used to construct Host service data objects.
+ *
+ * Description: This class defines a specialized object.
+ * The real purpose of the object is to create the HostService data
+ * as defined by the PHYP Initialization
+ * architecture.
+ *
+ * End Class Description
+ */
+class HdatHostsr : public HdatHdif
+{
+public:
+
+ /**
+ * @brief Construct an HdatHostsr object.
+ *
+ * This is the constructor for the HdatHostsr object when that Host service data
+ * is not currently plugged but has been reserved for concurrent
+ * maintenance.
+ *
+ * If you are constructing this object on the heap by using new, then
+ * you must check the pointer returned from new to see if it is null.
+ * If it is null, new failed to allocate storage and the constructor
+ * was not called. If it is not null, then you must check o_errlHndl
+ * to see if the constructor ran successfully. If o_errlHndl indicates
+ * an error was reported by the constructor, new has already allocated
+ * heap storage and the object must be deleted in order to free the
+ * heap storage.
+ *
+ * @pre None
+ *
+ * @post An HdatHostsr object has been constructed. Heap storage has been allocated.
+ *
+ * @param o_errlHndl - output parameter - If any errors occur, the HdatHostsr object
+ * is NOT constructed and errors are returned in this parameter
+ * @param i_msAddr - input parameter - The main memory address that the Host service data
+ * that will be DMA'd to.
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ */
+ HdatHostsr(errlHndl_t &o_errlHndl,
+ const hdatMsAddr_t &i_msAddr,
+ uint32_t &o_hostServiceDataSize,
+ uint32_t &o_hostServiceDataCnt);
+
+
+ /**
+ * @brief HdatHostsr object destructor
+ *
+ * This is the destructor for an HdatHostsr object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatHostsr object has been destroyed and can no longer be used.
+ *
+ */
+ virtual ~HdatHostsr();
+ /**
+ * @brief Build Host Service Data
+ *
+ * @pre Virtual mapping is done in constructor
+ *
+ * @post Host service(parent) and Node data(children) setting done
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t
+ */
+
+ errlHndl_t hdatHostServiceBuild(uint32_t &o_hostServiceTotalSize);
+
+ /**
+ * @brief Build the hypervisor data area structres for Node Data.
+ *
+ * @pre None
+ *
+ * @post A node data has been added to the object. Heap storage
+ * has been allocated.
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ */
+ errlHndl_t bldNodeDataStruct(uint32_t &o_NodeDataSize);
+
+ /**
+ * @brief Add Host Service Node data description.
+ *
+ * @pre None
+ *
+ * @post Node data has been added to the object. Heap storage
+ * has been allocated.
+ *
+ * @param i_resourceId - input parameter - Node number
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addNodeData(uint32_t node);
+
+ /**
+ * @brief Set node data child pointers.
+ *
+ * @pre Node data pointer should have built i.e., node data
+ * object should be instantiated
+ *
+ * @post Node data committed
+ */
+
+ errlHndl_t setChildPtrs();
+
+ /** Class (static) Data
+ *
+ * Only one copy of this data exists in a process.
+ *
+ * @li cv_actualCnt - a count of how many HdatServiceData objects are created
+ */
+ static uint32_t cv_actualCnt;
+
+private:
+
+ /** Object Instance Data
+ *
+ * @li iv_msAddr - main memory address
+ * @li iv_hostServiceData - Pointer to host service data
+ * @li iv_size - Size of the service Data structure
+ * @li iv_maxNodes - maximum number of Nodes
+ * @li iv_actNodeCnt - Actual Node Count
+ * @li iv_NodePtrs - Pointer to array of Node data pointers
+ * @li iv_virt_addr - Pointer to virtual mapped address
+ */
+ uint64_t iv_msAddr;
+ uint8_t* iv_hostServiceData;
+ uint64_t iv_size;
+ uint32_t iv_maxNodes;
+ uint32_t iv_actNodeCnt;
+ HdatNodedata **iv_NodePtrs;
+ uint8_t* iv_virt_addr;
+
+}; // end of HdatHostSr class
+
+
+}
+
+#endif // HDATHOSTSR_H
+
diff --git a/src/usr/hdat/hdathostslcadata.C b/src/usr/hdat/hdathostslcadata.C
new file mode 100755
index 000000000..dae700e1b
--- /dev/null
+++ b/src/usr/hdat/hdathostslcadata.C
@@ -0,0 +1,901 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdathostslcadata.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 <devicefw/userif.H>
+#include <hdat/hdat.H>
+#include <targeting/common/target.H>
+#include "hdatutil.H"
+#include "hdathostslcadata.H"
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include <vpd/vpd_if.H>
+
+#ifdef HDAT_DEBUG
+#include <iostream>
+#endif
+#include <targeting/common/util.H>
+#include <string.h>
+#include <util/align.H>
+
+using namespace TARGETING;
+using namespace std;
+using namespace VPD;
+
+namespace HDAT
+{
+
+extern trace_desc_t *g_trac_hdat;
+
+
+fru_id_rid_t g_fruIDRidMap[] =
+{
+ {0x0800 , "BP"},
+ {0x1E00 , "EV"},
+ {0x1C00 , "SV"},
+ {0x1000 , "PF"},
+ {0xD000 , "MS"},
+ {0x3600 , "PI"},
+ {0x0200 , "SP"},
+ {0x3100 , "PS"},
+ {0x3A00 , "AM"},
+ {0x2900 , "CU"},
+ {0x2800 , "CE"},
+ {0x0300 , "OP"},
+ {0x3900 , "RG"},
+ {0xA100 , "SA"},
+ {0xA200 , "EI"},
+ {0xA300 , "EF"},
+ {0x2A00 , "CS"},
+ {0xD000 , "MS"},
+ {0xA000 , "VV"},
+ {0x1400 , "RI"},
+};
+
+
+/**
+ * @brief This helper routine returns VPD Collected status
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_Target - input parameter - Target of parent FRU
+ *
+ * @return True : VPD is collected
+ * False : VPD is not collected
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+bool getVPDCollectedStatus(TARGETING::Target *i_Target)
+{
+ bool l_vpdCollectedStatus = true;
+//@TODO: RTC 149382: Method to get VPD collected status for Targets
+
+ if((i_Target->getAttr<ATTR_TYPE>() != TYPE_PCI) &&
+ (i_Target->getAttr<ATTR_TYPE>() != TYPE_SYS))
+ {
+ l_vpdCollectedStatus = pvpdPresent(i_Target);
+ }
+ return l_vpdCollectedStatus;
+}
+
+/**
+ * @brief This helper routine populates ordinal ids for Procs
+ * and cores
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+
+void hdatPopulateOrdinalId()
+{
+ TARGETING::Target *l_pSysTarget = NULL;
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSysTarget);
+
+ if(l_pSysTarget == NULL)
+ {
+ HDAT_ERR("hdatGetSystemParamters::Top Level Target not found");
+ assert(l_pSysTarget != NULL);
+ }
+
+ TARGETING::PredicateCTM l_procFilter(TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_PROC);
+
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+
+ TARGETING::PredicatePostfixExpr l_presentProc;
+ l_presentProc.push(&l_procFilter).push(&l_predHwas).And();
+
+ TARGETING::TargetHandleList l_procList;
+
+ //Get all Procs in the system
+ TARGETING::targetService().
+ getAssociated(l_procList, l_pSysTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL, &l_presentProc);
+
+ uint32_t l_procOrdinalId = 0;
+ for (TargetHandleList::const_iterator pTarget_it = l_procList.begin();
+ pTarget_it != l_procList.end();
+ ++pTarget_it)
+ {
+ TargetHandle_t l_procTarget = *pTarget_it;
+ l_procTarget->setAttr<TARGETING::ATTR_ORDINAL_ID>(l_procOrdinalId++);
+
+ TARGETING::PredicateCTM l_coreFilter(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_CORE);
+
+ TARGETING::PredicatePostfixExpr l_presentCore;
+ l_presentCore.push(&l_coreFilter).push(&l_predHwas).And();
+
+ TARGETING::TargetHandleList l_coreList;
+
+ //Get all Core in the Proc
+ TARGETING::targetService().
+ getAssociated(l_coreList, l_procTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL, &l_presentCore);
+
+ uint32_t l_coreOrdinalId = 0;
+ for (TargetHandleList::const_iterator pcoreTarget_it =
+ l_coreList.begin();
+ pcoreTarget_it != l_coreList.end();
+ ++pcoreTarget_it)
+ {
+ TargetHandle_t l_coreTarget = *pcoreTarget_it;
+ l_coreTarget->setAttr<TARGETING::ATTR_ORDINAL_ID>
+ (l_coreOrdinalId++);
+ }
+ HDAT_DBG("Added Ordinal IDs for Core : %d",l_coreOrdinalId);
+ }
+ HDAT_DBG("Added Ordinal IDs Proc: %d ",l_procOrdinalId);
+}
+
+/**
+ * @brief This routine adds a new SLCA entry for specified target
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_Target - input parameter - Target for which slca entry
+ * is added
+ * i_frutype - input parameter - FRU Type of the Target
+ * i_slcaParentIndex - input parameter - Index of parent FRU
+ * i_LocCodePrefix - input parameter - Location code prefix
+ * o_hdatslca - output parameter - Vector containing slca entries
+ * for DIMMs
+ *
+ * @return Index of Last SLCA entry added
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+uint16_t hdatAddSLCAEntry( TARGETING::Target *i_Target,
+ HDAT_FRUType_t i_frutype,
+ uint16_t i_slcaparentindex,
+ char *i_LocCodePrefix,
+ vector<HDAT_slcaEntry_t> &o_hdatslca )
+{
+ //Values for the SLCA's collected and installed fields
+ #define HDAT_SLCA_COLLECTED 2
+ #define HDAT_SLCA_NOT_COLLECTED 3
+ #define HDAT_SLCA_NO_PD_INFO 1
+ #define HDAT_SLCA_INSTALLED 2
+ #define HDAT_SLCA_NOT_INSTALLED 3
+ HDAT_slcaEntry_t l_hdatslcaentry;
+
+ l_hdatslcaentry.fru_index = o_hdatslca.size();
+ l_hdatslcaentry.fru_rid = g_fruIDRidMap[i_frutype].fru_rid++;
+
+ strncpy(l_hdatslcaentry.fru_id,
+ (const char *)g_fruIDRidMap[i_frutype].fru_id,
+ sizeof(l_hdatslcaentry.fru_id));
+
+ l_hdatslcaentry.parent_index = i_slcaparentindex;
+ l_hdatslcaentry.first_child_rid = 0xFFFF;
+ l_hdatslcaentry.max_location_code_len = 64;
+
+ memset(l_hdatslcaentry.location_code , 0 ,
+ l_hdatslcaentry.max_location_code_len);
+
+ hdatGetLocationCode(i_Target,i_LocCodePrefix,l_hdatslcaentry.location_code);
+ uint32_t l_length = strlen(l_hdatslcaentry.location_code);
+ l_hdatslcaentry.location_code[l_length]='\0';
+ l_hdatslcaentry.actual_location_code_len = l_length + 1;
+
+ l_hdatslcaentry.number_of_children = 0x0;
+ l_hdatslcaentry.first_child_index = 0xFFFF;
+ l_hdatslcaentry.first_redundant_index = 0xFFFF;
+ l_hdatslcaentry.number_redundant_copies = 0x0;
+ l_hdatslcaentry.number_of_children_2B = 0x0;
+
+ l_hdatslcaentry.installed = HDAT_SLCA_INSTALLED;
+ if(getVPDCollectedStatus(i_Target))
+ {
+ l_hdatslcaentry.collected = HDAT_SLCA_COLLECTED;
+ }
+ else
+ {
+ l_hdatslcaentry.collected = HDAT_SLCA_NOT_COLLECTED;
+ }
+
+ o_hdatslca.push_back(l_hdatslcaentry);
+
+ if(i_frutype != HDAT_SLCA_FRU_TYPE_EV && i_frutype != HDAT_SLCA_FRU_TYPE_VV)
+ {
+ if(!i_Target->trySetAttr<TARGETING::ATTR_SLCA_INDEX>
+ (o_hdatslca.size() - 1))
+ {
+ HDAT_ERR("Error while setting SLCA_INDEX attribute for frutype: %d",
+ i_frutype);
+ }
+ if(!i_Target->trySetAttr<TARGETING::ATTR_SLCA_RID>
+ (l_hdatslcaentry.fru_rid))
+ {
+ HDAT_ERR("Error while setting SLCA_RID attribute for frutype: %d",
+ i_frutype);
+ }
+ }
+ HDAT_DBG("Added SLCA Entry FI : %s loc_code : %s",
+ g_fruIDRidMap[i_frutype].fru_id,
+ l_hdatslcaentry.location_code);
+ return(o_hdatslca.size() - 1);
+}
+
+/**
+ * @brief This routine adds Nodes and its children to SLCA table
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_Target - input parameter - Target of Node FRU being added
+ * i_slcaParentIndex - input parameter - Index of parent FRU
+ * i_LocCodePrefix - input parameter - Initial part of location code
+ * o_hdatslca - output parameter - Vector containing slca entries
+ *
+ * @return Number of DIMMs added
+ *
+ */
+static void hdatAddNodeToSLCATable(TARGETING::Target *i_Target,
+ uint16_t i_slcaParentIndex,
+ char *i_LocCodePrefix,
+ vector<HDAT_slcaEntry_t> &o_hdatslca)
+{
+ uint16_t l_slcaBPIndex = 0;
+ char l_nodeLocCode[64] = {0};
+ uint16_t l_slcaEntryIndex = 0;
+
+ l_slcaEntryIndex = hdatAddSLCAEntry(i_Target, HDAT_SLCA_FRU_TYPE_BP,
+ i_slcaParentIndex,
+ i_LocCodePrefix,o_hdatslca);
+
+ if((o_hdatslca[i_slcaParentIndex].first_child_index == 0xFFFF) &&
+ (l_slcaEntryIndex))
+ {
+ o_hdatslca[i_slcaParentIndex].first_child_index = l_slcaEntryIndex;
+
+ o_hdatslca[i_slcaParentIndex].first_child_rid =
+ o_hdatslca[l_slcaEntryIndex].fru_rid;
+
+ o_hdatslca[i_slcaParentIndex].number_of_children++;
+ o_hdatslca[i_slcaParentIndex].number_of_children_2B++;
+
+ }
+
+ l_slcaBPIndex = l_slcaEntryIndex;
+ hdatGetLocationCode(i_Target, i_LocCodePrefix, l_nodeLocCode);
+
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+
+ TARGETING::PredicateCTM l_procFilter(TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_PROC);
+
+ TARGETING::PredicateCTM l_memFilter(TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_MEMBUF);
+
+ TARGETING::PredicateCTM l_pciFilter(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_PCI);
+
+ TARGETING::PredicateCTM l_psFilter(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_PS);
+
+ TARGETING::PredicateCTM l_vrmFilter(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_VRM);
+
+ TARGETING::PredicateCTM l_fanFilter(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_FAN);
+
+ TARGETING::PredicateCTM l_uartFilter(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_UART);
+
+ TARGETING::PredicateCTM l_usbFilter(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_USB);
+
+ TARGETING::PredicateCTM l_ethFilter(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_ETH);
+
+ TARGETING::PredicateCTM l_dimmFilter(TARGETING::CLASS_LOGICAL_CARD,
+ TARGETING::TYPE_DIMM);
+
+ TARGETING::PredicatePostfixExpr l_presentChildren;
+ l_presentChildren.push(&l_procFilter).push(&l_memFilter).Or().
+ push(&l_pciFilter).Or().push(&l_psFilter).Or().
+ push(&l_fanFilter).Or().push(&l_uartFilter).Or().
+ push(&l_usbFilter).Or().push(&l_ethFilter).Or().
+ push(&l_vrmFilter).Or().push(&l_dimmFilter).Or().
+ push(&l_predHwas).And();
+
+ TARGETING::TargetHandleList l_childList;
+
+ //Get all children of this node
+ TARGETING::targetService().
+ getAssociated(l_childList, i_Target,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL, &l_presentChildren);
+
+ for (TargetHandleList::const_iterator pTarget_it = l_childList.begin();
+ pTarget_it != l_childList.end();
+ ++pTarget_it)
+ {
+ TargetHandle_t l_childTarget = *pTarget_it;
+ TARGETING::ATTR_TYPE_type l_type;
+ HDAT_FRUType_t l_hdatFRUType = HDAT_SLCA_FRU_TYPE_UNKNOWN;
+ l_slcaEntryIndex = 0;
+
+ if(l_childTarget->tryGetAttr<ATTR_TYPE>(l_type))
+ {
+ switch(l_type)
+ {
+ case TYPE_PROC:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_PROC;
+ break;
+
+ case TYPE_MEMBUF:
+ {
+ ATTR_FRU_ID_type l_childFRUId;
+ ATTR_FRU_ID_type l_encFRUId;
+ TARGETING::TargetHandleList targetList;
+ targetList.clear();
+ getParentAffinityTargets(targetList,l_childTarget,
+ TARGETING::CLASS_ENC,TARGETING::TYPE_NODE);
+ if(!targetList.empty())
+ {
+ TARGETING::Target* l_pNodeTarget = targetList[0];
+ l_encFRUId = l_pNodeTarget->getAttr<ATTR_FRU_ID>();
+ l_childFRUId = l_childTarget->getAttr<ATTR_FRU_ID>();
+ if(l_encFRUId != l_childFRUId)
+ {
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_RI;
+ }
+ }
+ else
+ {
+ //target list is empty for type membuf then FRU type
+ //would be set as HDAT_SLCA_FRU_TYPE_UNKNOWN
+ HDAT_ERR("Empty list returned while querying"
+ "for parents of membuf");
+ }
+ }
+ break;
+
+ case TYPE_DIMM:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_DIMM;
+ break;
+
+ case TYPE_PCI:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_IOP;
+ break;
+
+ case TYPE_PS:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_PS;
+ break;
+
+ case TYPE_VRM:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_RG;
+ break;
+
+ case TYPE_FAN:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_AM;
+ break;
+
+ case TYPE_USB:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_CU;
+ break;
+
+ case TYPE_ETH:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_CE;
+ break;
+
+ case TYPE_UART:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_CS;
+ break;
+
+#ifdef BACKPLANE_EXTENSION_ENABLED
+ case TYPE_BX:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_BX;
+ hdatAddNodeToSLCATable(l_childTarget, l_slcaBPIndex,
+ l_nodeLocCode, o_hdatslca);
+ break;
+#endif
+
+ default:
+ l_hdatFRUType = HDAT_SLCA_FRU_TYPE_UNKNOWN;
+ break;
+ }
+
+ if(l_hdatFRUType != HDAT_SLCA_FRU_TYPE_UNKNOWN)
+ {
+ l_slcaEntryIndex = hdatAddSLCAEntry(l_childTarget,
+ l_hdatFRUType,
+ l_slcaBPIndex,
+ l_nodeLocCode,o_hdatslca);
+
+ o_hdatslca[l_slcaBPIndex].number_of_children++;
+
+ o_hdatslca[l_slcaBPIndex].number_of_children_2B++;
+
+ if((o_hdatslca[l_slcaBPIndex].first_child_index == 0xFFFF) &&
+ (l_slcaEntryIndex))
+ {
+ o_hdatslca[l_slcaBPIndex].first_child_index =
+ l_slcaEntryIndex;
+
+ o_hdatslca[l_slcaBPIndex].first_child_rid =
+ o_hdatslca[l_slcaEntryIndex].fru_rid;
+ }
+ }
+ }
+ else
+ {
+ HDAT_ERR("Error reading ATTR_TYPE attribute");
+ }
+ }
+}
+
+/**
+ * @brief This routine adds Service Processors to SLCA table
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_Target - input parameter - Target of SP FRU
+ * i_slcaParentIndex - input parameter - Index of parent FRU
+ * o_hdatslca - output parameter - Vector containing slca entries
+ * for Service Processors
+ *
+ * @return Number of Service Processor FRUs added
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+static void hdatAddSPToSLCATable(TARGETING::Target *i_Target,
+ uint16_t i_slcaParentIndex,
+ char *i_LocCodePrefix,
+ vector<HDAT_slcaEntry_t> &o_hdatslca)
+{
+ TARGETING::PredicateCTM l_spPredicate(TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_SP,
+ TARGETING::MODEL_BMC);
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+
+ TARGETING::PredicatePostfixExpr l_presentSP;
+ l_presentSP.push(&l_spPredicate).push(&l_predHwas).And();
+
+ //Get all Service processors in the system
+ TARGETING::TargetRangeFilter l_spFilter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentSP);
+
+ for (;l_spFilter;++l_spFilter)
+ {
+ TARGETING::Target *l_spTarget = (*l_spFilter);
+
+ hdatAddSLCAEntry(l_spTarget, HDAT_SLCA_FRU_TYPE_SP, i_slcaParentIndex,
+ i_LocCodePrefix,o_hdatslca);
+
+ o_hdatslca[i_slcaParentIndex].number_of_children++;
+ o_hdatslca[i_slcaParentIndex].number_of_children_2B++;
+
+ HDAT_DBG("Added Service Processor to SLCA");
+ }
+}
+
+/**
+ * @brief This routine adds op-panel SLCA entry
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_Target - input parameter - Target of panel FRU
+ * i_slcaParentIndex - input parameter - Index of parent FRU
+ * i_LocCodePrefix - input parameter - Loc Code Prefix
+ * o_hdatslca - output parameter - Vector containing slca entries
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+static void hdatAddOpPanelToSLCATable(TARGETING::Target *i_Target,
+ uint16_t i_slcaParentIndex,
+ char *i_LocCodePrefix,
+ vector<HDAT_slcaEntry_t> &o_hdatslca)
+{
+ TARGETING::PredicateCTM l_opPredicate(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_PANEL);
+
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+
+ TARGETING::PredicatePostfixExpr l_presentPanel;
+ l_presentPanel.push(&l_opPredicate).push(&l_predHwas).And();
+
+ //Get all op-panels in the system
+ TARGETING::TargetRangeFilter l_opFilter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentPanel);
+
+ for (;l_opFilter;++l_opFilter)
+ {
+ TARGETING::Target *l_opTarget = (*l_opFilter);
+
+ hdatAddSLCAEntry(l_opTarget, HDAT_SLCA_FRU_TYPE_OP, i_slcaParentIndex,
+ i_LocCodePrefix,o_hdatslca);
+
+ o_hdatslca[i_slcaParentIndex].number_of_children++;
+ o_hdatslca[i_slcaParentIndex].number_of_children_2B++;
+
+ HDAT_DBG("Added OpPanel to SLCA");
+ }
+}
+
+/**
+ * @brief This routine constructs SLCA table for all FRUs
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_hdatslcaentries - output parameter - Vector containing slca entries
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+errlHndl_t hdatConstructslcaTable(std::vector<HDAT_slcaEntry_t>
+ &o_hdatslcaentries)
+{
+
+ TARGETING::Target *l_pSystemTarget = NULL;
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSystemTarget);
+
+ if(l_pSystemTarget == NULL)
+ {
+ HDAT_ERR("Error in getting Top Level Target");
+ assert(l_pSystemTarget != NULL);
+ }
+
+ char l_locCode[64]={0};
+ hdatGetLocationCodePrefix(l_locCode);
+
+ uint16_t l_slcaVVIndex = hdatAddSLCAEntry(l_pSystemTarget,
+ HDAT_SLCA_FRU_TYPE_VV,0,
+ l_locCode,
+ o_hdatslcaentries);
+
+ uint16_t l_slcaSVIndex = hdatAddSLCAEntry(l_pSystemTarget,
+ HDAT_SLCA_FRU_TYPE_SV,l_slcaVVIndex,
+ l_locCode,
+ o_hdatslcaentries);
+
+ if((o_hdatslcaentries[0].first_child_index == 0xFFFF) &&
+ (l_slcaSVIndex))
+ {
+ o_hdatslcaentries[0].first_child_index = l_slcaSVIndex;
+
+ o_hdatslcaentries[0].first_child_rid =
+ o_hdatslcaentries[l_slcaSVIndex].fru_rid;
+
+ o_hdatslcaentries[0].number_of_children++;
+ o_hdatslcaentries[0].number_of_children_2B++;
+
+ }
+
+ TARGETING::PredicateCTM l_nodePredicate(TARGETING::CLASS_ENC,
+ TARGETING::TYPE_NODE);
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+
+ TARGETING::PredicatePostfixExpr l_presentNode;
+ l_presentNode.push(&l_nodePredicate).push(&l_predHwas).And();
+
+ //Get all Nodes
+ TARGETING::TargetRangeFilter l_nodeFilter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentNode);
+
+ TARGETING::Target *l_nodeTarget = (*l_nodeFilter);
+ if(l_nodeTarget != NULL)
+ {
+ l_nodeTarget->setAttr<TARGETING::ATTR_ORDINAL_ID>(0);
+
+ //Add EV here and make SP, BP and OP as children of EV
+ uint16_t l_slcaEVIndex = hdatAddSLCAEntry(l_pSystemTarget,
+ HDAT_SLCA_FRU_TYPE_EV,l_slcaVVIndex,
+ l_locCode,
+ o_hdatslcaentries);
+
+ o_hdatslcaentries[l_slcaEVIndex].first_child_index = 0xFFFF;
+ o_hdatslcaentries[l_slcaEVIndex].first_child_rid = 0xFFFF;
+
+ o_hdatslcaentries[l_slcaVVIndex].number_of_children++;
+ o_hdatslcaentries[l_slcaVVIndex].number_of_children_2B++;
+
+ hdatAddNodeToSLCATable(l_nodeTarget, l_slcaEVIndex, l_locCode,
+ o_hdatslcaentries);
+
+ //Add Service Processor FRUs to SLCA table
+ hdatAddSPToSLCATable(l_nodeTarget,l_slcaEVIndex,l_locCode,
+ o_hdatslcaentries);
+
+ //Add Op-Panel FRUs to SLCA table
+ hdatAddOpPanelToSLCATable(l_nodeTarget,l_slcaEVIndex,l_locCode,
+ o_hdatslcaentries);
+
+ hdatPopulateOrdinalId();
+ }
+ else
+ {
+ HDAT_ERR("Error retrieving nodes. There must be alteast one node");
+ assert(l_nodeTarget != NULL);
+ }
+ return NULL;
+
+}
+
+/**
+ * @brief This routine sets SLCA structure header parameters
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_slcaStruct - output parameter - Structure containing SLCA header
+ * i_nrOfSLCAEntries - input parameter - Number of SLCA entries
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+static errlHndl_t hdatSetSLCAStructHdrs(hdatSLCAStruct_t &o_slcaStruct,
+ uint32_t i_nrOfSLCAEntries)
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ uint32_t l_hdatslcastructsize = i_nrOfSLCAEntries *
+ sizeof(HDAT_slcaEntry_t);
+
+ o_slcaStruct.hdatHdr.hdatStructId = HDAT_HDIF_STRUCT_ID;
+ o_slcaStruct.hdatHdr.hdatInstance = 0;
+ o_slcaStruct.hdatHdr.hdatVersion = HDAT_SLCA_STRUCT_VERSION;
+ o_slcaStruct.hdatHdr.hdatSize = sizeof(hdatSLCAStruct_t) +
+ l_hdatslcastructsize;
+ o_slcaStruct.hdatHdr.hdatHdrSize = sizeof(hdatHDIF_t);
+ o_slcaStruct.hdatHdr.hdatDataPtrOffset = sizeof(hdatHDIF_t);
+ o_slcaStruct.hdatHdr.hdatDataPtrCnt = 1;
+ o_slcaStruct.hdatHdr.hdatChildStrCnt = 0;
+ o_slcaStruct.hdatHdr.hdatChildStrOffset = 0;
+
+ memcpy(o_slcaStruct.hdatHdr.hdatStructName, HDAT_SLCA_STRUCT_NAME,
+ sizeof(o_slcaStruct.hdatHdr.hdatStructName));
+
+ o_slcaStruct.hdatSLCAIntData[0].hdatOffset =
+ sizeof(hdatHDIF_t)+ sizeof(hdatHDIFDataHdr_t)
+ + sizeof(o_slcaStruct.hdatPadding);
+
+ o_slcaStruct.hdatSLCAIntData[0].hdatSize =
+ sizeof(hdatSLCAArrayHdr_t) + l_hdatslcastructsize;
+
+ memset(o_slcaStruct.hdatPadding, 0 , sizeof(o_slcaStruct.hdatPadding));
+
+ o_slcaStruct.hdatSLCAArrayHdr.hdatOffsetToSLCAArray =
+ sizeof(hdatSLCAArrayHdr_t);
+
+ o_slcaStruct.hdatSLCAArrayHdr.hdatActualNrEntries = i_nrOfSLCAEntries;
+
+ o_slcaStruct.hdatSLCAArrayHdr.hdatSizeOfEntryAllotted =
+ sizeof(HDAT_slcaEntry_t);
+
+ o_slcaStruct.hdatSLCAArrayHdr.hdatActualSizeOfEntry =
+ sizeof(HDAT_slcaEntry_t);
+
+ return l_errlHndl;
+}
+
+/**
+ * @brief This routine builds the SLCA structure as per HDAT specifications
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_msAddr - Mainstore address where SLCA structure is loaded
+ * o_hdatslcaCount - output parameter - Number of SLCA structures
+ * o_hdatslcaSize - output paramster - Size of SLCA created
+ *
+ * @return errlHndl_t - Error Handle
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+errlHndl_t hdatBuildSLCA(const HDAT::hdatMsAddr_t &i_msAddr,
+ uint32_t &o_hdatslcaCount,
+ uint32_t &o_hdatslcaSize)
+
+{
+ std::vector<HDAT_slcaEntry_t> l_hdatslcaentries;
+ hdatSLCAStruct_t l_hdatslcastruct;
+ errlHndl_t l_errl = NULL;
+
+ hdatPopulateMTMAndSerialNumber();
+ hdatConstructslcaTable(l_hdatslcaentries);
+
+ uint32_t l_hdatslcastructsize = l_hdatslcaentries.size() *
+ sizeof(HDAT_slcaEntry_t);
+
+ uint64_t l_base_addr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo;
+
+ //Set SLCA Headers
+ hdatSetSLCAStructHdrs(l_hdatslcastruct, l_hdatslcaentries.size());
+
+ // Allocate space for SLCA Header
+ void *l_virt_addr_hdr = mm_block_map(reinterpret_cast<void*>
+ (ALIGN_PAGE_DOWN(l_base_addr)),
+ (ALIGN_PAGE(sizeof(hdatSLCAStruct_t) +
+ l_hdatslcastructsize) + PAGESIZE));
+ l_virt_addr_hdr = reinterpret_cast<void *>(
+ reinterpret_cast<uint64_t>(l_virt_addr_hdr) +
+ (l_base_addr - ALIGN_PAGE_DOWN(l_base_addr)));
+
+ HDAT_DBG("SLCA hdr addr 0x%016llX SLCA hdr size %d",
+ (uint64_t)l_virt_addr_hdr, sizeof(hdatSLCAStruct_t));
+
+ memcpy(reinterpret_cast<hdatSLCAStruct_t *>(l_virt_addr_hdr),
+ &l_hdatslcastruct, sizeof(hdatSLCAStruct_t));
+
+ HDAT_slcaEntry_t *l_hdatSLCA = reinterpret_cast<HDAT_slcaEntry_t *>
+ ((uint64_t)l_virt_addr_hdr + sizeof(hdatSLCAStruct_t));
+
+ HDAT_DBG("HDAT SLCA addr 0x%016llX SLCA struct size %d",
+ (uint64_t) l_base_addr, l_hdatslcastructsize);
+
+ HDAT_DBG("HDAT SLCA addr 0x%016llX virtual addr 0x%016llX",
+ (uint64_t) l_hdatSLCA, (uint64_t)l_virt_addr_hdr);
+
+ std::copy(l_hdatslcaentries.begin(), l_hdatslcaentries.end(), l_hdatSLCA);
+
+ HDAT_DBG("HDAT:: Loaded SLCA structures: Size: 0x%X",
+ sizeof(hdatSLCAStruct_t) +
+ l_hdatslcastructsize);
+
+ o_hdatslcaSize = sizeof(hdatSLCAStruct_t) + l_hdatslcastructsize;
+ o_hdatslcaCount = 1;
+
+ int rc = mm_block_unmap(l_virt_addr_hdr);
+
+ if( rc != 0)
+ {
+ errlHndl_t l_errl = NULL;
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_SLCA_DESTRUCTOR
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCIA_DESTRUCTOR,
+ RC_DEV_MAP_FAIL,
+ (uint32_t)((uint64_t)l_virt_addr_hdr >> 32),
+ (uint32_t)((uint64_t)l_virt_addr_hdr),0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1, false);
+ }
+
+ return l_errl;
+}
+
+/**
+ * @brief This routine copies the SLCA from a source address to a destination
+ * address
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_msAddrSource - input parameter - Source address of SLCA
+ * i_msAddrDest - input parameter - Destination address of SLCA
+ * i_slcaSize - input parameter - Size of SLCA to be copied
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+void hdatMoveSLCA(const HDAT::hdatMsAddr_t &i_msAddrSource,
+ const HDAT::hdatMsAddr_t &i_msAddrDest,
+ uint32_t i_slcaSize)
+{
+
+ uint64_t l_base_addr_source = ((uint64_t) i_msAddrSource.hi << 32) |
+ i_msAddrSource.lo;
+ uint64_t l_base_addr_dest = ((uint64_t) i_msAddrDest.hi << 32) |
+ i_msAddrDest.lo;
+
+ HDAT_DBG("Move SLCA from 0x%016llX to 0x%016llX with size %d",
+ (uint64_t) l_base_addr_source, (uint64_t)l_base_addr_dest,
+ i_slcaSize);
+ // Allocate space for SLCA
+ void *l_virt_addr_source = mm_block_map(reinterpret_cast<void*>
+ (ALIGN_PAGE_DOWN(l_base_addr_source)),
+ (ALIGN_PAGE(i_slcaSize)+PAGESIZE));
+
+ l_virt_addr_source = reinterpret_cast<void *>(
+ reinterpret_cast<uint64_t>(l_virt_addr_source) +
+ (l_base_addr_source - ALIGN_PAGE_DOWN(l_base_addr_source)));
+
+ // Allocate space for SLCA
+ void *l_virt_addr_dest = mm_block_map(reinterpret_cast<void*>
+ (ALIGN_PAGE_DOWN(l_base_addr_dest)),
+ (ALIGN_PAGE(i_slcaSize) + PAGESIZE));
+
+ l_virt_addr_dest = reinterpret_cast<void *>(
+ reinterpret_cast<uint64_t>(l_virt_addr_dest) +
+ (l_base_addr_dest - ALIGN_PAGE_DOWN(l_base_addr_dest)));
+
+ memcpy(l_virt_addr_dest , reinterpret_cast<void*>(l_virt_addr_source),
+ i_slcaSize);
+
+ mm_block_unmap(l_virt_addr_source);
+ mm_block_unmap(l_virt_addr_dest);
+}
+
+
+}
diff --git a/src/usr/hdat/hdathostslcadata.H b/src/usr/hdat/hdathostslcadata.H
new file mode 100644
index 000000000..4a0355546
--- /dev/null
+++ b/src/usr/hdat/hdathostslcadata.H
@@ -0,0 +1,144 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdathostslcadata.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATHOSTDATA_H_
+#define HDATHOSTDATA_H_
+
+namespace HDAT
+{
+
+const uint16_t HDAT_SLCA_STRUCT_VERSION = 0x21;
+const char HDAT_SLCA_STRUCT_NAME[7] = "SLCA ";
+
+struct HDAT_slcaEntry_t
+{
+ uint16_t fru_index; //slca_index_of_this_fru
+ uint16_t fru_rid; //vpd_resourece_id_of_this_fru
+ char fru_id[2]; //ASCII resource description
+ uint16_t parent_index; //slca_index_of_this_frus_parent
+ uint8_t slca_reserved:6,
+ non_functional_redundant_copy:1, //1 = not functional, 0 = functional
+ flag_embedded_pluggable:1; //1 = embedded. 0=pluggable
+ uint8_t number_of_children; //number_of_children
+ uint16_t first_child_index; //slca_index_of_this_frus_first_child
+ uint16_t first_child_rid; //resource_ID of this frus first child
+ uint8_t max_location_code_len;
+ uint8_t actual_location_code_len; //length_of_location_code
+ char location_code[80]; //location_code (NULL terminated)
+ uint16_t first_redundant_index; //slca index of the redundant copy
+ uint8_t number_redundant_copies; //total number of redundant copy
+ uint8_t reserved;
+ uint16_t number_of_children_2B; //number of children - 2 byte version
+ uint8_t installed; //Is FRU installed
+ uint8_t collected; //Is FRU VPD collected
+};
+
+enum HDAT_FRUType_t
+{
+ HDAT_SLCA_FRU_TYPE_BP = 0x00,
+ HDAT_SLCA_FRU_TYPE_EV = 0x01,
+ HDAT_SLCA_FRU_TYPE_SV = 0x02,
+ HDAT_SLCA_FRU_TYPE_PROC = 0x03,
+ HDAT_SLCA_FRU_TYPE_MEM = 0x04,
+ HDAT_SLCA_FRU_TYPE_IOP = 0x05,
+ HDAT_SLCA_FRU_TYPE_SP = 0x06,
+ HDAT_SLCA_FRU_TYPE_PS = 0x07,
+ HDAT_SLCA_FRU_TYPE_AM = 0x08,
+ HDAT_SLCA_FRU_TYPE_CU = 0x09,
+ HDAT_SLCA_FRU_TYPE_CE = 0x0A,
+ HDAT_SLCA_FRU_TYPE_OP = 0x0B,
+ HDAT_SLCA_FRU_TYPE_RG = 0x0C,
+ HDAT_SLCA_FRU_TYPE_SA = 0x0D,
+ HDAT_SLCA_FRU_TYPE_EI = 0x0E,
+ HDAT_SLCA_FRU_TYPE_EF = 0x0F,
+ HDAT_SLCA_FRU_TYPE_CS = 0x10,
+ HDAT_SLCA_FRU_TYPE_DIMM = 0x11,
+ HDAT_SLCA_FRU_TYPE_VV = 0x12,
+ HDAT_SLCA_FRU_TYPE_RI = 0x13,
+ HDAT_SLCA_FRU_TYPE_UNKNOWN = 0xFF,
+};
+
+struct fru_id_rid_t
+{
+ uint16_t fru_rid;
+ uint8_t fru_id[3];
+};
+
+struct hdatSLCAArrayHdr_t
+{
+ uint32_t hdatOffsetToSLCAArray;
+ uint32_t hdatActualNrEntries;
+ uint32_t hdatSizeOfEntryAllotted;
+ uint32_t hdatActualSizeOfEntry;
+};
+
+struct hdatSLCAStruct_t
+{
+ hdatHDIF_t hdatHdr;
+ hdatHDIFDataHdr_t hdatSLCAIntData[1];
+ uint8_t hdatPadding[8];
+ hdatSLCAArrayHdr_t hdatSLCAArrayHdr;
+};
+
+/**
+ * @brief This routine builds the SLCA structure as per HDAT specifications
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_msAddr - Mainstore address where SLCA structure is loaded
+ * o_hdatslcaCount - output parameter - Number of SLCA structures
+ * o_hdatslcaSize - output paramster - Size of SLCA created
+ *
+ * @return errlHndl_t - Error Handle
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+errlHndl_t hdatBuildSLCA(const HDAT::hdatMsAddr_t &i_msAddr,
+ uint32_t &o_hdatslcaCount,
+ uint32_t &o_hdatslcaSize);
+
+/**
+ * @brief This routine copies the SLCA from a source address to a destination
+ * address
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_msAddrSource - input parameter - Source address of SLCA
+ * i_msAddrDest - input parameter - Destination address of SLCA
+ * i_slcaSize - input parameter - Size of SLCA to be copied
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+void hdatMoveSLCA(const HDAT::hdatMsAddr_t &i_msAddrSource,
+ const HDAT::hdatMsAddr_t &i_msAddrDest,
+ uint32_t i_slcaSize);
+
+}
+#endif
diff --git a/src/usr/hdat/hdatiohub.C b/src/usr/hdat/hdatiohub.C
new file mode 100644
index 000000000..b27cc471b
--- /dev/null
+++ b/src/usr/hdat/hdatiohub.C
@@ -0,0 +1,899 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatiohub.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 <sys/mm.h>
+#include <sys/mmio.h>
+#include "hdathdif.H"
+#include "hdatvpd.H"
+#include "hdatiohub.H"
+#include <targeting/common/util.H>
+#include<sys/time.h>
+#include <util/align.H>
+
+
+using namespace TARGETING;
+
+namespace HDAT
+{
+
+vpdData mvpdData[] =
+{
+ { PVPD::VINI, PVPD::DR },
+ { PVPD::VINI, PVPD::CE },
+ { PVPD::VINI, PVPD::VZ },
+ { PVPD::VINI, PVPD::FN },
+ { PVPD::VINI, PVPD::PN },
+ { PVPD::VINI, PVPD::SN },
+ { PVPD::VINI, PVPD::CC },
+ { PVPD::VINI, PVPD::HE },
+ { PVPD::VINI, PVPD::CT },
+ { PVPD::VINI, PVPD::B3 },
+ { PVPD::VINI, PVPD::B4 },
+ { PVPD::VINI, PVPD::B7 },
+ { PVPD::VINI, PVPD::PF },
+ { PVPD::VINI, PVPD::LX },
+};
+
+const HdatKeywordInfo l_pvpdKeywords[] =
+{
+
+ { PVPD::DR, "DR" },
+ { PVPD::CE, "CE" },
+ { PVPD::VZ, "VZ" },
+ { PVPD::FN, "FN" },
+ { PVPD::PN, "PN" },
+ { PVPD::SN, "SN" },
+ { PVPD::CC, "CC" },
+ { PVPD::HE, "HE" },
+ { PVPD::CT, "CT" },
+ { PVPD::B3, "B3" },
+ { PVPD::B4, "B4" },
+ { PVPD::B7, "B7" },
+ { PVPD::PF, "PF" },
+ { PVPD::LX, "LX" },
+};
+
+extern trace_desc_t *g_trac_hdat;
+
+const uint32_t HDAT_MULTIPLE = 16;
+
+
+
+/*******************************************************************************
+ * IO HUB constructor
+*******************************************************************************/
+
+HdatIoHubFru::HdatIoHubFru(errlHndl_t &o_errlHndl,
+ uint32_t i_resourceId,
+ hdatCardType i_cardType,
+ uint32_t i_daughterCnt,
+ uint32_t i_index,
+ uint32_t i_slcaIdx)
+:HdatHdif(o_errlHndl, "IO HUB", HDAT_PARENT_LAST,i_index,HDAT_CHILD_LAST,
+ HDAT_IO_VERSION),
+iv_hubStatus(0),iv_kwdSize(0),iv_maxHubs(HDAT_MAX_IO_CHIPS),
+iv_maxDaughters(i_daughterCnt),iv_hubArraySize(0),iv_actDaughterCnt(0),
+iv_maxDaughterSize(0),iv_kwd(NULL),iv_hubArray(NULL),iv_daughterPtrs(NULL)
+{
+ HDAT_ENTER();
+
+ o_errlHndl = NULL;
+
+ iv_hubId.hdatCardType = i_cardType;
+ iv_hubId.hdatReserved1 = 0;
+ iv_hubId.hdatReserved2 = 0;
+ iv_hubId.hdatReserved3 = 0;
+ iv_hubId.hdatReserved4 = 0;
+ iv_hubId.hdatReserved5 = 0;
+ iv_hubId.hdatReserved6 = 0;
+
+ iv_hubArrayHdr.hdatOffset = sizeof(hdatHDIFDataArray_t);
+ iv_hubArrayHdr.hdatArrayCnt = 0;
+ iv_hubArrayHdr.hdatAllocSize = sizeof(hdatHubEntry_t);
+ iv_hubArrayHdr.hdatActSize = sizeof(hdatHubEntry_t);
+
+ // Allocate space to build the I/O hub array
+ iv_hubArraySize = iv_maxHubs * sizeof(hdatHubEntry_t);
+ iv_hubArray = reinterpret_cast<hdatHubEntry_t *>(calloc(iv_maxHubs,
+ sizeof(hdatHubEntry_t)));
+
+ iv_fru.hdatResourceId = i_resourceId;
+
+
+ if (NULL == o_errlHndl)
+ {
+ iv_fru.hdatSlcaIdx = i_slcaIdx;
+ this->addData(HDAT_FRU_ID, sizeof(hdatFruId_t));
+ this->addData(HDAT_ASCII_KWD, iv_kwdSize);
+ this->addData(HDAT_HUB_ID, sizeof(hdatHubId_t));
+ this->addData(HDAT_HUBS_ARRAY, iv_hubArraySize +
+ sizeof(iv_hubArrayHdr));
+ this->align();
+ }
+
+ HDAT_EXIT();
+}
+
+
+/*******************************************************************************
+ * * IO HUB destructor
+*******************************************************************************/
+HdatIoHubFru::~HdatIoHubFru()
+{
+ uint32_t l_cnt;
+ HdatVpd *l_vpdObj, **l_curPtr;
+ HDAT_ENTER();
+
+ // Destroy daughter card objects
+ l_curPtr = iv_daughterPtrs;
+ for (l_cnt = 0; l_cnt < iv_actDaughterCnt; l_cnt++)
+ {
+ l_vpdObj = *l_curPtr;
+ delete l_vpdObj;
+ l_curPtr = reinterpret_cast<HdatVpd **>(reinterpret_cast<char *>
+ (l_curPtr) + sizeof(HdatVpd *));
+ }
+
+ free(iv_hubArray);
+ free(iv_daughterPtrs);
+
+ HDAT_EXIT();
+
+}
+
+
+
+//******************************************************************************
+// setIOHub
+//******************************************************************************
+
+//we enter the function each time with the starting address for the next
+//object to write
+uint8_t * HdatIoHubFru::setIOHub(uint8_t * io_virt_addr,
+ uint32_t& o_size)
+{
+ HDAT_DBG("virtual address=0x%016llX",
+ (uint64_t)io_virt_addr);
+
+ uint8_t *l_temp = NULL, *l_ioMarker = NULL;
+ HdatVpd *l_vpdObj;
+
+ //saving the starting offset as we need to add child pointer array offset
+ //to this location to start writing daughter cards which is often offset 820
+ l_ioMarker = io_virt_addr;
+
+ io_virt_addr = this->setHdif(io_virt_addr);
+
+ HDAT_DBG("after writing HDIF header address now 0x%016llX",
+ (uint64_t)io_virt_addr);
+
+
+ //write FRU ID
+ //cast to hdatFruId_t
+ hdatFruId_t *l_hdatFruId = reinterpret_cast<hdatFruId_t *>(io_virt_addr);
+
+ HDAT_DBG("writing FRU ID from address=0x%016llX",
+ (uint64_t)l_hdatFruId);
+
+ l_hdatFruId->hdatSlcaIdx = this->iv_fru.hdatSlcaIdx;
+ l_hdatFruId->hdatResourceId = this->iv_fru.hdatResourceId;
+
+ l_hdatFruId++; //increase by sizeof hdatFruId_t
+
+
+ //write HUB FRU id
+ //cast to hdatHubId_t *
+ hdatHubId_t *l_hdatHubId = reinterpret_cast<hdatHubId_t *>(l_hdatFruId);
+
+ HDAT_DBG("writing HUB FRU id from address=0x%016llX",
+ (uint64_t)l_hdatHubId);
+
+ l_hdatHubId->hdatCardType = this->iv_hubId.hdatCardType;
+
+ l_hdatHubId++;//pass through reserved1..6 by incrementing the pointer
+
+
+ //write Data array header of iohub array hdatHDIFDataArray_t iv_hubArrayHdr
+ hdatHDIFDataArray_t *l_hdatHDIFDataArray =
+ reinterpret_cast<hdatHDIFDataArray_t *>(l_hdatHubId);
+
+ HDAT_DBG("writing io hub Data array header at address=0x%016llX",
+ (uint64_t)l_hdatHDIFDataArray);
+
+ l_hdatHDIFDataArray->hdatOffset = this->iv_hubArrayHdr.hdatOffset;
+ l_hdatHDIFDataArray->hdatArrayCnt = this->iv_hubArrayHdr.hdatArrayCnt;
+ l_hdatHDIFDataArray->hdatAllocSize = this->iv_hubArrayHdr.hdatAllocSize;
+ l_hdatHDIFDataArray->hdatActSize = this->iv_hubArrayHdr.hdatActSize;
+
+ l_hdatHDIFDataArray++;//increase by sizeof hdatHDIFDataArray_t
+
+
+ //write io hub array entries
+ //number of entries are iv_hubArrayHdr.hdatArrayCnt
+
+ hdatHubEntry_t *l_hdatHubEntry =
+ reinterpret_cast<hdatHubEntry_t *>(l_hdatHDIFDataArray);
+
+ HDAT_DBG("writing io hub array from address=0x%016llX",
+ (uint64_t)l_hdatHubEntry);
+
+ for ( uint8_t l_cnt = 0; l_cnt < this->iv_hubArrayHdr.hdatArrayCnt; l_cnt++)
+ {
+ l_hdatHubEntry->hdatIoHubId =
+ this->iv_hubArray[l_cnt].hdatIoHubId;
+ l_hdatHubEntry->hdatChipId =
+ this->iv_hubArray[l_cnt].hdatChipId;
+ l_hdatHubEntry->hdatEcLvl =
+ this->iv_hubArray[l_cnt].hdatEcLvl;
+ l_hdatHubEntry->hdatProcChipID =
+ this->iv_hubArray[l_cnt].hdatProcChipID;
+ l_hdatHubEntry->hdatHardwareTopology =
+ this->iv_hubArray[l_cnt].hdatHardwareTopology;
+ l_hdatHubEntry->hdatMRID =
+ this->iv_hubArray[l_cnt].hdatMRID;
+ l_hdatHubEntry->hdatMemMapVersion =
+ this->iv_hubArray[l_cnt].hdatMemMapVersion;
+ l_hdatHubEntry->hdatFlags =
+ this->iv_hubArray[l_cnt].hdatFlags;
+ l_hdatHubEntry->hdatFab0PresDetect =
+ this->iv_hubArray[l_cnt].hdatFab0PresDetect;
+
+ for ( uint16_t l_phbcnt = 0 ; l_phbcnt < HDAT_PHB_LANES; l_phbcnt++)
+ {
+ l_hdatHubEntry->hdatLaneEqPHB[l_phbcnt] =
+ this->iv_hubArray[l_cnt].hdatLaneEqPHB[l_phbcnt];
+ }
+
+ l_hdatHubEntry++;//increase by size of hdatHubEntry_t
+
+ HDAT_DBG("wrote io hub array %d",l_cnt);
+ }
+
+ l_temp = reinterpret_cast<uint8_t *>(l_hdatHubEntry);
+
+
+ //doing padding for io hub
+
+ io_virt_addr = this->setpadding(l_temp,o_size);
+
+
+ //next to write daughter card values
+ //this should go to offset 820 usually
+ uint32_t l_chldOffset = this->getChildOffset();
+ l_ioMarker += l_chldOffset;
+
+ io_virt_addr = reinterpret_cast<uint8_t *>(l_ioMarker);
+
+ HDAT_DBG("start writing daughter cards from address 0x%016llX",
+ (uint64_t)io_virt_addr);
+
+ if (iv_actDaughterCnt > 0)
+ {
+ l_vpdObj = *iv_daughterPtrs;
+ uint32_t l_daughterCount = 0;
+ while ( l_daughterCount < iv_actDaughterCnt)
+ {
+ HDAT_DBG("writing daughter from address 0x%016llX",
+ (uint64_t)io_virt_addr);
+ io_virt_addr = l_vpdObj->setVpd( io_virt_addr);
+ l_daughterCount++;
+
+ if (l_daughterCount < iv_actDaughterCnt)
+ {
+ l_vpdObj = *(HdatVpd **)((char *)iv_daughterPtrs +
+ l_daughterCount * sizeof(HdatVpd *));
+ }
+ }
+ }
+ else
+ {
+ HDAT_DBG("no daughter information to write");
+ }
+
+ HDAT_DBG("exiting with virtual address=0x%016llX",
+ (uint64_t)io_virt_addr);
+ return io_virt_addr;
+}
+
+
+/******************************************************************************/
+// hdatGetDaughterInfoFromTarget
+/******************************************************************************/
+
+errlHndl_t HdatIoHubFru::hdatGetDaughterInfoFromTarget(
+ const TARGETING::Target * i_target,
+ TARGETING::TargetHandleList& o_targetList,
+ std::vector <uint32_t>& o_DaughterRids)
+{
+ //i_target is the TARGET of proc
+ //add parent of this (sysnode) to list as BP
+ //get all pci slot children of the proc in a list
+ //for(start from the 1st slot; iterate through all the slots; )
+ //add the pci slot to daughter list
+ //get all the pci card children of the slot
+ //for(start from the 1st card; iterate through all the cards; )
+ //add the card to the daughter list
+
+ //also add the vpdType enum here in this function and passover
+ //so we get the vpd type handy while calling vpd constructor
+
+ HDAT_ENTER();
+ errlHndl_t l_errl = NULL;
+ o_DaughterRids.clear();
+ do
+ {
+ if ( NULL == i_target )
+ {
+ HDAT_ERR("hdatGetDaughterInfoFromTarget:"
+ " input target pointer is NULL");
+
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_IOHUB_FETCH_DAUGHTER
+ * @reasoncode HDAT::RC_INVALID_OBJECT
+ * @devdesc input Target pointer is NULL
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_errl,
+ MOD_IOHUB_FETCH_DAUGHTER,
+ RC_INVALID_OBJECT,
+ 0,0,0,0);
+ assert ( i_target != NULL);
+ }
+ if ((i_target->getAttr<ATTR_CLASS>() != CLASS_CARD)&&
+ (i_target->getAttr<ATTR_CLASS>() != CLASS_LOGICAL_CARD)&&
+ (i_target->getAttr<ATTR_CLASS>() != CLASS_CHIP))
+ {
+ HDAT_ERR("hdatGetDaughterInfoFromTarget: input Target class "
+ "not supported");
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_IOHUB_FETCH_DAUGHTER
+ * @reasoncode HDAT::RC_TARGET_UNSUPPORTED
+ * @devdesc Target class not supported
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_errl,
+ MOD_IOHUB_FETCH_DAUGHTER,
+ RC_TARGET_UNSUPPORTED,
+ 0,0,0,0);
+
+ break;
+ }
+
+ o_targetList.clear();
+ getParentAffinityTargets(o_targetList,i_target,
+ TARGETING::CLASS_ENC,TARGETING::TYPE_NODE);
+ if(o_targetList.empty())
+ {
+ HDAT_ERR("hdatGetDaughterInfoFromTarget: node returned empty "
+ "Target list");
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_IOHUB_FETCH_DAUGHTER
+ * @reasoncode HDAT::RC_EMPTY_TARGET_LIST
+ * @devdesc node returned empty Target list
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_errl,
+ MOD_IOHUB_FETCH_DAUGHTER,
+ RC_EMPTY_TARGET_LIST,
+ 0,0,0,0);
+ assert ( !o_targetList.empty());
+
+ break;
+ }
+ //get the parent node id, this is BP of the proc
+ TARGETING::Target* l_pNodeTarget = o_targetList[0];
+ o_DaughterRids.push_back(l_pNodeTarget->getAttr<ATTR_SLCA_RID>());
+
+
+ //@TODO: RTC 148660 add the loop to fetch the pci slot and card
+ }while(0);
+
+
+ HDAT_EXIT();
+ return l_errl;
+
+}//end hdatGetDaughterInfoFromTarget
+
+/******************************************************************************/
+// bldDaughterStruct
+/******************************************************************************/
+errlHndl_t HdatIoHubFru::bldDaughterStruct(const TARGETING::Target * i_target,
+ uint32_t i_index)
+{
+ errlHndl_t l_errlHndl = NULL;
+ uint32_t l_InstalledEtRidCnt = 0;
+ uint32_t l_loopCnt = 0;
+ std::vector <uint32_t> l_etRidArray;
+ TARGETING::TargetHandleList l_targetList;
+ HdatVpd *l_daughter = NULL;
+
+ HDAT_ENTER();
+
+ l_errlHndl = hdatGetDaughterInfoFromTarget(i_target,
+ l_targetList,l_etRidArray);
+
+ if (NULL == l_errlHndl)
+ {
+ l_InstalledEtRidCnt = l_etRidArray.size();
+ HDAT_DBG("daughter count %d",l_InstalledEtRidCnt);
+ iv_maxDaughters = l_InstalledEtRidCnt;
+
+ iv_daughterPtrs = reinterpret_cast<HdatVpd **>(calloc(
+ l_InstalledEtRidCnt,sizeof(HdatVpd *)));
+
+ if(iv_daughterPtrs)
+ {
+ for (uint32_t i=0; i<l_InstalledEtRidCnt; i++)
+ {
+ HDAT_DBG("adding daughter %d",
+ l_etRidArray[i]);
+ l_errlHndl = this->addDaughterCard(l_etRidArray[i],
+ l_targetList[i], i_index);
+
+ if ( NULL != l_errlHndl )
+ {
+ HDAT_DBG("error adding daughter card");
+ break;
+ }
+ }
+ }
+ else
+ {
+ HDAT_DBG("error from calloc");
+
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_IOHUB_BUILD_DAUGHTER
+ * @reasoncode HDAT::RC_MEM_ALLOC_FAIL
+ * @devdesc memory alloc failed in calloc
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_errlHndl,
+ MOD_IOHUB_BUILD_DAUGHTER,
+ RC_MEM_ALLOC_FAIL,
+ 0,0,0,0);
+
+ }
+ }
+ else
+ {
+ HDAT_DBG("no daughter cards for RID:0x%04x",
+ iv_fru.hdatResourceId);
+ }
+
+ // Tell the base class about child structures and adjust size of
+ // daughter card structures so they are all the same size
+ if (NULL == l_errlHndl && iv_daughterPtrs != NULL)
+ {
+ for(l_loopCnt = 0;l_loopCnt < iv_actDaughterCnt;l_loopCnt++)
+ {
+ /*l_daughter = *(HdatVpd **)((char *)iv_daughterPtrs +
+ l_loopCnt * sizeof(HdatVpd *));*/
+
+ l_daughter = *(reinterpret_cast<HdatVpd **>
+ (reinterpret_cast<char *>(iv_daughterPtrs) +
+ l_loopCnt * sizeof(HdatVpd *)));
+
+ l_daughter->maxSiblingSize(iv_maxDaughterSize);
+
+ HDAT_DBG("calling addChild");
+ this->addChild(HDAT_DAUGHTER_CARD, iv_maxDaughterSize, 1);
+ }
+ }
+
+ HDAT_EXIT();
+
+ return l_errlHndl;
+
+}//end bldDaughterStruct
+
+
+/******************************************************************************/
+//getTotalIoKwdSize
+/******************************************************************************/
+
+uint64_t HdatIoHubFru::getTotalIoKwdSize()
+{
+ HDAT_ENTER();
+
+ return (iv_maxDaughterSize * iv_actDaughterCnt);
+
+ HDAT_EXIT();
+}
+
+/******************************************************************************/
+// addDaughterCard
+/******************************************************************************/
+errlHndl_t HdatIoHubFru::addDaughterCard(uint32_t i_resourceId,
+ TARGETING::Target * i_target,
+ uint32_t i_index)
+{
+ HDAT_ENTER();
+
+ //eye catcher
+ const char HDAT_KID_STRUCT_NAME[] = "IO KID";
+ errlHndl_t l_errlHndl = NULL;
+ HdatVpd *l_vpdObj, **l_arrayEntry;
+ uint32_t l_size;
+ uint32_t l_vpdType = 0x0;
+ uint32_t FRU_BP = 0x8;
+
+ l_vpdObj = NULL;
+ l_vpdType = i_resourceId >> 8;
+ HDAT_DBG("vpd type= %x",l_vpdType);
+
+ // Ensure we are not trying to add more daughter cards than what we were
+ // told to allow for on the constructor
+ if (iv_actDaughterCnt < iv_maxDaughters)
+ {
+ if ( l_vpdType == FRU_BP )
+ {
+
+ uint32_t i_num = sizeof(mvpdData)/sizeof(mvpdData[0]);
+ l_vpdObj = new HdatVpd(l_errlHndl, i_resourceId,i_target,
+ HDAT_KID_STRUCT_NAME,i_index,BP,
+ mvpdData,i_num,l_pvpdKeywords);
+ }
+ //@TODO: RTC 148660 pci slots and cards
+
+ if (NULL == l_errlHndl)
+ {
+ l_arrayEntry = reinterpret_cast<HdatVpd **>(reinterpret_cast<char *>
+ (iv_daughterPtrs) +
+ iv_actDaughterCnt * sizeof(HdatVpd *));
+ *l_arrayEntry = l_vpdObj;
+
+ // Keep track of the largest daughter card object
+ l_size = l_vpdObj->size();
+ if (l_size > iv_maxDaughterSize)
+ {
+ iv_maxDaughterSize = l_size;
+ }
+ iv_actDaughterCnt++;
+ }
+ else
+ {
+ HDAT_DBG("could not create HdatVpd obj,"
+ " got error");
+ delete l_vpdObj;
+ }
+ }
+ else
+ {
+ HDAT_DBG("exceeded limit of number of daughter card"
+ " array entries");
+ }
+
+ HDAT_EXIT();
+
+ return l_errlHndl;
+}
+
+
+
+/******************************************************************************/
+// hdatLoadIoData
+/******************************************************************************/
+
+errlHndl_t hdatLoadIoData(const hdatMsAddr_t &i_msAddr,
+ uint32_t& o_size,uint32_t& o_count)
+{
+ HDAT_ENTER();
+
+ errlHndl_t l_err = NULL;
+ uint32_t l_size = 0;
+ uint64_t l_totKwdSize = 0;
+ IO_MAP l_iomap;
+
+ o_size = 0;
+ o_count = 0;
+
+
+ do
+ {
+ //For all present procs in the system
+ TARGETING::PredicateCTM l_ctm1(TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_PROC);
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+ TARGETING::PredicatePostfixExpr l_presentProc;
+ l_presentProc.push(&l_ctm1).push(&l_predHwas).And();
+ TARGETING::TargetRangeFilter l_proc(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentProc);
+
+ uint32_t l_numProcs = 0; //number of io entries
+ for (;l_proc;++l_proc,l_numProcs++) //so index will be same as l_proc
+ {
+ HDAT_DBG("for loop starting for index=%d",l_numProcs);
+
+ TARGETING::Target *l_pProcTarget = *(l_proc);
+
+
+ uint32_t l_rid = 0,l_slcaIdx = 0;
+
+ l_rid = l_pProcTarget->getAttr<ATTR_SLCA_RID>();
+ l_slcaIdx = l_pProcTarget->getAttr<ATTR_SLCA_INDEX>();
+
+ HDAT_DBG("got RID value as %d",l_rid);
+
+ uint32_t l_procOrdId =
+ l_pProcTarget->getAttr<TARGETING::ATTR_ORDINAL_ID>();
+ HDAT_DBG("got ordinal id as %d",l_procOrdId);
+
+
+ TARGETING::PredicateCTM l_pciPredicate(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_PCI);
+ TARGETING::TargetHandleList l_pciList;
+
+
+ //Add support for finding the card type
+ //All values except HDAT_PROC_CARD is reverved
+ hdatCardType l_cardType = HDAT_PROC_CARD;
+
+ uint32_t l_procEcLevel = 0;
+ uint32_t l_procChipId = 0;
+ l_err = hdatGetIdEc(l_pProcTarget,
+ l_procEcLevel,
+ l_procChipId);
+ if(NULL != l_err)
+ {
+ HDAT_ERR("Error in getting proc IdEc");
+ break;
+ }
+ TARGETING::ATTR_MRU_ID_type l_mruId = 0;
+
+ l_mruId = l_pProcTarget->getAttr<TARGETING::ATTR_MRU_ID>();
+ HDAT_DBG("got mru id as %d",l_mruId);
+
+ if(NULL != l_err)
+ {
+ HDAT_ERR("Error in getting MRU ID");
+ break;
+ }
+
+ HdatIoHubFru * fruData = new HdatIoHubFru(l_err,
+ l_rid,
+ l_cardType,
+ 0,
+ l_numProcs,
+ l_slcaIdx);
+
+ hdatHubEntry_t *l_hub;
+
+ l_hub = reinterpret_cast<hdatHubEntry_t *>(reinterpret_cast<char *>
+ (fruData->iv_hubArray) +
+ fruData->iv_hubArrayHdr.hdatArrayCnt * sizeof(hdatHubEntry_t));
+
+ // Save information about the I/O chip
+ l_hub->hdatIoHubId = l_procOrdId;
+
+ if(isFunctional(l_pProcTarget))
+ {
+ l_hub->hdatFlags = HDAT_HUB_USABLE;
+ }
+ else
+ {
+ l_hub->hdatFlags = HDAT_HUB_NOT_USABLE;
+ }
+ if (fruData->iv_hubStatus != 0)
+ {
+ // Replace status bits in hdatFlags with iv_hdatStatus
+ l_hub->hdatFlags &= ~HDAT_HUB_STATUS_MASK;
+ l_hub->hdatFlags |= fruData->iv_hubStatus;
+ }
+ HDAT_DBG("hdatFlags 1: %X",l_hub->hdatFlags);
+
+ TARGETING::ATTR_MODEL_type l_model =
+ (l_pProcTarget->getAttr<TARGETING::ATTR_MODEL>());
+
+ if(l_model == TARGETING::MODEL_MURANO)
+ {
+ l_hub->hdatChipId = HDAT_MODULE_TYPE_ID_MURANO;
+ }
+ else if(l_model == TARGETING::MODEL_VENICE)
+ {
+ l_hub->hdatChipId = HDAT_MODULE_TYPE_ID_VENICE;
+ }
+ else
+ {
+ HDAT_ERR("Chip is not in Murano,Venice");
+ }
+
+ l_hub->hdatEcLvl = l_procEcLevel;
+ l_hub->hdatProcChipID = l_procOrdId;
+ l_hub->hdatHardwareTopology = l_pProcTarget->
+ getAttr<TARGETING::ATTR_PROC_HW_TOPOLOGY>();
+ l_hub->hdatMRID = l_mruId;
+
+ //memory map version
+ l_hub->hdatMemMapVersion = 2;
+
+ l_hub->hdatFab0PresDetect = l_pProcTarget->
+ getAttr<TARGETING::ATTR_PROC_PCIE_PHB_ACTIVE>();
+
+
+ TARGETING::ATTR_PROC_PCIE_LANE_EQUALIZATION_type l_laneEq = {{0}};
+
+ if(!l_pProcTarget->
+ tryGetAttr<TARGETING::ATTR_PROC_PCIE_LANE_EQUALIZATION>(
+ l_laneEq))
+ {
+ HDAT_ERR("ATTR_PROC_PCIE_LANE_EQUALIZATION"
+ " not found");
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_IOHUB_LOAD_DATA
+ * @reasoncode HDAT::RC_TGT_ATTR_NOTFOUND
+ * @devdesc Target attribute not found
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_err,
+ MOD_IOHUB_LOAD_DATA,
+ RC_TGT_ATTR_NOTFOUND,
+ 0,0,0,0);
+ break;
+ }
+
+ //copying data from l_laneEq(which is 4x32 bytes) to
+ //uint16_t hdatLaneEqPHB[64]
+ memcpy( l_hub->hdatLaneEqPHB, l_laneEq,
+ (NUM_BYTES_PER_LANE * HDAT_PHB_LANES));
+
+ //increment counts
+ fruData->iv_hubArrayHdr.hdatArrayCnt++;
+
+ //build the daughter structure
+ l_err = fruData->bldDaughterStruct(l_pProcTarget,l_numProcs);
+
+
+ if ( l_err )
+ {
+ HDAT_ERR("error in building daughter structure");
+ break;
+ }
+
+ HDAT_DBG("fruData.bldDaughterStruct done, will insert to the map");
+
+ //insert the fru data to the map
+ l_iomap.insert(std::pair<uint32_t,HdatIoHubFru*>
+ (l_numProcs,fruData));
+ HDAT_DBG("done inserting into the map");
+
+ l_totKwdSize = fruData->getTotalIoKwdSize();
+ HDAT_DBG("got l_totKwdSize=%x",l_totKwdSize);
+
+ }//end for loop
+
+ o_count = l_numProcs;
+ HDAT_DBG("setting count same to index=%d,o_count=%d",
+ l_numProcs,o_count);
+
+
+ //calculate the virtual address to start writing at main memory
+ //allocate space for iohub data
+
+ uint64_t i_base_addr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo;
+ uint64_t l_childPtrSize = HDAT_CHILD_LAST * sizeof(hdatHDIFChildHdr_t);
+ uint32_t l_mod = l_childPtrSize % HDAT_MULTIPLE;
+
+ if ( l_mod > 0 )
+ {
+ l_childPtrSize += HDAT_MULTIPLE - l_mod;
+ }
+ uint64_t l_totalsize = (HDAT_MAX_IO_CHIPS * sizeof(hdatHubEntry_t)) +
+ (HDAT_PARENT_LAST * sizeof(hdatHDIFDataHdr_t))+
+ l_childPtrSize;
+
+ uint64_t i_base_addr_down = ALIGN_PAGE_DOWN(i_base_addr);
+
+ //l_numProcs carries the number of proc
+ //allocate the memory
+ HDAT_DBG("allocating memory (l_totalsize * l_numProcs)+l_totKwdSize=%x",
+ ((l_totalsize * l_numProcs)+ l_totKwdSize));
+
+ void *l_virt_addr = mm_block_map (
+ reinterpret_cast<void*>(i_base_addr_down),
+ ALIGN_PAGE((l_totalsize * l_numProcs)+ l_totKwdSize)
+ + PAGESIZE);
+
+ uint64_t l_vaddr = reinterpret_cast<uint64_t>(l_virt_addr);
+ l_vaddr += i_base_addr-i_base_addr_down;
+ l_virt_addr = reinterpret_cast<void *>(l_vaddr);
+
+ uint8_t* l_virtAddr = reinterpret_cast<uint8_t *>(l_virt_addr);
+
+ HDAT_DBG("l_virtAddr =0x%016llX, l_virt_addr=0x%016llX",
+ (uint64_t)l_virtAddr,(uint64_t)l_virt_addr);
+
+ //Iterate thru each FRU data and write to mainstore
+
+ IO_MAP::iterator l_itr;
+ for(l_itr = l_iomap.begin(); l_itr != l_iomap.end(); ++l_itr)
+ {
+ HDAT_DBG("writing to main memory");
+ uint8_t* l_startAddr = l_virtAddr;
+
+ //write to main memory
+ l_virtAddr= l_itr->second->setIOHub(l_virtAddr,l_size);
+
+ if ( l_size > o_size )
+ {
+ o_size = l_size;
+ }
+
+ //add the required padding after each io object
+ uint32_t l_rem = o_size % 128;
+ uint32_t l_pad = l_rem ? (128 - l_rem) : 0;
+ l_virtAddr = l_startAddr + l_pad + o_size;
+ HDAT_DBG("wrote pad of 0x%x size after io object",l_pad);
+
+ }//done writing to memory
+
+
+ //unmap the region
+ int rc = 0;
+ rc = mm_block_unmap(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(
+ reinterpret_cast<uint64_t>(l_virt_addr))));
+
+ if( rc != 0)
+ {
+ HDAT_ERR("unmap of iohub region failed");
+ errlHndl_t l_errl = NULL;
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_IOHUB_LOAD_DATA
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_errl,
+ MOD_IOHUB_LOAD_DATA,
+ RC_DEV_MAP_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+
+ //erase the map
+ for (l_itr = l_iomap.begin(); l_itr != l_iomap.end();)
+ {
+ //need to delete the object first
+ delete(l_itr->second);
+
+ l_iomap.erase(l_itr++);
+ }//end erasing
+
+ }while(0);
+
+
+ HDAT_EXIT();
+ return l_err;
+} //end hdatLoadIoData
+}
diff --git a/src/usr/hdat/hdatiohub.H b/src/usr/hdat/hdatiohub.H
new file mode 100755
index 000000000..8e58d823a
--- /dev/null
+++ b/src/usr/hdat/hdatiohub.H
@@ -0,0 +1,500 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatiohub.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATIOHUB_H
+#define HDATIOHUB_H
+
+/**
+ * @file hdatiohubfru.H
+ *
+ * @brief This file contains the class definition for the I/O hub FRU object.
+ *
+ */
+
+
+/*---------------------------------------------------------------------------*/
+/* Includes */
+/*---------------------------------------------------------------------------*/
+#include <stdint.h>
+#include <hdat/hdat.H>
+#include "hdatutil.H"
+#include <hdat/hdat_reasoncodes.H>
+#include "hdathdif.H"
+#include "hdatvpd.H"
+#include <errl/errlentry.H>
+#include <vector>
+#include<map>
+
+
+namespace HDAT
+{
+
+#define HDAT_PHB_LANES 64
+#define NUM_BYTES_PER_LANE 2
+#define NUM_LANES_PER_PHB 16
+
+const uint16_t HDAT_VPD_VERSION = 0x0020;
+const uint16_t HDAT_IO_VERSION = 0x6A;
+
+const uint32_t HDAT_MAX_IO_CHIPS = 10;
+
+/*---------------------------------------------------------------------------*/
+/* Type definitions */
+/*---------------------------------------------------------------------------*/
+
+/** @brief Structure definition for the hub ID data section of the CEC HUB FRU
+ * hypervisor data area.
+ * Reserved bytes are added to make the structure a multiple of 4 bytes.
+ * Adjust the reserved size as necessary if new members are added to this
+ * structure.
+ */
+struct hdatHubId_t
+{
+ uint32_t hdatCardType; // 0x0000 FRU card type
+ uint32_t hdatReserved1; // 0x0004 Formerly Processor Module Id
+ uint16_t hdatReserved2; // 0x0008 Total number of chips on this FRU
+ // and daughter card
+ uint8_t hdatReserved3; // 0x000A Various flags
+ uint8_t hdatReserved4; // 0x000B padding for alignment
+ uint16_t hdatReserved5; // 0x000C Hub ID whose passthru port
+ // this FRU is connected to
+ uint16_t hdatReserved6; // 0x000E padding for alignment.
+ //Reuse if another field is added to this structure
+} __attribute__ ((packed));
+
+
+/** @brief Structure definition for the hub array entry data section of the CEC
+ * HUB FRU hypervisor data area
+ */
+struct hdatHubEntry_t
+{
+ hdatMsAddr_t hdatReserved1; // 0x0000 TCE address for I/O hub
+ uint32_t hdatReserved2; // 0x0008 Size of I/O hub's TCE
+ uint16_t hdatIoHubId; // 0x000C I/O hub chip instance number
+ uint8_t hdatFlags; // 0x000E Chip status
+ uint8_t hdatReserved3; // 0x000F Reserved
+ uint8_t hdatFab0PresDetect; // 0x0010 I/O hub chip fabric 0
+ // presence detect bits
+ uint8_t hdatReserved4; // 0x0011 Reserved
+ uint16_t hdatChipId; // 0x0012 Module type Identification
+ uint32_t hdatEcLvl; // 0x0014 EC level
+ uint32_t hdatReserved5; // 0x0018 Affinity domain 2
+ uint32_t hdatReserved6; // 0x001C Affinity Domain 3
+ uint32_t hdatReserved7; // 0x0020 Reserved
+ uint32_t hdatReserved8; // 0x0024 Reserved
+ uint32_t hdatProcChipID; // 0x0028 Proc Chip ID associated with
+ // this HUB
+ uint32_t hdatReserved9; // 0x002C Reserved
+ uint32_t hdatReserved10; // 0x0030 Reserved
+ uint16_t hdatReserved11; // 0x0032 Reserved
+ uint16_t hdatHardwareTopology;// 0x0034 Hardware Topology
+ uint32_t hdatMRID; // 0x0038 MRU ID of Chip
+ uint32_t hdatMemMapVersion; // 0x003C Memory Map Version
+ uint16_t hdatLaneEqPHB[HDAT_PHB_LANES]; // 0x0040 Lane Equalization values
+ //from PHB0 to PHB3
+
+
+
+ hdatHubEntry_t() : hdatProcChipID(0), hdatHardwareTopology(0),
+ hdatMRID(0xDEADBEEF), hdatMemMapVersion(0xDEADBEEF), hdatLaneEqPHB()
+ {
+ }
+} __attribute__ ((packed));
+
+
+
+/** @enum hdatDataPtrs
+ * Constants for the internal data pointers that are added to the base
+ * class
+ */
+enum hdatioDataPtrs
+{
+ HDAT_FRU_ID = 0,
+ HDAT_ASCII_KWD = 1,
+ HDAT_HUB_ID = 2,
+ HDAT_HUBS_ARRAY = 3,
+ HDAT_PARENT_RESERVED1 = 4,
+ HDAT_PARENT_RESERVED2 = 5,
+ HDAT_PARENT_LAST = 6
+};
+
+/** @enum hdatChildPtrs
+ * Constants for the child structure pointers that are added to the base
+ * class
+ */
+enum hdatioChildPtrs
+{
+ HDAT_DAUGHTER_CARD = 0,
+ HDAT_CHILD_RESERVED1 = 1,
+ HDAT_CHILD_LAST = 2
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Constants */
+/*---------------------------------------------------------------------------*/
+
+/** @enum hdatCardType
+ * Enumeration of FRU card types used in the CEC HUB FRU identification
+ * structure
+ */
+enum hdatCardType
+{
+ HDAT_IO_HUB_CARD = 1,
+ HDAT_PROC_CARD = 2,
+ HDAT_CEC_BACK_PLANE_CARD = 3,
+ HDAT_BACK_PLANE_EXT_CARD = 4
+};
+
+
+/** @enum hdatHubStatus
+ * Status of an I/O hub chip.
+ */
+enum hdatHubStatus
+{
+ HDAT_HUB_USABLE = 0x00, // Usable, no failures
+ HDAT_HUB_FAILURES = 0x40, // Usable, failures encountered
+ HDAT_HUB_NOT_INSTALLED = 0x80, // Not installed
+ HDAT_HUB_NOT_USABLE = 0xC0 // Unusable
+};
+
+
+// Bit definitions of the hdatFlags field of hdatHubEntry_t
+// that are not included in hdatHubStatus enum.
+#define HDAT_HUB_IS_MASTER 0x20 // HUB is the master I/O HUB
+#define HDAT_HUB_GARDMASK_VALID 0x08 // for setting gardmask valid
+#define HDAT_HUB_SWITCH_MASK_VALID 0x04 // Switch Mask field is valid
+#define HDAT_HUB_FABRIC_0_VALID 0x02 // Fabric Bridge 0 Presence Detect
+ //field is valid
+#define HDAT_HUB_FABRIC_1_VALID 0x01 // Fabric Bridge 1 Presence Detect
+ // field is valid
+#define HDAT_HUB_STATUS_MASK 0xC0 // for masking status bits during logical
+ // and/or ops
+
+
+// Bit definitions of the hdatFab0PresDetect & hdatFab1PresDetect
+// fields of hdatHubEntry_t
+#define HDAT_HUB_FAB_BRIDGE_PHB0 0x80 // HUB Fabric Bridge PHB0
+ //presence detect bit
+#define HDAT_HUB_FAB_BRIDGE_PHB1 0x40 // HUB Fabric Bridge PHB1
+ //presence detect bit
+#define HDAT_HUB_FAB_BRIDGE_PHB2 0x20 // HUB Fabric Bridge PHB2
+ //presence detect bit
+#define HDAT_HUB_FAB_BRIDGE_PHB3 0x10 // HUB Fabric Bridge PHB3
+ //presence detect bit
+
+
+#define HDAT_MODULE_TYPE_ID_MURANO 0x0001
+#define HDAT_MODULE_TYPE_ID_VENICE 0x0010
+
+
+
+/*---------------------------------------------------------------------------*/
+/* C++ class definition */
+/*---------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatIoHubFru class is used to construct I/O hub FRU objects.
+ * For P8, the CEC Hub FRU refers to the DCM.
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that any component can create an object of this type.
+ * In particular,the object is built only in the
+ * CEC Server process when requested
+ * by the hdat component.
+ *
+ * The real purpose of the object is to create the CEC Hub FRU
+ * array structure as defined by the PHYP Initialization
+ * architecture. This data structure is eventually DMA'd to
+ * main memory. The class is not defined to be a general purpose
+ * interface for building this object by anyone other than the
+ * CEC Server process.
+ *
+ * Thread safety: An HdatIoHubFru object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by multiple
+ * threads at the same time. In fact, an object interface is
+ * used only as a better way to built a flat structure to DMA
+ * to main memory.
+ *
+ * Signal handler usage: This class is not intended to be used in a
+ * signal handler and nothing has been done
+ * to try and make it safe to use
+ * in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatIoHubFru : public HdatHdif
+{
+public:
+
+
+ /**
+ * @brief Construct an HdatIoHubFru object.
+ *
+ * This is the constructor for the HdatIoHubFru object when that I/O HUB
+ * is not currently plugged but has been reserved for concurrent
+ * maintenance.
+ *
+ * If you are constructing this object on the heap by using new, then
+ * you must check the pointer returned from new to see if it is null.
+ * If it is null, new failed to allocate storage and the constructor
+ * was not called. If it is not null, then you must check o_errlHndl
+ * to see if the constructor ran successfully. If o_errlHndl indicates
+ * an error was reported by the constructor, new has already allocated
+ * heap storage and the object must be deleted in order to free the
+ * heap storage.
+ *
+ * @pre None
+ *
+ * @post An HdatIoHubFru object has been constructed.
+ * Heap storage has been allocated.
+ *
+ * @param o_errlHndl - output parameter - If any errors occur,
+ * the HdatIoHubFru object is NOT constructed
+ * and errors are returned in this parameter
+ *
+ * @param i_resourceId - input parameter RID value for the FRU
+ * @param i_cardType - input parameter - FRU card type
+ * @param i_daughterCnt - input parameter - The count of the number of
+ * daughter cards
+ * @param i_index - input parameter - instance of the object created
+ * @param i_slcaIdx - input parameter - SLCA index of the FRU
+ *
+ * @return A null error log handle if successful,else the return code pointed
+ * to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ */
+
+ HdatIoHubFru(errlHndl_t &o_errlHndl,
+ uint32_t i_resourceId,
+ hdatCardType i_cardType,
+ uint32_t i_daughterCnt,
+ uint32_t i_index,
+ uint32_t i_slcaIdx);
+
+
+ /**
+ * @brief HdatIoHubFru object destructor
+ *
+ * This is the destructor for an HdatIoHubFru object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatIoHubFru object has been destroyed and can no longer be used.
+ *
+ */
+ ~HdatIoHubFru();
+
+
+
+ /**
+ * @brief write the data to main memory
+ *
+ * @param io_virt_addr - input parameter inputs the address to be
+ * written at. outputs the next iohub address
+ *
+ * @param o_size - output parameter - size of iohub data
+ *
+ * @return A null error log handle if successful,else the return code pointed
+ * to by errlHndl_t contains one of the error
+ */
+ uint8_t * setIOHub(uint8_t * io_virt_addr,
+ uint32_t& o_size);
+
+ /**
+ * @brief Add a daughter card description.
+ *
+ * Each I/O daughter card which provides part of the I/O path must be added
+ * to the HdatIoHubFru object. This method adds information about the card
+ *
+ * @pre None
+ *
+ * @post A card's VPD definiton has been added to the object. Heap storage
+ * has been allocated.
+ *
+ * @param i_resourceId - input parameter -
+ * VPD resource id for the daughter card FRU
+ * @param i_target - input parameter - TARGET value of the FRU
+ * @param i_index - input parameter - instance number to be added
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addDaughterCard( uint32_t i_resourceId,
+ TARGETING::Target * i_target, uint32_t i_index);
+
+
+ /**
+ * @brief Build the hypervisor data area structres for I/O hub daughter cards.
+ *
+ * Each I/O daughter card which provides part of the I/O path must have
+ * a data structure built for it.
+ *
+ * IMPLEMENTATION NOTE. This is not a generalized method. For the
+ * Squadrons program, no I/O hubs required daughter card structures
+ * so there was no good way to test the implementation. When P5IOC2
+ * with Host Ethernet Adapter support came along in eClipz, there was
+ * a need for daughter card structures. But no other I/O hub type
+ * had this requirement. So again, no easy way to test a generalized
+ * implementation. So to simplify the code, this routine is specific
+ * to P5IOC2. If some other I/O card comes along with a need for
+ * daughter card structures, this rotuine will likely require changes.
+ *
+ *
+ * @pre None
+ *
+ * @param i_target - input parameter - TARGET value of the daughter
+ * @param i_index - input parameter - instance number to be added
+ *
+ * @post A card's VPD definiton has been added to the object. Heap storage
+ * has been allocated.
+ *
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ */
+ errlHndl_t bldDaughterStruct( const TARGETING::Target * i_target,
+ uint32_t i_index );
+
+
+ /*
+ * @brief fetches all the daughter card information for a proc when the
+ * TARGET is passed
+ *
+ * @pre None
+ *
+ * @param i_target - input parameter - TARGET value of the FRU
+ * @param o_targetList - output parameter - daughter TARGET list
+ * @param o_DaughterRids - output parameter - daughter card RID list
+ *
+ * @post o_DaughterRids is populated with the daughter RID data
+ *
+ * @return A null error log handle if successful, else the error
+ * handle
+ */
+
+ errlHndl_t hdatGetDaughterInfoFromTarget(const TARGETING::Target * i_target,
+ TARGETING::TargetHandleList& o_targetList,
+ std::vector <uint32_t>& o_DaughterRids);
+
+
+
+ /* @brief function to get the total keyword size for
+ * all the iohub objects
+ * @pre None
+ * @return the size
+ */
+
+ uint64_t getTotalIoKwdSize();
+
+
+
+
+ /* @brief construct the iohub data. This function will be called from
+ * the interface. The constructor of iohub will be called inside this
+ * function
+ *
+ * @pre None
+ *
+ * @param i_msAddr - input parameter - MS address where the io hub data need
+ * to be written at
+ *
+ * @param o_size - output parameter - size of the iohub data
+ * @param o_count - output parameter - number of iohub
+ *
+ * @post The iohub data along with daughter card information is constructed
+ * and written to memory
+ *
+ * @return A null error log handle if successful, else the error
+ * handle
+ *
+ */
+ friend errlHndl_t hdatLoadIoData(const hdatMsAddr_t &i_msAddr,
+ uint32_t &o_size,
+ uint32_t &o_count);
+
+
+
+ private:
+ /** Object Instance Data
+ *
+ * @li iv_msAddr - main memory address the final data structure is
+ * DMA'd to
+ * @li iv_hubStatus - operational status of the IO Hub
+ * @li iv_kwdSize - size of the VPD ASCII keyword
+ * @li iv_maxHubs - maximum number of hub chips that can be added
+ * with addIoChip()
+ * @li iv_maxDaughters - maximum number of daughter cards that can be
+ * added with
+ * addDaughterCard()
+ * @li iv_hubArraySize - total size of the I/O hub array.
+ * @li iv_actDaughterCnt - number of daughter cards added to this object
+ * @li iv_maxDaughterSize - maximum size of a daughter card
+ * @li iv_kwd - ptr to the VPD ASCII keyword
+ * @li iv_fru - I/O hub FRU structure
+ * @li iv_hubId - hub FRU ID structure
+ * @li iv_hubArrayHdr - data header for the I/O hub array
+ * @li iv_hubArray - ptr to storage which holds the I/O hub array
+ * entries
+ * @li iv_daughterPtrs - ptr to one or more ptrs which in turn point to
+ * HdatVpd objects
+ */
+ hdatMsAddr_t iv_msAddr;
+ uint8_t iv_hubStatus;
+ uint32_t iv_kwdSize;
+ uint32_t iv_maxHubs;
+ uint32_t iv_maxDaughters;
+ uint32_t iv_hubArraySize;
+ uint32_t iv_actDaughterCnt;
+ uint32_t iv_maxDaughterSize;
+ char *iv_kwd;
+ hdatFruId_t iv_fru;
+ hdatHubId_t iv_hubId;
+ hdatHDIFDataArray_t iv_hubArrayHdr;
+ hdatHubEntry_t *iv_hubArray;
+ HdatVpd **iv_daughterPtrs;
+
+}; // end of HdatIoHubFru class
+
+
+
+/* @brief
+ * map to store the pointers of iohub objects to write them to
+ * memory later
+ */
+
+
+typedef std::map<uint32_t,HdatIoHubFru*> IO_MAP;
+
+} //namespace HDAT
+
+#endif // HDATIOHUB_H
diff --git a/src/usr/hdat/hdatiplparms.C b/src/usr/hdat/hdatiplparms.C
new file mode 100755
index 000000000..01cffb564
--- /dev/null
+++ b/src/usr/hdat/hdatiplparms.C
@@ -0,0 +1,1148 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatiplparms.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+
+
+/**
+ * @file hdatiplparms.C
+ *
+ * @brief This file contains the implementation of the HdatIplParms class.
+ *
+ */
+
+/*------------------------------------------------------------------------*/
+/* Includes */
+/*------------------------------------------------------------------------*/
+#include <ctype.h> // endian testing
+#include "hdatiplparms.H" // HdatIplParms class definition
+#include <attributeenums.H>
+#include "hdatutil.H"
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include <vpd/mvpdenums.H>
+#include <pnor/pnorif.H>
+#include <util/align.H>
+
+#include <devicefw/userif.H>
+#include <targeting/common/util.H>
+
+using namespace TARGETING;
+
+namespace HDAT
+{
+
+extern trace_desc_t *g_trac_hdat;
+
+
+/*------------------------------------------------------------------------*/
+/* Constants */
+/*------------------------------------------------------------------------*/
+
+/**
+ * @brief This routine checks if a certain manufacturing flag is set
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_flag - input parameter - Specific mnfg flag to check
+ *
+ * @return true : The specified mnfg flag is set
+ * false : The specified mnfg flag is not set
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+static bool isMnfgFlagSet( uint32_t i_flag )
+{
+ bool o_rc = false;
+ TARGETING::ATTR_MNFG_FLAGS_type l_attrValue = 0;
+ TARGETING::TargetHandle_t l_pTopTarget= NULL;
+ targetService().getTopLevelTarget(l_pTopTarget);
+
+ if(l_pTopTarget)
+ {
+ l_attrValue = l_pTopTarget->getAttr<ATTR_MNFG_FLAGS>();
+ o_rc = l_attrValue & i_flag;
+ }
+ else
+ {
+ HDAT_ERR("[isMnfgFlagSet] error finding l_pTopTarget");
+ }
+
+ return o_rc;
+}
+
+
+/**
+ * @brief This routine gets number of cores in each processor
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_numCores - output parameter - Number of cores
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+static void hdatGetNumberOfCores(uint32_t &o_numCores)
+{
+ uint8_t l_prData[9];
+ size_t l_prDataSz = 8;
+ errlHndl_t l_err = NULL;
+
+ o_numCores = 0;
+
+
+ TARGETING::PredicateCTM l_procChipPredicate(TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_PROC);
+
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+
+ TARGETING::PredicatePostfixExpr l_presentProc;
+ l_presentProc.push(&l_procChipPredicate).push(&l_predHwas).And();
+
+ TARGETING::TargetRangeFilter l_procFilter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentProc);
+
+ TARGETING::Target *l_procTarget = (*l_procFilter);
+
+ l_err = deviceRead(l_procTarget,l_prData,l_prDataSz,
+ DEVICE_MVPD_ADDRESS(MVPD::VINI,MVPD::PR));
+
+ if(l_err)
+ {
+ HDAT_ERR("Error during VPD PR keyword read");
+ }
+ else
+ {
+ o_numCores = l_prData[2] >> 4;
+ HDAT_DBG("Number of Cores: %d",o_numCores);
+ }
+}
+
+/**
+ * @brief This routine gets the information for Enlarged IO Slot Count
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_EnlargedSlotCount - output parameter - Enlarged IO Slot Count for
+ * all nodes
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+static void hdatGetEnlargedIOCapacity(uint32_t &o_EnlargedSlotCount)
+{
+ TARGETING::PredicateCTM l_nodePredicate(TARGETING::CLASS_ENC,
+ TARGETING::TYPE_NODE);
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+
+ TARGETING::PredicatePostfixExpr l_presentNode;
+ l_presentNode.push(&l_nodePredicate).push(&l_predHwas).And();
+
+ TARGETING::TargetRangeFilter l_nodeFilter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentNode);
+
+ o_EnlargedSlotCount = 0;
+ uint8_t l_nodeindex = 3;
+
+ for (;l_nodeFilter;++l_nodeFilter)
+ {
+ TARGETING::Target *l_nodeTarget = (*l_nodeFilter);
+
+ TARGETING::ATTR_ENLARGED_IO_SLOT_COUNT_type l_enlargedIOSlotCount;
+ if(l_nodeTarget->tryGetAttr<TARGETING::ATTR_ENLARGED_IO_SLOT_COUNT>
+ (l_enlargedIOSlotCount))
+ {
+ o_EnlargedSlotCount |= (uint32_t)l_enlargedIOSlotCount <<
+ (8 * l_nodeindex);
+ }
+ else
+ {
+ HDAT_ERR("Error in getting ENLARGED_IO_SLOT_COUNT attribute");
+ }
+ l_nodeindex--;
+ }
+}
+
+/**
+ * @brief This routine gets the information for IPL Parameters
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_hdatOTA - output parameter - The structure to update with the
+ * other IPL attributes
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+static void hdatPopulateOtherIPLAttributes(hdatOtherIPLAttributes_t &o_hdatOTA)
+{
+ TARGETING::Target *l_pSysTarget = NULL;
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSysTarget);
+
+ if(l_pSysTarget == NULL)
+ {
+ HDAT_ERR("Error in getting Top Level Target");
+ assert(l_pSysTarget != NULL);
+ }
+
+ TARGETING::ATTR_IPL_ATTRIBUTES_type l_iplAttributes;
+ l_iplAttributes = l_pSysTarget->getAttr<TARGETING::ATTR_IPL_ATTRIBUTES>();
+
+ o_hdatOTA.hdatCreDefPartition = l_iplAttributes.createDefaultPartition;
+
+ o_hdatOTA.hdatCTAState = l_iplAttributes.clickToAcceptState;
+
+ o_hdatOTA.hdatDisVirtIOConn = l_iplAttributes.disableVirtIO;
+
+ o_hdatOTA.hdatResetPCINOs = l_iplAttributes.resetPCINumbers;
+
+ o_hdatOTA.hdatClrPhypNvram = l_iplAttributes.clearHypNVRAM;
+
+ TARGETING::ATTR_PRESERVE_MDC_PARTITION_VPD_type l_preserveMDCPartitionVPD;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_PRESERVE_MDC_PARTITION_VPD>
+ (l_preserveMDCPartitionVPD))
+ {
+ o_hdatOTA.hdatMDCLogPartVPD = l_preserveMDCPartitionVPD;
+ }
+ else
+ {
+ HDAT_ERR("Error in getting PRESERVE_MDC_PARTITION_VPD attribute");
+ }
+
+ //No CEC CM Capability on these systems
+ o_hdatOTA.hdatCECCMCapable = 0;
+
+ //i5/OS not available on this system
+ o_hdatOTA.hdati5OSEnable = 0;
+
+ o_hdatOTA.hdatSELFlagsValid = 1;
+
+ o_hdatOTA.hdatDelSELFromHyp = 1;
+
+ o_hdatOTA.hdatDelSELFromHB = 1;
+
+ o_hdatOTA.hdatDelSELFromBMC = 1;
+
+ //Lightpath support available on these systems
+ o_hdatOTA.hdatServiceIndMode = 1;
+
+ //RPA AIX/Linux
+ o_hdatOTA.hdatDefPartitionType = 1;
+
+}
+
+/**
+ * @brief This routine gets the information for IPL Parameters
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+void HdatIplParms::hdatGetIplParmsData()
+{
+ PNOR::SideInfo_t l_sideInfo;
+ errlHndl_t l_errl = NULL;
+
+ TARGETING::Target *l_pSysTarget = NULL;
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSysTarget);
+ if(l_pSysTarget == NULL)
+ {
+ HDAT_ERR("Error in getting Top Level Target");
+ assert(l_pSysTarget != NULL);
+ }
+
+ //IPL to hypervisor running
+ this->iv_hdatIPLParams->iv_iplParms.hdatIPLDestination = 0x02;
+
+ l_errl = PNOR::getSideInfo(PNOR::WORKING, l_sideInfo);
+ if(!l_errl)
+ {
+ if(l_sideInfo.isGolden)
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatIPLSide =
+ HDAT_FIRMWARE_SIDE_GOLDEN;
+ }
+ else
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatIPLSide =
+ HDAT_FIRMWARE_SIDE_WORKING;
+ }
+ }
+ else
+ {
+ ERRORLOG::errlCommit(l_errl,HDAT_COMP_ID);
+ }
+ // Fast IPL Speed
+ this->iv_hdatIPLParams->iv_iplParms.hdatIPLSpeed = 0xFF;
+
+
+ TARGETING::ATTR_IS_MPIPL_HB_type l_mpiplHB;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_IS_MPIPL_HB>(l_mpiplHB))
+ {
+ if(l_mpiplHB)
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatCECIPLAttributes = 0x2000;
+ this->iv_hdatIPLParams->iv_iplParms.hdatIPLMajorType = 0x01;
+ this->iv_hdatIPLParams->iv_iplParms.hdatIPLMinorType = 0x0D;
+ }
+ else
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatCECIPLAttributes = 0x1000;
+
+ this->iv_hdatIPLParams->iv_iplParms.hdatIPLMajorType = 0x00;
+
+ TARGETING::ATTR_CEC_IPL_TYPE_type l_cecIPLType;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_CEC_IPL_TYPE>
+ (l_cecIPLType))
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatIPLMinorType =
+ l_cecIPLType.MinorIPLType;
+ this->iv_hdatIPLParams->iv_iplParms.hdatIPLMinorType = 0xC;
+ HDAT_DBG("hdatGetIplParmsData: setting hdatIPLMinorType to 0xC0");
+ }
+ else
+ {
+ HDAT_ERR("Error in getting CEC_IPL_TYPE attribute");
+ }
+ }
+ }
+ else
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatIPLMinorType = 0x0C;
+ HDAT_DBG("hdatGetIplParmsData: setting hdatIPLMinorType to 0xC0");
+ HDAT_ERR("Error in getting IS_MPIPL_HB attribute");
+ }
+
+ TARGETING::ATTR_OS_IPL_MODE_type l_OSIPLMode;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_OS_IPL_MODE>(l_OSIPLMode))
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatOSIPLMode = l_OSIPLMode;
+ }
+ else
+ {
+ HDAT_ERR("Error in getting OS_IPL_MODE attribute");
+ }
+
+ this->iv_hdatIPLParams->iv_iplParms.hdatKeyLockPosition =
+ HDAT_KEYLOCK_MANUAL;
+
+ TARGETING::ATTR_LMB_SIZE_type l_lmbSize;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_LMB_SIZE>(l_lmbSize))
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatLMBSize = 4;
+ }
+ else
+ {
+ HDAT_ERR("Error in getting LMB_SIZE attribute");
+ }
+
+ TARGETING::ATTR_MAX_HSL_OPTICONNECT_CONNECTIONS_type l_hslConnections;
+ if(l_pSysTarget->tryGetAttr
+ <TARGETING::ATTR_MAX_HSL_OPTICONNECT_CONNECTIONS>
+ (l_hslConnections))
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatMaxHSLConns = l_hslConnections;
+ }
+ else
+ {
+ HDAT_ERR("Error in getting MAX_HSL_OPTICONNECT_CONNECTIONS attribute");
+ }
+
+ hdatPopulateOtherIPLAttributes(this->iv_hdatIPLParams->iv_iplParms.hdatOIA);
+
+ TARGETING::ATTR_HUGE_PAGE_COUNT_type l_hugePageCount;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_HUGE_PAGE_COUNT>
+ (l_hugePageCount))
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatHugePageMemCount =
+ l_hugePageCount;
+ }
+ else
+ {
+ HDAT_ERR("Error in getting HUGE_PAGE_COUNT attribute");
+ }
+
+ TARGETING::ATTR_HUGE_PAGE_SIZE_type l_hugePageSize;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_HUGE_PAGE_SIZE>
+ (l_hugePageSize))
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatHugePageMemSize =
+ l_hugePageSize;
+ }
+ else
+ {
+ HDAT_ERR("Error in getting HUGE_PAGE_SIZE attribute");
+ }
+
+ TARGETING::ATTR_VLAN_SWITCHES_type l_vlanSwitches;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_VLAN_SWITCHES>
+ (l_vlanSwitches))
+ {
+ this->iv_hdatIPLParams->iv_iplParms.hdatNumVlanSwitches =
+ l_vlanSwitches;
+ }
+ else
+ {
+ HDAT_ERR("Error in getting VLAN_SWITCHES attribute");
+ }
+
+ uint32_t hdatEnlargedIOCapacity = 0;
+ hdatGetEnlargedIOCapacity(hdatEnlargedIOCapacity);
+ this->iv_hdatIPLParams->iv_iplParms.hdatEnlargedIOCap =
+ hdatEnlargedIOCapacity;
+
+}
+
+/**
+ * @brief This routine gets the information for SP serial ports
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_portArrayHdr - output parameter - Array header
+ * @param o_ports - output parameter - The structure to update with the
+ * serial port information
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+static errlHndl_t hdatGetPortInfo(HDAT::hdatHDIFDataArray_t &o_portArrayHdr,
+ hdatPortCodes_t o_ports[])
+{
+ errlHndl_t l_errlHndl = NULL;
+ uint32_t l_loopCnt = 0;
+
+ o_portArrayHdr.hdatOffset = sizeof(HDAT::hdatHDIFDataArray_t);
+ o_portArrayHdr.hdatAllocSize = sizeof(hdatPortCodes_t);
+ o_portArrayHdr.hdatActSize = sizeof(o_ports);
+ o_portArrayHdr.hdatArrayCnt = 0;
+
+ TARGETING::PredicateCTM l_nodePredicate(TARGETING::CLASS_ENC,
+ TARGETING::TYPE_NODE);
+
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+
+ TARGETING::PredicatePostfixExpr l_presentNode;
+ l_presentNode.push(&l_nodePredicate).push(&l_predHwas).And();
+
+ //Get Node targets
+ TARGETING::TargetRangeFilter l_nodeFilter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentNode);
+
+ TARGETING::Target *l_nodeTarget = (*l_nodeFilter);
+
+ TARGETING::PredicateCTM l_serialPortPredicate(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_UART);
+
+ TARGETING::PredicatePostfixExpr l_presentSerialPort;
+ l_presentSerialPort.push(&l_serialPortPredicate).push(&l_predHwas).And();
+
+ TARGETING::TargetHandleList l_serialPortList;
+
+ //Get Serial Port targets associated with service processor
+ TARGETING::targetService().getAssociated(l_serialPortList, l_nodeTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL,
+ &l_presentSerialPort);
+
+ o_portArrayHdr.hdatArrayCnt = l_serialPortList.size();
+
+ for (uint32_t l_idx = 0; l_idx < l_serialPortList.size(); ++l_idx)
+ {
+ TARGETING::Target *l_serialportTarget = l_serialPortList[l_idx];
+ char l_locCodePrefix[64]={0};
+ char l_locCode[64]={0};
+
+ hdatGetLocationCodePrefix(l_locCodePrefix);
+ hdatGetLocationCode(l_serialportTarget,l_locCodePrefix,l_locCode);
+ HDAT_DBG(" Serial Port Loc Code :%s", l_locCode);
+
+ strncpy((char *)(o_ports[l_loopCnt].hdatLocCode),
+ l_locCode,
+ sizeof(o_ports[l_loopCnt].hdatLocCode));
+
+ o_ports[l_loopCnt].hdatResourceId = l_serialportTarget->getAttr
+ <TARGETING::ATTR_SLCA_RID>();
+
+ // None of the ports are used for callhome
+ o_ports[l_loopCnt].hdatCallHome = 0;
+ l_loopCnt++;
+ }
+
+ return l_errlHndl;
+}
+
+
+/**
+ * @brief This routine gets the information for System Parameters
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ **/
+void HdatIplParms::hdatGetSystemParamters()
+{
+
+ TARGETING::Target *l_pSysTarget = NULL;
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSysTarget);
+
+ if(l_pSysTarget == NULL)
+ {
+ HDAT_ERR("hdatGetSystemParamters::Top Level Target not found");
+ assert(l_pSysTarget != NULL);
+ }
+
+ // Get system information - system model
+ uint32_t l_sysModel = 0;
+
+ TARGETING::ATTR_RAW_MTM_type l_rawMTM = {0};
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_RAW_MTM>(l_rawMTM))
+ {
+ //we only want the last three bytes of the raw MTM, preceded by a 0x20
+ l_sysModel = *((reinterpret_cast<uint32_t*>(l_rawMTM))+1);
+ l_sysModel &= 0x00FFFFFF;
+ l_sysModel |= 0x20000000;
+ this->iv_hdatIPLParams->iv_sysParms.hdatSysModel = l_sysModel;
+ }
+ else
+ {
+ HDAT_ERR("Error in getting RAW_MTM attribute");
+ }
+
+ // Get system information - processor feature code
+ // Processor Feature Code = CCIN of Anchor Card
+ // No Anchor Card in BMC systems
+ this->iv_hdatIPLParams->iv_sysParms.hdatProcFeatCode = 0;
+
+ // Get system information - effective PVR
+ TARGETING::ATTR_EFFECTIVE_EC_type l_effectiveEc;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_EFFECTIVE_EC>(l_effectiveEc))
+ {
+ //Convert Ec format to PVR Ec format
+ uint32_t l_pvrEc = ( ((l_effectiveEc & 0xF0) << 4) |
+ (l_effectiveEc & 0xF) );
+
+ TARGETING::PredicateCTM l_procFilter(TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_PROC);
+
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+
+ TARGETING::PredicatePostfixExpr l_presentProc;
+ l_presentProc.push(&l_procFilter).push(&l_predHwas).And();
+
+ TARGETING::TargetHandleList l_procList;
+
+ //Get all Procs in the system
+ TARGETING::targetService().
+ getAssociated(l_procList, l_pSysTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL, &l_presentProc);
+
+ if(l_procList.size() > 0)
+ {
+ TARGETING::Target *l_procTarget = l_procList[0];
+ ATTR_MODEL_type l_procModel;
+
+ if(l_procTarget->tryGetAttr<ATTR_MODEL>(l_procModel))
+ {
+ //Effective Processor Version Register (PVR)
+ // bits 0-15: Processor version number
+ // bits 16-19: Reserved
+ // bits 20-23: Full RIT
+ // bits 24-27: Reserved
+ // bits 28-31: Minor revision level
+
+ if(l_procModel == MODEL_MURANO)
+ {
+ this->iv_hdatIPLParams->iv_sysParms.hdatEffectivePvr =
+ 0x004B0000 | l_pvrEc;
+ }
+ else if(l_procModel == MODEL_VENICE)
+ {
+ this->iv_hdatIPLParams->iv_sysParms.hdatEffectivePvr =
+ 0x004D0200 ;
+ }
+ HDAT_DBG(" Effective PVR :0X%x",
+ this->iv_hdatIPLParams->iv_sysParms.hdatEffectivePvr);
+ }
+ else
+ {
+ HDAT_ERR("Error reading attribute ATTR_MODEL");
+ }
+ }
+ else
+ {
+ HDAT_ERR("No Processors found in the system");
+ assert(l_procList.size() > 0);
+ }
+ }
+ else
+ {
+ HDAT_ERR(" Error in getting attribute EFFECTIVE_EC");
+ }
+
+ // Get system type
+ iv_hdatIPLParams->iv_sysParms.hdatSysType =
+ (l_pSysTarget->getAttr<TARGETING::ATTR_PHYP_SYSTEM_TYPE>());
+
+ //Get ABC Bus Speed
+ TARGETING::ATTR_FREQ_A_MHZ_type l_ABCBusSpeed;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_FREQ_A_MHZ>(l_ABCBusSpeed))
+ {
+ this->iv_hdatIPLParams->iv_sysParms.hdatABCBusSpeed = l_ABCBusSpeed;
+ }
+ else
+ {
+ HDAT_ERR(" Error in getting attribute FREQ_A_MHZ");
+ }
+
+ //Get XYZ Bus Speed
+ TARGETING::ATTR_FREQ_X_MHZ_type l_WXYZBusSpeed;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_FREQ_X_MHZ>(l_WXYZBusSpeed))
+ {
+ this->iv_hdatIPLParams->iv_sysParms.hdatWXYZBusSpeed = l_WXYZBusSpeed;
+ }
+ else
+ {
+ HDAT_ERR(" Error in getting attribute FREQ_X_MHZ");
+ }
+
+ // NO ECO Support
+ this->iv_hdatIPLParams->iv_sysParms.hdatSystemECOMode = 0;
+
+ this->iv_hdatIPLParams->iv_sysParms.hdatSystemAttributes = 0;
+
+ //Populate SMM Enabled/Disabled attribute
+ TARGETING::ATTR_PAYLOAD_IN_MIRROR_MEM_type l_payLoadMirrorMem;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_PAYLOAD_IN_MIRROR_MEM>
+ (l_payLoadMirrorMem))
+ {
+ this->iv_hdatIPLParams->iv_sysParms.hdatSystemAttributes |=
+ ( static_cast<uint8_t>(l_payLoadMirrorMem) ? HDAT_SMM_ENABLED : 0);
+ }
+ else
+ {
+ HDAT_ERR(" Error in getting attribute PAYLOAD_IN_MIRROR_MEM");
+ }
+
+ this->iv_hdatIPLParams->iv_sysParms.hdatMemoryScrubbing = 0;
+
+ // Get SPPL information
+ uint32_t l_numCores;
+
+ TARGETING::ATTR_OPEN_POWER_TURBO_MODE_SUPPORTED_type l_turboModeSupported;
+ if(l_pSysTarget->tryGetAttr
+ <TARGETING::ATTR_OPEN_POWER_TURBO_MODE_SUPPORTED>
+ (l_turboModeSupported))
+ {
+ HDAT::hdatGetNumberOfCores(l_numCores);
+
+ if(l_turboModeSupported == true)
+ {
+ this->iv_hdatIPLParams->iv_sysParms.hdatCurrentSPPLValue =
+ HDAT_TURBO_CORE_MODE_PART_SIZE_128;
+ }
+ else if( l_numCores == 6 )
+ {
+ this->iv_hdatIPLParams->iv_sysParms.hdatCurrentSPPLValue =
+ HDAT_NONTURBO_SIX_CORE_PART_SIZE_256;
+ }
+ else if( l_numCores == 8 )
+ {
+ this->iv_hdatIPLParams->iv_sysParms.hdatCurrentSPPLValue =
+ HDAT_NONTURBO_EIGHT_CORE_PART_SIZE_256;
+ }
+ }
+ else
+ {
+ HDAT_ERR("Error in getting OPEN_POWER_TURBO_MODE_SUPPORTED attribute");
+ }
+
+ this->iv_hdatIPLParams->iv_sysParms.usePoreSleep = 0x01;
+
+ TARGETING::ATTR_VTPM_ENABLED_type l_vTpmEnabled;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_VTPM_ENABLED>
+ (l_vTpmEnabled))
+ {
+ this->iv_hdatIPLParams->iv_sysParms.vTpmEnabled = l_vTpmEnabled;
+ }
+ else
+ {
+ HDAT_ERR("Error in getting VTPM_ENABLED attribute");
+ }
+
+ //HW Page Table Size : 0x07 : 1/128
+ this->iv_hdatIPLParams->iv_sysParms.hdatHwPageTbl = 0x07;
+
+ TARGETING::ATTR_HYP_DISPATCH_WHEEL_type l_hyperDispatchWheel;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_HYP_DISPATCH_WHEEL>
+ (l_hyperDispatchWheel))
+ {
+ if(!l_hyperDispatchWheel)
+ {
+ l_hyperDispatchWheel = 0x0a;
+ }
+ this->iv_hdatIPLParams->iv_sysParms.hdatDispWheel =
+ l_hyperDispatchWheel;
+ }
+ else
+ {
+ HDAT_ERR("Error in getting HYP_DISPATCH_WHEEL attribute");
+ }
+
+ TARGETING::ATTR_FREQ_PB_MHZ_type l_nestClockFreq;
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_FREQ_PB_MHZ>
+ (l_nestClockFreq))
+ {
+ this->iv_hdatIPLParams->iv_sysParms.hdatNestFreq =
+ static_cast<uint32_t>(l_nestClockFreq);
+ }
+ else
+ {
+ HDAT_ERR("Error in getting FREQ_PB_MHZ");
+ }
+
+ this->iv_hdatIPLParams->iv_sysParms.hdatSplitCoreMode = 1;
+
+ TARGETING::ATTR_SYSTEM_BRAND_NAME_type l_systemBrandName = {0};
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_SYSTEM_BRAND_NAME>
+ (l_systemBrandName))
+ {
+ strcpy(reinterpret_cast<char*>
+ (this->iv_hdatIPLParams->iv_sysParms.hdatSystemVendorName),
+ l_systemBrandName);
+ }
+ else
+ {
+ HDAT_ERR("Error in getting SYSTEM_BRAND_NAME");
+ }
+}
+
+/**
+ * @brief This routine gets the IPL Time Delta Structure
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_iplTime - output parameter - IPLTime Data
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+void hdatGetIPLTimeData(hdatIplTimeData_t & o_iplTime)
+{
+ //RTC and Delta values marked as invalid
+ o_iplTime.hdatRTCValidFlags = 0;
+
+ //Cumulative RTC Delta value is reset
+ o_iplTime.hdatCumulativeRTCDelta = 0;
+}
+
+
+/**
+ * @brief This routine gets the Manufacturing Flags
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_hdatManfFlags - output parameter - Manufacturing Flags
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+void hdatGetMnfgFlags(hdatManf_t &o_hdatManfFlags)
+{
+ o_hdatManfFlags.hdatPolicyFlags[0] = HDAT_MFG_FLAGS_CELL_0;
+ o_hdatManfFlags.hdatPolicyFlags[1] = HDAT_MFG_FLAGS_CELL_1;
+ o_hdatManfFlags.hdatPolicyFlags[2] = HDAT_MFG_FLAGS_CELL_2;
+ o_hdatManfFlags.hdatPolicyFlags[3] = HDAT_MFG_FLAGS_CELL_3;
+
+ if(HDAT::isMnfgFlagSet(TARGETING::MNFG_FLAG_AVP_ENABLE))
+ o_hdatManfFlags.hdatPolicyFlags[1] |= HDAT_MFG_FLAG_AVP_ENABLED;
+
+ if(HDAT::isMnfgFlagSet(TARGETING::MNFG_FLAG_HDAT_AVP_ENABLE))
+ o_hdatManfFlags.hdatPolicyFlags[2] |= HDAT_MFG_FLAG_HDAT_AVP_ENABLED;
+
+ if(HDAT::isMnfgFlagSet(TARGETING::MNFG_FLAG_SRC_TERM))
+ o_hdatManfFlags.hdatPolicyFlags[0] |= HDAT_MNFG_FLAG_SRC_TERM;
+
+ if(HDAT::isMnfgFlagSet(TARGETING::MNFG_FLAG_IPL_MEMORY_CE_CHECKING))
+ o_hdatManfFlags.hdatPolicyFlags[2] |=
+ HDAT_MNFG_IPL_MEM_CE_CHECKING_ACTIVE;
+
+ if(HDAT::isMnfgFlagSet(TARGETING::MNFG_FLAG_FAST_BACKGROUND_SCRUB))
+ o_hdatManfFlags.hdatPolicyFlags[1] |= HDAT_MNFG_FAST_BKG_SCRUB_ACTIVE;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_TEST_DRAM_REPAIRS))
+ o_hdatManfFlags.hdatPolicyFlags[0] |= HDAT_MNFG_TEST_DRAM_REPAIRS;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_DISABLE_DRAM_REPAIRS))
+ o_hdatManfFlags.hdatPolicyFlags[0] |= HDAT_MNFG_DISABLE_DRAM_REPAIRS;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_ENABLE_EXHAUSTIVE_PATTERN_TEST))
+ o_hdatManfFlags.hdatPolicyFlags[2] |=
+ HDAT_MNFG_ENABLE_EXHAUSTIVE_PATTERN_TEST;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_ENABLE_STANDARD_PATTERN_TEST))
+ o_hdatManfFlags.hdatPolicyFlags[2] |=
+ HDAT_MNFG_ENABLE_STANDARD_PATTERN_TEST;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_ENABLE_MINIMUM_PATTERN_TEST))
+ o_hdatManfFlags.hdatPolicyFlags[2] |= HDAT_MNFG_ENABLE_MIN_PATTERN_TEST;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_DISABLE_FABRIC_eREPAIR))
+ o_hdatManfFlags.hdatPolicyFlags[1] |= HDAT_MNFG_DISABLE_FABRIC_ERPAIR;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_DISABLE_MEMORY_eREPAIR))
+ o_hdatManfFlags.hdatPolicyFlags[1] |= HDAT_MNFG_DISABLE_MEMORY_ERPAIR;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_FABRIC_DEPLOY_LANE_SPARES))
+ o_hdatManfFlags.hdatPolicyFlags[2] |=
+ HDAT_MNFG_FABRIC_DEPLOY_LANE_SPARES;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_DMI_DEPLOY_LANE_SPARES))
+ o_hdatManfFlags.hdatPolicyFlags[2] |= HDAT_MNFG_DMI_DEPLOY_LANE_SPARES;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_PSI_DIAGNOSTIC))
+ o_hdatManfFlags.hdatPolicyFlags[1] |= HDAT_MNFG_PSI_DIAGNOSTIC;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_FSP_UPDATE_SBE_IMAGE))
+ o_hdatManfFlags.hdatPolicyFlags[1] |= HDAT_MNFG_FSP_UPDATE_SBE_IMAGE;
+
+ if(isMnfgFlagSet(TARGETING::MNFG_FLAG_UPDATE_BOTH_SIDES_OF_SBE))
+ o_hdatManfFlags.hdatPolicyFlags[1] |=
+ HDAT_MNFG_UPDATE_BOTH_SIDES_OF_SBE;
+
+}
+
+/**
+ * @brief This routine populates dump data table
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_hdatDump
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+void hdatGetPlatformDumpData(hdatDump_t &o_hdatDump)
+{
+
+ o_hdatDump.hdatReserved2 = 0;
+ o_hdatDump.hdatHypDumpPolicy = 0;
+ memset(o_hdatDump.hdatReserved3, 0 , sizeof(o_hdatDump.hdatReserved3));
+ o_hdatDump.hdatMaxHdwSize = 0;
+ o_hdatDump.hdatActHdwSize = 0;
+ o_hdatDump.hdatMaxSpSize = 0;
+
+ o_hdatDump.hdatFlags = 0;
+ o_hdatDump.hdatDumpId = 0;
+ o_hdatDump.hdatActPlatformDumpSize = 0;
+ o_hdatDump.hdatPlid = 0;
+
+}
+
+/**
+ * @brief This routine sets the Header information for IPL
+ * Parameters structure
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_iplparams - Output Parameter - IPL Parameter headers
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+static void hdatSetIPLParamsHdrs(hdatIPLParameters_t *o_iplparams)
+{
+
+ o_iplparams->hdatHdr.hdatStructId = HDAT_HDIF_STRUCT_ID;
+ o_iplparams->hdatHdr.hdatInstance = 0;
+ o_iplparams->hdatHdr.hdatVersion = HDAT_IPL_PARAMS_VERSION;
+ o_iplparams->hdatHdr.hdatSize = sizeof(hdatIPLParameters_t);
+ o_iplparams->hdatHdr.hdatHdrSize = sizeof(hdatHDIF_t);
+ o_iplparams->hdatHdr.hdatDataPtrOffset = sizeof(hdatHDIF_t);
+ o_iplparams->hdatHdr.hdatDataPtrCnt = HDAT_IPL_PARAMS_DA_CNT;
+ o_iplparams->hdatHdr.hdatChildStrCnt = 0;
+ o_iplparams->hdatHdr.hdatChildStrOffset = 0;
+
+ memcpy(o_iplparams->hdatHdr.hdatStructName, HDAT_IPLP_STRUCT_NAME,
+ sizeof(o_iplparams->hdatHdr.hdatStructName));
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_SYS_PARAMS].hdatOffset =
+ offsetof(hdatIPLParameters_t,iv_sysParms);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_SYS_PARAMS].hdatSize =
+ sizeof(hdatSysParms_t);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_IPL_PARAMS].hdatOffset =
+ offsetof(hdatIPLParameters_t,iv_iplParms);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_IPL_PARAMS].hdatSize =
+ sizeof(hdatIPLParams_t);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_TIME_DATA].hdatOffset =
+ offsetof(hdatIPLParameters_t,iv_iplTime);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_TIME_DATA].hdatSize =
+ sizeof(hdatIplTimeData_t);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_SPPL_PARAMS].hdatOffset =
+ offsetof(hdatIPLParameters_t,iv_pvt);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_SPPL_PARAMS].hdatSize =
+ sizeof(hdatIplSpPvt_t);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_PDUMP_DATA].hdatOffset =
+ offsetof(hdatIPLParameters_t, iv_dump);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_PDUMP_DATA].hdatSize =
+ sizeof(hdatDump_t);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_HMC_CONNS].hdatOffset =
+ offsetof(hdatIPLParameters_t, iv_hmc);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_HMC_CONNS].hdatSize =
+ sizeof(hdatHmc_t);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_CUOD_DATA].hdatOffset =
+ offsetof(hdatIPLParameters_t, iv_cuod);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_CUOD_DATA].hdatSize =
+ sizeof(hdatCuod_t);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_MFG_DATA].hdatOffset =
+ offsetof(hdatIPLParameters_t, iv_manf);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_MFG_DATA].hdatSize =
+ sizeof(hdatManf_t);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_SERIAL_PORTS].hdatOffset =
+ offsetof(hdatIPLParameters_t, iv_portArrayHdr);
+
+ o_iplparams->hdatIPLParamsIntData[HDAT_IPL_PARAMS_SERIAL_PORTS].hdatSize =
+ sizeof(hdatHDIFDataArray_t) + sizeof(hdatPortCodes_t);
+
+}
+
+/**
+ * @brief Constructor for IPL Parameters construction class
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_errlHndl - output parameter - Error Handlea
+ * i_msAddr - Mainstore address where IPL Params
+ * structure is loaded
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+HdatIplParms::HdatIplParms(errlHndl_t &o_errlHndl,
+ const HDAT::hdatMsAddr_t &i_msAddr)
+{
+ o_errlHndl = NULL;
+
+ // Copy the main store address for the pcia data
+ memcpy(&iv_msAddr, &i_msAddr, sizeof(hdatMsAddr_t));
+
+ uint64_t l_base_addr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo;
+
+ void *l_virt_addr = mm_block_map (
+ reinterpret_cast<void*>(ALIGN_PAGE_DOWN(l_base_addr)),
+ (ALIGN_PAGE(sizeof(hdatIPLParameters_t))+ PAGESIZE));
+
+ l_virt_addr = reinterpret_cast<void *>(
+ reinterpret_cast<uint64_t>(l_virt_addr) +
+ (l_base_addr - ALIGN_PAGE_DOWN(l_base_addr)));
+
+ // initializing the space to zero
+ memset(l_virt_addr ,0x0, sizeof(hdatIPLParameters_t));
+
+ iv_hdatIPLParams = reinterpret_cast<hdatIPLParameters_t *>(l_virt_addr);
+
+ HDAT_DBG("Ctr iv_hdatIPLParams addr 0x%016llX virtual addr 0x%016llX",
+ (uint64_t) this->iv_hdatIPLParams, (uint64_t)l_virt_addr);
+
+}
+
+/**
+ * @brief Load IPL Paramsters to Mainstore
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_size - output parameter - Size of IPL Parameters structure
+ * o_count - output parameter - Number of IPL Parameters structures
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+errlHndl_t HdatIplParms::hdatLoadIplParams(uint32_t &o_size, uint32_t &o_count)
+{
+ errlHndl_t l_errl = NULL;
+
+ //Set IPLParams Headers
+ hdatSetIPLParamsHdrs(this->iv_hdatIPLParams);
+
+ //Get the FSP private IPL type
+ TARGETING::Target *l_pSysTarget = NULL;
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSysTarget);
+
+ if(l_pSysTarget == NULL)
+ {
+ HDAT_ERR("Error in getting Top Level target");
+ assert(l_pSysTarget != NULL);
+ }
+
+ //Initializing SP IPL Type to Power On Reset
+ this->iv_hdatIPLParams->iv_pvt.hdatIplType = 0x00000801;
+
+ // Get the IPL parameters data
+ hdatGetIplParmsData();
+
+ // Get the IPL time data
+ hdatGetIPLTimeData(this->iv_hdatIPLParams->iv_iplTime);
+
+ // Get the System Parameters
+ hdatGetSystemParamters();
+
+ // Get HMC information
+ memset(&this->iv_hdatIPLParams->iv_hmc, 0x00,
+ sizeof(this->iv_hdatIPLParams->iv_hmc));
+
+ // Get dump information
+ hdatGetPlatformDumpData(this->iv_hdatIPLParams->iv_dump);
+
+ // Get CUOD information
+ this->iv_hdatIPLParams->iv_cuod.hdatCuodFlags = HDAT_POWER_OFF;
+
+ // Get manufacturing mode information
+ memset(&this->iv_hdatIPLParams->iv_manf, 0x00, sizeof(hdatManf_t));
+ hdatGetMnfgFlags(this->iv_hdatIPLParams->iv_manf);
+
+ // Get serial port information
+ memset(&this->iv_hdatIPLParams->iv_portArrayHdr, 0x00,
+ sizeof(HDAT::hdatHDIFDataArray_t));
+ memset(this->iv_hdatIPLParams->iv_ports, 0x00, sizeof(hdatPortCodes_t) * 2);
+ hdatGetPortInfo(this->iv_hdatIPLParams->iv_portArrayHdr,
+ this->iv_hdatIPLParams->iv_ports);
+
+ HDAT_DBG("HDAT:: IPL Parameters Loaded :: Size : 0x%X",
+ sizeof(hdatIPLParameters_t));
+
+ o_count = 1;
+ o_size = sizeof(hdatIPLParameters_t);
+
+ return l_errl;
+}
+
+/**
+ * @brief Destructor for IPL Parameters construction class
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+HdatIplParms::~HdatIplParms()
+{
+ int rc = 0;
+ rc = mm_block_unmap(iv_hdatIPLParams);
+ if( rc != 0)
+ {
+ errlHndl_t l_errl = NULL;
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_IPLPARMS_DESTRUCTOR
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCIA_DESTRUCTOR,
+ RC_DEV_MAP_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+
+ return;
+}
+};
diff --git a/src/usr/hdat/hdatiplparms.H b/src/usr/hdat/hdatiplparms.H
new file mode 100755
index 000000000..85729fb54
--- /dev/null
+++ b/src/usr/hdat/hdatiplparms.H
@@ -0,0 +1,475 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatiplparms.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATIPLPARMS_H
+#define HDATIPLPARMS_H
+
+/**
+ * @file hdatiplparms.H
+ *
+ * @brief This file contains the class definition for the IPL parms object
+ * constructed with data obtained from the registry and iplp component.
+ *
+ */
+
+// Change Log *****************************************************************/
+//
+// End Change Log *************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <stdint.h> // standard types
+#include <errl/errlentry.H>
+#include <hdat/hdat_reasoncodes.H>
+#include "hdatutil.H"
+#include <hdat/hdat.H>
+
+namespace HDAT
+{
+
+/*----------------------------------------------------------------------------*/
+/* Typedefs */
+/*----------------------------------------------------------------------------*/
+
+const uint16_t HDAT_IPL_PARAMS_VERSION = 0x5F;
+const char HDAT_IPLP_STRUCT_NAME[7] = "IPLPMS";
+
+
+
+/** @enum hdatDataPtrs
+ * Constants for the internal data pointers that are added to the base
+ * class
+ */
+enum hdatIplDataPtrs
+{
+ HDAT_IPL_SYS = 0,
+ HDAT_IPL_PARMS = 1,
+ HDAT_IPL_TIME = 2,
+ HDAT_IPL_PVT = 3,
+ HDAT_IPL_DUMP = 4,
+ HDAT_IPL_HMC = 5,
+ HDAT_IPL_CUOD = 6,
+ HDAT_IPL_MANF = 7,
+ HDAT_IPL_PORT_CODES = 8,
+ HDAT_IPL_LAST = 9
+};
+
+/** @brief Structure definition for system model and feature code
+ */
+struct hdatSysParms_t
+{
+ uint32_t hdatSysModel;
+ uint32_t hdatProcFeatCode;
+ uint32_t hdatEffectivePvr;
+ uint32_t hdatSysType;
+ uint8_t hdatReserved3[8]; // Reserved
+ uint32_t hdatABCBusSpeed; // Speed in MHz
+ uint32_t hdatWXYZBusSpeed; // Speed in MHz
+ uint32_t hdatSystemECOMode; // System ECO Mode set by the user
+ uint32_t hdatSystemAttributes; // System supports multiple TPMDs
+ uint32_t hdatMemoryScrubbing; // Memory Scrubbing
+ uint16_t hdatCurrentSPPLValue; // The Current SPPL Value
+ uint8_t hdatReserved2; // Reserved
+ uint8_t usePoreSleep; // Use PORE Sleep
+ uint32_t hdatReserved1; // Reserved
+ uint8_t vTpmEnabled; // vTPM Enabled
+ uint8_t hdatHwPageTbl; // Hardware Page Table
+ uint16_t hdatDispWheel; // Hypervisor Dispatch Wheel
+ uint32_t hdatNestFreq; // Nest Clock Frequency in MHz
+ uint8_t hdatSplitCoreMode; // Split Core Mode
+ uint8_t hdatReserved4; // Reserved
+ uint16_t hdatReserved5; // Reserved
+ uint8_t hdatSystemVendorName[64]; // System Vendor Name
+} __attribute__ ((packed));
+
+/** @brief Structure definition for Other IPL Attributes within hdatIPLParams_t
+ * */
+struct hdatOtherIPLAttributes_t
+{
+ uint32_t hdatReserved1 : 1; // Reserved
+ uint32_t hdatCreDefPartition : 1; // Create Default Parititon
+ uint32_t hdatCTAState : 1; // Click To Accept State
+ uint32_t hdatDisVirtIOConn : 1; // Disable Virtual IO Connectivity
+ uint32_t hdatResetPCINOs : 1; // Reset PCI Numbers
+ uint32_t hdatClrPhypNvram : 1; // Clear PHYP NVRAM
+ uint32_t hdatMDCLogPartVPD : 1; // Preserve MDC Logical Paritition VPD
+ uint32_t hdatCECCMCapable : 1; // CEC Concurrent Maintanance Capable
+ uint32_t hdati5OSEnable : 1; // i5/OS enable
+ uint32_t hdatSELFlagsValid : 1; // SEL Flags Valid
+ uint32_t hdatDelSELFromHyp : 1; // Delete SELs originated from PHYP/OPAL
+ uint32_t hdatDelSELFromHB : 1; // Delete SELs originated from Hostboot
+ uint32_t hdatDelSELFromBMC : 1; // Delete SELs originated from BMC
+ uint32_t hdatReserved2 : 15; // Reserved
+ uint32_t hdatServiceIndMode : 2; // Platform Service Indicator Mode
+ uint32_t hdatDefPartitionType : 2; // Default Partition Type
+}__attribute__ ((packed));
+
+/** @brief Structure definition for IPL Parameters
+ * */
+struct hdatIPLParams_t
+{
+ uint8_t hdatReserved1; // Reserved
+ uint8_t hdatIPLDestination; // Hypervisor IPL Destination
+ uint8_t hdatIPLSide; // Platform IPL Side
+ uint8_t hdatIPLSpeed; // Platform IPL Speed for Current IPL
+ uint16_t hdatCECIPLAttributes; // CEC IPL Attributes
+ uint8_t hdatIPLMajorType; // CEC IPL Major Type
+ uint8_t hdatIPLMinorType; // CEC IPL Minor Type
+ uint8_t hdatOSIPLMode; // Operating System IPL Mode
+ uint8_t hdatKeyLockPosition; // Key Lock Position
+ uint8_t hdatLMBSize; // Logical Memory Block Size
+ uint8_t hdatReserved2; // Reserved
+ uint32_t hdatMaxHSLConns; // Max number of HSL Opticonnect
+ // connections
+ hdatOtherIPLAttributes_t hdatOIA; // Other IPL Attributes
+ uint16_t hdatHugePageMemCount; // Huge Page Memory Count
+ uint8_t hdatHugePageMemSize; // Huge Page Memory Size
+ uint8_t hdatNumVlanSwitches; // Number of VLAN Switches
+ uint32_t hdatReserved3; // Reserved
+ uint32_t hdatEnlargedIOCap; // Enlarged IO Capacity
+}__attribute__ ((packed));
+
+
+/** @brief Structure definition for IPL Time Data
+ * */
+struct hdatIplTimeData_t
+{
+ uint32_t hdatReserved1; // Reserved
+ uint32_t hdatReserved2; // Reserved
+ uint32_t hdatReserved3; // Reserved
+ union {uint32_t hdatRTCValidFlags; // Real Time Clock and Delta Valid Flags
+ uint32_t hdatReserved4 :27,
+ hdatFSPTimeRef : 1,
+ hdatHYPSetTOD : 1,
+ hdatReserved5 : 1,
+ hdatCumRTCDeltaValid : 1,
+ hdatIPLStartRTCValid : 1;};
+ uint64_t hdatCumulativeRTCDelta; // Cumulative RTC Delta
+ uint32_t hdatReserved6; // Reserved
+ uint32_t hdatReserved7; // Reserved
+} __attribute__ ((packed));
+
+/** @brief Structure definition for service processor private IPL type
+ */
+struct hdatIplSpPvt_t
+{
+ uint32_t hdatIplType;
+} __attribute__ ((packed));
+
+
+/** @brief Structure definition for dump information
+ */
+struct hdatDump_t
+{
+ union {uint16_t hdatFlags; // word view unioned with bit view
+ uint16_t hdatRptPending : 1, // 1 = A dump exists and is
+ // waiting to be extracted
+ hdatHdwDumpExists : 1, // 1 = Hardware dump exists
+ hdatMemDumpExists : 1, // 1 = Memory dump exists
+ hdatHdwDumpErrs : 1, // 1 = Errors occurred during
+ // hardware dump collection
+ hdatMemDumpErrs : 1, // 1 = Errors occurred during
+ // memory dump collection
+ hdatHdwDumpReq : 1, // 1 = Hardware dump requested
+ hdatMemDumpReq : 1, // 1 = Memory dump requested
+ hdatUserReq : 1, // 1 = User requested the dump
+ hdatErrReq : 1, // 1 = Hardware or software
+ // error caused the dump
+ hdatReserved1 : 7;}; // Reserved for future use
+ uint8_t hdatReserved2;
+ uint8_t hdatHypDumpPolicy;
+ uint32_t hdatDumpId;
+ uint8_t hdatReserved3[8];
+ uint64_t hdatActPlatformDumpSize;
+ uint32_t hdatMaxHdwSize;
+ uint32_t hdatActHdwSize;
+ uint32_t hdatMaxSpSize;
+ uint32_t hdatPlid;
+} __attribute__ ((packed));
+
+
+/** @brief Structure definition for hardware management console information
+ */
+struct hdatHmc_t
+{
+ uint8_t hdatHmcFlags;
+ uint8_t hdatReserved1[3];
+} __attribute__ ((packed));
+
+const uint8_t HDAT_HMC_MANAGED = 0x80;
+
+
+/** @brief Structure definition for capacity upgrade on demand information
+ */
+struct hdatCuod_t
+{
+ uint8_t hdatCuodFlags;
+ uint8_t hdatReserved1[3];
+} __attribute__ ((packed));
+
+
+const uint32_t HDAT_POWER_LOST = 0x80;
+const uint32_t HDAT_POWER_OFF = 0x40;
+
+
+const uint32_t HDAT_MNFG_MAX_CELLS = 0x04;
+
+/** @brief Structure definition for manufacturing mode information
+ */
+struct hdatManf_t
+{
+ uint32_t hdatPolicyFlags[HDAT_MNFG_MAX_CELLS]; // 4 cells of mfg mode data
+} __attribute__ ((packed));
+
+
+/** @brief Structure definition for SP serial port information
+ */
+const uint32_t hdatMaxPorts = 2; // maximum number of serial ports
+
+struct hdatPortCodes_t
+{
+ char hdatLocCode[80]; // serial port location code
+ uint16_t hdatResourceId; // serial port resource id
+ uint16_t hdatCallHome : 1, // 1 = designated as the "Call Home" port
+ hdatReserved1 : 15;// Reserved for future use
+} __attribute__ ((packed));
+
+
+#define HDAT_CHIP_TYPE_MURANO "MURANO"
+#define HDAT_CHIP_TYPE_VENICE "VENICE"
+#define HDAT_CHIP_TYPE_NIMBUS "NIMBUS"
+#define HDAT_CHIP_TYPE_CUMULUS "CUMULUS"
+
+#define HDAT_SYSTEM_TYPE_BASE_FIRENZE 0x30000000
+#define HDAT_SYSTEM_TYPE_PLUS_FIRENZE 0x30000001
+#define HDAT_SYSTEM_TYPE_MISC_OPENPOWER 0x00150000
+
+#define HDAT_FIRMWARE_SIDE_GOLDEN 0x00
+#define HDAT_FIRMWARE_SIDE_WORKING 0x22
+
+#define HDAT_KEYLOCK_MANUAL 0x02
+#define HDAT_KEYLOCK_NORMAL 0x04
+
+#define HDAT_MULT_TPMDS 0x80000000
+#define HDAT_SMM_ENABLED 0x40000000
+#define HDAT_CRYPTO_DISABLED_BIT 0x20000000
+
+#define HDAT_ECO_ENABLED 0x80000000
+#define HDAT_ECO_CAPABLE 0x40000000
+
+#define HDAT_TURBO_CORE_MODE_PART_SIZE_128 0x0080
+#define HDAT_NONTURBO_EIGHT_CORE_PART_SIZE_32 0x0020
+#define HDAT_NONTURBO_EIGHT_CORE_PART_SIZE_256 0x8020
+#define HDAT_NONTURBO_SIX_CORE_PART_SIZE_24 0x0018
+#define HDAT_NONTURBO_SIX_CORE_PART_SIZE_256 0x8018
+
+
+#define HDAT_MFG_FLAGS_CELL_0 0x00000000
+#define HDAT_MFG_FLAGS_CELL_1 0x00020000
+#define HDAT_MFG_FLAGS_CELL_2 0x00040000
+#define HDAT_MFG_FLAGS_CELL_3 0x00080000
+
+#define HDAT_MFG_FLAG_AVP_ENABLED 0x00000100
+#define HDAT_MFG_FLAG_HDAT_AVP_ENABLED 0x00000010
+#define HDAT_MNFG_FLAG_SRC_TERM 0x00000200
+#define HDAT_MNFG_IPL_MEM_CE_CHECKING_ACTIVE 0x00000008
+#define HDAT_MNFG_FAST_BKG_SCRUB_ACTIVE 0x00000080
+#define HDAT_MNFG_TEST_DRAM_REPAIRS 0x00000200
+#define HDAT_MNFG_DISABLE_DRAM_REPAIRS 0x00000008
+#define HDAT_MNFG_ENABLE_EXHAUSTIVE_PATTERN_TEST 0x00000001
+#define HDAT_MNFG_ENABLE_STANDARD_PATTERN_TEST 0x00000002
+#define HDAT_MNFG_ENABLE_MIN_PATTERN_TEST 0x00000004
+#define HDAT_MNFG_DISABLE_FABRIC_ERPAIR 0x00000010
+#define HDAT_MNFG_DISABLE_MEMORY_ERPAIR 0x00000020
+#define HDAT_MNFG_FABRIC_DEPLOY_LANE_SPARES 0x00000200
+#define HDAT_MNFG_DMI_DEPLOY_LANE_SPARES 0x00000100
+#define HDAT_MNFG_PSI_DIAGNOSTIC 0x00000001
+#define HDAT_MNFG_FSP_UPDATE_SBE_IMAGE 0x00000004
+#define HDAT_MNFG_UPDATE_BOTH_SIDES_OF_SBE 0x00000008
+
+enum hdatIPLParamsDataPtrs
+{
+ HDAT_IPL_PARAMS_SYS_PARAMS = 0,
+ HDAT_IPL_PARAMS_IPL_PARAMS = 1,
+ HDAT_IPL_PARAMS_TIME_DATA = 2,
+ HDAT_IPL_PARAMS_SPPL_PARAMS = 3,
+ HDAT_IPL_PARAMS_PDUMP_DATA = 4,
+ HDAT_IPL_PARAMS_HMC_CONNS = 5,
+ HDAT_IPL_PARAMS_CUOD_DATA = 6,
+ HDAT_IPL_PARAMS_MFG_DATA = 7,
+ HDAT_IPL_PARAMS_SERIAL_PORTS = 8,
+ HDAT_IPL_PARAMS_DA_CNT = 9,
+ HDAT_IPL_PARAMS_DA_LAST = 10
+};
+
+struct hdatIPLParameters_t{
+ /** Object Instance Data
+ *
+ * @li iv_sysParms - system model/feature code
+ * @li iv_iplParms - IPL parameter information
+ * @li iv_iplTime - IPL time information
+ * @li iv_pvt - SP private IPL information
+ * @li iv_dump - dump information
+ * @li iv_hmc - hardware management console information
+ * @li iv_cuod - Capacity upgrade on demand information
+ * @li iv_manf - manufacturing flags
+ * @li iv_portArrayHdr - serial port array header
+ * @li iv_ports - serial port location codes and resource ids
+ */
+ hdatHDIF_t hdatHdr;
+ hdatHDIFDataHdr_t hdatIPLParamsIntData[HDAT_IPL_PARAMS_DA_LAST];
+ hdatSysParms_t iv_sysParms;
+ hdatIPLParams_t iv_iplParms;
+ hdatIplTimeData_t iv_iplTime;
+ hdatIplSpPvt_t iv_pvt;
+ hdatDump_t iv_dump;
+ hdatHmc_t iv_hmc;
+ hdatCuod_t iv_cuod;
+ hdatManf_t iv_manf;
+ hdatHDIFDataArray_t iv_portArrayHdr;
+ hdatPortCodes_t iv_ports[hdatMaxPorts];
+};
+
+/*----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatIplParms class is used to construct the IPL Parameters
+ * hypervisor data area.
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that any component can create an object of this type.
+ * In particular, the object is built only by the hdat component.
+ *
+ * The real purpose of the object is to create the IPL parameters
+ * data structure as defined by the PHYP Initialization
+ * architecture. This data structure is eventually copied to
+ * main memory. The class is not defined to be a general purpose
+ * interface for building this object by anyone other than the
+ * hdat process.
+ *
+ * Thread safety: An HdatIplParms object is not thread safe. That is, a
+ * single object cannot be shared and used concurrently by
+ * multiple threads at the same time. An object can be used by
+ * multiple threads if the threads serialize access. And of
+ * course, each thread can use its own object with no concerns
+ * about what other threads are doing.
+ *
+ * Signal handler usage: This class is not intended to be used in a signal
+ * handler and nothing has been done to try and make
+ * it safe to use in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatIplParms
+{
+ public:
+
+/*
+ * @brief Construct an HdatIplParms object.
+ *
+ * This is the constructor for the HdatIplParms object.
+ *
+ * If you are constructing this object on the heap by using new,
+ * then you must check the pointer returned from new to see if
+ * it is null.
+ * If it is null, new failed to allocate storage and the
+ * constructor was not called. If it is not null, then you must
+ * check o_errlHndl to see if the constructor ran successfully.
+ * If o_errlHndl indicates an error was reported by the
+ * constructor, new has already allocated heap storage and the
+ * object must be deleted in order to free the heap storage.
+ *
+ * @pre None
+ *
+ * @post An HdatIplParms object has been constructed.
+ * Heap storage has been allocated.
+ *
+ * @param o_errlHndl - output parameter - If any errors occur, the
+ * HdatIplParms object is NOT
+ * constructed and errors are
+ * returned in this parameter
+ * @param i_msAddr - input parameter - The main memory address that
+ * the service processor subsystem
+ * structure will be DMA'd to.
+ *
+ * @return A null error log handle if successful, else the return
+ * code pointed to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_REGISTRY_ERROR
+ */
+ HdatIplParms(errlHndl_t &o_errlHndl,
+ const HDAT::hdatMsAddr_t &i_msAddr);
+
+
+ /**
+ * @brief HdatIplParms object destructor
+ *
+ * This is the destructor for an HdatIplParms object.
+ * Any heap storage allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatIplParms object has been destroyed and can
+ * no longer be used.
+ *
+ */
+ ~HdatIplParms();
+
+ /**
+ * @brief Load IPL Paramsters to Mainstore
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_size - output parameter - Size of IPL Parameters structure
+ * o_count - output parameter - Number of IPL Parameters
+ * structures
+ *
+ * @return None
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+
+ errlHndl_t hdatLoadIplParams(uint32_t &o_size,uint32_t &o_count);
+ private:
+
+ void hdatGetSystemParamters(void);
+
+ void hdatGetIplParmsData(void);
+
+ HDAT::hdatMsAddr_t iv_msAddr;
+
+ hdatIPLParameters_t *iv_hdatIPLParams;
+
+
+}; // end of HdatIplParms class
+
+}
+#endif // HDATIPLPARMS_H
diff --git a/src/usr/hdat/hdatmsarea.C b/src/usr/hdat/hdatmsarea.C
new file mode 100755
index 000000000..f2031c08d
--- /dev/null
+++ b/src/usr/hdat/hdatmsarea.C
@@ -0,0 +1,720 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatmsarea.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+/**
+ * @file hdatmsarea.C
+ *
+ * @brief This file contains the implementation of the HdatMsArea class.
+ *
+ */
+
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <stdlib.h> // malloc & free
+#include <hdat/hdat.H> // debug compile control variables
+#include "hdatmsarea.H" // HdatMsArea class definition
+#include "hdatutil.H" // utility functions
+#include "hdatmsvpd.H"
+
+#include <stdio.h>
+
+namespace HDAT
+{
+/*----------------------------------------------------------------------------*/
+/* Global variables */
+/*----------------------------------------------------------------------------*/
+uint32_t HdatMsArea::cv_actualCnt;
+
+static vpdData cvpdData[] =
+{
+// { CVPD::VINI, CVPD::RT },
+ { CVPD::VINI, CVPD::DR },
+ { CVPD::VINI, CVPD::FN },
+ { CVPD::VINI, CVPD::PN },
+ { CVPD::VINI, CVPD::SN },
+ { CVPD::VINI, CVPD::CC },
+// { CVPD::VINI, CVPD::PR },
+ //{ CVPD::VINI, CVPD::SZ },
+ { CVPD::VINI, CVPD::HE },
+ { CVPD::VINI, CVPD::CT },
+ { CVPD::VINI, CVPD::HW },
+ // { CVPD::VINI, CVPD::B3 },
+ // { CVPD::VINI, CVPD::B4 },
+ // { CVPD::VINI, CVPD::B7 },
+ { CVPD::VINI, CVPD::PF },
+};
+
+const HdatKeywordInfo l_cvpdKeywords[] =
+{
+ { CVPD::DR, "DR" },
+ { CVPD::FN, "FN" },
+ { CVPD::PN, "PN" },
+ { CVPD::SN, "SN" },
+ { CVPD::CC, "CC" },
+ { CVPD::HE, "HE" },
+ { CVPD::CT, "CT" },
+ { CVPD::HW, "HW" },
+ { CVPD::PF, "PF" },
+};
+
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+HdatMsArea::HdatMsArea(errlHndl_t &o_errlHndl,
+ TARGETING::Target * i_target,
+ uint16_t i_msAreaId,
+ uint32_t i_ramCnt,
+ uint32_t i_chipEcCnt,
+ uint32_t i_addrRngCnt,
+ uint32_t i_resourceId,
+ uint32_t i_slcaIdx,
+ uint32_t i_kwdSize,
+ char *&i_kwd)
+
+: HdatHdif(o_errlHndl,HDAT_MSAREA_STRUCT_NAME,HDAT_MS_AREA_LAST,cv_actualCnt++,
+ HDAT_MS_AREA_CHILD_LAST,HDAT_MS_AREA_VERSION),
+ iv_kwdSize(i_kwdSize),
+ iv_maxAddrRngCnt(HDAT_MAX_ADDR_RNG_ENTRIES), iv_maxEcCnt(HDAT_MAX_EC_ENTRIES),
+ iv_maxRamCnt(i_ramCnt), iv_actRamCnt(0), iv_maxRamObjSize(0), iv_kwd(NULL),
+ iv_ramPadReq(false),iv_addrRange(NULL), iv_ecLvl(NULL), iv_ramPtrs(NULL)
+{
+ HDAT_ENTER( );
+
+ uint32_t l_slcaIdx = 0;
+
+ o_errlHndl = NULL;
+ iv_fru.hdatResourceId = i_resourceId;
+
+ memset(&iv_msId, 0x00, sizeof(hdatMsAreaId_t));
+ memset(&iv_msSize, 0x00, sizeof(hdatMsAreaSize_t));
+ memset(&iv_aff, 0x00, sizeof(hdatMsAreaAffinity_t));
+
+ iv_msId.hdatMsAreaId = i_msAreaId;
+
+ iv_addrRngArrayHdr.hdatOffset = sizeof(hdatHDIFDataArray_t);
+ iv_addrRngArrayHdr.hdatArrayCnt = 0;
+ iv_addrRngArrayHdr.hdatAllocSize = sizeof(hdatMsAreaAddrRange_t);
+ iv_addrRngArrayHdr.hdatActSize = sizeof(hdatMsAreaAddrRange_t);
+
+ iv_ecArrayHdr.hdatOffset = sizeof(hdatHDIFDataArray_t);
+ iv_ecArrayHdr.hdatArrayCnt = 0;
+ iv_ecArrayHdr.hdatAllocSize = sizeof(hdatMsAreaEcLvl_t);
+ iv_ecArrayHdr.hdatActSize = sizeof(hdatMsAreaEcLvl_t);
+ l_slcaIdx = i_slcaIdx;
+
+
+ // If the ASCII keyword data and related info has been passed to us as a
+ // parm, use it and avoid calling into svpd. This is an IPL performance
+ // improvement since all mainstore areas for an MCM will have the same
+ // resource id and thus the same keyword VPD.
+ if (i_kwdSize > 0)
+ {
+ l_slcaIdx = i_slcaIdx;
+ iv_kwd = new char[i_kwdSize];
+ memcpy(iv_kwd, i_kwd, i_kwdSize);
+ }
+ else
+ {
+ // Get the SLCA index and ASCII keyword for this resource id
+ uint32_t l_num = sizeof(cvpdData)/sizeof(cvpdData[0]);
+ size_t theSize[l_num];
+ hdatGetAsciiKwdForMvpd(i_target,iv_kwdSize,iv_kwd,cvpdData,
+ l_num,theSize);
+ do
+ {
+ char *o_fmtKwd;
+ uint32_t o_fmtkwdSize;
+ o_errlHndl = hdatformatAsciiKwd(cvpdData , l_num , theSize, iv_kwd,
+ iv_kwdSize, o_fmtKwd, o_fmtkwdSize, l_cvpdKeywords);
+ if( o_fmtKwd != NULL )
+ {
+ delete[] iv_kwd;
+ //padding extra 8 bytes to keep data sync as FSP
+ iv_kwd = new char [o_fmtkwdSize + 8];
+ memcpy(iv_kwd,o_fmtKwd,o_fmtkwdSize);
+ iv_kwdSize = o_fmtkwdSize + 8;
+ delete[] o_fmtKwd;
+ }
+ }while(0);
+ }
+
+ // Allocate space for the address range array
+ if (NULL == o_errlHndl)
+ {
+ iv_addrRange = new hdatMsAreaAddrRange_t[iv_maxAddrRngCnt];
+ memset(iv_addrRange,0,
+ (sizeof(hdatMsAreaAddrRange_t) * iv_maxAddrRngCnt));
+ }
+
+ // Allocate space for the EC level array
+ if (NULL == o_errlHndl)
+ {
+ iv_fru.hdatSlcaIdx = l_slcaIdx;
+ iv_ecLvl = new hdatMsAreaEcLvl_t[iv_maxEcCnt];
+ }
+ // Allocate space for the RAM entries
+ if (NULL == o_errlHndl)
+ {
+ iv_ramPtrs = new HdatRam*[i_ramCnt];
+ }
+
+ HDAT_EXIT();
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+HdatMsArea::~HdatMsArea()
+{
+ HDAT_ENTER( );
+
+ uint32_t l_cnt;
+ HdatRam *l_ramObj, **l_curPtr;
+
+ // Delete RAM Objects
+ l_curPtr = iv_ramPtrs;
+ for (l_cnt = 0; l_cnt < iv_actRamCnt; l_cnt++)
+ {
+ l_ramObj = *l_curPtr;
+ delete l_ramObj;
+ l_curPtr = reinterpret_cast<HdatRam **>(reinterpret_cast<char*>(l_curPtr)
+ + sizeof(HdatRam *));
+ }
+
+ delete[] iv_kwd;
+ delete[] iv_addrRange;
+ delete[] iv_ecLvl;
+ delete [] iv_ramPtrs;
+
+ HDAT_EXIT();
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::setParentType(uint16_t i_type)
+{
+ iv_msId.hdatMsAreaParentType = i_type;
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::setStatus(uint16_t i_status)
+{
+ iv_msId.hdatMsAreaStatus = i_status;
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::setInterleavedId(uint16_t i_id)
+{
+ iv_msId.hdatInterleavedId = i_id;
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::setSize(uint32_t i_size)
+{
+ iv_msSize.hdatReserved1 = 0;
+ iv_msSize.hdatMsAreaSize = i_size;
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::setModuleId(uint32_t i_moduleId)
+{
+ iv_aff.hdatMsAreaModuleId = i_moduleId;
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::setAffinityDomain(uint32_t i_affinityDomain)
+{
+ iv_aff.hdatMsAffinityDomain = i_affinityDomain;
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::getKwdInfo(uint32_t &o_resourceId,
+ uint32_t &o_slcaIdx,
+ uint32_t &o_kwdSize,
+ char *&o_kwd)
+{
+ o_resourceId = iv_fru.hdatResourceId;
+ o_slcaIdx = iv_fru.hdatSlcaIdx;
+ o_kwdSize = iv_kwdSize;
+ o_kwd = iv_kwd;
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+errlHndl_t HdatMsArea::addAddrRange(hdatMsAddr_t &i_start,
+ hdatMsAddr_t &i_end,
+ uint32_t i_procChipId,
+ bool i_rangeIsMirrorable,
+ uint8_t i_mirroringAlgorithm,
+ hdatMsAddr_t &i_startMirrAddr)
+{
+ HDAT_ENTER();
+ errlHndl_t l_errlHndl = NULL;
+ hdatMsAreaAddrRange_t *l_addr;
+
+ if (iv_addrRngArrayHdr.hdatArrayCnt < iv_maxAddrRngCnt)
+ {
+ l_addr = reinterpret_cast<hdatMsAreaAddrRange_t*>(
+ reinterpret_cast<char*>(iv_addrRange) + iv_addrRngArrayHdr.hdatArrayCnt*
+ sizeof(hdatMsAreaAddrRange_t));
+
+ l_addr->hdatMsAreaStrAddr = i_start;
+ l_addr->hdatMsAreaEndAddr = i_end;
+ l_addr->hatMsAreaProcChipId = i_procChipId;
+ l_addr->hdatSMMAttributes.hdatRangeIsMirrorable =
+ i_rangeIsMirrorable ? 1 : 0;
+ l_addr->hdatSMMAttributes.hdatMirroringAlgorithm = i_mirroringAlgorithm;
+ l_addr->hdatStartMirrAddr = i_startMirrAddr;
+ iv_addrRngArrayHdr.hdatArrayCnt++;
+ }
+ else
+ {
+ /*@
+ * @errortype
+ * @refcode LIC_REFCODE
+ * @subsys EPUB_FIRMWARE_SP
+ * @reasoncode RC_ERC_MAX_EXCEEDED
+ * @moduleid MOD_ADD_ADDR_RANGE
+ * @userdata1 current number of array entries
+ * @userdata2 maximum number of array entries
+ * @userdata3 ID number of mainstore area
+ * @userdata4 none
+ * @devdesc Failed trying to add another entry to a mainstore area
+ * address range array
+ */
+ hdatBldErrLog(l_errlHndl,
+ MOD_ADD_ADDR_RANGE, // SRC module ID
+ RC_ERC_MAX_EXCEEDED, // SRC extended reference code
+ iv_addrRngArrayHdr.hdatArrayCnt, // SRC hex word 1
+ iv_maxAddrRngCnt, // SRC hex word 2
+ iv_msId.hdatMsAreaId); // SRC hex word 3
+ }
+ HDAT_EXIT();
+ return l_errlHndl;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+errlHndl_t HdatMsArea::addEcEntry(uint32_t i_manfId,
+ uint32_t i_ecLvl)
+{
+ HDAT_ENTER();
+ errlHndl_t l_errlHndl = NULL;
+ hdatMsAreaEcLvl_t *l_ec;
+
+
+ if (iv_ecArrayHdr.hdatArrayCnt < iv_maxEcCnt)
+ {
+ l_ec = reinterpret_cast<hdatMsAreaEcLvl_t*>(reinterpret_cast<char*>
+ (iv_ecLvl) + iv_ecArrayHdr.hdatArrayCnt * sizeof(hdatMsAreaEcLvl_t));
+ l_ec->hdatChipManfId = i_manfId;
+ l_ec->hdatChipEcLvl = i_ecLvl;
+ iv_ecArrayHdr.hdatArrayCnt++;
+ }
+
+ HDAT_EXIT();
+ return l_errlHndl;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+errlHndl_t HdatMsArea::addRam(HdatRam &i_ram)
+{
+ HDAT_ENTER();
+ errlHndl_t l_errlHndl = NULL;
+ HdatRam **l_arrayEntry;
+ uint32_t l_ramSize;
+
+ if (iv_actRamCnt < iv_maxRamCnt)
+ {
+ l_arrayEntry = reinterpret_cast<HdatRam**>(reinterpret_cast<char*>
+ (iv_ramPtrs) + iv_actRamCnt * sizeof(HdatRam *));
+
+ *l_arrayEntry = &i_ram;
+
+ //Determine if the size of this RAM is larger than any other RAM objects
+ // associated with this mainstore area
+ l_ramSize = i_ram.size();
+ if (l_ramSize != iv_maxRamObjSize)
+ {
+ // If not the first RAM object, then we have to pad some shorter
+ // RAM object(s)
+ if (iv_maxRamObjSize != 0)
+ {
+ iv_ramPadReq = true;
+ }
+ if (l_ramSize > iv_maxRamObjSize)
+ {
+ iv_maxRamObjSize = l_ramSize;
+ }
+ }
+
+ iv_actRamCnt++;
+ }
+ else
+ {
+ /*@
+ * @errortype
+ * @refcode LIC_REFCODE
+ * @subsys EPUB_FIRMWARE_SP
+ * @reasoncode RC_ERC_MAX_EXCEEDED
+ * @moduleid MOD_ADD_RAM
+ * @userdata1 current number of array entries
+ * @userdata2 maximum number of array entries
+ * @userdata3 ID number of mainstore area
+ * @userdata4 none
+ * @devdesc Failed trying to add another entry to a mainstore area
+ * RAM array
+ */
+
+ HDAT_INF("Failed trying to add another entry to a mainstore area RAM "
+ "array %d",iv_actRamCnt);
+
+ hdatBldErrLog(l_errlHndl,
+ MOD_ADD_RAM, // SRC module ID
+ RC_ERC_MAX_EXCEEDED, // SRC extended reference code
+ iv_actRamCnt, // SRC hex word 1
+ iv_maxRamCnt, // SRC hex word 2
+ iv_msId.hdatMsAreaId); // SRC hex word 3
+ }
+ HDAT_EXIT();
+ return l_errlHndl;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+uint32_t HdatMsArea::ramObjSizes()
+{
+ HDAT_ENTER();
+ uint32_t l_size, l_cnt;
+ HdatRam *l_ramObj;
+
+ l_size = 0;
+
+ // Process the RAM objects
+ for (l_cnt = 0; l_cnt < iv_actRamCnt; l_cnt++)
+ {
+ l_ramObj = *(reinterpret_cast<HdatRam **>(reinterpret_cast<char*>
+ (iv_ramPtrs) + l_cnt * sizeof(HdatRam *)));
+ l_size += l_ramObj->size();
+ }
+
+ HDAT_EXIT();
+ return l_size;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::finalizeObjSize()
+{
+ HDAT_ENTER();
+ uint32_t l_idx;
+ HdatRam **l_ramEntry;
+
+ // Update the base class internal data pointers
+ // When the data is written to the file by commit(), it must be done in the
+ // same order as these addData() calls
+ this->addData(HDAT_MS_AREA_FRU_ID, sizeof(hdatFruId_t));
+ this->addData(HDAT_MS_AREA_KWD, iv_kwdSize);
+ this->addData(HDAT_MS_AREA_ID, sizeof(hdatMsAreaId_t));
+ this->addData(HDAT_MS_AREA_SIZE, sizeof(hdatMsAreaSize_t));
+ this->addData(HDAT_MS_AREA_ADDR_RNG, sizeof(hdatHDIFDataArray_t) +
+ iv_maxAddrRngCnt * sizeof(hdatMsAreaAddrRange_t));
+
+ this->addData(HDAT_MS_AREA_AFF, sizeof(hdatMsAreaAffinity_t));
+ this->addData(HDAT_MS_AREA_EC_ARRAY, sizeof(hdatHDIFDataArray_t) +
+ iv_maxEcCnt * sizeof(hdatMsAreaEcLvl_t));
+
+ this->align();
+
+ // If we have RAM objects of different sizes, the smaller ones have to be
+ // padded to the size of the largest one so that PHYP can traverse through
+ // the RAM objects as elements of an array.
+ if (iv_ramPadReq)
+ {
+ for (l_idx = 0; l_idx < iv_actRamCnt; l_idx++)
+ {
+ l_ramEntry = (reinterpret_cast<HdatRam **>(reinterpret_cast<char*>
+ (iv_ramPtrs) + l_idx * sizeof(HdatRam *)));
+
+ if (iv_maxRamObjSize > (*l_ramEntry)->size())
+ {
+ (*l_ramEntry)->maxSiblingSize(iv_maxRamObjSize);
+ }
+ }
+ }
+
+ // Update the base class for children that have been added
+ for (l_idx = 0; l_idx < iv_actRamCnt; l_idx++)
+ {
+ l_ramEntry = (reinterpret_cast<HdatRam **>(reinterpret_cast<char*>
+ (iv_ramPtrs) + l_idx * sizeof(HdatRam *)));
+ this->addChild(HDAT_MS_AREA_RAM_AREAS, (*l_ramEntry)->size(), 1);
+ // 1st parm is 0 based
+ }
+
+ HDAT_EXIT();
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+uint32_t HdatMsArea::getMsAreaSize()
+{
+ uint32_t l_size = 0;
+
+ // Start committing the base class data
+ l_size += this->getSize();
+
+ // Write the various pieces of data from this derived class
+ l_size += sizeof(hdatFruId_t);
+
+ if ( iv_kwdSize > 0)
+ {
+ l_size += iv_kwdSize;
+ }
+
+ l_size += sizeof(hdatMsAreaId_t);
+
+ l_size += sizeof(hdatMsAreaSize_t);
+
+ l_size += sizeof(hdatHDIFDataArray_t);
+
+ l_size += (iv_maxAddrRngCnt * sizeof(hdatMsAreaAddrRange_t));
+
+ l_size += sizeof(hdatMsAreaAffinity_t);
+
+ l_size += sizeof(hdatHDIFDataArray_t);
+
+ l_size += (iv_maxEcCnt * sizeof(hdatMsAreaEcLvl_t));
+
+ l_size += this->endCommitSize();
+ return l_size;
+}
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+uint32_t HdatMsArea::getRamAreaSize()
+{
+ uint32_t l_size = 0, l_cnt = 0;
+ HdatRam *l_ramObj;
+
+ // Write the RAM structures
+ if (iv_actRamCnt > 0)
+ {
+ l_cnt = 0;
+ while (l_cnt < iv_actRamCnt)
+ {
+ l_ramObj = *(reinterpret_cast<HdatRam **>(reinterpret_cast<char*>
+ (iv_ramPtrs) + l_cnt * sizeof(HdatRam *)));
+
+ l_size += l_ramObj->getRamSize();
+ l_cnt++;
+
+ }
+ }
+
+ return l_size;
+}
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::commit(UtilMem &i_data)
+{
+
+ // Start committing the base class data
+ this->startCommit(i_data);
+
+
+ i_data.write(&iv_fru,sizeof(hdatFruId_t));
+
+ if (iv_kwdSize > 0)
+ {
+ i_data.write(iv_kwd,iv_kwdSize);
+ }
+
+
+ i_data.write(&iv_msId,sizeof(hdatMsAreaId_t));
+
+
+ i_data.write(&iv_msSize, sizeof(hdatMsAreaSize_t));
+
+ i_data.write(&iv_addrRngArrayHdr,sizeof(hdatHDIFDataArray_t));
+
+ i_data.write(iv_addrRange,iv_maxAddrRngCnt * sizeof(hdatMsAreaAddrRange_t));
+
+ i_data.write(&iv_aff, sizeof(hdatMsAreaAffinity_t));
+
+ i_data.write(&iv_ecArrayHdr, sizeof(hdatHDIFDataArray_t));
+
+ i_data.write(iv_ecLvl,iv_maxEcCnt * sizeof(hdatMsAreaEcLvl_t));
+
+ this->endCommit(i_data);
+}
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::commitRamAreas(UtilMem &i_data)
+{
+
+ uint32_t l_cnt;
+ HdatRam *l_ramObj;
+
+ // Write the RAM structures
+ if (iv_actRamCnt > 0)
+ {
+ l_cnt = 0;
+ while (l_cnt < iv_actRamCnt)
+ {
+ l_ramObj = *(reinterpret_cast<HdatRam **>(reinterpret_cast<char*>
+ (iv_ramPtrs) + l_cnt * sizeof(HdatRam *)));
+
+ l_ramObj->commit(i_data);
+ l_cnt++;
+
+ }
+ }
+}
+
+
+
+/** @brief See the prologue in hdatmsarea.H
+ */
+void HdatMsArea::prt()
+{
+ uint32_t l_cnt;
+ hdatMsAreaEcLvl_t *l_ec;
+ hdatMsAreaAddrRange_t *l_addr;
+ HdatRam *l_ramObj;
+
+ HDAT_INF(" **** HdatMsArea start ****");
+ HDAT_INF(" cv_actualCnt = %u", cv_actualCnt);
+ HDAT_INF(" iv_kwdSize = %u", iv_kwdSize);
+ HDAT_INF(" iv_maxAddrRngCnt = %u", iv_maxAddrRngCnt);
+ HDAT_INF(" iv_maxEcCnt = %u", iv_maxEcCnt);
+ HDAT_INF(" iv_maxRamCnt = %u", iv_maxRamCnt);
+ HDAT_INF(" iv_actRamCnt = %u", iv_actRamCnt);
+ this->print();
+ //hdatPrintFruId(&iv_fru);
+ hdatPrintKwd(iv_kwd, iv_kwdSize);
+
+ HDAT_INF(" **hdatMsAreaId_t**");
+ HDAT_INF(" hdatMsAreaId = %u", iv_msId.hdatMsAreaId);
+ HDAT_INF(" hdatMsAreaParentType = %u", iv_msId.hdatMsAreaParentType);
+ HDAT_INF(" hdatMsAreaStatus %u", iv_msId.hdatMsAreaStatus);
+
+ HDAT_INF(" **hdatMsAreaSize_t**");
+ HDAT_INF(" hdatMsAreaSize = %u", iv_msSize.hdatMsAreaSize);
+
+ HDAT_INF(" **hdatMsAreaAddrRange_t**");
+ hdatPrintHdrs(NULL, NULL, &iv_addrRngArrayHdr, NULL);
+ l_addr = iv_addrRange;
+ for (l_cnt = 0; l_cnt < iv_ecArrayHdr.hdatArrayCnt; l_cnt++)
+ {
+ HDAT_INF(" hdatMsAreaStrAddr = 0X %08X %08X ",
+ l_addr->hdatMsAreaStrAddr.hi,
+ l_addr->hdatMsAreaStrAddr.lo);
+ HDAT_INF(" hdatMsAreaEndAddr = 0X %08X %08X ",
+ l_addr->hdatMsAreaEndAddr.hi,
+ l_addr->hdatMsAreaEndAddr.lo);
+ HDAT_INF(" hatMsAreaProcChipId = %u", l_addr->hatMsAreaProcChipId);
+ HDAT_INF(" hdatSMMAttributes.hdatRangeIsMirrorable = %u",
+ l_addr->hdatSMMAttributes.hdatRangeIsMirrorable);
+ HDAT_INF(" hdatSMMAttributes.hdatMirroringAlgorithm = %u",
+ l_addr->hdatSMMAttributes.hdatMirroringAlgorithm);
+ HDAT_INF(" hdatStartMirrAddr = 0X %08X %08X ",
+ l_addr->hdatStartMirrAddr.hi, l_addr->hdatStartMirrAddr.lo);
+ l_addr++;
+ l_cnt++;
+ }
+ HDAT_INF("");
+
+
+ HDAT_INF(" **hdatMsAreaAffinity_t**");
+ HDAT_INF(" hdatMsAreaModuleId = %u", iv_aff.hdatMsAreaModuleId);
+ HDAT_INF(" hdatMsAffinityDomain = %u", iv_aff.hdatMsAffinityDomain);
+
+ HDAT_INF(" **hdatMsAreaEcLvl_t**");
+ hdatPrintHdrs(NULL, NULL, &iv_ecArrayHdr, NULL);
+ l_ec = iv_ecLvl;
+ for (l_cnt = 0; l_cnt < iv_ecArrayHdr.hdatArrayCnt; l_cnt++)
+ {
+ HDAT_INF(" hdatChipManfId = %u", l_ec->hdatChipManfId);
+ HDAT_INF(" hdatChipEcLvl = %u", l_ec->hdatChipEcLvl);
+ l_ec++;
+ }
+
+ HDAT_INF(" **** HdatMsArea end ****");
+
+ // Write the RAM structures
+ if (iv_actRamCnt > 0)
+ {
+ HDAT_INF(" **associated RAM objects**");
+ for(l_cnt = 0; l_cnt < iv_actRamCnt; l_cnt++)
+ {
+ l_ramObj = *(HdatRam **)((char *)iv_ramPtrs + l_cnt
+ * sizeof(HdatRam *));
+ l_ramObj->prt();
+ }
+ }
+
+ return;
+}
+}
diff --git a/src/usr/hdat/hdatmsarea.H b/src/usr/hdat/hdatmsarea.H
new file mode 100755
index 000000000..79fa04a10
--- /dev/null
+++ b/src/usr/hdat/hdatmsarea.H
@@ -0,0 +1,609 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatmsarea.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATMSAREA_H
+#define HDATMSAREA_H
+
+/**
+ * @file hdatmsarea.H
+ *
+ * @brief This file contains the class definition for the mainstore areas.
+ * This structure is part of the larger mainstore VPD structure
+ * which describes the various chips which make up the memory subsystem.
+ *
+ */
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <stdint.h> // standard types
+#include <hdat/hdat.H> // HDAT header type definitions
+#include "hdathdif.H" // HdatHdif base class definition
+#include "hdatram.H" // HdatRam class definition
+#include <errl/errlentry.H> // ErrlEntry class
+
+namespace HDAT
+{
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+const uint16_t HDAT_MS_AREA_VERSION = 0x30;
+const char HDAT_MSAREA_STRUCT_NAME[] = "MSAREA";
+
+/** @brief Since the size of each MS Area must the same as all others, the
+ * total size of the EC level array and the address range array must
+ * be the same in each MS area. The constants below are the result of
+ * a bug found during initial PHYP bringup when several MS areas were
+ * built with different sizes. We always reserve enough space for the
+ * maximum number of array entries since we don't know in advance how
+ * many entries will actually be added.
+ */
+const uint32_t HDAT_MAX_EC_ENTRIES = 5;
+const uint32_t HDAT_MAX_ADDR_RNG_ENTRIES = 4;
+
+ /** @enum hdatDataPtrs
+ * Constants for the internal data pointers that are added to the base class
+ */
+enum hdatMsAreaDataPtrs
+{
+ HDAT_MS_AREA_FRU_ID = 0,
+ HDAT_MS_AREA_KWD = 1,
+ HDAT_MS_AREA_ID = 2,
+ HDAT_MS_AREA_SIZE = 3,
+ HDAT_MS_AREA_ADDR_RNG = 4,
+ HDAT_MS_AREA_AFF = 5,
+ HDAT_MS_AREA_EC_ARRAY = 6,
+ HDAT_MS_AREA_RESERVED1 = 7,
+ HDAT_MS_AREA_RESERVED2 = 8,
+ HDAT_MS_AREA_RESERVED3 = 9,
+ HDAT_MS_AREA_LAST = 10
+};
+
+
+/*----------------------------------------------------------------------------*/
+/* Typedefs */
+/*----------------------------------------------------------------------------*/
+
+/** @brief Structure definition for the main store area id and status.
+ Reserved bytes are added to make the structure a multiple of 4 bytes.
+ Adjust the reserved size as necessary if new members are added to this
+ structure.
+ */
+struct hdatMsAreaId_t
+{
+ uint16_t hdatMsAreaId; // 0x0000 Identifier for this mainstore area
+ uint16_t hdatMsAreaParentType; // 0x0002 Memory parent type
+ uint16_t hdatMsAreaStatus; // 0x0004 Status
+ uint16_t hdatInterleavedId; // 0x0006 Id for MS areas which are interleaved
+} __attribute__ ((packed));
+
+
+/** @brief Structure definition for the size of the main store area
+ */
+struct hdatMsAreaSize_t
+{
+ uint32_t hdatReserved1; // 0x0000 Reserved to make hdatMsAreaSize 8 bytes
+ // in future
+ uint32_t hdatMsAreaSize; // 0x0004 Total size of the configured main store
+ // in mega-bytes
+} __attribute__ ((packed));
+
+/** @brief Structure definition for Selective Memory Mirroring attributes field
+ */
+struct hdatSMMAttributes_t
+{
+ uint8_t hdatRangeIsMirrorable; // 0x0000 Memory range is mirrorable
+ uint8_t hdatMirroringAlgorithm; // 0x0001 Hardware mirroring algorithm to
+ // use
+ uint16_t hdatReserved; // 0x0002
+} __attribute__ ((packed));
+
+
+/** @brief Structure definition for an array of main store area address ranges
+ */
+struct hdatMsAreaAddrRange_t
+{
+ hdatMsAddr_t hdatMsAreaStrAddr; // 0x0000 Range starting address
+ hdatMsAddr_t hdatMsAreaEndAddr; // 0x0008 Range ending address+1
+ uint32_t hatMsAreaProcChipId; // 0x0010 Processor physical chip id
+ // associated with this address range
+ hdatSMMAttributes_t hdatSMMAttributes; // 0x0014 SMM Attributes
+ hdatMsAddr_t hdatStartMirrAddr; // 0x0018 Starting Mirrorable Address
+ // for range
+} __attribute__ ((packed));
+
+
+/** @brief Structure definition for the processor affinity
+ */
+struct hdatMsAreaAffinity_t
+{
+ uint32_t hdatMsAreaModuleId; // 0x0000 Processor Module ID associated
+ // with this mainstore area
+ uint32_t hdatMsAffinityDomain; // 0x0004 Affinity Domain
+} __attribute__ ((packed));
+
+
+/** @brief Structure definition for an entry in the chip's engineering change
+ * level array
+ */
+struct hdatMsAreaEcLvl_t
+{
+ uint32_t hdatChipManfId; // 0x0000 Memory interface chip manufacturing id
+ uint32_t hdatChipEcLvl; // 0x0004 Memory interface chip EC level
+} __attribute__ ((packed));
+
+
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/** @enum hdatMsAreaChildPtrs
+ * Constants for the child structure pointers that are added to the base
+ * class
+ */
+enum hdatMsAreaChildPtrs
+{
+ HDAT_MS_AREA_RAM_AREAS = 0,
+ HDAT_MS_AREA_CHILD_RESERVED1 = 1,
+ HDAT_MS_AREA_CHILD_LAST = 2
+};
+
+
+/*----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatMsArea class is used to construct objects which describe
+ * main store areas.
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that anyone can create an object of this type. In particular,
+ * the object is built only in the hdatstep process when the step
+ * that builds hypervisor data structures is run.
+ *
+ * The real purpose of the object is to create the various main store
+ * area structures as defined by the PHYP Initialization architecture
+ * This data structure is eventually DMA'd to main memory. The
+ * class is not defined to be a general purpose interface for
+ * building this object by anyone other than the hdatstep process.
+ *
+ * Thread safety: An HdatMsArea object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by
+ * multiple threads at the same time. An object can be used by
+ * multiple threads if the threads serialize access. And of
+ * course, each thread can use its own object with no concerns
+ * about what other threads are doing.
+ *
+ * Signal handler usage: This class is not intended to be used in a signal
+ * handler and nothing has been done to try and make it safe to use
+ * in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatMsArea : public HdatHdif
+{
+public:
+
+ /**
+ * @brief Construct an HdatMsArea object.
+ *
+ * This is the constructor for the HdatMsArea object.
+ *
+ * If you are constructing this object on the heap by using new, then
+ * you must check the pointer returned from new to see if it is null.
+ * If it is null, new failed to allocate storage and the constructor
+ * was not called. If it is not null, then you must check o_errlHndl
+ * to see if the constructor ran successfully. If o_errlHndl indicates
+ * an error was reported by the constructor, new has already allocated
+ * heap storage and the object must be deleted in order to free the
+ * heap storage.
+ *
+ * @pre None
+ *
+ * @post An HdatMsArea object has been constructed.
+ * Heap storage has been allocated.
+ *
+ * @param[out] o_errlHndl - If any errors occur, the HdatMsArea object
+ * is NOT constructed and errors are returned in this
+ * parameter
+ * @param[in]i_msAreaId - input parameter - A unique id for each main store
+ * area associated with a mainstore VPD object. The id
+ * starts at 0 and is incremented by 1 for each new
+ * mainstore area.
+ * @param[in] i_ramCnt - The number of RAM objects that will be
+ * added to the mainstore area. If an exact count cannot
+ * be computed, a maximum number can be provided.
+ * @param[in] i_chipEcCnt - The number of EC entries that will be
+ * added to the mainstore area. If an exact count
+ * cannot be computed, a maximum number can be provided.
+ * @param[in] i_addrRngCnt - The number of address range entries that
+ * will be added to the mainstore area. If an exact
+ * count cannot be computed, a maximum number can be
+ * provided.
+ * @param[in] i_resourceId - The FRU's resource id
+ * @param[in] i_slcaIdx - SLCA index for this FRU (only meaningful
+ * if keyword size > 0).
+ * @param[in] i_kwdSize - Size of the ASCII keyword data if available,
+ * otherwise 0.
+ * @param[in] i_kwd - ASCII keyword data if available, otherwise
+ * NULL.
+ *
+ * @return A null error log handle if successful, else the return code point
+ * to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ */
+ HdatMsArea(errlHndl_t &o_errlHndl,
+ TARGETING::Target* i_target,
+ uint16_t i_msAreaId,
+ uint32_t i_ramCnt,
+ uint32_t i_chipEcCnt,
+ uint32_t i_addrRngCnt,
+ uint32_t i_resourceId,
+ uint32_t i_slcaIdx,
+ uint32_t i_kwdSize,
+ char *&i_kwd);
+
+
+ /**
+ * @brief HdatMsArea object destructor
+ *
+ * This is the destructor for an HdatMsArea object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatMsArea object has been destroyed and can no longer be used.
+ *
+ */
+ virtual ~HdatMsArea();
+
+
+ /**
+ * @brief Add a RAM area to this main store area
+ *
+ * A RAM object is added.
+ *
+ * @pre The number of RAM objects added cannot exceed the RAM count specified
+ * on the HdatMsArea constructor
+ *
+ * @post None
+ *
+ * @param[in] i_ram - input parameter - A RAM object
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addRam(HdatRam &i_ram);
+
+
+ /**
+ * @brief Update the mainstore area to specify the type of memory.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[in] i_type - input parameter - This specifies the type of memory
+ * card for this mainstore area.
+ */
+ void setParentType(uint16_t i_type);
+
+
+ /**
+ * @brief Update the mainstore area to specify the status of the memory DIMMS
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[in] i_status - input parameter - See the hdatMsAreaStatus enum.
+ * The value specified here can be a bitwise OR of the enum values.
+ */
+ void setStatus(uint16_t i_status);
+
+
+ /**
+ * @brief Update the mainstore area with a unique ID for interleaved areas
+ *
+ * The call to setStatus must also turn on the HDAT_MEM_SHARED flag.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[in] i_status - A unique ID. All MS areas which are
+ * interleaved will have the same ID.
+ */
+ void setInterleavedId(uint16_t i_id);
+
+
+ /**
+ * @brief Update the mainstore area to specify the total size of the mainstore
+ * area.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[in] i_size - The total size of the configured mainstore
+ * area in megabytes. It is the (high address of the mainstore
+ * area + 1 minus the low address of the mainstore area) divided
+ * by 1 megabyte.
+ */
+ void setSize(uint32_t i_size);
+
+
+ /**
+ * @brief Update the mainstore area to specify associated processor id
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[in] i_moduleId - The Module Id of the processor
+ * associated with this mainstore area.
+ */
+ void setModuleId(uint32_t i_moduleId);
+
+ /**
+ * @brief Update the mainstore area to specify its affinity domain
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[in] i_affinityDomain - The Affinity Domain
+ * associated with this mainstore area.
+ */
+ void setAffinityDomain(uint32_t i_affinityDomain);
+
+ /**
+ * @brief Get the SLCA index, the keyword size, and the ASCII keyword
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[out] o_resourceId - The resource ID for this FRU
+ * @param[out] o_slcaIdx - The SLCA index for this FRU
+ * @param[out] o_kwdSize The size of the ASCII keyword data
+ * @param[out] o_kwd - A pointer to the ASCII keyword
+ *
+ */
+ void getKwdInfo(uint32_t &o_resourceId,
+ uint32_t &o_slcaIdx,
+ uint32_t &o_kwdSize,
+ char *&o_kwd);
+
+
+ /**
+ * @brief Update the mainstore area to specify a memory address range.
+ * More than one address range can be added.
+ *
+ * @pre One cannot add any more address range entries than was specified by
+ * the i_addrRngCnt parameter on the HdatMsArea constructor.
+ *
+ * @post An address range entry has been added.
+ *
+ * @param[in] i_start - The starting address of the range
+ * @param[in] i_end - The ending address of the range + 1
+ * @param[in] i_procChipId - which is the chip id of the physical processor
+ * @param[in] i_rangeIsMirrorable - Specifies whether the range is
+ * mirrorable
+ * @param[in] i_mirroringAlgorithm - Specifies hardware mirroring
+ * algorithm to use
+ * @param[in] i_startMirrAddr - Specifies the starting mirrorable
+ * address for range
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addAddrRange(hdatMsAddr_t &i_start,
+ hdatMsAddr_t &i_end,
+ uint32_t i_procChipId,
+ bool i_rangeIsMirrorable,
+ uint8_t i_mirroringAlgorithm,
+ hdatMsAddr_t &i_startMirrAddr);
+
+
+ /**
+ * @brief Add engineering change information for memory interface chips
+ *
+ * @pre The first EC entry added must be for the memory controller
+ *
+ * @post One cannot add any more engineering change entries than was specified
+ * by the i_chipEcCnt parameter on the HdatMsArea constructor.
+ *
+ * @param[in] i_manfId - input parameter - Chip's manufacturing id
+ * @param[in] i_ecLvl - input parameter - Chip's engineering change level
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addEcEntry(uint32_t i_manfId,
+ uint32_t i_ecLvl);
+
+
+ /**
+ * @brief This routine returns the length of all RAM objects associated
+ * with this mainstore area
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ */
+ uint32_t ramObjSizes();
+
+
+ /**
+ * @brief This routine finalizes the object's size and updates header
+ * information
+ *
+ *
+ * @pre All data must have been added to the object and it must be ready to
+ * commit.
+ *
+ * @post This method must be called first before the inherited size() method
+ * can be called and return correct results.
+ *
+ */
+ void finalizeObjSize();
+
+
+ /**
+ * @brief Print an HdatMsArea object.
+ *
+ * This method is a debug mthod which prints out a mainstore area object.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ */
+ void prt();
+
+ /**
+ * @brief Get MS area size
+ *
+ * This method is to retreive complete MS area size
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @return - returns size value
+ *
+ */
+ uint32_t getMsAreaSize();
+
+ /**
+ * @brief Get Ram area size
+ *
+ * This method invokes ram getSize routine for all the child pointers
+ * and gets the size.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @return - returns size value
+ *
+ */
+ uint32_t getRamAreaSize();
+ /**
+ * @brief Writes the MS area data in main store memory
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[inout] i_data - memory used to write the data
+ *
+ *
+ */
+ void commit(UtilMem &i_data);
+ /**
+ * @brief Iterates all the child pointers to invoke function that writes ram
+ * area data
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[inout] i_data - memory used to write the data
+ *
+ *
+ */
+ void commitRamAreas(UtilMem &i_data);
+private:
+
+
+ /** Object Instance Data
+ *
+ * @li iv_kwdSize - size of the ASCII keyword
+ * @li iv_maxAddrRngCnt - maximum number of address range entries that
+ * can be added
+ * @li iv_maxEcCnt - maximum number of EC entries that can be added
+ * @li iv_maxRamCnt - maximum number of RAM objects that can be added
+ * @li iv_actRamCnt - actual number of RAM objects that were added
+ * @li iv_maxRamObjSize - maximum size of any RAM object associated with
+ * this mainstore area
+ * @li iv_kwd - ptr to storage which holds the ASCII keyword
+ * @li iv_ramPadReq - padding will be required for one or more RAM
+ * objects to make them all the same size
+ * @li iv_fru - FRU Id information
+ * @li iv_msId - mainstore area id information
+ * @li iv_msSize - mainstore size information
+ * @li iv_AddrRngArrayHdr - data array header
+ * @li iv_addrRange - mainstore addresses
+ * @li iv_aff - CPU affinity information
+ * @li iv_ecArrayHdr - data array header
+ * @li iv_ecLvl - EC level array
+ * @li iv_ramPtrs - ptr to storage which contains one of more ptrs
+ * to RAM objects
+ */
+ uint32_t iv_kwdSize;
+ uint32_t iv_maxAddrRngCnt;
+ uint32_t iv_maxEcCnt;
+ uint32_t iv_maxRamCnt;
+ uint32_t iv_actRamCnt;
+ uint32_t iv_maxRamObjSize;
+ char *iv_kwd;
+ bool iv_ramPadReq;
+ hdatFruId_t iv_fru;
+ hdatMsAreaId_t iv_msId;
+ hdatMsAreaSize_t iv_msSize;
+ hdatHDIFDataArray_t iv_addrRngArrayHdr;
+ hdatMsAreaAddrRange_t *iv_addrRange;
+ hdatMsAreaAffinity_t iv_aff;
+ hdatHDIFDataArray_t iv_ecArrayHdr;
+ hdatMsAreaEcLvl_t *iv_ecLvl;
+ HdatRam **iv_ramPtrs;
+
+
+ /** Class (static) Data
+ *
+ * Only one copy of this data exists in a process.
+ *
+ * @li cv_actualCnt - a count of how many HdatMsArea objects are created
+ */
+ static uint32_t cv_actualCnt;
+
+}; // end of HdatMsArea class
+
+}
+#endif // HDATMSAREA_H
diff --git a/src/usr/hdat/hdatmsvpd.C b/src/usr/hdat/hdatmsvpd.C
new file mode 100755
index 000000000..a83669a71
--- /dev/null
+++ b/src/usr/hdat/hdatmsvpd.C
@@ -0,0 +1,2015 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatmsvpd.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+/**
+ * @file hdatmsvpd.C
+ *
+ * @brief This file contains the implementation of the HdatMsVpd class.
+ *
+ */
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include "hdatmsvpd.H" // HdatMsVpd class definition
+#include "hdathdif.H"
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include <assert.h>
+#include <util/align.H>
+#include <limits.h>
+
+
+namespace HDAT
+{
+/*----------------------------------------------------------------------------*/
+/* Global variables */
+/*----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------*/
+/* Macros */
+/*----------------------------------------------------------------------------*/
+// macro to compute the address of a main store area
+#define HDAT_MS_AREA(_i_idx_) *((HdatMsArea **)((char *)iv_msAreaPtrs + \
+_i_idx_ * sizeof(HdatMsArea *)))
+
+
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+HdatMsVpd::HdatMsVpd(errlHndl_t &o_errlHndl,
+ const hdatMsAddr_t &i_msAddr
+ ):HdatHdif(o_errlHndl,
+ HDAT_MSVPD_STRUCT_NAME, HDAT_MS_VPD_LAST, HDAT_START_INSTANCE,
+ HDAT_MS_CHILD_LAST, HDAT_MS_VPD_VERSION),
+ iv_actMsAreaCnt(0), iv_maxMsAreaCnt(0), iv_msAreaPtrs(NULL),
+ iv_IMTaddrRangeArray(NULL), iv_maxIMTAddrRngCnt(0),
+ iv_UEaddrRangeArray(NULL), iv_maxUEAddrRngCnt(0)
+{
+ memcpy(&iv_msAddr, &i_msAddr, sizeof(hdatMsAddr_t));
+}
+
+
+
+void HdatMsVpd::hdatInit(hdatMsAddr_t &i_maxMsAddr,
+ hdatMsAddr_t &i_maxMsCcmAddr,
+ uint32_t i_msSize,
+ uint32_t i_msAreaCnt,
+ uint32_t i_MostSigAffinityDomain,
+ uint32_t i_ueAreaCnt,
+ uint64_t i_MirrMemStartAddr)
+{
+ iv_maxUEAddrRngCnt = i_ueAreaCnt;
+ iv_maxMsAreaCnt = i_msAreaCnt;
+ iv_maxIMTAddrRngCnt = i_msAreaCnt;
+ memcpy(&iv_maxAddr.hdatMaxAddr, &i_maxMsAddr, sizeof(hdatMsAddr_t));
+ memcpy(&iv_maxAddr.hdatMaxCcmAddr, &i_maxMsCcmAddr, sizeof(hdatMsAddr_t));
+ iv_maxAddr.hdatMstSigAffntyDom = i_MostSigAffinityDomain;
+ memcpy(&iv_maxAddr.hdatMirrMemStartAddr, &i_MirrMemStartAddr,
+ sizeof(hdatMsAddr_t));
+ iv_maxSize.hdatReserved1 = 0;
+ iv_maxSize.hdatTotSize = i_msSize;
+ memset(&iv_mover, 0x00, sizeof(hdatMsVpdPageMover_t));
+ iv_IMTaddrRngArrayHdr.hdatOffset = sizeof(hdatHDIFDataArray_t);
+ iv_IMTaddrRngArrayHdr.hdatArrayCnt = 0;
+ iv_IMTaddrRngArrayHdr.hdatAllocSize = sizeof(hdatMsVpdImtAddrRange_t);
+ iv_IMTaddrRngArrayHdr.hdatActSize = sizeof(hdatMsVpdImtAddrRange_t);
+ iv_UEaddrRngArrayHdr.hdatOffset = sizeof(hdatHDIFDataArray_t);
+ iv_UEaddrRngArrayHdr.hdatArrayCnt = 0;
+ iv_UEaddrRngArrayHdr.hdatAllocSize = sizeof(hdatMsVpdUEAddrRange_t);
+ iv_UEaddrRngArrayHdr.hdatActSize = sizeof(hdatMsVpdUEAddrRange_t);
+ iv_RHBaddrRngArrayHdr.hdatOffset = sizeof(hdatHDIFDataArray_t);
+ iv_RHBaddrRngArrayHdr.hdatArrayCnt = 0;
+ iv_RHBaddrRngArrayHdr.hdatAllocSize = sizeof(hdatMsVpdRhbAddrRange_t);
+ iv_RHBaddrRngArrayHdr.hdatActSize = sizeof(hdatMsVpdRhbAddrRange_t);
+
+ iv_maxRHBAddrRngCnt = hdatGetMaxCecNodes();
+
+ // Allocate space for the mainstore area entries and IMT Addr Range array
+ iv_msAreaPtrs = new HdatMsArea*[iv_maxMsAreaCnt];
+ iv_IMTaddrRangeArray = new hdatMsVpdImtAddrRange_t[iv_maxIMTAddrRngCnt];
+ iv_UEaddrRangeArray = new hdatMsVpdUEAddrRange_t[iv_maxUEAddrRngCnt];
+ // Allocate space for the host boot memory reserve range
+ iv_RHBaddrRangeArray = new hdatMsVpdRhbAddrRange_t[iv_maxRHBAddrRngCnt];
+
+ // Update the base class internal data pointers.
+ // When the data is written to the file by commit(), it must be done in the
+ // same order as these addData() calls
+ this->addData(HDAT_MS_VPD_MAX_ADDR, sizeof(hdatMsVpdAddr_t));
+ this->addData(HDAT_MS_VPD_MAX_SIZE, sizeof(hdatMsVpdSize_t));
+ this->addData(HDAT_MS_VPD_PAGE_MOVER, sizeof(hdatMsVpdPageMover_t));
+
+ this->addData(HDAT_MS_VPD_IMT_ADDR_RNG, (sizeof(hdatHDIFDataArray_t) +
+ (iv_maxIMTAddrRngCnt * sizeof(hdatMsVpdImtAddrRange_t))));
+ this->addData(HDAT_MS_VPD_UE_ADDR_RNG, (sizeof(hdatHDIFDataArray_t) +
+ (iv_maxUEAddrRngCnt * sizeof(hdatMsVpdUEAddrRange_t))));
+
+ this->addData(HDAT_MS_VPD_HB_ADDR_RNG, (sizeof(hdatHDIFDataArray_t) +
+ (iv_maxRHBAddrRngCnt * sizeof(hdatMsVpdRhbAddrRange_t))));
+ this->align();
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+HdatMsVpd::~HdatMsVpd()
+{
+
+ uint32_t l_cnt;
+ HdatMsArea *l_obj, **l_curPtr;
+
+ // Delete mainstore area objects (which in turn delete RAM objects)
+ l_curPtr = iv_msAreaPtrs;
+ for (l_cnt = 0; l_cnt < iv_actMsAreaCnt; l_cnt++)
+ {
+ l_obj = *l_curPtr;
+ delete l_obj;
+ l_curPtr = reinterpret_cast<HdatMsArea**>(reinterpret_cast<char*>
+ (l_curPtr) + sizeof(HdatMsArea *));
+ }
+
+ delete[] iv_msAreaPtrs;
+
+ // Delete IMT Address Range Array
+ delete[] iv_IMTaddrRangeArray;
+
+ // Delete UE Address Range Array
+ delete[] iv_UEaddrRangeArray;
+
+ delete[] iv_RHBaddrRangeArray;
+
+ uint64_t l_addr = reinterpret_cast<uint64_t> (iv_virtAddr);
+ l_addr = ALIGN_PAGE_DOWN(l_addr);
+
+ iv_virtAddr = reinterpret_cast<void*>(l_addr);
+
+ int rc = mm_block_unmap(iv_virtAddr);
+ if( rc != 0)
+ {
+ errlHndl_t l_errl = NULL;
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_MSVPD_DESTRUCTOR
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errl,
+ MOD_MSVPD_DESTRUCTOR,
+ RC_DEV_MAP_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+
+ return;
+}
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+errlHndl_t HdatMsVpd::addIMTAddrRange(hdatMsAddr_t &i_start,
+ hdatMsAddr_t &i_end)
+{
+
+ errlHndl_t l_errlHndl = NULL;
+ hdatMsVpdImtAddrRange_t *l_addr;
+
+ if (iv_IMTaddrRngArrayHdr.hdatArrayCnt < iv_maxIMTAddrRngCnt)
+ {
+ l_addr = reinterpret_cast<hdatMsVpdImtAddrRange_t*>(reinterpret_cast
+ <char*>(iv_IMTaddrRangeArray) + (iv_IMTaddrRngArrayHdr.hdatArrayCnt *
+ sizeof(hdatMsVpdImtAddrRange_t)));
+
+ l_addr->hdatImtAddrRngStrAddr = i_start;
+ l_addr->hdatImtAddrRngEndAddr = i_end;
+ iv_IMTaddrRngArrayHdr.hdatArrayCnt++;
+ }
+ else
+ {
+ /*@
+ * @errortype
+ * @refcode LIC_REFCODE
+ * @subsys EPUB_FIRMWARE_SP
+ * @reasoncode RC_ERC_MAX_EXCEEDED
+ * @moduleid MOD_ADD_IMT_ADDR_RANGE
+ * @userdata1 current number of array entries
+ * @userdata2 maximum number of array entries
+ * @userdata3 none
+ * @userdata4 none
+ * @devdesc Exceeded limit of number of mainstore VPD
+ * In Memory Trace array entries
+ */
+ hdatBldErrLog(l_errlHndl,
+ MOD_ADD_IMT_ADDR_RANGE, // SRC module ID
+ RC_ERC_MAX_EXCEEDED, // SRC extended reference code
+ iv_IMTaddrRngArrayHdr.hdatArrayCnt, // SRC hex word 1
+ iv_maxIMTAddrRngCnt); // SRC hex word 2
+ }
+
+ return l_errlHndl;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+errlHndl_t HdatMsVpd::addUEAddrRange(hdatMsAddr_t &i_addr)
+{
+
+ errlHndl_t l_errlHndl = NULL;
+ hdatMsVpdUEAddrRange_t *l_addr;
+
+ if (iv_UEaddrRngArrayHdr.hdatArrayCnt < iv_maxUEAddrRngCnt)
+ {
+ l_addr = reinterpret_cast<hdatMsVpdUEAddrRange_t*>(reinterpret_cast
+ <char*>(iv_UEaddrRangeArray) + (iv_UEaddrRngArrayHdr.hdatArrayCnt *
+ sizeof(hdatMsVpdUEAddrRange_t)));
+
+ l_addr->hdatUEAddr = i_addr;
+ iv_UEaddrRngArrayHdr.hdatArrayCnt++;
+ }
+ else
+ {
+ /*@
+ * @errortype
+ * @refcode LIC_REFCODE
+ * @subsys EPUB_FIRMWARE_SP
+ * @reasoncode RC_ERC_MAX_EXCEEDED
+ * @moduleid MOD_ADD_UE_ADDR_RANGE
+ * @userdata1 current number of array entries
+ * @userdata2 maximum number of array entries
+ * @userdata3 none
+ * @userdata4 none
+ * @devdesc Exceeded limit of number of mainstore
+ * VPD In Memory Trace array entries
+ */
+ hdatBldErrLog(l_errlHndl,
+ MOD_ADD_UE_ADDR_RANGE, // SRC module ID
+ RC_ERC_MAX_EXCEEDED, // SRC extended reference code
+ iv_UEaddrRngArrayHdr.hdatArrayCnt, // SRC hex word 1
+ iv_maxUEAddrRngCnt); // SRC hex word 2
+ }
+
+ return l_errlHndl;
+}
+
+
+errlHndl_t HdatMsVpd::addRHBAddrRange(uint32_t i_dbob_id, hdatMsAddr_t &i_start,
+ hdatMsAddr_t &i_end, uint32_t i_labelSize,
+ uint8_t* &i_labelStringPtr)
+{
+ errlHndl_t l_errlHndl = NULL;
+ hdatMsVpdRhbAddrRange_t *l_addr;
+
+ if (iv_RHBaddrRngArrayHdr.hdatArrayCnt < iv_maxRHBAddrRngCnt)
+ {
+ l_addr = reinterpret_cast<hdatMsVpdRhbAddrRange_t*>(reinterpret_cast
+ <char*>(iv_RHBaddrRangeArray) + (iv_RHBaddrRngArrayHdr.hdatArrayCnt *
+ sizeof(hdatMsVpdRhbAddrRange_t)));
+
+ l_addr->hdatDbobID = i_dbob_id;
+ l_addr->hdatRhbAddrRngStrAddr = i_start;
+ l_addr->hdatRhbAddrRngEndAddr = i_end;
+ //TODO : : RTC Story 159684
+ //Need to verify the correct data for label size and string
+ if (i_labelSize <= HDAT_MS_RHB_LABEL_LEN)
+ {
+ l_addr->hdatRhbLabelSize = i_labelSize;
+ }
+ else
+ {
+ l_addr->hdatRhbLabelSize = HDAT_MS_RHB_LABEL_LEN;
+ }
+
+ memset(l_addr->hdatRhbLabelString, 0x00, HDAT_MS_RHB_LABEL_LEN);
+
+ if (i_labelStringPtr != NULL)
+ {
+ for(uint8_t l_idx = 0; l_idx < l_addr->hdatRhbLabelSize; l_idx++)
+ {
+ l_addr->hdatRhbLabelString[l_idx] = i_labelStringPtr[l_idx];
+ }
+ }
+ else
+ {
+ HDAT_INF("hdatmsvpd:addRHBAddrRange "
+ "i_labelStringPtr is NULL");
+ }
+ iv_RHBaddrRngArrayHdr.hdatArrayCnt++;
+ }
+ else
+ {
+ /*@
+ * @errortype
+ * @refcode LIC_REFCODE
+ * @subsys EPUB_FIRMWARE_SP
+ * @reasoncode RC_ERC_MAX_EXCEEDED
+ * @moduleid MOD_ADD_RES_HB_ADDR_RANGE
+ * @userdata1 current number of array entries
+ * @userdata2 maximum number of array entries
+ * @userdata3 none
+ * @userdata4 none
+ * @devdesc Exceeded limit of number of mainstore VPD Reserved
+ * Hostboot array entries
+ */
+ hdatBldErrLog(l_errlHndl,
+ MOD_ADD_RES_HB_ADDR_RANGE, // SRC module ID
+ RC_ERC_MAX_EXCEEDED, // SRC extended reference code
+ iv_RHBaddrRngArrayHdr.hdatArrayCnt, // SRC hex word 1
+ iv_maxRHBAddrRngCnt); // SRC hex word 2
+ }
+
+ return l_errlHndl;
+
+}
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::setBSR(const hdatMsAddr_t &i_bsrAddr,
+ hdatBsrMode i_bsrMode)
+{
+ const uint32_t HDAT_BSR_ENABLED = 0x20000000;
+
+ iv_mover.hdatFlags |= (HDAT_BSR_ENABLED | i_bsrMode);
+
+ memcpy(&iv_mover.hdatBSRAddr, &i_bsrAddr, sizeof(hdatMsAddr_t));
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::setXSCOM(const hdatMsAddr_t &i_xscomAddr)
+{
+
+ const uint32_t HDAT_XSCOM_ENABLED = 0x10000000;
+
+ iv_mover.hdatFlags |= HDAT_XSCOM_ENABLED;
+
+ memcpy(&iv_mover.hdatXSCOMAddr, &i_xscomAddr, sizeof(hdatMsAddr_t));
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+errlHndl_t HdatMsVpd::addMsAreaFru(uint32_t i_resourceId,
+ uint32_t i_slcaIndex,
+ TARGETING::Target * i_target,
+ uint16_t i_msAreaId,
+ uint32_t i_ramCnt,
+ uint32_t i_chipEcCnt,
+ uint32_t i_addrRngCnt)
+{
+ errlHndl_t l_errlHndl = NULL;
+ HdatMsArea *l_msArea, *l_prevMsArea, **l_arrayEntry;
+ uint32_t l_slcaIdx, l_kwdSize, l_resourceId, l_prevIdx;
+ char *l_kwd;
+
+ l_msArea = NULL;
+ l_kwd = NULL;
+ l_slcaIdx = i_slcaIndex;
+ l_kwdSize = 0;
+
+ // Ensure we are not over max mainstore areas that we were told this object
+ // could handle on the constructor.
+ if (iv_actMsAreaCnt < iv_maxMsAreaCnt)
+ {
+
+ // Determine if the resource ID associated with this mainstore area is
+ // the same as the resoruce id of the previous mainstore area.If it is,
+ // we can gain a performance advantage (translates into a smaller IPL
+ // time for the builddata step) by using the ASCII keyword data we
+ // already have rather than going to svpd to get it again.
+ if (iv_actMsAreaCnt > 0)
+ {
+ l_prevIdx = iv_actMsAreaCnt - 1;
+ l_prevMsArea = HDAT_MS_AREA(l_prevIdx);
+ l_prevMsArea->getKwdInfo(l_resourceId, l_slcaIdx, l_kwdSize, l_kwd);
+ if (l_resourceId != i_resourceId)
+ {
+ l_kwd = NULL;
+ l_slcaIdx = 0;
+ l_kwdSize = 0;
+ }
+ }
+
+ // Create a mainstore area object and add it to the array of objects we
+ // are managing
+ l_msArea = new HdatMsArea(l_errlHndl,
+ i_target,
+ i_msAreaId,
+ i_ramCnt,
+ i_chipEcCnt,
+ i_addrRngCnt,
+ i_resourceId,
+ l_slcaIdx,
+ l_kwdSize,
+ l_kwd);
+ if (NULL == l_errlHndl)
+ {
+ l_arrayEntry = reinterpret_cast<HdatMsArea**>(reinterpret_cast
+ <char*>(iv_msAreaPtrs) + iv_actMsAreaCnt * sizeof(HdatMsArea *));
+
+ *l_arrayEntry = l_msArea;
+ iv_actMsAreaCnt++;
+ }
+ else
+ {
+ delete l_msArea;
+ }
+ }
+ else
+ {
+ /*@
+ * @errortype
+ * @refcode LIC_REFCODE
+ * @subsys EPUB_FIRMWARE_SP
+ * @reasoncode RC_ERC_MAX_EXCEEDED
+ * @moduleid MOD_ADD_MS_AREA_FRU
+ * @userdata1 current array entry count
+ * @userdata2 maximum array entry count
+ * @userdata3 ID number of mainstore area that wasn't added
+ * @userdata4 none
+ * @devdesc Exceeded limit of number of mainstore area array entries
+ */
+ hdatBldErrLog(l_errlHndl,
+ MOD_ADD_MS_AREA_FRU, // SRC module ID
+ RC_ERC_MAX_EXCEEDED, // SRC extended reference code
+ iv_actMsAreaCnt, // SRC hex word 1
+ iv_maxMsAreaCnt, // SRC hex word 2
+ i_msAreaId); // SRC hex word 3
+ }
+
+ return l_errlHndl;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::setMsAreaType(uint16_t i_msAreaId,
+ hdatMemParentType i_type)
+{
+ HdatMsArea *l_obj;
+
+ if (i_msAreaId < iv_actMsAreaCnt)
+ {
+ l_obj = HDAT_MS_AREA(i_msAreaId);
+ l_obj->setParentType(i_type);
+ }
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::setMsAreaStat(uint16_t i_msAreaId,
+ uint16_t i_status)
+{
+
+ HdatMsArea *l_obj;
+
+ if (i_msAreaId < iv_actMsAreaCnt)
+ {
+ l_obj = HDAT_MS_AREA(i_msAreaId);
+ l_obj->setStatus(i_status);
+ }
+ else
+ {
+ HDAT_ERR( "hdatmsvpd:setMsAreaStat - invalid i_msAreadId parameter");
+ }
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::setMsAreaInterleavedId(uint16_t i_msAreaId,
+ uint16_t i_id)
+{
+ HdatMsArea *l_obj;
+
+ if (i_msAreaId < iv_actMsAreaCnt)
+ {
+ l_obj = HDAT_MS_AREA(i_msAreaId);
+ l_obj->setInterleavedId(i_id);
+ }
+ else
+ {
+ HDAT_ERR( "hdatmsvpd:setMsAreaInterleavedId-invalid i_msAreadId "
+ "parameter");
+ }
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::setMsAreaSize(uint16_t i_msAreaId,
+ uint32_t i_size)
+{
+ HdatMsArea *l_obj;
+
+ if (i_msAreaId < iv_actMsAreaCnt)
+ {
+ l_obj = HDAT_MS_AREA(i_msAreaId);
+ l_obj->setSize(i_size);
+ }
+ else
+ {
+ HDAT_ERR( "hdatmsvpd:setMsAreaSize - invalid i_msAreadId parameter");
+ }
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::setMsAreaModuleId(uint16_t i_msAreaId,
+ uint32_t i_moduleId)
+{
+ HdatMsArea *l_obj;
+
+ if (i_msAreaId < iv_actMsAreaCnt)
+ {
+ l_obj = HDAT_MS_AREA(i_msAreaId);
+ l_obj->setModuleId(i_moduleId);
+ }
+ else
+ {
+ HDAT_ERR( "hdatmsvpd:setMsAreaModuleId - invalid i_msAreadId"
+ " parameter");
+ }
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::setMsAreaAffinityDomain(uint16_t i_msAreaId,
+ uint32_t i_affinityDomain)
+{
+ HdatMsArea *l_obj;
+
+ if (i_msAreaId < iv_actMsAreaCnt)
+ {
+ l_obj = HDAT_MS_AREA(i_msAreaId);
+ l_obj->setAffinityDomain(i_affinityDomain);
+ }
+ else
+ {
+ HDAT_ERR("hdatmsvpd:setMsAreaAffinityDomain-invalid "
+ "i_msAreadId parameter");
+ }
+
+ return;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+errlHndl_t HdatMsVpd::addMsAreaAddr(uint16_t i_msAreaId,
+ hdatMsAddr_t &i_start,
+ hdatMsAddr_t &i_end,
+ uint32_t i_procChipId,
+ bool i_rangeIsMirrorable,
+ uint8_t i_mirroringAlgorithm,
+ uint64_t i_startMirrAddr)
+{
+ errlHndl_t l_errlHndl = NULL;
+ HdatMsArea *l_obj;
+ hdatMsAddr_t l_startMirrAddr;
+
+ memcpy(&l_startMirrAddr, &i_startMirrAddr, sizeof(hdatMsAddr_t));
+
+ if (i_msAreaId < iv_actMsAreaCnt)
+ {
+ l_obj = HDAT_MS_AREA(i_msAreaId);
+ l_errlHndl = l_obj->addAddrRange(i_start, i_end, i_procChipId,
+ i_rangeIsMirrorable, i_mirroringAlgorithm, l_startMirrAddr);
+ }
+ else
+ {
+ HDAT_INF( "hdatmsvpd:addMsAreaAddr - invalid i_msAreadId parameter");
+ }
+
+ return l_errlHndl;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+errlHndl_t HdatMsVpd::addEcEntry(uint16_t i_msAreaId,
+ uint32_t i_manfId,
+ uint32_t i_ecLvl)
+{
+ errlHndl_t l_errlHndl = NULL;
+ HdatMsArea *l_obj;
+
+ if (i_msAreaId < iv_actMsAreaCnt)
+ {
+ l_obj = HDAT_MS_AREA(i_msAreaId);
+ l_errlHndl = l_obj->addEcEntry(i_manfId, i_ecLvl);
+ }
+ else
+ {
+ HDAT_ERR( "hdatmsvpd:addEcEntry - invalid i_msAreadId parameter");
+ }
+
+ return l_errlHndl;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+errlHndl_t HdatMsVpd::addRamFru(uint16_t i_msAreaId,
+ TARGETING::Target * i_target,
+ uint32_t i_resourceId,
+ uint32_t i_slcaIndex,
+ uint16_t i_ramId,
+ uint16_t i_status,
+ uint32_t i_size)
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ HdatMsArea *l_msArea;;
+ HdatRam *l_ram;
+
+ // Ensure we are not over the current mainstore area count
+ if (i_msAreaId < iv_actMsAreaCnt)
+ {
+ l_ram = NULL;
+ l_msArea = HDAT_MS_AREA(i_msAreaId);
+
+ // Create a RAM object
+ l_ram = new HdatRam(l_errlHndl, i_target, i_resourceId,i_slcaIndex);
+ if (NULL == l_errlHndl)
+ {
+ l_ram->iv_ramArea.hdatRamAreaId = i_ramId;
+ l_ram->iv_ramArea.hdatRamStatus = i_status;
+ l_ram->iv_ramSize.hdatRamTotalSize = i_size;
+
+ // Add the RAM object to the mainstore area object
+ if (l_msArea)
+ {
+ l_errlHndl = l_msArea->addRam(*l_ram);
+ }
+ }
+
+ if (NULL != l_errlHndl)
+ {
+ delete l_ram;
+ }
+ }
+ else
+ {
+ /*@
+ * @errortype
+ * @refcode LIC_REFCODE
+ * @subsys EPUB_FIRMWARE_SP
+ * @reasoncode RC_ERC_NO_PARENT
+ * @moduleid MOD_ADD_RAM_FRU
+ * @userdata1 main store area id
+ * @userdata2 current count of main store areas
+ * @userdata3 none
+ * @userdata4 none
+ * @devdesc Attempted to add a RAM FRU for an invalid mainstore area
+ */
+ HDAT_INF("Attempted to add a RAM FRU for an invalid mainstore area %d",
+ i_msAreaId);
+
+ hdatBldErrLog(l_errlHndl,
+ MOD_ADD_RAM_FRU, // SRC module ID
+ RC_ERC_NO_PARENT, // SRC extended reference code
+ i_msAreaId, // SRC hex word 1
+ iv_actMsAreaCnt); // SRC hex word 2
+ }
+
+ return l_errlHndl;
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::adjustMsAreaObjects()
+{
+ HdatMsArea *l_msEntry;
+ uint32_t l_idx, l_maxSize, l_tempSize;
+ bool l_adjust;
+
+ l_maxSize = 0;
+ l_adjust = false;
+
+ // Finalize the object size for each MS area object. Also, determine if
+ // the objects differ in size. If they do, an extra step is needed to make
+ // them all the same size.
+ for (l_idx = 0; l_idx < iv_actMsAreaCnt; l_idx++)
+ {
+ l_msEntry = *(reinterpret_cast<HdatMsArea**>(reinterpret_cast
+ <char*>(iv_msAreaPtrs) + l_idx * sizeof(HdatMsArea *)));
+
+ l_msEntry->finalizeObjSize(); // Get the MS area sizes updated before
+ // size() method is used
+ l_tempSize = l_msEntry->size();
+ if (l_maxSize != l_tempSize)
+ {
+ if (l_maxSize != 0)
+ {
+ l_adjust = true;
+ }
+ if (l_maxSize < l_tempSize)
+ {
+ l_maxSize = l_tempSize;
+ }
+ }
+ }
+
+ // Do we need to adjust some of the MS area objects to make them all the
+ // same size?
+ if (l_adjust)
+ {
+ for (l_idx = 0; l_idx < iv_actMsAreaCnt; l_idx++)
+ {
+ l_msEntry = *(reinterpret_cast<HdatMsArea**>(reinterpret_cast
+ <char*>(iv_msAreaPtrs) + l_idx * sizeof(HdatMsArea *)));
+
+ // If too small, adjust its size
+ if (l_msEntry->size() < l_maxSize)
+ {
+ l_msEntry->maxSiblingSize(l_maxSize);
+ }
+ }
+ }
+
+ // Tell the base class about child and grandchild structures.
+ for (l_idx = 0; l_idx < iv_actMsAreaCnt; l_idx++)
+ {
+ l_msEntry = *(reinterpret_cast<HdatMsArea**>(reinterpret_cast
+ <char*>(iv_msAreaPtrs) + l_idx * sizeof(HdatMsArea *)));
+
+ this->addChild(HDAT_MS_AREAS, l_msEntry->size(),1);//1st parm is 0 based
+ this->addGrandChild(l_msEntry->ramObjSizes());
+ }
+
+ return;
+}
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::getTotalSize(uint32_t &o_size)
+{
+
+ HdatMsArea *l_msEntry;
+ // Since MS area objects could be different sizes at this point (different
+ // size for the VPD, for example) and since PHYP traverses the MS areas
+ // as an array, we may need to adjust the MS areas so they are all the same
+ // size.
+ this->adjustMsAreaObjects();
+
+ o_size = this->getSize();
+
+ o_size += sizeof(hdatMsVpdAddr_t);
+
+ o_size += sizeof(hdatMsVpdSize_t);
+
+ o_size += sizeof(hdatMsVpdPageMover_t);
+
+ o_size += sizeof(hdatHDIFDataArray_t);
+
+ o_size += (iv_maxIMTAddrRngCnt * sizeof(hdatMsVpdImtAddrRange_t));
+
+ o_size += sizeof(hdatHDIFDataArray_t);
+
+ o_size += (iv_maxUEAddrRngCnt * sizeof(hdatMsVpdUEAddrRange_t));
+
+ o_size += sizeof(hdatHDIFDataArray_t);
+
+ o_size += (iv_maxRHBAddrRngCnt * sizeof(hdatMsVpdRhbAddrRange_t));
+
+ o_size += this->endCommitSize();
+
+ // Write the MS area structures and RAM structures
+ if (iv_actMsAreaCnt > 0)
+ {
+ // All of the mainstore areas must be written first so that can be
+ // processed as an array of mainstore areas.
+ uint32_t l_ramSizes = 0;
+ uint8_t l_cnt = 0;
+ uint8_t l_currOffset = 0;
+
+ while (l_cnt < iv_actMsAreaCnt)
+ {
+ l_msEntry = *(reinterpret_cast<HdatMsArea**>(reinterpret_cast
+ <char*>(iv_msAreaPtrs) + l_cnt * sizeof(HdatMsArea *)));
+
+ // Since we don't know what order mainstore areas and RAM
+ // areas were created, update the offset in the HdatMsArea
+ // child structure triple so it points to the first RAM area.
+
+ l_currOffset = (iv_actMsAreaCnt - l_cnt) * l_msEntry->size()
+ + l_ramSizes;
+ l_msEntry->chgChildOffset(HDAT_MS_AREA_RAM_AREAS, l_currOffset);
+ o_size += l_msEntry->getMsAreaSize();
+
+ // Now compute the size of the RAM areas associated with this
+ // mainstore area. These will have to be added to the child offset
+ // for the next mainstore area to skip over them.
+ l_ramSizes += l_msEntry->ramObjSizes();
+
+ l_cnt++;
+ }
+
+ // Now the children (RAM areas) of each mainstore area must be committed
+ l_cnt = 0;
+
+ while (l_cnt < iv_actMsAreaCnt)
+ {
+ l_msEntry = *(reinterpret_cast<HdatMsArea**>(reinterpret_cast
+ <char*>(iv_msAreaPtrs) + l_cnt * sizeof(HdatMsArea *)));
+
+ o_size += l_msEntry->getRamAreaSize();
+ l_cnt++;
+ }
+ }
+
+}
+
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::prt()
+{
+ uint32_t l_cnt;
+ HdatMsArea *l_obj;
+
+ HDAT_INF(" **** HdatMsVpd start ****");
+ HDAT_INF(" iv_msAddr = 0X %08X %08X ", iv_msAddr.hi, iv_msAddr.lo);
+ HDAT_INF(" iv_actMsAreaCnt = %u", iv_actMsAreaCnt);
+ HDAT_INF(" iv_maxMsAreaCnt = %u", iv_maxMsAreaCnt);
+ this->print();
+
+ HDAT_INF(" **hdatMsVpdAddr_t**");
+ HDAT_INF(" hdatMaxAddr = 0X %08X %08X ", iv_maxAddr.hdatMaxAddr.hi,
+ iv_maxAddr.hdatMaxAddr.lo);
+ HDAT_INF(" hdatMaxCcmAddr = 0X %08X %08X ", iv_maxAddr.hdatMaxCcmAddr.hi,
+ iv_maxAddr.hdatMaxCcmAddr.lo);
+ HDAT_INF(" hdatMstSigAffntyDom = 0X %08X ", iv_maxAddr.hdatMstSigAffntyDom);
+
+ HDAT_INF(" **hdatMsVpdSize_t**");
+ HDAT_INF(" hdatReserved1 = %u", iv_maxSize.hdatReserved1);
+ HDAT_INF(" hdatTotSize = %u", iv_maxSize.hdatTotSize);
+
+ HDAT_INF(" **hdatMsVpdPageMover_t**");
+ HDAT_INF(" hdatFlags = %u", iv_mover.hdatFlags);
+ HDAT_INF(" hdatLockCnt = %u", iv_mover.hdatLockCnt);
+ HDAT_INF(" hdatLockAddr = 0X %08X %08X ", iv_mover.hdatLockAddr.hi,
+ iv_mover.hdatLockAddr.lo);
+ HDAT_INF(" hdatMoverAddr = 0X %08X %08X ", iv_mover.hdatMoverAddr.hi,
+ iv_mover.hdatMoverAddr.lo);
+ HDAT_INF(" hdatBSRAddr = 0X %08X %08X ", iv_mover.hdatBSRAddr.hi,
+ iv_mover.hdatBSRAddr.lo);
+
+ HDAT_INF(" **hdatMsVpdImtAddrRange_t**");
+ hdatPrintHdrs(NULL, NULL, &iv_IMTaddrRngArrayHdr, NULL);
+{
+ hdatMsVpdImtAddrRange_t *l_addr = iv_IMTaddrRangeArray;
+ for (l_cnt = 0; l_cnt < iv_IMTaddrRngArrayHdr.hdatArrayCnt; l_cnt++)
+ {
+ HDAT_INF(" hdatImtAddrRngStrAddr = 0X %08X %08X ",
+ l_addr->hdatImtAddrRngStrAddr.hi,
+ l_addr->hdatImtAddrRngStrAddr.lo);
+ HDAT_INF(" hdatImtAddrRngEndAddr = 0X %08X %08X ",
+ l_addr->hdatImtAddrRngEndAddr.hi,
+ l_addr->hdatImtAddrRngEndAddr.lo);
+ l_addr++;
+ l_cnt++;
+ }
+}
+ HDAT_INF(" **hdatMsVpdUEAddrRange_t**");
+ hdatPrintHdrs(NULL, NULL, &iv_UEaddrRngArrayHdr, NULL);
+ {
+ hdatMsVpdUEAddrRange_t *l_addr = iv_UEaddrRangeArray;
+ for (l_cnt = 0; l_cnt < iv_UEaddrRngArrayHdr.hdatArrayCnt; l_cnt++)
+ {
+ HDAT_INF(" hdatUEAddrRngStrAddr = 0X %08X %08X ",
+ l_addr->hdatUEAddr.hi,
+ l_addr->hdatUEAddr.lo);
+ l_addr++;
+ l_cnt++;
+ }
+ }
+ HDAT_INF(" **hdatMsVpdRhbAddrRange_t**");
+ hdatPrintHdrs(NULL, NULL, &iv_RHBaddrRngArrayHdr, NULL);
+ {
+ hdatMsVpdRhbAddrRange_t *l_addr = iv_RHBaddrRangeArray;
+ for (l_cnt = 0; l_cnt < iv_RHBaddrRngArrayHdr.hdatArrayCnt; l_cnt++)
+ {
+ HDAT_INF(" hdatRhbAddrRngStrAddr = 0X %08X %08X ",
+ l_addr->hdatRhbAddrRngStrAddr.hi,
+ l_addr->hdatRhbAddrRngStrAddr.lo);
+ HDAT_INF(" hdatRhbAddrRngEndAddr = 0X %08X %08X ",
+ l_addr->hdatRhbAddrRngEndAddr.hi,
+ l_addr->hdatRhbAddrRngEndAddr.lo);
+ l_addr++;
+ l_cnt++;
+ }
+
+ }
+ HDAT_INF("");;
+
+ HDAT_INF(" **** HdatMsVpd end ****");
+
+ HDAT_INF(" **main store areas and their associated RAM areas**");
+ for (l_cnt = 0; l_cnt < iv_actMsAreaCnt; l_cnt++)
+ {
+ l_obj = *(HdatMsArea **)((char *)iv_msAreaPtrs + l_cnt *
+ sizeof(HdatMsArea *));
+ l_obj->prt();
+ }
+
+ return;
+}
+
+
+
+
+/*******************************************************************************
+* hdatLoadMsData
+*******************************************************************************/
+errlHndl_t HdatMsVpd::hdatLoadMsData(uint32_t &o_size, uint32_t &o_count)
+{
+ errlHndl_t l_err = NULL;
+ HDAT_ENTER();
+
+ do
+ {
+ //Find the system target
+ TARGETING::Target *l_pSysTarget = NULL;
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSysTarget);
+
+ assert(l_pSysTarget != NULL);
+
+ hdatMsAddr_t l_addr_range;
+ hdatMsAddr_t l_end;
+ l_addr_range.hi = 0x0;
+ l_addr_range.lo = 0x0;
+ l_end = l_addr_range;
+
+ uint32_t l_sizeConfigured = 0;
+ uint64_t l_maxMsAddr = hdatGetMaxMemConfiguredAddress();
+
+ hdatMsAddr_t l_tmpMaxMsAddr;
+ l_tmpMaxMsAddr.hi = (l_maxMsAddr & 0xFFFFFFFF00000000ull) >> 32;
+ l_tmpMaxMsAddr.lo = l_maxMsAddr & 0x00000000FFFFFFFFull;
+
+ HDAT_INF("MaxMsAddr high:0x%.8X 0x%.8X",
+ l_tmpMaxMsAddr.hi,l_tmpMaxMsAddr.lo);
+
+ uint32_t l_mostSigAffinityDomain_x = 0;
+ uint32_t l_ueCount = 1;
+
+ TARGETING::ATTR_MIRROR_BASE_ADDRESS_type l_mirroringBaseAddress_x =
+ l_pSysTarget->getAttr<TARGETING::ATTR_MIRROR_BASE_ADDRESS>();
+ l_mirroringBaseAddress_x |= HDAT_REAL_ADDRESS_MASK64;
+
+ TARGETING::ATTR_MAX_MCS_PER_SYSTEM_type l_maxMsAreas =
+ l_pSysTarget->getAttr<TARGETING::ATTR_MAX_MCS_PER_SYSTEM>();
+
+ // Initialize the MS vpd class
+ hdatInit(l_tmpMaxMsAddr,l_tmpMaxMsAddr,l_sizeConfigured,l_maxMsAreas,
+ l_mostSigAffinityDomain_x,l_ueCount,l_mirroringBaseAddress_x);
+
+ TARGETING::ATTR_XSCOM_BASE_ADDRESS_type l_xscomAddr =
+ l_pSysTarget->getAttr<TARGETING::ATTR_XSCOM_BASE_ADDRESS>();
+ assert(l_xscomAddr != 0);
+ {
+ hdatMsAddr_t l_hdatXscomAddr;
+ l_hdatXscomAddr.hi = (l_xscomAddr & 0xFFFFFFFF00000000ull) >> 32;
+ l_hdatXscomAddr.lo = l_xscomAddr & 0x00000000FFFFFFFFull;
+
+ l_hdatXscomAddr.hi |= HDAT_REAL_ADDRESS_MASK;
+
+ setXSCOM(l_hdatXscomAddr);
+ }
+
+ uint32_t l_index = 0;
+ //for each proc/ memory controller in the system
+ TARGETING::PredicateCTM l_procPred(TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_PROC);
+ TARGETING::PredicateHwas l_predHwasPresent;
+ l_predHwasPresent.present(true);
+ TARGETING::PredicateHwas l_predHwasFunc;
+ l_predHwasFunc.functional(true);
+ TARGETING::PredicatePostfixExpr l_funcProc;
+ l_funcProc.push(&l_procPred).push(&l_predHwasFunc).And();
+
+ TARGETING::TargetRangeFilter l_procs(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_funcProc);
+
+ uint32_t l_nxtSharingGroupId = 0;
+
+ for(;l_procs;++l_procs)
+ {
+ TARGETING::Target *l_pProcTarget = *(l_procs);
+ TARGETING::ATTR_ORDINAL_ID_type l_procChipId
+ = l_pProcTarget->getAttr<TARGETING::ATTR_ORDINAL_ID>();
+
+ // TODO : RTC Story 159682
+ // Further CHTM support needs to be added which contains the trace
+ // array for 24 cores
+ hdatMsAddr_t l_hdatNhtmStartAddr;
+ hdatMsAddr_t l_hdatNhtmEndAddr;
+
+ TARGETING::ATTR_PROC_NHTM_BAR_BASE_ADDR_type l_nhtmStartAddr =
+ l_pProcTarget->getAttr<TARGETING::ATTR_PROC_NHTM_BAR_BASE_ADDR>();
+ TARGETING::ATTR_PROC_NHTM_BAR_SIZE_type l_nhtmSize =
+ l_pProcTarget->getAttr<TARGETING::ATTR_PROC_NHTM_BAR_SIZE>();
+
+ if( 0 != l_nhtmSize )
+ {
+ l_hdatNhtmStartAddr.hi =
+ (l_nhtmStartAddr & 0xFFFFFFFF00000000ull) >> 32;
+ l_hdatNhtmStartAddr.lo =
+ l_nhtmStartAddr & 0x00000000FFFFFFFFull;
+ l_hdatNhtmStartAddr.hi |= HDAT_REAL_ADDRESS_MASK;
+
+ l_nhtmSize = l_nhtmStartAddr + l_nhtmSize;
+ l_hdatNhtmEndAddr.hi =
+ (l_nhtmSize & 0xFFFFFFFF00000000ull) >> 32;
+ l_hdatNhtmEndAddr.lo = l_nhtmSize & 0x00000000FFFFFFFFull;
+ l_hdatNhtmEndAddr.hi |= HDAT_REAL_ADDRESS_MASK;
+
+ HDAT_INF("hdatNhtmStartAddr = 0x%08X 0x%08X ",
+ l_hdatNhtmStartAddr.hi, l_hdatNhtmStartAddr.lo);
+ HDAT_INF("hdatNhtmEndAddr = 0x%08X 0x%08X ",
+ l_hdatNhtmEndAddr.hi, l_hdatNhtmEndAddr.lo);
+
+ addIMTAddrRange(l_hdatNhtmStartAddr, l_hdatNhtmEndAddr);
+ }
+ else
+ {
+ HDAT_INF("NHTM Bar size value = 0x%016llX",
+ l_nhtmSize);
+ }
+
+ TARGETING::ATTR_PROC_MEM_BASES_type l_procMemBases = {0};
+ assert(l_pProcTarget->
+ tryGetAttr<TARGETING::ATTR_PROC_MEM_BASES>(l_procMemBases));
+
+ //Sharing count for each group
+ TARGETING::ATTR_MSS_MEM_MC_IN_GROUP_type l_mcsSharingCount = {0};
+
+ //Group ID for each group, group id will be assigned only
+ //if the group is shared
+ TARGETING::ATTR_MSS_MEM_MC_IN_GROUP_type l_mcsSharingGrpIds = {0};
+
+ //Size configured under each group
+ TARGETING::ATTR_PROC_MEM_SIZES_type l_procMemSizesBytes = {0};
+
+ assert(l_pProcTarget->tryGetAttr<TARGETING::ATTR_PROC_MEM_SIZES>
+ (l_procMemSizesBytes));
+
+ TARGETING::PredicateCTM l_mcbistPredicate(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_MCBIST);
+
+ TARGETING::PredicatePostfixExpr l_presentMcbist;
+ l_presentMcbist.push(&l_mcbistPredicate).
+ push(&l_predHwasFunc).And();
+
+ TARGETING::TargetHandleList l_mcbistList;
+
+ // Find Associated MCBIST list
+ TARGETING::targetService().getAssociated(l_mcbistList,
+ l_pProcTarget,
+ TARGETING::TargetService::CHILD_BY_AFFINITY,
+ TARGETING::TargetService::ALL,
+ &l_presentMcbist);
+
+ //scan all mcbist in this proc
+ for(uint32_t l_mcbistIdx =0;
+ l_mcbistIdx < l_mcbistList.size();
+ ++l_mcbistIdx)
+ {
+ TARGETING::Target *l_pMcbistTarget = l_mcbistList[l_mcbistIdx];
+
+ TARGETING::PredicateCTM l_mcsPredicate(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_MCS);
+
+ TARGETING::PredicatePostfixExpr l_funcMcs;
+ l_funcMcs.push(&l_mcsPredicate).push(&l_predHwasFunc).And();
+
+ TARGETING::TargetHandleList l_mcsList;
+
+ // Find Associated memory controllers
+ TARGETING::targetService().getAssociated(l_mcsList,
+ l_pMcbistTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL,
+ &l_funcMcs);
+
+ //scan all mcs in this proc to get sharing counit
+ for(uint32_t l_idx = 0; l_idx<l_mcsList.size(); ++l_idx)
+ {
+ TARGETING::Target *l_pMcsTarget = l_mcsList[l_idx];
+
+ uint32_t l_mcsInGrp = 0;
+ if(!hdatFindGroupForMc(l_pProcTarget,
+ l_pMcsTarget,
+ l_mcsInGrp))
+ {
+ //Skip this MCS is not in any group
+ continue;
+ }
+
+ //Increment sharing count if mem configured under group.
+ if(l_procMemSizesBytes[l_mcsInGrp] > 0)
+ {
+ l_mcsSharingCount[l_mcsInGrp]++;
+
+ //Assign sharing group id only if shared
+ //And only when first instance of sharing is found
+ if(l_mcsSharingCount[l_mcsInGrp] ==
+ HDAT_MIN_NUM_FOR_SHARING)
+ {
+ l_mcsSharingGrpIds[l_mcsInGrp] =
+ l_nxtSharingGroupId;
+ l_nxtSharingGroupId++;
+ }
+ }
+ }
+
+ for(uint32_t l_mcsIdx = 0; l_mcsIdx<l_mcsList.size();
+ ++l_mcsIdx)
+ {
+ TARGETING::Target *l_pMcsTarget =
+ l_mcsList[l_mcsIdx];
+
+ //Group which this MCS is belonging
+ uint32_t l_mcsInGrp = 0;
+
+ if(!hdatFindGroupForMc(l_pProcTarget,
+ l_pMcsTarget,
+ l_mcsInGrp))
+ {
+ HDAT_INF("No group found for MCS");
+ //Skip this MCS is not under any group
+ continue;
+ }
+
+ uint32_t l_mcaFruId = 0;
+ hdatMemParentType l_parentType = HDAT_MEM_PARENT_CEC_FRU;
+
+ std::list<hdatRamArea> l_areas;
+ l_areas.clear();
+ uint32_t l_areaSizeInMB = 0;
+ bool l_areaFunctional = false;
+ uint32_t l_numDimms =0;
+
+ l_err = hdatScanDimms(l_pMcsTarget,
+ l_mcaFruId,
+ l_areas,
+ l_areaSizeInMB,
+ l_numDimms,
+ l_areaFunctional,
+ l_parentType);
+
+ if(NULL != l_err)
+ {
+ HDAT_ERR("Error in calling Scan Dimms");
+ break;
+ }
+
+ HDAT_INF("l_areaSizeInMB:0x%.8X l_numDimms:0x%.8X"
+ " l_areas.size():0x%.8X", l_areaSizeInMB, l_numDimms,
+ l_areas.size());
+
+ //Skip if no memory configured under this MCS
+ if(l_areaSizeInMB == 0)
+ {
+ continue;
+ }
+
+ uint32_t l_maxMemBlocks = 0;
+ l_err = hdatGetMaxMemoryBlocks(l_pMcsTarget,l_maxMemBlocks);
+ if(NULL != l_err)
+ {
+ HDAT_ERR("Error error in get max blocks");
+ break;
+ }
+
+ TARGETING::ATTR_SLCA_RID_type l_procRid =
+ l_pProcTarget->getAttr<TARGETING::ATTR_SLCA_RID>();
+
+ TARGETING::ATTR_SLCA_INDEX_type l_procSlcaIndex =
+ l_pProcTarget->getAttr<TARGETING::ATTR_SLCA_INDEX>();
+
+ l_err = addMsAreaFru(l_procRid,
+ l_procSlcaIndex,
+ l_pProcTarget,
+ l_index,
+ l_numDimms,
+ MAX_CHIP_EC_CNT_PER_MSAREA,
+ l_maxMemBlocks);
+
+ if(NULL != l_err)
+ {
+ HDAT_ERR("Error adding MSArea %d"
+ "Number of Dimms: %d Max Blocks: %d",
+ l_index,
+ l_numDimms,l_maxMemBlocks);
+ break;
+ }
+
+ uint32_t l_memStatus = 0;
+ //If group is shared with more than one area
+ if(l_mcsSharingCount[l_mcsInGrp] >=
+ HDAT_MIN_NUM_FOR_SHARING)
+ {
+ l_memStatus = HDAT_MEM_SHARED;
+ setMsAreaInterleavedId(l_index,
+ l_mcsSharingGrpIds[l_mcsInGrp]);
+ }
+
+ setMsAreaType(l_index,l_parentType);
+ setMsAreaSize(l_index,l_areaSizeInMB);
+
+ iv_maxSize.hdatTotSize += l_areaSizeInMB;
+
+ l_memStatus |= l_areaFunctional ?
+ (HDAT_MEM_INSTALLED | HDAT_MEM_FUNCTIONAL) :
+ HDAT_MEM_INSTALLED;
+
+ setMsAreaStat(l_index, l_memStatus);
+
+ //Add MCS ec level
+ uint32_t l_mcsEcLevel = 0;
+ uint32_t l_mcsChipId = 0;
+ l_err = hdatGetIdEc(l_pMcsTarget,
+ l_mcsEcLevel,
+ l_mcsChipId);
+ if(NULL != l_err)
+ {
+ HDAT_ERR("Error in getting MCS ID "
+ "and EC HUID:[0x%08X]",
+ l_pMcsTarget->getAttr<TARGETING::ATTR_HUID>());
+ break;
+ }
+
+ l_err = addEcEntry(l_index,
+ l_mcsChipId,
+ l_mcsEcLevel);
+ if(NULL != l_err)
+ {
+ HDAT_ERR("Error in adding"
+ " ID[0x%08X] and EC[0x%08X] to ms area"
+ " HUID:[0x%08X]",l_mcsChipId,
+ l_mcsEcLevel,
+ l_pMcsTarget->getAttr<TARGETING::ATTR_HUID>());
+ break;
+ }
+
+ std::list<hdatRamArea>::iterator l_area = l_areas.begin();
+
+ for (uint32_t l_ramId = 0;
+ l_area != l_areas.end();
+ ++l_ramId, ++l_area)
+ {
+ uint32_t l_status = (l_area)->ivFunctional ?
+ (HDAT_RAM_INSTALLED | HDAT_RAM_FUNCTIONAL)
+ : HDAT_RAM_INSTALLED;
+
+ TARGETING::Target *l_pDimmTarget =
+ TARGETING::Target::getTargetFromHuid(l_area->ivHuid);
+
+ TARGETING::ATTR_SLCA_RID_type l_dimmRid =
+ l_pDimmTarget->getAttr<TARGETING::ATTR_SLCA_RID>();
+
+ TARGETING::ATTR_SLCA_INDEX_type l_dimmSlcaIndex =
+ l_pDimmTarget->getAttr<TARGETING::ATTR_SLCA_INDEX>();
+
+ l_err = addRamFru(l_index,
+ l_pDimmTarget,
+ l_dimmRid,
+ l_dimmSlcaIndex,
+ l_ramId,
+ l_status,
+ (l_area)->ivSize);
+
+ if (l_err) // Failed to add ram fru information
+ {
+ HDAT_ERR("Error in adding RAM FRU"
+ "Index:%d Rid:[0x%08X] status:[0x%08X]"
+ "Size:[0x%08X] RamID:[0x%08X]",
+ l_index,(l_area)->ivHuid,
+ l_status,(l_area)->ivSize,l_ramId);
+ ERRORLOG::errlCommit(l_err,HDAT_COMP_ID);
+
+ delete l_err;
+ l_err = NULL;
+ continue;
+ }
+ }//end of RAM list
+
+ l_addr_range.hi = (l_procMemBases[l_mcsInGrp] &
+ 0xFFFFFFFF00000000ull) >> 32;
+ l_addr_range.lo = l_procMemBases[l_mcsInGrp] &
+ 0x00000000FFFFFFFFull;
+
+ l_end = l_addr_range;
+
+ //Update the range
+ l_end.hi += (l_procMemSizesBytes[l_mcsInGrp] &
+ 0xFFFFFFFF00000000ull) >> 32;
+ l_end.lo += l_procMemSizesBytes[l_mcsInGrp] &
+ 0x00000000FFFFFFFFull;
+
+ HDAT_INF("MCS:0x%08X l_addr_range:0x%08X 0x%08X"
+ " l_end:0x%08X 0x%08X",
+ l_pMcsTarget->getAttr<TARGETING::ATTR_HUID>(),
+ l_addr_range.hi, l_addr_range.lo,
+ l_end.hi,l_end.lo);
+
+ uint64_t l_hdatMirrorAddr_x = 0x0ull;
+ uint64_t l_hdatMirrorAddr = 0x0ull;
+ uint8_t l_hdatMirrorAlogrithm = 0xFF;
+ bool l_rangeIsMirrorable = false;
+
+ TARGETING::ATTR_PROC_MIRROR_BASES_type l_MirrorAddr = {0};
+ assert(l_pProcTarget->tryGetAttr<
+ TARGETING::ATTR_PROC_MIRROR_BASES>(l_MirrorAddr));
+
+ TARGETING::ATTR_PROC_MIRROR_SIZES_type l_MirrorSize = {0};
+ assert(l_pProcTarget->tryGetAttr<
+ TARGETING::ATTR_PROC_MIRROR_SIZES>(l_MirrorSize));
+
+ TARGETING::ATTR_MIRROR_BASE_ADDRESS_type l_mirrorBaseAddress_x =
+ l_pSysTarget->getAttr<TARGETING::ATTR_MIRROR_BASE_ADDRESS>();
+
+ uint64_t l_startAddr = (((uint64_t)(l_addr_range.hi) << 32 )
+ | (uint64_t)(l_addr_range.lo));
+ l_hdatMirrorAddr_x = (l_startAddr / 2) + l_mirrorBaseAddress_x;
+
+ TARGETING::ATTR_PAYLOAD_IN_MIRROR_MEM_type l_payLoadMirrorMem =
+ l_pSysTarget->getAttr<TARGETING::ATTR_PAYLOAD_IN_MIRROR_MEM>();
+
+ HDAT_INF(
+ "Start add : 0x%016llX MirrorBase : 0x%016llX"
+ " MirrorAddr : 0x%016llX PayLoadMirrorMem : 0x%X",
+ l_startAddr, l_mirrorBaseAddress_x,
+ l_hdatMirrorAddr_x, l_payLoadMirrorMem);
+
+ if ( 0 != l_payLoadMirrorMem )
+ {
+ for ( int idx=0 ; idx <
+ (int)(sizeof(TARGETING::ATTR_PROC_MIRROR_SIZES_type)
+ / sizeof(uint64_t)) ; idx++ )
+ {
+ HDAT_INF("Mirror size : 0x%016llX"
+ " MirrorAddr[idx] : 0x%016llX"
+ " hdatMirrorAddr_x : 0x%016llX",
+ l_MirrorSize[idx], l_MirrorAddr[idx],
+ l_hdatMirrorAddr_x);
+
+ if( (0 != l_MirrorSize[idx]) &&
+ (l_MirrorAddr[idx] == l_hdatMirrorAddr_x) )
+ {
+ l_rangeIsMirrorable = true;
+ l_hdatMirrorAddr = l_MirrorAddr[idx]
+ | HDAT_REAL_ADDRESS_MASK64;
+ break;
+ }
+ }
+ }
+ l_err = addMsAreaAddr(l_index,
+ l_addr_range,
+ l_end,
+ l_procChipId,
+ l_rangeIsMirrorable,
+ l_hdatMirrorAlogrithm,
+ l_hdatMirrorAddr);
+ if(NULL != l_err)
+ {
+ HDAT_ERR("Error in adding addMsAreaAddr"
+ " to ms area index[%d]",
+ l_index);
+ break;
+ }
+
+ // TODO : RTC Story 159682
+ // Further CHTM support needs to be added which contains the
+ // trace array for 24 cores
+ // Reinitializing the NHTM size
+ l_nhtmSize =
+ l_pProcTarget->getAttr
+ <TARGETING::ATTR_PROC_NHTM_BAR_SIZE>();
+
+ uint64_t l_end_addr =
+ (((uint64_t)(l_end.hi) << 32 ) | (uint64_t)(l_end.lo));
+ uint64_t l_start_addr = (((uint64_t)(l_addr_range.hi) << 32 )
+ | (uint64_t)(l_addr_range.lo));
+ uint64_t l_size_bytes = (l_areaSizeInMB) * 1024 * 1024;
+
+ if((0 != l_nhtmSize) &&
+ (l_size_bytes != (l_end_addr - l_start_addr)))
+ {
+ HDAT_INF("NHTM Bar size = 0x%016llX "
+ " MS area size = 0x%016llX"
+ " l_end_addr = 0x%016llX"
+ " l_start_addr = 0x%016llX",
+ l_nhtmSize,l_size_bytes, l_end_addr, l_start_addr);
+
+ l_addr_range.lo = l_hdatNhtmStartAddr.lo;
+ l_addr_range.hi = l_hdatNhtmStartAddr.hi;
+
+ l_end.lo = l_hdatNhtmEndAddr.lo;
+ l_end.hi = l_hdatNhtmEndAddr.hi;
+
+ l_err = addMsAreaAddr(l_index,
+ l_addr_range,
+ l_end,
+ l_procChipId,
+ false, 0, 0);
+ if(NULL != l_err)
+ {
+ HDAT_ERR("Error in adding "
+ " addMsAreaAddr to ms area index[%d]",
+ l_index);
+ break;
+ }
+ l_nhtmSize=0; //only add 1 entry
+ }
+ l_addr_range = l_end;
+ l_index++;
+ } //end of MCS list
+ } //end of MCBIST list
+ if(l_err)
+ {
+ // Error message recorded above
+ break;
+ }
+ } //end of proc list
+
+ TARGETING::PredicateCTM l_nodePred(TARGETING::CLASS_ENC,
+ TARGETING::TYPE_NODE);
+ TARGETING::PredicateHwas l_predFunctional;
+ l_predFunctional.functional(true);
+ TARGETING::PredicatePostfixExpr l_functionalnode;
+ l_functionalnode.push(&l_nodePred).push(&l_predFunctional).And();
+
+ TARGETING::TargetRangeFilter l_nodes(TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_functionalnode);
+
+ TARGETING::ATTR_HB_RSV_MEM_SIZE_MB_type l_rhbSize =
+ l_pSysTarget->getAttr<TARGETING::ATTR_HB_RSV_MEM_SIZE_MB>();
+ if( 0 != l_rhbSize )
+ {
+ for(;l_nodes;++l_nodes)
+ {
+ TARGETING::ATTR_HB_HRMOR_NODAL_BASE_type l_rhbStartAddr =
+ l_pSysTarget->getAttr<TARGETING::ATTR_HB_HRMOR_NODAL_BASE>();
+
+ TARGETING::Target *l_pNodeTarget = *(l_nodes);
+ uint32_t l_dbobId =
+ l_pNodeTarget->getAttr<TARGETING::ATTR_ORDINAL_ID>();
+
+ hdatMsAddr_t l_hdatRhbStartAddr;
+ hdatMsAddr_t l_hdatRhbEndAddr;
+
+ l_rhbStartAddr = l_rhbStartAddr * l_dbobId;
+ l_hdatRhbStartAddr.hi =
+ (l_rhbStartAddr & 0xFFFFFFFF00000000ull) >> 32;
+ l_hdatRhbStartAddr.lo = l_rhbStartAddr & 0x00000000FFFFFFFFull;
+ l_hdatRhbStartAddr.hi |= HDAT_REAL_ADDRESS_MASK;
+
+ // need to store a 64 bit range
+ uint64_t l_hbSize=0;
+ // in bytes
+ uint64_t l_size_bytes = (l_rhbSize * 1024 * 1024) -1;
+ l_hbSize = l_rhbStartAddr + l_size_bytes;
+ l_hdatRhbEndAddr.hi = (l_hbSize & 0xFFFFFFFF00000000ull) >> 32;
+ l_hdatRhbEndAddr.lo = l_hbSize & 0x00000000FFFFFFFFull;
+ l_hdatRhbEndAddr.hi |= HDAT_REAL_ADDRESS_MASK;
+
+ //TODO : : RTC Story 159684
+ //Need to populate correct label size and label string
+ uint32_t l_rhbLabelSize = 0;
+ uint8_t* l_rhbLabelStringPtr = NULL;
+
+ addRHBAddrRange(l_dbobId, l_hdatRhbStartAddr,
+ l_hdatRhbEndAddr, l_rhbLabelSize,
+ l_rhbLabelStringPtr);
+ }
+ }
+ else
+ {
+ HDAT_INF("Reserve HB mem size 0x%08X",l_rhbSize);
+ }
+
+ if(l_err)
+ {
+ // Error message recorded above
+ break;
+ }
+
+ o_size = 0;
+ o_count = 1; // Only 1 of these structures is ever built
+
+ getTotalSize (o_size);
+
+
+ uint64_t l_base_addr = ((uint64_t) iv_msAddr.hi << 32) | iv_msAddr.lo;
+ uint64_t l_base_addr_down = ALIGN_PAGE_DOWN(l_base_addr);
+ iv_virtAddr = mm_block_map ( reinterpret_cast<void*>(l_base_addr_down),
+ (ALIGN_PAGE(o_size) + PAGESIZE));
+
+ uint64_t l_final_addr = reinterpret_cast<uint64_t>(iv_virtAddr);
+
+ l_final_addr += l_base_addr - l_base_addr_down;
+
+
+ iv_virtAddr = reinterpret_cast<void *> (l_final_addr);
+
+
+ commit(iv_virtAddr,o_size);
+
+ prt();
+ }
+ while(0);
+
+ HDAT_EXIT();
+
+ return l_err;
+}
+
+/** @brief See the prologue in hdatmsvpd.H
+ */
+void HdatMsVpd::commit(void * i_addr,
+ uint32_t i_size)
+{
+
+ uint32_t l_cnt,l_currOffset, l_ramSizes;
+ HdatMsArea *l_msEntry;
+ UtilMem l_data(i_addr, i_size);
+
+ // Start committing the base class data
+ this->startCommit(l_data);
+
+ l_data.write(&iv_maxAddr, sizeof(hdatMsVpdAddr_t));
+
+ l_data.write(&iv_maxSize, sizeof(hdatMsVpdSize_t));
+
+ // Page mover is called 'Misc Addr Structure' on OPAL but still exists
+ l_data.write(&iv_mover, sizeof(hdatMsVpdPageMover_t));
+
+ l_data.write(&iv_IMTaddrRngArrayHdr,sizeof(hdatHDIFDataArray_t));
+
+ l_data.write(iv_IMTaddrRangeArray,
+ iv_maxIMTAddrRngCnt * sizeof(hdatMsVpdImtAddrRange_t));
+
+ l_data.write(&iv_UEaddrRngArrayHdr, sizeof(hdatHDIFDataArray_t));
+
+ l_data.write(iv_UEaddrRangeArray,
+ iv_maxUEAddrRngCnt * sizeof(hdatMsVpdUEAddrRange_t));
+
+ l_data.write(&iv_RHBaddrRngArrayHdr,sizeof(hdatHDIFDataArray_t));
+
+ l_data.write (iv_RHBaddrRangeArray,iv_maxRHBAddrRngCnt
+ * sizeof(hdatMsVpdRhbAddrRange_t));
+
+ this->endCommit(l_data);
+
+
+ // Write the MS area structures and RAM structures
+ if (iv_actMsAreaCnt > 0)
+ {
+ // All of the mainstore areas must be written first so that can be
+ // processed as an array of mainstore areas.
+ l_ramSizes = 0;
+ l_cnt = 0;
+
+ while (l_cnt < iv_actMsAreaCnt)
+ {
+ l_msEntry = *(reinterpret_cast<HdatMsArea **>(
+ reinterpret_cast<char *>(iv_msAreaPtrs) + l_cnt
+ * sizeof(HdatMsArea *)));
+
+ // Since we don't know what order mainstore areas and RAM
+ // areas were created, update the offset in the HdatMsArea
+ // child structure triple so it points to the first RAM area.
+
+ l_currOffset = (iv_actMsAreaCnt - l_cnt) * l_msEntry->size()
+ + l_ramSizes;
+ l_msEntry->chgChildOffset(HDAT_MS_AREA_RAM_AREAS, l_currOffset);
+ l_msEntry->commit(l_data);
+
+ // Now compute the size of the RAM areas associated with this
+ // mainstore area. These will have to be added to the child
+ // offset for the next mainstore area to skip over them.
+ l_ramSizes += l_msEntry->ramObjSizes();
+
+ l_cnt++;
+ }
+
+ // Now the children (RAM areas) of each mainstore area must be committed
+ l_cnt = 0;
+
+ while (l_cnt < iv_actMsAreaCnt)
+ {
+ l_msEntry = *(reinterpret_cast<HdatMsArea **>(reinterpret_cast<char *>
+ (iv_msAreaPtrs) + l_cnt
+ * sizeof(HdatMsArea *)));
+ l_msEntry->commitRamAreas(l_data);
+ l_cnt++;
+ }
+ }
+}
+
+/*******************************************************************************
+* hdatGetMaxMemConfiguredAddress
+*******************************************************************************/
+uint64_t HdatMsVpd::hdatGetMaxMemConfiguredAddress()
+{
+ //For each processor in the system
+ TARGETING::PredicateCTM l_procChipPred(TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_PROC);
+
+ TARGETING::PredicateHwas l_predFunctional;
+ l_predFunctional.functional(true);
+ TARGETING::PredicatePostfixExpr l_functionalProc;
+ l_functionalProc.push(&l_procChipPred).push(&l_predFunctional).And();
+
+ TARGETING::TargetRangeFilter l_procs(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_functionalProc);
+
+ uint64_t l_maxBase = 0x0ull;
+ uint64_t l_maxMsAddress = 0x0ull;
+ bool l_processedAnyGroup = false;
+ uint64_t l_hdatMaxImtAddr = 0x0ull;
+
+ for(;l_procs;++l_procs)
+ {
+ TARGETING::Target *l_pProcTarget = (*l_procs);
+
+ TARGETING::ATTR_PROC_MEM_BASES_type l_procMemBases = {0};
+ TARGETING::ATTR_PROC_MEM_SIZES_type l_procMemSizesBytes = {0};
+
+ assert(l_pProcTarget->tryGetAttr<TARGETING::ATTR_PROC_MEM_SIZES>
+ (l_procMemSizesBytes));
+
+ assert(l_pProcTarget->
+ tryGetAttr<TARGETING::ATTR_PROC_MEM_BASES>(l_procMemBases));
+
+ //For each MCS
+ TARGETING::PredicateCTM l_allMcs(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_MCS);
+ TARGETING::PredicateHwas l_funcMcs;
+ l_funcMcs.functional(true);
+ TARGETING::PredicatePostfixExpr l_allFuncMcs;
+ l_allFuncMcs.push(&l_allMcs).push(&l_funcMcs).And();
+
+ TARGETING::TargetHandleList l_mcsList;
+
+ TARGETING::targetService().
+ getAssociated(l_mcsList, l_pProcTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL, &l_allFuncMcs);
+
+ for(uint32_t i=0; i < l_mcsList.size(); i++)
+ {
+
+ TARGETING::Target *l_pMcsTarget = l_mcsList[i];
+
+ uint32_t l_mcsInGroup = 0;
+ if(!hdatFindGroupForMc(l_pProcTarget,
+ l_pMcsTarget,
+ l_mcsInGroup))
+ {
+ //Skip this MC not part of any group
+ continue;
+ }
+
+ if(!l_processedAnyGroup ||
+ (l_procMemBases[l_mcsInGroup] > l_maxBase))
+ {
+ l_maxBase = l_procMemBases[l_mcsInGroup];
+ l_processedAnyGroup = true;
+ l_maxMsAddress = l_maxBase + l_procMemSizesBytes[l_mcsInGroup];
+ }
+ }
+
+ // TODO : RTC Story 159682
+ // Further CHTM support needs to be added which contains the trace array
+ // for 24 cores
+ hdatMsAddr_t l_hdatNhtmStartAddr;
+ hdatMsAddr_t l_hdatNhtmEndAddr;
+
+ TARGETING::ATTR_PROC_NHTM_BAR_BASE_ADDR_type l_nhtmStartAddr =
+ l_pProcTarget->getAttr<TARGETING::ATTR_PROC_NHTM_BAR_BASE_ADDR>();
+ TARGETING::ATTR_PROC_NHTM_BAR_SIZE_type l_nhtmSize =
+ l_pProcTarget->getAttr<TARGETING::ATTR_PROC_NHTM_BAR_SIZE>();
+
+ if( 0 != l_nhtmSize )
+ {
+ l_hdatNhtmStartAddr.hi =
+ (l_nhtmStartAddr & 0xFFFFFFFF00000000ull) >> 32;
+ l_hdatNhtmStartAddr.lo = l_nhtmStartAddr & 0x00000000FFFFFFFFull;
+ l_hdatNhtmStartAddr.hi |= HDAT_REAL_ADDRESS_MASK;
+
+ l_nhtmSize = l_nhtmStartAddr + l_nhtmSize;
+ l_hdatNhtmEndAddr.hi =
+ (l_nhtmSize & 0xFFFFFFFF00000000ull) >> 32;
+ l_hdatNhtmEndAddr.lo = l_nhtmSize & 0x00000000FFFFFFFFull;
+ l_hdatNhtmEndAddr.hi |= HDAT_REAL_ADDRESS_MASK;
+
+ if( l_hdatMaxImtAddr <
+ (((uint64_t)l_hdatNhtmEndAddr.hi << 32) |l_hdatNhtmEndAddr.lo))
+ {
+ l_hdatMaxImtAddr =
+ (((uint64_t)l_hdatNhtmEndAddr.hi << 32) |l_hdatNhtmEndAddr.lo);
+ HDAT_INF("NHTM Max Addr: = 0x%016llX", l_hdatMaxImtAddr);
+ }
+ }
+ else
+ {
+ HDAT_INF("NHTM Bar size value = 0x%016llX ", l_nhtmSize);
+ }
+ }
+ // Set MSB to 1 for PHYP
+ l_maxMsAddress |= HDAT_REAL_ADDRESS_MASK64;
+
+ if(l_hdatMaxImtAddr > l_maxMsAddress)
+ {
+ l_maxMsAddress = l_hdatMaxImtAddr;
+ HDAT_INF("IMT Max MS Addr: = 0x%016llX",l_maxMsAddress);
+ }
+ // We now have to subtract 1 since the address range starts at 0
+ if(l_maxMsAddress != 0)
+ {
+ l_maxMsAddress -= 1;
+ }
+
+ return l_maxMsAddress;
+}
+
+//******************************************************************************
+//* hdatFindGroupForMc
+//******************************************************************************
+bool HdatMsVpd::hdatFindGroupForMc(const TARGETING::Target *i_pProcTarget,
+ const TARGETING::Target *i_pMcsTarget,
+ uint32_t& o_groupOfMc)
+{
+ bool l_foundGroup = false;
+ TARGETING::ATTR_MSS_MEM_MC_IN_GROUP_type l_mcsGroups = {0};
+ assert(i_pProcTarget != NULL || i_pMcsTarget != NULL);
+
+ assert(!(i_pProcTarget->getAttr<TARGETING::ATTR_TYPE>()
+ != TARGETING::TYPE_PROC)||
+ !(i_pProcTarget->getAttr<TARGETING::ATTR_CLASS>()
+ != TARGETING::CLASS_CHIP));
+
+ assert(i_pProcTarget->
+ tryGetAttr<TARGETING::ATTR_MSS_MEM_MC_IN_GROUP>(l_mcsGroups));
+
+ assert(!(i_pMcsTarget->getAttr<TARGETING::ATTR_TYPE>()
+ != TARGETING::TYPE_MCS)||
+ !(i_pMcsTarget->getAttr<TARGETING::ATTR_CLASS>()
+ != TARGETING::CLASS_UNIT));
+ TARGETING::ATTR_CHIP_UNIT_type l_chipUnit =
+ i_pMcsTarget->getAttr<TARGETING::ATTR_CHIP_UNIT>();
+ uint32_t l_sizeOfArray = sizeof(l_mcsGroups)/sizeof(l_mcsGroups[0]);
+
+ assert(!(sizeof( l_mcsGroups[0] ) != sizeof(uint8_t)));
+
+
+ assert(!( l_chipUnit >= ( sizeof( l_mcsGroups[0] ) * HDAT_BITS_PER_BYTE )));
+
+
+ const uint8_t MC_IN_GROUP_MCS_0 = 0x80;
+ for(uint32_t l_idx =0; l_idx < l_sizeOfArray;++l_idx)
+ {
+ //Attribute ATTR_MSS_MEM_MC_IN_GROUP is an array of bitmask
+ //bit 0 of bitmask corresponds to mcs 0, bit 7 to mcs7
+ if((l_mcsGroups[l_idx] & (MC_IN_GROUP_MCS_0 >> l_chipUnit)) ==
+ (MC_IN_GROUP_MCS_0 >> l_chipUnit))
+ {
+ HDAT_INF("hdatFindGroupForMc::: Found group : %d",l_idx);
+ o_groupOfMc = l_idx;
+ l_foundGroup = true;
+ break;
+ }
+ }
+
+ return l_foundGroup;
+}
+/*******************************************************************************
+* hdatScanDimms
+*******************************************************************************/
+errlHndl_t HdatMsVpd::hdatScanDimms(const TARGETING::Target *i_pTarget,
+ uint32_t i_mcaFruid,
+ std::list<hdatRamArea>& o_areas,
+ uint32_t& o_areaSize,
+ uint32_t& o_dimmNum,
+ bool& o_areaFunctional,
+ hdatMemParentType& o_parentType)
+{
+ errlHndl_t l_err = NULL;
+
+ do
+ {
+ if(i_pTarget->getAttr<TARGETING::ATTR_TYPE>() != TARGETING::TYPE_MCS)
+ {
+ HDAT_ERR("Input Target is type not supported.");
+ break;
+ }
+
+ TARGETING::ATTR_EFF_DIMM_SIZE_type l_dimSizes = {{0}};
+ //Get configured memory size
+ if(!i_pTarget->
+ tryGetAttr<TARGETING::ATTR_EFF_DIMM_SIZE>(l_dimSizes))
+ {
+ HDAT_ERR("DIMM size should be available with MCS");
+ }
+
+ //for each MCA connected to this this MCS
+ TARGETING::PredicateCTM l_mcaPredicate(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_MCA);
+
+ TARGETING::PredicateHwas l_predMca;
+ l_predMca.present(true);
+ TARGETING::PredicatePostfixExpr l_presentMca;
+ l_presentMca.push(&l_mcaPredicate).push(&l_predMca).And();
+ TARGETING::TargetHandleList l_mcaList;
+
+ // Get associated MCAs
+ TARGETING::targetService().
+ getAssociated(l_mcaList, i_pTarget,
+ TARGETING::TargetService::CHILD_BY_AFFINITY,
+ TARGETING::TargetService::ALL, &l_presentMca);
+
+ o_dimmNum = 0;
+ for (uint32_t i = 0; i < l_mcaList.size(); ++i)
+ {
+
+ TARGETING::Target *l_pMcaTarget = l_mcaList[i];
+
+ //for each DIMM connected to this this MCA
+ TARGETING::PredicateCTM l_dimmPredicate(TARGETING::
+ CLASS_LOGICAL_CARD,
+ TARGETING::TYPE_DIMM);
+ TARGETING::PredicateHwas l_predDimm;
+ l_predDimm.present(true);
+ TARGETING::PredicatePostfixExpr l_presentDimm;
+ l_presentDimm.push(&l_dimmPredicate).push(&l_predDimm).And();
+
+ TARGETING::TargetHandleList l_dimmList;
+
+ // Get associated dimms
+ TARGETING::targetService().
+ getAssociated(l_dimmList, l_pMcaTarget,
+ TARGETING::TargetService::CHILD_BY_AFFINITY,
+ TARGETING::TargetService::ALL, &l_presentDimm);
+
+
+ for(uint32_t j=0; j < l_dimmList.size(); ++j)
+ {
+ //fetch each dimm
+ TARGETING::Target *l_pDimmTarget = l_dimmList[j];
+
+ uint32_t l_dimmfru = 0;
+ l_dimmfru = l_pDimmTarget->getAttr<TARGETING::ATTR_FRU_ID>();
+
+ uint8_t l_mcaDimm = 0;
+ uint8_t l_mcaPort = 0;
+ TARGETING::ATTR_REL_POS_type l_dimmRelPos = 0;
+
+ if(l_pDimmTarget->
+ tryGetAttr<TARGETING::ATTR_REL_POS>(l_dimmRelPos))
+ {
+ l_mcaDimm = l_dimmRelPos%2; //2 DIMMs per MCA
+ l_dimmRelPos = 0;
+ if(!l_pMcaTarget->
+ tryGetAttr<TARGETING::ATTR_REL_POS>(l_dimmRelPos))
+ {
+ HDAT_ERR("Attribute REL_POS in MCA is not "
+ "present");
+ }
+ else
+ {
+ l_mcaPort = l_dimmRelPos%2; //2 MCAs per MCS
+ }
+ }
+ else
+ {
+ HDAT_ERR("Attribute REL_POS in DIMM "
+ "is not present");
+ }
+
+ //Convert GB to MB
+ uint32_t l_dimmSizeInMB =
+ l_dimSizes[l_mcaPort][l_mcaDimm] * HDAT_MB_PER_GB;
+ uint32_t l_huid = TARGETING::get_huid(l_pDimmTarget);
+
+
+ bool foundArea = false;
+ for (std::list<hdatRamArea>::iterator l_area = o_areas.begin();
+ l_area != o_areas.end();
+ ++l_area)
+ {
+ //we do not need to compare each dimm fru id with mca fru id
+ //to create ram area, by the below logic
+ //dimms with same fruid will fall into same ram area
+ //even if they have fru id same with mca
+ if (l_area->ivfruId == l_dimmfru)//this means soldered dimms
+ {
+ foundArea = true;
+ l_area->ivFunctional = (l_area)->ivFunctional ||
+ isFunctional(l_pDimmTarget);
+ (l_area)->ivFunctional = true;
+ (l_area)->ivSize += l_dimmSizeInMB;
+ break;
+ }
+ }
+
+ //Search in the list of RAM Areas if not
+ //present create a new ram area
+ if (!foundArea)
+ {
+ o_dimmNum++;
+ o_areas.push_back(hdatRamArea(l_huid,
+ isFunctional(l_pDimmTarget),
+ l_dimmSizeInMB,l_dimmfru));
+ }
+ o_areaSize += l_dimmSizeInMB;
+ o_areaFunctional = o_areaFunctional ||
+ isFunctional(l_pDimmTarget);
+ }
+ if(l_err != NULL)
+ {
+ //Break of error
+ break;
+ }
+ }
+ o_parentType = HDAT_MEM_PARENT_CEC_FRU;
+
+ if(l_err != NULL)
+ {
+ //break if error
+ break;
+ }
+ }
+ while(0);
+ return l_err;
+}
+/*******************************************************************************
+* hdatGetMaxMemoryBlocks
+*******************************************************************************/
+errlHndl_t HdatMsVpd::hdatGetMaxMemoryBlocks(const TARGETING::Target *i_pTarget,
+ uint32_t &o_maxMemoryBlocks)
+{
+ errlHndl_t l_err = NULL;
+ do
+ {
+ //One Memctrl connected to only one membuf in P8
+ o_maxMemoryBlocks = 1;
+ }
+ while(0);
+ return l_err;
+}
+} //namespace HDAT
diff --git a/src/usr/hdat/hdatmsvpd.H b/src/usr/hdat/hdatmsvpd.H
new file mode 100755
index 000000000..ade185b41
--- /dev/null
+++ b/src/usr/hdat/hdatmsvpd.H
@@ -0,0 +1,936 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatmsvpd.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATMSVPD_H
+#define HDATMSVPD_H
+
+/**
+ * @file hdatmsvpd.H
+ *
+ * @brief This file contains the class definition for the main store
+ * VPD object.
+ *
+ */
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <stdint.h> // standard types
+#include <hdat/hdat.H> // HDAT header type definitions
+#include "hdathdif.H" // HdatHdif base class definition
+#include "hdatmsarea.H" // HdatMsArea class definition
+#include <errl/errlentry.H> // ErrlEntry class
+#include <vpd/cvpdenums.H>
+#include "hdatutil.H"
+
+namespace HDAT
+{
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/** @brief eye catcher for the HDIF header for the mainstore VPD data area
+ */
+const char HDAT_MSVPD_STRUCT_NAME[] = "MS VPD";
+const uint32_t HDAT_NO_MEMORY = 0;
+const uint32_t HDAT_MIN_NUM_FOR_SHARING = 2;
+const uint32_t HDAT_BITS_PER_BYTE = 8;
+const uint32_t HDAT_MB_PER_GB = 1024;
+const uint32_t MAX_CHIP_EC_CNT_PER_MSAREA = 2;
+const uint32_t HDAT_START_INSTANCE = 0;
+
+
+/** @brief Structure version number
+ */
+const uint16_t HDAT_MS_VPD_VERSION = 0x24;
+
+/** @brief Other constants
+ */
+const uint16_t HDAT_MS_RHB_LABEL_LEN = 64; //Reserved HB length
+
+/** @enum hdatDataPtrs
+ * Constants for the internal data pointers that are added to the base class
+ */
+enum hdatMsVpdDataPtrs
+{
+ HDAT_MS_VPD_MAX_ADDR = 0,
+ HDAT_MS_VPD_MAX_SIZE = 1,
+ HDAT_MS_VPD_PAGE_MOVER = 2,
+ HDAT_MS_VPD_IMT_ADDR_RNG = 3,
+ HDAT_MS_VPD_UE_ADDR_RNG = 4,
+ HDAT_MS_VPD_HB_ADDR_RNG = 5,
+ HDAT_MS_VPD_LAST = 6
+};
+
+
+/** @enum hdatChildPtrs
+ * Constants for the child structure pointers that are added to the base
+ * class
+ */
+enum hdatMsVpdChildPtrs
+{
+ HDAT_MS_AREAS = 0,
+ HDAT_MS_CHILD_RESERVED1 = 1,
+ HDAT_MS_CHILD_LAST = 2
+};
+
+
+/*----------------------------------------------------------------------------*/
+/* Typedefs */
+/*----------------------------------------------------------------------------*/
+
+/**
+* @brief structure for RAM AREA Information
+*
+*/
+struct hdatRamArea
+{
+ uint32_t ivHuid;
+ bool ivFunctional;
+ uint32_t ivSize;
+ uint32_t ivfruId;
+ hdatRamArea(uint32_t i_huid,
+ bool status,
+ uint32_t dimmSize,uint32_t i_fruId) :
+ ivHuid(i_huid),
+ ivFunctional(status),
+ ivSize(dimmSize),
+ ivfruId(i_fruId) {
+ }
+};
+
+/** @brief Main store address information
+ */
+struct hdatMsVpdAddr_t
+{
+ hdatMsAddr_t hdatMaxAddr; // 0x0000 Maximum configured mainstore address
+ hdatMsAddr_t hdatMaxCcmAddr; // 0x0008 Maximum mainstore address that could
+ // be configured if memory is added with
+ // concurrent maintenance
+ uint32_t hdatMstSigAffntyDom; // 0x0010 The affinity domain considered
+ //most important when making affinity decisions
+ hdatMsAddr_t hdatMirrMemStartAddr;//0x0014 Mirrorable MemoryStarting Address
+} __attribute__ ((packed));
+
+
+/** @brief Main store size information
+ */
+struct hdatMsVpdSize_t
+{
+ uint32_t hdatReserved1; // 0x0000 reserved to make hdatTotSize 8 bytes
+ // in future
+ uint32_t hdatTotSize; // 0x0004 Total configured mainstore size in
+ // mega-bytes
+} __attribute__ ((packed));
+
+
+/** @brief Page mover information
+ */
+struct hdatMsVpdPageMover_t
+{
+ uint32_t hdatFlags; // 0x0000 Flags
+ uint32_t hdatLockCnt; // 0x0004 Count of hardware locks per page
+ hdatMsAddr_t hdatLockAddr; // 0x0008 Hardware lock address
+ hdatMsAddr_t hdatMoverAddr; // 0x0010 Page mover address
+ hdatMsAddr_t hdatBSRAddr; // 0x0018 Barrier sync register address
+ hdatMsAddr_t hdatXSCOMAddr; // 0x0020 address of XSCOM address range
+} __attribute__ ((packed));
+
+
+/** @brief In Memory Trace address range array element information
+ */
+struct hdatMsVpdImtAddrRange_t
+{
+ hdatMsAddr_t hdatImtAddrRngStrAddr; // 0x0000 Range starting address
+ hdatMsAddr_t hdatImtAddrRngEndAddr; // 0x0008 Range ending address+1
+} __attribute__ ((packed));
+
+
+/** @brief In UE address range array element information - added for bi01
+ */
+struct hdatMsVpdUEAddrRange_t
+{
+ hdatMsAddr_t hdatUEAddr; // 0x0000 UE area starting address
+} __attribute__ ((packed));
+
+/** @brief In Reserved Hostboot Memory iaddress range array element information-
+ */
+struct hdatMsVpdRhbAddrRange_t
+{
+ uint32_t hdatDbobID; // 0x0000 Node instance
+ // number
+ hdatMsAddr_t hdatRhbAddrRngStrAddr; // 0x0004 Range starting
+ // address
+ hdatMsAddr_t hdatRhbAddrRngEndAddr; // 0x000C Range ending
+ // address+1
+ uint32_t hdatRhbLabelSize; // 0x0014 Label size
+ uint8_t hdatRhbLabelString[HDAT_MS_RHB_LABEL_LEN];// 0x0019 Label string Ptr
+} __attribute__ ((packed));
+
+
+struct hdatMsVpd_t
+{
+ hdatMsVpdAddr_t hdatMsAddr;
+ hdatMsVpdSize_t hdatMsSize;
+ hdatMsVpdPageMover_t hdatPageMover;
+ hdatMsVpdImtAddrRange_t hdatImtAddrRange;
+ hdatMsVpdUEAddrRange_t hdatUEAddrRange;
+ hdatMsVpdRhbAddrRange_t hdatRhbAddrRange;
+}__attribute__ ((packed));
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/* @enum hdatMsAreaStatus
+ * Status of an MS area.
+ */
+enum hdatMsAreaStatus
+{
+ HDAT_MEM_INSTALLED = 0x8000, // DIMMs are installed
+ HDAT_MEM_FUNCTIONAL = 0x4000, // DIMMs are functional
+ HDAT_MEM_SHARED = 0x2000 // Memory is shared
+};
+
+/* @enum hdatRamStatus
+ * Status of a RAM FRU.
+ */
+enum hdatRamStatus
+{
+ HDAT_RAM_NOT_INSTALLED = 0x0000, // RAM is NOT installed
+ HDAT_RAM_INSTALLED = 0x8000, // RAM is installed
+ HDAT_RAM_FUNCTIONAL = 0x4000 // RAM is functional
+};
+
+/* @enum hdatMemParentType
+ *
+ */
+enum hdatMemParentType
+{
+ HDAT_MEM_PARENT_RISER = 0x8000, // RISER card
+ HDAT_MEM_PARENT_MEMCARD = 0x4000, // Memory card
+ HDAT_MEM_PARENT_CEC_FRU = 0x2000, // Other CEC FRU
+ HDAT_MEM_PARENT_HYB_RISER = 0x1000, // Hybrid RISER card
+};
+
+/* @enum hdatBsrMode
+ *
+ */
+enum hdatBsrMode
+{
+ HDAT_BSR_16_BYTE = 0x00000000, // 16 byte BSR mode
+ HDAT_BSR_64_BYTE = 0x02000000, // 64 byte BSR mode
+ HDAT_BSR_128_BYTE = 0x04000000, // 128 byte BSR mode
+
+ // P7 values
+ HDAT_BSR_1M_BYTE = 0x00000000, // 1MB BSR mode
+ HDAT_BSR_2M_BYTE = 0x02000000, // 2MB BSR mode
+ HDAT_BSR_4M_BYTE = 0x04000000, // 4MB BSR mode
+ HDAT_BSR_8M_BYTE = 0x06000000 // 8MB BSR mode
+};
+
+
+
+
+/*----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatMsVpd class is used to construct a main store VPD object.
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that any component can create an object of this type.
+ * In particular,the object is built only in the CEC Server process
+ * when requested by the hdat component. And only 1 HdatMsVpd
+ * object can be built.These restrictions are not checked or
+ * enforced by HDAT.
+ *
+ * The real purpose of the object is to create the main store
+ * VPD structure as defined by the PHYP Initialization
+ * architecture. This data structure is eventually DMA'd to
+ * main memory. The class is not defined to be a general purpose
+ * interface for building this object by anyone other than the
+ * CEC Server process.
+ *
+ * Contained within the mainstore VPD object are mainstore area
+ * objects and RAM objects.
+ *
+ * Thread safety: An HdatMsVpd object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by multiple
+ * threads at the same time. In fact, an object interface is
+ * used only as a better way to built a flat structure to DMA
+ * to main memory.
+ *
+ * Signal handler usage: This class is not intended to be used in a signal
+ * handler and nothing has been done to try and make it safe
+ * to use in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatMsVpd : public HdatHdif
+{
+ public:
+
+ /**
+ * @brief Construct an HdatMsVpd object.
+ *
+ * This is the constructor for the HdatMsVpd object.
+ *
+ * If you are constructing this object on the heap by using new, then
+ * you must check the pointer returned from new to see if it is null.
+ * If it is null, new failed to allocate storage and the constructor
+ * was not called. If it is not null, then you must check o_errlHndl
+ * to see if the constructor ran successfully. If o_errlHndl indicates
+ * an error was reported by the constructor, new has already allocated
+ * heap storage and the object must be deleted in order to free the
+ * heap storage.
+ *
+ * @pre None
+ *
+ * @post An HdatMsVpd object has been constructed.Heap storage has been
+ * allocated.
+ *
+ * @param[out] o_errlHndl - If any errors occur, the HdatMsVpd object
+ * is NOT constructed and errors are returned in
+ * this parameter
+ * @param[in] i_msAddr - The main memory address that the main
+ * store VPD structure will be DMA'd to.
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl.
+ *
+ */
+ HdatMsVpd(errlHndl_t &o_errlHndl,const hdatMsAddr_t &i_msAddr);
+
+ /**
+ * @brief HdatMsVpd object destructor
+ *
+ * This is the destructor for an HdatMsVpd object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatMsVpd object has been destroyed and can no longer be
+ * used.
+ *
+ */
+ virtual ~HdatMsVpd();
+
+ /**
+ * @brief Update the mainstore VPD to specify a memory address range for
+ * the In Memory Trace tool. More than one address range can be added.
+ *
+ * @post An address range entry has been added.
+ *
+ * @param[in] i_start - The starting address of the range
+ * @param[in] i_end - The ending address of the range + 1
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addIMTAddrRange(hdatMsAddr_t &i_start,
+ hdatMsAddr_t &i_end);
+
+ /**
+ * @brief Update the mainstore VPD to specify a memory address range for
+ * UE areas. More than one address range can be added. Added for
+ * bi01.
+ *
+ * @post An address range entry has been added.
+ *
+ * @param[in] i_addr - The starting address of the range
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addUEAddrRange(hdatMsAddr_t &i_addr);
+
+ /**
+ * @brief Update the mainstore VPD to specify a memory address range for
+ * host boot reserver.
+ *
+ * @post An address range entry has been added.
+ *
+ * @param[in] i_dbobId - DBOB ID
+ * @param[in] i_start - The starting address of the range
+ * @param[in] i_end - The end address of the range
+ * @param[in] i_labelSize - RHB Label Size
+ * @param[in] i_labelStringPtr - RHB Label String
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_ARRAY_ERROR
+ */
+
+ errlHndl_t addRHBAddrRange( uint32_t i_dbob_id, hdatMsAddr_t &i_start,
+ hdatMsAddr_t &i_end, uint32_t i_labelSize,
+ uint8_t* &i_labelStringPtr);
+
+ /**
+ * @brief Update the mainstore VPD with Barrier Synchronization Register
+ * information
+ *
+ * Note: If the Barrier Synchronization Register is NOT enabled, this
+ * method does not have to be called.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[in] i_bsrAddr - Address of memory mapped BSR
+ * @param[in] i_bsrMode - Mode the BSR is initialized to
+ */
+ void setBSR(const hdatMsAddr_t &i_bsrAddr,
+ hdatBsrMode i_bsrMode = HDAT_BSR_128_BYTE);
+
+
+ /**
+ * @brief Update the mainstore VPD with address of XSCOM
+ *
+ * Note: If the XSCOM address is NOT supported, this
+ * method does not have to be called.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[in] i_xscomAddr - Address of XSCOM address range
+ */
+ void setXSCOM(const hdatMsAddr_t &i_xscomAddr);
+
+
+ /**
+ * @brief Add a main store area FRU.
+ *
+ * Each main store area FRU which contains memory must be added to the
+ * HdatMsVpd object. This method adds information about the FRU.
+ *
+ * @pre One cannot add any more mainstore area FRUs than was specified
+ * by the i_msAreaCnt parameter on the HdatMsVpd constructor.
+ *
+ * @post A main store area FRU has been added to the object.
+ * Heap storage has been allocated.
+ *
+ * @param[in] i_resourceId - The FRU's resource id
+ * @param[in] i_msAreaId - A unique id for each main store area
+ * associated with a mainstore VPD object. The id starts at
+ * 0 and is incremented by 1 for each new
+ * mainstore area.
+ * @param[in] i_ramCnt - The number of RAM objects that will be
+ * added to the mainstore area. If an exact count
+ * cannot be computed, a maximum number can be
+ * provided.
+ * @param[in] i_chipEcCnt - The number of EC entries that will be
+ * added to the mainstore area. If an exact count cannot be
+ * computed, a maximum number can be provided.
+ * @param[in] i_addrRngCnt - The number of address range entries that
+ * will be added to the mainstore area. If an
+ * exact count cannot be computed, a maximum
+ * number can be provided.
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addMsAreaFru(uint32_t i_resourceId,
+ uint32_t i_slcaIndex,
+ TARGETING::Target * i_target,
+ uint16_t i_msAreaId,
+ uint32_t i_ramCnt,
+ uint32_t i_chipEcCnt,
+ uint32_t i_addrRngCnt);
+
+
+ /**
+ * @brief Update the mainstore area to specify the type of memory.
+ *
+ * @pre The i_msAreaId parameter must be for a valid mainstore area that
+ * was added with the addMsAreaFru() method. HDAT does not check or
+ * enforce that this is a valid main store area ID.
+ *
+ * @post None
+ *
+ * @param[in] i_msAreaId - A unique id for each main store area
+ * associated with a mainstore VPD object. The id
+ * identifies the mainstore area that is to be
+ * updated.
+ * @param[in] i_type - This specifies the type of memory card
+ * for this mainstore area.
+ */
+ void setMsAreaType(uint16_t i_msAreaId,
+ hdatMemParentType i_type);
+
+
+ /**
+ * @brief Update the mainstore area to specify the status of the memory
+ * DIMMS
+ *
+ * @pre The i_msAreaId parameter must be for a valid mainstore area that
+ * was added with the addMsAreaFru() method.HDAT does not check or
+ * enforce that this is a valid main store area ID.
+ *
+ * @post None
+ *
+ * @param[in] i_msAreaId - A unique id for each main store area
+ * associated with a mainstore VPD object. The id
+ * identifies the mainstore area that is to be updated.
+ * @param[in] i_status - See the hdatMsAreaStatus enum. The value
+ * specified here can be a bitwise OR of the enum
+ * values.
+ */
+ void setMsAreaStat(uint16_t i_msAreaId,
+ uint16_t i_status);
+
+
+ /**
+ * @brief Update the mainstore area with an id for interleaved memory
+ *
+ * @pre The i_msAreaId parameter must be for a valid mainstore area that
+ * was added with the addMsAreaFru() method.HDAT does not check or
+ * enforce that this is a valid main store area ID.
+ *
+ * @post None
+ *
+ * @param[in] i_msAreaId - A unique id for each main store area
+ * associated with a mainstore VPD object. The id
+ * identifies the mainstore area that is to be updated
+ * @param[in] i_id - An identifier from 0 to N which is the same
+ * for each MS area which is interleaved. In
+ * addition, the HDAT_MEM_SHARED status attribute
+ * must have been used for this
+ * MS area when setMsAreaStat() was called.
+ */
+ void setMsAreaInterleavedId(uint16_t i_msAreaId,
+ uint16_t i_id);
+
+
+ /**
+ * @brief Update the mainstore area to specify the total size of the
+ * mainstore area.
+ *
+ * @pre The i_msAreaId parameter must be for a valid mainstore area that
+ * was added with the addMsAreaFru() method. HDAT does not check or
+ * enforce that this is a valid main store area ID.
+ *
+ * @post None
+ *
+ * @param[in] i_msAreaId - A unique id for each main store area
+ * associated with a mainstore VPD object. The id
+ * identifies the mainstore area that is to be
+ * updated.
+ * @param[in] i_size - The total size of the configured mainstore
+ * area in megabytes. It is the (high address of
+ * the mainstore area + 1 minus the low address of
+ * the mainstore area) divided by 1 megabyte.
+ */
+ void setMsAreaSize(uint16_t i_msAreaId,
+ uint32_t i_size);
+
+
+ /**
+ * @brief Update the mainstore area to specify associated processor id
+ *
+ * @pre The i_msAreaId parameter must be for a valid mainstore area that
+ * was added with the addMsAreaFru() method. HDAT does not check or
+ * enforce that this is a valid main store area ID.
+ *
+ * @post None
+ *
+ * @param[in] i_msAreaId - A unique id for each main store area
+ * associated with a mainstore VPD object.
+ * The id identifies the mainstore area that is
+ * to be updated.
+ * @param[in] i_moduleId - The Module Id of the processor
+ * associated with this mainstore area.
+ */
+ void setMsAreaModuleId(uint16_t i_msAreaId,
+ uint32_t i_moduleId);
+
+
+ /**
+ * @brief Update the mainstore area to specify the affinity domain
+ *
+ * @pre The i_msAreaId parameter must be for a valid mainstore area that
+ * was added with the addMsAreaFru() method. HDAT does not check or
+ * enforce that this is a valid main store area ID.
+ *
+ * @post None
+ *
+ * @param[in] i_msAreaId - A unique id for each main store area
+ * associated with a mainstore VPD object.
+ * The id identifies the mainstore area that is
+ * to be updated.
+ * @param[in] i_affinityDomain - The affinity domain
+ * associated with this mainstore area.
+ */
+ void setMsAreaAffinityDomain(uint16_t i_msAreaId,
+ uint32_t i_affinityDomain);
+
+
+ /**
+ * @brief Update the mainstore area to specify the memory address range
+ * More than one address range can be added.
+ *
+ * @pre The i_msAreaId parameter must be for a valid mainstore area that
+ * was added with the addMsAreaFru() method. HDAT does not check or
+ * enforce that this is a valid main store area ID.
+ *
+ * @post None
+ *
+ * @param[in] i_msAreaId - A unique id for each main store area
+ * associated with a mainstore VPD object. The id
+ * identifies the mainstore area that is to be
+ * updated.
+ * @param[in] i_start - The starting address of the range
+ * @param[in] i_end - The ending address of the range + 1
+ * @param[in] i_procChipId - which is the chip id of the physical
+ * processor
+ * @param[in] i_rangeIsMirrorable - Specifies whether the range is
+ * mirrorable
+ * @param[in] i_mirroringAlgorithm - Specifies hardware mirroring
+ * algorithm to use
+ * @param[in] i_startMirrAddr - Specifies the starting mirrorable
+ * address for range
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addMsAreaAddr(uint16_t i_msAreaId,
+ hdatMsAddr_t &i_start,
+ hdatMsAddr_t &i_end,
+ uint32_t i_procChipId,
+ bool i_rangeIsMirrorable = false,
+ uint8_t i_mirroringAlgorithm = 0,
+ uint64_t i_startMirrAddr = 0);
+
+
+ /**
+ * @brief Add engineering change information for memory interface chips
+ *
+ * @pre The first EC entry added must be for the memory controller.
+ * HDAT has no way of validating or enforcing this so it is up to the
+ * user of the method to do this correctly.
+ *
+ * The i_msAreaId parameter must be for a valid mainstore area that
+ * was added with the addMsAreaFru() method.HDAT does not check or
+ * enforce that this is a valid main store area ID.
+ *
+ * @post One cannot add any more engineering change entries than was
+ * specified by the i_chipEcCnt parameter on the addMsAreaFru method.
+ *
+ * @param[in] i_msAreaId -A unique id for each main store area
+ * associated with a mainstore VPD object. The id
+ * identifies the mainstore area that is to be
+ * updated.
+ * @param[in] i_manfId - Chip's manufacturing id
+ * @param[in] i_ecLvl - Chip's engineering change level
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addEcEntry(uint16_t i_msAreaId,
+ uint32_t i_manfId,
+ uint32_t i_ecLvl);
+
+
+ /**
+ * @brief Add a RAM area FRU.
+ *
+ * After a mainstore area has been added to the mainstore VBPD object,
+ * one or more RAM FRUs must be added to the mainstore area.
+ *
+ * @pre A mainstore area must have been previously created so this RAM
+ * area can be added to it.
+ *
+ * The i_msAreaId parameter must be for a valid mainstore area that
+ * was added with the addMsAreaFru() method. HDAT does not check
+ * or enforce that this is a valid main store area ID.
+ *
+ * @post A RAM card's VPD definiton has been added to the object. Heap
+ * storage has been allocated.
+ *
+ * @param[in] i_msAreaId - The id of the mainstore area this
+ * RAM is associated with
+ * @param[in] i_resourceId - VPD resource ID for the RAM FRU.
+ * @param[in] i_slcaIndex - SLCA index of ms area
+ * @param[in] i_ramId - RAM area identifier; a number from 0 to N
+ * @param[in] i_status - staus of the DIMMS and is the bitwise OR of
+ * values from hdatRamStatus defined above
+ * @param[in] i_size -the total size of configured mainstore in this
+ * RAM area
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t addRamFru(uint16_t i_msAreaId,
+ TARGETING::Target * i_target,
+ uint32_t i_resourceId,
+ uint32_t i_slcaIndex,
+ uint16_t i_ramId,
+ uint16_t i_status,
+ uint32_t i_size);
+ /**
+ * @brief Initialization of HdatMsVpd object.
+ *
+ * If you are constructing this object on the heap by using new, then
+ * you must check the pointer returned from new to see if it is null.
+ * If it is null, new failed to allocate storage and the constructor
+ * was not called. If it is not null, then you must check o_errlHndl
+ * to see if the constructor ran successfully. If o_errlHndl indicates
+ * an error was reported by the constructor, new has already allocated
+ * heap storage and the object must be deleted in order to free the
+ * heap storage.
+ *
+ * @pre None
+ *
+ * @post An HdatMsVpd object has been initialized. Heap storage has
+ * been allocated.
+ *
+ * @param[in] i_maxMsAddr - maximum configured main store address
+ * @param[in] i_maxMsCcmAddr - maximum main store address that could be
+ * configured if memory was added with
+ * concurrent maintenance.If concurrent
+ * maintenance cannot be performed on this
+ * machine,this parameter has the same value as
+ * i_maxMsAddr.
+ * @param[in] i_msSize - total size of configured main store in
+ * mega-bytes. (number of mega-bytes from lowest
+ * main store address to highest main store
+ * address minus the number of mega-bytes of a
+ * ddress holes)
+ * @param[in] i_msAreaCnt The count of the number of main store areas
+ * that will be defined by using the
+ * addMsAreaFru() method below.If the actual
+ * count cannot be derived when this object is
+ * constructed, a maximum count can be supplied.
+ * @param[in] i_MostSigAffinityDomain -most significant affinity domain.
+ * The affinity domain considered most important
+ * when making affinity decisions. The value is
+ * model dependent.
+ * @param[in] i_ueAreaCnt - Maximum number of UE Address ranges
+ * @param[in] i_MirrMemStartAddr - The address of the start of
+ * mirrorable memory
+ *
+ */
+ void hdatInit(hdatMsAddr_t &i_maxMsAddr,
+ hdatMsAddr_t &i_maxMsCcmAddr,
+ uint32_t i_msSize,
+ uint32_t i_msAreaCnt,
+ uint32_t i_MostSigAffinityDomain,
+ uint32_t i_ueAreaCnt,
+ uint64_t i_MirrMemStartAddr);
+
+ /**
+ * @brief Gather MS data for HDAT
+ * @par Description:
+ * This function collects various MS attributes and fills MS Data area
+ *
+ * @param[in] o_size - total size written
+ * @param[in] o_count - total count of ms vpd instance
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_ARRAY_ERROR
+ */
+ errlHndl_t hdatLoadMsData(uint32_t &o_size, uint32_t &o_count);
+
+ /**
+ * @brief Gets maximum configured memory address
+ *
+ *
+ * @return value of ms address
+ */
+ uint64_t hdatGetMaxMemConfiguredAddress();
+
+ /**
+ * @brief Fetches the group of MC
+ *
+ * @param[in] i_pTarget Proc target
+ * @param[in] i_pMcsTarget MCS target
+ * @param[out] o_groupOfMc MC group value
+ *
+ * @return Success or failure
+ */
+ bool hdatFindGroupForMc(const TARGETING::Target *i_pProcTarget,
+ const TARGETING::Target *i_pMcsTarget,
+ uint32_t& o_groupOfMc);
+
+ /**
+ * @brief Get the DIMMS list present on the system
+ *
+ * @param[in] i_pTarget Mcs target
+ * @param[in] i_membufFruid - membuf fruid decides the parent type
+ * @param[out] o_areas list of ram area structure based on the DIMM
+ * present.
+ * @param[out] o_areaSize - Total DIMM size
+ * @param[out] o_dimmNum - Total DIMM number
+ * @param[out] o_areaFunctional - DIMM functional status
+ * @param[out] o_parentType - memory parent type based on whether
+ * the dimms are pluggable or soldered
+ *
+ * @return A null error log handle if successful, else the return the
+ * error handle
+ */
+ errlHndl_t hdatScanDimms(const TARGETING::Target *i_pTarget,
+ uint32_t i_membufFruid,
+ std::list<hdatRamArea>& o_areas,
+ uint32_t& o_areaSize,
+ uint32_t& o_dimmNum,
+ bool& o_areaFunctional,
+ hdatMemParentType& i_parentType);
+
+ /**
+ * @brief Get max memory blocks connected to membuf
+ *
+ * @param[in] i_pTarget Mcs target
+ * @param[out] o_maxMemoryBlocks - max memory block value
+ *
+ * @return A null error log handle if successful, else the return the
+ * error handle
+ */
+ errlHndl_t hdatGetMaxMemoryBlocks(const TARGETING::Target *i_pTarget,
+ uint32_t &o_maxMemoryBlocks);
+
+ /**
+ * @brief Write the data to Mainstore area space
+ *
+ * @param[in] i_addr - MS address
+ * @param[in] i_size - total size to be written
+ *
+ */
+ void commit(void * i_addr,uint32_t i_size);
+
+ /**
+ * @brief Get total size of MS data to be written
+ *
+ * @param[out] o_size - total size value
+ *
+ */
+ void getTotalSize(uint32_t &o_size);
+
+ /**
+ * @brief Print an HdatMsVpd object.
+ *
+ * This method is a debug mthod which prints out a mainstore VPD object.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ */
+ void prt();
+
+ protected:
+
+ /**
+ * @brief After all MS area objects have been created, this routine must
+ * be called to see if they are all the same size.If they are not, the
+ * smaller one(s) will be adjusted with padding so they are all
+ * the same size.
+ *
+ * This is required because PHYP traverses through the MS areas
+ * as entries in an array.
+ *
+ * @pre All MS area objects must have been created
+ *
+ * @post Some objects' size may be adjusted
+ *
+ */
+ void adjustMsAreaObjects();
+
+
+ private:
+
+
+ /** Object Instance Data
+ *
+ * @li iv_msAddr - main memory address the final data structure is
+ * DMA'd to
+ * @li iv_actMsAreaCnt - actual count of main store areas that are added
+ * @li iv_maxMsAreaCnt - maximum count of main store areas that can be
+ * added
+ * @li iv_maxAddr - maximum main store addresses
+ * @li iv_maxSize - maximum main store size
+ * @li iv_mover - page mover information
+ * @li iv_msAreaPtrs - ptr to one or more ptrs which in turn point to
+ * HdatMsArea objects
+ * @li iv_IMTaddrRngArrayHdr - In memory trace address range header
+ * @li iv_IMTaddrRangeArray - In memory trace address range array
+ * @li iv_UEaddrRngArrayHdr - UE address range header
+ * @li iv_UEaddrRangeArray - UE address range array
+ * @li iv_maxUEAddrRngCnt - Max UE address range count
+ * @li iv_RHBaddrRngArrayHdr - Reserved host boot address range header
+ * @li iv_RHBaddrRangeArray - Reserved host boot address range array
+ * @li iv_maxRHBAddrRngCnt - Max RHB address range count
+ * @li iv_virtAddr - virtual address
+ */
+ hdatMsAddr_t iv_msAddr;
+ uint32_t iv_actMsAreaCnt;
+ uint32_t iv_maxMsAreaCnt;
+ hdatMsVpdAddr_t iv_maxAddr;
+ hdatMsVpdSize_t iv_maxSize;
+ hdatMsVpdPageMover_t iv_mover;
+ HdatMsArea **iv_msAreaPtrs;
+ hdatHDIFDataArray_t iv_IMTaddrRngArrayHdr;
+ hdatMsVpdImtAddrRange_t *iv_IMTaddrRangeArray;
+ uint32_t iv_maxIMTAddrRngCnt;
+ hdatHDIFDataArray_t iv_UEaddrRngArrayHdr;
+ hdatMsVpdUEAddrRange_t *iv_UEaddrRangeArray;
+ uint32_t iv_maxUEAddrRngCnt;
+ hdatHDIFDataArray_t iv_RHBaddrRngArrayHdr;
+ hdatMsVpdRhbAddrRange_t *iv_RHBaddrRangeArray;
+ uint32_t iv_maxRHBAddrRngCnt;
+ void *iv_virtAddr;
+
+
+ /** Class (static) Data
+ *
+ * Only one copy of this data exists in a process.
+ *
+ * @li cv_actualCnt - a count of how many HdatMsVpd objects are created
+ */
+ static uint32_t cv_actualCnt;
+
+}; // end of HdatMsVpd class
+
+}
+
+#endif // HDATMSVPD_H
diff --git a/src/usr/hdat/hdatnaca.C b/src/usr/hdat/hdatnaca.C
new file mode 100644
index 000000000..6ad0e9307
--- /dev/null
+++ b/src/usr/hdat/hdatnaca.C
@@ -0,0 +1,228 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatnaca.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 <hdat/hdatnaca.H>
+#include "hdatspiraH.H"
+#include <hdat/hdat.H>
+#include "hdatspiraS.H"
+#include "hdatutil.H"
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include <targeting/common/util.H>
+#include <initservice/initserviceif.H>
+
+using namespace TARGETING;
+
+namespace HDAT
+{
+extern trace_desc_t *g_trac_hdat;
+
+errlHndl_t hdatGetNacaFromMem(hdatNaca_t &o_naca)
+{
+ HDAT_ENTER();
+ errlHndl_t l_errl = NULL;
+ void* l_virtualAddress = NULL;
+ do
+ {
+ // Get Target Service, and the system target.
+ TargetService& l_targetService = targetService();
+ TARGETING::Target* l_sysTarget = NULL;
+ (void) l_targetService.getTopLevelTarget(l_sysTarget);
+
+ assert(l_sysTarget != NULL);
+
+ uint64_t l_hrmor = l_sysTarget->getAttr<ATTR_PAYLOAD_BASE>() * MEGABYTE;
+
+ // Mapping the uncompressed region. HDAT areas are at the hrmor address
+ // + the naca offset so we are reading the entire area of 256 MB.
+ l_virtualAddress = mm_block_map(reinterpret_cast<void*>(l_hrmor),
+ l_hrmor );
+
+ // Reading the data at hrmor + Naca offset
+ hdatNaca_t* l_naca = reinterpret_cast<hdatNaca_t*>(
+ reinterpret_cast<uint64_t>(l_virtualAddress) +
+ HDAT_NACA_OFFSET);
+
+ if( l_naca == NULL)
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_NACA_GET_MEM
+ * @reasoncode HDAT::RC_INVALID_NACA
+ * @devdesc map a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errl,
+ MOD_NACA_GET_MEM,
+ RC_INVALID_NACA,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ break;
+ }
+
+ memcpy(&o_naca, l_naca, sizeof(hdatNaca_t));
+ }while(0);
+
+ if ( l_virtualAddress != NULL )
+ {
+ int rc = 0;
+ rc = mm_block_unmap(l_virtualAddress);
+ if( rc != 0)
+ {
+
+ errlHndl_t l_errl = NULL;
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_NACA_GET_MEM
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errl,
+ MOD_NACA_GET_MEM,
+ RC_DEV_MAP_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+ }
+ return l_errl;
+}
+
+/**************************************************************/
+//hdatGetCpuCtrlFromMem
+/**************************************************************/
+
+void hdatGetCpuCtrlFromMem(hdatMsAddr_t i_msAddr, uint32_t i_size)
+{
+ HDAT_ENTER();
+ hdatMsAddr_t l_addr;
+ hdatCpuCtrlArea_t l_cpuCtrl;
+ hdatSvcRoutines_t l_svcRtn;
+
+ uint64_t l_baddr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo;
+
+ memcpy(&l_cpuCtrl, &l_baddr,i_size);
+
+ TRACFBIN(g_trac_hdat,"Read Cpu Ctrl area",&l_cpuCtrl,i_size);
+
+ l_addr.hi = l_cpuCtrl.hdatSR[HDAT_SVC_RTNS].hdatSsrPtr.hi;
+ l_addr.lo = l_cpuCtrl.hdatSR[HDAT_SVC_RTNS].hdatSsrPtr.lo;
+
+ l_baddr = ((uint64_t) l_addr.hi << 32) | l_addr.lo;
+
+ memcpy(&l_svcRtn,&l_baddr,sizeof(hdatSvcRoutines_t));
+
+ TRACFBIN(g_trac_hdat,"Read Svc Routine Area",&l_svcRtn,
+ sizeof(hdatSvcRoutines_t));
+
+ HDAT_EXIT();
+}
+
+/**************************************************************/
+//call_hdat_steps
+/**************************************************************/
+void * call_hdat_steps( void *io_pArgs )
+{
+ HDAT_ENTER();
+
+ errlHndl_t l_errlHndl=NULL;
+ hdatMsAddr_t i_msAddr,l_cpuAddr;
+ hdat5Tuple_t l_spirasHostEntry, l_spirhCpuCtrlEntry;
+ do {
+
+ //true => FSP present. OR ! running on PHYP mode
+ if(INITSERVICE::spBaseServicesEnabled() || !(is_phyp_load()))
+ {
+ break;
+ }
+
+ hdatNaca_t l_naca;
+ l_errlHndl = hdatGetNacaFromMem(l_naca);
+
+ if ( l_errlHndl )
+ {
+ HDAT_ERR("could not get NACA from memory");
+ l_errlHndl->addFFDC(HDAT_COMP_ID,AT,sizeof(AT),
+ HDAT_VERSION1,HDAT_NACA_FFDC_SUBSEC1);
+ break;
+ }
+
+ i_msAddr.lo = l_naca.nacaOpalMasterThreadEntry.lo;
+ i_msAddr.hi = l_naca.nacaOpalMasterThreadEntry.hi;
+
+ HDAT_DBG("creating SPIRA-H with address hi=%x, lo=%x",
+ i_msAddr.hi,i_msAddr.lo);
+ HdatSpiraH l_spirah(l_errlHndl, i_msAddr);
+
+ l_spirah.getSpiraHEntry(HDAT_SEC_CPU_CTRL,l_spirhCpuCtrlEntry);
+ l_cpuAddr.hi = l_spirhCpuCtrlEntry.hdatAbsAddr.hi;
+ l_cpuAddr.lo = l_spirhCpuCtrlEntry.hdatAbsAddr.lo;
+
+ HDAT_DBG("CPU controls structures at 0x%08x",l_cpuAddr.lo);
+ hdatGetCpuCtrlFromMem(l_cpuAddr,sizeof(hdatCpuCtrlArea_t));
+
+ //add for dump header later
+
+ l_spirah.getSpiraHEntry(HDAT_SEC_HOST_DATA_AREA,l_spirasHostEntry);
+ HDAT_DBG("got spiras addrss from SPIRAH hi=%x,lo=%x",
+ l_spirasHostEntry.hdatAbsAddr.hi,
+ l_spirasHostEntry.hdatAbsAddr.lo);
+ HDAT_DBG("creating all data areas through spiras");
+
+
+ HDAT_DBG("l_spirasHostEntry.hdatAbsAddr.lo=0x%x",
+ l_spirasHostEntry.hdatAbsAddr.lo);
+
+ HdatSpiraS l_spiras (l_spirasHostEntry.hdatAbsAddr);
+
+ uint32_t l_hostAreaCnt=0, l_hostAreaSize=0;
+
+ l_errlHndl = l_spiras.loadDataArea(l_spirasHostEntry,
+ l_hostAreaCnt,l_hostAreaSize);
+ HDAT_DBG("got back total size from spiras=0x%x",l_hostAreaSize);
+
+ if ( l_errlHndl )
+ {
+ HDAT_ERR("could not create all data areas");
+ l_errlHndl->addFFDC(HDAT_COMP_ID,AT,sizeof(AT),
+ HDAT_VERSION1,HDAT_NACA_FFDC_SUBSEC2);
+ break;
+ }
+
+ l_spirah.chgSpiraHEntry(HDAT_SEC_HOST_DATA_AREA,
+ l_hostAreaCnt,l_hostAreaSize);
+
+ HDAT_DBG("loaded all data areas successfully");
+
+ }while(0);
+
+ HDAT_EXIT();
+ return NULL;
+}
+
+} //namespace HDAT
diff --git a/src/usr/hdat/hdatnodedata.C b/src/usr/hdat/hdatnodedata.C
new file mode 100755
index 000000000..6e735b9f4
--- /dev/null
+++ b/src/usr/hdat/hdatnodedata.C
@@ -0,0 +1,144 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatnodedata.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+/**
+ * @file hdatnodedata.C
+ *
+ * @brief This file contains the implementation of the HdatNodedata class.
+ *
+ */
+
+/*-----------------------------------------------------------------------------*/
+/* Includes */
+/*-----------------------------------------------------------------------------*/
+
+#include <stdlib.h> // malloc & free
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include <util/align.H>
+#include "hdatnodedata.H" // HdatNodedata class definition
+#include "hdathdif.H"
+#include "hdatutil.H"
+#include "hdatvpd.H"
+#include <targeting/common/util.H>
+
+using namespace HDAT;
+namespace HDAT
+{
+/*-----------------------------------------------------------------------------*/
+/* Global variables */
+/*-----------------------------------------------------------------------------*/
+extern trace_desc_t *g_trac_hdat;
+uint32_t HdatNodedata::cv_actualCnt;
+
+/** @brief See the prologue in hdatnodedata.H
+ */
+HdatNodedata::HdatNodedata(errlHndl_t &o_errlHndl,
+ uint64_t &io_msAddr,
+ const char *i_eyeCatcher,
+ uint32_t &o_NodeStructSize)
+: HdatHdif(o_errlHndl, i_eyeCatcher, HDAT_NODE_DATA_LAST,
+cv_actualCnt++, HDAT_NO_CHILD, HDAT_NODE_DATA_VERSION)
+{
+ HDAT_ENTER();
+ o_errlHndl = NULL;
+
+ // Copy the mainstore address to object variable
+ iv_msAddr = io_msAddr;
+
+ // Total size of Node Data
+ iv_size = sizeof(hdatHDIF_t) +
+ ( sizeof(hdatHDIFDataHdr_t) *
+ HDAT_NODE_DATA_LAST)+
+ HDAT_NODE_ATTR_DATA_SIZE + 0x08; // padding as per spec
+
+ // Create a virtual address mapping
+ uint64_t l_base_addr_down = ALIGN_PAGE_DOWN((uint64_t)iv_msAddr);
+ iv_virt_addr =(uint8_t *) mm_block_map (
+ reinterpret_cast<void*>(l_base_addr_down),
+ (ALIGN_PAGE(iv_size) + PAGESIZE));
+ iv_hdatNodeData = iv_virt_addr +
+ ((uint64_t)iv_msAddr - ALIGN_PAGE_DOWN((uint64_t)iv_msAddr));
+
+ o_NodeStructSize = iv_size;
+
+ // Copy the end adress back to input pointer for next node use
+ io_msAddr += iv_size;
+
+ HDAT_EXIT();
+ return;
+}
+
+
+/** @brief See the prologue in HdatNodedata.H
+ */
+errlHndl_t HdatNodedata::setNodeData()
+{
+ HDAT_ENTER();
+ errlHndl_t o_errlHndl=NULL;
+
+ // Add the internal pointer Data
+ this->addData(HDAT_NODE_ATTRIBUTE, HDAT_NODE_ATTR_DATA_SIZE);
+ this->align();
+
+ // initializing the space to zero
+ memset(iv_hdatNodeData ,0x0, iv_size );
+
+ iv_hdatNodeData = this->setHdif(iv_hdatNodeData);
+
+ iv_hdatNodeData += HDAT_NODE_ATTR_DATA_SIZE;
+
+ HDAT_EXIT();
+ return o_errlHndl;
+}
+
+HdatNodedata::~HdatNodedata()
+{
+ HDAT_ENTER();
+
+ errlHndl_t o_errlHndl=NULL;
+ uint32_t rc = mm_block_unmap(reinterpret_cast<void*>(
+ ALIGN_PAGE_DOWN((uint64_t)iv_virt_addr)));
+ if( rc != 0)
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_HDAT_NODEDATA_DTOR
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(o_errlHndl,
+ HDAT::MOD_HDAT_NODEDATA_DTOR,
+ RC_DEV_MAP_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+ HDAT_EXIT();
+
+}
+
+}// HDAT namespace
diff --git a/src/usr/hdat/hdatnodedata.H b/src/usr/hdat/hdatnodedata.H
new file mode 100755
index 000000000..58adb1256
--- /dev/null
+++ b/src/usr/hdat/hdatnodedata.H
@@ -0,0 +1,179 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatnodedata.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATNODEDATA_H
+#define HDATNODEDATA_H
+
+/**
+ * @file hdatvpd.H
+ *
+ * @brief This file contains the class definition for the Host service node data object constructed
+ *
+ */
+
+/*-----------------------------------------------------------------------------*/
+/* Includes */
+/*-----------------------------------------------------------------------------*/
+#include <stdint.h> // standard types
+#include "hdathdif.H" // HdatHdif base class definition
+#include <hdat/hdat.H>
+
+/*-----------------------------------------------------------------------------*/
+/* Constants
+*/
+/*-----------------------------------------------------------------------------*/
+#define HDAT_NODE_ATTR_DATA_SIZE 256000
+
+const uint16_t HDAT_NODE_DATA_VERSION = 0x0010;
+
+
+/** @enum hdatDataPtrs
+ * Constants for the internal data pointers that are added to the base
+ * class
+ */
+enum hdatDataPtrs
+{
+ HDAT_NODE_ATTRIBUTE = 0,
+ HDAT_NODE_DATA_LAST = 1
+};
+
+/*-----------------------------------------------------------------------------*/
+/* Type definitions */
+/*-----------------------------------------------------------------------------*/
+
+using namespace HDAT;
+
+/*-----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*-----------------------------------------------------------------------------*/
+namespace HDAT
+{
+
+ /** Begin Class Description
+ *
+ * @brief The HdatNodedata class
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that anyone can create an object of this type. In particular,
+ * the object is built only in the hdatstep process when the step
+ * that builds hypervisor data structures is run.
+ *
+ * Thread safety: An HdatNodedata object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by
+ * multiple threads at the same time. An object can be used by
+ * multiple threads if the threads serialize access. And of
+ * course, each thread can use its own object with no concerns
+ * about what other threads are doing.
+ *
+ * Signal handler usage: This class is not intended to be used in a signal handler
+ * and nothing has been done to try and make it safe to use
+ * in a signal handler.
+ *
+ * End Class Description
+ */
+ class HdatNodedata : public HdatHdif
+ {
+ public:
+
+ /**
+ * @brief Construct an HdatNodedata object.
+ *
+ * This is the constructor for the HdatNodedata object.
+ *
+ * If you are constructing this object on the heap by using new, then
+ * you must check the pointer returned from new to see if it is null.
+ * If it is null, new failed to allocate storage and the constructor
+ * was not called. If it is not null, then you must check o_errlHndl
+ * to see if the constructor ran successfully. If o_errlHndl indicates
+ * an error was reported by the constructor, new has already allocated
+ * heap storage and the object must be deleted in order to free the
+ * heap storage.
+ *
+ * @pre None
+ *
+ * @post An HdatNodedata object has been constructed. Heap storage has been allocated.
+ *
+ * @param o_errlHndl - output parameter - If any errors occur, the HdatNodedata object
+ * is NOT constructed and errors are returned in this parameter
+ * @param io_msAddr - input output parameter - The main memory address
+ * @param i_eyeCatcher - input parameter - A character string to put in the structure's
+ * eye catcher field.
+ * @param o_NodeStructSize- Whole Node Data structure size
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+ HdatNodedata(errlHndl_t &o_errlHndl,
+ uint64_t &io_msAddr,
+ const char *i_eyeCatcher,
+ uint32_t &o_NodeStructSize);
+
+
+ /**
+ * @brief HdatNodedata object destructor
+ *
+ * This is the destructor for an HdatNodedata object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+
+ * @post The HdatNodedata object has been destroyed and can no longer be used.
+ *
+ */
+ virtual ~HdatNodedata();
+ errlHndl_t setNodeData();
+
+ /** Class (static) Data
+ *
+ * Only one copy of this data exists in a process.
+ *
+ * @li cv_actualCnt - a count of how many HdatNodedata objects are created
+ */
+ static uint32_t cv_actualCnt;
+
+ private:
+
+ /** Object Instance Data
+ *
+ * @li iv_msAddr - main store address the structure need to be copied to
+ * @li iv_hdatNodeData - Pointer to Node Data
+ * @li iv_virt_addr - Pointr to hold virtual address post mem map.
+ * @li iv_nodeAttritbuteData - Pointer to internal Data pointer
+ * @li iv_size - Size of the Node data
+ */
+ uint64_t iv_msAddr;
+ uint8_t * iv_hdatNodeData;
+ uint8_t * iv_virt_addr;
+ uint8_t *iv_nodeAttritbuteData;
+ uint64_t iv_size;
+
+}; // end of HdatNodedata class
+
+
+}//HDAT
+
+#endif // HDATNODEDATA_H
+
diff --git a/src/usr/hdat/hdatpcia.C b/src/usr/hdat/hdatpcia.C
new file mode 100644
index 000000000..129d80878
--- /dev/null
+++ b/src/usr/hdat/hdatpcia.C
@@ -0,0 +1,626 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatpcia.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 <sys/mm.h>
+#include <sys/mmio.h>
+#include "hdatpcia.H"
+#include <targeting/common/util.H>
+#include <util/align.H>
+
+using namespace TARGETING;
+
+namespace HDAT
+{
+extern trace_desc_t *g_trac_hdat;
+
+/*******************************************************************************
+* hdatSetPciaHdrs
+*
+* @brief Routine initializes HDIF headers for a PCIA array entry
+*
+* @pre None
+*
+* @post None
+*
+* @param[in] i_pcia
+* The iv_spPcia array element to operate on
+*
+* @return A null error log handle if successful, Currently can't fail.
+*
+*******************************************************************************/
+static errlHndl_t hdatSetPciaHdrs(hdatSpPcia_t *i_pcia)
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ i_pcia->hdatHdr.hdatStructId = HDAT_HDIF_STRUCT_ID;
+ i_pcia->hdatHdr.hdatInstance = 0;
+ i_pcia->hdatHdr.hdatVersion = HDAT_PCIA_VERSION;
+ i_pcia->hdatHdr.hdatSize = sizeof(hdatSpPcia_t);
+ i_pcia->hdatHdr.hdatHdrSize = sizeof(hdatHDIF_t);
+ i_pcia->hdatHdr.hdatDataPtrOffset = sizeof(hdatHDIF_t);
+ i_pcia->hdatHdr.hdatDataPtrCnt = HDAT_PCIA_DA_CNT;
+ i_pcia->hdatHdr.hdatChildStrCnt = 0;
+ i_pcia->hdatHdr.hdatChildStrOffset = 0;
+
+ memcpy(i_pcia->hdatHdr.hdatStructName, HDAT_PCIA_STRUCT_NAME,
+ sizeof(i_pcia->hdatHdr.hdatStructName));
+ i_pcia->hdatPciaIntData[HDAT_PCIA_DA_COREDATA].hdatOffset =
+ offsetof(hdatSpPcia_t, hdatCoreData);
+ i_pcia->hdatPciaIntData[HDAT_PCIA_DA_COREDATA].hdatSize =
+ sizeof(hdatPciaCoreUniqueData_t);
+ i_pcia->hdatPciaIntData[HDAT_PCIA_DA_CPU_TIME_BASE].hdatOffset =
+ offsetof(hdatSpPcia_t, hdatTime);
+ i_pcia->hdatPciaIntData[HDAT_PCIA_DA_CPU_TIME_BASE].hdatSize =
+ sizeof(hdatPciaCpuTimeBase_t);
+ i_pcia->hdatPciaIntData[HDAT_PCIA_DA_CACHE_SIZE].hdatOffset =
+ offsetof(hdatSpPcia_t, hdatCache);
+ i_pcia->hdatPciaIntData[HDAT_PCIA_DA_CACHE_SIZE].hdatSize =
+ sizeof(hdatPciaCacheSize_t);
+ i_pcia->hdatPciaIntData[HDAT_PCIA_DA_THREADDATA].hdatOffset =
+ offsetof(hdatSpPcia_t, hdatThreadData);
+ i_pcia->hdatPciaIntData[HDAT_PCIA_DA_THREADDATA].hdatSize =
+ sizeof(hdatPciaThreadUniqueData_t);
+ i_pcia->hdatPciaIntData[HDAT_PCIA_DA_CPU_ATTRIBUTES].hdatOffset =
+ offsetof(hdatSpPcia_t, hdatAttr);
+ i_pcia->hdatPciaIntData[HDAT_PCIA_DA_CPU_ATTRIBUTES].hdatSize =
+ sizeof(hdatPciaCpuAttributes_t);
+
+ return l_errlHndl;
+}
+
+/*******************************************************************************
+* PCIA Constructor
+*******************************************************************************/
+HdatPcia::HdatPcia(errlHndl_t &o_errlHndl, const hdatMsAddr_t &i_msAddr)
+: iv_numPciaEntries(0), iv_spPciaEntrySize(0), iv_spPcia(NULL)
+{
+ // Copy the main store address for the pcia data
+ memcpy(&iv_msAddr, &i_msAddr, sizeof(hdatMsAddr_t));
+
+ // We are using the CORE DATA section
+ iv_numPciaEntries = HDAT_NUM_P8_PCIA_ENTRIES;
+ iv_spPciaEntrySize = sizeof(hdatSpPcia_t);
+
+ // Allocate space for each CORE -- will use max amount to start
+ uint64_t l_base_addr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo;
+
+ void *l_virt_addr = mm_block_map (
+ reinterpret_cast<void*>(ALIGN_PAGE_DOWN(l_base_addr)),
+ (ALIGN_PAGE(iv_numPciaEntries*iv_spPciaEntrySize)+PAGESIZE));
+
+ l_virt_addr = reinterpret_cast<void *>(
+ reinterpret_cast<uint64_t>(l_virt_addr) +
+ (l_base_addr - ALIGN_PAGE_DOWN(l_base_addr)));
+
+ // initializing the space to zero
+ memset(l_virt_addr ,0x0, (iv_numPciaEntries*iv_spPciaEntrySize));
+
+ iv_spPcia = reinterpret_cast<hdatSpPcia_t *>(l_virt_addr);
+
+ HDAT_DBG("Constructor iv_spPcia addr 0x%016llX virtual addr 0x%016llX",
+ (uint64_t) this->iv_spPcia, (uint64_t)l_virt_addr);
+}
+
+/*******************************************************************************
+* hdatLoadPcia
+*******************************************************************************/
+errlHndl_t HdatPcia::hdatLoadPcia(uint32_t &o_size, uint32_t &o_count)
+{
+ errlHndl_t l_errl = NULL;
+
+ do
+ {
+ // PCIA index
+ uint32_t index = 0;
+
+ //Storing offset address for calculating the sizing of each PCIA
+ uint64_t l_offset = (uint64_t)&this->iv_spPcia[index];
+
+ // Get Max threads
+ ATTR_THREAD_COUNT_type l_coreThreadCount = 0;
+ Target* l_pTopLevel = NULL;
+ (void)TARGETING::targetService().getTopLevelTarget(l_pTopLevel);
+ if(NULL == l_pTopLevel)
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_PCIA_LOAD
+ * @reasoncode HDAT::RC_TOP_LVL_TGT_NOT_FOUND
+ * @devdesc Top level target not found
+ * @custdesc Firmware encountered an internal
+ * error while retrieving target data
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCIA_LOAD,
+ RC_TOP_LVL_TGT_NOT_FOUND,
+ 0,0,0,0);
+
+ HDAT_ERR("Error getting top level target");
+ break;
+ }
+
+ l_coreThreadCount = l_pTopLevel->getAttr<ATTR_THREAD_COUNT>();
+ uint32_t l_procStatus;
+ if ( l_coreThreadCount == HDAT_MAX_EIGHT_THREADS_SUPPORTED )
+ {
+ l_procStatus =
+ HDAT_PROC_NOT_INSTALLED | HDAT_PRIM_THREAD | HDAT_EIGHT_THREAD;
+ }
+ else if ( l_coreThreadCount == HDAT_MAX_FOUR_THREADS_SUPPORTED )
+ {
+ l_procStatus =
+ HDAT_PROC_NOT_INSTALLED | HDAT_PRIM_THREAD | HDAT_FOUR_THREAD;
+ }
+ else
+ {
+ l_procStatus =
+ HDAT_PROC_NOT_INSTALLED | HDAT_PRIM_THREAD | HDAT_TWO_THREAD;
+ }
+ //for each procs in the system
+ TARGETING::PredicateCTM l_procFilter(CLASS_CHIP, TYPE_PROC);
+ TARGETING::PredicateHwas l_pred;
+ l_pred.present(true);
+ TARGETING::PredicatePostfixExpr l_presentProc;
+ l_presentProc.push(&l_procFilter).push(&l_pred).And();
+
+ TARGETING::TargetRangeFilter l_filter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentProc);
+ for (;l_filter;++l_filter)
+ {
+ TARGETING::Target* l_pProcTarget = *l_filter;
+ uint32_t Procstatus = 0;
+
+ uint32_t l_procFabricId =
+ l_pProcTarget->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>();
+
+ uint64_t l_procIntrBase =
+ l_pProcTarget->getAttr<TARGETING::ATTR_INTP_BASE_ADDR>();
+
+ uint32_t l_procPosition =
+ l_pProcTarget->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
+
+ TARGETING::PredicateCTM l_corePredicate(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_CORE);
+
+ //Cores with partial good data are present and reported
+ //Cores that are present but not functional, also reported
+ TARGETING::PredicateHwas l_predPresent;
+ l_predPresent.present(true);
+
+ TARGETING::PredicatePostfixExpr l_PresentCore;
+ l_PresentCore.push(&l_corePredicate).push(&l_predPresent).And();
+
+ TARGETING::TargetHandleList l_coreList;
+
+ TARGETING::targetService().getAssociated(l_coreList, l_pProcTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL,
+ &l_PresentCore);
+
+ for (uint32_t l_idx = 0; l_idx < l_coreList.size(); ++l_idx)
+ {
+ HDAT_DBG("Core list size %d PCIA offset 0x%016llX",
+ l_coreList.size(),(uint64_t) &this->iv_spPcia[index]);
+ TARGETING::Target* l_pTarget = l_coreList[l_idx];
+ uint32_t l_coreNum =
+ l_pTarget->getAttr<TARGETING::ATTR_CHIP_UNIT>();
+
+ for ( uint32_t l_threadIndex=0;
+ l_threadIndex < l_coreThreadCount; ++l_threadIndex)
+ {
+ l_errl = hdatSetCoreInfo(index,
+ l_pTarget,l_pProcTarget);
+ if(l_errl)
+ {
+ HDAT_ERR("Error [0x%08X] in call to set core info",
+ l_errl->reasonCode());
+ break;
+ }
+ this->iv_spPcia[index].hdatThreadData.
+ pciaThreadData[l_threadIndex].pciaPhysThreadId =
+ l_threadIndex;
+
+ HDAT_DBG("HdatPcia thread idx %d, thread id %d ",
+ l_threadIndex, this->iv_spPcia[index].hdatThreadData.
+ pciaThreadData[l_threadIndex].pciaPhysThreadId);
+
+ /* Proc ID Reg is NNNCCCPPPPTTT
+ Where NNN is node number
+ CCC is Chip
+ PPPP is the core number
+ TTT is thread id
+ */
+ uint32_t l_ThreadProcIdReg = l_procFabricId * 0x400;
+ l_ThreadProcIdReg += l_procPosition*0x80;
+ l_ThreadProcIdReg += (l_coreNum * l_coreThreadCount) +
+ l_threadIndex;
+
+ hdatSetPciaHdrs(&this->iv_spPcia[index]);
+ this->iv_spPcia[index].hdatCoreData.pciaProcStatus
+ = l_procStatus;
+ this->iv_spPcia[index].hdatThreadData.
+ pciaThreadData[l_threadIndex].pciaProcIdReg =
+ l_ThreadProcIdReg;
+
+ this->iv_spPcia[index].hdatThreadData.
+ pciaThreadData[l_threadIndex].pciaInterruptLine =
+ l_ThreadProcIdReg;
+
+ Procstatus = isFunctional(l_pTarget) ?
+ HDAT_PROC_USABLE :
+ HDAT_PROC_NOT_USABLE;
+
+ Procstatus |= HDAT_EIGHT_THREAD;
+
+ uint32_t l_stat = this->iv_spPcia[index].hdatCoreData.
+ pciaProcStatus & HDAT_PROC_STAT_MASK;
+ this->iv_spPcia[index].hdatCoreData.pciaProcStatus =
+ (static_cast<hdatProcStatus> (Procstatus)
+ | l_stat ) & HDAT_EXIST_FLAGS_MASK_FOR_PCIA;
+
+ //IBASE ADDRESS + NNNN + 000
+ //Where NNNN = Thread Number =
+ // (Core Number * Number of threads) + Thread Number
+ uint64_t l_ibase = l_procIntrBase +
+ (l_coreNum * 0x1000 * l_coreThreadCount) +
+ l_threadIndex * 0x1000;
+
+ this->iv_spPcia[index].hdatThreadData.
+ pciaThreadData[l_threadIndex].pciaIbaseAddr.hi =
+ ((l_ibase & 0xFFFFFFFF00000000ull) >> 32);
+ this->iv_spPcia[index].hdatThreadData.
+ pciaThreadData[l_threadIndex].pciaIbaseAddr.hi |=
+ HDAT_REAL_ADDRESS_MASK;
+
+ this->iv_spPcia[index].hdatThreadData.
+ pciaThreadData[l_threadIndex].pciaIbaseAddr.lo =
+ (l_ibase & 0x00000000FFFFFFFFull);
+
+ if(HDAT_PROC_NOT_INSTALLED == (HDAT_PROC_STAT_BITS &
+ this->iv_spPcia[index].hdatCoreData.pciaProcStatus))
+ {
+ this->iv_spPcia[index].hdatPciaIntData
+ [HDAT_PCIA_DA_CPU_TIME_BASE].hdatOffset = 0;
+ this->iv_spPcia[index].hdatPciaIntData
+ [HDAT_PCIA_DA_CPU_TIME_BASE].hdatSize = 0;
+ this->iv_spPcia[index].hdatPciaIntData
+ [HDAT_PCIA_DA_CACHE_SIZE].hdatOffset = 0;
+ this->iv_spPcia[index].hdatPciaIntData
+ [HDAT_PCIA_DA_CACHE_SIZE].hdatSize = 0;
+ this->iv_spPcia[index].hdatPciaIntData
+ [HDAT_PCIA_DA_CPU_ATTRIBUTES].hdatOffset = 0;
+ this->iv_spPcia[index].hdatPciaIntData
+ [HDAT_PCIA_DA_CPU_ATTRIBUTES].hdatSize = 0;
+ }
+ // Need to setup header information for Thread Array Data
+ this->iv_spPcia[index].hdatThreadData.pciaThreadOffsetToData
+ = offsetof(hdatPciaThreadUniqueData_t, pciaThreadData);
+ this->iv_spPcia[index].hdatThreadData.pciaThreadNumEntries
+ = l_coreThreadCount;
+ this->iv_spPcia[index].hdatThreadData.
+ pciaThreadSizeAllocated = sizeof(hdatPciaThreadArray_t);
+ this->iv_spPcia[index].hdatThreadData.pciaThreadSizeActual =
+ sizeof(hdatPciaThreadArray_t);
+
+ }
+ if(NULL != l_errl)
+ {
+ //Break if there is an error
+ HDAT_ERR("Error [0x%08X] in call to get chip parent failed",
+ l_errl->reasonCode());
+ break;
+ }
+ index++;
+ if ((HDAT_RESERVE_FOR_CCM == (HDAT_RESERVE_FOR_CCM &
+ this->iv_spPcia[index].hdatCoreData.pciaProcStatus))||
+ (HDAT_PROC_NOT_INSTALLED != (HDAT_PROC_STAT_BITS &
+ this->iv_spPcia[index].hdatCoreData.pciaProcStatus)))
+ {
+ // The PCIA is a fixed size, but wanted it padded to a 128
+ // byte boundary
+ uint32_t l_rem=0, l_pad=0;
+ l_rem=0; l_pad=0;
+ // Pad to 128 bytes
+ l_rem = this->iv_spPcia[index-1].hdatHdr.hdatSize % 128;
+ l_pad = l_rem ? (128 - l_rem ) : 0;
+ uint8_t *l_addr=
+ reinterpret_cast<uint8_t *> (this->iv_spPcia);
+ // padding is allocated for size of PCIA entry. If it was
+ // smaller than 128 bytes, then you may need to bump it up
+ l_addr += l_pad;
+ this->iv_spPcia =
+ reinterpret_cast<hdatSpPcia_t *>(l_addr);
+ }
+ }
+ if(NULL != l_errl)
+ {
+ //Break if there is an error
+ break;
+ }
+ }
+ //End offset - starting offset divided by index
+ //for calculating each PCIA size.
+ o_size = ((uint64_t)&this->iv_spPcia[index] - l_offset)/index;
+ o_count = index;
+ }while(0);
+
+ return l_errl;
+}
+
+/*******************************************************************************
+* hdatSetCoreInfo
+*******************************************************************************/
+errlHndl_t HdatPcia::hdatSetCoreInfo(const uint32_t i_index,
+ const Target* i_pCoreTarget,
+ const Target* i_pProcTarget)
+{
+ errlHndl_t l_errl = NULL;
+ do
+ {
+ if(NULL == i_pCoreTarget)
+ {
+ HDAT_ERR("Input Target Pointer is NULL");
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_PCIA_SET_CORE_INF
+ * @reasoncode HDAT::RC_INVALID_OBJECT
+ * @userdata1 Index of proc target
+ * @devdesc Input Target Pointer is NULL
+ * @custdesc Firmware encountered an internal
+ * error while retrieving target data
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCIA_SET_CORE_INF,
+ RC_INVALID_OBJECT,
+ i_index,0,0,0);
+ break;
+ }
+
+ if(i_pCoreTarget->getAttr<ATTR_TYPE>() != TYPE_CORE)
+ {
+ HDAT_ERR("Input Target type is not valid");
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_PCIA_SET_CORE_INF
+ * @reasoncode HDAT::RC_INVALID_TGT_ATTR
+ * @userdata1 Index of proc target
+ * @userdata2 Target HUID
+ * @devdesc Invalid input target attribute
+ * @custdesc Firmware encountered an internal error
+ * while retrieving attribute data
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCIA_SET_CORE_INF,
+ RC_INVALID_TGT_ATTR,
+ i_index,get_huid(i_pCoreTarget),0,0);
+ break;
+ }
+ TARGETING::Target *l_pSysTarget = NULL;
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSysTarget);
+
+ // asserting
+ assert(l_pSysTarget != NULL);
+
+ uint32_t l_procOrdId = i_pProcTarget->getAttr<ATTR_ORDINAL_ID>();
+
+ uint32_t l_coreOrdId = i_pCoreTarget->getAttr<ATTR_ORDINAL_ID>();
+
+ HDAT_DBG("proc ord ID:0x%08X, core ord ID:0x%08X",
+ l_procOrdId,l_coreOrdId);
+
+ uint32_t l_HWCardId = 0;
+ l_errl = HDAT::hdatGetHwCardId(i_pProcTarget,l_HWCardId);
+ if(NULL != l_errl)
+ {
+ HDAT_ERR("Error [0x%08X] in call to get card id failed",
+ l_errl->reasonCode());
+
+ l_errl->addFFDC(HDAT_COMP_ID,AT,sizeof(AT),
+ HDAT_VERSION1,HDAT_PCIA_FFDC_SUBSEC);
+ break;
+ }
+ HDAT_DBG("hw card ID:0x%08X", l_HWCardId);
+
+ iv_spPcia[i_index].hdatCoreData.pciaHWCardID = l_HWCardId;
+
+ TARGETING::TargetHandleList targetListNode;
+ targetListNode.clear();
+ getParentAffinityTargets(targetListNode,i_pCoreTarget,
+ TARGETING::CLASS_ENC,TARGETING::TYPE_NODE);
+ if(targetListNode.empty())
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_PCIA_SET_CORE_INF
+ * @reasoncode HDAT::RC_EMPTY_TARGET_LIST
+ * @devdesc Target List is Empty
+ * @custdesc Firmware encountered an internal
+ * error while retrieving target data
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCIA_SET_CORE_INF,
+ RC_EMPTY_TARGET_LIST,
+ 0,0,0,0);
+ break;
+ }
+ //get the parent node id
+ Target* l_pNodeTarget = targetListNode[0];
+
+ uint32_t l_nodeOrdId = l_pNodeTarget->getAttr<ATTR_ORDINAL_ID>();
+
+ uint32_t l_fabNodeId = i_pProcTarget->getAttr<ATTR_FABRIC_NODE_ID>();
+
+ //Set the Internal Drawer Node ID
+ iv_spPcia[i_index].hdatCoreData.pciaDrawerNodeID = l_fabNodeId;
+
+ //get the parent node id and set that
+ this->iv_spPcia[i_index].hdatCoreData.pciaDBOBID = l_nodeOrdId;
+
+ //set the LCO target to 0
+ this->iv_spPcia[i_index].hdatCoreData.pciaLCOTarget = 0;
+ this->iv_spPcia[i_index].hdatCoreData.pciaCCMNodeID = l_nodeOrdId;
+ //get the parent node id and set that
+
+ //Ordinal Id of the fru containing this proc
+ uint32_t l_fruOrdId = i_pProcTarget->getAttr<TARGETING::ATTR_FRU_ID>();
+ this->iv_spPcia[i_index].hdatCoreData.pciaFruId = l_fruOrdId;
+
+ //Module id is same as FRU Ordinal ID
+ this->iv_spPcia[i_index].hdatCoreData.pciaModuleId = l_fruOrdId;
+
+ //Ordinal ID of the core
+ this->iv_spPcia[i_index].hdatCoreData.pciaHdwProcId = l_coreOrdId;
+
+ uint32_t l_eclevel = 0;
+ uint32_t l_chipId = 0;
+
+ //Set the Chip EC level
+ l_errl = HDAT::hdatGetIdEc(i_pProcTarget, l_eclevel, l_chipId);
+ if(NULL != l_errl)
+ {
+ HDAT_ERR("Error [0x%08X] in call to get IdEc Failed",
+ l_errl->reasonCode());
+ l_errl->addFFDC(HDAT_COMP_ID,AT,sizeof(AT),
+ HDAT_VERSION1,HDAT_PCIA_FFDC_SUBSEC);
+ break;
+ }
+ iv_spPcia[i_index].hdatCoreData.pciaChipEcLvl = l_eclevel;
+
+ //Ordinal id of the proc(chip)
+ this->iv_spPcia[i_index].hdatCoreData.pciaChipId = l_procOrdId;
+
+ //Set Clock Freq - Cycle Time in MHz
+ iv_spPcia[i_index].hdatTime.pciaClockSpeed =
+ l_pSysTarget->getAttr<TARGETING::ATTR_NOMINAL_FREQ_MHZ>();
+
+ //CPU Time Base Structure
+ uint32_t l_CycleTime = pow(2,34) /
+ iv_spPcia[i_index].hdatTime.pciaClockSpeed;
+
+ //Set Cycle Time
+ iv_spPcia[i_index].hdatTime.pciaCycleTime = l_CycleTime;
+ //Set Time Base - units of microseconds * 2^32
+ iv_spPcia[i_index].hdatTime.pciaTimeBase =
+ i_pProcTarget->getAttr<TARGETING::ATTR_TIME_BASE>();
+
+ //Set ICache Info
+ //Cache Size Structure
+ this->iv_spPcia[i_index].hdatCache.pciaICacheSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_ICACHE_SIZE>();
+ this->iv_spPcia[i_index].hdatCache.pciaICacheLineSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_ICACHE_LINE_SIZE>();
+ this->iv_spPcia[i_index].hdatCache.pciaICacheBlkSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_ICACHE_BLOCK_SIZE>();
+
+ this->iv_spPcia[i_index].hdatCache.pciaICacheAssocSets =
+ i_pProcTarget->getAttr<TARGETING::ATTR_ICACHE_ASSOC_SETS>();
+
+ //Set DCache Info
+ this->iv_spPcia[i_index].hdatCache.pciaDCacheBlkSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_DCACHE_LINE_SIZE>();
+ this->iv_spPcia[i_index].hdatCache.pciaDCacheAssocSets =
+ i_pProcTarget->getAttr<TARGETING::ATTR_DCACHE_ASSOC_SETS>();
+
+
+ //Set L1 Cache Info
+ this->iv_spPcia[i_index].hdatCache.pciaL1DCacheSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_DATA_CACHE_SIZE>();
+ this->iv_spPcia[i_index].hdatCache.pciaL1DCacheLineSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_DATA_CACHE_LINE_SIZE>();
+
+ //Set L2 Cache Info
+ this->iv_spPcia[i_index].hdatCache.pciaL2DCacheSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_L2_CACHE_SIZE>();
+ this->iv_spPcia[i_index].hdatCache.pciaL2DCacheLineSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_L2_CACHE_LINE_SIZE>();
+
+ this->iv_spPcia[i_index].hdatCache.pciaL2AssocSets =
+ i_pProcTarget->getAttr<TARGETING::ATTR_L2_CACHE_ASSOC_SETS>();
+
+ //Set L3 Cache Info
+ this->iv_spPcia[i_index].hdatCache.pciaL3DCacheSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_L3_CACHE_SIZE>();
+ this->iv_spPcia[i_index].hdatCache.pciaL3DCacheLineSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_L3_CACHE_LINE_SIZE>();
+
+ //ECO not supported initialize to 0
+ this->iv_spPcia[i_index].hdatCache.pciaL3Pt5DCacheSize = 0;
+ this->iv_spPcia[i_index].hdatCache.pciaL3Pt5DCacheLineSize = 0;
+
+ //Set TLB info
+ this->iv_spPcia[i_index].hdatCache.pciaITlbEntries =
+ i_pProcTarget->getAttr<TARGETING::ATTR_TLB_INSTR_ENTRIES>();
+ this->iv_spPcia[i_index].hdatCache.pciaITlbAssocSets =
+ i_pProcTarget->getAttr<TARGETING::ATTR_TLB_INSTR_ASSOC_SETS>();
+
+ this->iv_spPcia[i_index].hdatCache.pciaDTlbEntries =
+ i_pProcTarget->getAttr<TARGETING::ATTR_TLB_DATA_ENTRIES>();
+ this->iv_spPcia[i_index].hdatCache.pciaDTlbAssocSets =
+ i_pProcTarget->getAttr<TARGETING::ATTR_TLB_DATA_ASSOC_SETS>();
+
+ this->iv_spPcia[i_index].hdatCache.pciaReserveSize =
+ i_pProcTarget->getAttr<TARGETING::ATTR_TLB_RESERVE_SIZE>();
+
+ //Set CPU Attributes
+ iv_spPcia[i_index].hdatAttr.pciaAttributes =
+ i_pProcTarget->getAttr<TARGETING::ATTR_CPU_ATTR>();
+ }
+ while(0);
+
+ return l_errl;
+}
+
+/*******************************************************************************
+* PCIA Destructor
+*******************************************************************************/
+HdatPcia :: ~HdatPcia()
+{
+ int rc = 0;
+ rc = mm_block_unmap(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(
+ reinterpret_cast<uint64_t>(iv_spPcia))));
+ if( rc != 0)
+ {
+ errlHndl_t l_errl = NULL;
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_PCIA_DESTRUCTOR
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCIA_DESTRUCTOR,
+ RC_DEV_MAP_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+
+}
+
+} //namespace HDAT
diff --git a/src/usr/hdat/hdatpcia.H b/src/usr/hdat/hdatpcia.H
new file mode 100755
index 000000000..e1ba47522
--- /dev/null
+++ b/src/usr/hdat/hdatpcia.H
@@ -0,0 +1,356 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatpcia.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 */
+
+
+/**
+ * @file hdatpcia.H
+ *
+ * @brief This file contains the definition of the Processor Core Information
+ * Area (PCIA) data structure.
+ *
+ * A C++ class is defined that is used to update the copy of the PCIA.
+ * The PCIA is written to main memory.
+ */
+
+#ifndef HDATPCIA_H
+#define HDATPCIA_H
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <hdat/hdat.H>
+#include <errl/errlentry.H>
+#include <hdat/hdat_reasoncodes.H>
+#include "hdatutil.H"
+#include <math.h>
+
+namespace HDAT
+{
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+#define HDAT_NUM_P8_PCIA_ENTRIES 32 * 8
+
+const uint16_t HDAT_PCIA_VERSION = 0x01;
+const char HDAT_PCIA_STRUCT_NAME[7] = "SPPCIA";
+const uint32_t HDAT_PROC_STAT_MASK = 0x00008000;
+
+// Bits in the proc/exist flags for PCIA data
+ #define HDAT_EXIST_FLAGS_MASK_FOR_PCIA 0xD0FF0000
+
+/** @enum hdatDataPtrs
+ * Enumeration which defines the data sections of the PCIA
+ */
+enum hdatDataPtrs
+{
+ HDAT_PCIA_DA_COREDATA = 0,
+ HDAT_PCIA_DA_CPU_TIME_BASE = 1,
+ HDAT_PCIA_DA_CACHE_SIZE = 2,
+ HDAT_PCIA_DA_THREADDATA = 3,
+ HDAT_PCIA_DA_CPU_ATTRIBUTES = 4,
+ HDAT_PCIA_DA_CNT = 5,
+ HDAT_PCIA_DA_LAST = 8
+};
+
+/*----------------------------------------------------------------------------*/
+/* Type definitions */
+/*----------------------------------------------------------------------------*/
+
+/** @brief This defines the Core unique data section of the PCIA.
+ * Data here is related to processor cores
+ */
+struct hdatPciaCoreUniqueData_t
+{
+ uint32_t reserved_01; // 0x0000 Reserved.
+ uint32_t pciaFruId; // 0x0004 FRU ID
+ uint32_t pciaHdwProcId; // 0x0008 hardware processor ID
+ uint32_t pciaProcStatus; // 0x000C processor status flags
+ uint32_t pciaChipEcLvl; // 0x0010 chip EC level
+ uint32_t pciaChipId; // 0x0014 processor chip ID
+ uint32_t reserved_02; // 0x0018 Deprecated
+ uint32_t reserved_03; // 0x001C Deprecated
+ uint32_t reserved_04; // 0x0020 Reserved
+ uint32_t pciaModuleId; // 0x0024 module id for the DCM,
+ // MCM, QCM, etc.
+ hdatMsAddr_t reserved_05; // 0x0028 Reserved.
+ uint32_t reserved_06; // 0x0030 Reserved.
+ uint32_t reserved_07; // 0x0034 Deprecated
+ uint32_t reserved_08; // 0x0038 Reserved.
+ uint32_t pciaCCMNodeID; // 0x003C CCM Node ID
+ uint32_t pciaHWCardID; // 0x0040 HW Card ID
+ uint32_t pciaDrawerNodeID; // 0x0044 Internal Drawer Node ID
+ uint32_t pciaDBOBID; // 0x0048 Drawer/Book/Octant/Blade ID
+ uint32_t reserved_09; // 0x004C Reserved.
+ uint32_t pciaLCOTarget; // 0x0050 LCO Target.
+ uint32_t reserved_10; // 0x0054 Reserved.
+} __attribute__ ((packed));
+
+
+/** @brief CPU Time Base portion of the FipS PCIA section
+ */
+struct hdatPciaCpuTimeBase_t
+{
+ uint32_t pciaCycleTime; // 0x0000 cycle time
+ uint32_t pciaTimeBase; // 0x0004 time base
+ uint32_t pciaClockSpeed; // 0x0008 actual clock speed
+ uint32_t pciaMemBusFreq; // 0x000C memory bus frequency
+} __attribute__ ((packed));
+
+
+/** @brief Cache Size portion of the FipS PCIA section
+ */
+struct hdatPciaCacheSize_t
+{
+ uint32_t pciaICacheSize; // 0x0000 instruction cache size (in KB)
+ uint32_t pciaICacheLineSize; // 0x0004 instruction cache line size
+ // (in bytes)
+ uint32_t pciaL1DCacheSize; // 0x0008 L1 data cache size (in KB)
+ uint32_t pciaL1DCacheLineSize; // 0x000C L1 data cache line size
+ // (in bytes)
+ uint32_t pciaL2DCacheSize; // 0x0010 L2 data cache size (in KB)
+ uint32_t pciaL2DCacheLineSize; // 0x0014 L2 cache line size (in bytes)
+ uint32_t pciaL3DCacheSize; // 0x0018 L3 data cache size (in KB)
+ uint32_t pciaL3DCacheLineSize; // 0x001C L3 cache line size (in bytes)
+ uint32_t pciaDCacheBlkSize; // 0x0020 data cache block size
+ // (in bytes)
+ uint32_t pciaICacheBlkSize; // 0x0024 instruction cache block size
+ // (in bytes)
+ uint32_t pciaDCacheAssocSets; // 0x0028 number of associativity sets
+ // in data cache
+ uint32_t pciaICacheAssocSets; // 0x002C number of associativity sets
+ // in instruction cache
+ uint32_t pciaDTlbEntries; // 0x0030 number of data TLB entries
+ uint32_t pciaDTlbAssocSets; // 0x0034 number of associativity sets
+ // in data TLB
+ uint32_t pciaITlbEntries; // 0x0038 number of instruction TLB
+ // entries
+ uint32_t pciaITlbAssocSets; // 0x003C number of associativity sets
+ // in instruction TLB
+ uint32_t pciaReserveSize; // 0x0040 reservation size
+ uint32_t pciaL2AssocSets; // 0x0044 number of associativity sets
+ // in L2
+ uint32_t pciaL3Pt5DCacheSize; // 0x0048 L3.5 data cache size (in KB)
+ uint32_t pciaL3Pt5DCacheLineSize; // 0x004C L3.5 cache line size
+ // (in bytes)
+} __attribute__ ((packed));
+
+
+/** @brief This defines the thread array for each processor core area.
+ */
+struct hdatPciaThreadArray_t
+{
+ uint32_t pciaInterruptLine; // 0x0000 processor interrupt line.
+ uint32_t pciaPhysThreadId; // 0x0004 processor thread ID (0,1,...)
+ hdatMsAddr_t pciaIbaseAddr; // 0x0008 IBASE register address.
+ uint32_t pciaProcIdReg; // 0x0010 processor ID register
+} __attribute__ ((packed));
+
+
+/** @brief This defines the thread specific data section for each
+ * processor core.
+ */
+struct hdatPciaThreadUniqueData_t
+{
+ uint32_t pciaThreadOffsetToData; // 0x0000 Should be fixed at size
+ // of this 16 byte header
+ uint32_t pciaThreadNumEntries; // 0x0004 Number of entries in the
+ // thread data array past header
+ uint32_t pciaThreadSizeAllocated; // 0x0008 Allocated size of array
+ // entry in bytes (will be
+ // 16 bytes for now)
+ uint32_t pciaThreadSizeActual; // 0x000C Actual size of each
+ // entry in bytes
+ hdatPciaThreadArray_t pciaThreadData[HDAT_MAX_THREADS_SUPPORTED];
+ // 0x0010 Actual array thread data
+
+} __attribute__ ((packed));
+
+
+/** @brief CPU Attributes portion of the FipS PCIA section
+ */
+struct hdatPciaCpuAttributes_t
+{
+ uint32_t pciaAttributes; // 0x0000 bit map of attributes
+} __attribute__ ((packed));
+
+
+
+/** @brief This defines the PCIA. FipS updates this
+ * portion and DMAs the entire PCIA back to main memory.
+ */
+struct hdatSpPcia_t
+{
+ hdatHDIF_t hdatHdr;
+ hdatHDIFDataHdr_t hdatPciaIntData[HDAT_PCIA_DA_LAST];
+ hdatPciaCoreUniqueData_t hdatCoreData;
+ hdatPciaCpuTimeBase_t hdatTime;
+ hdatPciaCacheSize_t hdatCache;
+ hdatPciaThreadUniqueData_t hdatThreadData;
+ hdatPciaCpuAttributes_t hdatAttr;
+} __attribute__ ((packed));
+
+/*----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatPcia class is used to construct the PCIA object.
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that any component can create an object of this type.
+ * In particular, the object is built only in the
+ * CEC Server process when requested by the hdat component.
+ *
+ * The real purpose of the object is to create the PCIA array
+ * structure as defined by the PHYP Initialization architecture.
+ *
+ * Signal handler usage: This class is not intended to be used in a signal
+ * handler
+ *
+ * End Class Description
+ */
+class HdatPcia
+{
+ public:
+ /**
+ * @brief Construct an HdatPcia object
+ *
+ * This is the constructor for the HdatPcia object.
+ *
+ * @pre None
+ *
+ * @post An HdatPcia object pointer would be pointing to the host memory
+ * where the data would be directly written on to the memory.
+ * Each PCIA entry is initialized to indicate the processor is not
+ * installed. If the processor is installed, set the status and
+ * supply other information.
+ *
+ * @param[out] o_errlHndl
+ * If any errors occur, the HdatPcia object is NOT constructed
+ * and errors are returned in this parameter
+
+ * @param[in] i_msAddr
+ * The main memory address that the PCIA structure will be DMA'd to.
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl.
+ *
+ */
+
+ HdatPcia(errlHndl_t &o_errlHndl,
+ const hdatMsAddr_t &i_msAddr);
+ /**
+ * @brief HdatPcia object destructor
+ *
+ * This is the destructor for an HdatPcia object.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatPcia object has been destroyed and can no longer be used.
+ *
+ */
+ ~HdatPcia();
+
+ /**
+ * @brief Load the HdatPcia object
+ *
+ * This function is used to the load the HdatPcia object with all the
+ * hdatSpPcia_t structure data. HdatPcia object would be having all
+ * the core data with partial good data which are present and all
+ * the present which are not functional also
+ *
+ * @param[out] o_size
+ * Size of PCIA object which are written onto Host memory.
+ *
+ * @param[out] o_count
+ * Count of PCIA objects which are written onto Host memory.
+ *
+ * @pre HdatPcia Object should be constructed with the main memory address
+ *
+ * @post The HdatPcia object with all the PCIA entry populated.
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl.
+ */
+ errlHndl_t hdatLoadPcia(uint32_t &o_size, uint32_t &o_count);
+
+ private:
+
+ /** Object instance Data
+ *
+ * Only one copy of this data exists in a process.
+ *
+ */
+
+ /* @li iv_msAddr - main memory address the final data structure written */
+ hdatMsAddr_t iv_msAddr;
+
+ /* @li iv_numPciaEntries - number of PCIA entries*/
+ uint32_t iv_numPciaEntries; // Number of core entries
+
+ /* @li iv_spPciaEntrySize - size of one entry in PCIA*/
+ uint32_t iv_spPciaEntrySize; // Size of a PCIA entry
+
+ /* @li iv_spPcia - pointer to the first PCIA Entry */
+ hdatSpPcia_t *iv_spPcia;
+
+ /**
+ * @brief Set the core specific info
+ *
+ * This function is an helper function used to the set the core
+ * specific info into the HdatPcia object with for all the
+ * hdatPciaCoreUniqueData_t, hdatPciaCacheSize_t,
+ * hdatPciaCpuAttributes_t structure data.
+ *
+ * @pre HdatPcia Object should be constructed with the main memory address
+ * Target pointer to the core which is present on the system
+ * Target pointer to the present procs in the system
+ *
+ * @post The HdatPcia object with all the core related data populated.
+ *
+ * @param[in] i_index
+ * Index value
+ *
+ * @param[in] i_pTarget
+ * Core target pointer. Must not be NULL (otherwise call will return an
+ * error log). Must be a valid target from the system blueprint.
+ *
+ * @param[in] i_pTarget
+ * Proc target pointer. Must not be NULL (otherwise call will return an
+ * error log). Must be a valid target from the system blueprint.
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl.
+ */
+
+ errlHndl_t hdatSetCoreInfo(const uint32_t i_index,
+ const TARGETING::Target* i_pCoreTarget,
+ const TARGETING::Target* i_pProcTarget);
+};
+
+} //namespace HDAT
+#endif // HDATPCIA_H
diff --git a/src/usr/hdat/hdatpcrd.C b/src/usr/hdat/hdatpcrd.C
new file mode 100644
index 000000000..8df9b615c
--- /dev/null
+++ b/src/usr/hdat/hdatpcrd.C
@@ -0,0 +1,645 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatpcrd.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 <sys/mm.h>
+#include <sys/mmio.h>
+#include "hdatpcrd.H"
+#include <targeting/common/util.H>
+#include "hdatvpd.H"
+#include <util/align.H>
+#include <devicefw/driverif.H>
+#include <vpd/mvpdenums.H>
+
+using namespace VPD;
+using namespace MVPD;
+using namespace TARGETING;
+
+namespace HDAT
+{
+extern trace_desc_t *g_trac_hdat;
+
+/**
+ * @brief Data sample to be used for MVPD testing.
+ * NOTE: By reading this entire list, it also validates that the records
+ * and keywords that we expect to be there are actually there...
+ */
+vpdData procVpdData[] =
+{
+ { MVPD::VINI, MVPD::DR },
+ { MVPD::VINI, MVPD::VZ },
+ { MVPD::VINI, MVPD::CC },
+ { MVPD::VINI, MVPD::CE },
+ { MVPD::VINI, MVPD::FN },
+ { MVPD::VINI, MVPD::PN },
+ { MVPD::VINI, MVPD::SN },
+ { MVPD::VINI, MVPD::PR },
+ { MVPD::VINI, MVPD::HE },
+ { MVPD::VINI, MVPD::CT },
+ { MVPD::VINI, MVPD::HW },
+ };
+
+const HdatKeywordInfo l_mvpdKeywords[] =
+{
+ { MVPD::DR, "DR" },
+ { MVPD::VZ, "VZ" },
+ { MVPD::CC, "CC" },
+ { MVPD::CE, "CE" },
+ { MVPD::FN, "FN" },
+ { MVPD::PN, "PN" },
+ { MVPD::SN, "SN" },
+ { MVPD::PR, "PR" },
+ { MVPD::HE, "HE" },
+ { MVPD::CT, "CT" },
+ { MVPD::HW, "HW" },
+
+};
+
+/*******************************************************************************
+ * hdatSetPcrdHdrs
+ *
+ * @brief Routine initializes HDIF headers for a PCRD array entry
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[in] i_pcrd
+ * The iv_spPcrd array element to operate on
+ *
+ * @return A null error log handle if successful, Currently can't fail.
+ *
+*******************************************************************************/
+static errlHndl_t hdatSetPcrdHdrs(hdatSpPcrd_t *i_pcrd)
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ i_pcrd->hdatHdr.hdatStructId = HDAT_HDIF_STRUCT_ID;
+ i_pcrd->hdatHdr.hdatInstance = 0;
+ i_pcrd->hdatHdr.hdatVersion = HDAT_PCRD_VERSION;
+ i_pcrd->hdatHdr.hdatSize = offsetof(hdatSpPcrd_t, vpd_data);
+ i_pcrd->hdatHdr.hdatHdrSize = sizeof(hdatHDIF_t);
+ i_pcrd->hdatHdr.hdatDataPtrOffset = sizeof(hdatHDIF_t);
+ i_pcrd->hdatHdr.hdatDataPtrCnt = HDAT_PCRD_DA_CNT;
+ i_pcrd->hdatHdr.hdatChildStrCnt = 0;
+ i_pcrd->hdatHdr.hdatChildStrOffset = 0;
+
+ memcpy(i_pcrd->hdatHdr.hdatStructName, HDAT_PCRD_STRUCT_NAME,
+ sizeof(i_pcrd->hdatHdr.hdatStructName));
+ i_pcrd->hdatPcrdIntData[HDAT_PCRD_DA_CHIP_INFO].hdatOffset =
+ offsetof(hdatSpPcrd_t, hdatChipData);
+ i_pcrd->hdatPcrdIntData[HDAT_PCRD_DA_CHIP_INFO].hdatSize =
+ sizeof(hdatPcrdChipInfo_t);
+
+ i_pcrd->hdatPcrdIntData[HDAT_PCRD_DA_CHIP_TIMEOFDAY].hdatOffset =
+ offsetof(hdatSpPcrd_t, hdatChipTodData);
+ i_pcrd->hdatPcrdIntData[HDAT_PCRD_DA_CHIP_TIMEOFDAY].hdatSize =
+ sizeof(hdatPcrdChipTod_t);
+ i_pcrd->hdatPcrdIntData[HDAT_PCRD_DA_FRU_ID].hdatOffset =
+ offsetof(hdatSpPcrd_t, hdatFruId);
+
+ i_pcrd->hdatPcrdIntData[HDAT_PCRD_DA_FRU_ID].hdatSize = sizeof(hdatFruId_t);
+ i_pcrd->hdatPcrdIntData[HDAT_PCRD_DA_ASCII_KWD].hdatOffset = 0;
+ i_pcrd->hdatPcrdIntData[HDAT_PCRD_DA_ASCII_KWD].hdatSize = 0;
+ i_pcrd->hdatPcrdIntData[HDAT_PCRD_DA_CHIP_VPD].hdatOffset = 0;
+ i_pcrd->hdatPcrdIntData[HDAT_PCRD_DA_CHIP_VPD].hdatSize = 0;
+
+ return l_errlHndl;
+}
+
+/*******************************************************************************
+* PCRD Constructor
+*******************************************************************************/
+HdatPcrd::HdatPcrd(errlHndl_t &o_errlHndl, const hdatMsAddr_t &i_msAddr)
+ : iv_numPcrdEntries(0), iv_spPcrdEntrySize(0), iv_spPcrd(NULL)
+{
+ // Allocate the CHIP INFO section also
+ iv_numPcrdEntries = HDAT_NUM_P7_PCRD_ENTRIES;
+ iv_spPcrdEntrySize = sizeof(hdatSpPcrd_t) + HDAT_FULL_MVPD_SIZE;
+
+ // Allocate space for each CHIP -- will use max amount to start
+ uint64_t l_base_addr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo;
+ void *l_virt_addr = mm_block_map (
+ reinterpret_cast<void*>(ALIGN_PAGE_DOWN(l_base_addr)),
+ (ALIGN_PAGE(iv_numPcrdEntries*iv_spPcrdEntrySize)+PAGESIZE));
+
+ l_virt_addr = reinterpret_cast<void *>(
+ reinterpret_cast<uint64_t>(l_virt_addr) +
+ (l_base_addr - ALIGN_PAGE_DOWN(l_base_addr)));
+
+ // initializing the space to zero
+ memset(l_virt_addr ,0x0,(iv_numPcrdEntries*iv_spPcrdEntrySize));
+
+ iv_spPcrd = reinterpret_cast<hdatSpPcrd_t *>(l_virt_addr);
+
+ HDAT_DBG("Constructor iv_spPcrd addr 0x%016llX virtual addr 0x%016llX",
+ (uint64_t) this->iv_spPcrd, (uint64_t)l_virt_addr);
+}
+
+/*******************************************************************************
+* hdatLoadPcrd
+*******************************************************************************/
+errlHndl_t HdatPcrd::hdatLoadPcrd(uint32_t &o_size, uint32_t &o_count)
+{
+ errlHndl_t l_errl = NULL;
+ do
+ {
+ // PCRD index
+ uint32_t index = 0;
+
+ //Storing offset address for calculating the sizing of each PCRD
+ uint8_t *l_offset = reinterpret_cast<uint8_t *> (this->iv_spPcrd);
+ uint8_t *l_addr =l_offset;
+
+ // Get Max threads
+ ATTR_THREAD_COUNT_type l_coreThreadCount = 0;
+ Target* l_pTopLevel = NULL;
+ (void)TARGETING::targetService().getTopLevelTarget(l_pTopLevel);
+ if(NULL == l_pTopLevel)
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_PCRD_LOAD
+ * @reasoncode HDAT::RC_TOP_LVL_TGT_NOT_FOUND
+ * @devdesc Top level target not found
+ * @custdesc Firmware encountered an internal
+ * error while retrieving target data
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCRD_LOAD,
+ RC_TOP_LVL_TGT_NOT_FOUND,
+ 0,0,0,0);
+
+ HDAT_ERR("Error getting top level target");
+ break;
+ }
+
+ // @TODO: RTC 142465. Add check to know whether in fused mode or not
+ l_coreThreadCount = l_pTopLevel->getAttr<ATTR_THREAD_COUNT>();
+ uint32_t l_procStatus;
+ if ( l_coreThreadCount == HDAT_MAX_EIGHT_THREADS_SUPPORTED )
+ {
+ l_procStatus =
+ HDAT_PROC_NOT_INSTALLED | HDAT_PRIM_THREAD | HDAT_EIGHT_THREAD;
+ }
+ else if ( l_coreThreadCount == HDAT_MAX_FOUR_THREADS_SUPPORTED )
+ {
+ l_procStatus =
+ HDAT_PROC_NOT_INSTALLED | HDAT_PRIM_THREAD | HDAT_FOUR_THREAD;
+ }
+ else
+ {
+ l_procStatus =
+ HDAT_PROC_NOT_INSTALLED | HDAT_PRIM_THREAD | HDAT_TWO_THREAD;
+ }
+
+ //for each procs in the system
+ TARGETING::PredicateCTM l_procFilter(CLASS_CHIP, TYPE_PROC);
+ TARGETING::PredicateHwas l_pred;
+ l_pred.present(true);
+ TARGETING::PredicatePostfixExpr l_presentProc;
+ l_presentProc.push(&l_procFilter).push(&l_pred).And();
+
+ TARGETING::TargetRangeFilter l_filter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentProc);
+ for (;l_filter;++l_filter)
+ {
+ HDAT_DBG("Pcrd Address 0x%08X \n",
+ reinterpret_cast<uint8_t *> (this->iv_spPcrd));
+ bool l_all_cores_usable = true;
+ TARGETING::Target* l_pProcTarget = *l_filter;
+ TARGETING::PredicateCTM l_corePredicate(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_CORE);
+
+ TARGETING::PredicateHwas l_predPresent;
+ l_predPresent.present(true);
+
+ TARGETING::PredicatePostfixExpr l_PresentCore;
+ l_PresentCore.push(&l_corePredicate).push(&l_predPresent).And();
+
+ TARGETING::TargetHandleList l_coreList;
+
+ TARGETING::targetService().getAssociated(l_coreList, l_pProcTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL,
+ &l_PresentCore);
+
+ if(l_coreList.size() == 0 )
+ {
+ l_all_cores_usable = false;
+ }
+
+ for (uint32_t l_idx = 0; l_idx < l_coreList.size(); ++l_idx)
+ {
+ TARGETING::Target* l_pTarget = l_coreList[l_idx];
+ l_procStatus = isFunctional(l_pTarget) ?
+ HDAT_PROC_USABLE :
+ HDAT_PROC_NOT_USABLE;
+
+ if(l_procStatus == HDAT_PROC_NOT_USABLE)
+ {
+ l_all_cores_usable = false;
+ }
+ l_procStatus |= l_coreThreadCount;
+ }
+ if(l_all_cores_usable)
+ {
+ l_procStatus = HDAT_PROC_USABLE;
+ }
+ else
+ {
+ l_procStatus = HDAT_PROC_FAILURES;
+ }
+ hdatSetPcrdHdrs(this->iv_spPcrd);
+
+ l_errl = this->hdatSetProcessorInfo( l_pProcTarget,
+ l_procStatus);
+ if ( NULL != l_errl )
+ {
+ HDAT_ERR("Error [0x%08X] in call to get processor info failed",
+ l_errl->reasonCode());
+ break;
+ }
+
+ this->iv_spPcrd->hdatFruId.hdatSlcaIdx =
+ l_pProcTarget->getAttr<ATTR_SLCA_INDEX>();
+ this->iv_spPcrd->hdatFruId.hdatResourceId =
+ l_pProcTarget->getAttr<ATTR_SLCA_RID>();
+
+ if (HDAT_PROC_NOT_INSTALLED == (HDAT_PROC_STAT_BITS &
+ this->iv_spPcrd->hdatChipData.hdatPcrdStatusFlags))
+ {
+ // Will leave the chip time-of-day info since that has its
+ // own exist bits and we never wiped out before
+ this->iv_spPcrd->hdatPcrdIntData
+ [HDAT_PCRD_DA_FRU_ID].hdatOffset = 0;
+ this->iv_spPcrd->hdatPcrdIntData
+ [HDAT_PCRD_DA_FRU_ID].hdatSize = 0;
+ this->iv_spPcrd->hdatPcrdIntData
+ [HDAT_PCRD_DA_ASCII_KWD].hdatOffset = 0;
+ this->iv_spPcrd->hdatPcrdIntData
+ [HDAT_PCRD_DA_ASCII_KWD].hdatSize = 0;
+ this->iv_spPcrd->hdatPcrdIntData
+ [HDAT_PCRD_DA_CHIP_VPD].hdatOffset = 0;
+ this->iv_spPcrd->hdatPcrdIntData
+ [HDAT_PCRD_DA_CHIP_VPD].hdatSize = 0;
+ }
+ else
+ {
+ // Need to complete the chip TOD information fetch
+ //TODO : RTC 147507 - Fetch TOD information
+ if(index ==0 )
+ {
+ this->iv_spPcrd->hdatChipTodData.
+ hdatPcrdTodFlags=0x06;
+ }
+ else
+ {
+ this->iv_spPcrd->hdatChipTodData.
+ hdatPcrdTodFlags=0x05;
+ }
+ this->iv_spPcrd->hdatChipTodData.hdatPcrdTodControls=
+ 0x03F30000;
+ this->iv_spPcrd->hdatChipTodData.
+ hdatPcrdTodControlRegister=0x003F0000;
+
+ // Get ascii keyword
+ char *l_keyword= NULL;
+ uint32_t l_asciiKeywordSize=0;
+ uint32_t l_num = sizeof(procVpdData) / sizeof(procVpdData[0]);
+ size_t theSize[l_num];
+ l_errl = hdatGetAsciiKwd(l_pProcTarget,l_asciiKeywordSize,l_keyword,
+ PROC,procVpdData,l_num,theSize);
+ if(l_errl )
+ {
+ HDAT_ERR("Error [0x%08X] in the collect the VPD data",
+ l_errl->reasonCode());
+ break;
+ }
+ char *o_fmtKwd;
+ uint32_t o_fmtkwdSize;
+ l_errl = hdatformatAsciiKwd(procVpdData, l_num,
+ theSize, l_keyword, l_asciiKeywordSize, o_fmtKwd,
+ o_fmtkwdSize, l_mvpdKeywords);
+ if( o_fmtKwd != NULL )
+ {
+ delete[] l_keyword;
+ l_keyword = new char [o_fmtkwdSize];
+ memcpy(l_keyword,o_fmtKwd,o_fmtkwdSize);
+ l_asciiKeywordSize = o_fmtkwdSize;
+ delete[] o_fmtKwd;
+ }
+
+ uint8_t *l_keywordAddr=
+ reinterpret_cast<uint8_t *>
+ (&this->iv_spPcrd->hdatKwd);
+
+ memcpy(l_keywordAddr ,l_keyword,l_asciiKeywordSize);
+
+ if(l_keyword != NULL)
+ {
+ delete[] l_keyword;
+ }
+
+ this->iv_spPcrd->hdatPcrdIntData
+ [HDAT_PCRD_DA_ASCII_KWD].hdatOffset =
+ offsetof(hdatSpPcrd_t, hdatKwd);
+ this->iv_spPcrd->hdatPcrdIntData
+ [HDAT_PCRD_DA_ASCII_KWD].hdatSize = l_asciiKeywordSize;
+ this->iv_spPcrd->hdatHdr.hdatSize += l_asciiKeywordSize;
+
+ // Populating of ASCII KWD Done. Time for Full mvpd dptr
+ // Set the offset of Full MVPD int dptr based on prev dptr end point
+ this->iv_spPcrd->hdatPcrdIntData
+ [HDAT_PCRD_DA_CHIP_VPD].hdatOffset =
+ offsetof(hdatSpPcrd_t, hdatKwd) + l_asciiKeywordSize;
+
+ // Get full Mvpd.
+ char *l_FullMvpd = NULL;
+ size_t l_FullMvpdSize = HDAT_FULL_MVPD_SIZE - 1;
+
+ l_errl = hdatGetFullEepromVpd(l_pProcTarget,
+ l_FullMvpdSize,
+ l_FullMvpd);
+
+ if(l_errl)
+ {
+ HDAT_ERR("hdatGetFullEepromVpd returns Error [0x%08X]",
+ l_errl->reasonCode());
+ break;
+ }
+
+ //Virt address to fill full mvpd based on prev dptr end point
+ uint8_t *l_FullMvpdAddr = (reinterpret_cast<uint8_t *>
+ (&this->iv_spPcrd->hdatKwd)) + l_asciiKeywordSize;
+
+ if(l_FullMvpd != NULL)
+ {
+ memcpy(l_FullMvpdAddr ,(uint8_t *)l_FullMvpd,l_FullMvpdSize);
+ delete[] l_FullMvpd;
+ l_FullMvpd = NULL;
+ }
+
+ // Set the Full mvpd dptr and full pcrd struct sizes
+ this->iv_spPcrd->hdatPcrdIntData
+ [HDAT_PCRD_DA_CHIP_VPD].hdatSize = l_FullMvpdSize;
+ this->iv_spPcrd->hdatHdr.hdatSize += l_FullMvpdSize;
+
+ }
+ if( NULL != l_errl)
+ {
+ break;
+ }
+ index++;
+
+ // The PCRD structure is a fixed size and has boundary of 128 bytes
+ // so padding by 128 boundary.
+ uint32_t l_rem=0, l_pad=0;
+ l_rem=0; l_pad=0;
+ l_rem = this->iv_spPcrd->hdatHdr.hdatSize % 128;
+ l_pad = l_rem ? (128 - l_rem ) : 0;
+
+ l_addr += this->iv_spPcrd->hdatHdr.hdatSize;
+
+ // padding is allocated for size of PCRD entry. If it was
+ // smaller than 128 bytes, then you may need to bump it up
+ l_addr += l_pad;
+ this->iv_spPcrd = reinterpret_cast<hdatSpPcrd_t *>(l_addr);
+ }
+ o_size = (reinterpret_cast<uint8_t *> (this->iv_spPcrd)
+ - l_offset ) / index ;
+ o_count = index;
+ }while(0);
+
+ return l_errl;
+}
+
+/*******************************************************************************
+* hdatSetProcessorInfo
+*******************************************************************************/
+errlHndl_t HdatPcrd::hdatSetProcessorInfo(
+ const TARGETING::Target* i_pProcTarget, uint32_t i_procstatus)
+{
+ errlHndl_t l_errl = NULL;
+
+ do
+ {
+ if(NULL == i_pProcTarget)
+ {
+ HDAT_ERR("Input Target Pointer is NULL");
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_PCRD_SET_PROC_INF
+ * @reasoncode HDAT::RC_INVALID_OBJECT
+ * @userdata1 Index of proc target
+ * @userdata2 Target HUID
+ * @devdesc Input Target Pointer is NULL
+ * @custdesc Firmware encountered an internal
+ * error while retrieving target data
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCRD_SET_PROC_INF,
+ RC_INVALID_OBJECT,
+ 0,0,0,0);
+ break;
+ }
+ iv_spPcrd->hdatChipData.hdatPcrdProcChipId =
+ i_pProcTarget->getAttr<TARGETING::ATTR_ORDINAL_ID>();
+
+ iv_spPcrd->hdatChipData.hdatPcrdStatusFlags =
+ isFunctional(i_pProcTarget)? i_procstatus : HDAT_PROC_NOT_USABLE;
+
+ //Set NxFunctional State
+ iv_spPcrd->hdatChipData.hdatPcrdNxFunctional = 0;
+ TARGETING::PredicateCTM l_predNx(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_NX);
+ TARGETING::TargetHandleList l_predNxlist;
+ TARGETING::targetService().getAssociated(l_predNxlist, i_pProcTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL, &l_predNx);
+ if(l_predNxlist.size() > 0)
+ {
+ TARGETING::Target *l_predNxTarget = l_predNxlist[0];
+ iv_spPcrd->hdatChipData.hdatPcrdNxFunctional =
+ isFunctional(l_predNxTarget);
+ }
+
+ //set PORE functional state
+ iv_spPcrd->hdatChipData.hdatPcrdPoreFunctional = 0;
+ TARGETING::PredicateCTM l_predPore(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_PORE);
+ TARGETING::TargetHandleList l_predPorelist;
+ TARGETING::targetService().getAssociated(l_predPorelist, i_pProcTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL, &l_predPore);
+
+ if (l_predPorelist.size() > 0)
+ {
+ TARGETING::Target *l_predPoreTarget = l_predPorelist[0];
+ iv_spPcrd->hdatChipData.hdatPcrdPoreFunctional =
+ isFunctional(l_predPoreTarget);
+
+ }
+
+ uint32_t l_procFabricId =
+ i_pProcTarget->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>();
+
+ // Set fabric nodeid (NNN) and chip (CC) into xscom id: NN_N0CC
+ uint32_t l_XscomChipId =
+ i_pProcTarget->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
+ l_XscomChipId |= l_procFabricId << 3;
+
+
+ iv_spPcrd->hdatChipData.hdatPcrdXscomChipId = l_XscomChipId;
+
+
+ TARGETING::TargetHandleList targetListNode;
+ targetListNode.clear();
+ getParentAffinityTargets(targetListNode,i_pProcTarget,
+ TARGETING::CLASS_ENC,TARGETING::TYPE_NODE);
+ if(targetListNode.empty())
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_PCRD_SET_PROC_INF:
+ * @reasoncode HDAT::RC_EMPTY_TARGET_LIST
+ * @devdesc Input Target Pointer is NULL
+ * @custdesc Firmware encountered an internal
+ * error while retrieving target data
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCRD_SET_PROC_INF,
+ RC_EMPTY_TARGET_LIST,
+ 0,0,0,0);
+ break;
+ }
+ //get the parent node id
+ TARGETING::Target* l_pNodeTarget = targetListNode[0];
+
+ iv_spPcrd->hdatChipData.hdatPcrdDbobId =
+ l_pNodeTarget->getAttr<TARGETING::ATTR_ORDINAL_ID>();
+
+ iv_spPcrd->hdatChipData.hdatPcrdOccFuncState = 0;
+ TARGETING::PredicateCTM l_occPredicate(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_OCC);
+ TARGETING::TargetHandleList l_occList;
+ TARGETING::targetService().getAssociated(l_occList, i_pProcTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL, &l_occPredicate);
+ if(l_occList.size() > 0)
+ {
+ TARGETING::Target *l_pOccTarget = l_occList[0];
+ iv_spPcrd->hdatChipData.hdatPcrdOccFuncState =
+ isFunctional(l_pOccTarget);
+ }
+
+ iv_spPcrd->hdatChipData.hdatPcrdProcessorFruId =
+ i_pProcTarget->getAttr<TARGETING::ATTR_FRU_ID>();
+
+ uint32_t l_eclevel = 0;
+ uint32_t l_chipId = 0;
+
+ //Set the Chip EC level
+ l_errl = HDAT::hdatGetIdEc(i_pProcTarget, l_eclevel, l_chipId);
+ if(NULL != l_errl)
+ {
+ HDAT_ERR("Error [0x%08X] in call to get IdEc Failed",
+ l_errl->reasonCode());
+ break;
+ }
+ iv_spPcrd->hdatChipData.hdatPcrdChipECLevel = l_eclevel;
+ iv_spPcrd->hdatChipData.hdatPcrdHwModuleId =
+ i_pProcTarget->getAttr<TARGETING::ATTR_FRU_ID>();
+ // Set Hardware Card ID
+ uint32_t l_HWCardId = 0;
+ l_errl = hdatGetHwCardId(i_pProcTarget,l_HWCardId);
+ if(NULL != l_errl)
+ {
+ HDAT_ERR("Error [0x%08X] in call to get card id failed",
+ l_errl->reasonCode());
+ break;
+ }
+ HDAT_DBG("hw card ID:0x%llx", l_HWCardId);
+
+ iv_spPcrd->hdatChipData.hdatPcrdHwCardID = l_HWCardId;
+ iv_spPcrd->hdatChipData.hdatPcrdFabricId = l_procFabricId;
+ iv_spPcrd->hdatChipData.hdatPcrdCcmNodeID =
+ l_pNodeTarget->getAttr<TARGETING::ATTR_ORDINAL_ID>();
+
+ //set CAPP functional state
+ iv_spPcrd->hdatChipData.hdatPcrdCappFunctional = 0;
+ TARGETING::PredicateCTM l_predCapp(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_CAPP);
+ TARGETING::TargetHandleList l_predCapplist;
+ TARGETING::targetService().getAssociated(l_predCapplist, i_pProcTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL, &l_predCapp);
+
+ if (l_predCapplist.size() > 0)
+ {
+ TARGETING::Target *l_predCappTarget = l_predCapplist[0];
+ iv_spPcrd->hdatChipData.hdatPcrdCappFunctional =
+ isFunctional(l_predCappTarget)?1:0;
+ }
+
+ //set supported stop level
+ iv_spPcrd->hdatChipData.hdatPcrdStopLevelSupport =
+ i_pProcTarget->getAttr<TARGETING::ATTR_SUPPORTED_STOP_STATES>();
+ }
+ while(0);
+ return l_errl;
+}
+
+/*******************************************************************************
+* PCRD Destructor
+*******************************************************************************/
+HdatPcrd :: ~HdatPcrd()
+{
+ int rc = 0;
+ rc = mm_block_unmap(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(
+ reinterpret_cast<uint64_t>(iv_spPcrd))));
+ if( rc != 0)
+ {
+ errlHndl_t l_errl = NULL;
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_PCRD_DESTRUCTOR
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errl,
+ MOD_PCRD_DESTRUCTOR,
+ RC_DEV_MAP_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+}
+
+
+} // namespace HDATPcrd
diff --git a/src/usr/hdat/hdatpcrd.H b/src/usr/hdat/hdatpcrd.H
new file mode 100644
index 000000000..b3ac168d3
--- /dev/null
+++ b/src/usr/hdat/hdatpcrd.H
@@ -0,0 +1,267 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatpcrd.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+
+/**
+ * @file hdatpcrd.H
+ *
+ * @brief This file contains the definition of the Processor Chip Related
+ * Data structure.
+ *
+ * A C++ class is defined that is used to update the copy of the PCRD.
+ * The PCRD is written to main memory.
+ */
+
+#ifndef HDATPCRD_H
+#define HDATPCRD_H
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <hdat/hdat.H>
+#include <errl/errlentry.H>
+#include <hdat/hdat_reasoncodes.H>
+#include "hdatutil.H"
+
+namespace HDAT
+{
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+#define HDAT_NUM_P7_PCRD_ENTRIES 32
+#define HDAT_FULL_MVPD_SIZE 0x10000
+const uint16_t HDAT_PCRD_VERSION = 0x0D;
+const char HDAT_PCRD_STRUCT_NAME[7] = "SPPCRD";
+
+/** @enum hdatDataPtrs
+ * Enumeration which defines the data sections of the PCRD
+ */
+enum hdatPcrdDataPtrs
+{
+ // Values used for PCRD
+ HDAT_PCRD_DA_CHIP_INFO = 0,
+ HDAT_PCRD_DA_CHIP_TIMEOFDAY = 1,
+ HDAT_PCRD_DA_FRU_ID = 2,
+ HDAT_PCRD_DA_ASCII_KWD = 3,
+ HDAT_PCRD_DA_CHIP_VPD = 4,
+ HDAT_PCRD_DA_CNT = 5,
+ HDAT_PCRD_DA_LAST = 8,
+};
+
+/*----------------------------------------------------------------------------*/
+/* Type definitions */
+/*----------------------------------------------------------------------------*/
+
+/*
+ * @brief This defines the Chip Info structure in the PCRD.
+ */
+struct hdatPcrdChipInfo_t
+{
+ uint32_t hdatPcrdProcChipId; // 0x0000 Processor Chip ID
+ uint32_t hdatPcrdStatusFlags; // 0x0004 verify/exist flags
+ uint32_t hdatPcrdNxFunctional; // 0x0008 NX functional
+ uint32_t hdatPcrdPoreFunctional; // 0x000C Pore functional
+ uint32_t hdatPcrdXscomChipId; // 0x0010 XSCOM chip ID
+ uint32_t reserved_01; // 0x0014 ECO Cores
+ uint32_t hdatPcrdDbobId; // 0x0018 Drawer/Book/Octant/Blade ID
+ // (DBOB)
+ uint32_t hdatPcrdOccFuncState; // 0x001C OCC Functional State
+ uint32_t hdatPcrdProcessorFruId; // 0x0020 Processor FRU ID
+ uint32_t hdatPcrdChipECLevel; // 0x0024 Chip EC Level
+ uint32_t hdatPcrdHwModuleId; // 0x0028 Hardware module ID
+ uint32_t hdatPcrdHwCardID; // 0x002C HW Card ID
+ uint32_t hdatPcrdFabricId; // 0x0030 Internal Drawer Node ID
+ // (Fabric Id)
+ uint32_t hdatPcrdCcmNodeID; // 0x0034 CCM Node ID
+ uint32_t hdatPcrdCappFunctional; // 0x0038 Capp functional state
+ uint32_t hdatPcrdStopLevelSupport; // 0x003C Supported Stop Level
+} __attribute__ ((packed));
+
+/* @brief Defines 'chip time-of-day structure in the PCRD */
+struct hdatPcrdChipTod_t
+{
+ uint32_t hdatPcrdTodFlags; // 0x0000 Flags
+ uint32_t hdatPcrdTodControls; // 0x0004 Time-of-day controls
+ uint32_t hdatPcrdTodControlRegister; // 0x0008 Chip Time-of-day
+ // control register
+} __attribute__ ((packed));
+
+/** @brief Defines the PCRD.
+ * FipS updates this portion and DMAs the entire PCRD back to main memory.
+ */
+struct hdatSpPcrd_t
+{
+ hdatHDIF_t hdatHdr;
+ hdatHDIFDataHdr_t hdatPcrdIntData[HDAT_PCRD_DA_LAST];
+ hdatPcrdChipInfo_t hdatChipData;
+ hdatPcrdChipTod_t hdatChipTodData;
+ hdatFruId_t hdatFruId;
+ char *hdatKwd;
+ uint8_t *vpd_data;
+ //add in padding here. uint32_t whatever it is.
+} __attribute__ ((packed));
+
+
+/*----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatPcrd class is used to construct the PCRD object.
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that any component can create an object of this type.
+ * In particular, the object is built only in the
+ * CEC Server process when requested by the hdat component.
+ *
+ * The real purpose of the object is to create the PCRD array
+ * structure as defined by the PHYP Initialization architecture.
+ *
+ * Signal handler usage: This class is not intended to be used in a signal
+ * handler
+ *
+ * End Class Description
+ */
+class HdatPcrd
+{
+ public:
+ /**
+ * @brief Construct an HdatPcrd object
+ *
+ * This is the constructor for the HdatPcrd object.
+ *
+ * @pre None
+ *
+ * @post An HdatPcrd object pointer would be pointing to the host memory
+ * where the data would be directly written on to the memory.
+ * Each PCRD entry is initialized to indicate the processor is not
+ * installed. If the processor is installed, set the status and
+ * supply other information.
+ *
+ * @param[out] o_errlHndl
+ * If any errors occur, the HdatPcrd object is NOT constructed
+ * and errors are returned in this parameter
+
+ * @param[in] i_msAddr
+ * The main memory address that the PCRD structure will be DMA'd to.
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl.
+ *
+ */
+
+ HdatPcrd(errlHndl_t &o_errlHndl,
+ const hdatMsAddr_t &i_msAddr);
+
+ /**
+ * @brief HdatPcrd object destructor
+ *
+ * This is the destructor for an HdatPcrd object.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatPcrd object has been destroyed and can no longer be used.
+ *
+ */
+
+ ~HdatPcrd();
+
+ /**
+ * @brief Load the HdatPcrd object
+ *
+ * This function is used to the load the HdatPcrd object with all the
+ * hdatSpPcrd_t structure data. HdatPcrd object would be having all
+ * the processor data which are present and all the present which
+ * are not functional also
+ *
+ * @param[out] o_size
+ * Size of PCRD object which are written onto Host memory.
+ *
+ * @param[out] o_count
+ * Count of PCRD objects which are written onto Host memory.
+ *
+ * @pre HdatPcrd Object should be constructed with the main memory address
+ *
+ * @post The HdatPcrd object with all the PCRD entry populated.
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl.
+ */
+ errlHndl_t hdatLoadPcrd(uint32_t &o_size, uint32_t &o_count);
+
+ private:
+
+ /** Object instance Data
+ *
+ * Only one copy of this data exists in a process.
+ *
+ */
+
+ /* @li iv_msAddr - main memory address the final data structure written */
+ hdatMsAddr_t iv_msAddr;
+
+ /* @li iv_numPcrdEntries - number of PCRD entries*/
+ uint32_t iv_numPcrdEntries; // Number of PCRD entries
+
+ /* @li iv_spPcrdEntrySize - size of one entry in PCRD*/
+ uint32_t iv_spPcrdEntrySize; // Size of a PCRD entry
+
+ /* @li iv_spPcrd - pointer to the first PCRD Entry */
+ hdatSpPcrd_t *iv_spPcrd;
+
+ /**
+ * @brief Set the Processor Chip Related Info
+ *
+ * This function is an helper function used to set the processor chip
+ * specific info into the HdatPcrd object with for all the
+ * hdatHDIF_t, hdatHDIFDataHdr_t, hdatPcrdChipInfo_t,
+ * hdatPcrdChipTod_t and module VPD related data into structure data.
+ *
+ * @pre HdatPcrd Object should be constructed with the main memory address
+ * Target pointer to the present procs in the system
+ *
+ * @post The HdatPcrd object with all the processor chipd related data
+ * populated.
+ *
+ * @param[in] i_pTarget
+ * Proc target pointer. Must not be NULL (otherwise call will return an
+ * error log). Must be a valid target from the system blueprint.
+ *
+ * @param[in] i_procstatus
+ * Processor status place holder
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by o_errlHndl.
+ */
+
+ errlHndl_t hdatSetProcessorInfo(const TARGETING::Target* i_pProcTarget,
+ uint32_t i_procstatus);
+};
+
+
+} //namespace HDAT
+#endif // HDATPCRD_H
diff --git a/src/usr/hdat/hdatram.C b/src/usr/hdat/hdatram.C
new file mode 100755
index 000000000..a0d671f8e
--- /dev/null
+++ b/src/usr/hdat/hdatram.C
@@ -0,0 +1,194 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatram.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+
+/**
+ * @file hdatram.C
+ *
+ * @brief This file contains the implementation of the HdatRam class.
+ *
+ */
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include "hdatram.H" // HdatRam class definition
+#include "hdatutil.H" // utility functions
+#include "hdatmsvpd.H"
+
+#include <stdio.h>
+
+
+namespace HDAT
+{
+/*----------------------------------------------------------------------------*/
+/* Global variables */
+/*----------------------------------------------------------------------------*/
+uint32_t HdatRam::cv_actualCnt;
+
+vpdData cvpdData[] =
+{
+// { CVPD::VINI, CVPD::RT },
+ { CVPD::VINI, CVPD::DR },
+ { CVPD::VINI, CVPD::FN },
+ { CVPD::VINI, CVPD::PN },
+ { CVPD::VINI, CVPD::SN },
+ { CVPD::VINI, CVPD::CC },
+// { CVPD::VINI, CVPD::PR },
+ //{ CVPD::VINI, CVPD::SZ },
+ { CVPD::VINI, CVPD::HE },
+ { CVPD::VINI, CVPD::CT },
+ { CVPD::VINI, CVPD::HW },
+ // { CVPD::VINI, CVPD::B3 },
+ // { CVPD::VINI, CVPD::B4 },
+ // { CVPD::VINI, CVPD::B7 },
+ { CVPD::VINI, CVPD::PF },
+};
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+
+
+/** @brief See the prologue in hdatram.H
+ */
+HdatRam::HdatRam(errlHndl_t &o_errlHndl,
+ TARGETING::Target * i_target,
+ uint32_t i_resourceId,
+ uint32_t i_slcaIndex)
+
+: HdatHdif(o_errlHndl, HDAT_RAM_STRUCT_NAME, HDAT_RAM_LAST, cv_actualCnt++,
+ HDAT_NO_CHILD, HDAT_RAM_VERSION),
+ iv_kwdSize(0), iv_kwd(NULL)
+{
+ HDAT_ENTER();
+
+
+ iv_fru.hdatResourceId = i_resourceId;
+
+ if ( i_slcaIndex != 0)
+ {
+ iv_fru.hdatSlcaIdx = i_slcaIndex;
+ }
+ else
+ {
+ iv_fru.hdatSlcaIdx = i_target->getAttr<TARGETING::ATTR_SLCA_INDEX>();
+ }
+
+ hdatGetAsciiKwdForSpd(i_target,iv_kwdSize,iv_kwd);
+
+ // Update the base class internal data pointers
+ // When the data is written to the file by commit(), it must be done in the
+ // same order as these addData() calls
+ this->addData(HDAT_RAM_FRU_ID, sizeof(hdatFruId_t));
+ this->addData(HDAT_RAM_KWD, iv_kwdSize);
+ this->addData(HDAT_RAM_ID, sizeof(hdatRamAreaId_t));
+ this->addData(HDAT_RAM_SIZE, sizeof(hdatRamAreaSize_t));
+ this->align();
+
+ HDAT_EXIT();
+ return;
+}
+
+
+/** @brief See the prologue in hdatram.H
+ */
+HdatRam::~HdatRam()
+{
+ HDAT_ENTER();
+
+ delete [] iv_kwd;
+
+ HDAT_EXIT();
+ return;
+}
+
+
+/** @brief See the prologue in hdatram.H
+ */
+uint32_t HdatRam::getRamSize()
+{
+ uint32_t l_size = 0;
+ // Start committing the base class data
+ l_size += this->getSize();
+
+ // Write the various pieces of data from this derived class
+ l_size += sizeof(hdatFruId_t);
+ if (iv_kwdSize > 0)
+ {
+ l_size += iv_kwdSize;
+ }
+ l_size += sizeof(hdatRamAreaId_t);
+ l_size += sizeof(hdatRamAreaSize_t);
+
+ l_size+= this->endCommitSize();
+
+ return l_size;
+}
+
+/** @brief See the prologue in hdatram.H
+ */
+void HdatRam::commit(UtilMem &i_data)
+{
+
+ // Start committing the base class data
+ this->startCommit(i_data);
+
+ i_data.write(&iv_fru, sizeof(hdatFruId_t));
+ if (iv_kwdSize > 0)
+ {
+ i_data.write(iv_kwd,iv_kwdSize);
+ }
+ i_data.write(&iv_ramArea, sizeof(hdatRamAreaId_t));
+ i_data.write(&iv_ramSize, sizeof(hdatRamAreaSize_t));
+
+ this->endCommit(i_data);
+
+}
+
+
+/** @brief See the prologue in hdatram.H
+ */
+void HdatRam::prt()
+{
+ HDAT_INF(" **** HdatRam start ****");
+ HDAT_INF(" cv_actualCnt = %u", cv_actualCnt);
+ HDAT_INF(" iv_kwdSize = %u", iv_kwdSize);
+ this->print();
+ //hdatPrintFruId(&iv_fru);
+ hdatPrintKwd(iv_kwd, iv_kwdSize);
+
+ HDAT_INF(" **hdatRamAreaId_t**");
+ HDAT_INF(" hdatRamAreaId = %u", iv_ramArea.hdatRamAreaId);
+ HDAT_INF(" hdatRamStatus = 0X %04X", iv_ramArea.hdatRamStatus);
+
+ HDAT_INF(" **hdatRamAreaSize_t**");
+ HDAT_INF(" hdatReserved1 = %u", iv_ramSize.hdatReserved1);
+ HDAT_INF(" hdatRamTotalSize = %u", iv_ramSize.hdatRamTotalSize);
+
+ HDAT_INF(" **** HdatRam end ****");
+
+ return;
+}
+}
diff --git a/src/usr/hdat/hdatram.H b/src/usr/hdat/hdatram.H
new file mode 100755
index 000000000..4c8e2ec20
--- /dev/null
+++ b/src/usr/hdat/hdatram.H
@@ -0,0 +1,257 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatram.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATRAM_H
+#define HDATRAM_H
+
+/**
+ * @file hdatram.H
+ *
+ * @brief This file contains the class definition for the RAM object which
+ * describes memory DIMMS. This structure is part of the larger
+ * mainstore VPD structure which describes the various chips which
+ * make up the memory subsystem.
+ *
+ */
+
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <stdint.h> // standard types
+#include <hdat/hdat.H> // HDAT header type definitions
+#include "hdathdif.H" // HdatHdif base class definition
+#include <errl/errlentry.H> // ErrlEntry class
+
+namespace HDAT
+{
+
+/*----------------------------------------------------------------------------*/
+/* Typedefs */
+/*----------------------------------------------------------------------------*/
+
+/** @brief Structure definition for the RAM ID and status
+ */
+struct hdatRamAreaId_t
+{
+ uint16_t hdatRamAreaId; // 0x0000 Identifier for this RAM area
+ uint16_t hdatRamStatus; // 0x0002 Status of the RAM DIMM
+} __attribute__ ((packed));
+
+
+/** @brief Structure definition for the RAM size
+ */
+struct hdatRamAreaSize_t
+{
+ uint32_t hdatReserved1; // 0x0000 Reserved to make hdatRamTotalSize 8
+ // bytes in future
+ uint32_t hdatRamTotalSize; // 0x0004 Total size of configured main store
+ // in this RAM area in megabytes
+} __attribute__ ((packed));
+
+
+/*---------------------------------------------------------------------------*/
+/* Constants */
+/*---------------------------------------------------------------------------*/
+const char HDAT_RAM_STRUCT_NAME[] = "RAM ";
+
+const uint16_t HDAT_RAM_VERSION = 0x0020;
+
+
+/** @brief eye catcher for the HDIF header for the RAM data area
+ */
+
+/** @enum hdatDataPtrs
+ * Constants for the internal data pointers that are added to the base class
+ */
+enum hdatRamDataPtrs
+{
+ HDAT_RAM_FRU_ID = 0,
+ HDAT_RAM_KWD = 1,
+ HDAT_RAM_ID = 2,
+ HDAT_RAM_SIZE = 3,
+ HDAT_RAM_RESERVED1 = 4,
+ HDAT_RAM_RESERVED2 = 5,
+ HDAT_RAM_LAST = 6
+};
+/*----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatRam class is used to construct objects for memory DIMMs.
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that anyone can create an object of this type. In particular,
+ * the object is built only as a internal object within the
+ * HdatMsArea object.
+ *
+ * The real purpose of the object is to create the various RAM
+ * structures as defined by the PHYP Initialization architecture
+ * This data structure is eventually DMA'd to main memory. The
+ * class is not defined to be a general purpose interface for
+ * building this object by anyone other than the hdatstep process.
+ *
+ * Thread safety: An HdatRam object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by
+ * multiple threads at the same time. An object can be used by
+ * multiple threads if the threads serialize access. And of
+ * course, each thread can use its own object with no concerns
+ * about what other threads are doing.
+ *
+ * Signal handler usage: This class is not intended to be used in a signal
+ * handler and nothing has been done to try and make it safe to use
+ * in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatRam : public HdatHdif
+{
+public:
+
+
+ /**
+ * @brief Construct an HdatRam object.
+ *
+ * This is the constructor for the HdatRam object.
+ *
+ * If you are constructing this object on the heap by using new, then
+ * you must check the pointer returned from new to see if it is null.
+ * If it is null, new failed to allocate storage and the constructor
+ * was not called. If it is not null, then you must check o_errlHndl
+ * to see if the constructor ran successfully. If o_errlHndl indicates
+ * an error was reported by the constructor, new has already allocated
+ * heap storage and the object must be deleted in order to free the
+ * heap storage.
+ *
+ * @pre None
+ *
+ * @post An HdatRam object has been constructed.
+ * Heap storage has been allocated.
+ *
+ * @param[out] o_errlHndl - If any errors occur, the HdatRam object
+ * is NOT constructed and errors are returned in this parameter
+ * @param[in] i_resourceId - input parameter - The FRU's resource id
+ * @param[in] i_slcaIndex - input parameter - ms area slca index,
+ * if not provided then add dimms slca index
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+ HdatRam(errlHndl_t &o_errlHndl,
+ TARGETING::Target* i_target,
+ uint32_t i_resourceId,
+ uint32_t i_slcaIndex=0);
+
+
+ /**
+ * @brief HdatRam object destructor
+ *
+ * This is the destructor for an HdatRam object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatRam object has been destroyed and can no longer be used.
+ *
+ */
+ virtual ~HdatRam();
+
+ /**
+ * @brief Get Ram area size
+ *
+ * This method invokes ram getSize routine for all the child pointers
+ * and gets the size.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @return - returns size value
+ *
+ */
+ uint32_t getRamSize();
+
+ /**
+ * @brief Writes the MS area data in main store memory
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param[inout] i_data - memory used to write the data
+ *
+ *
+ */
+ void commit(UtilMem &i_data);
+
+ /**
+ * @brief Print an HdatRam object.
+ *
+ * This method is a debug mthod which prints out a RAM object.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ */
+ void prt();
+
+ /** Object Instance Data
+ * @li iv_ramArea - RAM Id structure
+ * @li iv_ramSize - RAM size structure
+ */
+ hdatRamAreaId_t iv_ramArea;
+ hdatRamAreaSize_t iv_ramSize;
+
+private:
+
+
+ /** Object Instance Data
+ *
+ * @li iv_kwdSize - size of the VPD ASCII keyword
+ * @li iv_kwd - ptr to the VPD ASCII keyword
+ * @li iv_fru - FRU id structure
+ */
+ size_t iv_kwdSize;
+ char *iv_kwd;
+ hdatFruId_t iv_fru;
+
+ /** Class (static) Data
+ *
+ * Only one copy of this data exists in a process.
+ *
+ * @li cv_actualCnt - a count of how many HdatRam objects are created
+ */
+ static uint32_t cv_actualCnt;
+
+}; // end of HdatRam class
+
+}
+
+#endif // HDATRAM_H
diff --git a/src/usr/hdat/hdatspiraH.C b/src/usr/hdat/hdatspiraH.C
new file mode 100755
index 000000000..b0bab3ed9
--- /dev/null
+++ b/src/usr/hdat/hdatspiraH.C
@@ -0,0 +1,377 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatspiraH.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+/**
+ * @file hdatspiraH.H
+ *
+ * @brief This file contains the definition of the Service Processor Interface
+ * Root Array Secure boot (SPIRA-H) data structure. This data structure
+ * is prebuilt as part of one of the LIDS loaded into memory.
+ *
+ * Usage note: The SPIRA-H structure is built as part of the host LIDs.
+ * These are big endian structures. If this structure is used on a little
+ * endian machine, the user is responsible for performing big endian to
+ * little endian conversions.
+ */
+
+/*-----------------------------------------------------------------------------*/
+/* Includes */
+/*-----------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include "hdatspiraH.H"
+#include "hdatutil.H"
+#include "hdatvpd.H"
+#include <util/align.H>
+#include <targeting/common/util.H>
+/*-----------------------------------------------------------------------------*/
+/* Global variables */
+/*-----------------------------------------------------------------------------*/
+extern trace_desc_t *g_trac_hdat;
+/*-----------------------------------------------------------------------------*/
+/* Constants */
+/*-----------------------------------------------------------------------------*/
+const uint16_t HDAT_SPIRAH_VERSION = 0x50;
+
+using namespace TARGETING;
+
+namespace HDAT
+{
+
+/**
+ * @brief Construct an HdatSpiraH object.
+ *
+ * This function maps the Service Processor Interface Root Array (SPIRA-H)
+ * structure from the mainstore address where the containing lid loaded.
+ *
+ * @pre The SPIRA-H containing Lid must have loaded in mainstore.
+ *
+ * @post The SPIRA-H data mapped to a HB process' memory
+ *
+ * @param o_errlHndl - output parameter - error log handle
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t
+ *
+ */
+HdatSpiraH::HdatSpiraH(errlHndl_t &o_errlHndl, hdatMsAddr_t &i_msAddr)
+{
+
+ HDAT_ENTER();
+
+ HDAT_DBG("HdatSpiraH i_msAddr addr hi 0x%08X lo 0x%08X",
+ i_msAddr.hi, i_msAddr.lo);
+ memcpy(&iv_msAddr , &i_msAddr , sizeof(hdatMsAddr_t));
+
+ // Get Target Service, and the system target.
+ TargetService& l_targetService = targetService();
+ TARGETING::Target* l_sysTarget = NULL;
+ (void) l_targetService.getTopLevelTarget(l_sysTarget);
+
+ // asserting
+ assert(l_sysTarget != NULL);
+
+ uint64_t l_hrmor = l_sysTarget->getAttr<ATTR_PAYLOAD_BASE>();
+ l_hrmor = l_sysTarget->getAttr<ATTR_PAYLOAD_BASE>() * MEGABYTE;
+ iv_msAddr +=l_hrmor;
+
+ // Allocate space for spiraH in process memory
+
+ iv_spirah = reinterpret_cast<hdatSpiraH_t *>(calloc(sizeof(hdatSpiraH_t),
+ 1));
+
+ if(NULL == o_errlHndl)
+ { // Set SPIRA-H to defaults
+ setSpiraHHdrs();
+ }
+
+ // Now get the spiraH from mainstore address.
+ o_errlHndl = getSpiraH();
+
+ HDAT_EXIT();
+ return;
+}
+
+/**
+ * @brief This function gets the spirah from the stored mainstore adress.
+ * The mainstore address is where spirah is loaded as part of lid.
+ *
+ * @pre The primary LID which contains the NACA and the primary/secondary LID
+ * which contains the SPIRA-H must have been loaded
+ *
+ * @post The SPIRA-H is copied into process space.
+ *
+ */
+errlHndl_t HdatSpiraH::getSpiraH()
+{
+ errlHndl_t l_errlHndl = NULL;
+ HDAT_ENTER();
+
+ if(iv_msAddr != 0)
+ {
+ uint64_t l_base_addr_down = ALIGN_PAGE_DOWN((uint64_t)iv_msAddr);
+ iv_virt_addr = (uint8_t *)mm_block_map(
+ reinterpret_cast<void*>(l_base_addr_down),
+ (ALIGN_PAGE(sizeof(hdatSpiraH_t)) + PAGESIZE));
+ iv_virt_addr = iv_virt_addr +
+ ((uint64_t)iv_msAddr - ALIGN_PAGE_DOWN((uint64_t)iv_msAddr));
+
+ memcpy((void *)iv_spirah,(void *)iv_virt_addr,sizeof(hdatSpiraH_t));
+ }
+ else
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_HDAT_GET_SPIRAH
+ * @reasoncode HDAT::RC_NULL_PTR_PASSED
+ * @devdesc Null passed for spirah ms addr
+ * @custdesc Firmware encountered an internal error.
+ */
+
+ hdatBldErrLog(l_errlHndl,
+ MOD_HDAT_GET_SPIRAH,
+ RC_NULL_PTR_PASSED,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+ HDAT_EXIT();
+ return l_errlHndl;
+}
+
+
+/**
+ * @brief HdatSpiraH object destructor
+ *
+ * This is the destructor for an HdatSpiraH object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatSpiraH object has been destroyed and can no longer be used.
+ *
+ */
+HdatSpiraH::~HdatSpiraH()
+{
+ errlHndl_t l_errlHndl = NULL;
+ uint32_t rc=0;
+ HDAT_ENTER();
+
+ free(iv_spirah);
+ if(iv_virt_addr != NULL)
+ {
+ rc = mm_block_unmap(reinterpret_cast<void*>(
+ ALIGN_PAGE_DOWN((uint64_t)iv_virt_addr)));
+ if( rc != 0)
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_HDAT_SPIRAH_DTOR
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @userdata1 Spirah address hi
+ * @userdata2 Spirah address lo
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(l_errlHndl,
+ HDAT::MOD_HDAT_SPIRAH_DTOR,
+ RC_DEV_MAP_FAIL,
+ static_cast<uint32_t>(iv_msAddr>> 32),
+ static_cast<uint32_t>(iv_msAddr),
+ 0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+ }
+
+ HDAT_EXIT();
+}
+
+
+/**
+ * @brief This function computes the address of a 5-tuple entry within the
+ * SPIRA-H structure and returns it.
+ *
+ * Usage note: The SPIRA-H structure is built as part of the host LIDs.
+ * These are big endian structures. This function performs any
+ * big endian to little endian conversions needed.
+ *
+ * @pre None
+ *
+ * @post A copy of the desired 5-tuple returned, with any endian conversion done.
+ *
+ * @param i_dataArea - input parameter - an enumeration for the 5-tuple entry
+ * being requested.
+ * @param o_entry - output parameter - a copy of the 5-tuple entry being
+ * requested, with any endian conversion already performed.
+ *
+ * @return NONE
+ */
+void HdatSpiraH::getSpiraHEntry(hdatSpiraHDataAreas i_dataArea,
+ hdat5Tuple_t &o_entry)
+{
+ HDAT_ENTER();
+ hdatHDIF_t *l_hdif;
+ hdatHDIFDataHdr_t *l_dataHdr;
+ hdat5Tuple_t *l_entry;
+ hdatHDIFDataArray_t *l_arrayHdr;
+
+ // Compute the address of the entry in the SPIRA-H the caller wants. This
+ // entry is a 5-tuple for a particular data structure.
+ l_hdif = reinterpret_cast<hdatHDIF_t *>(iv_spirah);
+
+ l_dataHdr = reinterpret_cast<hdatHDIFDataHdr_t *>(reinterpret_cast<char *>
+ (l_hdif) + l_hdif->hdatDataPtrOffset);
+
+ l_arrayHdr = reinterpret_cast<hdatHDIFDataArray_t *>(
+ reinterpret_cast<char *>(l_hdif) + l_dataHdr->hdatOffset);
+
+ l_entry = reinterpret_cast<hdat5Tuple_t *>(reinterpret_cast<char *>
+ (l_arrayHdr) + l_arrayHdr->hdatOffset +
+ (l_arrayHdr->hdatAllocSize) * i_dataArea);
+
+ o_entry.hdatAbsAddr.hi = l_entry->hdatAbsAddr.hi;
+ o_entry.hdatAbsAddr.lo = l_entry->hdatAbsAddr.lo;
+ o_entry.hdatAllocCnt = l_entry->hdatAllocCnt;
+ o_entry.hdatActualCnt = l_entry->hdatActualCnt;
+ o_entry.hdatAllocSize = l_entry->hdatAllocSize;
+ o_entry.hdatActualSize = l_entry->hdatActualSize;
+ o_entry.hdatTceOffset = l_entry->hdatTceOffset;
+ HDAT_EXIT();
+ return;
+}
+
+/**
+ * @brief This function updates a SPIRA-H entry. Any required endian conversion
+ * is performed on the 5-tuple entry before the update.
+ *
+ * @pre None
+ *
+ * @post The SPIRA-H has been updated
+ *
+ * @param i_dataArea - input parameter - An enumeration for the 5-tuple entry
+ * being updated.
+ * @param i_entry - input parameter - the 5-tuple entry being updated.
+ */
+void HdatSpiraH::chgSpiraHEntry(hdatSpiraHDataAreas i_dataArea,
+ const hdat5Tuple_t &i_entry)
+{
+ HDAT_ENTER();
+ hdatHDIF_t *l_hdif;
+ hdatHDIFDataHdr_t *l_dataHdr;
+ hdatHDIFDataArray_t *l_arrayHdr;
+ hdat5Tuple_t *l_entry;
+
+ // Compute the address of the entry in the SPIRA-H the caller wants. This
+ // entry is a 5-tuple for a particular data structure.
+ l_hdif = reinterpret_cast<hdatHDIF_t *>(iv_spirah);
+
+ l_dataHdr = reinterpret_cast<hdatHDIFDataHdr_t *>(reinterpret_cast<char *>
+ (l_hdif) + l_hdif->hdatDataPtrOffset);
+
+ l_arrayHdr = reinterpret_cast<hdatHDIFDataArray_t *>(
+ reinterpret_cast<char *>(l_hdif) + l_dataHdr->hdatOffset);
+
+ l_entry = reinterpret_cast<hdat5Tuple_t *>(reinterpret_cast<char *>
+ (l_arrayHdr) + l_arrayHdr->hdatOffset +
+ l_arrayHdr->hdatAllocSize * i_dataArea);
+
+ // Update the data in the SPIRA-H entry.
+ l_entry->hdatAbsAddr.hi = i_entry.hdatAbsAddr.hi;
+ l_entry->hdatAbsAddr.lo = i_entry.hdatAbsAddr.lo;
+ l_entry->hdatAllocCnt = i_entry.hdatAllocCnt;
+ l_entry->hdatActualCnt = i_entry.hdatActualCnt;
+ l_entry->hdatAllocSize = i_entry.hdatAllocSize;
+ l_entry->hdatActualSize = i_entry.hdatActualSize;
+ l_entry->hdatTceOffset = i_entry.hdatTceOffset;
+
+ HDAT_EXIT();
+ return;
+}
+
+/**
+ * @brief This routine initializes the SPIRA-H HDIF header and clears the N-Tuple array
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @retval no errors currently defined
+ */
+void HdatSpiraH::setSpiraHHdrs()
+{
+ HDAT_ENTER();
+ iv_spirah->hdatHDIF.hdatStructId = HDAT_HDIF_STRUCT_ID;
+ iv_spirah->hdatHDIF.hdatInstance = 0;
+ iv_spirah->hdatHDIF.hdatVersion = HDAT_SPIRAH_VERSION;
+ iv_spirah->hdatArrayInfo.hdatArrayCnt = HDAT_SPIRAH_DA_LAST;
+ iv_spirah->hdatHDIF.hdatSize = sizeof(hdatSpiraH_t);
+
+ iv_spirah->hdatHDIF.hdatHdrSize = sizeof(hdatHDIF_t);
+ iv_spirah->hdatHDIF.hdatDataPtrOffset = sizeof(hdatHDIF_t);
+ iv_spirah->hdatHDIF.hdatDataPtrCnt = 1;
+ iv_spirah->hdatHDIF.hdatChildStrCnt = 0;
+ iv_spirah->hdatHDIF.hdatChildStrOffset = 0;
+
+ memcpy(iv_spirah->hdatHDIF.hdatStructName, HDAT_SPIRAH_EYE_CATCHER, sizeof(iv_spirah->hdatHDIF.hdatStructName));
+
+ iv_spirah->hdatDataHdr.hdatOffset = offsetof(hdatSpiraH_t, hdatArrayInfo);
+ iv_spirah->hdatDataHdr.hdatSize = sizeof(hdatHDIFDataArray_t) + sizeof(iv_spirah->hdatDataArea);
+ iv_spirah->hdatArrayInfo.hdatOffset = sizeof(hdatHDIFDataArray_t);
+ iv_spirah->hdatArrayInfo.hdatAllocSize = sizeof(hdat5Tuple_t);
+ iv_spirah->hdatArrayInfo.hdatActSize = offsetof(hdat5Tuple_t, hdatReserved1);
+
+ memset(iv_spirah->hdatDataArea, 0, sizeof((iv_spirah->hdatDataArea)));
+ HDAT_EXIT();
+ return;
+}
+
+
+void HdatSpiraH::chgSpiraHEntry(hdatSpiraHDataAreas i_dataArea,
+ uint32_t i_actCount,uint32_t i_actSize)
+{
+ HDAT_ENTER();
+ hdatSpiraH_t * l_temp;
+
+ l_temp = reinterpret_cast<hdatSpiraH_t *>(iv_virt_addr);
+ HDAT_DBG("updating the spiraH hostdata area with count=0x%x and size=0x%x",
+ i_actCount,i_actSize);
+ l_temp->hdatDataArea[i_dataArea].hdatActualCnt = i_actCount;
+ l_temp->hdatDataArea[i_dataArea].hdatActualSize = i_actSize;
+
+ HDAT_DBG("actual count=0x%x, actual size=0x%x",
+ l_temp->hdatDataArea[i_dataArea].hdatActualCnt,
+ l_temp->hdatDataArea[i_dataArea].hdatActualSize);
+
+ HDAT_EXIT();
+}
+
+} //HDAT
diff --git a/src/usr/hdat/hdatspiraH.H b/src/usr/hdat/hdatspiraH.H
new file mode 100755
index 000000000..c0d336794
--- /dev/null
+++ b/src/usr/hdat/hdatspiraH.H
@@ -0,0 +1,247 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatspiraH.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATSPIRAH_H
+#define HDATSPIRAH_H
+
+/**
+ * @file hdatspiraH.H
+ *
+ * @brief This file contains the definition of the Service Processor Interface
+ * Root Array Secure boot (SPIRA-H) data structure. This data structure
+ * is prebuilt as part of one of the LIDS loaded into memory.
+ *
+ * Usage note: The SPIRA-H structure is built as part of the host LIDs.
+ * These are big endian structures. If this structure is used on a little
+ * endian machine, the user is responsible for performing big endian to
+ * little endian conversions.
+ */
+
+/*-----------------------------------------------------------------------------*/
+/* Includes */
+/*-----------------------------------------------------------------------------*/
+#include <stdint.h> // integer data type definitions
+#include <hdat/hdat.H>
+#include "hdathdif.H"
+/*-----------------------------------------------------------------------------*/
+/* Constants */
+/*-----------------------------------------------------------------------------*/
+const char HDAT_SPIRAH_EYE_CATCHER[] = "SPIRAH";
+
+namespace HDAT
+{
+
+/*-----------------------------------------------------------------------------*/
+/* Type definitions */
+/*-----------------------------------------------------------------------------*/
+
+
+/** @enum hdatSpiraHDataAreas
+ * This enumeration defines the various data areas in spiraH
+ * This list must be kept in the same order as the 5-tuple entries in
+ * the SPIRA-H.
+ *
+ * If the order is changed, entries are added, or entries are deleted,
+ * update.
+ */
+enum hdatSpiraHDataAreas
+{
+ HDAT_SPIRAH_DA_FIRST = 0,
+ HDAT_SEC_HOST_DATA_AREA = 0,
+ HDAT_SEC_PROC_INIT = 1, // phyp-supplied processor init data
+ HDAT_SEC_CPU_CTRL = 2, // CPU controls
+ HDAT_SEC_MS_DUMP_SRC_TBL = 3, // mainstore dump source table (can change at run time)
+ HDAT_SEC_MS_DUMP_DST_TBL = 4, // mainstore dump destination table (can change at run time)
+ HDAT_SEC_MS_DUMP_RSLT_TBL = 5, // mainstore dump results table
+
+ HDAT_SPIRAH_DA_LAST = 6
+};
+
+/*-----------------------------------------------------------------------------*/
+/* Type definitions */
+/*-----------------------------------------------------------------------------*/
+
+/** @brief The SPIRA-H is composed of an HDIF header and an array. Each array
+ * entry is an n-tuple. That is, it is a structure with a particular
+ * number of fields
+ */
+struct hdatSpiraH_t
+{
+ hdatHDIF_t hdatHDIF; // 0x0000 Common HDIF header
+ hdatHDIFDataHdr_t hdatDataHdr; // 0x0020 Data "pointers"
+ uint8_t hdatReserved1[8]; // 0x0028 Padding/future growth
+ hdatHDIFDataArray_t hdatArrayInfo; // 0x0030 Info on 5-tuple array
+ hdat5Tuple_t hdatDataArea[HDAT_SPIRAH_DA_LAST]; //0x0040 5-tuple array
+} __attribute__ ((packed));
+
+/*-----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*-----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatSpiraH class is used to construct the SPIRA-H object.
+ *
+ * Description: The SPIRA-H object contains mainstore addresses and other information
+ * about various hypervisor data structures.
+ * Constructing thr SPIRA-H objects maps the spiraH into a
+ * process' address space.
+ *
+ * Thread safety: An HdatSpiraH object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by multiple
+ * threads at the same time.
+ *
+ * Signal handler usage: This class is not intended to be used in a signal handler
+ * and nothing has been done to try and make it safe to use
+ * in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatSpiraH
+{
+public:
+
+ /* @brief Construct an HdatSpiraH object.
+ *
+ * This function maps the Service Processor Interface Root Array (SPIRA-H)
+ * structure from hypervisor lid space to a process' address space.
+ *
+ * @pre The SPIRA-H containing Lid must have loaded on memory
+ *
+ * @post The SPIRA-H is mapped to a process' memory
+ *
+ * @param o_errlHndl - output parameter - error log handle
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ */
+ HdatSpiraH(errlHndl_t &o_errlHndl, hdatMsAddr_t &i_msAddr);
+
+ /**
+ * @brief HdatSpiraH object destructor
+ *
+ * This is the destructor for an HdatSpiraH object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatSpiraH object has been destroyed and can no longer be used.
+ *
+ */
+ virtual ~HdatSpiraH();
+
+ /**
+ * @brief This function computes the address of a 5-tuple entry within the
+ * SPIRA-H structure and returns it.
+ *
+ * Usage note: The SPIRA-H structure is built as part of the host LIDs.
+ * These are big endian structures.
+ *
+ * @pre None
+ *
+ * @post A copy of the desired 5-tuple returned, with any endian conversion done.
+ *
+ * @param i_dataArea - input parameter - an enumeration for the 5-tuple entry
+ * being requested.
+ * @param o_entry - output parameter - a copy of the 5-tuple entry being
+ * requested, with any endian conversion already performed.
+ *
+ * @return NONE
+ */
+ void getSpiraHEntry(hdatSpiraHDataAreas i_dataArea,
+ hdat5Tuple_t &o_entry);
+
+ /**
+ * @brief This function updates a SPIRA-H entry. Any required endian conversion
+ * is performed on the 5-tuple entry before the update.
+ *
+ * @pre None
+ *
+ * @post The SPIRA-H has been updated
+ *
+ * @param i_dataArea - input parameter - An enumeration for the 5-tuple entry
+ * being updated.
+ * @param i_entry - input parameter - the 5-tuple entry being updated.
+ */
+ void chgSpiraHEntry(hdatSpiraHDataAreas i_dataArea,
+ const hdat5Tuple_t &i_entry);
+
+ /**
+ * @brief This function updates a data area entry for spiraH in main memory
+ *
+ * @pre spiraH is present at main memory
+ *
+ * @param i_dataArea - input parameter -An enumeration for the 5-tuple entry
+ * being updated
+ *
+ * @param i_actCount,i_actSize - actual count and size of the data area
+ */
+
+ void chgSpiraHEntry(hdatSpiraHDataAreas i_dataArea,
+ uint32_t i_actCount,uint32_t i_actSize);
+private:
+
+ /**
+ * @brief This function copies the Service Processor Interface Root Array (SPIRA-H)
+ * structure from phyp lid space.
+ *
+ * @pre The primary LID which contains the NACA and the primary/secondary LID
+ * which contains the SPIRA-H must have been Loaded to memory.
+ *
+ * @post The SPIRA-H is copied from main memory into iv_spirah
+ *
+ */
+
+ errlHndl_t getSpiraH();
+
+ /**
+ * @brief This routine initializes the SPIRA-H HDIF header and clears the N-Tuple array
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @retval no errors currently defined
+ */
+ void setSpiraHHdrs();
+
+
+ /** Object Instance Data
+ *
+ * @li iv_spirah - pointer to the SPIRA-H structure
+ * @li iv_msAddr - Mainstore address of spiraH
+ * @li iv_virt_addr - virtual address mapped to phyisical ms addr of spirah
+ */
+ hdatSpiraH_t *iv_spirah;
+ uint64_t iv_msAddr;
+ uint8_t *iv_virt_addr;
+
+}; // end of HdatSpiraH class
+
+} //HDAT
+#endif // HDATSPIRAH_H
diff --git a/src/usr/hdat/hdatspiraS.C b/src/usr/hdat/hdatspiraS.C
new file mode 100755
index 000000000..b6fc0b049
--- /dev/null
+++ b/src/usr/hdat/hdatspiraS.C
@@ -0,0 +1,694 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatspiraS.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+/**
+ * @file hdatspiraS.C
+ *
+ * @brief
+ * This file contains the definition of the Service Processor Interface
+ * Root Array Secure boot (SPIRA-S) data structure. This data structure
+ * is built by FSP and placed at the beginning of the host data areas
+ * space located using the SPIRA-H. Data areas pointed to by this portion
+ * of the SPIRA will be located after it in the host data areas space.
+ *
+ */
+
+
+/*---------------------------------------------------------------------------*/
+/* Includes */
+/*---------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include "hdatspiraS.H"
+#include "hdatutil.H"
+#include <hdat/hdat_reasoncodes.H>
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include "hdatpcia.H"
+#include "hdatpcrd.H"
+#include "hdathostslcadata.H"
+#include "hdatiplparms.H"
+#include "hdatspsubsys.H"
+#include "hdatmsvpd.H"
+#include "hdathostservices.H"
+#include "hdatbldda.H"
+#include "hdatiohub.H"
+#include "hdathbrt.H"
+#include <util/align.H>
+#include <targeting/common/commontargeting.H>
+
+
+
+namespace HDAT
+{
+/*---------------------------------------------------------------------------*/
+/* Global variables */
+/*---------------------------------------------------------------------------*/
+extern trace_desc_t *g_trac_hdat;
+extern errlHndl_t hdatLoadIoData(const hdatMsAddr_t &i_msAddr,
+ uint32_t &o_size,
+ uint32_t &o_count);
+
+
+/*****************************************************************************/
+// HdatSpiraS constructor
+/*****************************************************************************/
+
+
+HdatSpiraS::HdatSpiraS(const hdatMsAddr_t &i_msAddr)
+: iv_spirasSize(0), iv_spiras(NULL)
+{
+ HDAT_ENTER();
+
+
+ iv_spirasSize = sizeof(hdatSpiraS_t);
+
+
+ uint64_t l_base_addr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo;
+
+ HDAT_DBG("l_base_addr at SPIRA-S=0x%016llX",l_base_addr);
+
+
+ //calculate the hrmor and add to base address
+ TARGETING::Target * sys = NULL;
+ TARGETING::targetService().getTopLevelTarget( sys );
+
+ assert(sys != NULL);
+
+ uint64_t l_hrmor =
+ sys->getAttr<TARGETING::ATTR_PAYLOAD_BASE>()*MEGABYTE;
+
+ HDAT_DBG("HRMOR=0x%08x",l_hrmor);
+
+ l_base_addr = l_hrmor + l_base_addr;
+
+ HDAT_DBG("base address after adding HRMOR=0x%08x",l_base_addr);
+
+ uint64_t l_base_addr_down = ALIGN_PAGE_DOWN(l_base_addr);
+ HDAT_DBG("l_base_addr_down=0x%016llX",l_base_addr_down);
+
+ HDAT_DBG("reqd space=0x%x, will do a block map of size 0x%x",
+ iv_spirasSize, ALIGN_PAGE(iv_spirasSize));
+
+
+ void *l_virt_addr = mm_block_map( reinterpret_cast<void*>(l_base_addr_down),
+ ALIGN_PAGE(iv_spirasSize) + PAGESIZE);
+
+ HDAT_DBG("l_virt_addr=0x%016llX after block map",l_virt_addr);
+
+ uint64_t l_vaddr = reinterpret_cast<uint64_t>(l_virt_addr);
+
+ HDAT_DBG("will add offset %x to starting virtual address",
+ (l_base_addr-l_base_addr_down));
+
+ l_vaddr += l_base_addr-l_base_addr_down;
+
+ HDAT_DBG("l_vaddr after adding=0x%016llX",l_vaddr);
+
+ l_virt_addr = reinterpret_cast<void *>(l_vaddr);
+ HDAT_DBG("l_virt_addr=0x%016llX",l_virt_addr);
+
+
+
+ iv_spiras = reinterpret_cast<hdatSpiraS_t *>(l_virt_addr);
+
+ HDAT_DBG("constructor iv_spiras addr 0x%016llX virtual addr 0x%016llX,space"
+ " allocated=0x%x",(uint64_t) this->iv_spiras,
+ (uint64_t)l_virt_addr,iv_spirasSize);
+
+ HDAT_DBG("creating SPIRA-S header");
+ setSpiraSHdrs();
+
+ HDAT_DBG("done setting the SPIRA-S header");
+
+
+ iv_spiras->hdatHDIF.hdatSize = sizeof(hdatSpira_t);
+
+ HDAT_EXIT();
+
+ return;
+}
+
+/*****************************************************************************/
+// setSpiraSHdrs
+/*****************************************************************************/
+void HdatSpiraS::setSpiraSHdrs()
+{
+ HDAT_ENTER()
+
+
+ iv_spiras->hdatHDIF.hdatStructId = HDAT_HDIF_STRUCT_ID;
+ iv_spiras->hdatHDIF.hdatInstance = 0;
+ iv_spiras->hdatHDIF.hdatVersion = HDAT_SPIRAS_VERSION;
+ iv_spiras->hdatArrayInfo.hdatArrayCnt = HDAT_SPIRAS_DA_LAST;
+ iv_spiras->hdatHDIF.hdatSize = sizeof(hdatSpiraS_t);
+
+ iv_spiras->hdatHDIF.hdatHdrSize = sizeof(hdatHDIF_t);
+ iv_spiras->hdatHDIF.hdatDataPtrOffset = sizeof(hdatHDIF_t);
+ iv_spiras->hdatHDIF.hdatDataPtrCnt = 1;
+ iv_spiras->hdatHDIF.hdatChildStrCnt = 0;
+ iv_spiras->hdatHDIF.hdatChildStrOffset = 0;
+
+ memcpy(iv_spiras->hdatHDIF.hdatStructName, HDAT_SPIRAS_EYE_CATCHER,
+ sizeof(iv_spiras->hdatHDIF.hdatStructName));
+
+ iv_spiras->hdatDataHdr.hdatOffset =
+ offsetof(hdatSpiraS_t, hdatArrayInfo);
+
+ iv_spiras->hdatDataHdr.hdatSize =
+ (sizeof(hdatHDIFDataArray_t)
+ + sizeof(iv_spiras->hdatDataArea));
+
+ iv_spiras->hdatArrayInfo.hdatOffset =
+ sizeof(hdatHDIFDataArray_t);
+
+ iv_spiras->hdatArrayInfo.hdatAllocSize =
+ sizeof(hdat5Tuple_t);
+
+ iv_spiras->hdatArrayInfo.hdatActSize =
+ offsetof(hdat5Tuple_t, hdatReserved1);
+
+
+ HDAT_EXIT();
+ return;
+}
+
+
+/******************************************************************************/
+// ~HdatSpiraS
+/******************************************************************************/
+
+HdatSpiraS::~HdatSpiraS()
+{
+ HDAT_ENTER();
+
+ int rc = 0;
+ rc = mm_block_unmap(iv_spiras);
+
+ if ( rc != 0 )
+ {
+ HDAT_ERR("unmap of spiras failed");
+ errlHndl_t l_errl = NULL;
+ hdatMsAddr_t l_tmpaddr = {0};
+
+ if ( iv_spiras )
+ {
+ memcpy(&l_tmpaddr,(void*)iv_spiras,sizeof(hdatMsAddr_t));
+ }
+
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_SPIRAS_DESTRUCTOR
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_errl,
+ MOD_SPIRAS_DESTRUCTOR,
+ RC_DEV_MAP_FAIL,
+ l_tmpaddr.hi,l_tmpaddr.lo,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+
+ }
+
+ HDAT_EXIT();
+ return;
+}
+
+
+/***********************************************************************/
+// getStructAddr
+/***********************************************************************/
+
+const hdatSpiraS_t *HdatSpiraS::getStructAddr()
+{
+ return iv_spiras;
+}
+
+
+/***********************************************************************/
+// loadDataArea
+/***********************************************************************/
+
+errlHndl_t HdatSpiraS::loadDataArea( const hdat5Tuple_t& i_spirasHostEntry,
+ uint32_t& o_actCount, uint32_t& o_actSize)
+{
+ HDAT_ENTER();
+ errlHndl_t l_err = NULL;
+ hdatMsAddr_t l_msAddr,l_addrToPass,i_slcaMsAddr = SLCA_BUILD_ADDR;
+ hdat5Tuple_t l_spirasEntry;
+ uint32_t l_hostUsed = 0;
+ uint32_t l_size,l_count,l_hdatslcaSize,l_hdatSlcaCnt;
+ uint64_t l_binAddr;
+ o_actCount = 1;
+ o_actSize = 0;
+
+ do {
+
+ //calculate HRMOR
+ TARGETING::Target * sys = NULL;
+ TARGETING::targetService().getTopLevelTarget( sys );
+
+ assert(sys != NULL);
+
+ uint64_t l_hrmor =
+ sys->getAttr<TARGETING::ATTR_PAYLOAD_BASE>()*MEGABYTE;
+
+ HDAT_DBG("HRMOR=0x%08x",l_hrmor);
+
+
+ HDAT_DBG("building SLCA");
+ l_binAddr = ((uint64_t)i_slcaMsAddr.hi << 32)
+ |
+ i_slcaMsAddr.lo;
+
+ l_binAddr += l_hrmor;
+ memcpy(&i_slcaMsAddr, &l_binAddr, sizeof(l_binAddr));
+
+ HDAT_DBG("building SLCA at i_slcaMsAddr.hi=%x,i_slcaMsAddr.lo=%x",
+ i_slcaMsAddr.hi,i_slcaMsAddr.lo);
+
+ l_err = hdatBuildSLCA(i_slcaMsAddr,l_hdatSlcaCnt,l_hdatslcaSize);
+
+ if ( l_err )
+ {
+ HDAT_ERR("failed to build SLCA");
+ break;
+ }
+
+ HDAT_DBG("built SLCA, size=0x%x",l_hdatslcaSize);
+
+ l_hostUsed = i_spirasHostEntry.hdatActualSize + (sizeof(hdatSpiraS_t));
+
+ HDAT_DBG("size of hdatSpiraS_t: 0x%08X, hdatActualSize: 0x%08X",
+ (sizeof(hdatSpiraS_t)),i_spirasHostEntry.hdatActualSize);
+
+
+ for ( hdatSpiraSDataAreas l_entryToPrint=HDAT_SPIRAS_DA_FIRST;
+ (l_entryToPrint < HDAT_SPIRAS_DA_LAST);
+ l_entryToPrint=(hdatSpiraSDataAreas)((uint32_t)l_entryToPrint +1) )
+ {
+ HDAT_DBG("for loop index=%d",l_entryToPrint);
+ l_count = 0;
+ l_size = 0;
+
+ l_binAddr = 0x0;
+ l_binAddr = ((uint64_t)i_spirasHostEntry.hdatAbsAddr.hi << 32)
+ |
+ i_spirasHostEntry.hdatAbsAddr.lo;
+
+
+ l_binAddr += (uint64_t)l_hostUsed;
+
+ memcpy(&l_msAddr, &l_binAddr, sizeof(l_binAddr));
+
+ HDAT_DBG("next spiras tuple will be l_msAddr.hi=0x%8x,"
+ "l_msAddr.lo=0x%8x",l_msAddr.hi,l_msAddr.lo);
+
+
+ l_binAddr += l_hrmor;
+
+ memcpy(&l_addrToPass, &l_binAddr, sizeof(l_binAddr));
+
+ HDAT_DBG("address to pass to next data area after adding hrmor"
+ " l_addrToPass.hi"
+ "=0x%8x,l_addrToPass.lo=0x%8x",l_addrToPass.hi,l_addrToPass.lo);
+
+ switch ( l_entryToPrint )
+ {
+ case HDAT_SPIRAS_SP_SUBSYS:
+ {
+ HDAT_DBG("calling SP SUBSYS from spiras");
+ l_err = HdatLoadSpSubSys(l_addrToPass,
+ l_size,l_count);
+ HDAT_DBG("returned from SP SUBSYS, count=%d"
+ "size=0x%x",l_count,l_size);
+ }
+ break;
+ case HDAT_SPIRAS_IPL_PARMS:
+ {
+ HDAT_DBG("calling IPL PARMS from spiras");
+ HdatIplParms l_iplParms(l_err,l_addrToPass);
+
+ if ( NULL == l_err)
+ {
+ l_err = l_iplParms.hdatLoadIplParams(l_size,l_count);
+
+ if ( NULL == l_err )
+ {
+ HDAT_DBG("returned from IPL PARMS, size=0x%x,count=%d",
+ l_size,l_count);
+ }
+ else
+ {
+ HDAT_DBG("could not load IPL PARMS");
+ }
+ }
+ else
+ {
+ HDAT_DBG("could not create IPL PARMS object");
+ }
+ }
+ break;
+ case HDAT_SPIRAS_ENCLOSURE_VPD:
+ {
+ HDAT_DBG("calling ENCLOSURE VPD from spiras");
+ l_err = hdatBldSpecificVpd(HDAT_ENCLOSURE_VPD,l_addrToPass,
+ l_count,l_size);
+ if ( l_err )
+ {
+ HDAT_ERR("could not build ENCLOSURE VPD");
+ }
+ else
+ {
+ HDAT_DBG("returned from ENCLOSURE VPD count=%d, size=0x%x",
+ l_count,l_size);
+ }
+ }
+ break;
+ case HDAT_SPIRAS_SLCA:
+ {
+ HDAT_DBG("calling SLCA from spiras ");
+ l_count = l_hdatSlcaCnt;
+ l_size = l_hdatslcaSize;
+ hdatMoveSLCA(i_slcaMsAddr,
+ l_addrToPass,l_hdatslcaSize);
+ HDAT_DBG("moved SLCA count=%d, size=0x%x",l_count,l_size);
+ }
+ break;
+ case HDAT_SPIRAS_BACKPLANE_VPD:
+ {
+ HDAT_DBG("calling BACKPLANE VPD from spiras");
+ l_err = hdatBldSpecificVpd( HDAT_BACKPLANE_VPD, l_addrToPass,
+ l_count,l_size);
+ if ( l_err )
+ {
+ HDAT_ERR("could not build BACKPLANE VPD");
+ }
+ else
+ {
+ HDAT_DBG("returned from BACKPLANE VPD count=%d, size=0x%x",
+ l_count,l_size);
+ }
+ }
+ break;
+ case HDAT_SPIRAS_SYS_VPD:
+ {
+ HDAT_DBG("calling SYS VPD from spiras");
+ l_err = hdatBldSpecificVpd( HDAT_SYS_VPD,l_addrToPass,l_count,
+ l_size);
+ if ( l_err )
+ {
+ HDAT_ERR("could not build SYS VPD");
+ }
+ else
+ {
+ HDAT_DBG("returned from SYS VPD count=%d, size=0x%x",
+ l_count,l_size);
+ }
+ }
+ break;
+ case HDAT_SPIRAS_CLOCK_VPD:
+ {
+ HDAT_DBG("calling CLOCK VPD from spiras");
+ l_err = hdatBldSpecificVpd( HDAT_CLOCK_VPD,l_addrToPass,l_count,
+ l_size);
+ if ( l_err )
+ {
+ HDAT_ERR("could not build CLOCK VPD");
+ }
+ else
+ {
+ HDAT_DBG("returned from CLOCK VPD count=%d, size=0x%x",
+ l_count,l_size);
+ }
+ }
+ break;
+ case HDAT_SPIRAS_ANCHOR_VPD:
+ {
+ HDAT_DBG("calling ANCHOR VPD from spiras");
+ l_err = hdatBldSpecificVpd(HDAT_ANCHOR_VPD,l_addrToPass,l_count,
+ l_size);
+ if ( l_err )
+ {
+ HDAT_ERR("could not build ANCHOR VPD");
+ }
+ else
+ {
+ HDAT_DBG("returned from ANCHOR VPD count=%d, size=0x%x",
+ l_count,l_size);
+ }
+ }
+ break;
+ case HDAT_SPIRAS_OP_PNL_VPD:
+ {
+ HDAT_DBG("calling OP PANL VPD from spiras");
+ l_err = hdatBldSpecificVpd(HDAT_OP_PNL_VPD,l_addrToPass,l_count,
+ l_size);
+ if( l_err )
+ {
+ HDAT_ERR("could not build OP PANL VPD");
+ }
+ else
+ {
+ HDAT_DBG("returned from OP PANL VPD count=%d, size=0x%x",
+ l_count,l_size);
+ }
+ }
+ break;
+ case HDAT_SPIRAS_MISC_CEC_VPD:
+ {
+ HDAT_DBG("calling MISC CEC VPD from spiras");
+ l_err = hdatBldSpecificVpd( HDAT_MISC_CEC_VPD,l_addrToPass,
+ l_count,l_size);
+ if ( l_err )
+ {
+ HDAT_ERR("could not build MISC CEC VPD");
+ }
+ else
+ {
+ HDAT_DBG("returned from MISC CEC VPD count=%d, size=0x%x",
+ l_count,l_size);
+ }
+ }
+ break;
+ case HDAT_SPIRAS_MSVPD:
+ {
+ HDAT_DBG("calling MS VPD from spiras");
+ HdatMsVpd l_msvpd(l_err,l_addrToPass);
+ if ( l_err == NULL )
+ {
+ l_err = l_msvpd.hdatLoadMsData(l_size,l_count);
+ HDAT_DBG("MS VPD count=%d, size=0x%x",l_count,l_size);
+ }
+ else
+ {
+ HDAT_DBG("could not create MS VPD object");
+ }
+ }
+ break;
+ case HDAT_SPIRAS_IO_HUB:
+ {
+ HDAT_DBG("calling IO HUB from spiras");
+ l_err = hdatLoadIoData(l_addrToPass,l_size,l_count);
+ HDAT_DBG("returned size=0x%x,count=%d from iohub",
+ l_size,l_count);
+ }
+ break;
+ case HDAT_SPIRAS_PCIA:
+ {
+ HDAT_DBG("calling PCIA from spiras");
+ HdatPcia pcia(l_err,l_addrToPass);
+ if ( NULL == l_err )
+ {
+ l_err = pcia.hdatLoadPcia(l_size,l_count);
+ HDAT_DBG("returned from PCIA count=%d,size=0x%x",
+ l_count,l_size);
+ }
+ else
+ {
+ HDAT_DBG("could not create PCIA object");
+ }
+ }
+ break;
+ case HDAT_SPIRAS_PCRD:
+ {
+ HDAT_DBG("calling PCRD from spiras");
+ HdatPcrd l_pcrd(l_err,l_addrToPass);
+
+ if ( NULL == l_err )
+ {
+ l_pcrd.hdatLoadPcrd(l_size,l_count);
+ HDAT_DBG("PCRD count=%d,size=%x",l_count,l_size);
+ }
+ else
+ {
+ HDAT_ERR("could not create PCRD object");
+ }
+ }
+ break;
+ case HDAT_SPIRAS_HOSTSR:
+ {
+ HDAT_DBG("HOSTSR from spiras");
+ HdatHostsr l_hdatHostSr(l_err,l_addrToPass,l_size,l_count);
+ HDAT_DBG("HOSTSR count=%d,size=%x",l_count,l_size);
+ }
+ break;
+
+ case HDAT_SPIRAS_HBRT:
+ {
+ HDAT_DBG("HBRT from spiras");
+ l_err = loadHbrt(l_addrToPass,l_size,l_count);
+
+ if ( l_err )
+ {
+ HDAT_ERR("loading HBRT failed");
+ }
+ else
+ {
+ HDAT_DBG("HBRT count=%d,size=0x%x",l_count,l_size);
+ }
+ }
+ break;
+ default:
+ {
+ HDAT_ERR("not a valid data area");
+ }
+ break;
+
+ }
+ if (l_err)
+ {
+ HDAT_ERR("error in creating data area %d",l_entryToPrint);
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_SPIRAS_CREATE_DATA_AREA
+ * @reasoncode HDAT::RC_DATA_AREA_FAIL
+ * @devdesc could not create the data area from spiras
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog (l_err,
+ MOD_SPIRAS_CREATE_DATA_AREA,
+ RC_DATA_AREA_FAIL,
+ l_entryToPrint,0,0,0);
+
+ break;
+ }
+ if ( l_count && l_size )
+ {
+ memset(&l_spirasEntry, 0, sizeof(hdat5Tuple_t));
+ l_spirasEntry.hdatAbsAddr.hi = l_msAddr.hi;
+ l_spirasEntry.hdatAbsAddr.lo = l_msAddr.lo;
+
+ l_spirasEntry.hdatAllocCnt = l_count;
+ l_spirasEntry.hdatActualCnt = l_count;
+
+ uint32_t l_rem = l_size % 128;
+ uint32_t l_pad = l_rem ? (128 - l_rem) : 0;
+
+ l_spirasEntry.hdatAllocSize = l_size + l_pad;
+ l_spirasEntry.hdatActualSize = l_size;
+
+ l_hostUsed += l_count * l_spirasEntry.hdatAllocSize;
+
+ //copy the tuple to spira-s memory
+
+ memcpy(&iv_spiras->hdatDataArea[l_entryToPrint],&l_spirasEntry,
+ sizeof(hdat5Tuple_t));
+
+ HDAT_DBG("iv_spiras->hdatDataArea[%d].hdatActualCnt=%d,"
+ "hdatActualSize=%x",l_entryToPrint,
+ iv_spiras->hdatDataArea[l_entryToPrint].hdatActualCnt,
+ iv_spiras->hdatDataArea[l_entryToPrint].hdatActualSize);
+
+ }
+ }//end for
+
+ }while(0);
+
+ o_actSize = l_hostUsed;
+
+ HDAT_EXIT();
+ return l_err;
+
+}//end loadDataArea
+
+
+/****************************************************************/
+//getSpirasObject
+/****************************************************************/
+
+void HdatSpiraS::getSpirasObject(uint8_t* &io_spiras,uint32_t& o_size,
+ const hdatMsAddr_t& i_msAddr)
+{
+ HDAT_ENTER();
+
+ io_spiras = NULL;
+
+ //user is responsible to free up the memory
+ io_spiras = new uint8_t[iv_spirasSize];
+
+ o_size = iv_spirasSize;
+
+ memcpy(io_spiras, iv_spiras, iv_spirasSize);
+
+ HDAT_EXIT();
+}
+
+
+
+/****************************************************************/
+// getSpiraSEntry
+/****************************************************************/
+
+void HdatSpiraS::getSpiraSEntry(hdatSpiraSDataAreas i_dataArea,
+ hdat5Tuple_t &o_entry)
+{
+ HDAT_ENTER();
+
+ o_entry.hdatAbsAddr.hi = iv_spiras->hdatDataArea[i_dataArea].hdatAbsAddr.hi;
+ o_entry.hdatAbsAddr.lo = iv_spiras->hdatDataArea[i_dataArea].hdatAbsAddr.lo;
+ o_entry.hdatAllocCnt = iv_spiras->hdatDataArea[i_dataArea].hdatAllocCnt;
+ o_entry.hdatActualCnt = iv_spiras->hdatDataArea[i_dataArea].hdatActualCnt;
+ o_entry.hdatAllocSize = iv_spiras->hdatDataArea[i_dataArea].hdatAllocSize;
+ o_entry.hdatActualSize = iv_spiras->hdatDataArea[i_dataArea].hdatActualSize;
+ o_entry.hdatTceOffset = iv_spiras->hdatDataArea[i_dataArea].hdatTceOffset;
+
+ HDAT_DBG("returning tuple o_entry.hdatAbsAddr.hi : 0x%08X,"
+ " o_entry.hdatAbsAddr.lo : 0x%08X",
+ o_entry.hdatAbsAddr.hi,o_entry.hdatAbsAddr.lo);
+
+ HDAT_DBG("o_entry.hdatAllocCnt : 0x%08X, o_entry.hdatActualCnt: 0x%08X ",
+ o_entry.hdatAllocCnt,o_entry.hdatActualCnt);
+
+ HDAT_DBG("o_entry.hdatAllocSize : 0x%08X, o_entry.hdatActualSize: 0x%08X",
+ o_entry.hdatAllocSize,o_entry.hdatActualSize);
+
+ HDAT_EXIT();
+}
+
+
+
+}//end namespace
diff --git a/src/usr/hdat/hdatspiraS.H b/src/usr/hdat/hdatspiraS.H
new file mode 100755
index 000000000..97d6a5972
--- /dev/null
+++ b/src/usr/hdat/hdatspiraS.H
@@ -0,0 +1,293 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatspiraS.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATSPIRAS_H
+#define HDATSPIRAS_H
+
+/**
+ * @file hdatspiraS.H
+ *
+ * @brief This file contains the definition of the Service Processor Interface
+ * Root Array Secure boot (SPIRA-S) data structure. This data structure
+ * is built by FSP and placed at the beginning of the host data areas
+ * space located using the SPIRA-H. Data areas pointed to by this portion
+ * of the SPIRA will be located after it in the host data areas space.
+ *
+ */
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Includes */
+/*---------------------------------------------------------------------------*/
+#include <stdint.h>
+#include <errl/errlentry.H>
+#include <hdat/hdat.H>
+
+
+namespace HDAT
+{
+
+/*---------------------------------------------------------------------------*/
+/* Constants */
+/*---------------------------------------------------------------------------*/
+const char HDAT_SPIRAS_EYE_CATCHER[] = "SPIRAS";
+
+const uint16_t HDAT_SPIRAS_VERSION = 0x40;
+
+const hdatMsAddr_t SLCA_BUILD_ADDR = {0x00000000, 0x80000000};
+
+/*---------------------------------------------------------------------------*/
+/* Type definitions */
+/*---------------------------------------------------------------------------*/
+enum hdatSpiraSDataAreas
+{
+ HDAT_SPIRAS_DA_FIRST = 0,
+ HDAT_SPIRAS_SP_SUBSYS = 0, // service processor subsystem
+ HDAT_SPIRAS_IPL_PARMS = 1, // IPL parameters
+ HDAT_SPIRAS_ENCLOSURE_VPD = 2, // enclosure vital product data
+ HDAT_SPIRAS_SLCA = 3, // slot location code array
+ HDAT_SPIRAS_BACKPLANE_VPD = 4, // backplane vital product data
+ HDAT_SPIRAS_SYS_VPD = 5, // system vital product data
+ HDAT_SPIRAS_CLOCK_VPD = 6, // clock vital product data
+ HDAT_SPIRAS_ANCHOR_VPD = 7, // anchor card vital product data
+ HDAT_SPIRAS_OP_PNL_VPD = 8, // operator panel vital product data
+ HDAT_SPIRAS_MISC_CEC_VPD = 9, // miscellaneous FRU vital product data
+ HDAT_SPIRAS_MSVPD = 10, // memory description tree
+ HDAT_SPIRAS_IO_HUB = 11, // I/O hub FRU array
+ HDAT_SPIRAS_PCIA = 12, // PCIA (Core information area)
+ HDAT_SPIRAS_PCRD = 13, // PCRD (Chip related data area)
+ HDAT_SPIRAS_HOSTSR = 14, // HOSTSR (Host service data)
+ HDAT_SPIRAS_HBRT = 15, //HBRT (runtime data)
+
+ HDAT_SPIRAS_DA_LAST = 16
+};
+
+
+/** @brief The SPIRA-S is composed of an HDIF header and an array. Each array
+ * entry is an n-tuple. That is, it is a structure with a particular
+ * number of fields
+ */
+struct hdatSpiraS_t
+{
+ hdatHDIF_t hdatHDIF; // 0x0000 Common HDIF header
+ hdatHDIFDataHdr_t hdatDataHdr; // 0x0020 Data "pointers"
+ uint8_t hdatReserved1[8]; // 0x0028 Padding/future growth
+ hdatHDIFDataArray_t hdatArrayInfo; // 0x0030 Info on 5-tuple array
+ hdat5Tuple_t hdatDataArea[HDAT_SPIRAS_DA_LAST]; //0x0040 5-tuple array
+ // At this point, the host OS may have reserved extra space for future growth
+ // but FipS does not need to be concerned with the reserved space nor DMA it
+ // back from main memory.
+} __attribute__ ((packed));
+
+
+/*---------------------------------------------------------------------------*/
+/* C++ class definition */
+/*---------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatSpiraS class is used to construct the SPIRA-S object
+ *
+ * Description:
+ * The SPIRA-S object contains mainstore addresses and other information
+ * about various hypervisor data structures. The SPIRA-S is initially
+ * DMA'd from mainstore to FipS control store and written to a
+ * file. Constructing thr SPIRA-S objects maps the file into a
+ * process' address space.
+ *
+ * Thread safety:
+ * An HdatSpiraS object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by multiple
+ * threads at the same time.
+ *
+ * Signal handler usage:
+ * This class is not intended to be used in a signal handler
+ * and nothing has been done to try and make it safe to use
+ * in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatSpiraS
+{
+public:
+
+
+ /**
+ * @brief Construct an HdatSpiraS object.
+ *
+ * This function reads in the Service Processor Interface Root Array
+ * (SPIRA-S) structure from main memory,
+ *
+ * THIS CONSTRUCTOR CAN BE USED ONLY BY THE HDAT COMPONENT.
+ *
+ * @pre The primary LID which contains the NACA and the primary/secondary LID
+ * which contains the SPIRA-S must have been read to main memory.
+ *
+ * @post The SPIRA-S is read from main memory and is initiailized to default
+ * values
+ *
+ *
+ * @param i_msAddr - input parameter - The main memory address where the
+ * SPIRA-S is located
+ *
+ * @return A null error log handle if successful, else the return code
+ * pointed to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ * @retval HDAT_FILE_ERROR
+ */
+ HdatSpiraS(const hdatMsAddr_t& i_msAddr);
+
+
+ /**
+ * @brief HdatSpiraS object destructor
+ *
+ * This is the destructor for an HdatSpiraS object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatSpiraS object has been destroyed and can no longer be used.
+ *
+ */
+ ~HdatSpiraS();
+
+
+
+
+ /**
+ * @brief This function returns the address to the raw SPIRA-S structure. It
+ * is intended to be used only to put the structure into an error log.
+ *
+ * THIS FUNCTION SHOULD BE USED ONLY BY THE HDAT COMPONENT.
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @return An address to the spiraH
+ */
+ const hdatSpiraS_t *getStructAddr();
+
+
+ /**
+ * @brief This routine initializes the SPIRA-S HDIF header and
+ * clears the N-Tuple array
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @retval no errors currently defined
+ */
+ void setSpiraSHdrs();
+
+
+ /**
+ * @brief This function constructs the (SPIRA-S)
+ * structure in main memory
+ *
+ * @pre The primary LID which contains the NACA and the primary/secondary LID
+ * which contains the SPIRA-S must have been read to main memory.
+ *
+ * THIS FUNCTION CAN BE USED ONLY BY THE HDAT COMPONENT.
+ *
+ * @post The SPIRA-S is written to main memory, and initialized to default
+ * values if required
+ *
+ * @param i_spirasHostEntry the spiras starting address entry fetched
+ * from spira-h
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval HDAT_ALLOC_ERROR
+ * @retval HDAT_FILE_ERROR
+ */
+ errlHndl_t loadDataArea( const hdat5Tuple_t& i_spirasHostEntry,
+ uint32_t& o_actCount, uint32_t& o_actSize);
+
+
+ /**
+ * @brief this function returns a copy of the spiras object into
+ * a buffer provided by the user
+ *
+ * @pre None
+ *
+ * @post the buffer area is allocated and spiras is copied to that area.
+ * the user is responsible to free up the memory area used
+ *
+ * @param io_spiras - input-output parameter- area where spiras is copied
+ *
+ * @param i_msAddr - starting address of spiras retrieved from spirah
+ *
+ * @return None
+ */
+
+ void getSpirasObject(uint8_t * &io_spiras,uint32_t& o_size,
+ const hdatMsAddr_t& i_msAddr);
+
+
+
+ /**
+ * @brief This function computes the address of a 5-tuple entry within the
+ * SPIRA-S structure and returns it
+ *
+ * Usage note: The SPIRA-S structure is already built as part of the Host
+ * LIDS
+ * @pre None
+ * @post A copy of the desired 5-tuple returned
+ *
+ * @param i_dataArea - input parameter - an enumeration for the 5-tuple entry
+ * being requested
+ * @param o_entry - output parameter - a copy of the 5-tuple entry being
+ * requested
+ *
+ * @return NONE
+ */
+
+ void getSpiraSEntry(hdatSpiraSDataAreas i_dataArea,
+ hdat5Tuple_t &o_entry);
+
+
+private:
+
+
+ /** Object Instance Data
+ *
+ * @li iv_spirasSize - size if the SPIRA-S structure
+ * @li iv_spiras - pointer to the SPIRA-S structure
+ */
+ uint32_t iv_spirasSize;
+ hdatSpiraS_t *iv_spiras;
+
+}; // end of HdatSpiraS class
+
+} //end namespace
+#endif // HDATSPIRAS_H
diff --git a/src/usr/hdat/hdatspsubsys.C b/src/usr/hdat/hdatspsubsys.C
new file mode 100755
index 000000000..540d43e25
--- /dev/null
+++ b/src/usr/hdat/hdatspsubsys.C
@@ -0,0 +1,521 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatspsubsys.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+
+/**
+ * @file hdatspsubsys.C
+ *
+ * @brief This file contains the implementation of the HdatSpSubsys class.
+ *
+ */
+
+
+/*---------------------------------------------------------------------------*/
+/* Includes */
+/*---------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <sys/mm.h>
+#include <sys/mmio.h>
+#include <pnor/pnorif.H>
+#include <util/align.H>
+#include "hdatspsubsys.H"
+#include "hdathdif.H"
+#include "hdatutil.H"
+#include "hdatvpd.H"
+#include <targeting/common/util.H>
+
+using namespace TARGETING;
+
+namespace HDAT
+{
+
+/*----------------------------------------------------------------------------*/
+/* Global variables */
+/*----------------------------------------------------------------------------*/
+uint32_t HdatSpSubsys::cv_actualCnt;
+
+
+vpdData mvpdDataTable[] =
+{
+ { MVPD::VINI, MVPD::DR },
+ { MVPD::VINI, MVPD::VZ },
+ { MVPD::VINI, MVPD::CC },
+ { MVPD::VINI, MVPD::CE },
+ { MVPD::VINI, MVPD::FN },
+ { MVPD::VINI, MVPD::PN },
+ { MVPD::VINI, MVPD::SN },
+ { MVPD::VINI, MVPD::PR },
+ { MVPD::VINI, MVPD::HE },
+ { MVPD::VINI, MVPD::CT },
+ { MVPD::VINI, MVPD::HW },
+};
+
+const HdatKeywordInfo l_mvpdKeywords[] =
+{
+ { MVPD::DR, "DR" },
+ { MVPD::VZ, "VZ" },
+ { MVPD::CC, "CC" },
+ { MVPD::CE, "CE" },
+ { MVPD::FN, "FN" },
+ { MVPD::PN, "PN" },
+ { MVPD::SN, "SN" },
+ { MVPD::PR, "PR" },
+ { MVPD::HE, "HE" },
+ { MVPD::CT, "CT" },
+ { MVPD::HW, "HW" },
+
+};
+
+extern trace_desc_t *g_trac_hdat;
+
+/**
+ * @brief This routine fill up the SP I/O path information.
+ *
+ * @pre The o_pathArray must be set to zero.
+ *
+ * @post None
+ *
+ * @param l_pSpTarget - input parameter - Target handle of the SP
+ * @param o_arrayHdr - output parameter - The I/O path array header structure
+ * @param o_pathArray - output parameter - The structure to update with the SP
+ * I/O path information
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval
+ */
+static errlHndl_t hdatGetPathInfo(
+ uint32_t &io_numOfIoPaths,
+ hdatHDIFDataArray_t &o_arrayHdr,
+ hdatSpIoPath_t o_pathArray[])
+{
+
+ HDAT_ENTER();
+
+ errlHndl_t l_errlHndl = NULL;
+
+ // Set the number of Io Paths.
+ // For now, we have only 1, may change in future
+ io_numOfIoPaths = HDAT_NUM_IO_PATHS_FOR_BMC;
+
+ // Set fields in the array header
+ o_arrayHdr.hdatOffset = sizeof(hdatHDIFDataArray_t);
+ o_arrayHdr.hdatAllocSize = sizeof(hdatSpIoPath_t);
+ o_arrayHdr.hdatActSize = sizeof(hdatSpIoPath_t);
+ o_arrayHdr.hdatArrayCnt = 0;
+
+ for( ; o_arrayHdr.hdatArrayCnt < io_numOfIoPaths ; )
+ {
+ o_pathArray[o_arrayHdr.hdatArrayCnt].
+ hdatPathType = HDAT_LPC_PATH_TYPE;
+ o_pathArray[o_arrayHdr.hdatArrayCnt].
+ hdatLinkStatus = HDAT_CURRENT_LINK;
+ o_pathArray[o_arrayHdr.hdatArrayCnt].hdatML2ChipVer = 0x10;
+ o_pathArray[o_arrayHdr.hdatArrayCnt].
+ hdatSlcaCnt = LPC_PATH_FRU_CNT_FOR_BMC;
+
+ // Get the master proc handle.
+
+ TARGETING::Target* l_pMasterProcChipTargetHandle = NULL;
+ (void)TARGETING::targetService().masterProcChipTargetHandle(
+ l_pMasterProcChipTargetHandle);
+
+ if (l_pMasterProcChipTargetHandle == NULL)
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_GET_PATH_INFO
+ * @reasoncode HDAT::RC_MASTER_PROC_TARGET_NULL
+ * @devdesc Master proc target returned is Null
+ * @custdesc Firmware encountered an internal
+ * error while retrieving target handle
+ */
+ hdatBldErrLog(l_errlHndl,
+ MOD_GET_PATH_INFO,
+ RC_MASTER_PROC_TARGET_NULL,
+ 0,0,0,0);
+
+ HDAT_ERR("Master proc target handle is Null");
+ }
+ else
+ {
+
+ o_pathArray[o_arrayHdr.hdatArrayCnt].hdatProcChipId =
+ l_pMasterProcChipTargetHandle->getAttr<ATTR_ORDINAL_ID>();
+
+ uint64_t l_gxcBaseAddr = 0;
+ memcpy(&o_pathArray[o_arrayHdr.hdatArrayCnt].hdatGxcBaseAddr,
+ &l_gxcBaseAddr,
+ sizeof(o_pathArray[o_arrayHdr.hdatArrayCnt].hdatGxcBaseAddr));
+ }
+
+ // LPC link doesn't have any FRU's in the path
+ // except the end points Service Processor and master proc
+ // The Fru's slca index should be populated for this entry by
+ // starting from SP
+
+ /* TARGETING::Target* l_lpcPathTargetsArray[] =
+ { i_pSpTarget , l_pMasterProcChipTargetHandle };
+ uint32_t l_fruIdx = 0;
+ for ( ; l_fruIdx < LPC_PATH_FRU_CNT_FOR_BMC ; l_fruIdx++)
+ {
+ o_pathArray[o_arrayHdr.hdatArrayCnt].hdatSlcaIdx[l_fruIdx] =
+ l_lpcPathTargetsArray[l_fruIdx]->getAttr<ATTR_SLCA_INDEX>();
+ }*/
+ o_arrayHdr.hdatArrayCnt++;
+ }
+
+ HDAT_EXIT();
+ return l_errlHndl;
+}
+
+/**
+ * @brief This routine Loads SP Sub sys information.
+ *
+ * @param io_msAddr- input parameter - Mainstore address for SP subsys to write
+ * @param o_spSubSysTotalSize - output parameter Total size of sp sub sys
+ * @param o_spSubsysCnt - output parameter - Count of SP Sub sys structures
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval
+ */
+
+errlHndl_t HdatLoadSpSubSys(hdatMsAddr_t &io_msAddr,
+ uint32_t &o_spSubSysTotalSize,
+ uint32_t &o_spSubsysCnt)
+{
+ errlHndl_t l_errlHndl = NULL;
+ hdatMsAddr_t l_msAddr = io_msAddr;
+
+ HDAT_ENTER();
+
+
+ HdatSpSubsys l_hdatSpSubsys(l_errlHndl, l_msAddr);
+
+ // Iterate through the SP targets and fill the SP sub sys
+ // structure for each SP
+ /* do{
+ TARGETING::PredicateCTM l_spFilter(CLASS_CHIP, TYPE_SP, MODEL_BMC);
+ TARGETING::PredicateHwas l_pred;
+ l_pred.present(true);
+ TARGETING::PredicatePostfixExpr l_presentSp;
+ l_presentSp.push(&l_spFilter).push(&l_pred).And();
+
+ TARGETING::TargetRangeFilter l_filter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentSp);
+ for( ; l_filter ; ++l_filter )
+ {
+ TARGETING::Target* l_pSpTarget = *l_filter;
+
+ HdatSpSubsys l_hdatSpSubsys(l_errlHndl, l_msAddr); */
+
+ if( l_errlHndl )
+ {
+ // Break the loop and return the error
+ HDAT_ERR("Got an error while filling sp sub sys"
+ " for sp: 0x%x", o_spSubsysCnt);
+ // break;
+ }
+ else
+ {
+ // Update the count and msaddr before continuing
+ // the loop for next SP.
+ memcpy(&io_msAddr , &l_msAddr , sizeof(hdatMsAddr_t));
+ o_spSubsysCnt++;
+ o_spSubSysTotalSize += l_hdatSpSubsys.getSpSubSysStructSize();;
+ }
+
+ //}
+ //}while(0);
+
+ HDAT_EXIT();
+ return l_errlHndl;
+}
+
+
+/** @brief See the prologue in hdatspsubsys.H
+ */
+HdatSpSubsys::HdatSpSubsys(errlHndl_t &o_errlHndl,
+ hdatMsAddr_t &io_msAddr
+ ):
+ HdatHdif(o_errlHndl, HDAT_STRUCT_NAME,
+ HDAT_SPSUBSYS_LAST, cv_actualCnt++, HDAT_NO_CHILD,
+ HDAT_SP_SUBSYS_VERSION), iv_kwdSize(0),
+ iv_kwd(NULL),iv_ioPathArray(NULL),
+ iv_spSubsys(NULL),iv_size(0),
+ iv_numOfIoPaths(0)
+{
+
+ HDAT_ENTER();
+
+ // Copy the input phy address to this object member variable
+ iv_msAddr = ((uint64_t) io_msAddr.hi << 32) | io_msAddr.lo;
+
+ do{
+ // Fill the internal data pointers
+ o_errlHndl = this->hdatFillDataPtrs();
+ if(o_errlHndl)
+ {
+ HDAT_ERR("Error while filling internal data ptrs for SP subsys");
+ break;
+ }
+
+ // Size of the SP sub sys structure
+ iv_size = sizeof(hdatHDIF_t) +
+ ( sizeof(hdatHDIFDataHdr_t) *
+ HDAT_SPSUBSYS_NUM_DATA_PTRS)+
+ sizeof(hdatFruId_t) +
+ iv_kwdSize +
+ sizeof(hdatSpImpl_t) +
+ sizeof(hdatSpMem_t) +
+ sizeof(hdatHDIFDataArray_t) +
+ (sizeof(hdatSpIoPath_t) * iv_numOfIoPaths);
+
+ uint64_t l_base_addr_down = ALIGN_PAGE_DOWN(iv_msAddr);
+ uint8_t *l_virt_addr =
+ (uint8_t *) mm_block_map (
+ reinterpret_cast<void*>(l_base_addr_down),
+ (ALIGN_PAGE(iv_size) + PAGESIZE));
+ iv_spSubsys = l_virt_addr + (iv_msAddr - ALIGN_PAGE_DOWN(iv_msAddr));
+
+ // initializing the space to zero
+ memset(iv_spSubsys ,0x0, iv_size );
+
+ iv_spSubsys = this->setHdif(iv_spSubsys);
+
+ memcpy(iv_spSubsys, &iv_fru, sizeof(hdatFruId_t));
+ iv_spSubsys += sizeof(hdatFruId_t);
+
+ memcpy(iv_spSubsys, iv_kwd, iv_kwdSize);
+ iv_spSubsys += iv_kwdSize;
+
+ memcpy(iv_spSubsys, &iv_impl, sizeof(hdatSpImpl_t));
+ iv_spSubsys += sizeof(hdatSpImpl_t);
+
+ memcpy(iv_spSubsys, &iv_mem, sizeof(hdatSpMem_t));
+ iv_spSubsys += sizeof(hdatSpMem_t);
+
+ memcpy(iv_spSubsys , &iv_ioPathArrayHdr, sizeof(hdatHDIFDataArray_t));
+ iv_spSubsys += sizeof(hdatHDIFDataArray_t);
+
+ memcpy(iv_spSubsys, iv_ioPathArray,
+ sizeof(hdatSpIoPath_t) * iv_numOfIoPaths);
+ iv_spSubsys += sizeof(hdatSpIoPath_t) * iv_numOfIoPaths;
+
+ // update the base address for next SP sub sys
+ uint64_t l_msAddrEnd = iv_msAddr + iv_size;
+
+ memcpy(&io_msAddr, &l_msAddrEnd, sizeof(hdatMsAddr_t));
+
+ } while(0);
+
+ HDAT_EXIT();
+ return;
+}
+
+errlHndl_t HdatSpSubsys::hdatFillDataPtrs()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ HDAT_ENTER();
+
+ do{
+ // Initialize all the values to zero
+ memset(&iv_impl , 0x0 , sizeof(hdatSpImpl_t));
+ memset(&iv_fru, 0x0 , sizeof(hdatFruId_t));
+ memset(&iv_mem, 0x0 , sizeof(hdatSpMem_t));
+
+ // Fill the SP impl data
+ iv_impl.hdatHdwVer = 0x0003;
+ iv_impl.hdatSftVer = 0x0002;
+ iv_impl.hdatChipVer = 0x10;
+ iv_impl.hdatStatus = HDAT_SP_INSTALLED;
+ iv_impl.hdatStatus |= HDAT_SP_PRIMARY;
+ iv_impl.hdatStatus |= HDAT_SP_FUNCTIONAL;
+
+ // Fill the FRU data
+ iv_fru.hdatSlcaIdx = 0;
+ iv_fru.hdatResourceId = 0;
+
+ // Fill the SP memory info
+ PNOR::SectionInfo_t l_info;
+ l_errlHndl = PNOR::getSectionInfo(PNOR::NVRAM, l_info);
+ if(l_errlHndl)
+ {
+ HDAT_ERR("PNOR::getSectionInfo returns error. Fill the size as 0");
+ iv_mem.hdatHostRamSize = 0;
+ }
+ else
+ {
+ iv_mem.hdatHostRamSize = l_info.size;
+ }
+
+ // Fill the SP I/O path information
+
+ iv_ioPathArray = reinterpret_cast<hdatSpIoPath_t *>(calloc(
+ HDAT_MAX_NUM_IO_PATHS,sizeof(hdatSpIoPath_t)));
+ // No need to check iv_ioPathArray because calloc won't return if out of memory.
+
+ l_errlHndl = hdatGetPathInfo(
+ iv_numOfIoPaths,
+ iv_ioPathArrayHdr,
+ iv_ioPathArray);
+ HDAT_DBG(" Num of Io Paths returned : %d", iv_numOfIoPaths);
+ if(l_errlHndl)
+ {
+ HDAT_ERR("hdatGetPathInfo returns Error");
+ break;
+ }
+
+ // Fill the kwd
+
+ // As of now there is no VPD present on BMC.
+ // Hence we are filling PROC data to get things moving.
+ // TODO : RTC : 151618 Will relook at this once we get mail from Tom.
+
+
+ TARGETING::Target* l_pMasterProcChipTargetHandle = NULL;
+ (void)TARGETING::targetService().masterProcChipTargetHandle(
+ l_pMasterProcChipTargetHandle);
+
+ if (l_pMasterProcChipTargetHandle == NULL)
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_HDAT_SP_SUBSYS_CTOR
+ * @reasoncode HDAT::RC_MASTER_PROC_TARGET_NULL
+ * @devdesc Master proc target returned is Null
+ * @custdesc Firmware encountered an internal
+ * error while retrieving target data
+ */
+ hdatBldErrLog(l_errlHndl,
+ MOD_GET_PATH_INFO,
+ RC_MASTER_PROC_TARGET_NULL,
+ 0,0,0,0);
+
+ HDAT_ERR("Master proc target handle is Null");
+ break;
+ }
+ else
+ {
+ uint32_t l_num = sizeof(mvpdDataTable) / sizeof(vpdData);
+ size_t theSize[l_num];
+ HDAT_DBG(" spsubsys number of vpd : %X", l_num);
+ l_errlHndl = hdatGetAsciiKwd(l_pMasterProcChipTargetHandle,
+ iv_kwdSize,
+ iv_kwd,
+ HDAT::PROC,
+ mvpdDataTable,
+ l_num,theSize);
+ HDAT_DBG(" initial size vpd : %X", iv_kwdSize);
+ if(l_errlHndl)
+ {
+ HDAT_ERR("hdatGetAsciiKwd returns Error");
+ break;
+ }
+ char *o_fmtKwd;
+ uint32_t o_fmtkwdSize;
+ l_errlHndl = hdatformatAsciiKwd(mvpdDataTable, l_num, theSize,
+ iv_kwd, iv_kwdSize, o_fmtKwd,
+ o_fmtkwdSize, l_mvpdKeywords);
+ if( o_fmtKwd != NULL )
+ {
+ delete[] iv_kwd;
+ iv_kwd = new char [o_fmtkwdSize + 8];
+ memcpy(iv_kwd,o_fmtKwd,o_fmtkwdSize);
+ iv_kwdSize = o_fmtkwdSize + 8;
+ delete[] o_fmtKwd;
+ }
+ }
+
+ // Done with getting all the data. Now its time to Add.
+ if( l_errlHndl == NULL )
+ {
+ this->addData(HDAT_SPSUBSYS_FRU_ID, sizeof(hdatFruId_t));
+ this->addData(HDAT_SPSUBSYS_KWD, iv_kwdSize);
+ this->addData(HDAT_SPSUBSYS_IMPL, sizeof(hdatSpImpl_t));
+ this->addData(HDAT_SPSUBSYS_DEPRECATED, 0); // Still need to account for the deprecated pointer pair
+
+ this->addData(HDAT_SPSUBSYS_MEMORY, sizeof(hdatSpMem_t));
+ this->addData(HDAT_SPSUBSYS_IO_PATH, sizeof(hdatHDIFDataArray_t) +
+ sizeof(hdatSpIoPath_t) * iv_ioPathArrayHdr.hdatArrayCnt);
+
+ this->align();
+ }
+
+ }while(0);
+ HDAT_EXIT();
+ return l_errlHndl;
+}
+
+/** @brief get the sp sub sys structure total size
+*/
+uint32_t HdatSpSubsys::getSpSubSysStructSize()
+{
+ return iv_size;
+}
+
+
+/** @brief See the prologue in hdathdatspsubsys.H
+ */
+HdatSpSubsys::~HdatSpSubsys()
+{
+ errlHndl_t o_errlHndl=NULL;
+
+ HDAT_ENTER();
+
+ // Free the memory allocated for filling this entry.
+ int rc=0;
+ free(iv_ioPathArray);
+ delete[] iv_kwd;
+ rc = mm_block_unmap(reinterpret_cast<void*>(
+ ALIGN_PAGE_DOWN((uint64_t)iv_spSubsys)));
+ if( rc != 0)
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_HDAT_SP_SUBSYS_DTOR
+ * @reasoncode HDAT::RC_DEV_MAP_FAIL
+ * @devdesc Unmap a mapped region failed
+ * @custdesc Firmware encountered an internal error.
+ */
+ hdatBldErrLog(o_errlHndl,
+ HDAT::MOD_HDAT_SP_SUBSYS_DTOR,
+ RC_DEV_MAP_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ HDAT_VERSION1,
+ true);
+ }
+
+ HDAT_EXIT();
+ return;
+}
+
+
+} // end namespace
diff --git a/src/usr/hdat/hdatspsubsys.H b/src/usr/hdat/hdatspsubsys.H
new file mode 100755
index 000000000..927bc13f0
--- /dev/null
+++ b/src/usr/hdat/hdatspsubsys.H
@@ -0,0 +1,291 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatspsubsys.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+
+/**
+ * @file hdatspsubsys.H
+ *
+ * @brief This file contains the class definition for the service processor
+ * subsystem object.
+ *
+ */
+
+#ifndef HDATSPSUBSYS_H
+#define HDATSPSUBSYS_H
+
+/*--------------------------------------------------------------------------*/
+/* Includes */
+/*--------------------------------------------------------------------------*/
+#include <stdint.h> // standard types
+#include <hdat/hdat.H> // HDAT header type definitions
+#include "hdathdif.H" // HdatHdif base class definition
+#include <hdat/hdat_reasoncodes.H>
+
+namespace HDAT
+{
+
+/*--------------------------------------------------------------------------*/
+/* Type definitions */
+/*--------------------------------------------------------------------------*/
+
+/** @enum hdatSpStatus
+ * Status of a service procesor card
+ */
+enum hdatSpStatus
+{
+ HDAT_SP_INSTALLED = 0x8000, // service processor is installed
+ HDAT_SP_FUNCTIONAL = 0x4000, // service processor is functional
+ HDAT_SP_PRIMARY = 0x2000 // this is the primary service processor
+};
+
+// The number of data pointers in hdatDataPtrs (defined in hdatspsubsys.C)
+#define HDAT_SPSUBSYS_NUM_DATA_PTRS 8
+
+/** @brief eye catcher for the HDIF header for the SP subsystem data area
+ */
+const char HDAT_STRUCT_NAME[] = "SPINFO";
+
+/** @brief Structure version number
+ */
+const uint16_t HDAT_SP_SUBSYS_VERSION = 0x0021;
+
+/** @brief Structure definition for service processor hardware and software.
+ Reserved bytes are added to make the structure a multiple of 4 bytes.
+ Adjust the reserved size as necessary if new members are added to this
+ structure.
+ */
+struct hdatSpImpl_t
+{
+ uint16_t hdatHdwVer; // 0x0000 Hardware version
+ uint16_t hdatSftVer; // 0x0002 Software version
+ uint16_t hdatStatus; // 0x0004 SP functionality/status
+ uint8_t hdatChipVer; // 0x0006 SP chip DD level
+ uint8_t hdatReserved1; // 0x0007 padding for alignment
+} __attribute__ ((packed));
+
+
+/** @brief Structure definition for the I/O path to the service processor
+ */
+struct hdatSpIoPath_t
+{
+ uint16_t hdatPathType; // 0x0000 I/O path type
+ uint16_t hdatLinkStatus; // 0x0002 PSI Link status
+ uint8_t hdatML2ChipVer; // 0x0004 Chip DD level of ML2 controller
+ uint8_t hdatResvd[1]; // 0x0005 Reserved
+ uint16_t hdatSlcaCnt; // 0x0006 Count of entries in hdatSlxaIdx
+ uint16_t hdatSlcaIdx[8]; // 0x0008 Array of SLCA indexes
+ uint32_t hdatProcChipId; // 0x0018 Processor chip id
+ uint8_t hdatResvd1[4]; // 0x001C Padding for alignment
+ hdatMsAddr_t hdatGxcBaseAddr; // 0x0020 PSI GX Base address
+
+} __attribute__ ((packed));
+
+#define HDAT_NON_FUNCTIONAL 0 // PSI link is not functional
+#define HDAT_CURRENT_LINK 1 // This FSP's current functional link
+#define HDAT_CANDIDATE_LINK 2 // Candidate link if current link fails
+
+/** @brief Structure definition for the service processor memory
+ */
+struct hdatSpMem_t
+{
+ uint32_t deprecated1[5]; // Deprecated in latest spec 9.13c
+ uint32_t hdatHostRamSize; // 0x0014 Size of host private NVRAM
+ uint32_t deprecated2[2]; // Deprecated in latest spec 9.13c
+} __attribute__ ((packed));
+
+/** @enum hdatSpSubSysDataPtrs
+ * Constants for the internal data pointers that are added to the base
+ * class
+ */
+enum hdatSpSubSysDataPtrs
+{
+ HDAT_SPSUBSYS_FRU_ID = 0,
+ HDAT_SPSUBSYS_KWD = 1,
+ HDAT_SPSUBSYS_IMPL = 2,
+ HDAT_SPSUBSYS_DEPRECATED = 3,
+ HDAT_SPSUBSYS_MEMORY = 4,
+ HDAT_SPSUBSYS_IO_PATH = 5,
+ HDAT_SPSUBSYS_RESERVED1 = 6,
+ HDAT_SPSUBSYS_RESERVED2 = 7,
+ HDAT_SPSUBSYS_LAST = 8
+};
+
+const uint32_t HDAT_MAX_NUM_IO_PATHS = 32;
+const uint16_t HDAT_LPC_PATH_TYPE = 3;
+const uint32_t HDAT_NUM_IO_PATHS_FOR_BMC = 1;
+const uint32_t LPC_PATH_FRU_CNT_FOR_BMC = 2;
+
+
+/*-----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*-----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatSpSubsys class is used to construct objects that describe
+ * the service processor hardware and software.
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that anyone can create an object of this type. In particular,
+ * the object is built only in the hdatstep process when the step
+ * that builds hypervisor data structures is run.
+ *
+ * The real purpose of the object is to create the service processor
+ * subsystem structure as defined by the PHYP Initialization architecture
+ * This data structure is eventually DMA'd to main memory. The
+ * class is not defined to be a general purpose interface for
+ * building this object by anyone other than the hdatstep process.
+ *
+ * Thread safety: An HdatSpSubsys object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by
+ * multiple threads at the same time. An object can be used by
+ * multiple threads if the threads serialize access. And of
+ * course, each thread can use its own object with no concerns
+ * about what other threads are doing.
+ *
+ * Signal handler usage: This class is not intended to be used in a signal handler
+ * and nothing has been done to try and make it safe to use
+ * in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatSpSubsys : public HdatHdif
+{
+ public:
+
+ /**
+ * @brief Construct an HdatSpSubsys object.
+ *
+ * This is the constructor for the HdatSpSubsys object.
+ *
+ * If you are constructing this object on the heap by using new, then
+ * you must check the pointer returned from new to see if it is null.
+ * If it is null, new failed to allocate storage and the constructor
+ * was not called. If it is not null, then you must check o_errlHndl
+ * to see if the constructor ran successfully. If o_errlHndl indicates
+ * an error was reported by the constructor, new has already allocated
+ * heap storage and the object must be deleted in order to free the
+ * heap storage.
+ *
+ * @pre None
+ *
+ * @post An HdatSpSubsys object has been constructed. Heap storage has been allocated.
+ *
+ * @param o_errlHndl - output parameter - If any errors occur, the HdatSpSubsys object
+ * is NOT constructed and errors are returned in this parameter
+ * @param i_resourceId - input parameter - The resource id of the service processor FRU
+ * @param i_msAddr - input parameter - The main memory address that the service
+ * processor subsystem structure will be DMA'd to.
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by o_errlHndl contains one of:
+ *
+ * @retval HDAT_REGISTRY_ERROR
+ * @retval HDAT_OTHER_COMP_ERROR
+ */
+ HdatSpSubsys(errlHndl_t &o_errlHndl,
+ hdatMsAddr_t &io_msAddr);
+
+
+ /**
+ * @brief HdatSpSubsys object destructor
+ *
+ * This is the destructor for an HdatSpSubsys object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatSpSubsys object has been destroyed and can no longer be used.
+ *
+ */
+ virtual ~HdatSpSubsys();
+ /**
+ * @brief member function to get the size of sp sub sys structure
+ *
+ * Getter for iv_size
+ */
+ uint32_t getSpSubSysStructSize();
+
+ /**
+ * @brief function to fill internal data pointers.
+ *
+ * @return A null error handle if successfull
+ */
+ errlHndl_t hdatFillDataPtrs();
+
+
+ private:
+ /** Object Instance Data
+ *
+ * @li iv_msAddr - Mainstore phyisical address
+ * @li iv_kwdSize - size of the ASCII keyword
+ * @li iv_kwd - ptr to storage which holds the ASCII keyword
+ * @li iv_fru - FRU Id information
+ * @li iv_impl - hardware/software implementation
+ * @li iv_mem - FSP memory information
+ * @li iv_ioPathArrayHdr - I/O path array header
+ * @li iv_ioPathArray - I/O path(s) to the FSP card
+ * @li iv_spSubsys - virtual address for SP sub sys data
+ * @li iv_size - size of the sp sub sys total structure
+ */
+ uint64_t iv_msAddr;
+ uint32_t iv_kwdSize;
+ char *iv_kwd;
+ hdatFruId_t iv_fru;
+ hdatSpImpl_t iv_impl;
+ hdatSpMem_t iv_mem;
+ hdatHDIFDataArray_t iv_ioPathArrayHdr;
+ hdatSpIoPath_t *iv_ioPathArray;
+ uint8_t *iv_spSubsys;
+ uint32_t iv_size;
+ uint32_t iv_numOfIoPaths;
+
+
+ /** Class (static) Data
+ *
+ * Only one copy of this data exists in a process.
+ *
+ * @li cv_actualCnt - a count of how many HdatSpSubsys objects are created
+ */
+ static uint32_t cv_actualCnt;
+
+}; // end of HdatSpSubsys class
+
+/**
+ * @brief This routine Loads SP Sub sys information.
+ *
+ * @param io_msAddr - input parameter - Mainstore address for SP subsys to write
+ * @param o_spSubsysCnt - output parameter - Count of SP Sub sys structures
+ *
+ * @return A null error log handle if successful, else the return code pointed
+ * to by errlHndl_t contains one of:
+ *
+ * @retval
+ */
+
+errlHndl_t HdatLoadSpSubSys(hdatMsAddr_t &i_msAddr,
+ uint32_t &o_spSubSysTotalSize , uint32_t &o_spSubsysCnt);
+
+}
+#endif // HDATSPSUBSYS_H
diff --git a/src/usr/hdat/hdatutil.C b/src/usr/hdat/hdatutil.C
new file mode 100644
index 000000000..4d95fbc8f
--- /dev/null
+++ b/src/usr/hdat/hdatutil.C
@@ -0,0 +1,1351 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatutil.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 "hdatutil.H"
+#include <i2c/eepromif.H>
+#include <stdio.h>
+
+#define UINT16_IN_LITTLE_ENDIAN(x) (((x) >> 8) | ((x) << 8))
+
+using namespace TARGETING;
+namespace HDAT
+{
+trace_desc_t *g_trac_hdat = NULL;
+TRAC_INIT(&g_trac_hdat,HDAT_COMP_NAME,4096);
+
+
+/*******************************************************************************
+* hdatBldErrLog
+*******************************************************************************/
+void hdatBldErrLog(errlHndl_t & io_err,
+ const uint8_t i_modid,
+ const uint16_t i_rc,
+ const uint32_t i_data1,
+ const uint32_t i_data2,
+ const uint32_t i_data3,
+ const uint32_t i_data4,
+ const ERRORLOG::errlSeverity_t i_sev,
+ const uint16_t i_version,
+ const bool i_commit,
+ const bool i_callout )
+{
+ HDAT_DBG("mod:0x%02X, rc:0x%02X, data:%08X %08X %08X %08X, sev:0x%02X",
+ i_modid, i_rc, i_data1, i_data2, i_data3, i_data4,
+ i_sev);
+
+ if (NULL == io_err)
+ {
+ io_err = new ERRORLOG::ErrlEntry(i_sev,
+ i_modid,
+ i_rc,
+ TWO_UINT32_TO_UINT64(i_data1,i_data2),
+ TWO_UINT32_TO_UINT64(i_data3,i_data4));
+ }
+ else
+ {
+ uint32_t additionalSrc[] =
+ {
+ uint32_t(HDAT_COMP_ID | i_rc), uint32_t(i_modid),
+ uint32_t(i_sev),
+ i_data1, i_data2, i_data3, i_data4
+ };
+ io_err->addFFDC(HDAT_COMP_ID,
+ additionalSrc,
+ sizeof(additionalSrc),
+ i_version,
+ SUBSEC_ADDITIONAL_SRC);
+
+ }
+
+ if ( i_callout )
+ {
+ io_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ }
+ io_err->collectTrace(HDAT_COMP_NAME);
+ io_err->collectTrace("HDAT_DBG");
+ io_err->collectTrace("HDAT_ERR");
+
+ if ( i_commit )
+ {
+ ERRORLOG::errlCommit(io_err,HDAT_COMP_ID);
+ }
+}
+
+/*******************************************************************************
+* isFunctional
+*******************************************************************************/
+bool isFunctional( const Target* i_Target)
+{
+ bool o_funcState = false;
+ errlHndl_t l_errl = NULL;
+ do
+ {
+ if(NULL == i_Target)
+ {
+ HDAT_ERR("Input Target Pointer is NULL");
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_IS_FUNCTIONAL
+ * @reasoncode HDAT::RC_INVALID_OBJECT
+ * @devdesc Input Target Pointer is NULL
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_errl,
+ MOD_UTIL_IS_FUNCTIONAL,
+ RC_INVALID_OBJECT,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ HDAT_VERSION1,
+ true);
+ break;
+ }
+ else
+ {
+ o_funcState = i_Target->getAttr<ATTR_HWAS_STATE>().functional;
+ }
+ }while(0);
+ return o_funcState;
+}
+
+/*******************************************************************************
+* hdatGetIdEc
+*******************************************************************************/
+errlHndl_t hdatGetIdEc(const Target *i_pTarget,
+ uint32_t &o_ecLevel,
+ uint32_t &o_chipId)
+{
+ errlHndl_t l_err = NULL;
+
+ do
+ {
+ const TARGETING::Target *l_pCTarget = NULL;
+ if(i_pTarget->getAttr<TARGETING::ATTR_CLASS>() != TARGETING::CLASS_CHIP)
+ {
+ l_pCTarget = getParentChip(i_pTarget);
+ o_ecLevel = l_pCTarget->getAttr<TARGETING::ATTR_EC>();
+ o_chipId = l_pCTarget->getAttr<TARGETING::ATTR_CHIP_ID>();
+ }
+ else
+ {
+ o_ecLevel = i_pTarget->getAttr<TARGETING::ATTR_EC>();
+ o_chipId = i_pTarget->getAttr<TARGETING::ATTR_CHIP_ID>();
+ }
+ }
+ while(0);
+
+ return l_err;
+}
+
+/*******************************************************************************
+* hdatGetHwCardId
+*******************************************************************************/
+errlHndl_t hdatGetHwCardId(const Target *i_pTarget, uint32_t &o_cardId)
+{
+ errlHndl_t l_errl = NULL;
+ do
+ {
+ if(NULL == i_pTarget)
+ {
+ HDAT_ERR("Input Target pointer is NULL.");
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_CARD_ID
+ * @reasoncode HDAT::RC_INVALID_OBJECT
+ * @devdesc Input Target Pointer is NULL
+ * @custdesc Firmware encountered an internal
+ * error while retrieving target data
+ */
+ hdatBldErrLog(l_errl,
+ MOD_UTIL_CARD_ID,
+ RC_INVALID_OBJECT,
+ 0,0,0,0);
+ break;
+ }
+ if((i_pTarget->getAttr<ATTR_CLASS>() != CLASS_CARD)&&
+ (i_pTarget->getAttr<ATTR_CLASS>() != CLASS_LOGICAL_CARD)&&
+ (i_pTarget->getAttr<ATTR_CLASS>() != CLASS_CHIP))
+ {
+ HDAT_ERR("Input Target is class not supported.");
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_CARD_ID
+ * @reasoncode HDAT::RC_TARGET_UNSUPPORTED
+ * @devdesc Target is not currently supported
+ * @custdesc Firmware encountered an internal error
+ * while retrieving attribute data
+ */
+ hdatBldErrLog(l_errl,
+ MOD_UTIL_CARD_ID,
+ RC_TARGET_UNSUPPORTED,
+ 0,0,0,0);
+ break;
+ }
+ TARGETING::TargetHandleList targetList;
+ targetList.clear();
+ getParentAffinityTargets(targetList,i_pTarget,
+ TARGETING::CLASS_ENC,TARGETING::TYPE_NODE);
+ if(targetList.empty())
+ {
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_CARD_ID
+ * @reasoncode HDAT::RC_EMPTY_TARGET_LIST
+ * @devdesc Target list is empty
+ * @custdesc Firmware encountered an internal
+ * error while retrieving target data
+ */
+ hdatBldErrLog(l_errl,
+ MOD_UTIL_CARD_ID,
+ RC_EMPTY_TARGET_LIST,
+ 0,0,0,0);
+ break;
+ }
+ //get the parent node id
+ TARGETING::Target* l_pNodeTarget = targetList[0];
+ o_cardId = l_pNodeTarget->getAttr<ATTR_ORDINAL_ID>();
+ }
+ while(0);
+
+ return l_errl;
+}
+
+/**
+ * @brief This routine populates the MTM and Serial number attributes
+ of system Target
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param None
+ *
+ * @return None
+ */
+void hdatPopulateMTMAndSerialNumber()
+{
+ errlHndl_t l_errl = NULL;
+ TARGETING::ATTR_RAW_MTM_type l_rawMTM = {0};
+ TARGETING::ATTR_SERIAL_NUMBER_type l_serialNumber = {0};
+ TARGETING::Target *l_pSysTarget = NULL;
+ size_t l_vpdSize = 0;
+
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSysTarget);
+ if(l_pSysTarget == NULL)
+ {
+ HDAT_ERR("Error in getting Top Level Target");
+ assert(l_pSysTarget != NULL);
+ }
+
+ TARGETING::PredicateCTM l_nodePredicate(TARGETING::CLASS_ENC,
+ TARGETING::TYPE_NODE);
+ TARGETING::PredicateHwas l_predHwas;
+ l_predHwas.present(true);
+
+ TARGETING::PredicatePostfixExpr l_presentNode;
+ l_presentNode.push(&l_nodePredicate).push(&l_predHwas).And();
+
+ //Get all Nodes
+ TARGETING::TargetRangeFilter l_nodeFilter(
+ TARGETING::targetService().begin(),
+ TARGETING::targetService().end(),
+ &l_presentNode);
+
+ TARGETING::Target *l_nodeTarget = (*l_nodeFilter);
+
+ l_errl = deviceRead(l_nodeTarget, NULL, l_vpdSize,
+ DEVICE_PVPD_ADDRESS( PVPD::OSYS, PVPD::MM ));
+
+ if(l_errl == NULL)
+ {
+ uint8_t l_vpddata[l_vpdSize];
+
+ l_errl = deviceRead(l_nodeTarget, l_vpddata, l_vpdSize,
+ DEVICE_PVPD_ADDRESS( PVPD::OSYS, PVPD::MM ));
+
+ if(l_errl == NULL)
+ {
+ const uint8_t l_mtmSize= 0x08;
+ //phyp would requre just 8 character of MTM
+ strncpy(l_rawMTM,reinterpret_cast<const char*>(l_vpddata),
+ l_mtmSize);
+ for(uint8_t i=0; i<sizeof(l_rawMTM); i++)
+ {
+ if(l_rawMTM[i] == '-')
+ {
+ l_rawMTM[i]='.';
+ break;
+ }
+ }
+
+ if(!l_pSysTarget->trySetAttr<TARGETING::ATTR_RAW_MTM>
+ (l_rawMTM))
+ {
+ HDAT_ERR("Error in setting MTM");
+ }
+ }
+ }
+ if(l_errl)
+ {
+ ERRORLOG::errlCommit(l_errl,HDAT_COMP_ID);
+ }
+
+ l_errl = deviceRead(l_nodeTarget, NULL, l_vpdSize,
+ DEVICE_PVPD_ADDRESS( PVPD::OSYS, PVPD::SS ));
+
+ if(l_errl == NULL)
+ {
+ uint8_t l_vpddata[l_vpdSize];
+
+ l_errl = deviceRead(l_nodeTarget, l_vpddata, l_vpdSize,
+ DEVICE_PVPD_ADDRESS( PVPD::OSYS, PVPD::SS ));
+
+ if(l_errl == NULL)
+ {
+ const uint8_t l_serialSize = 0x07;
+ //phyp would requre just 7 character of serial number
+ strncpy(reinterpret_cast<char *>(l_serialNumber),
+ reinterpret_cast<const char*>(l_vpddata),l_serialSize);
+
+ if(!l_pSysTarget->trySetAttr
+ <TARGETING::ATTR_SERIAL_NUMBER>(l_serialNumber))
+ {
+ HDAT_ERR("Error in setting Serial Number");
+ }
+ }
+ }
+
+ if(l_errl)
+ {
+ ERRORLOG::errlCommit(l_errl,HDAT_COMP_ID);
+ }
+
+}
+
+/**
+ * @brief This routine gets prefix of location code
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param o_locCode - output parameter - Location Code Prefix
+ *
+ * @return None
+ */
+void hdatGetLocationCodePrefix(char *o_locCode)
+{
+ TARGETING::ATTR_RAW_MTM_type l_rawMTM = {0};
+ TARGETING::ATTR_SERIAL_NUMBER_type l_serialNumber = {0};
+ TARGETING::Target *l_pSysTarget = NULL;
+
+ (void) TARGETING::targetService().getTopLevelTarget(l_pSysTarget);
+ if(l_pSysTarget == NULL)
+ {
+ HDAT_ERR("Error in getting Top Level Target");
+ assert(l_pSysTarget != NULL);
+ }
+
+ strcpy(o_locCode, "U");
+
+ //if(l_pSysTarget == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL)
+ // {
+ // assert(false);
+ // }
+
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_RAW_MTM>(l_rawMTM))
+ {
+ if(l_pSysTarget->tryGetAttr<TARGETING::ATTR_SERIAL_NUMBER>
+ (l_serialNumber))
+ {
+ strcat(o_locCode,"OPWR");
+ strcat(o_locCode,".");
+ strcat(o_locCode,"BAR");
+ strcat(o_locCode,".");
+ strcat(o_locCode,(const char*)l_serialNumber);
+ }
+ else
+ {
+ HDAT_ERR("Error accessing ATTR_SERIAL_NUMBER attribute");
+ }
+ }
+ else
+ {
+ HDAT_ERR("Error accessing ATTR_RAW_MTM attribute");
+ }
+}
+
+/**
+ * @brief This routine constructs the location Code for the incoming target
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_pFruTarget - input parameter - System target
+ * i_locCodePrefix - input parameter - Location Code prefix
+ * o_locCode - output parameter - Constructed location code
+ *
+ * @return None
+ */
+void hdatGetLocationCode(TARGETING::Target *i_pFruTarget,
+ char *i_locCodePrefix,
+ char *o_locCode)
+{
+ TARGETING::ATTR_PHYS_PATH_type l_physPath;
+ char *l_pPhysPath;
+ char l_locCode[64] = {0};
+
+//@TODO:RTC 149347: Add methods to generate location codes
+
+ if(i_pFruTarget->tryGetAttr<TARGETING::ATTR_PHYS_PATH>(l_physPath))
+ {
+ char *l_cutString;
+ char *l_suffix;
+
+ l_pPhysPath = i_pFruTarget->getAttr
+ <TARGETING::ATTR_PHYS_PATH>().toString();
+
+ l_cutString = strchr(l_pPhysPath, '/');
+ l_suffix = l_cutString;
+
+ while (l_cutString != NULL)
+ {
+ l_suffix = l_cutString;
+ l_cutString = strchr(l_cutString+1, '/');
+ }
+
+#if USE_PHYS_PATH_FOR_LOC_CODE
+
+ strncpy(l_hdatslcaentry.location_code,
+ reinterpret_cast<const char *>
+ (i_Target->getAttr<TARGETING::ATTR_PHYS_PATH>().toString()),
+ l_hdatslcaentry.max_location_code_len);
+#else
+
+ sprintf(l_locCode, "%s-%s",i_locCodePrefix,(l_suffix+1));
+
+ uint8_t l_index = 0;
+ while(l_index < strlen(l_locCode))
+ {
+ if(l_locCode[l_index] != ' ')
+ {
+ *o_locCode++ = l_locCode[l_index];
+ }
+ l_index++;
+ }
+ // *o_locCode = 0;
+#endif
+ }
+ else
+ {
+ HDAT_ERR("Error accessing ATTR_PHYS_PATH attribute");
+ }
+}
+
+/******************************************************************************/
+//hdatGetAsciiKwd
+/******************************************************************************/
+
+errlHndl_t hdatGetAsciiKwd( TARGETING::Target * i_target,uint32_t &o_kwdSize,
+ char* &o_kwd,vpdType i_vpdtype,struct vpdData i_fetchVpd[],
+ uint32_t i_num, size_t theSize[])
+{
+ HDAT_ENTER();
+ errlHndl_t l_err = NULL;
+
+ switch (i_vpdtype)
+ {
+ case PROC:
+ l_err = hdatGetAsciiKwdForMvpd(i_target,o_kwdSize,o_kwd,
+ i_fetchVpd,i_num,theSize);
+ HDAT_DBG("got back kwd size=%x",o_kwdSize);
+ break;
+ case BP:
+ l_err = hdatGetAsciiKwdForPvpd(i_target,o_kwdSize,o_kwd,
+ i_fetchVpd,i_num,theSize);
+ HDAT_DBG("got back kwd size=%x",o_kwdSize);
+ break;
+ default:
+ HDAT_DBG("no appropriate vpd function to call");
+ break;
+ }
+ HDAT_EXIT();
+ return l_err;
+}//end hdatGetAsciiKwd
+
+/******************************************************************************/
+//hdatGetAsciiKwdForPvpd
+/******************************************************************************/
+errlHndl_t hdatGetAsciiKwdForPvpd(TARGETING::Target * i_target,
+ uint32_t &o_kwdSize,char* &o_kwd,
+ struct vpdData i_fetchVpd[], size_t i_num, size_t theSize[])
+{
+
+ errlHndl_t l_err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+ VPD::vpdRecord theRecord = 0x0;
+ VPD::vpdKeyword theKeyword = 0x0;
+
+
+ o_kwd = NULL;
+ o_kwdSize = 0;
+ //size_t theSize[i_num];
+ memset (theSize,0, sizeof(theSize));
+
+ do
+ {
+ assert(i_target != NULL);
+
+ uint8_t *theData = NULL;
+
+ const uint32_t numCmds = i_num;
+
+ for( uint32_t curCmd = 0; curCmd < numCmds; curCmd++ )
+ {
+ cmds++;
+ theRecord = i_fetchVpd[curCmd].record;
+ theKeyword = i_fetchVpd[curCmd].keyword;
+
+ if( theKeyword == PVPD::LX)
+ {
+ theSize[curCmd] = 0;
+ continue;
+ }
+ l_err = deviceRead( i_target,
+ NULL,
+ theSize[curCmd],
+ DEVICE_PVPD_ADDRESS( theRecord,
+ theKeyword ) );
+ if( l_err )
+ {
+ fails++;
+ HDAT_DBG("hdatGetAsciiKwdForPvpd::failure reading keyword size "
+ "rec: 0x%04x, kwd: 0x%04x",
+ theRecord,theKeyword );
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_PVPD_READ_FUNC
+ * @reasoncode HDAT::RC_PVPD_FAIL
+ * @userdata1 pvpd record
+ * @userdata2 pvpd keyword
+ * @devdesc PVPD read fail
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_err,
+ MOD_UTIL_PVPD_READ_FUNC,
+ RC_PVPD_FAIL,
+ theRecord,theKeyword,0,0,
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ HDAT_VERSION1,
+ true);
+
+ continue;
+ }
+ HDAT_DBG("fetching BP kwd size PVPD, size initialised=%x "
+ " keyword =%04x",theSize[curCmd],theKeyword);
+ o_kwdSize += theSize[curCmd];
+ }
+
+ HDAT_DBG("hdatGetAsciiKwdForPvpd:: allocating total key word size %d",
+ o_kwdSize);
+ o_kwd = new char[o_kwdSize];
+
+ uint32_t loc = 0;
+ for( uint32_t curCmd = 0; curCmd < numCmds; curCmd++ )
+ {
+ theRecord = i_fetchVpd[curCmd].record;
+ theKeyword = i_fetchVpd[curCmd].keyword;
+
+ //this conidtion is , if in the top loop there is a fail then
+ //theSize[curCmd] will be 0.
+ if( theSize[curCmd] == 0)
+ {
+ continue;
+ }
+ theData = new uint8_t [theSize[curCmd]];
+
+ HDAT_DBG("hdatGetAsciiKwdForPvpd: reading %dth keyword of size %d",
+ curCmd,theSize[curCmd]);
+
+ l_err = deviceRead( i_target,
+ theData,
+ theSize[curCmd],
+ DEVICE_PVPD_ADDRESS( theRecord,
+ theKeyword ) );
+ HDAT_DBG("hdatGetAsciiKwdForPvpd: read BP data %s",theData);
+
+ if ( l_err )
+ {
+ fails++;
+ HDAT_DBG("hdatGetAsciiKwdForPvpd: Failure on Record: "
+ "0x%04x, keyword: 0x%04x, of size: 0x%04x - test %d",
+ theRecord,theKeyword,theSize,curCmd);
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_PVPD_READ_FUNC
+ * @reasoncode HDAT::RC_PVPD_READ_FAIL
+ * @userdata1 pvpd record
+ * @userdata2 pvpd keyword
+ * @devdesc PVPD read fail
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_err,
+ MOD_UTIL_PVPD_READ_FUNC,
+ RC_PVPD_READ_FAIL,
+ theRecord,theKeyword,0,0,
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ HDAT_VERSION1,
+ true);
+
+ if ( NULL != theData )
+ {
+ delete[] theData;
+ theData = NULL;
+ }
+ continue;
+ }
+ if ( NULL != theData )
+ {
+ memcpy(reinterpret_cast<void *>(o_kwd + loc),theData,
+ theSize[curCmd]);
+
+ loc += theSize[curCmd];
+ delete[] theData;
+ theData = NULL;
+ HDAT_DBG("hdatGetAsciiKwdForPvpd: copied to main array %d kwd",
+ curCmd);
+ }
+ }
+ }while(0);
+
+ HDAT_DBG("hdatGetAsciiKwdForPvpd: returning keyword size %d and data %s",
+ o_kwdSize,o_kwd);
+ return l_err;
+
+}
+
+/******************************************************************************/
+// hdatGetAsciiKwdForMvpd
+/******************************************************************************/
+
+errlHndl_t hdatGetAsciiKwdForMvpd(TARGETING::Target * i_target,
+ uint32_t &o_kwdSize,char* &o_kwd,
+ struct vpdData i_fetchVpd[], uint32_t i_num,size_t theSize[])
+{
+ HDAT_ENTER();
+ errlHndl_t err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+ uint64_t theRecord = 0x0;
+ uint64_t theKeyword = 0x0;
+
+ o_kwd = NULL;
+ o_kwdSize = 0;
+
+
+ do
+ {
+ if(i_target == NULL)
+ {
+ HDAT_ERR("no functional Targets found");
+ break;
+ }
+
+ //size_t theSize[100] = {0};//assuming max kwd num 100
+ uint8_t *theData = NULL;
+
+
+ for( uint32_t curCmd = 0; curCmd < i_num; curCmd++ )
+ {
+ cmds++;
+ theRecord = (uint64_t)i_fetchVpd[curCmd].record;
+ theKeyword = (uint64_t)i_fetchVpd[curCmd].keyword;
+
+ HDAT_DBG("fetching proc kwd size MVPD, size initialised=%x",
+ theSize[curCmd]);
+ err = deviceRead( i_target,
+ NULL,
+ theSize[curCmd],
+ DEVICE_MVPD_ADDRESS( theRecord,
+ theKeyword ) );
+ HDAT_DBG("fetched proc kwd size MVPD, size=%x",theSize[curCmd]);
+
+ if( err )
+ {
+ fails++;
+ HDAT_DBG("failure reading keyword size "
+ "rec: 0x%04x, kwd: 0x%04x",
+ theRecord,theKeyword );
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_VPD
+ * @reasoncode HDAT::RC_DEV_READ_FAIL
+ * @devdesc Device read failed
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(err,
+ MOD_UTIL_VPD,
+ RC_DEV_READ_FAIL,
+ theRecord,theKeyword,0,0,
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ HDAT_VERSION1,
+ true);
+ continue;
+ }
+ o_kwdSize += theSize[curCmd];
+ }
+
+ HDAT_DBG("allocating total key word size %d",
+ o_kwdSize);
+ //o_kwd = static_cast<char *>(malloc( o_kwdSize));
+ o_kwd = new char[o_kwdSize];
+
+ uint32_t loc = 0;
+ for( uint32_t curCmd = 0; curCmd < i_num; curCmd++ )
+ {
+ theRecord = (uint64_t)i_fetchVpd[curCmd].record;
+ theKeyword = (uint64_t)i_fetchVpd[curCmd].keyword;
+
+ //theData = static_cast<uint8_t*>(malloc( theSize[curCmd] ));
+ theData = new uint8_t [theSize[curCmd]];
+
+ HDAT_DBG("reading %dth keyword of size %d",
+ curCmd,theSize[curCmd]);
+
+ err = deviceRead( i_target,
+ theData,
+ theSize[curCmd],
+ DEVICE_MVPD_ADDRESS( theRecord,
+ theKeyword ) );
+ HDAT_DBG("read PROC data %s",theData);
+
+ if ( err )
+ {
+ fails++;
+ HDAT_DBG("hdatGetAsciiKwdForMvpd: Failure on Record: "
+ "0x%04x, keyword: 0x%04x, of size: 0x%04x - test %d",
+ theRecord,theKeyword,theSize,curCmd);
+
+ delete err;
+
+ if ( NULL != theData )
+ {
+ // free( theData );
+ delete[] theData;
+ theData = NULL;
+ }
+ continue;
+ }
+ if ( NULL != theData )
+ {
+ //copy to output array and free theData
+ memcpy(reinterpret_cast<void *>(o_kwd + loc),theData,
+ theSize[curCmd]);
+
+ loc += theSize[curCmd];
+ //free( theData );
+ delete[] theData;
+ theData = NULL;
+ HDAT_DBG("copied to main array %d kwd",
+ curCmd);
+ }
+ }
+
+ }while(0);
+
+ HDAT_DBG("returning keyword size %d and data %s",
+ o_kwdSize,o_kwd);
+
+ HDAT_EXIT();
+ return err;
+}//end hdatGetAsciiKwdForMvpd
+
+
+/******************************************************************************/
+// hdatGetAsciiKwdForCvpd
+/******************************************************************************/
+errlHndl_t hdatGetAsciiKwdForCvpd(TARGETING::Target * i_target,
+ uint32_t &o_kwdSize,char* &o_kwd,
+ struct vpdData i_fetchVpd[], size_t i_num,size_t theSize[])
+{
+
+ errlHndl_t l_err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+ VPD::vpdRecord theRecord = 0x0;
+ VPD::vpdKeyword theKeyword = 0x0;
+
+
+ o_kwd = NULL;
+ o_kwdSize = 0;
+ //size_t theSize[i_num];
+
+ do
+ {
+ assert(i_target != NULL);
+
+ uint8_t *theData = NULL;
+
+ const uint32_t numCmds = i_num;
+
+ for( uint32_t curCmd = 0; curCmd < numCmds; curCmd++ )
+ {
+ cmds++;
+ theRecord = i_fetchVpd[curCmd].record;
+ theKeyword = i_fetchVpd[curCmd].keyword;
+
+ HDAT_DBG("fetching DIMM kwd size CVPD, size initialised=%x",
+ theSize[curCmd]);
+ l_err = deviceRead( i_target,
+ NULL,
+ theSize[curCmd],
+ DEVICE_CVPD_ADDRESS( theRecord,
+ theKeyword ) );
+
+ if( l_err )
+ {
+ fails++;
+ HDAT_DBG("hdatGetAsciiKwdForCvpd::failure reading keyword size "
+ "rec: 0x%04x, kwd: 0x%04x",
+ theRecord,theKeyword );
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_CVPD_READ_FUNC
+ * @reasoncode HDAT::RC_CVPD_FAIL
+ * @userdata1 cvpd record
+ * @userdata2 cvpd keyword
+ * @devdesc CVPD read fail
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_err,
+ MOD_UTIL_CVPD_READ_FUNC,
+ RC_CVPD_FAIL,
+ theRecord,theKeyword,0,0,
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ HDAT_VERSION1,
+ true);
+
+
+ continue;
+ }
+ o_kwdSize += theSize[curCmd];
+ }
+
+ HDAT_DBG("hdatGetAsciiKwdForCvpd:: allocating total key word size %d",
+ o_kwdSize);
+ o_kwd = new char[o_kwdSize];
+
+ uint32_t loc = 0;
+ for( uint32_t curCmd = 0; curCmd < numCmds; curCmd++ )
+ {
+ theRecord = i_fetchVpd[curCmd].record;
+ theKeyword = i_fetchVpd[curCmd].keyword;
+
+ //this conidtion is , if in the top loop there is a fail then
+ //theSize[curCmd] will be 0.
+ if( theSize[curCmd] == 0)
+ {
+ continue;
+ }
+ theData = new uint8_t [theSize[curCmd]];
+
+ HDAT_DBG("hdatGetAsciiKwdForCvpd: reading %dth keyword of size %d",
+ curCmd,theSize[curCmd]);
+
+ l_err = deviceRead( i_target,
+ theData,
+ theSize[curCmd],
+ DEVICE_CVPD_ADDRESS( theRecord,
+ theKeyword ) );
+ HDAT_DBG("hdatGetAsciiKwdForCvpd: read PROC data %s",theData);
+
+ if ( l_err )
+ {
+ fails++;
+ HDAT_DBG("hdatGetAsciiKwdForCvpd: Failure on Record: "
+ "0x%04x, keyword: 0x%04x, of size: 0x%04x - test %d",
+ theRecord,theKeyword,theSize,curCmd);
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_CVPD_READ_FUNC
+ * @reasoncode HDAT::RC_CVPD_READ_FAIL
+ * @userdata1 cvpd record
+ * @userdata2 cvpd keyword
+ * @devdesc CVPD read fail
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_err,
+ MOD_UTIL_CVPD_READ_FUNC,
+ RC_CVPD_READ_FAIL,
+ theRecord,theKeyword,0,0,
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ HDAT_VERSION1,
+ true);
+
+ if ( NULL != theData )
+ {
+ delete[] theData;
+ theData = NULL;
+ }
+ continue;
+ }
+ if ( NULL != theData )
+ {
+ //copy to output array and free theData
+ memcpy(reinterpret_cast<void *>(o_kwd + loc),theData,
+ theSize[curCmd]);
+
+ loc += theSize[curCmd];
+ delete[] theData;
+ theData = NULL;
+ HDAT_DBG("hdatGetAsciiKwdForCvpd: copied to main array %d kwd",
+ curCmd);
+ }
+ }
+ }while(0);
+
+ HDAT_DBG("hdatGetAsciiKwdForCvpd: returning keyword size %d and data %s",
+ o_kwdSize,o_kwd);
+ return l_err;
+
+}
+
+/*******************************************************************************
+* hdatGetMaxCecNodes
+*******************************************************************************/
+
+uint32_t hdatGetMaxCecNodes()
+{
+ TARGETING::TargetHandleList l_nodeTargetList;
+ do
+ {
+ TARGETING::Target* sys = NULL;
+ TARGETING::targetService().getTopLevelTarget(sys);
+
+ PredicateCTM predNode(CLASS_ENC, TYPE_NODE);
+ PredicateHwas predFunctional;
+ predFunctional.functional(true);
+ PredicatePostfixExpr nodeCheckExpr;
+ nodeCheckExpr.push(&predNode).push(&predFunctional).And();
+ targetService().getAssociated(l_nodeTargetList, sys,
+ TargetService::CHILD, TargetService::IMMEDIATE,
+ &nodeCheckExpr);
+
+ }while(0);
+
+ return l_nodeTargetList.size();
+}
+
+/*******************************************************************************
+* hdatPrintHdrs
+*******************************************************************************/
+void hdatPrintHdrs(const hdatHDIF_t *i_hdif,
+ const hdatHDIFDataHdr_t *i_data,
+ const hdatHDIFDataArray_t *i_dataArray,
+ const hdatHDIFChildHdr_t *i_child)
+{
+ hdatHDIFDataHdr_t *l_data;
+ hdatHDIFChildHdr_t *l_child;
+ uint32_t l_idx;
+ char l_string[sizeof(i_hdif->hdatStructName)+1];
+
+ if (NULL != i_hdif)
+ {
+ // Null terminate the eye catcher string.
+ memcpy(l_string, &i_hdif->hdatStructName,
+ sizeof(i_hdif->hdatStructName));
+ l_string[sizeof(i_hdif->hdatStructName)] = 0x00;
+
+ HDAT_INF(" **hdatHDIF_t**");
+ HDAT_INF(" hdatStructId = 0X %04X ", i_hdif->hdatStructId);
+ HDAT_INF(" hdatStructName = %s", l_string);
+ HDAT_INF(" hdatInstance = %hu", i_hdif->hdatInstance);
+ HDAT_INF(" hdatVersion = %hu", i_hdif->hdatVersion);
+ HDAT_INF(" hdatSize = %u", i_hdif->hdatSize);
+ HDAT_INF(" hdatHdrSize = %u", i_hdif->hdatHdrSize);
+ HDAT_INF(" hdatDataPtrOffset = %u", i_hdif->hdatDataPtrOffset);
+ HDAT_INF(" hdatDataPtrCnt = %hu", i_hdif->hdatDataPtrCnt);
+ HDAT_INF(" hdatChildStrCnt = %hu", i_hdif->hdatChildStrCnt);
+ HDAT_INF(" hdatChildStrOffset = %u", i_hdif->hdatChildStrOffset);
+ }
+
+ if (NULL != i_data && NULL != i_hdif)
+ {
+ l_data = const_cast<hdatHDIFDataHdr_t *>(i_data);
+ HDAT_INF(" **hdatHDIFDataHdr_t**");
+ for (l_idx=0; l_idx<i_hdif->hdatDataPtrCnt; l_idx++)
+ {
+ HDAT_INF(" hdatOffset = %u", l_data->hdatOffset);
+ HDAT_INF(" hdatSize = %u", l_data->hdatSize);
+ l_data++;
+ }
+ }
+
+ if (NULL != i_child && NULL != i_hdif)
+ {
+ l_child = const_cast<hdatHDIFChildHdr_t *>(i_child);
+ HDAT_INF(" **hdatHDIFChildHdr_t**");
+ for (l_idx=0; l_idx<i_hdif->hdatChildStrCnt; l_idx++)
+ {
+ HDAT_INF(" hdatOffset = %u", l_child->hdatOffset);
+ HDAT_INF(" hdatSize = %u", l_child->hdatSize);
+ HDAT_INF(" hdatCnt = %u", l_child->hdatCnt);
+ l_child++;
+ }
+ HDAT_INF("");
+ }
+
+ if (NULL != i_dataArray)
+ {
+ HDAT_INF(" **hdatHDIFDataArray_t**");
+ HDAT_INF(" hdatOffset = %u", i_dataArray->hdatOffset);
+ HDAT_INF(" hdatArrayCnt = %u", i_dataArray->hdatArrayCnt);
+ HDAT_INF(" hdatAllocSize = %u", i_dataArray->hdatAllocSize);
+ HDAT_INF(" hdatActSize = %u", i_dataArray->hdatActSize);
+ }
+
+ return;
+}
+
+/*******************************************************************************
+* hdatPrintKwd
+*******************************************************************************/
+void hdatPrintKwd(const char *i_kwd,
+ int32_t i_kwdLen)
+{
+ const uint32_t HDAT_HEX_SIZE = 16; //16 hex characters per line
+ uint32_t l_cnt, l_lines, l_rem ;
+ char * l_kwd = const_cast<char *>(i_kwd);
+
+
+ l_lines = i_kwdLen / HDAT_HEX_SIZE;
+ l_rem = i_kwdLen % HDAT_HEX_SIZE;
+
+ HDAT_INF(" **ASCII keyword VPD**");
+ if (NULL == i_kwd)
+ {
+ HDAT_INF(" No keyword VPD");
+ }
+ else
+ {
+ for (l_cnt = 0; l_cnt < l_lines; l_cnt++)
+ {
+ HDAT_INF( "0X %08X %08X %08X %08X",
+ (*(reinterpret_cast<uint32_t *>(l_kwd ))) ,
+ (*(reinterpret_cast<uint32_t *>(l_kwd + 4))),
+ (*(reinterpret_cast<uint32_t *>(l_kwd + 8))) ,
+ (*(reinterpret_cast<uint32_t *>(l_kwd + 12))) );
+
+ i_kwd += 16;
+ } // end for loop
+
+
+ if ( l_rem > 0 )
+ {
+ // More to print, but can't go past end of storage and
+ // not easy to use TRACF statements for this
+ if ( l_rem < 5 )
+ {
+ HDAT_INF( "0X %08X ", (*(reinterpret_cast<uint32_t *>(l_kwd))) );
+ }
+ else if ( l_rem < 9 )
+ {
+ HDAT_INF( "0X %08X %08X ",
+ (*(reinterpret_cast<uint32_t *>(l_kwd ))) ,
+ (*(reinterpret_cast<uint32_t *>(l_kwd + 4))) );
+ }
+ else if ( l_rem < 13 )
+ {
+ HDAT_INF( "0X %08X %08X %08X ",
+ (*(reinterpret_cast<uint32_t *>(l_kwd ))) ,
+ (*(reinterpret_cast<uint32_t *>(l_kwd + 4))),
+ (*(reinterpret_cast<uint32_t *>(l_kwd + 8))) );
+ }
+ else
+ { // remainder is up to 15 bytes
+ HDAT_INF( "0X %08X %08X %08X %08X",
+ (*(reinterpret_cast<uint32_t *>(l_kwd ))) ,
+ (*(reinterpret_cast<uint32_t *>(l_kwd + 4))),
+ (*(reinterpret_cast<uint32_t *>(l_kwd + 8))) ,
+ (*(reinterpret_cast<uint32_t *>(l_kwd + 12))) );
+ }
+
+ } // end if remainder non-zero
+
+ } // else we have keyword VPD
+
+ return;
+}
+
+/******************************************************************************/
+// hdatGetAsciiKwdForSpd
+/******************************************************************************/
+errlHndl_t hdatGetAsciiKwdForSpd(TARGETING::Target * i_target,
+ size_t &o_kwdSize,char* &o_kwd)
+{
+
+ errlHndl_t l_err = NULL;
+ uint64_t keyword = SPD::ENTIRE_SPD;
+
+ do
+ {
+ assert(i_target != NULL);
+
+ l_err = deviceRead( i_target,
+ NULL,
+ o_kwdSize,
+ DEVICE_SPD_ADDRESS(keyword) );
+ if (l_err)
+ {
+ break;
+ }
+
+ o_kwd = new char[o_kwdSize];
+
+ l_err = deviceRead( i_target,
+ o_kwd,
+ o_kwdSize,
+ DEVICE_SPD_ADDRESS(keyword) );
+
+ }while(0);
+ if ( l_err )
+ {
+ HDAT_DBG("hdatGetAsciiKwdForSpd : Failure on "
+ " keyword: 0x%04x, of size: 0x%04x ",
+ keyword,o_kwdSize);
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_SPD_READ_FUNC
+ * @reasoncode HDAT::RC_SPD_READ_FAIL
+ * @userdata1 spd keyword
+ * @devdesc SPD read fail
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(l_err,
+ MOD_UTIL_SPD_READ_FUNC,
+ RC_SPD_READ_FAIL,
+ keyword,0,0,0,
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ HDAT_VERSION1,
+ true);
+
+ if ( NULL != o_kwd)
+ {
+ delete[] o_kwd;
+ o_kwd = NULL;
+ }
+ }
+
+ HDAT_DBG("hdatGetAsciiKwdForSpd: returning keyword size %d and data %s",
+ o_kwdSize,o_kwd);
+ return l_err;
+
+}
+
+void hdatGetTarget (const hdatSpiraDataAreas i_dataArea,
+ TARGETING::TargetHandleList &o_targList)
+{
+ TARGETING::TYPE l_type;
+ TARGETING::CLASS l_class;
+
+ switch (i_dataArea)
+ {
+ case HDAT_BACKPLANE_VPD:
+ l_type = TARGETING::TYPE_NODE;
+ l_class = TARGETING::CLASS_ENC;
+ break;
+
+ case HDAT_CLOCK_VPD:
+ l_type = TARGETING::TYPE_NA;
+ l_class = TARGETING::CLASS_NA;
+ break;
+
+ case HDAT_SYS_VPD:
+ l_type = TARGETING::TYPE_SYS;
+ l_class = TARGETING::CLASS_SYS;
+ break;
+
+ case HDAT_ENCLOSURE_VPD:
+ l_type = TARGETING::TYPE_NA;
+ l_class = TARGETING::CLASS_NA;
+ break;
+
+ case HDAT_ANCHOR_VPD:
+ l_type = TARGETING::TYPE_NA;
+ l_class = TARGETING::CLASS_NA;
+ break;
+
+ case HDAT_MISC_CEC_VPD:
+ l_type = TARGETING::TYPE_NA;
+ l_class = TARGETING::CLASS_NA;
+ break;
+ default:
+ l_type = TARGETING::TYPE_NA;
+ l_class = TARGETING::CLASS_NA;
+ break;
+ }
+
+ if ( (l_type != TARGETING::TYPE_NA) &&
+ (l_class != TARGETING::CLASS_NA))
+ {
+ TARGETING::Target* l_sys = NULL;
+ TARGETING::targetService().getTopLevelTarget(l_sys);
+ assert(l_sys != NULL);
+
+ if( (l_type == TARGETING::TYPE_SYS ) &&
+ (l_class == TARGETING::CLASS_SYS))
+ {
+ o_targList.push_back(l_sys);
+ }
+ else
+ {
+ PredicateCTM predNode(l_class, l_type);
+ PredicateHwas predFunctional;
+ predFunctional.functional(true);
+ PredicatePostfixExpr nodeCheckExpr;
+ nodeCheckExpr.push(&predNode).push(&predFunctional).And();
+
+ targetService().getAssociated(o_targList, l_sys,
+ TargetService::CHILD, TargetService::IMMEDIATE,
+ &nodeCheckExpr);
+ }
+
+ }
+
+}
+
+errlHndl_t hdatformatAsciiKwd(const struct vpdData i_fetchVpd[],
+ const size_t &i_num, const size_t theSize[], char* &i_kwd,
+ const uint32_t &i_kwdSize, char* &o_fmtKwd, uint32_t &o_fmtkwdSize,
+ const HdatKeywordInfo i_Keywords[])
+{
+ HDAT_ENTER();
+
+ // i_kwdSize - data size
+ // (i_num* sizeof(uint8_t)) - individual datat size
+ // (2 * sizeof(uint8_t)) - 0x78, 0x84
+ // sizeof(uint16_t) = total data size in size
+ // (i_num* 2) - keyword size
+ o_fmtkwdSize = i_kwdSize + (i_num* sizeof(uint8_t)) +
+ (2 * sizeof(uint8_t)) + sizeof(uint16_t) + (i_num* 2);
+
+ o_fmtKwd = new char[o_fmtkwdSize];
+ //Tag for start of the section
+ uint8_t l_initial = 0x84;
+ uint16_t l_kwdSize = o_fmtkwdSize - sizeof(uint16_t) - (2*sizeof(uint8_t));
+
+ //Need to convert the size into little endian as per format
+ l_kwdSize= UINT16_IN_LITTLE_ENDIAN(l_kwdSize);
+ memcpy(reinterpret_cast<void *>(o_fmtKwd ),&l_initial,sizeof(l_initial));
+ memcpy(reinterpret_cast<void *>(o_fmtKwd + 1),&l_kwdSize,sizeof(l_kwdSize));
+
+ uint32_t l_loc = sizeof(uint16_t) + sizeof(uint8_t);
+ char *ptr = i_kwd;
+
+ for( uint32_t curCmd = 0; curCmd < i_num; curCmd++ )
+ {
+ if( theSize[curCmd] != 0)
+ {
+ memcpy(reinterpret_cast<void *>(o_fmtKwd + l_loc),
+ &i_Keywords[curCmd].keywordName, 2);
+ l_loc += 2;
+
+ uint8_t l_var = theSize[curCmd];
+ memcpy(reinterpret_cast<void *>(o_fmtKwd + l_loc),&l_var,
+ sizeof(uint8_t));
+
+ l_loc += sizeof(uint8_t);
+
+ memcpy(reinterpret_cast<void *>(o_fmtKwd + l_loc),ptr,
+ theSize[curCmd]);
+
+ l_loc += theSize[curCmd];
+
+ ptr += theSize[curCmd];
+ }
+ }
+ //End start tag of the section
+ uint8_t l_end= 0x78;
+ memcpy(reinterpret_cast<void *>(o_fmtKwd +l_loc),&l_end,sizeof(uint8_t));
+ l_loc +=sizeof(uint8_t);
+
+ HDAT_EXIT();
+ return NULL;
+}
+
+
+errlHndl_t hdatGetFullEepromVpd(TARGETING::Target * i_target,
+ size_t &io_dataSize,
+ char* &o_data)
+{
+ errlHndl_t err = NULL;
+
+ HDAT_ENTER();
+ if(i_target != NULL)
+ {
+ o_data = new char[io_dataSize];
+
+ //Collecting Full module VPD data
+ err = deviceOp( DeviceFW::READ,
+ i_target,
+ o_data,
+ io_dataSize,
+ DEVICE_EEPROM_ADDRESS(EEPROM::VPD_PRIMARY, 0));
+ if(err)
+ {
+ HDAT_ERR("Reading Full vpd from Eeprom failed");
+ /*@
+ * @errortype
+ * @moduleid HDAT::MOD_UTIL_FULL_MVPD_READ_FUNC
+ * @reasoncode HDAT::RC_DEV_READ_VPD_FAIL
+ * @devdesc Device read failed
+ * @custdesc Firmware encountered an internal error
+ */
+ hdatBldErrLog(err,
+ MOD_UTIL_FULL_MVPD_READ_FUNC,
+ RC_DEV_READ_VPD_FAIL,
+ 0,0,0,0,
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ HDAT_VERSION1,
+ true);
+ if(o_data != NULL) // No point in keeping this data with err
+ {
+ delete[] o_data;
+ o_data = NULL;
+ }
+ }
+ }
+ else
+ {
+ HDAT_ERR("Input Target is Null");
+ }
+ HDAT_EXIT();
+ return(err);
+}
+
+
+} //namespace HDAT
diff --git a/src/usr/hdat/hdatutil.H b/src/usr/hdat/hdatutil.H
new file mode 100755
index 000000000..6ded4f426
--- /dev/null
+++ b/src/usr/hdat/hdatutil.H
@@ -0,0 +1,396 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatutil.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 */
+
+
+/**
+ * @file hdatutil.H
+ *
+ * @brief This file contains various utility functions used internally by the
+ * hypervisor data area component.
+ */
+
+#ifndef HDATUTIL_H
+#define HDATUTIL_H
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <hdat/hdat_reasoncodes.H>
+#include <trace/interface.H>
+#include <targeting/common/targetservice.H>
+#include <targeting/common/utilFilter.H>
+#include <hdat/hdat.H>
+#include "hdatvpd.H"
+#include "hdatbldda.H"
+#include<vpd/mvpdenums.H>
+#include<vpd/pvpdenums.H>
+#include<vpd/cvpdenums.H>
+#include<vpd/spdenums.H>
+#include <devicefw/driverif.H>
+#include <targeting/common/predicates/predicatectm.H>
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+const uint16_t HDAT_VERSION1 = 1;
+const uint16_t HDAT_VERSION2 = 2;
+const uint16_t HDAT_VERSION3 = 3;
+#define DBG_MRK "D>"
+
+//initialize the trac buffers
+#define HDAT_ENTER() \
+ TRACFCOMP(g_trac_hdat,ENTER_MRK"[%s]",__FUNCTION__);
+
+#define HDAT_EXIT() \
+ TRACFCOMP(g_trac_hdat,EXIT_MRK"[%s]",__FUNCTION__);
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+
+#define AT " [ " __FILE__ " ]:[ " TOSTRING(__LINE__) " ]: "
+
+#define HDAT_ERR( _fmt_, _args_...) \
+ TRACFCOMP( g_trac_hdat,ERR_MRK AT _fmt_, ##_args_ );
+
+#define HDAT_DBG( _fmt_, _args_...) \
+ TRACFCOMP( g_trac_hdat,DBG_MRK _fmt_, ##_args_ );
+
+#define HDAT_INF( _fmt_, _args_...) \
+ TRACFCOMP( g_trac_hdat,DBG_MRK _fmt_, ##_args_ );
+
+namespace HDAT
+{
+
+extern trace_desc_t* g_trac_hdat;
+
+
+/**
+ * @brief Create/Build an Error log and add HADT component trace
+ * if the log exists then FFDC will be added to the existing log and
+ * trace will be collected
+ *
+ * @param[in,out] io_err Error handle to use or NULL to create new handle
+ * @param[in] i_modid Module ID
+ * @param[in] i_rc Return Code
+ * @param[in] i_data1 User data word 1
+ * @param[in] i_data2 User data word 2
+ * @param[in] i_data3 User data word 3
+ * @param[in] i_data4 User data word 4
+ * @param[in] i_sev Error severity
+ * @param[in] i_version Data Version identifier for errorlog user details
+ * @param[in] i_commit true if the log should be committed inside
+ * the function
+ * @param[in] i_callout Default is true to add software callout info
+ */
+void hdatBldErrLog(errlHndl_t & io_err,
+ const uint8_t i_modid,
+ const uint16_t i_rc,
+ const uint32_t i_data1 = 0,
+ const uint32_t i_data2 = 0,
+ const uint32_t i_data3 = 0,
+ const uint32_t i_data4 = 0,
+ const ERRORLOG::errlSeverity_t i_sev =
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ const uint16_t i_version =
+ HDAT_VERSION1,
+ const bool i_commit = false,
+ bool i_callout = true);
+
+/**
+ * @brief Check whether the supplied Target is functional
+ *
+ * @param[in] i_pTarget - Target pointer
+ *
+ * @return bool - Functional state of Target.
+ * functional(TRUE) or not(FALSE). If an invalid target is
+ * supplied then the interface will commit and will return false.
+ *
+ */
+bool isFunctional( const TARGETING::Target* i_Target);
+
+/**
+ * @brief Get the EC Id and Chip Level for the target
+ *
+ * @param[in] i_pTarget
+ * Input target pointer. Must not be NULL (otherwise call will return an
+ * error log). Must be a valid target from the system blueprint.
+ *
+ * @param[out] o_ecLevel - value of EC level for the target
+ * @param[out] o_chipId - value of Chip id for the target
+ *
+ * @return errlHndl_t Error log handle indicating the status of the operation
+ * @retval NULL for Success, non NULL for Failure
+ *
+ */
+errlHndl_t hdatGetIdEc(const TARGETING::Target *i_pTarget, uint32_t &o_ecLevel,
+ uint32_t &o_chipId);
+
+/**
+ * @brief Get the Hardware Card ID
+ *
+ * @param[in] i_pTarget
+ * Input target pointer. Must not be NULL (otherwise call will return an
+ * error log). Must be a valid target from the system blueprint.
+ *
+ * @param[out] o_cardId - Hardware Card ID
+ *
+ * @return errlHndl_t Error log handle indicating the status of the operation
+ * @retval NULL for Success, non NULL for Failure
+ *
+ */
+errlHndl_t hdatGetHwCardId(const TARGETING::Target *i_pTarget,
+ uint32_t &o_cardId);
+
+/**
+ * @brief This routine populates the MTM and Serial number attributes
+ of system Target
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param None
+ *
+ * @return None
+ */
+void hdatPopulateMTMAndSerialNumber();
+
+/**
+ * @brief This routine gets suffix of location code
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_pFruTarget - input parameter - System target
+ * o_LocCodeSuffix - output parameter - Location Code suffix
+ *
+ * @return None
+ */
+void hdatGetLocationCode(TARGETING::Target *i_pFruTarget,
+ char *i_locCodePrefix,
+ char *o_locCode);
+
+/**
+ * @brief This routine gets prefix of location code
+ *
+ * @pre None
+ *
+ * @post None
+ *
+ * @param i_pnodeTarget - input parameter - Node target
+ * o_locCode - output parameter - Location Code Prefix
+ *
+ * @return None
+ */
+void hdatGetLocationCodePrefix(char *o_locCode);
+
+/**
+ * @brief Get the ascii keyword for a TARGET
+ *
+ * @param[in] i_Target input target pointer
+ *
+ * @param[out]o_kwdSize: keyword size
+ * @param[out]o_kwd: key word array
+ *
+ * @param[in] i_vpdtype: enum vpdType to select the appropriate device address
+ * @param[in] i_fetchVpd: relevant structure to be read to fetch the VPD
+ * @param[in] i_num: number of elements in the structure
+ *
+ * @return errlHndl_t NULL on success
+ */
+errlHndl_t hdatGetAsciiKwd(
+ TARGETING::Target * i_target,
+ uint32_t &o_kwdSize,
+ char* &o_kwd,
+ vpdType i_vpdtype,
+ struct vpdData i_fetchVpd[],
+ uint32_t i_num,size_t theSize[]);
+
+/**
+ * @brief Get the ascii keyword for proc
+ *
+ * @param[in] i_target input target pointer
+ * @param[out]o_kwdSize: keyword size
+ * @param[out]o_kwd: key word array
+ * @param[in] i_fetchVpd: relevant structure to be read to fetch the VPD
+ * @param[in] i_num: number of elements in the structure
+ *
+ * @return errlHndl_t NULL on success
+ *
+ */
+errlHndl_t hdatGetAsciiKwdForMvpd(
+ TARGETING::Target * i_target,
+ uint32_t &o_kwdSize,
+ char* &o_kwd,
+ struct vpdData i_fetchVpd[],
+ uint32_t i_num,size_t theSize[]);
+
+/**
+ * @brief Get the ascii keyword for backplane
+ *
+ * @param[out]o_kwdSize: keyword size
+ * @param[out]o_kwd: key word array
+ * @param[in] i_fetchVpd: relevant structure to be read to fetch the VPD
+ * @param[in] i_num: number of elements in the structure
+ *
+ * @return errlHndl_t NULL on success
+ *
+ */
+errlHndl_t hdatGetAsciiKwdForPvpd(
+ TARGETING::Target * i_target,
+ uint32_t &o_kwdSize,
+ char* &o_kwd,
+ struct vpdData i_fetchVpd[],
+ size_t i_num,size_t theSize[]);
+/**
+ * @brief Get the ascii keyword for membuf
+ *
+ * @param[in] i_pTarget input target pointer
+ *
+ * @param[out]o_kwdSize: keyword size
+ * @param[out]o_kwd: key word array
+ * @param[in] i_fetchVpd: Vpd record-keyword table
+ * @return errlHndl_t NULL on success
+ *
+ */
+errlHndl_t hdatGetAsciiKwdForCvpd(
+ TARGETING::Target * i_target,
+ uint32_t &o_kwdSize,
+ char* &o_kwd,
+ struct vpdData i_fetchVpd[],
+ size_t i_num,size_t theSize[]);
+/**
+ * @brief Get the ascii keyword for dimm
+ *
+ * @param[in] i_pTarget input target pointer
+ *
+ * @param[out]o_kwdSize: keyword size
+ * @param[out]o_kwd: key word array
+ * @return errlHndl_t NULL on success
+ *
+ */
+errlHndl_t hdatGetAsciiKwdForSpd(
+ TARGETING::Target * i_target,
+ size_t&o_kwdSize,
+ char* &o_kwd);
+/**
+ * @brief Get the Max Cec nde count
+ *
+ *
+ * @return - Number of nodes present
+ *
+ */
+uint32_t hdatGetMaxCecNodes();
+
+
+/**
+ * @brief This routine is a debug routine that prints out the headers associated
+ * with an HDIF data structure.
+ *
+ * @pre None
+ *
+ * @post Output is directed to standard out
+ *
+ * @param[in] i_hdif - Pointer to data of type hdatHDIF_t
+ * @param[in] i_data - Pointer to data of type hdatHDIFDataHdr_t
+ * @param[in] i_dataArray - Pointer to data of type hdatHDIFDataArray_t
+ * @param[in] i_child - Pointer to data of type hdatHDIFChildHdr_t
+ *
+ */
+
+void hdatPrintHdrs(const hdatHDIF_t *i_hdif,
+ const hdatHDIFDataHdr_t *i_data,
+ const hdatHDIFDataArray_t *i_dataArray,
+ const hdatHDIFChildHdr_t *i_child);
+
+/**
+ * @brief This routine is a debug routine that prints out the ASCII keyword VPD
+ *
+ * @pre None
+ *
+ * @post Output is directed to standard out
+ *
+ * @param[in] i_kwd - Pointer to the ASCII keyword VPD
+ * @param[in] i_kwdLen - Length of the ASCII keyword VPD
+ *
+ */
+
+void hdatPrintKwd(const char *i_kwd,
+ int32_t i_kwdLen);
+
+/**
+ * @brief This routine return the target list for the given data area.
+ *
+ * @pre None
+ *
+ * @post Output is directed to standard out
+ *
+ * @param[in] i_dataArea - area that indicates different VPD type
+ * @param[out] o_targList - target list
+ *
+ */
+void hdatGetTarget (const hdatSpiraDataAreas i_dataArea,
+ TARGETING::TargetHandleList &o_targList);
+/**
+ * @brief Format the ascii keyword based on the HDAT specifiction format
+ *
+ * @param[in] i_fetchVpd: relevant structure to be read to fetch the VPD
+ * @param[in] i_num: number of elements in the structure
+ * @param[in] theSize: Size of the each keyword data value
+ * @param[in] i_kwd: keyword data array
+ * @param[in] i_kwdSize: keyword data size
+ * @param[out] o_kwd: format keyword data array
+ * @param[out] o_kwdSize: format keyword data size
+ * @param[in] i_Keywords : keyword string array
+ *
+ * @return errlHndl_t NULL on success
+ *
+ */
+
+errlHndl_t hdatformatAsciiKwd(const struct vpdData i_fetchVpd[],
+ const size_t &i_num, const size_t theSize[], char* &i_kwd,
+ const uint32_t &i_kwdSize, char* &o_fmtKwd, uint32_t &o_fmtkwdSize,
+ const HdatKeywordInfo i_Keywords[]) ;
+
+
+/**
+ * @brief Get the Full vpd of the target from eeprom
+ *
+ * @param[in] i_pTarget input target pointer
+ * @param[in/out]io_dataSize: VPD data size
+ * @param[out] o_data: VPD data
+ * @return errlHndl_t NULL on success
+ *
+ */
+errlHndl_t hdatGetFullEepromVpd ( TARGETING::Target * i_target,
+ size_t &io_dataSize,
+ char* &o_data);
+
+};// end namespace
+
+#endif // HDATUTILITY_H
diff --git a/src/usr/hdat/hdatvpd.C b/src/usr/hdat/hdatvpd.C
new file mode 100755
index 000000000..cc453f111
--- /dev/null
+++ b/src/usr/hdat/hdatvpd.C
@@ -0,0 +1,239 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatvpd.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+/**
+ * @file hdatvpd.C
+ *
+ * @brief This file contains the implementation of the HdatVpd class.
+ *
+ */
+
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include "hdatvpd.H"
+#include "hdatutil.H"
+#include <hdat/hdat_reasoncodes.H>
+#include <targeting/common/targetservice.H>
+#include <targeting/common/utilFilter.H>
+#include <targeting/common/predicates/predicatectm.H>
+#include <targeting/common/util.H>
+
+using namespace TARGETING;
+
+namespace HDAT
+{
+
+/*----------------------------------------------------------------------------*/
+/* Global variables */
+/*----------------------------------------------------------------------------*/
+extern trace_desc_t * g_hdatTraceDesc;
+
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+const uint16_t HDAT_VPD_VERSION = 0x0020;
+
+
+/** @brief See the prologue in hdatvpd.H
+ */
+HdatVpd::HdatVpd(errlHndl_t &o_errlHndl,
+ uint32_t i_resourceId,
+ TARGETING::Target * i_target,
+ const char *i_eyeCatcher,
+ uint32_t i_index,
+ vpdType i_vpdType,
+ struct vpdData i_fetchVpd[],
+ uint32_t i_num,
+ const HdatKeywordInfo i_pvpdKeywords[])
+: HdatHdif(o_errlHndl, i_eyeCatcher, HDAT_VPD_LAST,i_index,HDAT_NO_CHILD,
+ HDAT_VPD_VERSION),
+iv_kwdSize(0), iv_kwd(NULL)
+{
+ HDAT_ENTER();
+ o_errlHndl = NULL;
+ uint32_t l_slcaIdx = 0;
+ TARGETING::Target * l_target=i_target;
+ i_target->tryGetAttr<TARGETING::ATTR_SLCA_INDEX>(l_slcaIdx);
+
+ //overriding target for BP vpd
+ if ( FRU_SV == (i_resourceId >> 8 ) )
+ {
+ TARGETING::TargetHandleList l_targList;
+ PredicateCTM predNode(TARGETING::CLASS_ENC, TARGETING::TYPE_NODE);
+ PredicateHwas predFunctional;
+ predFunctional.functional(true);
+ PredicatePostfixExpr nodeCheckExpr;
+ nodeCheckExpr.push(&predNode).push(&predFunctional).And();
+
+ targetService().getAssociated(l_targList, i_target,
+ TargetService::CHILD, TargetService::IMMEDIATE,
+ &nodeCheckExpr);
+ l_target = l_targList[0];
+ }
+
+ //@TODO:RTC 149382(Method to get VPD collected status for Targets)
+ GARD_FunctionalState l_functional = GARD_Functional;
+ GARD_UsedState l_used = GARD_Used;
+
+ if (GARD_Functional == l_functional ||
+ GARD_PartialFunctional == l_functional)
+ {
+ iv_status.hdatFlags = HDAT_VPD_FRU_FUNCTIONAL;
+ }
+ if (GARD_Used == l_used)
+ {
+ iv_status.hdatFlags |= HDAT_VPD_REDUNDANT_FRU_USED;
+ }
+
+ iv_fru.hdatResourceId = i_resourceId;
+ size_t theSize[i_num];
+ //get the SLCA index and the keyword for the RID
+ o_errlHndl = hdatGetAsciiKwd(l_target,iv_kwdSize,iv_kwd,i_vpdType,
+ i_fetchVpd,i_num,theSize);
+
+ HDAT_DBG("hdatGetAsciiKwd returned kwd size =%d",iv_kwdSize);
+
+ if(strcmp(i_eyeCatcher,"IO KID")==0)
+ {
+ using namespace TARGETING;
+ // Get Target Service, and the system target.
+ TARGETING::TargetService& l_targetService = targetService();
+ TARGETING::Target* l_sysTarget = NULL;
+ (void) l_targetService.getTopLevelTarget(l_sysTarget);
+
+ assert(l_sysTarget != NULL);
+
+ //fetching lx data
+ uint64_t l_LXvalue = l_sysTarget->getAttr<ATTR_ASCII_VPD_LX_KEYWORD>();
+ char *temp_kwd = new char [iv_kwdSize];
+ uint32_t temp_kwdSize = iv_kwdSize;
+ memcpy(temp_kwd, iv_kwd,iv_kwdSize);
+ delete[] iv_kwd;
+ iv_kwdSize +=sizeof(uint64_t);
+ iv_kwd = new char [iv_kwdSize];
+ memcpy(iv_kwd,temp_kwd,temp_kwdSize);
+ memcpy((void *)(iv_kwd+temp_kwdSize),&l_LXvalue,sizeof(uint64_t));
+ theSize[i_num-1] = sizeof(uint64_t);
+ delete[] temp_kwd;
+ }
+ char *o_fmtKwd;
+ uint32_t o_fmtkwdSize;
+ o_errlHndl = hdatformatAsciiKwd(i_fetchVpd, i_num, theSize, iv_kwd,
+ iv_kwdSize, o_fmtKwd, o_fmtkwdSize, i_pvpdKeywords);
+ if( o_fmtKwd != NULL )
+ {
+ delete[] iv_kwd;
+ iv_kwd = new char [o_fmtkwdSize];
+ memcpy(iv_kwd,o_fmtKwd,o_fmtkwdSize);
+ iv_kwdSize = o_fmtkwdSize;
+ delete[] o_fmtKwd;
+ }
+
+ if (NULL == o_errlHndl)
+ {
+ iv_fru.hdatSlcaIdx = l_slcaIdx;
+ this->addData(HDAT_VPD_FRU_ID, sizeof(hdatFruId_t));
+ this->addData(HDAT_VPD_OP_STATUS, sizeof(hdatFruOpStatus_t));
+ //Padding the size
+ this->addData(HDAT_VPD_KWD, iv_kwdSize+1);
+ this->align();
+ }
+ HDAT_EXIT();
+}
+
+
+/** @brief See the prologue in hdatvpd.H
+ */
+HdatVpd::~HdatVpd()
+{
+ HDAT_ENTER();
+ if(iv_kwd!= NULL )
+ {
+ delete[] iv_kwd;
+ }
+ HDAT_EXIT();
+}
+
+
+uint8_t * HdatVpd::setVpd(uint8_t * io_virt_addr)
+{
+ uint32_t l_size = 0;
+ HDAT_DBG("virtual address=0x%016llX",
+ (uint64_t)io_virt_addr);
+
+
+ io_virt_addr = this->setHdif(io_virt_addr);
+
+
+ //write hdatFruId_t iv_fru
+ hdatFruId_t *l_hdatFruId = reinterpret_cast<hdatFruId_t *>(io_virt_addr);
+
+ HDAT_DBG("writing FRU ID from address=0x%016llX",
+ (uint64_t)l_hdatFruId);
+
+ l_hdatFruId->hdatSlcaIdx = this->iv_fru.hdatSlcaIdx;
+ l_hdatFruId->hdatResourceId = this->iv_fru.hdatResourceId;
+
+ l_hdatFruId++;
+
+
+ //write hdatFruOpStatus_t iv_status
+ hdatFruOpStatus_t *l_hdatFruOpStatus =
+ reinterpret_cast<hdatFruOpStatus_t *>(l_hdatFruId);
+
+ l_hdatFruOpStatus->hdatFlags = this->iv_status.hdatFlags;
+
+ l_hdatFruOpStatus++;
+
+ //write kwd
+ io_virt_addr = reinterpret_cast<uint8_t *>(l_hdatFruOpStatus);
+
+ if ( (NULL != this->iv_kwd) && (this->iv_kwdSize > 0))
+ {
+ HDAT_DBG("writing kwd from address 0x%016llX",
+ (uint64_t)io_virt_addr);
+ HDAT_DBG("kwd to be added %s,"
+ "size=0x%x sizeof(this->iv_kwd)=0x%x",
+ this->iv_kwd,this->iv_kwdSize,sizeof(this->iv_kwd));
+
+ memcpy(io_virt_addr,(this->iv_kwd),this->iv_kwdSize);
+
+ io_virt_addr += this->iv_kwdSize;
+
+ }
+
+ //write pad
+
+ io_virt_addr = this->setpadding( io_virt_addr,l_size );
+
+ HDAT_EXIT();
+ return io_virt_addr;
+
+}//end setVpd
+
+} //namespace HDAT
diff --git a/src/usr/hdat/hdatvpd.H b/src/usr/hdat/hdatvpd.H
new file mode 100755
index 000000000..5c12dda13
--- /dev/null
+++ b/src/usr/hdat/hdatvpd.H
@@ -0,0 +1,248 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hdat/hdatvpd.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 HDATVPD_H
+#define HDATVPD_H
+
+/**
+ * @file hdatvpd.H
+ *
+ * @brief This file contains the class definition for the VPD object
+ * with data obtained from the SVPD component. Besides typical VPD objects
+ * such as the Clock Card VPD object, this alos supports VPD objects which
+ * are part of a bigger object (such as the daughter card VPD object which
+ * is part of the HdatIoHubFru object).
+ *
+ */
+
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <stdint.h>
+#include <hdat/hdat.H>
+#include "hdathdif.H"
+#include <errl/errlentry.H>
+#include <vpd/vpd_if.H>
+//#include "hdatutil.H"
+
+namespace HDAT
+{
+
+typedef struct
+{
+ VPD::vpdKeyword keyword;
+ char keywordName[2+1];
+} HdatKeywordInfo;
+
+
+
+struct vpdData
+{
+ VPD::vpdRecord record;
+ VPD::vpdKeyword keyword;
+};
+
+enum vpdType
+{
+ PROC = 0x0,
+ DIMM,
+ BP,
+ CLOCK,
+ ENCLOSURE,
+ ANCHOR,
+ BP_EXT,
+};//add as required. this needs to be passed to hdatGetAsciiKwd
+//to choose the appropriate device address
+
+
+/*----------------------------------------------------------------------------*/
+/* Type definitions */
+/*----------------------------------------------------------------------------*/
+
+enum hdatVpdFruStatus
+{
+ HDAT_VPD_FRU_FUNCTIONAL = 0x01,
+ HDAT_VPD_REDUNDANT_FRU_USED = 0x02
+};
+
+/** @enum hdatDataPtrs
+ * Constants for the internal data pointers that are added to the base
+ * class
+ */
+enum hdatVpdDataPtrs
+{
+ HDAT_VPD_FRU_ID = 0,
+ HDAT_VPD_KWD = 1,
+ HDAT_VPD_OP_STATUS = 2,
+ HDAT_VPD_RESERVED2 = 3,
+ HDAT_VPD_LAST = 4
+};
+
+typedef enum {
+ GARD_Functional,
+ GARD_PartialFunctional,
+ GARD_NotFunctional
+}GARD_FunctionalState;
+
+typedef enum {
+ GARD_Used,
+ GARD_NotUsed
+}GARD_UsedState;
+
+struct hdatFruOpStatus_t
+{
+ uint8_t hdatFlags;
+ uint8_t hdatReserved1[3];
+} __attribute__ ((packed));
+
+
+/*----------------------------------------------------------------------------*/
+/* C++ class definition */
+/*----------------------------------------------------------------------------*/
+
+/** Begin Class Description
+ *
+ * @brief The HdatVpd class is used to construct objects that have the general
+ * format of VPD keyword data such as the CEC backplane VPD or L3 VPD,
+ * etc
+ *
+ * Description: This class defines a specialized object. It is not intended
+ * that anyone can create an object of this type. In particular,
+ * the object is built only in the hdatstep process when the step
+ * that builds hypervisor data structures is run.
+ *
+ * The real purpose of the object is to create the various VPD
+ * structures as defined by the PHYP Initialization architecture
+ * This data structure is eventually DMA'd to main memory. The
+ * class is not defined to be a general purpose interface for
+ * building this object by anyone other than the hdatstep process.
+ *
+ * Thread safety: An HdatVpd object is not thread safe. That is, a single
+ * object cannot be shared and used concurrently by
+ * multiple threads at the same time. An object can be used by
+ * multiple threads if the threads serialize access. And of
+ * course, each thread can use its own object with no concerns
+ * about what other threads are doing.
+ *
+ * Signal handler usage:
+ * This class is not intended to be used in a signal handler
+ * and nothing has been done to try and make it safe to use
+ * in a signal handler.
+ *
+ * End Class Description
+ */
+class HdatVpd : public HdatHdif
+{
+public:
+
+ /**
+ * @brief Construct an HdatVpd object.
+ *
+ * This is the constructor for the HdatVpd object
+ *
+ * If you are constructing this object on the heap by using new, then
+ * you must check the pointer returned from new to see if it is null.
+ * If it is null, new failed to allocate storage and the constructor
+ * was not called. If it is not null, then you must check o_errlHndl
+ * to see if the constructor ran successfully. If o_errlHndl indicates
+ * an error was reported by the constructor, new has already allocated
+ * heap storage and the object must be deleted in order to free the
+ * heap storage.
+ *
+ * @pre None
+ * @param o_errlHndl output error handle
+ * @param i_resourceId input resource id
+ * @param i_target input Target
+ * @param i_eyeCatcher input the eyecatcher string
+ * @param i_index input object instance
+ * @param i_vpdType input the vpd type to be added
+ * @param i_fetchVpd input the record-kwd structure like mVpd or pVpd etc
+ * @param i_num input the number of elements in the i_fetchVpd structure
+ * @param i_Keywords string array
+ *
+ * @post An HdatVpd object has been constructed. Heap storage has been
+ * allocated.
+ *
+ */
+ HdatVpd(errlHndl_t &o_errlHndl,
+ uint32_t i_resourceId,
+ TARGETING::Target * i_target,
+ const char *i_eyeCatcher,
+ uint32_t i_index,
+ vpdType i_vpdType,
+ struct vpdData i_fetchVpd[],
+ uint32_t i_num, const HdatKeywordInfo i_pvpdKeywords[]);
+
+
+
+ /**
+ * @brief HdatVpd object destructor
+ *
+ * This is the destructor for an HdatVpd object. Any heap storage
+ * allocated for the object is dallocated.
+ *
+ * @pre No preconditions exist
+ *
+ * @post The HdatVpd object has been destroyed and can no longer be used.
+ *
+ */
+ ~HdatVpd();
+
+ /*
+ * @brief write the vpd object to memory
+ *
+ * @pre the object must be constructed and the address to write at must
+ * be provided
+ *
+ * @param io_virt_addr - input parameter - inputs the address
+ * to start to write to mainstore
+ * @returns outputs thenext address
+
+ * @post data is written to memory and the next address is returned
+ *
+ */
+ uint8_t * setVpd(uint8_t * io_virt_addr);
+
+
+private:
+
+ /** Object Instance Data
+ *
+ * @li iv_kwdSize - size of the ASCII keyword
+ * @li iv_kwd - ptr to storage which holds the ASCII keyword
+ * @li iv_fru - FRU Id information
+ * @li iv_status - FRU operational status
+ */
+ uint32_t iv_kwdSize;
+ char *iv_kwd;
+ hdatFruId_t iv_fru;
+ hdatFruOpStatus_t iv_status;
+
+
+
+}; // end of HdatVpd class
+
+} //namespace HDAT
+#endif // HDATVPD_H
diff --git a/src/usr/hdat/makefile b/src/usr/hdat/makefile
new file mode 100644
index 000000000..456664f49
--- /dev/null
+++ b/src/usr/hdat/makefile
@@ -0,0 +1,51 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/hdat/makefile $
+#
+# 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
+
+ROOTPATH = ../../..
+MODULE = hdat
+
+EXTRAINCDIR +=
+
+OBJS += hdatutil.o
+OBJS += hdatpcia.o
+OBJS += hdatiplparms.o
+OBJS += hdathostslcadata.o
+OBJS += hdathdif.o
+OBJS += hdatvpd.o
+OBJS += hdatnaca.o
+OBJS += hdatiohub.o
+OBJS += hdatmsvpd.o
+OBJS += hdatmsarea.o
+OBJS += hdatram.o
+OBJS += hdatspsubsys.o
+OBJS += hdatpcrd.o
+OBJS += hdatbldda.o
+OBJS += hdatnodedata.o
+OBJS += hdathostservices.o
+OBJS += hdathbrt.o
+OBJS += hdatspiraS.o
+OBJS += hdatspiraH.o
+
+include ${ROOTPATH}/config.mk
OpenPOWER on IntegriCloud