diff options
-rw-r--r-- | src/include/arch/ppc.H | 1 | ||||
-rw-r--r-- | src/usr/runtime/common/hsvc_attribute_structs.H | 10 | ||||
-rw-r--r-- | src/usr/runtime/fakepayload.C | 83 | ||||
-rw-r--r-- | src/usr/runtime/fakepayload.H | 80 | ||||
-rw-r--r-- | src/usr/runtime/hdatservice.C | 39 | ||||
-rw-r--r-- | src/usr/runtime/hdatstructs.H | 45 | ||||
-rw-r--r-- | src/usr/runtime/makefile | 46 |
7 files changed, 226 insertions, 78 deletions
diff --git a/src/include/arch/ppc.H b/src/include/arch/ppc.H index e8e6701bb..ebb1f0f02 100644 --- a/src/include/arch/ppc.H +++ b/src/include/arch/ppc.H @@ -381,6 +381,7 @@ enum MAGIC_BREAK = 7007, // hard-code a breakpoint MAGIC_RANDOM = 7008, // generate random number MAGIC_MEMORYLEAK_FUNCTION = 7009, // A memory was function called. + MAGIC_FAKEPAYLOAD_ENTER = 7010, // Entered the fake payload. MAGIC_CONTINUOUS_TRACE = 7055, // extract mixed trace buffer }; diff --git a/src/usr/runtime/common/hsvc_attribute_structs.H b/src/usr/runtime/common/hsvc_attribute_structs.H index 4493b07d5..f291c58ef 100644 --- a/src/usr/runtime/common/hsvc_attribute_structs.H +++ b/src/usr/runtime/common/hsvc_attribute_structs.H @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/usr/runtime/attribute_structs.H $ */ +/* $Source: src/usr/runtime/common/hsvc_attribute_structs.H $ */ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012 */ +/* COPYRIGHT International Business Machines Corp. 2012,2013 */ /* */ /* p1 */ /* */ @@ -20,12 +20,14 @@ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ +#ifndef __RUNTIME_HSVC_ATTRIBUTE_STRUCTS_H +#define __RUNTIME_HSVC_ATTRIBUTE_STRUCTS_H + /** * @file attribute_structs.H * * @brief Shared structures with the HostServices code */ - struct hsvc_proc_header_t { uint64_t procid; //=NNNCCC uint64_t offset; //offset to attribute header relative to start of node_data @@ -76,3 +78,5 @@ struct hsvc_node_data_t static const uint64_t HSVC_HUID = 0xFF000001FFFFFFFF; static const uint64_t HSVC_PHYS_PATH = 0xFF000002FFFFFFFF; static const uint64_t HSVC_ECMD_STRING = 0xFF000003FFFFFFFF; + +#endif diff --git a/src/usr/runtime/fakepayload.C b/src/usr/runtime/fakepayload.C new file mode 100644 index 000000000..0600bfa68 --- /dev/null +++ b/src/usr/runtime/fakepayload.C @@ -0,0 +1,83 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/runtime/fakepayload.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include "fakepayload.H" +#include <string.h> +#include <sys/mm.h> +#include <sys/mmio.h> +#include <util/align.H> +#include <targeting/common/commontargeting.H> + + +namespace RUNTIME +{ + +void FakePayload::payload() +{ + MAGIC_INSTRUCTION(MAGIC_FAKEPAYLOAD_ENTER); // instr 1 + + nap(); // instr 2 + // Should never wake from nap, but just in case... + loop: + goto loop; // instr 3 +} + +const size_t FakePayload::size = 3 * sizeof(uint32_t); // 3 instructions. +const size_t FakePayload::safeClearArea = 1 * MEGABYTE; + +void FakePayload::load() +{ + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + + // Find payload base address and offset. + uint64_t base = sys->getAttr<TARGETING::ATTR_PAYLOAD_BASE>() * MEGABYTE; + uint64_t entry = sys->getAttr<TARGETING::ATTR_PAYLOAD_ENTRY>(); + + // Skip loading the payload if the address is 0. + if (0 == base) + { + return; + } + + // Verify payload size. + assert(ALIGN_PAGE(entry + size) < safeClearArea); + + // Map in the payload area. + void* memArea = mmio_dev_map(reinterpret_cast<void*>(base), THIRTYTWO_GB); + + // Clear out anything the FSP might have left around (for security). + memset(memArea, '\0', safeClearArea); + + // Copy over the fake payload code. + uint8_t* dest = reinterpret_cast<uint8_t*>(memArea) + entry; + memcpy(dest, *(reinterpret_cast<void**>(&payload)), size); + + // Invalidate the icache since this is instructions. + mm_icache_invalidate(memArea, ALIGN_8(safeClearArea) / sizeof(uint64_t)); + + // Unmap the payload area. + mmio_dev_unmap(memArea); + +} + +} diff --git a/src/usr/runtime/fakepayload.H b/src/usr/runtime/fakepayload.H new file mode 100644 index 000000000..81cdce0a6 --- /dev/null +++ b/src/usr/runtime/fakepayload.H @@ -0,0 +1,80 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/runtime/fakepayload.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __RUNTIME_FAKEPAYLOAD_H +#define __RUNTIME_FAKEPAYLOAD_H + +/** @file fakepayload.H + * @brief Interfaces for loading a 'fake' payload when a payload is not + * present. + * + * The purpose of the fake payload is to be able to exercise the Hostboot + * shutdown path, even when there is not a real payload. + * + * This payload will simply nap all of the processors. + */ +#include <stdint.h> +#include <arch/ppc.H> + +namespace RUNTIME +{ + /** @class FakePayload + * + * @brief Handles loading of the fake payload. + * + * Places the payload into the area of memory determined by the + * PAYLOAD_BASE / PAYLOAD_ENTRY attributes. + * + * @note This class does not perform verification that the addresses + * in the attributes are actually reasonable values. It is assumed + * that attribute verification (ex. for SecureBoot) will be done + * elsewhere in a central place for all payloads. + */ + class FakePayload + { + public: + /** Load payload into memory. */ + static void load(); + private: + /** The fake payload itself. */ + static void payload() + __attribute__((no_instrument_function)); + + /** Size of the payload (in bytes). */ + static const size_t size; + + /** @brief Size of memory to securely erase before loading + * the payload. + * + * For SecureBoot we cannot trust anything the FSP has left in + * memory. While we're loading a payload function into memory, + * the FSP had access to memory and could have loaded exception + * handlers. We need to clear out at least this much space in + * order to ensure that none of the interrupt handlers could be + * residing in memory. + */ + static const size_t safeClearArea; + }; +} + + +#endif diff --git a/src/usr/runtime/hdatservice.C b/src/usr/runtime/hdatservice.C index a6eceed51..4ad6325f6 100644 --- a/src/usr/runtime/hdatservice.C +++ b/src/usr/runtime/hdatservice.C @@ -30,6 +30,7 @@ #include <vmmconst.h> #include <util/align.H> #include "hdatstructs.H" +#include "fakepayload.H" extern trace_desc_t* g_trac_runtime; @@ -58,7 +59,7 @@ const hdatHeaderExp_t IPLPARMS_SYSTEM_HEADER = { }; //big enough to hold all of PHYP -const uint64_t HDAT_MEM_SIZE = 128*MEGABYTE; +const uint64_t HDAT_MEM_SIZE = 128*MEGABYTE; /******************** Utility Functions @@ -138,7 +139,7 @@ errlHndl_t check_header( uint64_t i_base, // Check the ID, Version and Name if( (i_header->hdatStructId != i_exp.id) - && (i_header->hdatVersion != i_exp.version) + && (i_header->hdatVersion != i_exp.version) && !memcmp(i_header->hdatStructName,i_exp.name,6) ) { TRACFCOMP( g_trac_runtime, ERR_MRK "RUNTIME::check_header> HDAT Header data not as expected (id:version:name). Act=%.4X:%.4X:%s, Exp=%.4X:%.4X :%s", i_header->hdatStructId, i_header->hdatVersion, i_header->hdatStructName, i_exp.id, i_exp.version, i_exp.name ); @@ -311,7 +312,7 @@ errlHndl_t RUNTIME::load_host_data( void ) // get the current payload kind TARGETING::ATTR_PAYLOAD_KIND_type payload_kind = sys->getAttr<TARGETING::ATTR_PAYLOAD_KIND>(); - + // read the mfg flags TARGETING::ATTR_MNFG_FLAGS_type mnfg_flags = sys->getAttr<TARGETING::ATTR_MNFG_FLAGS>(); @@ -365,36 +366,12 @@ errlHndl_t RUNTIME::load_host_data( void ) hdat_size ); errhdl->collectTrace("RUNTIME",1024); break; - } + } } else if( TARGETING::PAYLOAD_KIND_NONE == payload_kind ) { // Standalone Test Image with no payload - - // Ensure that there really is no payload being loaded - TARGETING::ATTR_PAYLOAD_BASE_type payload_base - = sys->getAttr<TARGETING::ATTR_PAYLOAD_BASE>(); - if( payload_base != 0 ) - { - TRACFCOMP( g_trac_runtime, "load_host_data> Non-zero PAYLOAD_BASE (0x%X) for PAYLOAD_KIND==NONE", payload_base ); - /*@ - * @errortype - * @moduleid RUNTIME::MOD_HDATSERVICE_LOAD_HOST_DATA - * @reasoncode RUNTIME::RC_WRONG_PAYLOAD_ATTRS - * @userdata1 PAYLOAD_BASE - * @userdata2 PAYLOAD_KIND - * @devdesc Nonzero PAYLOAD_BASE for standalone - * PAYLOAD_KIND - */ - errhdl = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - RUNTIME::MOD_HDATSERVICE_LOAD_HOST_DATA, - RUNTIME::RC_WRONG_PAYLOAD_ATTRS, - payload_base, - payload_kind ); - errhdl->collectTrace("RUNTIME",1024); - break; - } + FakePayload::load(); // Map in some arbitrary memory for the HostServices code to use TRACFCOMP( g_trac_runtime, "load_host_data> STANDALONE: Mapping in 0x%X-0x%X (%d MB)", HSVC_TEST_MEMORY_ADDR, HSVC_TEST_MEMORY_ADDR+HSVC_TEST_MEMORY_SIZE, HSVC_TEST_MEMORY_SIZE ); @@ -450,8 +427,8 @@ errlHndl_t RUNTIME::load_host_data( void ) DUMP_TEST_TABLE_SIZE); errhdl->collectTrace("RUNTIME",1024); break; - } - + } + } else { diff --git a/src/usr/runtime/hdatstructs.H b/src/usr/runtime/hdatstructs.H index d96a51883..e1e9be925 100644 --- a/src/usr/runtime/hdatstructs.H +++ b/src/usr/runtime/hdatstructs.H @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012 */ +/* COPYRIGHT International Business Machines Corp. 2012,2013 */ /* */ /* p1 */ /* */ @@ -20,13 +20,16 @@ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ +#ifndef __RUNTIME_HDATSTRUCTS_H +#define __RUNTIME_HDATSTRUCTS_H + #include <stdint.h> #include <vmmconst.h> #include <string.h> // Copied from FipS:src/hdat/fsp/hdatnaca.H // offset in mainstore where NACA starts -const uint64_t HDAT_NACA_OFFSET = 0x00004000; +const uint64_t HDAT_NACA_OFFSET = 0x00004000; /* NOTE: Most of these structures were copied and adapted from the HDAT @@ -39,16 +42,16 @@ const uint64_t HDAT_NACA_OFFSET = 0x00004000; * The NACA is a data structure used primarily by the host operating * system. The NACA is prebuilt as part of the primary host LID. FipS * uses several fields in the NACA to determine where the LID table - * and the Service Processor Interace Root Array reside. + * and the Service Processor Interace Root Array reside. * Fields which are not used by FipS are just defined as reserved so * that we don't have to chase uninteresting changes the host OS may * make to things FipS does not care about. */ struct hdatNaca_t { - uint8_t reserved1[48]; // 0x0000 Reserved space - uint64_t spira; // 0x0030 SPIRA offset - uint8_t reserved2[104]; // 0x0038 Reserved space + uint8_t reserved1[48]; // 0x0000 Reserved space + uint64_t spira; // 0x0030 SPIRA offset + uint8_t reserved2[104]; // 0x0038 Reserved space uint32_t spiraSize; // 0x00A0 Actual SPIRA size in bytes uint8_t nacaReserved4[28]; // 0x00A4 reserved space uint64_t nacaHypLoadMap; // 0x00C0 Hyp resident module load map @@ -93,15 +96,15 @@ enum hdatSpiraDataAreas 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 - HDAT_MS_DUMP_DST_TBL = 18, // mainstore dump destination table + HDAT_MS_DUMP_SRC_TBL = 17, // mainstore dump source table + HDAT_MS_DUMP_DST_TBL = 18, // mainstore dump destination table 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 - HDAT_PCIA = 21, // PCIA (Core information area) - HDAT_PCRD = 22, // PCRD (Chip related data area) + HDAT_HEAP = 20, // Phyp allocated storage location + HDAT_PCIA = 21, // PCIA (Core information area) + HDAT_PCRD = 22, // PCRD (Chip related data area) HSVC_DATA = 23, // Host Services Data - HDAT_SPIRA_DA_LAST = 24 + HDAT_SPIRA_DA_LAST = 24 }; @@ -123,11 +126,11 @@ struct hdat5Tuple_t // Copied from FipS:src/hdat/fsp/hdat.H /** @brief Type definition for the common hypervisor Data Interface - * Format (HDIF) header. + * Format (HDIF) header. */ struct hdatHDIF_t { - uint16_t hdatStructId; // 0x0000 Structure format ID + uint16_t hdatStructId; // 0x0000 Structure format ID char hdatStructName[6]; // 0x0002 Structure eye catcher uint16_t hdatInstance; // 0x0008 Instance number uint16_t hdatVersion; // 0x000A Structure version @@ -145,32 +148,32 @@ struct hdatHDIF_t */ struct hdatHDIFChildHdr_t { - uint32_t hdatOffset; // 0x0000 Offset from top of structure + uint32_t hdatOffset; // 0x0000 Offset from top of structure uint32_t hdatSize; // 0x0004 Child data structure size in bytes uint32_t hdatCnt; // 0x0008 Count of child data structures } __attribute__ ((packed)); // Copied from FipS:src/hdat/fsp/hdat.H -/** @brief Type definition for the "pointer" header to the internal data. +/** @brief Type definition for the "pointer" header to the internal data. */ struct hdatHDIFDataHdr_t { - uint32_t hdatOffset; // 0x0000 Offset from top of structure + uint32_t hdatOffset; // 0x0000 Offset from top of structure uint32_t hdatSize; // 0x0004 Data structure size in bytes } __attribute__ ((packed)); // Copied from FipS:src/hdat/fsp/hdat.H -/** @brief Type definition for the data array header. Used when internal - * data is an array. +/** @brief Type definition for the data array header. Used when internal + * data is an array. */ struct hdatHDIFDataArray_t { uint32_t hdatOffset; // 0x0000 Offset to array from this structure uint32_t hdatArrayCnt; // 0x0004 Number of array entries uint32_t hdatAllocSize; // 0x0008 Size of allocated space for array entry - uint32_t hdatActSize; // 0x000C Actual size of an array entry + uint32_t hdatActSize; // 0x000C Actual size of an array entry } __attribute__ ((packed)); @@ -241,4 +244,4 @@ struct hdatHeaderExp_t return retval; }; }; - +#endif diff --git a/src/usr/runtime/makefile b/src/usr/runtime/makefile index e5ef5bf81..8482289a0 100644 --- a/src/usr/runtime/makefile +++ b/src/usr/runtime/makefile @@ -1,25 +1,25 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/usr/runtime/makefile $ -# -# IBM CONFIDENTIAL -# -# COPYRIGHT International Business Machines Corp. 2012 -# -# p1 -# -# Object Code Only (OCO) source materials -# Licensed Internal Code Source Materials -# IBM HostBoot Licensed Internal Code -# -# The source code for this program is not published or otherwise -# divested of its trade secrets, irrespective of what has been -# deposited with the U.S. Copyright Office. -# -# Origin: 30 -# -# IBM_PROLOG_END_TAG +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/runtime/makefile $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2012,2013 +# +# p1 +# +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code +# +# The source code for this program is not published or otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END_TAG # # The runtime module provides code to handle manipulating data @@ -30,7 +30,7 @@ ROOTPATH = ../../.. MODULE = runtime -OBJS = populate_attributes.o hdatservice.o +OBJS = populate_attributes.o hdatservice.o fakepayload.o SUBDIRS = test.d |