diff options
Diffstat (limited to 'src')
31 files changed, 1195 insertions, 1055 deletions
diff --git a/src/build/buildpnor/memd_creation.pl b/src/build/buildpnor/memd_creation.pl index 4144a0ddf..c4f551b03 100755 --- a/src/build/buildpnor/memd_creation.pl +++ b/src/build/buildpnor/memd_creation.pl @@ -29,7 +29,7 @@ use strict; use File::Basename; ### CONSTANTS ### -use constant ROUNDING_DIVISOR => 1000; +use constant ROUNDING_DIVISOR => 1000; # 1K (not 1KB) use constant HEADER_INPUT_LOCATION => 12; print "Creating MEMD binary...\n"; @@ -44,6 +44,7 @@ print "Creating MEMD binary...\n"; my $memd_dir = ""; my $memd_output = ""; my @memd_files = ""; +my $record_name = "01.0"; #legacy support my $help = 0; my $man = 0; @@ -51,6 +52,7 @@ GetOptions( "memd_dir=s" => \$memd_dir, "memd_output=s" => \$memd_output, "memd_files=s" => \@memd_files, + "record=s" => \$record_name, "help" => \$help, "man" => \$man) || pod2usage(-verbose=>0); @@ -92,8 +94,8 @@ my $number_of_files = scalar(@memd_files); # Generate header - add to file my $header = "OKOK"; # shows that the memd partition is valid $header .= "01.0"; # current metadata header version -$header .= "01.0"; # current memd version -$header .= "0000"; # expected size of each memd blob (in KB's) placeholder +$header .= $record_name; # vpd record +$header .= "0000"; # expected size of each memd blob (in 1000's) placeholder $header .= "00"; # number of memd instances placeholder $header .= "00000000"; # padding for the future $header .= "000000"; # rounding up to 16 bytes diff --git a/src/build/mkrules/hbfw/img/makefile b/src/build/mkrules/hbfw/img/makefile index cf2aab233..5cf263bc2 100755 --- a/src/build/mkrules/hbfw/img/makefile +++ b/src/build/mkrules/hbfw/img/makefile @@ -202,9 +202,9 @@ BUILD_TYPE_PARAMS = --build-type fspbuild .if (${FAKEPNOR} == "") # Parameters passed into GEN_PNOR_IMAGE_SCRIPT. .if (${DEFAULT_PNOR} == 1) - GEN_DEFAULT_BIN_FILES = HBBL=${HBBL_IMG},HBB=${HBB_IMG},HBI=${HBI_IMG},HBRT=${HBRT_IMG},TEST=EMPTY,TESTRO=EMPTY,TESTLOAD=EMPTY,HBEL=EMPTY,GUARD=EMPTY,GLOBAL=EMPTY,PAYLOAD=EMPTY,CVPD=EMPTY,MVPD=EMPTY,DJVPD=EMPTY,RINGOVD=EMPTY,SBKT=EMPTY,FIRDATA=EMPTY,MEMD=EMPTY + GEN_DEFAULT_BIN_FILES = HBBL=${HBBL_IMG},HBB=${HBB_IMG},HBI=${HBI_IMG},HBRT=${HBRT_IMG},TEST=EMPTY,TESTRO=EMPTY,TESTLOAD=EMPTY,HBEL=EMPTY,GUARD=EMPTY,GLOBAL=EMPTY,PAYLOAD=EMPTY,CVPD=EMPTY,MVPD=EMPTY,DJVPD=EMPTY,RINGOVD=EMPTY,SBKT=EMPTY,FIRDATA=EMPTY,MEMD=${${ZZ_MEMD_IMG}:P} .else - GEN_DEFAULT_BIN_FILES = HBBL=${HBBL_IMG},HBB=${HBB_IMG},HBI=${HBI_IMG},HBRT=${HBRT_IMG},HBEL=EMPTY,GUARD=EMPTY,GLOBAL=EMPTY,CVPD=EMPTY,MVPD=EMPTY,DJVPD=EMPTY,RINGOVD=EMPTY,SBKT=EMPTY,MEMD=EMPTY + GEN_DEFAULT_BIN_FILES = HBBL=${HBBL_IMG},HBB=${HBB_IMG},HBI=${HBI_IMG},HBRT=${HBRT_IMG},HBEL=EMPTY,GUARD=EMPTY,GLOBAL=EMPTY,CVPD=EMPTY,MVPD=EMPTY,DJVPD=EMPTY,RINGOVD=EMPTY,SBKT=EMPTY,MEMD=${${ZZ_MEMD_IMG}:P} .endif DEFAULT_PARAMS = --build-all --emit-eccless ${TARGET_TEST:b--test} ${HB_STANDALONE:b--hb-standalone} \ ${CONFIG_SECUREBOOT:b--secureboot} --systemBinFiles ${GEN_DEFAULT_BIN_FILES} \ @@ -442,15 +442,15 @@ gen_system_specific_images: build_sbe_partitions .PMAKE @${MAKE:T:R} gen_system_specific_images_bypass_cache .if (${DEFAULT_PNOR} == 1) - HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},TEST=${TEST_FINAL_IMG},TESTRO=${TESTRO_FINAL_IMG},TESTLOAD=${TESTLOAD_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},GLOBAL=${GLOBAL_FINAL_IMG},PAYLOAD=${PAYLOAD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG},FIRDATA=${FIRDATA_FINAL_IMG},MEMD=${MEMD_FINAL_IMG} - NIMBUS_SECT = HBD=${NIMBUS_HBD_FINAL_IMG},SBE=${NIMBUS_SBE_FINAL_IMG},HCODE=${NIMBUS_HCODE_FINAL_IMG},OCC=${NIMBUS_OCC_FINAL_IMG},WOFDATA=${ZZ_WOFDATA_FINAL_IMG},CENHWIMG=${NIMBUS_CENHWIMG_FINAL_IMG} - CUMULUS_SECT = HBD=${CUMULUS_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG} - CUMULUS_CDIMM_SECT = HBD=${CUMULUS_CDIMM_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG} + HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},TEST=${TEST_FINAL_IMG},TESTRO=${TESTRO_FINAL_IMG},TESTLOAD=${TESTLOAD_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},GLOBAL=${GLOBAL_FINAL_IMG},PAYLOAD=${PAYLOAD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG},FIRDATA=${FIRDATA_FINAL_IMG} + NIMBUS_SECT = HBD=${NIMBUS_HBD_FINAL_IMG},SBE=${NIMBUS_SBE_FINAL_IMG},HCODE=${NIMBUS_HCODE_FINAL_IMG},OCC=${NIMBUS_OCC_FINAL_IMG},WOFDATA=${ZZ_WOFDATA_FINAL_IMG},CENHWIMG=${NIMBUS_CENHWIMG_FINAL_IMG},MEMD=${ZZ_MEMD_FINAL_IMG} + CUMULUS_SECT = HBD=${CUMULUS_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${MEMD_FINAL_IMG} + CUMULUS_CDIMM_SECT = HBD=${CUMULUS_CDIMM_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${MEMD_FINAL_IMG} .else - HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},GLOBAL=${GLOBAL_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG},MEMD=${MEMD_FINAL_IMG} - NIMBUS_SECT = HBD=${NIMBUS_HBD_FINAL_IMG},SBE=${NIMBUS_SBE_FINAL_IMG},HCODE=${NIMBUS_HCODE_FINAL_IMG},OCC=${NIMBUS_OCC_FINAL_IMG},WOFDATA=${ZZ_WOFDATA_FINAL_IMG},CENHWIMG=${NIMBUS_CENHWIMG_FINAL_IMG} - CUMULUS_SECT = HBD=${CUMULUS_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG} - CUMULUS_CDIMM_SECT = HBD=${CUMULUS_CDIMM_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG} + HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},GLOBAL=${GLOBAL_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG} + NIMBUS_SECT = HBD=${NIMBUS_HBD_FINAL_IMG},SBE=${NIMBUS_SBE_FINAL_IMG},HCODE=${NIMBUS_HCODE_FINAL_IMG},OCC=${NIMBUS_OCC_FINAL_IMG},WOFDATA=${ZZ_WOFDATA_FINAL_IMG},CENHWIMG=${NIMBUS_CENHWIMG_FINAL_IMG},MEMD=${ZZ_MEMD_FINAL_IMG} + CUMULUS_SECT = HBD=${CUMULUS_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${MEMD_FINAL_IMG} + CUMULUS_CDIMM_SECT = HBD=${CUMULUS_CDIMM_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${MEMD_FINAL_IMG} .endif PNOR_IMG_INFO = \ nimbus.pnor:${PNOR_LAYOUT}:${NIMBUS_SECT},${HOSTBOOT_DEFAULT_SECTIONS} \ diff --git a/src/include/usr/devicefw/userif.H b/src/include/usr/devicefw/userif.H index 4df37c8a8..68f923f95 100644 --- a/src/include/usr/devicefw/userif.H +++ b/src/include/usr/devicefw/userif.H @@ -67,7 +67,7 @@ namespace DeviceFW SIO, AHB_SIO, DVPD, // Direct access memory VPD - MEMD_VPD, + DEPRECATED_MEMD_VPD, NODECOMM, LAST_ACCESS_TYPE, @@ -256,30 +256,6 @@ namespace DeviceFW static_cast<uint64_t>(( i_location )) /** - * Construct the device addressing parameters for the DVPD (Direct access - * memory VPD) device ops. - * @param[in] i_record - The enumeration of the DVPD record to access. - * @param[in] i_keyword - The enumeration of the DVPD keyword, located - * within the i_record Record to access. - */ - #define DEVICE_MEMD_VPD_ADDRESS( i_record, i_keyword )\ - DEVICE_MEMD_VPD_FORCE_ADDRESS( i_record, i_keyword, VPD::PNOR ) - - /** - * Construct the device addressing parameters for the DVPD device ops. - * @param[in] i_record - The enumeration of the DVPD record to access. - * @param[in] i_keyword - The enumeration of the DVPD keyword, located - * within the i_record Record to access. - * @param[in] i_location - The location of the data (PNOR/SEEPROM) - see vpd_if.H - */ - #define DEVICE_MEMD_VPD_FORCE_ADDRESS( i_record, i_keyword, i_location )\ - DeviceFW::MEMD_VPD, static_cast<uint64_t>(( i_record )),\ - static_cast<uint64_t>(( i_keyword )),\ - static_cast<uint64_t>(( i_location )) - - - /** * Construct the device addressing parameters for the SCAN device ops. * @param[in] i_ring - The ring address to scan * @param[in] i_ringlen - The length of the ring to scan in bits diff --git a/src/include/usr/fapi2/plat_vpd_access.H b/src/include/usr/fapi2/plat_vpd_access.H index f28317df9..0bde2f363 100644 --- a/src/include/usr/fapi2/plat_vpd_access.H +++ b/src/include/usr/fapi2/plat_vpd_access.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -31,7 +31,6 @@ #define _FAPI2_PLAT_VPDACCESS_H_ #include <fapi2_vpd_access.H> -#include <vpd/memd_vpdenums.H> namespace fapi2 { @@ -52,19 +51,5 @@ fapi2::ReturnCode platGetVPD( VPDInfo<fapi2::TARGET_TYPE_MCS>& io_vpd_info, uint8_t* o_blob); -/** - * @brief Search through the PNOR::MEMD section to find the copy with - * a matching VM keyword compared to the EEPROM's VM. - * - * @param[in] i_eepromVM - The EEPROM's copy of the VM keyword - * @param[in] i_header - The header from PNOR::MEMD - * @param[in] i_target - A valid fapi2 MCS target - * @param[in] i_vm_size - Size of the VM keyword - * - * @return boolean - true if a matching MEMD was found, false if not - */ -bool find_memd_in_pnor(uint8_t* i_eepromVM, MemdHeader_t i_header, - TARGETING::Target * i_target, size_t i_vm_size); - }; #endif // _FAPI2_PLAT_VPDACCESS_H_ diff --git a/src/include/usr/runtime/runtime_reasoncodes.H b/src/include/usr/runtime/runtime_reasoncodes.H index 79ebe37a8..6b77d621a 100644 --- a/src/include/usr/runtime/runtime_reasoncodes.H +++ b/src/include/usr/runtime/runtime_reasoncodes.H @@ -138,6 +138,7 @@ namespace RUNTIME RC_RT_RES_TRACE_BUF_INVALID = RUNTIME_COMP_ID | 0x41, RC_SP_ATTN_AREA_OVERFLOW = RUNTIME_COMP_ID | 0x42, RC_SP_ATTN_AREA1_SIZE_OVERFLOW = RUNTIME_COMP_ID | 0x43, + RC_UNKNOWN_LABEL = RUNTIME_COMP_ID | 0x44, }; enum UserDetailsTypes diff --git a/src/include/usr/util/utilrsvdmem.H b/src/include/usr/util/utilrsvdmem.H index ed4d0e4f5..d93819b7b 100644 --- a/src/include/usr/util/utilrsvdmem.H +++ b/src/include/usr/util/utilrsvdmem.H @@ -35,23 +35,33 @@ namespace Util typedef uint64_t hbrt_mem_label_t; // Ascii label "VPD " in hex - constexpr hbrt_mem_label_t HBRT_MEM_LABEL_VPD = 0x5650442020202020; + constexpr hbrt_mem_label_t HBRT_MEM_LABEL_VPD = 0x5650442020202020; // Ascii label "ATTR " in hex - constexpr hbrt_mem_label_t HBRT_MEM_LABEL_ATTR = 0x4154545220202020; + constexpr hbrt_mem_label_t HBRT_MEM_LABEL_ATTR = 0x4154545220202020; // Ascii label "ATTROVER" in hex - constexpr hbrt_mem_label_t HBRT_MEM_LABEL_ATTROVER = 0x415454524F564552; + constexpr hbrt_mem_label_t HBRT_MEM_LABEL_ATTROVER = 0x415454524F564552; // Ascii label "PADDING " in hex - constexpr hbrt_mem_label_t HBRT_MEM_LABEL_PADDING = 0x50414444494E4720; + constexpr hbrt_mem_label_t HBRT_MEM_LABEL_PADDING = 0x50414444494E4720; // Ascii label "HYPCOMM " in hex - constexpr hbrt_mem_label_t HBRT_MEM_LABEL_HYPCOMM = 0x485950434f4d4d20; + constexpr hbrt_mem_label_t HBRT_MEM_LABEL_HYPCOMM = 0x485950434f4d4d20; // Ascii label "TRACEBUF" in hex constexpr hbrt_mem_label_t HBRT_MEM_LABEL_TRACEBUF = 0x5452414345425546; + // Note : may be several sections of the format 'VPD_xxxx' if support + // other overrides in the future + // Ascii label "VPD_"<blank> in hex + constexpr hbrt_mem_label_t HBRT_MEM_LABEL_VPD_XXXX = 0x5650445F00000000; + // Mask off specific VPD label + constexpr hbrt_mem_label_t HBRT_MEM_LABEL_VPD_MASK = 0x00000000FFFFFFFF; + // Ascii label "VPD_MEMD in hex + constexpr hbrt_mem_label_t HBRT_MEM_LABEL_VPD_MEMD = 0x5650445F4D454D44; + + /** @brief A 32 byte table of contents entry */ struct hbrtTableOfContentsEntry_t { diff --git a/src/include/usr/vpd/memd_vpdenums.H b/src/include/usr/vpd/memd_vpdenums.H deleted file mode 100644 index ecd20ef04..000000000 --- a/src/include/usr/vpd/memd_vpdenums.H +++ /dev/null @@ -1,201 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/usr/vpd/memd_vpdenums.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ -/* [+] 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 __MEMD_VPDENUMS_H -#define __MEMD_VPDENUMS_H - -#include <vpd/ipvpdenums.H> - -/** - * @brief Define the set of information included at the beginning of the - * MEMD PNOR section - */ -struct MemdHeader_t -{ - uint32_t eyecatch; /* Eyecatch to determine validity. "OKOK" */ - uint32_t header_version; /* What version of the header this is in */ - uint32_t memd_version; /* What version of the MEMD this includes */ - uint32_t expected_size_kb; /* Size in kilobytes of each MEMD instance */ - uint16_t expected_num; /* Number of MEMD instances in this section */ - uint8_t padding[14]; /* Padding for future changes */ -}__attribute__((packed)); - -enum MEMD_valid_constants -{ - MEMD_VALID_HEADER = 0x4f4b4f4b, // "OKOK" - MEMD_VALID_HEADER_VERSION = 0x30312e30, // "01.0"; - MEMD_VALID_MEMD_VERSION = 0x30312e30, //"01.0"; -}; - -namespace MEMD_VPD -{ - - /** - * @brief Enumeration for the MEMD_VPD Records that contain - * the keyword enumerations below. - */ - enum MEMD_VPDRecord - { - MEMD_VPD_FIRST_RECORD = 0x00, - VINI = MEMD_VPD_FIRST_RECORD, - MEMD = 0x01, - - // Last Record - MEMD_VPD_LAST_RECORD, - MEMD_VPD_TEST_RECORD, // Test purposes ONLY! - - //Start common IPVPD enums - MEMD_VPD_INVALID_RECORD = IPVPD::INVALID_RECORD, - }; - - /** - * @brief Enumerations for MEMD_VPD keywords that can be - * accessed in the MEMD_VPD. - */ - enum MEMD_VPDKeyword - { - MEMD_VPD_FIRST_KEYWORD = 0x00, - B3 = MEMD_VPD_FIRST_KEYWORD, - B4 = 0x01, - B7 = 0x02, - CC = 0x03, - CE = 0x04, - CT = 0x05, - DR = 0x06, - FC = 0x07, - FN = 0x08, - HE = 0x09, - HW = 0x0a, - I2 = 0x0b, - IN = 0x0c, - J0 = 0x0d, - J1 = 0x0e, - J2 = 0x0f, - J3 = 0x10, - J4 = 0x11, - J5 = 0x12, - J6 = 0x13, - J7 = 0x14, - J8 = 0x15, - J9 = 0x16, - JA = 0x17, - JB = 0x18, - JC = 0x19, - JD = 0x1a, - JE = 0x1b, - JF = 0x1c, - JG = 0x1d, - JH = 0x1e, - JI = 0x1f, - JJ = 0x20, - JK = 0x21, - JL = 0x22, - JM = 0x23, - JN = 0x24, - JO = 0x25, - JP = 0x26, - JQ = 0x27, - JR = 0x28, - JS = 0x29, - JT = 0x2a, - JU = 0x2b, - JV = 0x2c, - JW = 0x2d, - JX = 0x2e, - JY = 0x2f, - JZ = 0x30, - LX = 0x31, - MR = 0x32, - MT = 0x33, - PF = 0x34, - PN = 0x35, - PR = 0x36, - RB = 0x37, - RG = 0x38, - RT = 0x39, - SE = 0x3a, - SN = 0x3b, - SO = 0x3c, - TM = 0x3d, - VM = 0x3e, - VZ = 0x3f, - X0 = 0x40, - X1 = 0x41, - X2 = 0x42, - X3 = 0x43, - X4 = 0x44, - X5 = 0x45, - X6 = 0x46, - X7 = 0x47, - X8 = 0x48, - X9 = 0x49, - XA = 0x4a, - XB = 0x4b, - XC = 0x4c, - XD = 0x4d, - XE = 0x4e, - XF = 0x4f, - XG = 0x50, - XH = 0x51, - XI = 0x52, - XJ = 0x53, - XK = 0x54, - XL = 0x55, - XM = 0x56, - XN = 0x57, - XO = 0x58, - XP = 0x59, - XQ = 0x5a, - XR = 0x5b, - XS = 0x5c, - XT = 0x5d, - XU = 0x5e, - XV = 0x5f, - XW = 0x60, - XX = 0x61, - XY = 0x62, - XZ = 0x63, - Q0 = 0x64, - Q1 = 0x65, - Q2 = 0x66, - Q3 = 0x67, - Q4 = 0x68, - Q5 = 0x69, - Q6 = 0x6A, - Q7 = 0x6B, - Q8 = 0x6C, - CK = 0X6D, - - // Last Keyword - MEMD_VPD_LAST_KEYWORD, - MEMD_VPD_TEST_KEYWORD, // Test purposes ONLY! - - //Start common IPVPD enums - FULL_RECORD = IPVPD::FULL_RECORD, - MEMD_VPD_INVALID_KEYWORD = IPVPD::INVALID_KEYWORD, - }; - -}; // end MEMD_VPD - -#endif diff --git a/src/include/usr/vpd/vpd_if.H b/src/include/usr/vpd/vpd_if.H index 0d8cc4a2d..4e63a0965 100644 --- a/src/include/usr/vpd/vpd_if.H +++ b/src/include/usr/vpd/vpd_if.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -25,6 +25,8 @@ #if !defined(__VPD_IF_H) #define __VPD_IF_H +#include <pnor/pnorif.H> +#include <map> namespace VPD { @@ -41,9 +43,18 @@ namespace VPD */ enum vpdCmdTarget { - AUTOSELECT, - PNOR, - SEEPROM, + AUTOSELECT = 0x0000, + + // Use our cache or read the eeprom + PNOR = 0x0001, + SEEPROM = 0x0002, + LOCATION_MASK = 0x000F, + + // Use the real vpd or a firmware override + USEVPD = 0x0010, + USEOVERRIDE = 0x0020, + OVERRIDE_MASK = 0x00F0, + INVALID_LOCATION = 0xFFFF, }; @@ -137,6 +148,29 @@ namespace VPD */ errlHndl_t goldenCacheInvalidate ( void ); + /** + * @brief Structure used to specify VPD overrides for runtime + * reserved memory usage + */ + struct OverrideSpecifier_t + { + PNOR::SectionId pnorId; + size_t size; // size in bytes + }; + + /** + * @brief Map of override labels to sections + * index : uint64_t label = right-justified 4-digit ASCII string + * result : OverrideSpecifier_t + */ + typedef std::map<uint64_t,OverrideSpecifier_t> OverrideRsvMemMap_t; + + /** + * @brief Get a list of all overridden sections + * @param[out] List of known override sections + */ + void getListOfOverrideSections( OverrideRsvMemMap_t& o_overrides ); + }; //end vpd namespace #endif diff --git a/src/include/usr/vpd/vpdreasoncodes.H b/src/include/usr/vpd/vpdreasoncodes.H index 45652bf05..8c7402158 100644 --- a/src/include/usr/vpd/vpdreasoncodes.H +++ b/src/include/usr/vpd/vpdreasoncodes.H @@ -147,6 +147,7 @@ enum vpdReasonCode VPD_TARGET_CHIP_NOT_FOUND = VPD_COMP_ID | 0x39, VPD_EEPROM_VPD_PRIMARY_INFO_MISSING = VPD_COMP_ID | 0x3a, VPD_RT_NODE_TOO_LARGE = VPD_COMP_ID | 0x3b, + VPD_CANNOT_WRITE_OVERRIDDEN_VPD = VPD_COMP_ID | 0x3c, }; diff --git a/src/kernel/exception.C b/src/kernel/exception.C index ca05bf3a1..8dc4b53e3 100644 --- a/src/kernel/exception.C +++ b/src/kernel/exception.C @@ -110,6 +110,7 @@ void kernel_execute_data_storage() "Instruction where it occurred: %p\n", t->tid, getDAR(), getDSISR(), t->context.nip); KernelMisc::printkBacktrace(t); + MAGIC_INSTRUCTION(MAGIC_BREAK_ON_ERROR); TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED); } } diff --git a/src/usr/devicefw/test/associatortest.H b/src/usr/devicefw/test/associatortest.H index a9d87534e..98eb3edba 100644 --- a/src/usr/devicefw/test/associatortest.H +++ b/src/usr/devicefw/test/associatortest.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* [+] 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. */ @@ -164,7 +166,7 @@ public: // Reverse the wildcard test l_errl = as.registerRoute(WILDCARD, - PNOR, + DeviceFW::PNOR, TYPE_NODE, &performOperation); if (l_errl) @@ -172,7 +174,7 @@ public: TS_FAIL("testDoubleRegistration> Error received from registerRoute (2)."); } l_errl = as.registerRoute(WRITE, - PNOR, + DeviceFW::PNOR, TYPE_NODE, &performOperation); if (l_errl) diff --git a/src/usr/fapi2/plat_vpd_access.C b/src/usr/fapi2/plat_vpd_access.C index 164062c9d..f5a6c92e2 100644 --- a/src/usr/fapi2/plat_vpd_access.C +++ b/src/usr/fapi2/plat_vpd_access.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2017 */ +/* Contributors Listed Below - COPYRIGHT 2012,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -35,7 +35,6 @@ #include <p9_get_mem_vpd_keyword.H> #include <attribute_service.H> #include <vpd/dvpdenums.H> -#include <vpd/memd_vpdenums.H> #include <errl/errlmanager.H> //The following can be uncommented for unit testing //#undef FAPI_DBG @@ -52,8 +51,6 @@ fapi2::ReturnCode platGetVPD( fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; errlHndl_t l_errl = nullptr; keywordInfo_t l_keywordInfo; - uint8_t* l_dvpd_vm = nullptr; - uint32_t* l_full_dvpdVM = nullptr; // Assume that all memory keywords (MR,MT,J0..JZ,X0...XZ) are all the // same size of 255. This avoids going through the decode and asking @@ -96,7 +93,6 @@ fapi2::ReturnCode platGetVPD( io_vpd_info.iv_size, VPD_KEYWORD_SIZE, true); //software callout - l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); break; //return with error } @@ -106,7 +102,6 @@ fapi2::ReturnCode platGetVPD( if (l_errl) { FAPI_ERR("platGetVPD: Error from getTargetingTarget"); - l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); break; //return with error } @@ -203,121 +198,24 @@ fapi2::ReturnCode platGetVPD( io_vpd_info.iv_vpd_type, TARGETING::get_huid(l_pMcsTarget), true); //software callout - l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); break; //return with error } - // The PNOR::MEMD section potentially contains multiple copies of the - // MEMD VPD. This next section searches through the PNOR copy for a - // valid copy if it exists and uses that instead of the DVPD section. - //Read mapping keyword size_t l_buffSize = VPD_KEYWORD_SIZE; uint8_t * l_pMapping = new uint8_t[VPD_KEYWORD_SIZE](); - // MEMD Processing - PNOR::SectionInfo_t l_memd_info; - l_errl = PNOR::getSectionInfo(PNOR::MEMD,l_memd_info); - bool l_memd_found = false; - MemdHeader_t l_header; - + l_errl = deviceRead((TARGETING::Target *)l_pMcsTarget, + l_pMapping, + l_buffSize, + DEVICE_DVPD_ADDRESS(DVPD::MEMD, + l_mapKeyword)); if( l_errl ) { - FAPI_INF("platGetVPD: Optional MEMD section not found."); - delete l_errl; - l_errl = NULL; - } - else - { - do - { - const uint8_t * vaddr = reinterpret_cast<const uint8_t *>( - l_memd_info.vaddr); - // Get and process the header - memcpy(&l_header, vaddr, sizeof(l_header)); - - size_t theSize = 0; - - // Get the VM keyword size - l_errl = deviceRead( l_pMcsTarget, nullptr, - theSize, DEVICE_DVPD_ADDRESS( - DVPD::MEMD, DVPD::VM)); - - if( l_errl ) - { - FAPI_ERR("platGetVPD: ERROR getting MEMD VM size"); - l_rc.setPlatDataPtr(reinterpret_cast<void *>( l_errl )); - break; - } - - // Get the VM keyword from the real VPD - l_dvpd_vm = static_cast<uint8_t*>(malloc( theSize )); - - l_errl = deviceRead( l_pMcsTarget, l_dvpd_vm, - theSize, DEVICE_DVPD_ADDRESS( - DVPD::MEMD, DVPD::VM)); - if( l_errl ) - { - FAPI_ERR("platGetVPD: ERROR getting DVPD VM keyword"); - l_rc.setPlatDataPtr(reinterpret_cast<void *>( l_errl )); - break; - } - l_full_dvpdVM = (reinterpret_cast<uint32_t*>(l_dvpd_vm)); - - l_memd_found = find_memd_in_pnor(l_dvpd_vm, - l_header, l_pMcsTarget, theSize); - uint64_t l_memd_offset_bytes = l_pMcsTarget->getAttr< - TARGETING::ATTR_MEMD_OFFSET>(); - - if(l_memd_found) - { - FAPI_INF("platGetVPD: Matching MEMD data was found in the " - "PNOR section, VM value is %llx. Reading in at " - "offset %llx",l_full_dvpdVM[0], l_memd_offset_bytes); - l_errl = deviceRead((TARGETING::Target *)l_pMcsTarget, - l_pMapping, - l_buffSize, - DEVICE_MEMD_VPD_ADDRESS(MEMD_VPD::MEMD, - l_mapKeyword) + l_memd_offset_bytes ); - break; - }else - { - FAPI_INF("platGetVPD: Matching MEMD data was not found in " - "the PNOR section, DVPD VM value is %llx", - l_full_dvpdVM[0]); - } - - }while(0); - - } - if(l_errl) - { - FAPI_ERR("find_memd_in_pnor: ERROR getting the PNOR MEMD information"); - l_rc.setPlatDataPtr(reinterpret_cast<void *>(l_errl)); + FAPI_ERR("platGetVPD: ERROR returned from deviceRead(MEMD,%d)",l_mapKeyword); break; } - if( !(l_memd_found) ) - { - FAPI_INF("platGetVPD: MEMD data was not found in the PNOR " - "section. Using EEPROM. VM value is: %llx", - l_full_dvpdVM[0]); - - l_errl = deviceRead((TARGETING::Target *)l_pMcsTarget, - l_pMapping, - l_buffSize, - DEVICE_DVPD_ADDRESS(DVPD::MEMD, - l_mapKeyword)); - if (l_errl) - { - delete l_pMapping; - l_pMapping = nullptr; - FAPI_ERR("platGetVPD: ERROR reading mapping keyword"); - l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); - break; //return with error - } - } - // Find vpd keyword name based on VPDInfo FAPI_EXEC_HWP(l_rc, p9_get_mem_vpd_keyword, @@ -377,28 +275,15 @@ fapi2::ReturnCode platGetVPD( //Read vpd blob l_buffSize = l_keywordInfo.kwBlobSize; - if(l_memd_found) - { - l_errl = deviceRead((TARGETING::Target *)l_pMcsTarget, - o_blob, - l_buffSize, - DEVICE_MEMD_VPD_ADDRESS(MEMD_VPD::MEMD, - l_keywordEnum)); - - } - else - { - l_errl = deviceRead((TARGETING::Target *)l_pMcsTarget, + l_errl = deviceRead((TARGETING::Target *)l_pMcsTarget, o_blob, l_buffSize, DEVICE_DVPD_ADDRESS(DVPD::MEMD, l_keywordEnum)); - } if (l_errl) { FAPI_ERR("platGetVPD: ERROR reading keyword"); - l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); break; //return with error } @@ -434,106 +319,19 @@ fapi2::ReturnCode platGetVPD( HWAS::NO_DECONFIG, HWAS::GARD_NULL ); - l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); break; //return with error } } } while (0); - free(l_dvpd_vm); - l_dvpd_vm = nullptr; - l_full_dvpdVM = nullptr; - - FAPI_DBG("platGetVPD: exit"); - - return l_rc; -} - -bool find_memd_in_pnor(uint8_t* i_eepromVM, MemdHeader_t i_header, - TARGETING::Target * i_target, size_t i_vm_size) -{ - errlHndl_t l_errl = nullptr; - - bool memdFoundInPnor = false; - bool l_valid_memd = ((i_header.eyecatch == MEMD_VALID_HEADER) & - (i_header.header_version == MEMD_VALID_HEADER_VERSION) & - (i_header.memd_version == MEMD_VALID_MEMD_VERSION) ); - - uint8_t* l_memd_vm = nullptr; - uint32_t l_memd_iteration = 0; - bool l_retValue = false; - - if(l_valid_memd && !memdFoundInPnor) + if( l_errl ) { - FAPI_INF("find_memd_in_pnor: MEMD is valid!"); - // Reset memd offset before we start the first iteration - i_target->setAttr<TARGETING::ATTR_MEMD_OFFSET>(0); - - //do-while loop (needs to be executed at least once) - // while VM keywods don't match, and we haven't gone - // through all the MEMD copies - do - { - // Get the VM keyword from the copy in PNOR - l_memd_vm = static_cast<uint8_t*>(malloc( i_vm_size )); - - uint64_t l_memd_offset = i_target->getAttr< - TARGETING::ATTR_MEMD_OFFSET>(); - - FAPI_INF("find_memd_in_pnor: attempting to read MEMD VM keyword"); - l_errl = deviceRead( i_target, l_memd_vm, i_vm_size, - DEVICE_MEMD_VPD_ADDRESS( - MEMD_VPD::MEMD, MEMD_VPD::VM)); - if(l_errl) - { - FAPI_ERR("find_memd_in_pnor: ERROR getting MEMD VM keyword"); - errlCommit(l_errl, FAPI2_COMP_ID); - break; - } - - assert(i_vm_size != 0); - - // Compare the last nibbles - if( !((i_eepromVM[i_vm_size-1] & 0x0F) == - (l_memd_vm[i_vm_size-1] & 0x0F)) ) - { - // VM's don't match, we need to keep looking - FAPI_INF("find_memd_in_pnor: DVPD and MEMD VM's last nibble" - " don't match: %llx and %llx", - (reinterpret_cast<uint32_t*>(i_eepromVM))[0], - (reinterpret_cast<uint32_t*>(l_memd_vm))[0] ); - i_target->setAttr<TARGETING::ATTR_MEMD_OFFSET - >(l_memd_offset + - (i_header.expected_size_kb * 1000)); - } - else - { - FAPI_INF("find_memd_in_pnor: Matching MEMD data was found in " - "the PNOR section. VM value is: %llx. Offset " - "is %llx, DVPD VM is %llx", - (reinterpret_cast<uint32_t*>(l_memd_vm))[0], - l_memd_offset, - (reinterpret_cast<uint32_t*>(i_eepromVM))[0]); - memdFoundInPnor = true; - l_retValue = true; - break; - } - - l_memd_iteration = l_memd_iteration + 1; - free(l_memd_vm); - l_memd_vm = nullptr; - - }while(l_memd_iteration < i_header.expected_num); - - free(l_memd_vm); - l_memd_vm = nullptr; + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); } + FAPI_DBG("platGetVPD: exit"); - return l_retValue; - + return l_rc; } - - } // namespace diff --git a/src/usr/isteps/istep11/call_host_prd_hwreconfig.C b/src/usr/isteps/istep11/call_host_prd_hwreconfig.C index 81eede957..0df8a468e 100644 --- a/src/usr/isteps/istep11/call_host_prd_hwreconfig.C +++ b/src/usr/isteps/istep11/call_host_prd_hwreconfig.C @@ -23,6 +23,11 @@ /* */ /* IBM_PROLOG_END_TAG */ #include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <isteps/hwpisteperror.H> +#include <pnor/pnorif.H> +#include <config.h> +#include <initservice/isteps_trace.H> using namespace ERRORLOG; @@ -30,9 +35,26 @@ namespace ISTEP_11 { void* call_host_prd_hwreconfig (void *io_pArgs) { + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, ENTER_MRK"call_host_prd_hwreconfig"); + errlHndl_t l_err = NULL; + ISTEP_ERROR::IStepError l_StepError; //@TODO-RTC:158411 call p9_enable_reconfig.C - return l_err; + + +#ifdef CONFIG_SECUREBOOT + // Load the MEMD section here as the first part of step11, it + // will stay loaded until the end of step14 + l_err = loadSecureSection(PNOR::MEMD); + if( l_err ) + { + l_StepError.addErrorDetails(l_err); + ERRORLOG::errlCommit(l_err, HWPF_COMP_ID); + } +#endif + + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, EXIT_MRK"call_host_prd_hwreconfig"); + return l_StepError.getErrorHandle(); } }; diff --git a/src/usr/isteps/istep14/call_proc_exit_cache_contained.C b/src/usr/isteps/istep14/call_proc_exit_cache_contained.C index 45d4bbf73..7b5e86d46 100644 --- a/src/usr/isteps/istep14/call_proc_exit_cache_contained.C +++ b/src/usr/isteps/istep14/call_proc_exit_cache_contained.C @@ -461,6 +461,7 @@ void* call_proc_exit_cache_contained (void *io_pArgs) } } } + if ( l_errl ) { // Create IStep error log and cross reference to error that occurred @@ -470,6 +471,17 @@ void* call_proc_exit_cache_contained (void *io_pArgs) errlCommit( l_errl, HWPF_COMP_ID ); } +#ifdef CONFIG_SECUREBOOT + // Unload the MEMD section that was loaded at the beginning of step11 + l_errl = unloadSecureSection(PNOR::MEMD); + if (l_errl) + { + l_stepError.addErrorDetails(l_errl); + errlCommit(l_errl, HWPF_COMP_ID); + } +#endif + + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_proc_exit_cache_contained exit" ); // @@@@@ END CUSTOM BLOCK: @@@@@ diff --git a/src/usr/pnor/spnorrp.C b/src/usr/pnor/spnorrp.C index f3e67d202..5b1ef5b03 100644 --- a/src/usr/pnor/spnorrp.C +++ b/src/usr/pnor/spnorrp.C @@ -884,12 +884,14 @@ void SPnorRP::waitForMessage() } else { + TRACDCOMP(g_trac_pnor,"Loading %s for the first time", PNOR::SectionIdToString(l_id)); l_record = new LoadRecord; } TRACDCOMP(g_trac_pnor, "SPnorRP::waitForMessage> MSG_LOAD_SECTION refCount is %i",l_record->refCount); if (l_record->refCount == 0) { + TRACDCOMP(g_trac_pnor,"Loading %s fresh", PNOR::SectionIdToString(l_id)); uint32_t loadPlid=0; l_rc = verifySections(l_id, l_loadedPreviously, @@ -1027,6 +1029,7 @@ void SPnorRP::waitForMessage() // 2 or more break; } + TRACDCOMP(g_trac_pnor,"Completely unloading %s", PNOR::SectionIdToString(l_id)); l_errhdl = removePages(l_rec->secAddr, l_sizeWithHdr); diff --git a/src/usr/runtime/populate_hbruntime.C b/src/usr/runtime/populate_hbruntime.C index 4d26bce26..bf891b09c 100644 --- a/src/usr/runtime/populate_hbruntime.C +++ b/src/usr/runtime/populate_hbruntime.C @@ -443,9 +443,12 @@ errlHndl_t setNextHbRsvMemEntry(const HDAT::hdatMsVpdRhbAddrRangeType i_type, * ----- HB Data Layout ------- * io_start_address * -- HB Table of Contents - * -- ATTR Override Data + * -- ATTR Override Data (optional) * -- ATTR Data * -- VPD + * -- HYPCOMM + * -- VPD Overrides + * -- HBRT Trace Area (master node only) * -- Padding * io_end_address * @@ -564,6 +567,21 @@ errlHndl_t fill_RsvMem_hbData(uint64_t & io_start_address, ALIGN_PAGE(l_hbTOC.entry[l_hbTOC.total_entries].size); l_hbTOC.total_entries++; + // Fill in VPD_XXXX sizes (if there are any) + VPD::OverrideRsvMemMap_t l_vpdOverrides; + VPD::getListOfOverrideSections( l_vpdOverrides ); + for( auto l_over : l_vpdOverrides ) + { + // Or in the specific label with the "VPD_" prefix + l_hbTOC.entry[l_hbTOC.total_entries].label = + Util::HBRT_MEM_LABEL_VPD_XXXX | l_over.first; + l_hbTOC.entry[l_hbTOC.total_entries].offset = 0; + l_hbTOC.entry[l_hbTOC.total_entries].size = l_over.second.size; + l_totalSectionSize += + ALIGN_PAGE(l_hbTOC.entry[l_hbTOC.total_entries].size); + l_hbTOC.total_entries++; + } + // Fill in the TRACEBUF only for Master Node if(i_master_node == true ) { @@ -778,7 +796,84 @@ errlHndl_t fill_RsvMem_hbData(uint64_t & io_start_address, memset(reinterpret_cast<uint8_t*>(l_prevDataAddr),0,aligned_size); break; + case Util::HBRT_MEM_LABEL_VPD_MEMD: + { + TRACFCOMP( g_trac_runtime, "fill_RsvMem_hbData> VPD_MEMD v address 0x%.16llX, size: %lld", l_prevDataAddr, aligned_size); + + VPD::OverrideSpecifier_t l_over = + l_vpdOverrides[l_hbTOC.entry[i].label + & Util::HBRT_MEM_LABEL_VPD_MASK]; + +#ifdef CONFIG_SECUREBOOT + // load the section in, copy the data, then unload it + l_elog = PNOR::loadSecureSection(l_over.pnorId); + if(l_elog) + { + TRACFCOMP( g_trac_runtime, + "fill_RsvMem_hbData> failed secure load call" ); + break; + } +#endif + + PNOR::SectionInfo_t l_memd_info; + l_elog = PNOR::getSectionInfo(l_over.pnorId,l_memd_info); + if( l_elog ) + { + TRACFCOMP( g_trac_runtime, + "fill_RsvMem_hbData> failed getSectionInfo call" ); + break; + } + +#ifdef CONFIG_SECUREBOOT + memcpy(reinterpret_cast<uint8_t*>(l_prevDataAddr), + reinterpret_cast<uint8_t *>(l_memd_info.vaddr), + l_memd_info.secureProtectedPayloadSize); +#else + memcpy(reinterpret_cast<uint8_t*>(l_prevDataAddr), + reinterpret_cast<uint8_t *>(l_memd_info.vaddr), + l_memd_info.size); +#endif + + +#ifdef CONFIG_SECUREBOOT + l_elog = PNOR::unloadSecureSection(l_over.pnorId); + if(l_elog) + { + TRACFCOMP( g_trac_runtime, + "fill_RsvMem_hbData> failed secure unload call" ); + break; + } +#endif + + TRACFCOMP( g_trac_runtime, "fill_RsvMem_hbData> VPD v address 0x%.16llX, size: %lld done", l_prevDataAddr, aligned_size); + break; + } + + case(Util::HBRT_MEM_LABEL_PADDING): + // NOOP + break; + default: + TRACFCOMP( g_trac_runtime, "fill_RsvMem_hbData> Unrecognized label 0x%.ll16X", l_hbTOC.entry[i].label ); + /*@ + * @errortype ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid RUNTIME::MOD_FILL_RSVMEM_HBDATA + * @reasoncode RUNTIME::RC_UNKNOWN_LABEL + * @userdata1 Unknown Label + * @userdata2 <unused> + * + * @devdesc Unknown reserved memory label attempted + * @custdesc Firmware error initializing system + * data structures during boot + */ + l_elog = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_FILL_RSVMEM_HBDATA, + RUNTIME::RC_UNKNOWN_LABEL, + l_hbTOC.entry[i].label, + 0, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT ); + l_elog->collectTrace(RUNTIME_COMP_NAME); break; } i++; @@ -3138,6 +3233,7 @@ errlHndl_t populate_hbRuntimeData( void ) if(l_elog != nullptr) { TRACFCOMP( g_trac_runtime, "fill_RsvMem_hbData failed" ); + break; } // Get list of processor chips diff --git a/src/usr/util/runtime/util_rt.C b/src/usr/util/runtime/util_rt.C index 3dc3935f3..468db6ee7 100644 --- a/src/usr/util/runtime/util_rt.C +++ b/src/usr/util/runtime/util_rt.C @@ -28,7 +28,6 @@ #include <util/utilrsvdmem.H> #include <util/runtime/util_rt.H> - /** * @brief Get the address of a reserved hostboot memory region by its label * @param[in] i_label HBRT_MEM_LABEL_ constant @@ -55,6 +54,7 @@ uint64_t hb_get_rt_rsvd_mem(Util::hbrt_mem_label_t i_label, case Util::HBRT_MEM_LABEL_PADDING: case Util::HBRT_MEM_LABEL_HYPCOMM: case Util::HBRT_MEM_LABEL_TRACEBUF: + case Util::HBRT_MEM_LABEL_VPD_MEMD: if( (g_hostInterfaces != NULL) && (g_hostInterfaces->get_reserved_mem) ) { diff --git a/src/usr/util/utilrsvdmem.C b/src/usr/util/utilrsvdmem.C index 32859f311..e0a788b33 100644 --- a/src/usr/util/utilrsvdmem.C +++ b/src/usr/util/utilrsvdmem.C @@ -62,6 +62,7 @@ namespace Util case HBRT_MEM_LABEL_PADDING: case HBRT_MEM_LABEL_HYPCOMM: case HBRT_MEM_LABEL_TRACEBUF: + case HBRT_MEM_LABEL_VPD_MEMD: // Find offset of label section for (uint16_t i = 0; i < toc_ptr->total_entries; i++) { diff --git a/src/usr/vpd/cvpd.C b/src/usr/vpd/cvpd.C index 7576009eb..fe203dd50 100644 --- a/src/usr/vpd/cvpd.C +++ b/src/usr/vpd/cvpd.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -115,10 +115,38 @@ namespace CVPD TRACSSCOMP( g_trac_vpd, ENTER_MRK"cvpdRead()" ); - err = Singleton<CvpdFacade>::instance().read(i_target, - io_buffer, - io_buflen, - args); +#ifdef CONFIG_SECUREBOOT + // Load the secure section just in case if we're using it + bool l_didload = false; + err = Singleton<CvpdFacade>::instance(). + loadUnloadSecureSection( args, i_target, true, l_didload ); +#endif + + if( !err ) + { + err = Singleton<CvpdFacade>::instance().read(i_target, + io_buffer, + io_buflen, + args); + } + +#ifdef CONFIG_SECUREBOOT + if( l_didload ) + { + errlHndl_t err2 = Singleton<CvpdFacade>::instance(). + loadUnloadSecureSection( args, i_target, false, l_didload ); + if( err2 && !err ) + { + err = err2; + err2 = nullptr; + } + else if( err2 ) + { + err2->plid(err->plid()); + errlCommit( err2, VPD_COMP_ID ); + } + } +#endif return err; } @@ -288,3 +316,113 @@ void CvpdFacade::getRecordLists( #endif } +/** + * @brief Callback function to check for a record override and + * set iv_overridePtr appropriately + */ +errlHndl_t CvpdFacade::checkForRecordOverride( const char* i_record, + TARGETING::Target* i_target, + uint8_t*& o_ptr ) +{ + TRACFCOMP(g_trac_vpd,ENTER_MRK"CvpdFacade::checkForRecordOverride( %s, 0x%.8X )", + i_record, get_huid(i_target)); + errlHndl_t l_errl = nullptr; + o_ptr = nullptr; + + assert( i_record != nullptr, "CvpdFacade::checkForRecordOverride() i_record is null" ); + assert( i_target != nullptr, "CvpdFacade::checkForRecordOverride() i_target is null" ); + + VPD::RecordTargetPair_t l_recTarg = + VPD::makeRecordTargetPair(i_record,i_target); + + do + { + // We only support overriding SPDX + if( strcmp( i_record, "SPDX" ) ) + { + TRACFCOMP(g_trac_vpd,"Record %s has no override", i_record); + iv_overridePtr[l_recTarg] = nullptr; + break; + } + + // Compare the 5th nibble + constexpr uint32_t l_vmMask = 0x00000F00; + input_args_t l_args = { CVPD::SPDX, CVPD::VM, VPD::AUTOSELECT }; + l_errl = getMEMDFromPNOR( l_args, + i_target, + l_vmMask ); + if( l_errl ) + { + TRACFCOMP(g_trac_vpd,ERR_MRK"ERROR from getMEMDFromPNOR."); + break; + } + + } while(0); + + // For any error, we should reset the override map so that we'll + // attempt everything again the next time we want VPD + if( l_errl ) + { + iv_overridePtr.erase(l_recTarg); + } + else + { + o_ptr = iv_overridePtr[l_recTarg]; + } + + return l_errl; +} + +#ifdef CONFIG_SECUREBOOT +/** + * @brief Load/unload the appropriate secure section for + * an overriden PNOR section + */ +errlHndl_t CvpdFacade::loadUnloadSecureSection( input_args_t i_args, + TARGETING::Target* i_target, + bool i_load, + bool& o_loaded ) +{ + errlHndl_t l_err = nullptr; + o_loaded = false; + +#ifndef __HOSTBOOT_RUNTIME + // Only relevant for SPDX + if( i_args.record != CVPD::SPDX ) + { + return nullptr; + } + + const char* l_record = nullptr; + l_err = translateRecord( i_args.record, l_record ); + if( l_err ) + { + return l_err; + } + + // Jump out if we don't have an override + VPD::RecordTargetPair_t l_recTarg = + VPD::makeRecordTargetPair(l_record,i_target); + VPD::OverrideMap_t::iterator l_overItr = iv_overridePtr.find(l_recTarg); + if( l_overItr == iv_overridePtr.end() ) + { + return nullptr; + } + + if( i_load ) + { + l_err = loadSecureSection(PNOR::MEMD); + if( !l_err ) + { + o_loaded = true; + } + } + else + { + l_err = unloadSecureSection(PNOR::MEMD); + } +#endif + + return l_err; +} +#endif diff --git a/src/usr/vpd/cvpd.H b/src/usr/vpd/cvpd.H index 73c54128d..31f89b29f 100644 --- a/src/usr/vpd/cvpd.H +++ b/src/usr/vpd/cvpd.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -176,6 +176,22 @@ class CvpdFacade: public IpVpdFacade */ CvpdFacade( ); +#ifdef CONFIG_SECUREBOOT + /** + * @brief Load/unload the appropriate secure section for + * an overriden PNOR section + * @param[in] i_args Record/keyword + * @param[in] i_target Target pointer + * @param[in] i_load true=load, false=unload + * @param[out] o_loaded true=section loaded, false=section not loaded + * @return Error log + */ + virtual errlHndl_t loadUnloadSecureSection( input_args_t i_args, + TARGETING::Target* i_target, + bool i_load, + bool& o_loaded ); +#endif + private: /** @@ -197,5 +213,19 @@ class CvpdFacade: public IpVpdFacade const recordInfo* & o_altVpdRecords, uint64_t & o_altRecSize); + protected: + /** + * @brief Callback function to check for a record override and + * set iv_overridePtr appropriately + * @param[in] i_record Record name + * @param[in] i_target Target pointer + * @param[out] o_ptr Pointer to location of record in PNOR, + * ==nullptr if there is no override + * @return Error log + */ + virtual errlHndl_t checkForRecordOverride( const char* i_record, + TARGETING::Target* i_target, + uint8_t*& o_ptr ); + }; #endif // __CVPD_H diff --git a/src/usr/vpd/dvpd.C b/src/usr/vpd/dvpd.C index 8adf670f7..9e5e7fbf4 100644 --- a/src/usr/vpd/dvpd.C +++ b/src/usr/vpd/dvpd.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -113,12 +113,44 @@ namespace DVPD args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t )); TRACSSCOMP( g_trac_vpd, - ENTER_MRK"dvpdRead()" ); + ENTER_MRK"dvpdRead(0x%.8X):rec=%d,kw=%d,loc=%d", + TARGETING::get_huid(i_target), + args.record, + args.keyword, + args.location); + +#ifdef CONFIG_SECUREBOOT + // Load the secure section just in case if we're using it + bool l_didload = false; + err = Singleton<DvpdFacade>::instance(). + loadUnloadSecureSection( args, i_target, true, l_didload ); +#endif - err = Singleton<DvpdFacade>::instance().read(i_target, - io_buffer, - io_buflen, - args); + if( !err ) + { + err = Singleton<DvpdFacade>::instance().read(i_target, + io_buffer, + io_buflen, + args); + } + +#ifdef CONFIG_SECUREBOOT + if( l_didload ) + { + errlHndl_t err2 = Singleton<DvpdFacade>::instance(). + loadUnloadSecureSection( args, i_target, false, l_didload ); + if( err2 && !err ) + { + err = err2; + err2 = nullptr; + } + else if( err2 ) + { + err2->plid(err->plid()); + errlCommit( err2, VPD_COMP_ID ); + } + } +#endif return err; } @@ -166,7 +198,11 @@ namespace DVPD args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t )); TRACSSCOMP( g_trac_vpd, - ENTER_MRK"dvpdWrite()" ); + ENTER_MRK"dvpdWrite(0x%.8X):rec=%d,kw=%d,loc=%d", + TARGETING::get_huid(i_target), + args.record, + args.keyword, + args.location); err = Singleton<DvpdFacade>::instance().write(i_target, @@ -337,9 +373,8 @@ IpVpdFacade(DVPD::dvpdRecords, iv_configInfo.vpdWriteHW = false; #endif -iv_vpdSectionSize = DVPD::SECTION_SIZE; -iv_vpdMaxSections = DVPD::MAX_SECTIONS; - + iv_vpdSectionSize = DVPD::SECTION_SIZE; + iv_vpdMaxSections = DVPD::MAX_SECTIONS; } // Retrun lists of records that should be copied to pnor. void DvpdFacade::getRecordLists( @@ -367,3 +402,112 @@ void DvpdFacade::getRecordLists( #endif } +/** + * @brief Callback function to check for a record override + */ +errlHndl_t DvpdFacade::checkForRecordOverride( const char* i_record, + TARGETING::Target* i_target, + uint8_t*& o_ptr ) +{ + TRACFCOMP(g_trac_vpd,ENTER_MRK"DvpdFacade::checkForRecordOverride( %s, 0x%.8X )", + i_record, get_huid(i_target)); + errlHndl_t l_errl = nullptr; + o_ptr = nullptr; + + assert( i_record != nullptr, "DvpdFacade::checkForRecordOverride() i_record is null" ); + assert( i_target != nullptr, "DvpdFacade::checkForRecordOverride() i_target is null" ); + + VPD::RecordTargetPair_t l_recTarg = + VPD::makeRecordTargetPair(i_record,i_target); + + do + { + // We only support overriding MEMD + if( strcmp( i_record, "MEMD" ) ) + { + TRACFCOMP(g_trac_vpd,"Record %s has no override", i_record); + iv_overridePtr[l_recTarg] = nullptr; + break; + } + + // Compare the last nibble + constexpr uint32_t l_vmMask = 0x0000000F; + input_args_t l_args = { DVPD::MEMD, DVPD::VM, VPD::AUTOSELECT }; + l_errl = getMEMDFromPNOR( l_args, + i_target, + l_vmMask ); + if( l_errl ) + { + TRACFCOMP(g_trac_vpd,ERR_MRK"ERROR from getMEMDFromPNOR."); + break; + } + + } while(0); + + // For any error, we should reset the override map so that we'll + // attempt everything again the next time we want VPD + if( l_errl ) + { + iv_overridePtr.erase(l_recTarg); + } + else + { + o_ptr = iv_overridePtr[l_recTarg]; + } + + return l_errl; +} + +#ifdef CONFIG_SECUREBOOT +/** + * @brief Load/unload the appropriate secure section for + * an overriden PNOR section + */ +errlHndl_t DvpdFacade::loadUnloadSecureSection( input_args_t i_args, + TARGETING::Target* i_target, + bool i_load, + bool& o_loaded ) +{ + errlHndl_t l_err = nullptr; + o_loaded = false; + +#ifndef __HOSTBOOT_RUNTIME + // Only relevant for MEMD + if( i_args.record != DVPD::MEMD ) + { + return nullptr; + } + + const char* l_record = nullptr; + l_err = translateRecord( i_args.record, l_record ); + if( l_err ) + { + return l_err; + } + + // Jump out if we don't have an override + VPD::RecordTargetPair_t l_recTarg = + VPD::makeRecordTargetPair(l_record,i_target); + VPD::OverrideMap_t::iterator l_overItr = iv_overridePtr.find(l_recTarg); + if( l_overItr == iv_overridePtr.end() ) + { + return nullptr; + } + + if( i_load ) + { + l_err = loadSecureSection(PNOR::MEMD); + if( !l_err ) + { + o_loaded = true; + } + } + else + { + l_err = unloadSecureSection(PNOR::MEMD); + } +#endif + + return l_err; +} +#endif diff --git a/src/usr/vpd/dvpd.H b/src/usr/vpd/dvpd.H index 73279e844..92985aebe 100644 --- a/src/usr/vpd/dvpd.H +++ b/src/usr/vpd/dvpd.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -225,6 +225,22 @@ class DvpdFacade: public IpVpdFacade */ DvpdFacade( ); +#ifdef CONFIG_SECUREBOOT + /** + * @brief Load/unload the appropriate secure section for + * an overriden PNOR section + * @param[in] i_args Record/keyword + * @param[in] i_target Target pointer + * @param[in] i_load true=load, false=unload + * @param[out] o_loaded true=section loaded, false=section not loaded + * @return Error log + */ + virtual errlHndl_t loadUnloadSecureSection( input_args_t i_args, + TARGETING::Target* i_target, + bool i_load, + bool& o_loaded ); +#endif + private: /** @@ -246,5 +262,19 @@ class DvpdFacade: public IpVpdFacade const recordInfo* & o_altVpdRecords, uint64_t & o_altRecSize); + protected: + /** + * @brief Callback function to check for a record override and + * set iv_overridePtr appropriately + * @param[in] i_record Record name + * @param[in] i_target Target pointer + * @param[out] o_ptr Pointer to location of record in PNOR, + * ==nullptr if there is no override + * @return Error log + */ + virtual errlHndl_t checkForRecordOverride( const char* i_record, + TARGETING::Target* i_target, + uint8_t*& o_ptr ); + }; #endif // __DVPD_H diff --git a/src/usr/vpd/ipvpd.C b/src/usr/vpd/ipvpd.C index c62c8355f..25b7970f2 100644 --- a/src/usr/vpd/ipvpd.C +++ b/src/usr/vpd/ipvpd.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -41,7 +41,8 @@ #include <vpd/vpd_if.H> #include <config.h> #include <vpd/ipvpdenums.H> -#include <vpd/memd_vpdenums.H> +#include <util/utilrsvdmem.H> +#include <util/runtime/util_rt.H> #include "vpd.H" #include "cvpd.H" @@ -68,7 +69,6 @@ extern trace_desc_t* g_trac_vpd; static const uint64_t IPVPD_TOC_SIZE = 0x100; //256 static const uint64_t IPVPD_TOC_ENTRY_SIZE = 8; static const uint64_t IPVPD_TOC_INVALID_DATA = 0xFFFFFFFFFFFFFFFF; -uint64_t MEMD_HEADER_SIZE = sizeof(MemdHeader_t); /** * @brief Constructor @@ -88,7 +88,6 @@ IpVpdFacade::IpVpdFacade(const recordInfo* i_vpdRecords, ,iv_mutex(i_mutex) ,iv_cachePnorAddr(0x0) ,iv_vpdMsgType(i_vpdMsgType) -,iv_memdAccessed(false) { iv_configInfo.vpdReadPNOR = false; iv_configInfo.vpdReadHW = false; @@ -243,11 +242,9 @@ errlHndl_t IpVpdFacade::write ( TARGETING::Target * i_target, // write() recursively for each location if ( iv_configInfo.vpdWritePNOR && iv_configInfo.vpdWriteHW && - i_args.location == VPD::AUTOSELECT ) + ((i_args.location & VPD::LOCATION_MASK) == VPD::AUTOSELECT) ) { - input_args_t l_args; - l_args.record = i_args.record; - l_args.keyword = i_args.keyword; + input_args_t l_args = i_args; l_args.location = VPD::SEEPROM; err = write( i_target, @@ -615,7 +612,8 @@ errlHndl_t IpVpdFacade::loadPnor ( TARGETING::Target * i_target ) sRecLength, pRecPtr, i_target, - sRecArgs.location ); + sRecArgs.location, + (*it).record_name ); if( err ) { TRACFCOMP(g_trac_vpd,"IpVpdFacade::loadPnor() Error reading record %s",(*it).record_name); @@ -858,6 +856,43 @@ errlHndl_t IpVpdFacade::findRecordOffset ( const char * i_record, { errlHndl_t err = NULL; + // Look for a record override in our image unless explicitly told not to + if( (i_args.location & VPD::OVERRIDE_MASK) != VPD::USEVPD ) + { + uint8_t* l_overridePtr = nullptr; + VPD::RecordTargetPair_t l_recTarg = + VPD::makeRecordTargetPair(i_record,i_target); + + // Check if we already figured out where to get this record from + VPD::OverrideMap_t::iterator l_overItr = iv_overridePtr.find(l_recTarg); + if( l_overItr != iv_overridePtr.end() ) + { + l_overridePtr = l_overItr->second; + } + else + { + // Now go see if we should be using the override and if so + // where we find the right copy + err = checkForRecordOverride(i_record,i_target,l_overridePtr); + if( err ) + { + TRACFCOMP( g_trac_vpd, ERR_MRK"findRecordOffset> failure calling checkForRecordOverride for %s on %.8X", + i_record, get_huid(i_target) ); + return err; + } + + TRACFCOMP( g_trac_vpd, INFO_MRK" Record %s for target 0x%.8X exists at %p in PNOR", + i_record, get_huid(i_target), l_overridePtr ); + } + + // If we have an override, the record is already pointed at directly + if( l_overridePtr != nullptr ) + { + o_offset = 0; + return nullptr; + } + } + // Determine the VPD source (PNOR/SEEPROM) VPD::vpdCmdTarget vpdSource = VPD::AUTOSELECT; bool configError = false; @@ -940,17 +975,17 @@ bool IpVpdFacade::hasVpdPresent( TARGETING::Target * i_target, uint16_t recordOffset = 0x0; input_args_t i_args; bool vpdPresent = false; - const char * recordName = NULL; - const char * keywordName = NULL; + const char * l_recordName = NULL; + const char * l_keywordName = NULL; i_args.record = i_record; i_args.keyword = i_keyword; do { - //get the Recod/Keyword names + //get the Record/Keyword names err = translateRecord( i_args.record, - recordName ); + l_recordName ); if( err ) { @@ -960,7 +995,7 @@ bool IpVpdFacade::hasVpdPresent( TARGETING::Target * i_target, } err = translateKeyword( i_args.keyword, - keywordName ); + l_keywordName ); if( err ) { @@ -969,10 +1004,10 @@ bool IpVpdFacade::hasVpdPresent( TARGETING::Target * i_target, break; } - vpdPresent = recordPresent( recordName, + vpdPresent = recordPresent( l_recordName, recordOffset, i_target, - VPD::AUTOSELECT ); + VPD::USEVPD ); }while( 0 ); @@ -996,7 +1031,7 @@ bool IpVpdFacade::recordPresent( const char * i_record, { errlHndl_t err = NULL; uint64_t tmpOffset = 0x0; - char record[RECORD_BYTE_SIZE] = { '\0' }; + char l_record[RECORD_BYTE_SIZE] = { '\0' }; bool matchFound = false; do @@ -1018,9 +1053,10 @@ bool IpVpdFacade::recordPresent( const char * i_record, //Read Record Name err = fetchData( tmpOffset, RECORD_BYTE_SIZE, - record, + l_record, i_target, - i_location ); + i_location, + i_record ); tmpOffset += RECORD_BYTE_SIZE; if( err ) @@ -1028,7 +1064,7 @@ bool IpVpdFacade::recordPresent( const char * i_record, break; } - if( !(memcmp(record, i_record, RECORD_BYTE_SIZE )) ) + if( !(memcmp(l_record, i_record, RECORD_BYTE_SIZE )) ) { matchFound = true; @@ -1037,7 +1073,8 @@ bool IpVpdFacade::recordPresent( const char * i_record, RECORD_ADDR_BYTE_SIZE, &o_offset, i_target, - i_location ); + i_location, + i_record ); if( err ) { break; @@ -1485,7 +1522,8 @@ errlHndl_t IpVpdFacade::retrieveKeyword ( const char * i_keywordName, keywordSize, io_buffer, i_target, - i_args.location ); + i_args.location, + i_recordName ); if( err ) { break; @@ -1525,7 +1563,8 @@ errlHndl_t IpVpdFacade::retrieveRecord( const char * i_recordName, sizeof(l_size), &l_size, i_target, - i_args.location ); + i_args.location, + i_recordName ); if( err ) { @@ -1557,7 +1596,8 @@ errlHndl_t IpVpdFacade::retrieveRecord( const char * i_recordName, l_size, io_buffer, i_target, - i_args.location ); + i_args.location, + i_recordName ); if( err ) { break; @@ -1581,7 +1621,8 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr, size_t i_numBytes, void * o_data, TARGETING::Target * i_target, - VPD::vpdCmdTarget i_location ) + VPD::vpdCmdTarget i_location, + const char* i_record ) { errlHndl_t err = NULL; @@ -1594,12 +1635,58 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr, i_location, vpdSource ); + // Look for a record override in our image unless explicitly told not to + bool l_foundOverride = false; + if( (i_location & VPD::OVERRIDE_MASK) != VPD::USEVPD ) + { + uint8_t* l_overridePtr = nullptr; + VPD::RecordTargetPair_t l_recTarg = + VPD::makeRecordTargetPair(i_record,i_target); + + // At this point we can assume that the pointer is set into our + // map if we need it + VPD::OverrideMap_t::iterator l_overItr = iv_overridePtr.find(l_recTarg); + if( l_overItr != iv_overridePtr.end() ) + { + l_overridePtr = l_overItr->second; + + // Just do a simple memcpy + if( l_overridePtr != nullptr ) + { + memcpy( o_data, l_overridePtr+i_byteAddr, i_numBytes ); + l_foundOverride = true; + } + } + // Automatically populate a bunch of infrastructure records that + // we would never override (makes the error checks pass cleaner) + else if( (0 == memcmp( i_record, "VHDR", 4 )) + || (0 == memcmp( i_record, "VTOC", 4 )) ) + { + iv_overridePtr[l_recTarg] = nullptr; + } + else + { + TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::fetchData: " + "iv_overridePtr is not set as expected for %s on %.8X", + i_record, TARGETING::get_huid(i_target) ); + for( auto l_over : iv_overridePtr ) + { + TRACFCOMP( g_trac_vpd, "%.8X : %.8X = %p", + TARGETING::get_huid((l_over.first).second), + (l_over.first).first, + l_over.second ); + } + assert( false, + "iv_overridePtr is not set inside IpVpdFacade::fetchData" ); + } + } + // Get the data - if ( vpdSource == VPD::PNOR ) + if ( (vpdSource == VPD::PNOR) && !l_foundOverride ) { err = fetchDataFromPnor( i_byteAddr, i_numBytes, o_data, i_target ); } - else if ( vpdSource == VPD::SEEPROM ) + else if ( (vpdSource == VPD::SEEPROM) && !l_foundOverride ) { err = fetchDataFromEeprom( i_byteAddr, i_numBytes, o_data, i_target ); } @@ -1608,7 +1695,7 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr, configError = true; } - if( configError ) + if( configError && !l_foundOverride ) { TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::fetchData: " "Error resolving VPD source (PNOR/SEEPROM)"); @@ -1738,9 +1825,12 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, int matchesFound = 0; TRACSSCOMP( g_trac_vpd, - ENTER_MRK"IpVpdFacade::findKeywordAddr(%s, %s, . . .)", + ENTER_MRK"IpVpdFacade::findKeywordAddr(%s, %s, %d, %d, %.8X )", i_keywordName, - i_recordName ); + i_recordName, + i_offset, + i_index, + TARGETING::get_huid(i_target) ); do { @@ -1749,31 +1839,14 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, RECORD_ADDR_BYTE_SIZE, &recordSize, i_target, - i_args.location ); + i_args.location, + i_recordName ); offset += RECORD_ADDR_BYTE_SIZE; if( err ) { break; } - if((iv_pnorSection == PNOR::MEMD)) - { - static uint64_t l_basePnorAddr = 0;//getPnorAddr(*this); - uint64_t l_cache_address = 0; - - if((iv_cachePnorAddr !=0) && !(iv_memdAccessed)) - { - l_basePnorAddr = getPnorAddr(*this); - iv_memdAccessed = true; - } - - TARGETING::ATTR_MEMD_OFFSET_type l_memd_offset = - i_target->getAttr<TARGETING::ATTR_MEMD_OFFSET>(); - l_cache_address = l_basePnorAddr + - MEMD_HEADER_SIZE + l_memd_offset; - setPnorAddr(l_cache_address); - } - // Byte Swap recordSize = le16toh( recordSize ); @@ -1784,7 +1857,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, RECORD_BYTE_SIZE, record, i_target, - i_args.location ); + i_args.location, + i_recordName ); // If we were looking for the Record Type (RT) keyword, we are done. if (memcmp( i_keywordName, "RT", KEYWORD_BYTE_SIZE ) == 0) { @@ -1809,10 +1883,11 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, if( memcmp( record, i_recordName, RECORD_BYTE_SIZE ) ) { TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::findKeywordAddr: " - "Record(%s) for offset (0x%04x) did not match " + "Record(%s) for offset (0x%04x->0x%04x) did not match " "expected record(%s)!", record, i_offset, + offset, i_recordName ); /*@ @@ -1866,7 +1941,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, KEYWORD_BYTE_SIZE, keyword, i_target, - i_args.location ); + i_args.location, + i_recordName ); offset += KEYWORD_BYTE_SIZE; if( err ) @@ -1894,7 +1970,8 @@ errlHndl_t IpVpdFacade::findKeywordAddr ( const char * i_keywordName, keywordLength, &keywordSize, i_target, - i_args.location ); + i_args.location, + i_recordName ); offset += keywordLength; if( err ) @@ -2055,6 +2132,52 @@ errlHndl_t IpVpdFacade::writeKeyword ( const char * i_keywordName, i_args.location, vpdDest ); + // Look for a record override in our image unless explicitly told not to + if( (i_args.location & VPD::OVERRIDE_MASK) != VPD::USEVPD ) + { + uint8_t* l_overridePtr = nullptr; + VPD::RecordTargetPair_t l_recTarg + = VPD::makeRecordTargetPair(i_recordName,i_target); + + // At this point we can assume that the pointer is set into our + // map if we need it + VPD::OverrideMap_t::iterator l_overItr = iv_overridePtr.find(l_recTarg); + if( l_overItr != iv_overridePtr.end() ) + { + // If we are using an override, we can't write to it + if( l_overridePtr != nullptr ) + { + uint32_t l_kw = 0; + memcpy( &l_kw, i_keywordName, KEYWORD_BYTE_SIZE ); + /*@ + * @errortype + * @reasoncode VPD::VPD_CANNOT_WRITE_OVERRIDDEN_VPD + * @moduleid VPD::VPD_IPVPD_WRITE_KEYWORD + * @userdata1[0:31] Target HUID + * @userdata1[32:63] <unused> + * @userdata2[0:31] VPD Record (ASCII) + * @userdata2[32:63] VPD Keyword (ASCII) + * @devdesc Attempting to write to a VPD record + * that has been overridden by firmware + * @custdesc Firmware error writing VPD + */ + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_IPVPD_WRITE_KEYWORD, + VPD::VPD_WRITE_DEST_UNRESOLVED, + TWO_UINT32_TO_UINT64( + TARGETING::get_huid(i_target), + 0 ), + TWO_UINT32_TO_UINT64( + l_recTarg.first, + l_kw), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT ); + err->collectTrace( "VPD", 256 ); + break; + } + } + } + // Write the data if ( vpdDest == VPD::PNOR ) { @@ -2119,7 +2242,7 @@ errlHndl_t IpVpdFacade::writeKeyword ( const char * i_keywordName, if( configError ) { - TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::fetchData: " + TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::writeKeyword: " "Error resolving VPD source (PNOR/SEEPROM)"); /*@ @@ -2270,3 +2393,230 @@ void IpVpdFacade::getRecordLists( o_altRecSize = 0; } +/** + * @brief Callback function to check for a record override + */ +errlHndl_t IpVpdFacade::checkForRecordOverride( const char* i_record, + TARGETING::Target* i_target, + uint8_t*& o_ptr ) +{ + // by default there is not an override + o_ptr = nullptr; + TRACDCOMP( g_trac_vpd, "No override for %s on %.8X", i_record, TARGETING::get_huid(i_target) ); + VPD::RecordTargetPair_t l_recTarg = + VPD::makeRecordTargetPair(i_record,i_target); + iv_overridePtr[l_recTarg] = nullptr; + return nullptr; +} + +/** + * @brief Retrieves the MEMD record from PNOR, finds a matching + * set of data, and sets up sets up the override pointer. + */ +errlHndl_t IpVpdFacade::getMEMDFromPNOR( input_args_t i_recKw, + TARGETING::Target* i_target, + uint32_t i_vmMask ) +{ + TRACFCOMP(g_trac_vpd,ENTER_MRK"IpVpdFacade::getMEMDFromPNOR( %d, %.8X )", + i_recKw.record, get_huid(i_target)); + errlHndl_t l_errl = nullptr; + + /** + * @brief Define the set of information included at the beginning of the + * MEMD PNOR section + */ + struct MemdHeader_t + { + uint32_t eyecatch; /* Eyecatch to determine validity. "OKOK" */ + uint32_t header_version; /* What version of the header this is in */ + uint32_t memd_version; /* What version of the MEMD this includes */ + uint32_t expected_size_k; /* Size in thousands (not KB) of each MEMD instance */ + uint16_t expected_num; /* Number of MEMD instances in this section */ + uint8_t padding[14]; /* Padding for future changes */ + }__attribute__((packed)); + + enum MEMD_valid_constants + { + MEMD_VALID_HEADER = 0x4f4b4f4b, // "OKOK" + MEMD_VALID_HEADER_VERSION = 0x30312e30, // "01.0"; + }; + + do + { + // Get the Record/keyword names + const char* l_record = nullptr; + l_errl = translateRecord( i_recKw.record, + l_record ); + if( l_errl ) + { + break; + } + + const char* l_keyword = nullptr; + l_errl = translateKeyword( i_recKw.keyword, + l_keyword ); + if( l_errl ) + { + break; + } + + VPD::RecordTargetPair_t l_recTarg = + VPD::makeRecordTargetPair(l_record,i_target); + + // MEMD Processing +#ifdef __HOSTBOOT_RUNTIME + uint64_t l_memdSize = 0; + uint64_t l_memd_addr = hb_get_rt_rsvd_mem( + Util::HBRT_MEM_LABEL_VPD_MEMD, + 0, + l_memdSize ); + if( (l_memd_addr == 0) || (l_memdSize == 0) ) + { + TRACFCOMP(g_trac_vpd,"Optional MEMD section not found in reserved mem."); + break; + } + + uint8_t* l_memd_vaddr + = reinterpret_cast<uint8_t *>(l_memd_addr); +#else + PNOR::SectionInfo_t l_memd_info; + l_errl = PNOR::getSectionInfo(PNOR::MEMD,l_memd_info); + if( l_errl ) + { + TRACFCOMP(g_trac_vpd,"Optional MEMD section not found in PNOR."); + delete l_errl; + l_errl = nullptr; + iv_overridePtr[l_recTarg] = nullptr; + break; + } + + uint8_t* l_memd_vaddr + = reinterpret_cast<uint8_t *>(l_memd_info.vaddr); +#endif + + TRACFCOMP(g_trac_vpd,"MEMD is at %p", l_memd_vaddr); + + // Get and process the header + MemdHeader_t l_header; + memcpy(&l_header, l_memd_vaddr, sizeof(l_header)); + TRACFBIN(g_trac_vpd,"MEMD Header", &l_header, sizeof(l_header)); + + // See if we have any valid override records + bool l_valid_memd = ((l_header.eyecatch == MEMD_VALID_HEADER) & + (l_header.header_version == MEMD_VALID_HEADER_VERSION) & + ( (l_header.memd_version == l_recTarg.first) + // also handle old version to avoid coreqs + || (l_header.memd_version == MEMD_VALID_HEADER_VERSION) )); + if( !l_valid_memd ) + { + TRACFCOMP(g_trac_vpd,"MEMD is not valid, ignoring it"); + iv_overridePtr[l_recTarg] = nullptr; + break; + } + + // Get the VM keyword size from the real VPD + size_t l_vm_size = 0; + input_args_t l_vm_args = i_recKw; + l_vm_args.location = VPD::USEVPD; + l_errl = read( i_target, nullptr, l_vm_size, l_vm_args ); + if( l_errl ) + { + TRACFCOMP(g_trac_vpd,"ERROR getting MEMD VM size"); + break; + } + + // VM should be exactly 4 bytes long + uint32_t l_vm_kw = 0; + assert( l_vm_size == sizeof(l_vm_kw) ); + + // Get the VM keyword from the real VPD + l_errl = read( i_target, &l_vm_kw, l_vm_size, l_vm_args ); + if( l_errl ) + { + TRACFCOMP(g_trac_vpd,"ERROR getting DVPD VM keyword"); + break; + } + TRACFCOMP(g_trac_vpd,"VPD VM = %.8X", l_vm_kw); + + // Offset past the header to start with + uint16_t l_memd_offset = sizeof(MemdHeader_t); + bool l_found_match = false; + + // Loop through each possible instance until we find a match or run out + for( auto l_inst = 0; l_inst < l_header.expected_num; ++l_inst ) + { + // Get the VM keyword from the copy in PNOR + TRACFCOMP(g_trac_vpd,"Attempting to read MEMD VM keyword from override"); + input_args_t l_pnor_args = i_recKw; + l_pnor_args.location = VPD::USEOVERRIDE; + + // Set the ptr in the map to allow the lookups inside + // IpVpdFacade to work + iv_overridePtr[l_recTarg] = l_memd_vaddr + l_memd_offset; + + uint32_t l_memd_vm = 0; + l_errl = retrieveKeyword( l_keyword, l_record, + 0, 0, + i_target, + &l_memd_vm, l_vm_size, + l_pnor_args ); + if(l_errl) + { + TRACFCOMP(g_trac_vpd,"getMEMDFromPNOR: ERROR getting %s:%s keyword in slot %d", l_record, l_keyword, l_inst); + // if we got this using the legacy header version then it is + // because we are looking at a bunch of the wrong record + // type, so just move on + if( l_header.memd_version == MEMD_VALID_HEADER_VERSION ) + { + delete l_errl; + l_errl = nullptr; + } + break; + } + + // Compare the appropriate portion of VM + if( (l_memd_vm != 0) && + ((l_vm_kw & i_vmMask) == (l_memd_vm & i_vmMask)) ) + { + TRACFCOMP(g_trac_vpd,"Matching data was found in PNOR at %.llX. VM: PNOR=%.8X, VPD=%.8X", + l_memd_offset, + l_memd_vm, + l_vm_kw); + l_found_match = true; + break; + } + + // VM's don't match, we need to keep looking + TRACFCOMP(g_trac_vpd,"No match. VM: PNOR=%.8X, VPD=%.8X", + l_memd_vm, + l_vm_kw ); + l_memd_offset += (l_header.expected_size_k * 1000); + } + if( l_errl ) { break; } + + // If we did not find a match, set our map back to a nullptr + if( !l_found_match ) + { + iv_overridePtr[l_recTarg] = nullptr; + } + } while(0); + + TRACFCOMP(g_trac_vpd,EXIT_MRK"getMEMDFromPNOR()"); + return l_errl; +} + +#ifdef CONFIG_SECUREBOOT +/** + * @brief Load/unload the appropriate secure section for + * an overriden PNOR section + */ +errlHndl_t IpVpdFacade::loadUnloadSecureSection( input_args_t i_args, + TARGETING::Target* i_target, + bool i_load, + bool& o_loaded ) +{ + // nothing to do by default + o_loaded = false; + return nullptr; +} +#endif diff --git a/src/usr/vpd/ipvpd.H b/src/usr/vpd/ipvpd.H index 4797cb317..597c6e256 100644 --- a/src/usr/vpd/ipvpd.H +++ b/src/usr/vpd/ipvpd.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -28,10 +28,13 @@ #include <list> +#include <map> #include <pnor/pnorif.H> #include <devicefw/driverif.H> +#include <config.h> #include "vpd.H" + /** @file ipvpd.H * @brief Provides base support for i/p-Series style IBM VPD */ @@ -84,8 +87,7 @@ class IpVpdFacade } input_args_t; /** - * @brief Structure of information needed to access requested - * record/keyword combinations. + * @brief Mapping from keyword enum into 4 character string */ typedef struct { @@ -94,6 +96,7 @@ class IpVpdFacade } recordInfo; /** + * @brief Mapping from keyword enum into 2 character string */ typedef struct { @@ -102,6 +105,16 @@ class IpVpdFacade } keywordInfo; /** + * @brief Mapping from record enum into PNOR section + * where override might be + */ + typedef struct + { + VPD::vpdRecord record; + PNOR::SectionId section; + } recordOverrideInfo_t; + + /** * @brief Structure defining where to read/write VPD data */ typedef struct @@ -138,7 +151,7 @@ class IpVpdFacade * * @param[in] i_vpdKeywords - Pointer to array of VPD Keywords to use * - * @param[in] i_keyCount - size of i_vpdKeywords array + * @param[in] i_keySize - size of i_vpdKeywords array * * @param[in] i_pnorSection - PNOR Section containing VPD for current * chip @@ -293,6 +306,23 @@ class IpVpdFacade */ void setConfigFlagsHW ( ); +#ifdef CONFIG_SECUREBOOT + /** + * @brief Load/unload the appropriate secure section for + * an overriden PNOR section + * @param[in] i_args Record/keyword + * @param[in] i_target Target pointer + * @param[in] i_load true=load, false=unload + * @param[out] o_loaded true=section loaded, false=section not loaded + * @return Error log + */ + virtual errlHndl_t loadUnloadSecureSection( input_args_t i_args, + TARGETING::Target* i_target, + bool i_load, + bool& o_loaded ); +#endif + + protected: /** @@ -578,6 +608,8 @@ class IpVpdFacade * * @param[in] i_location - VPD location to fetch data from (PNOR/SEEPROM) * + * @param[in] i_record - String representation of the record. + * * @return errHndl_t - NULL if successful, otherwise a pointer to the * error log. */ @@ -585,7 +617,8 @@ class IpVpdFacade size_t i_numBytes, void * o_data, TARGETING::Target * i_target, - VPD::vpdCmdTarget i_location ); + VPD::vpdCmdTarget i_location, + const char* i_record ); /** * @brief This function actually reads the data from PNOR @@ -625,8 +658,7 @@ class IpVpdFacade void * o_data, TARGETING::Target * i_target ); - - /** + /** * @brief This function compares 2 ipvpd record values. Used for binary * search to find a match. * @@ -688,6 +720,51 @@ class IpVpdFacade const recordInfo* & o_altVpdRecords, uint64_t & o_altRecSize); + /** + * @brief Returns the cached pnor address + * + */ + inline static uint64_t getPnorAddr(const IpVpdFacade& x) + { + return x.iv_cachePnorAddr; + }; + + /** + * @brief Set the cached pnor address to the given value + * + */ + inline void setPnorAddr(uint64_t i_pnorAddr) + { + this->iv_cachePnorAddr = i_pnorAddr; + }; + + + /** + * @brief Retrieves the MEMD record from PNOR, finds a matching + * set of data, and sets up sets up the override pointer. + * @param[in] i_recKw Record/Keyword values + * @param[in] i_target Relevant Target + * @param[in] i_vmMask Specific bits to compare with EEPROM + * @return Error log + */ + errlHndl_t getMEMDFromPNOR( input_args_t i_recKw, + TARGETING::Target* i_target, + uint32_t i_vmMask ); + + /** + * @brief Callback function to check for a record override and + * set iv_overridePtr appropriately + * @param[in] i_record Record name + * @param[in] i_target Target pointer + * @param[out] o_ptr Pointer to location of record in PNOR, + * ==nullptr if there is no override + * @return Error log + */ + virtual errlHndl_t checkForRecordOverride( const char* i_record, + TARGETING::Target* i_target, + uint8_t*& o_ptr ); + + protected: // Variables /** @@ -702,8 +779,7 @@ class IpVpdFacade */ uint64_t iv_vpdMaxSections; - - public: // Variables + public: //Used by static function /** * @brief Pointer to array of VPD Record information * @@ -711,30 +787,12 @@ class IpVpdFacade const recordInfo* iv_vpdRecords; /** - * @brief Returns the cached pnor address - * - */ - inline static uint64_t getPnorAddr(const IpVpdFacade& x) - { - return x.iv_cachePnorAddr; - } - - /** - * @brief Set the cached pnor address to the given value - * - */ - inline void setPnorAddr(uint64_t i_pnorAddr) - { - this->iv_cachePnorAddr = i_pnorAddr; - } - - /** * @brief Number of VPD Records for current chip * */ - uint64_t iv_recSize; + const uint64_t iv_recSize; - protected: // Variables + protected: /** * @brief Pointer to array of VPD Keyword information * @@ -745,7 +803,7 @@ class IpVpdFacade * @brief Number of VPD Keywords for current chip * */ - uint64_t iv_keySize; + const uint64_t iv_keySize; /** * @brief PNOR section enum for vpd type @@ -778,10 +836,11 @@ class IpVpdFacade configInfo iv_configInfo; /** - * @brief Boolean variable to denote if the pnor section was - * accessed for the MEMD section + * @brief Used to denote if a record is being + * fetched from a copy in our code image versus the + * real VPD EEPROM (or cache) */ - bool iv_memdAccessed; + VPD::OverrideMap_t iv_overridePtr; }; diff --git a/src/usr/vpd/memd_vpd.C b/src/usr/vpd/memd_vpd.C deleted file mode 100644 index 08f122d03..000000000 --- a/src/usr/vpd/memd_vpd.C +++ /dev/null @@ -1,228 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/vpd/memd_vpd.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ -/* [+] 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 */ -// ---------------------------------------------- -// Includes -// ---------------------------------------------- -#include <string.h> -#include <endian.h> -#include <trace/interface.H> -#include <errl/errlentry.H> -#include <errl/errlmanager.H> -#include <targeting/common/targetservice.H> -#include <targeting/common/util.H> -#include <targeting/common/utilFilter.H> -#include <devicefw/driverif.H> -#include <vfs/vfs.H> -#include <vpd/vpdreasoncodes.H> -#include <vpd/memd_vpdenums.H> -#include <vpd/vpd_if.H> -#include <i2c/eepromif.H> -#include <config.h> -#include "memd_vpd.H" -#include "cvpd.H" -#include "vpd.H" -#include "pvpd.H" -#include <initservice/initserviceif.H> - -// ---------------------------------------------- -// Trace definitions -// ---------------------------------------------- -extern trace_desc_t* g_trac_vpd; - - -// ------------------------ -// Macros for unit testing -//#define TRACUCOMP(args...) TRACFCOMP(args) -#define TRACUCOMP(args...) -//#define TRACSSCOMP(args...) TRACFCOMP(args) -#define TRACSSCOMP(args...) - -namespace MEMD_VPD -{ - // ---------------------------------------------- - // Globals - // ---------------------------------------------- - mutex_t g_mutex = MUTEX_INITIALIZER; - - - /** - * @brief This function will perform the steps required to do a read from - * the Hostboot MEMD_VPD data. - * - * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in - * driververif.H - * - * @param[in] i_target - Processor Target device - * - * @param [in/out] io_buffer - Pointer to the data that was read from - * the target device. This parameter, when set to NULL, will return - * the keyword size value in io_buflen. - * - * @param [in/out] io_buflen - Length of the buffer to be read or written - * to/from the target. This value should indicate the size of the - * io_buffer parameter that has been allocated. Being returned it - * will indicate the number of valid bytes in the buffer being - * returned. This parameter will contain the size of a keyword when - * the io_buffer parameter is passed in NULL. - * - * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in - * usrif.H - * - * @param [in] i_args - This is an argument list for the device driver - * framework. - * - * @return errlHndl_t - NULL if successful, otherwise a pointer to the - * error log. - */ - errlHndl_t MEMD_VPDRead ( DeviceFW::OperationType i_opType, - TARGETING::Target * i_target, - void * io_buffer, - size_t & io_buflen, - int64_t i_accessType, - va_list i_args ) - { - errlHndl_t err = NULL; - IpVpdFacade::input_args_t args; - args.record = ((MEMD_VPDRecord)va_arg( i_args, uint64_t )); - args.keyword = ((MEMD_VPDKeyword)va_arg( i_args, uint64_t )); - args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t )); - - TRACSSCOMP( g_trac_vpd, - ENTER_MRK"MEMD_VPDRead()" ); - - err = Singleton<MEMD_VpdFacade>::instance().read(i_target, - io_buffer, - io_buflen, - args); - - return err; - } - - - /** - * @brief This function will perform the steps required to do a write to - * the Hostboot MEMD_VPD data. - * - * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in - * driververif.H - * - * @param[in] i_target - Processor Target device - * - * @param [in/out] io_buffer - Pointer to the data that was read from - * the target device. It will also be used to contain data to - * be written to the device. - * - * @param [in/out] io_buflen - Length of the buffer to be read or written - * to/from the target. This value should indicate the size of the - * io_buffer parameter that has been allocated. Being returned it - * will indicate the number of valid bytes in the buffer being - * returned. - * - * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in - * usrif.H - * - * @param [in] i_args - This is an argument list for the device driver - * framework. - * - * @return errlHndl_t - NULL if successful, otherwise a pointer to the - * error log. - */ - errlHndl_t MEMD_VPDWrite ( DeviceFW::OperationType i_opType, - TARGETING::Target * i_target, - void * io_buffer, - size_t & io_buflen, - int64_t i_accessType, - va_list i_args ) - { - errlHndl_t err = NULL; - IpVpdFacade::input_args_t args; - args.record = ((MEMD_VPDRecord)va_arg( i_args, uint64_t )); - args.keyword = ((MEMD_VPDKeyword)va_arg( i_args, uint64_t )); - args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t )); - - TRACSSCOMP( g_trac_vpd, - ENTER_MRK"MEMD_VPDWrite()" ); - - - err = Singleton<MEMD_VpdFacade>::instance().write(i_target, - io_buffer, - io_buflen, - args); - - return err; - } - - // Register with the routing code - DEVICE_REGISTER_ROUTE( DeviceFW::READ, - DeviceFW::MEMD_VPD, - TARGETING::TYPE_MCS, - MEMD_VPDRead ); - DEVICE_REGISTER_ROUTE( DeviceFW::WRITE, - DeviceFW::MEMD_VPD, - TARGETING::TYPE_MCS, - MEMD_VPDWrite ); - -}; // end namespace MEMD_VPD - - -//MEMD_VpdFacade Class Functions -/** - * @brief Constructor - * Planar VPD is included in the Centaur PNOR section. - * Including with Centaur vpd minimizes the number of PNOR sections. - */ -MEMD_VpdFacade::MEMD_VpdFacade() : -IpVpdFacade(MEMD_VPD::MEMD_VPDRecords, - (sizeof(MEMD_VPD::MEMD_VPDRecords)/sizeof( - MEMD_VPD::MEMD_VPDRecords[0])), - MEMD_VPD::MEMD_VPDKeywords, - (sizeof(MEMD_VPD::MEMD_VPDKeywords)/sizeof( - MEMD_VPD::MEMD_VPDKeywords[0])), - PNOR::MEMD, // note use of MEMD - MEMD_VPD::g_mutex, - VPD::VPD_INVALID) // Direct access memory -{ - TRACUCOMP(g_trac_vpd, "MEMD_VpdFacade::MEMD_VpdFacade> " ); - - iv_configInfo.vpdReadPNOR = true; - iv_configInfo.vpdReadHW = false; - iv_configInfo.vpdWritePNOR = false; - iv_configInfo.vpdWriteHW = false; - iv_vpdSectionSize = MEMD_VPD::SECTION_SIZE; - iv_vpdMaxSections = MEMD_VPD::MAX_SECTIONS; -} - -/** - * @brief returns true if the record is present in this facade. - * this will always return true in this function - */ -bool MEMD_VpdFacade::recordPresent( const char * i_record, - uint16_t & offset, - TARGETING::Target * i_target, - VPD::vpdCmdTarget i_location ) -{ - offset = 0; - return true; -} diff --git a/src/usr/vpd/memd_vpd.H b/src/usr/vpd/memd_vpd.H deleted file mode 100644 index d94532b4a..000000000 --- a/src/usr/vpd/memd_vpd.H +++ /dev/null @@ -1,227 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/vpd/memd_vpd.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ -/* [+] 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 __MEMD_VPD_H -#define __MEMD_VPD_H - - -/** - * @file MEMD_VPD.H - * - * @brief Provides the interfaces for the MEMD_VPD device driver - * - */ - -// ---------------------------------------------- -// Includes -// ---------------------------------------------- -#include <errl/errlentry.H> -#include <vpd/memd_vpdenums.H> - -#include "ipvpd.H" -#include <config.h> - -namespace MEMD_VPD -{ - - enum - { - MAX_SECTIONS = 1, - SECTION_SIZE = 0x6000, - }; - - - /** - * @brief Conversion of MEMD_VPD Records to corresponding character - * representation. - */ - const IpVpdFacade::recordInfo MEMD_VPDRecords[] = - { - // ------------------------------------------------------------------- - // NOTE: This list must remain an ordered list! There is a - // testcase that checks this. When adding new entries to the - // list, be sure that the keyword in each entry (value 0) - // are in ascending order. - // ------------------------------------------------------------------- - { MEMD, "MEMD" }, - - // ------------------------------------------------------------------- - // DO NOT USE!! This is for test purposes ONLY! - { MEMD_VPD_TEST_RECORD, "TEST" }, - // ------------------------------------------------------------------- - }; - - /** - * @brief Conversion of MEMD_VPD Keywords to corresponding character - * representation. - */ - const IpVpdFacade::keywordInfo MEMD_VPDKeywords[] = - { - // ------------------------------------------------------------------- - // NOTE: This list must remain an ordered list! There is a - // testcase that checks this. When adding new entries to - // the list, be sure that the keyword in each entry (value 0) - // are in ascending order. - // ------------------------------------------------------------------- - { B3, "B3" }, - { B4, "B4" }, - { B7, "B7" }, - { CC, "CC" }, - { CE, "CE" }, - { CT, "CT" }, - { DR, "DR" }, - { FC, "FC" }, - { FN, "FN" }, - { HE, "HE" }, - { HW, "HW" }, - { I2, "I2" }, - { IN, "IN" }, - { J0, "J0" }, - { J1, "J1" }, - { J2, "J2" }, - { J3, "J3" }, - { J4, "J4" }, - { J5, "J5" }, - { J6, "J6" }, - { J7, "J7" }, - { J8, "J8" }, - { J9, "J9" }, - { JA, "JA" }, - { JB, "JB" }, - { JC, "JC" }, - { JD, "JD" }, - { JE, "JE" }, - { JF, "JF" }, - { JG, "JG" }, - { JH, "JH" }, - { JI, "JI" }, - { JJ, "JJ" }, - { JK, "JK" }, - { JL, "JL" }, - { JM, "JM" }, - { JN, "JN" }, - { JO, "JO" }, - { JP, "JP" }, - { JQ, "JQ" }, - { JR, "JR" }, - { JS, "JS" }, - { JT, "JT" }, - { JU, "JU" }, - { JV, "JV" }, - { JW, "JW" }, - { JX, "JX" }, - { JY, "JY" }, - { JZ, "JZ" }, - { LX, "LX" }, - { MR, "MR" }, - { MT, "MT" }, - { PF, "PF" }, - { PN, "PN" }, - { PR, "PR" }, - { RB, "RB" }, - { RG, "RG" }, - { RT, "RT" }, - { SE, "SE" }, - { SN, "SN" }, - { SO, "SO" }, - { TM, "TM" }, - { VM, "VM" }, - { VZ, "VZ" }, - { X0, "X0" }, - { X1, "X1" }, - { X2, "X2" }, - { X3, "X3" }, - { X4, "X4" }, - { X5, "X5" }, - { X6, "X6" }, - { X7, "X7" }, - { X8, "X8" }, - { X9, "X9" }, - { XA, "XA" }, - { XB, "XB" }, - { XC, "XC" }, - { XD, "XD" }, - { XE, "XE" }, - { XF, "XF" }, - { XG, "XG" }, - { XH, "XH" }, - { XI, "XI" }, - { XJ, "XJ" }, - { XK, "XK" }, - { XL, "XL" }, - { XM, "XM" }, - { XN, "XN" }, - { XO, "XO" }, - { XP, "XP" }, - { XQ, "XQ" }, - { XR, "XR" }, - { XS, "XS" }, - { XT, "XT" }, - { XU, "XU" }, - { XV, "XV" }, - { XW, "XW" }, - { XX, "XX" }, - { XY, "XY" }, - { XZ, "XZ" }, - { Q0, "Q0" }, - { Q1, "Q1" }, - { Q2, "Q2" }, - { Q3, "Q3" }, - { Q4, "Q4" }, - { Q5, "Q5" }, - { Q6, "Q6" }, - { Q7, "Q7" }, - { Q8, "Q8" }, - { CK, "CK" }, - - // ------------------------------------------------------------------- - // DO NOT USE!! This is for test purposes ONLY! - { MEMD_VPD_TEST_KEYWORD, "ZZ" }, - // ------------------------------------------------------------------- - - //Common ipvpd - { FULL_RECORD, "FL"}, - }; - -}; // end MEMD_VPD namespace - -class MEMD_VpdFacade: public IpVpdFacade -{ - public: - - /** - * @brief Constructor - */ - MEMD_VpdFacade( ); - - - protected: - virtual bool recordPresent( const char * i_record, - uint16_t & offset, - TARGETING::Target * i_target, - VPD::vpdCmdTarget i_location ); - - -}; -#endif // __MEMD_VPD_H diff --git a/src/usr/vpd/test/dvpdtest.H b/src/usr/vpd/test/dvpdtest.H index e7c61cdd2..b0d62a062 100755 --- a/src/usr/vpd/test/dvpdtest.H +++ b/src/usr/vpd/test/dvpdtest.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -37,6 +37,7 @@ #include <errl/errlentry.H> #include <devicefw/driverif.H> #include <targeting/common/predicates/predicatectm.H> +#include <config.h> #include <vpd/dvpdenums.H> #include <vpd/vpdreasoncodes.H> @@ -204,6 +205,7 @@ class DVPDTest: public CxxTest::TestSuite /** * @brief This function will test DVPD writes. + * Note: this forces the path to not use the FW override */ void testDvpdWrite ( void ) { @@ -234,7 +236,9 @@ class DVPDTest: public CxxTest::TestSuite err = deviceRead( theTarget, testData, theSize, - DEVICE_DVPD_ADDRESS(DVPD::MEMD,TSTKEYWD) ); + DEVICE_DVPD_FORCE_ADDRESS(DVPD::MEMD, + TSTKEYWD, + VPD::USEVPD) ); if( err ) { fails++; @@ -254,7 +258,9 @@ class DVPDTest: public CxxTest::TestSuite err = deviceRead( theTarget, origData, theSize, - DEVICE_DVPD_ADDRESS(DVPD::MEMD,TSTKEYWD) ); + DEVICE_DVPD_FORCE_ADDRESS(DVPD::MEMD, + TSTKEYWD, + VPD::USEVPD) ); if( err ) { fails++; @@ -282,7 +288,9 @@ class DVPDTest: public CxxTest::TestSuite err = deviceWrite( theTarget, testData, theSize, - DEVICE_DVPD_ADDRESS(DVPD::MEMD,TSTKEYWD) ); + DEVICE_DVPD_FORCE_ADDRESS(DVPD::MEMD, + TSTKEYWD, + VPD::USEVPD) ); if( err ) { fails++; @@ -302,7 +310,9 @@ class DVPDTest: public CxxTest::TestSuite err = deviceRead( theTarget, verifyData, theSize, - DEVICE_DVPD_ADDRESS(DVPD::MEMD,TSTKEYWD) ); + DEVICE_DVPD_FORCE_ADDRESS(DVPD::MEMD, + TSTKEYWD, + VPD::USEVPD) ); if( err ) { fails++; @@ -334,7 +344,9 @@ class DVPDTest: public CxxTest::TestSuite err = deviceWrite( theTarget, origData, theSize, - DEVICE_DVPD_ADDRESS(DVPD::MEMD,TSTKEYWD) ); + DEVICE_DVPD_FORCE_ADDRESS(DVPD::MEMD, + TSTKEYWD, + VPD::USEVPD) ); if( err ) { fails++; @@ -716,6 +728,36 @@ class DVPDTest: public CxxTest::TestSuite "testDvpdCheckStructOrder - %d fails", fails ); } + + DVPDTest() : CxxTest::TestSuite() + { + TRACFCOMP( g_trac_vpd, "Starting DVPDTest" ); +#ifdef CONFIG_SECUREBOOT +#ifndef __HOSTBOOT_RUNTIME + errlHndl_t l_err = loadSecureSection(PNOR::MEMD); + if(l_err) + { + TS_FAIL( "DVPDTest : loadSecureSection" ); + delete l_err; + } +#endif +#endif + } + + ~DVPDTest() + { +#ifdef CONFIG_SECUREBOOT +#ifndef __HOSTBOOT_RUNTIME + errlHndl_t l_err = unloadSecureSection(PNOR::MEMD); + TRACFCOMP( g_trac_vpd, "Ending DVPDTest" ); + if(l_err) + { + TS_FAIL( "DVPDTest : unloadSecureSection" ); + delete l_err; + } +#endif +#endif + } }; #endif diff --git a/src/usr/vpd/vpd.C b/src/usr/vpd/vpd.C index 585c168fa..a9bc590b5 100755 --- a/src/usr/vpd/vpd.C +++ b/src/usr/vpd/vpd.C @@ -1106,4 +1106,30 @@ errlHndl_t validateSharedPnorCache() return errl; } +/** + * @brief Get a list of all overridden sections + */ +void getListOfOverrideSections( OverrideRsvMemMap_t& o_overrides ) +{ + // Note - any new sections need to be added here + + PNOR::SectionInfo_t l_memd_info; + errlHndl_t l_elog = PNOR::getSectionInfo(PNOR::MEMD,l_memd_info); + if( l_elog ) + { + TRACFCOMP( g_trac_vpd, + "getListOfOverrideSections> failed getSectionInfo call" ); + delete l_elog; + return; + } + + // Add MEMD section + OverrideSpecifier_t l_memd = { + PNOR::MEMD, + l_memd_info.size + }; + + o_overrides[0x4D454D44/*MEMD*/] = l_memd; +} + }; //end VPD namespace diff --git a/src/usr/vpd/vpd.H b/src/usr/vpd/vpd.H index 2753a476d..7446dc491 100644 --- a/src/usr/vpd/vpd.H +++ b/src/usr/vpd/vpd.H @@ -27,6 +27,7 @@ #include <pnor/pnorif.H> #include <vpd/vpd_if.H> +#include <map> namespace VPD { @@ -83,6 +84,35 @@ union VpdWriteMsg_t } PACKED; }; +/** + * first = 4-character record name as a 4-byte uint + * second = Target pointer + */ +typedef std::pair<uint32_t, TARGETING::Target*> RecordTargetPair_t; + +/** + * @brief Helper function to convert record string to uint + * @param[in] 4-character record string + * @param[in] Target pointer + * @return Fully formed RecordTargetPair_t + */ +inline RecordTargetPair_t makeRecordTargetPair( const char* i_rec, + TARGETING::Target* i_targ ) +{ + uint32_t l_rec = 0; + memcpy( &l_rec, i_rec, sizeof(l_rec) ); + return std::make_pair(l_rec,i_targ); +}; + + +/** + * Indexed by RecordTargetPair_t + * Returns a pointer to this record within the override section + * if it is being used, or nullptr if not. + */ +typedef std::map<RecordTargetPair_t,uint8_t*> OverrideMap_t; + + /** * @brief This function is used to query the attribute code to get the VPD @@ -258,6 +288,10 @@ errlHndl_t getPnAndSnRecordAndKeywords( TARGETING::Target * i_target, vpdKeyword & io_partKeyword, vpdKeyword & io_serialKeyword); +/** + * @brief Read data from the BMC to update the system serial number + * @param[in] i_target - node target to update vpd of + */ void updateSerialNumberFromBMC( TARGETING::Target * i_nodetarget ); }; //end VPD namespace diff --git a/src/usr/vpd/vpd.mk b/src/usr/vpd/vpd.mk index d07a2bbea..b8337b989 100644 --- a/src/usr/vpd/vpd.mk +++ b/src/usr/vpd/vpd.mk @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2013,2017 +# Contributors Listed Below - COPYRIGHT 2013,2018 # [+] International Business Machines Corp. # # @@ -29,6 +29,5 @@ OBJS += mvpd.o OBJS += cvpd.o OBJS += pvpd.o OBJS += dvpd.o -OBJS += memd_vpd.o OBJS += spd.o OBJS += errlud_vpd.o diff --git a/src/usr/vpd/vpd_common.C b/src/usr/vpd/vpd_common.C index d11dc8743..3c657acb5 100644 --- a/src/usr/vpd/vpd_common.C +++ b/src/usr/vpd/vpd_common.C @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/usr/vpd/vpd.C $ */ +/* $Source: src/usr/vpd/vpd_common.C $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2015 */ +/* Contributors Listed Below - COPYRIGHT 2013,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -77,7 +77,7 @@ bool resolveVpdSource( TARGETING::Target * i_target, bool badConfig = false; o_vpdSource = VPD::INVALID_LOCATION; - if( i_vpdCmdTarget == VPD::PNOR ) + if( (i_vpdCmdTarget & VPD::LOCATION_MASK) == VPD::PNOR ) { if( i_rwPnorEnabled ) { @@ -89,7 +89,7 @@ bool resolveVpdSource( TARGETING::Target * i_target, TRACFCOMP(g_trac_vpd,"resolveVpdSource: VpdCmdTarget=PNOR but READ/WRITE PNOR CONFIG is disabled"); } } - else if( i_vpdCmdTarget == VPD::SEEPROM ) + else if( (i_vpdCmdTarget & VPD::LOCATION_MASK) == VPD::SEEPROM ) { if( i_rwHwEnabled ) { |