summaryrefslogtreecommitdiffstats
path: root/src/usr/hdat/hdatspiraH.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/hdat/hdatspiraH.C')
-rwxr-xr-xsrc/usr/hdat/hdatspiraH.C377
1 files changed, 377 insertions, 0 deletions
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
OpenPOWER on IntegriCloud