diff options
| author | Mike Baiocchi <baiocchi@us.ibm.com> | 2013-09-20 14:47:15 -0500 |
|---|---|---|
| committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-10-28 12:21:53 -0500 |
| commit | a094332bbe8807c8f24aeb79f34be063845cea10 (patch) | |
| tree | 7b05b516287bd27d971ee8404a980bfad311ac2b /src | |
| parent | 7b8d4a482ca2d110f3bf67b7a8e1bed758318420 (diff) | |
| download | blackbird-hostboot-a094332bbe8807c8f24aeb79f34be063845cea10.tar.gz blackbird-hostboot-a094332bbe8807c8f24aeb79f34be063845cea10.zip | |
Initial Support for Updating SBE SEEPROM
This initial commit will be used to create the new SBE
directories and files. It also supports the usr functions
to find and copy SBE PNOR images. NOTE: It will not enable
Updating SBE SEEPROMs in the IPL.
Change-Id: I3f545a134493c7595ce50fd885478bbe606de472
RTC: 47032
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/6311
Tested-by: Jenkins Server
Reviewed-by: ADAM R. MUHLE <armuhle@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
28 files changed, 4354 insertions, 26 deletions
diff --git a/src/build/buildpnor/buildSbePart.pl b/src/build/buildpnor/buildSbePart.pl new file mode 100755 index 000000000..11269bcfe --- /dev/null +++ b/src/build/buildpnor/buildSbePart.pl @@ -0,0 +1,348 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/buildpnor/buildSbePart.pl $ +# +# 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 + +#Builds an SBE partition for PNOR based on user-provided SBE images +#It works for both Processor SBE-IPL images and Centaur SBE images + +use strict; +use File::Basename; +use File::Temp qw/ tempfile tempdir /; + +my $TRAC_ERR = 0; +# 0=errors, >0 for more traces, leaving at 1 to keep key milestone traces. +my $g_trace = 1; + +my $progName = File::Basename::basename $0; +my $outBin = ""; +my %ecImgs; +my $injectVerHdrs = undef; +my $tocVersion = 1; #Only version 1 currently defined + +if ($#ARGV < 0) { + usage(); + exit; +} + + +#Parse the commandline args +for (my $i=0; $i < $#ARGV + 1; $i++) +{ + if ($ARGV[$i] =~ /-h/) { + usage(); + exit 0; + } + elsif($ARGV[$i] =~ /--injectVersionHeaders/) { + $injectVerHdrs = 1; + trace(2, "injectVersionHeaders flag specified"); + } + elsif($ARGV[$i] =~ /--sbeOutBin/) { + $outBin = $ARGV[++$i]; + trace(2, "SBE output Binary File=$outBin"); + } + elsif($ARGV[$i] =~ /--ecImg/) { + my $argName = $ARGV[$i]; + my $argVal = $ARGV[++$i]; + saveInputFile("--ecImg", $argName, $argVal, \%ecImgs); + } + else { + traceErr("Unrecognized Input: $ARGV[$i]"); + exit 1; + } +} + + +#Verify all the SBE images exist +my $rc = verifyFilesExist(\%ecImgs); +if($rc != 0) +{ + trace(0, "$progName: Error detected from call to verifyFilesExist(). Exiting"); + exit 1; +} + +#Generate the output image +my $rc = genOutputImage($injectVerHdrs, $tocVersion, $outBin, \%ecImgs); +if($rc != 0) +{ + trace(0, "$progName: Error detected from call to genOutputImage(). Exiting"); + exit 1; +} + + +################################################################################ +# saveInputFile - save inputfile name into ecImgss array +################################################################################ +sub saveInputFile +{ + my ($i_argPrefix, $i_argName, $i_argVal, $i_ecImgs) = @_; + my $this_func = (caller(0))[3]; + + #$i_argName will be something like --ecIMG_10 + #This substr command should return just the 10, which is the image EC Level + my $ecLevel = substr($i_argName, + length($i_argPrefix)+1, + length($i_argName)-length($i_argPrefix)); + + trace(10, "$this_func: $ecLevel=$i_argVal"); + + $$i_ecImgs{$ecLevel} = $i_argVal; + + trace(10, "$this_func: $$i_ecImgs{$ecLevel}"); + + #no return code expected +} + +################################################################################ +# verifyFilesExist - Verify all the input files exist +################################################################################ +sub verifyFilesExist +{ + my ($i_ecImgs) = @_; + my $this_func = (caller(0))[3]; + my $key; + my $rc = 0; + + for $key ( keys %$i_ecImgs) + { + unless(-e $$i_ecImgs{$key}) + { + my $inputFile = $$i_ecImgs{$key}; + trace(0, "$this_func: Specified input file ($inputFile) for key ($key) does not exist. Aborting!"); + $rc = 1; + last; + } + else + { + trace(10, "$this_func: $$i_ecImgs{$key} exists"); + } + } + + return $rc; +} + +################################################################################ +# genOutputImage - Generate output image +# -Build SBE TOC in first 128 bytes +# -Insert 4K header in front of each image with SHA512 as version +# -Insert each SBE image after corresponding header +################################################################################ +#Output image layout (Defined in Hostboot SBE Layout document) +#word 0: 'SBE\0' eyecatcher +#word 1: SBE TOC Layout version - currently only 1 is defined +#word 2: SBE image EC +#word 3: Sbe image offset in partition +#word 4: SBE image size +#Repeat words 2-4 for each supported EC + +#Actual SBE Images start at offset 0x1000 and must always be on a 4k boundary. +################################################################################ +sub genOutputImage +{ + my ($i_injectVerHdrs, $i_tocVersion, $i_outBin, $i_ecImgs) = @_; + my $this_func = (caller(0))[3]; + my $key; + my %ecOffsets; + my $rc = 0; + my $FILEHANDLE; + my $curOffset = 0x1000; #first offset is at 4k + trace(4, "$this_func: >>Enter"); + +#open output file + open( $FILEHANDLE, ">:raw", $i_outBin) + or die "Can't open $i_outBin file for writing"; + + #Build the TOC + #WORD 0: EyeCatcher - "SBE\0" in ASCII + my @charArray = split //, 'SBE'; + my $curChar; + foreach $curChar (@charArray) + { + print $FILEHANDLE pack('C', ord($curChar)); + } + + #Pad byte for null character after SBE + insertPadBytes($FILEHANDLE, 1); + + #WORD 1: Version = 0x00000001 + print $FILEHANDLE pack('N', 1); + + #Insert header data for each EC provided + for $key ( keys %{$i_ecImgs}) + { + trace(2, "$this_func: Inserting header for EC=$key"); + my $filesize = -s $$i_ecImgs{$key}; + + if($i_injectVerHdrs) + { + $filesize += 0x1000; + } + + #EC Word + print $FILEHANDLE pack('N', hex($key)); + + #Offset Word + print $FILEHANDLE pack('N', $curOffset); + + #Size Word + print $FILEHANDLE pack('N', $filesize); + + #safe offset for inserting images + $ecOffsets{$key} = $curOffset; + + #generate next to 4k offset + $curOffset += $filesize; + if (($curOffset & 0x00000FFF) != 0) + { + $curOffset = $curOffset & 0xFFFFF000; + $curOffset += 0x1000; + } + } + + close $FILEHANDLE; + + #Insert actual image for each EC provided + for $key ( keys %{$i_ecImgs}) + { + trace(2, "$this_func: Inserting data for EC=$key, offset=$ecOffsets{$key}"); + + my $seekOffset = $ecOffsets{$key}; + my $inFile = $$i_ecImgs{$key}; + + #Image is prefixed with 4k header containing version + if($i_injectVerHdrs) + { + my $headerOffset = $seekOffset; + $seekOffset += 0x1000; + + my $headerFh; + my $headerFile; + ($headerFh, $headerFile) = tempfile(UNLINK => 1); + #Disable file handle buffering + + trace(0, "$this_func: headerFile=$headerFile"); + + + #Insert 'VERSION\0' Eyecatcher + my @eyeCatchArray = split //, 'VERSION'; + foreach $curChar (@eyeCatchArray) + { + print $headerFh pack('C', ord($curChar)); + } + #Pad byte for null character after VERSION + insertPadBytes($headerFh, 1); + + #make sure date written to file handle is flushed to disk + close $headerFh; + + #Create the SHA512 hash + my $cmd = "sha512sum $inFile \| awk \'\{print $1\}\' \| xxd -ps -r \>> $headerFile"; + system( $cmd ) == 0 or die "Creating $headerFile failed!"; + + #Write to output file + my $hdrdd = "dd if=$headerFile of=$i_outBin bs=1 seek=$headerOffset"; + system ( $hdrdd ) == 0 or die "Couldn't Write $headerFile to $i_outBin!"; + } + my $ddCmd = "dd if=$inFile of=$i_outBin bs=1 seek=$seekOffset"; + system ( $ddCmd ) == 0 or die "Couldn't Write $inFile to $i_outBin!"; + + } + + trace(4, "$this_func: <<Exit"); + + return $rc; +} + +################################################# +# Insert specifed number of pad bytes into file +# +################################################# +sub insertPadBytes +{ + my ($i_FILEHANDLE, $i_padBytes) = @_; + my $i; + print $i_FILEHANDLE pack("C[$i_padBytes]", map { 0 } 1..$i_padBytes); + +} + + + +################################################################################ +# trace +################################################################################ +sub traceErr +{ + my $i_string = shift; + trace($TRAC_ERR, $i_string); +} + +################################################################################ +# trace +################################################################################ +sub trace +{ + my $i_traceLevel; + my $i_string; + + ($i_traceLevel, $i_string) = @_; + + #traceLevel 0 is for errors + if($i_traceLevel == 0) + { + print "ERROR: ".$i_string."\n"; + } + elsif ($g_trace >= $i_traceLevel) + { + print "TRACE: ".$i_string."\n"; + } +} + + + +################################################################################ +# print usage instructions +################################################################################ +sub usage +{ +print <<"ENDUSAGE"; + $progName = Creates SBE partition with SBE TOC based on input data. + + Usage: + $progName --sbeOutBin <complete SBE Partition image> + [--ecImg_10 <EC 10 SBE image>] [--ecImg_20 <EC_20_SBE_image>] + [--injectVersionHeaders] + + Parms: + -h Print this help text + --sbeOutBin <file> Name of output file for PNOR Binary + --ecImg_<EC> <file> This is a special paramater. It is used to specify + input files to use for populating the partition with + supported SBE EC specific images + Examples: --binFile_10 s1_10.sbe_seeprom.bin + --binFile_13 s1_13.sbe_seeprom.bin + --binFile_20 s1_20.sbe_seeprom.bin + --injectVersionHeaders Injects a 4k header at the top of each image + containing a SHA512 Hash computed over the image. + + +ENDUSAGE +} diff --git a/src/build/mkrules/dist.targets.mk b/src/build/mkrules/dist.targets.mk index 44405b6a2..a17e95c0c 100644 --- a/src/build/mkrules/dist.targets.mk +++ b/src/build/mkrules/dist.targets.mk @@ -169,6 +169,7 @@ simics.tar_CONTENTS = \ fsp.tar_CONTENTS = \ obj/genfiles/hwp_id.html \ src/build/mkrules/hbfw/fsp/makefile \ + src/build/buildpnor/buildSbePart.pl \ src/build/buildpnor/buildpnor.pl \ src/build/buildpnor/defaultPnorLayout.xml \ img/simics_MURANO_targeting.bin \ diff --git a/src/build/mkrules/hbfw/img/makefile b/src/build/mkrules/hbfw/img/makefile index 94647f827..4e6aa8179 100755 --- a/src/build/mkrules/hbfw/img/makefile +++ b/src/build/mkrules/hbfw/img/makefile @@ -36,8 +36,13 @@ VPATH += ../fsp DEFAULT_PATH = ${.PATH} SRCPATH = ${DEFAULT_PATH:M*src*} -build_all: cp_hbfiles -install_all: build_pnor_images +build_all: cp_hbfiles +install_all: build_sbe_partitions build_pnor_images + +#Some useful search paths +HBFW_OBJPATH = ${.PATH:M*obj*} +ENGD_OBJPATH = ${HBFW_OBJPATH:S/hbfw\/img/engd\/href/g} + ################################################# # Copy Hostboot binary images to obj dir to be grabbed @@ -96,6 +101,57 @@ clobber_cp_hbfiles: rm -f ${ALL_HB_IMAGES} \ sbe.header secureboot.header hb.footer hostboot.stage.bin +################################################# +### SAMPLE for building an SBE Partition with multiple ECs +################################################# +#S1_EC10_BIN = ${ENGD_OBJPATH:Fs1_10.sbe_seeprom.bin} +#s1SbePartition.bin: ${SBE_BUILD_SCRIPT} ${S1_EC10_BIN} +# ${buildSbePart.pl:P} --sbeOutBin s1SbePartition.bin \ +# --ecImg_10 ${S1_EC10_BIN} +################################################# +SBE_BUILD_SCRIPT = ${buildSbePart.pl:P} + +S1_EC10_BIN = ${ENGD_OBJPATH:Fs1_10.sbe_seeprom.hdr.bin} +S1_EC12_BIN = ${ENGD_OBJPATH:Fs1_12.sbe_seeprom.hdr.bin} +S1_EC13_BIN = ${ENGD_OBJPATH:Fs1_13.sbe_seeprom.hdr.bin} +S1_EC20_BIN = ${ENGD_OBJPATH:Fs1_20.sbe_seeprom.hdr.bin} +P8_EC10_BIN = ${ENGD_OBJPATH:Fp8_10.sbe_seeprom.hdr.bin} +CENT_EC10_BIN = ${ENGD_OBJPATH:Fcentaur_10.sbe_seeprom.hdr.bin} +CENT_EC20_BIN = ${ENGD_OBJPATH:Fcentaur_20.sbe_seeprom.hdr.bin} + +SBE_PART_INFO = \ + s1SbePartition.bin:10=${S1_EC10_BIN},12=${S1_EC12_BIN},13=${S1_EC13_BIN},20=${S1_EC20_BIN} \ + p8SbePartition.bin:10=${P8_EC10_BIN} \ + centSbePartition.bin:10=${CENT_EC10_BIN},20=${CENT_EC20_BIN} + + +__SBE_PART_BUILD/% : .SPECTARG .PMAKE + @${MAKE:T:R} BUILD_SPECIFIC_SBEPART \ + "SBE_PART_PARAMS=${.TARGET:s/__SBE_PART_BUILD\///:s/:/ /g}" + +.ifdef SBE_PART_PARAMS + +SBEPART_TARGET = ${SBE_PART_PARAMS:xs/ .*//} +SBEPART_SECTIONS = ${SBE_PART_PARAMS:xs/[^ ]* //:xs/ .*//} +SBEPART_BINS = ${SBEPART_SECTIONS:s/,/ /g:xS/[^=]*=//g} +SBEPART_BIN_OPTION = ${SBEPART_SECTIONS:s/,/ /g:S/^/--ecImg_/g:s/=/ /g:p} + +BUILD_SPECIFIC_SBEPART: .SPECTARG ${SBEPART_TARGET} + #@echo TARGET ${SBEPART_TARGET} + #@echo LAYOUT ${SBEPART_LAYOUT} + #@echo BINARIES ${SBEPART_BINS} + #@echo BIN_OPTION ${SBEPART_BIN_OPTION} + +${SBEPART_TARGET}: ${SBEPART_LAYOUT} ${SBEPART_BINS} ${PNOR_BUILD_SCRIPT} + ${SBE_BUILD_SCRIPT} --sbeOutBin ${SBEPART_TARGET} \ + ${SBEPART_BIN_OPTION} + +.endif + +build_sbe_partitions: .SPECTARG ${SBE_PART_INFO:S/^/__SBE_PART_BUILD\//g} + +clobber_build_sbe_partitions: + ${SBE_PART_INFO:@image@${pnorimg:!rm -f ${image:s/:/ /g:xs/ .*//};!e}@} ################################################# ### SAMPLE for building a PNOR image @@ -123,10 +179,16 @@ HOSTBOOT_DEFAULT_SECTIONS = HBB=${BASE_W_HEADER_ECC_IMAGE},HBI=${EXT_HEADER_IMAG HBFW_OBJPATH = ${.PATH:M*obj*} ENGD_OBJPATH = ${HBFW_OBJPATH:S/hbfw\/img/engd\/href/g} +MURANO_TARG_IMG = simics_MURANO_targeting.bin +VENICE_TARG_IMG = simics_VENICE_targeting.bin MURANO_SLW_IMG = ${ENGD_OBJPATH:Fs1.ref_image.bin} VENICE_SLW_IMG = ${ENGD_OBJPATH:Fp8.ref_image.bin} -MURANO_SECT = HBD=simics_MURANO_targeting.bin,WINK=${MURANO_SLW_IMG} -VENICE_SECT = HBD=simics_VENICE_targeting.bin,WINK=${VENICE_SLW_IMG} +MURANO_SBE_IMG = s1SbePartition.bin +VENICE_SBE_IMG = p8SbePartition.bin +SBEC_IMG = centSbePartition.bin +MURANO_SECT = HBD=${MURANO_TARG_IMG},SBE=${MURANO_SBE_IMG},SBEC=${SBEC_IMG},WINK=${MURANO_SLW_IMG} +VENICE_SECT = HBD=${VENICE_TARG_IMG},SBE=${VENICE_SBE_IMG},SBEC=${SBEC_IMG},WINK=${VENICE_SLW_IMG} + PNOR_IMG_INFO = \ murano.pnor:defaultPnorLayout.xml:${MURANO_SECT},${HOSTBOOT_DEFAULT_SECTIONS} \ @@ -180,7 +242,7 @@ clobber_build_pnor_images: FLASH_DEST = $(MAKETOP)$(OBJECTDIRTOP)../images/$(CONTEXT)/lab/flash FLASH_IMG = ${BASE_IMAGE} ${BASE_ECC_IMAGE} -update_images_for_sandbox: build_pnor_images +update_images_for_sandbox: build_sbe_partitions build_pnor_images mkdir -p ${FLASH_DEST} #Copy hostboot base image to flash dir ${FLASH_IMG:@image@${baseimg:!cd ${FLASH_DEST}; cp -f ${.PATH:F${image}} ${image};!e}@} diff --git a/src/include/sys/mm.h b/src/include/sys/mm.h index 38272c684..980918238 100644 --- a/src/include/sys/mm.h +++ b/src/include/sys/mm.h @@ -154,7 +154,7 @@ void mm_icache_invalidate(void * i_addr, size_t i_cpu_word_count); * * @param[in] i_vaddr - Virtual address to translate * - * @return uint64_t - 0 if there is no associated address, + * @return uint64_t - -EFAULT if there is no associated address, * physical address otherwise */ uint64_t mm_virt_to_phys( void* i_vaddr ); diff --git a/src/include/usr/hbotcompid.H b/src/include/usr/hbotcompid.H index 994aac1de..9425f569f 100644 --- a/src/include/usr/hbotcompid.H +++ b/src/include/usr/hbotcompid.H @@ -282,7 +282,6 @@ const char VPD_COMP_NAME[] = "vpd"; //@{ const compId_t SECURE_COMP_ID = 0x1E00; const char SECURE_COMP_NAME[] = "secure"; -//@} /** @name IPC * IPC - Inter Processor Communication component @@ -308,6 +307,15 @@ const compId_t DEVTREE_COMP_ID = 0x2100; const char DEVTREE_COMP_NAME[] = "devtree"; //@} +/** @name SBE + * SBE utility component + */ +//@{ +const compId_t SBE_COMP_ID = 0x2200; +const char SBE_COMP_NAME[] = "sbe"; +//@} + + /** @name RESERVED * Reserved component ID. x3100 is the component ID * of FipS ERRL component. Due to our use of diff --git a/src/include/usr/hwpf/plat/fapiPlatAttributeService.H b/src/include/usr/hwpf/plat/fapiPlatAttributeService.H index 6d3c0f41c..bcbf50612 100644 --- a/src/include/usr/hwpf/plat/fapiPlatAttributeService.H +++ b/src/include/usr/hwpf/plat/fapiPlatAttributeService.H @@ -1025,6 +1025,7 @@ fapi::ReturnCode fapiPlatGetSpdAttrAccessor ( fapi::AttrOverrideSync::getAttrOverrideFunc(fapi::ID, PTARGET, &VAL) ? fapi::FAPI_RC_SUCCESS : \ fapi::platAttrSvc::fapiPlatGetEnableAttr ( fapi::ID, PTARGET, VAL ) + //------------------------------------------------------------------------------ // MACROS to support MVPD attributes //------------------------------------------------------------------------------ diff --git a/src/include/usr/isteps/istep09list.H b/src/include/usr/isteps/istep09list.H index a273d58bc..87a018f21 100644 --- a/src/include/usr/isteps/istep09list.H +++ b/src/include/usr/isteps/istep09list.H @@ -95,6 +95,8 @@ const DepModInfo g_istep09Dependancies = { { DEP_LIB(libactivate_powerbus.so), DEP_LIB(libdram_initialization.so), + DEP_LIB(libsbe.so), + DEP_LIB(libbuild_winkle_images.so), { 0 }, } }; diff --git a/src/include/usr/sbe/sbeif.H b/src/include/usr/sbe/sbeif.H new file mode 100644 index 000000000..4570aaf85 --- /dev/null +++ b/src/include/usr/sbe/sbeif.H @@ -0,0 +1,72 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/sbe/sbeif.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 _SBEIF_H +#define _SBEIF_H + +#include <errl/errlentry.H> +#include <pnor/pnorif.H> + +namespace SBE +{ + // Each SBE Image stored in PNOR has a 64-byte version associated with it + // (like a SHA hash of the image) + const size_t SBE_IMAGE_VERSION_SIZE = 64; // 64 bytes + + typedef uint8_t sbe_image_version_t[SBE_IMAGE_VERSION_SIZE]; + + + /** + * @brief Gets a pointer to the proper SBE image in PNOR + * + * @param[in] i_target Target used to find right SBE Image in PNOR + * + * @param[out] o_imgPtr Pointer to SBE Image mapped in PNOR + * Note: Pointer moved past any header(s) + * + * @param[out] o_imgSize Size of the SBE Image in PNOR + * Note: Size does not include any header(s) + * + * @param[out] o_version Pointer to SBE Image Version Struct + * If Pointer is NULL, version not returned; + * Else sbe_image_version_t is filled in + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t findSBEInPnor(TARGETING::Target* i_target, + void*& o_imgPt, + size_t& o_imgSize, + sbe_image_version_t* o_version = NULL); + + + /** + * @brief Iterates through all the functional processors and updates + * the SBE Image in a SEEPROM, if necessary. + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t updateProcessorSbeSeeproms(); + + +} //end namespace SBE + +#endif /* _SBEIF_H */ diff --git a/src/include/usr/sbe/sbereasoncodes.H b/src/include/usr/sbe/sbereasoncodes.H new file mode 100644 index 000000000..44416aa95 --- /dev/null +++ b/src/include/usr/sbe/sbereasoncodes.H @@ -0,0 +1,88 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/vpd/vpdreasoncodes.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 __SBEREASONCODES_H +#define __SBEREASONCODES_H + +// ----------------------------------------------- +// Includes +// ----------------------------------------------- +#include <hbotcompid.H> + +namespace SBE +{ + +/** +* @enum SbeModuleid +* +* @brief Module Ids used in created errorlogs. Indicates which +* functions an error log was created in. +* +*/ +enum sbeModuleId +{ + SBE_INVALID_MODULE = 0x00, + SBE_FIND_IN_PNOR = 0x01, + SBE_UPDATE_SEEPROMS = 0x02, + SBE_GETSET_MVPD_VERSION = 0x03, + SBE_READ_PNOR_VERSION = 0x04, + SBE_READ_SBE_FROM_PNOR = 0x05, + SBE_CREATE_TEST_SPACE = 0x06, + SBE_CLEANUP_TEST_SPACE = 0x07, + SBE_GET_TARGET_INFO_STATE = 0x08, + SBE_GET_SEEPROM_INFO = 0x09, +}; + +/** + * @enum sbeReasonCode + * + * @brief Reasoncodes used to describe what errors are being indicated. + * + */ +enum sbeReasonCode +{ + SBE_INVALID_REASONCODE = SBE_COMP_ID | 0x00, // Invalid RC + SBE_ALLOC_BLOCK_FAIL = SBE_COMP_ID | 0x01, + SBE_SET_PERMISSION_FAIL = SBE_COMP_ID | 0x02, + SBE_REMOVE_PAGES_FAIL = SBE_COMP_ID | 0x03, + SBE_REMOVE_PAGES_FOR_EC = SBE_COMP_ID | 0x04, + SBE_REMOVE_PAGES_CLEANUP = SBE_COMP_ID | 0x05, + SBE_UNSUPPORTED_TOC = SBE_COMP_ID | 0x06, + SBE_INVALID_EYECATCHER = SBE_COMP_ID | 0x07, + SBE_EC_NOT_FOUND = SBE_COMP_ID | 0x08, + SBE_XIP_IMG_SIZE_FAIL = SBE_COMP_ID | 0x09, + SBE_MVPD_LEN_INVALID = SBE_COMP_ID | 0x0A, + SBE_VERSION_NOT_FOUND = SBE_COMP_ID | 0x0B, + + // SBE_UPDATE_REQUEST_REIPL Must have one unique use + // for Shutdown path. FSP relies on it. + // termination_rc + SBE_UPDATE_REQUEST_REIPL = SBE_COMP_ID | 0x0C, + + SBE_INVALID_INPUT = SBE_COMP_ID | 0x0D, + SBE_INVALID_SEEPROM_SIDE = SBE_COMP_ID | 0x0E, + SBE_ECC_FAIL = SBE_COMP_ID | 0x0F, +}; + +}; // end SBE + +#endif diff --git a/src/include/usr/vmmconst.h b/src/include/usr/vmmconst.h index fbb787ea1..d1d0d38a8 100644 --- a/src/include/usr/vmmconst.h +++ b/src/include/usr/vmmconst.h @@ -80,6 +80,11 @@ /** PNOR Resource Provider is at 2GB */ #define VMM_VADDR_PNOR_RP (2 * GIGABYTE) +/** SBE Update process is at 3GB, uses 256KB */ +#define VMM_VADDR_SBE_UPDATE (3 * GIGABYTE) +#define VMM_SBE_UPDATE_SIZE (256*KILOBYTE) +#define VMM_VADDR_SBE_UPDATE_END (VMM_VADDR_SBE_UPDATE + VMM_SBE_UPDATE_SIZE) + /** Attribute Resource Provider */ // Note: Not simplified to make it easier to extract with the PNOR targeting // image generator script diff --git a/src/include/util/crc32.H b/src/include/util/crc32.H new file mode 100644 index 000000000..25e46f725 --- /dev/null +++ b/src/include/util/crc32.H @@ -0,0 +1,43 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/util/crc32.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 __UTIL_CRC32_H +#define __UTIL_CRC32_H + + +namespace Util +{ + /** + * @brief Creates a 4-byte Cyclic Redundancy Check (CRC) on the data + * provided + * + * @param[in] ptr Pointer to the data + * + * @param[in] size Size of the data + * + * @return uint32_t 4-byte CRC + */ + uint32_t crc32_calc(const void* ptr, size_t size); +}; + +#endif + diff --git a/src/lib/crc32.C b/src/lib/crc32.C new file mode 100644 index 000000000..0c06c62c5 --- /dev/null +++ b/src/lib/crc32.C @@ -0,0 +1,67 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/lib/crc32.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 <stdint.h> +#include <util/crc32.H> + +namespace Util +{ + static const uint64_t CRC32_POLY = 0x104C11DB7ull; + + uint32_t crc32_calc(const void* ptr, size_t size) + { + const uint8_t* _ptr = (const uint8_t*)ptr; + uint64_t crc = 0; + while(size) + { + uint64_t data = 0; + for (int i = 0; i < 4; ++i) + { + data <<= 8; + if (size) + { + data |= *(_ptr++); + --size; + } + } + + crc <<= 32; + crc ^= (data << 32); + + + int idx = 0; + do + { + idx = __builtin_clzl(crc); + if (idx < 32) + { + crc ^= (CRC32_POLY << (31 - idx)); + } + + } while (idx < 32); + } + + return crc; + } + +}; + diff --git a/src/lib/makefile b/src/lib/makefile index e8b648c6c..42571c341 100644 --- a/src/lib/makefile +++ b/src/lib/makefile @@ -25,7 +25,7 @@ ROOTPATH = ../.. OBJS = string.o string_ext.o stdlib.o ctype.o assert.o stdio.o math.o sprintf.o OBJS += syscall_stub.o syscall_task.o syscall_msg.o OBJS += syscall_mmio.o syscall_time.o sync.o syscall_misc.o -OBJS += syscall_mm.o splaytree.o cxxtest_data.o +OBJS += syscall_mm.o splaytree.o cxxtest_data.o crc32.o ifdef HOSTBOOT_MEMORY_LEAKS COMMONFLAGS += -DHOSTBOOT_MEMORY_LEAKS=1 diff --git a/src/makefile b/src/makefile index 7f71f9b5b..5235f1fc2 100644 --- a/src/makefile +++ b/src/makefile @@ -27,7 +27,7 @@ SUBDIRS = kernel.d lib.d libc++.d sys.d usr.d build.d runtime.d IMGS = hbicore hbicore_test hbirt hbirt_test BASE_OBJECTS = string.o string_ext.o ctype.o math.o builtins.o stdio.o \ - splaytree.o cxxtest_data.o sprintf.o + splaytree.o cxxtest_data.o sprintf.o crc32.o ifdef HOSTBOOT_PROFILE BASE_OBJECTS += gcov.o @@ -59,7 +59,7 @@ EXTENDED_MODULES = targeting ecmddatabuffer fapi hwp plat \ establish_system_smp occ\ nest_chiplets start_payload thread_activate slave_sbe \ attn runtime ibscom dump tod_init secureboot_ext \ - devtree + devtree sbe TESTCASE_MODULES = cxxtest testtrace testerrl testdevicefw testsyslib \ testscom testxscom testtargeting testinitservice testkernel \ @@ -67,7 +67,7 @@ TESTCASE_MODULES = cxxtest testtrace testerrl testdevicefw testsyslib \ testpnor testi2c testfsi testvfs testhwas testintr testvpd \ testpore testutil testmbox testmdia testprdf testattn \ testscan testruntime testibscom testdump testsecureboot \ - testfsiscom testrtloader + testfsiscom testrtloader testsbe RUNTIME_OBJECTS = rt_start.o rt_main.o rt_console.o rt_stdlib.o rt_sync.o \ rt_assert.o rt_vfs.o diff --git a/src/usr/hwpf/hwp/activate_powerbus/activate_powerbus.C b/src/usr/hwpf/hwp/activate_powerbus/activate_powerbus.C index 2cbfc4409..a1d1da4ab 100644 --- a/src/usr/hwpf/hwp/activate_powerbus/activate_powerbus.C +++ b/src/usr/hwpf/hwp/activate_powerbus/activate_powerbus.C @@ -44,6 +44,8 @@ #include <initservice/isteps_trace.H> #include <hwpisteperror.H> +#include <sbe/sbeif.H> + // targeting support #include <targeting/common/commontargeting.H> #include <targeting/common/utilFilter.H> @@ -301,7 +303,8 @@ void * call_host_slave_sbe_update( void * io_pArgs ) TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_slave_sbe_update entry" ); - // call p8_customize_image.C + // @todo RTC 47033 - enable this call + // l_errl = SBE::updateProcessorSbeSeeproms(); TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_slave_sbe_update exit" ); diff --git a/src/usr/hwpf/hwp/sbe_centaur_init/sbe_centaur_init.C b/src/usr/hwpf/hwp/sbe_centaur_init/sbe_centaur_init.C index 097fe78ea..1bf3e339c 100644 --- a/src/usr/hwpf/hwp/sbe_centaur_init/sbe_centaur_init.C +++ b/src/usr/hwpf/hwp/sbe_centaur_init/sbe_centaur_init.C @@ -53,6 +53,7 @@ #include "sbe_centaur_init.H" #include <hwpisteperror.H> #include <errl/errludtarget.H> +#include <sbe/sbeif.H> #include "cen_xip_customize.H" extern fapi::ReturnCode fapiPoreVe(const fapi::Target i_target, @@ -143,6 +144,14 @@ void* call_sbe_centaur_init( void *io_pArgs ) l_membuf_iter != l_membufTargetList.end(); ++l_membuf_iter) { +/* + //find SBE image in PNOR + // @todo RTC 77647 + // Will use SBE::findSBEInPnor() function rather than + // VFS::module_load/address() function calls above + +*/ + // Make sure we have successfully retrieved the reference image if (l_errl) { diff --git a/src/usr/hwpf/plat/fapiPlatAttributeService.C b/src/usr/hwpf/plat/fapiPlatAttributeService.C index af9aacc68..a4c68d653 100644 --- a/src/usr/hwpf/plat/fapiPlatAttributeService.C +++ b/src/usr/hwpf/plat/fapiPlatAttributeService.C @@ -1576,6 +1576,7 @@ fapi::ReturnCode fapiPlatGetSpdAttrAccessor( return l_rc; } + } // End platAttrSvc namespace } // End fapi namespace diff --git a/src/usr/i2c/test/i2ctest.H b/src/usr/i2c/test/i2ctest.H index 15fe1f226..0224d8dd8 100755 --- a/src/usr/i2c/test/i2ctest.H +++ b/src/usr/i2c/test/i2ctest.H @@ -113,7 +113,7 @@ class I2CTest: public CxxTest::TestSuite // Read/Write SBE Primary: Murano-0, port-0 - // Safe to write to first 1K: 0x-0x400 + // Safe to write to first 0x300: 0x0-0x2FF { 0x00, 0x00, 0xAC, 0x0000ababcdcdefef, 8, false, TARGETING::TYPE_PROC }, // Write data to 0x0000 @@ -142,7 +142,7 @@ class I2CTest: public CxxTest::TestSuite // Read/Write SBE Backup: Murano-0, port-0 - // Safe to write to first 1K: 0x-0x400 + // Safe to write to first 0x300: 0x0-0x2FF { 0x00, 0x00, 0xAE, 0x0000ababcdcdefef, 8, false, TARGETING::TYPE_PROC }, // Write data to 0x0000 @@ -371,12 +371,12 @@ class I2CTest: public CxxTest::TestSuite // PROCESSOR TESTS // Read/Write SBE Backup: Murano-0, port-0 - // Safe to write to first 1K: 0x-0x400 + // Safe to write to first 0x300: 0x0-0x2FF { 0x00, 0x00, 0xAE, 0x0123, 0xFEFEDADA57579191, 8, TARGETING::TYPE_PROC }, // Read/Write SBE Primary: Murano-0, port-0 - // Safe to write to first 1K: 0x-0x400 + // Safe to write to first 0x300: 0x0-0x2FF { 0x00, 0x00, 0xAC, 0x02FC, 0x5ABC310000000000, 3, TARGETING::TYPE_PROC }, }; diff --git a/src/usr/makefile b/src/usr/makefile index 890756706..6433dba12 100644 --- a/src/usr/makefile +++ b/src/usr/makefile @@ -30,6 +30,6 @@ SUBDIRS = trace.d cxxtest.d testcore.d errl.d devicefw.d \ scom.d xscom.d targeting.d initservice.d hwpf.d \ ecmddatabuffer.d pnor.d i2c.d vfs.d fsi.d hwas.d fsiscom.d \ intr.d pore.d util.d mbox.d diag.d vpd.d scan.d \ - runtime.d ibscom.d dump.d secureboot.d devtree.d + runtime.d ibscom.d dump.d secureboot.d devtree.d sbe.d include ${ROOTPATH}/config.mk diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C index 3d859c48b..cfb7fbd07 100644 --- a/src/usr/pnor/pnorrp.C +++ b/src/usr/pnor/pnorrp.C @@ -218,8 +218,8 @@ void PnorRP::initDaemon() * @devdesc PnorRP::initDaemon> Error from mm_alloc_block */ l_errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - PNOR::MOD_PNORRP_GETSECTIONINFO, - PNOR::RC_INVALID_SECTION, + PNOR::MOD_PNORRP_INITDAEMON, + PNOR::RC_EXTERNAL_ERROR, TO_UINT64(BASE_VADDR), TO_UINT64(rc)); l_errhdl->collectTrace(PNOR_COMP_NAME); diff --git a/src/usr/sbe/makefile b/src/usr/sbe/makefile new file mode 100644 index 000000000..50de91c2d --- /dev/null +++ b/src/usr/sbe/makefile @@ -0,0 +1,42 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/sbe/makefile $ +# +# 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 +ROOTPATH = ../../.. +MODULE = sbe + +## support for Targeting and fapi +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/ecmddatabuffer +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/fapi +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp + +## pointer to common HWP files +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/include + +## pointer to already consumed procedures. +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/p8_slw_build + +OBJS = sbe_update.o + +SUBDIRS = test.d + +include ${ROOTPATH}/config.mk diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C new file mode 100644 index 000000000..8001c9954 --- /dev/null +++ b/src/usr/sbe/sbe_update.C @@ -0,0 +1,2311 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbe/sbe_update.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 <vector> +#include <trace/interface.H> +#include <vpd/mvpdenums.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <errl/errludtarget.H> +#include <targeting/common/predicates/predicatectm.H> +#include <targeting/common/utilFilter.H> +#include <util/align.H> +#include <util/crc32.H> +#include <errno.h> +#include <pnor/pnorif.H> +#include <pnor/ecc.H> +#include <devicefw/driverif.H> +#include <sys/mm.h> +#include <sys/misc.h> +#include <hwas/common/deconfigGard.H> +#include <sbe/sbeif.H> +#include <sbe/sbereasoncodes.H> +#include "sbe_update.H" + +// fapi support +#include <fapi.H> +#include <fapiPlatHwpInvoker.H> +#include <hwpf/plat/fapiPlatTrace.H> + +//Procedures +#include <p8_xip_customize.H> +#include <sbe_xip_image.h> +#include <p8_image_help_base.H> + +// ---------------------------------------------- +// Trace definitions +// ---------------------------------------------- +trace_desc_t* g_trac_sbe = NULL; +TRAC_INIT( & g_trac_sbe, SBE_COMP_NAME, KILOBYTE ); + +// ------------------------ +// Macros for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + +using namespace ERRORLOG; +using namespace TARGETING; + +namespace SBE +{ + + enum { + SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE, + RING_BUF1_VADDR = FIXED_SEEPROM_WORK_SPACE + SBE_IMG_VADDR, + RING_BUF2_VADDR = RING_BUF1_VADDR + FIXED_RING_BUF_SIZE, + //NOTE: recycling the same memory space for different + //steps in the process. + SBE_ECC_IMG_VADDR = RING_BUF1_VADDR, + SBE_ECC_IMG_MAX_SIZE = VMM_VADDR_SBE_UPDATE_END - SBE_ECC_IMG_VADDR, + }; + +///////////////////////////////////////////////////////////////////// + errlHndl_t updateProcessorSbeSeeproms() + { + errlHndl_t err = NULL; + errlHndl_t err_cleanup = NULL; + sbeTargetState_t sbeState; + std::vector<sbeTargetState_t> sbeStates_vector; + + bool l_cleanupVmmSpace = false; + bool l_restartNeeded = false; + + TRACUCOMP( g_trac_sbe, + ENTER_MRK"updateProcessorSbeSeeproms()" ); + + do{ + + //Make sure procedure constants keep within expected range. + assert((FIXED_SEEPROM_WORK_SPACE <= VMM_SBE_UPDATE_SIZE/2), + "updateProcessorSbeSeeproms() FIXED_SEEPROM_WORK_SPACE " + "too large"); + assert((FIXED_RING_BUF_SIZE <= VMM_SBE_UPDATE_SIZE/4), + "updateProcessorSbeSeeproms() FIXED_RING_BUF_SIZE too " + "large"); + + err = createSbeImageVmmSpace(); + if (err) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): " + "createSbeImageVmmSpace() Failed. ", + "rc=0x%.4X", err->reasonCode() ); + + break; + } + else + { + // Make sure cleanup gets called + l_cleanupVmmSpace = true; + } + + /*****************************************************************/ + /* Iterate over all the functional processors and do for each: */ + /* 1) Check their SBE State (PNOR, MVPD, SEEPROMs, etc), */ + /* 2) Determine the Necessary Update */ + /* 3) Perform Update Action */ + /*****************************************************************/ + TARGETING::TargetHandleList procList; + TARGETING::getAllChips(procList, + TARGETING::TYPE_PROC, + true); // true: return functional targets + + if( ( 0 == procList.size() ) || + ( NULL == procList[0] ) ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"updateProcessorSbeSeeproms() - " + "No functional processors Found!" ); + break; + } + + + for(uint32_t i=0; i<procList.size(); i++) + { + + /*********************************************/ + /* Collect SBE Information for this Target */ + /*********************************************/ + memset(&sbeState, 0, sizeof(sbeState)); + sbeState.target = procList[i]; + + // @todo RTC 47033 check attribute on target to see if it's + // the master processor and set sbeState.target_is_master + + err = getSbeInfoState(sbeState); + + if (err) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): " + "getSbeInfoState() Failed " + "rc=0x%.4X, Target UID=0x%X", + err->reasonCode(), + TARGETING::get_huid(sbeState.target)); + + // Don't break - handle error at the end of the loop + + } + + + /**********************************************/ + /* Determine update actions for this target */ + /**********************************************/ + // Skip if we got an error collecting SBE Info State + if ( err == NULL ) + { + err = getTargetUpdateActions(sbeState); + if (err) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): " + "getTargetUpdateActions() Failed ", + "rc=0x%.4X, Target UID=0x%X", + err->reasonCode(), + TARGETING::get_huid(sbeState.target)); + + // Don't break - handle error at the end of the loop, + } + } + + /**********************************************/ + /* Perform Update Actions For This Target */ + /**********************************************/ + if ((err == NULL) && (sbeState.update_actions & DO_UPDATE)) + { + + err = performUpdateActions(sbeState); + if (err) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): " + "performUpdateActions() Failed ", + "rc=0x%.4X, Target UID=0x%X", + err->reasonCode(), + TARGETING::get_huid(sbeState.target)); + + break; + } + else + { + // Target updated without failure, so set IPL_RESTART + // flag, if necessary + if (sbeState.update_actions & IPL_RESTART) + { + l_restartNeeded = true; + } + } + + } + + + // Push this sbeState onto the vector + sbeStates_vector.push_back(sbeState); + + if ( err ) + { + // Something failed for this target. + // Commit the error here and move on to the next target, + // or if no targets left, will just continue the IPL + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): " + "Committing Error Log rc=0x%.4X for " + "Target UID=0x%X, but continuing procedure", + err->reasonCode(), + TARGETING::get_huid(sbeState.target)); + errlCommit( err, SBE_COMP_ID ); + } + + + + } //end of Target for loop collecting each target's SBE State + + + /**************************************************************/ + /* Perform System Operation */ + /**************************************************************/ + //TODO RTC: 47033 - Restart IPL if SBE Update requires it + // For Now just trace that a restart is needed + if (l_restartNeeded == true) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): Restart " + "Needed, but not currently supported (%d). " + "Continuing IPL", + l_restartNeeded ); + } + + + }while(0); + + + + // Cleanup VMM Workspace + if ( l_cleanupVmmSpace == true ) + { + err_cleanup = cleanupSbeImageVmmSpace(); + if ( err_cleanup != NULL ) + { + + if ( err != NULL ) + { + // 2 error logs, so commit the cleanup log here + TRACFCOMP( g_trac_sbe, + ERR_MRK"updateProcessorSbeSeeproms(): Previous " + "error (rc=0x%X) before cleanupSbeImageVmmSpace" + "() failed. Committing cleanup error (rc=0x%X) " + "and returning original error", + err->reasonCode(), err_cleanup->reasonCode() ); + + errlCommit( err_cleanup, SBE_COMP_ID ); + } + else + { + // no previous error, so returning cleanup error + TRACFCOMP( g_trac_sbe, + ERR_MRK"updateProcessorSbeSeeproms(): " + "cleanupSbeImageVmmSpace() failed.", + "rc=0x%.4X", err_cleanup->reasonCode() ); + err = err_cleanup; + } + } + } + + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"updateProcessorSbeSeeproms()" ); + + return err; + } + +///////////////////////////////////////////////////////////////////// + errlHndl_t findSBEInPnor(TARGETING::Target* i_target, + void*& o_imgPtr, + size_t& o_imgSize, + sbe_image_version_t* o_version) + { + errlHndl_t err = NULL; + PNOR::SectionInfo_t pnorInfo; + sbeToc_t* sbeToc = NULL; + uint8_t ec = 0; + PNOR::SectionId pnorSectionId = PNOR::INVALID_SECTION; + + void* hdr_Ptr = NULL; + o_imgPtr = NULL; + o_imgSize = 0; + + TRACDCOMP( g_trac_sbe, + ENTER_MRK"findSBEInPnor()" ); + + do{ + + // Get the correct PNOR Section Id + if ( i_target->getAttr<ATTR_TYPE>() == TYPE_PROC ) + { + pnorSectionId = PNOR::SBE_IPL; + } + else if ( i_target->getAttr<ATTR_TYPE>() == TYPE_MEMBUF ) + { + pnorSectionId = PNOR::CENTAUR_SBE; + } + else + { + // Unsopported target type was passed in + TRACFCOMP( g_trac_sbe, ERR_MRK"findSBEInPnor: Unsupported " + "target type was passed in: uid=0x%X, type=0x%X", + TARGETING::get_huid(i_target), + i_target->getAttr<ATTR_TYPE>()); + + /*@ + * @errortype + * @moduleid SBE_FIND_IN_PNOR + * @reasoncode SBE_INVALID_INPUT + * @userdata1 Target Unit Id + * @userdata2 Target Type + * @devdesc Unsupported Target Type passed in + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_FIND_IN_PNOR, + SBE_INVALID_INPUT, + TARGETING::get_huid(i_target), + i_target->getAttr<ATTR_TYPE>()); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + break; + } + + + // Get SBE PNOR section info from PNOR RP + err = PNOR::getSectionInfo( pnorSectionId, + PNOR::CURRENT_SIDE, + pnorInfo ); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"findSBEInPnor: Error calling " + "PNOR::getSectionInfo() rc=0x%.4X", + err->reasonCode() ); + break; + } + + TRACUCOMP( g_trac_sbe, + INFO_MRK"findSBEInPnor: UID=0x%X, sectionId=0x%X. " + "pnor vaddr = 0x%.16X", + TARGETING::get_huid(i_target), + pnorSectionId, pnorInfo.vaddr); + + sbeToc = reinterpret_cast<sbeToc_t*>( pnorInfo.vaddr ); + + if (sbeToc->eyeCatch != SBETOC_EYECATCH) + { + //The SBE partition does not have the proper eyecatcher + TRACFCOMP( g_trac_sbe, ERR_MRK"findSBEInPnor: SBE partition " + "does not have the proper eyecatcher: was: 0x%X, " + "should be: 0x%X", + sbeToc->eyeCatch, SBETOC_EYECATCH ); + + /*@ + * @errortype + * @moduleid SBE_FIND_IN_PNOR + * @reasoncode SBE_INVALID_EYECATCHER + * @userdata1 SBE TOC EYE-CATCHER + * @userdata2 Expected EYE-CATCHER + * @devdesc Unsupported EYE-CATCHER found in TOC + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_FIND_IN_PNOR, + SBE_INVALID_EYECATCHER, + sbeToc->eyeCatch, + SBETOC_EYECATCH); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_SP_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + break; + } + else + { + + //Check the TOC Version + if( SUPPORTED_TOC_VER != sbeToc->tocVersion) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"findSBEInPnor: Unsupported " + "SBE TOC Version in SBE Partition" ); + /*@ + * @errortype + * @moduleid SBE_FIND_IN_PNOR + * @reasoncode SBE_UNSUPPORTED_TOC + * @userdata1[0:31] CHIP EC + * @userdata1[32:63] Expected TOC Version + * @userdata2[0:31] SBE TOC Version + * @userdata2[32:63] SBE TOC EyeCatch + * @devdesc SBE partition contains unsupported version + * of Table of Contents + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_FIND_IN_PNOR, + SBE_UNSUPPORTED_TOC, + TWO_UINT32_TO_UINT64(ec, + SUPPORTED_TOC_VER), + TWO_UINT32_TO_UINT64(sbeToc->tocVersion, + sbeToc->eyeCatch)); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_SP_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + + // @todo RTC 47033 capture SBE TOC for analysis + + break; + } + + //Walk the TOC and find our current EC + ec = i_target->getAttr<TARGETING::ATTR_EC>(); + for(uint32_t i=0; i<MAX_SBE_ENTRIES; i++) + { + if(static_cast<uint32_t>(ec) == sbeToc->entries[i].ec) + { + + // EC found in TOC + uint64_t offset = pnorInfo.vaddr + + static_cast<uint64_t>(sbeToc->entries[i].offset); + hdr_Ptr = reinterpret_cast<void*>( offset ); + + o_imgSize = sbeToc->entries[i].size; + + TRACUCOMP( g_trac_sbe, INFO_MRK"findSBEInPnor: Found " + "EC Image: ec=0x%.2X offset=0x%.16X, i=%d " + "size=0x%X", + ec, offset, i, o_imgSize ); + break; + } + } + } + + if(NULL == hdr_Ptr) + { + //if we get here, it's an error + TRACFCOMP( g_trac_sbe,ERR_MRK"findSBEInPnor:SBE Image not " + "located, ec=0x%.2X",ec ); + + /*@ + * @errortype + * @moduleid SBE_FIND_IN_PNOR + * @reasoncode SBE_EC_NOT_FOUND + * @userdata1[0:31] CHIP EC + * @userdata1[32:63] PNOR Section ID + * @userdata2[0:31] SBE TOC Version + * @userdata2[32:63] SBE TOC EyeCatch + * @devdesc SBE image for current chip EC was not found + * in PNOR + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_FIND_IN_PNOR, + SBE_EC_NOT_FOUND, + TWO_UINT32_TO_UINT64(ec, + pnorSectionId), + TWO_UINT32_TO_UINT64(sbeToc->tocVersion, + sbeToc->eyeCatch)); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_SP_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + // @todo RTC 47033 capture SBE TOC for analysis + + break; + } + + // The SBE Image for the corresponding EC was found and includes a + // SBE Header, so advance PNOR pointer 4k to move it past header + // page to the start of the non-customized SBE image + o_imgPtr = reinterpret_cast<void*> + (reinterpret_cast<char*>(hdr_Ptr)+0x1000); + + + if(NULL != o_version) + { + err = readPNORVersion(hdr_Ptr, + *o_version); + if(err) + { + break; + } + } + + }while(0); + + + TRACDCOMP( g_trac_sbe, + EXIT_MRK"findSBEInPnor(): o_imgPtr=%p, o_imgSize=0x%X", + o_imgPtr, o_imgSize ); + + + return err; + } + + + +///////////////////////////////////////////////////////////////////// + errlHndl_t procCustomizeSbeImg(TARGETING::Target* i_target, + void* i_sbePnorPtr, + size_t i_maxImgSize, + void* io_imgPtr, + size_t& o_actImgSize) + { + errlHndl_t err = NULL; + uint32_t coreMask = 0x0000FFFF; + size_t maxCores = P8_MAX_EX_PER_PROC; + uint32_t procIOMask = 0; + + TRACUCOMP( g_trac_sbe, + ENTER_MRK"procCustomizeSbeImg(): uid=0x%X, i_sbePnorPtr= " + "%p, maxS=0x%X, io_imgPtr=%p", + TARGETING::get_huid(i_target), i_sbePnorPtr, + i_maxImgSize, io_imgPtr); + + do{ + + // cast OUR type of target to a FAPI type of target. + const fapi::Target + l_fapiTarg(fapi::TARGET_TYPE_PROC_CHIP, + (const_cast<TARGETING::Target*>(i_target))); + + + // The p8_xip_customize() procedure tries to include as much core + // information as possible, but is limited by SBE Image size + // constraints. + // This loop is designed to remove the number of cores passed into + // p8_xip_customize() until an image can be created successfully. + + while( __builtin_popcount(procIOMask) < + __builtin_popcount(coreMask)) + { + + err = selectBestCores(i_target, + maxCores, + coreMask); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"procCustomizeSbeImg() - " + "selectBestCores() failed rc=0x%X. " + "MaxCores=0x%.8X. HUID=0x%.8X. Aborting Update", + err->reasonCode(), maxCores, + TARGETING::get_huid(i_target)); + break; + } + + procIOMask = coreMask; + + uint32_t tmpImgSize = static_cast<uint32_t>(i_maxImgSize); + + FAPI_INVOKE_HWP( err, + p8_xip_customize, + l_fapiTarg, + i_sbePnorPtr, //image in + io_imgPtr, //image out + tmpImgSize, + 0, //IPL + 0, //HB/IPL + (void*)RING_BUF1_VADDR, + (uint32_t)FIXED_RING_BUF_SIZE, + (void*)RING_BUF2_VADDR, + (uint32_t)FIXED_RING_BUF_SIZE, + procIOMask); + + o_actImgSize = static_cast<size_t>(tmpImgSize); + + maxCores = __builtin_popcount(procIOMask); + + if ( err ) + { + TRACFCOMP( g_trac_sbe, + ERR_MRK"procCustomizeSbeImg(): FAPI_INVOKE_HWP(" + "p8_xip_customize) failed with rc=0x%x04X, " + "MaxCores=0x%.8X. HUID=0x%.8X. coreMask=0x%.8X, " + "procIOMask=0x%.8X.", + err->reasonCode(), maxCores, + TARGETING::get_huid(i_target), + coreMask, procIOMask); + + ERRORLOG::ErrlUserDetailsTarget(i_target, + "Proc Target") + .addToLog(err); + + // @todo RTC 47033 look for specific return code for + // the case where he couldn't fix the cores we asked for + // but could possibly fit a lesser amount + + break; + } + + } + + + if(err) + { + break; + } + }while(0); + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"procCustomizeSbeImg(): io_imgPtr=%p, " + "o_actImgSize=0x%X", io_imgPtr, o_actImgSize ); + + return err; + } + +///////////////////////////////////////////////////////////////////// + errlHndl_t selectBestCores(TARGETING::Target* i_target, + size_t i_maxExs, + uint32_t& o_exMask) + { + TRACUCOMP( g_trac_sbe, + ENTER_MRK"selectBestCores(i_maxCores=0x%.8X)", + i_maxExs); + + errlHndl_t err = NULL; + uint32_t manGuardExs = 0x00000000; + uint32_t exCount = 0; + uint32_t deconfigByEid = 0; + + o_exMask = 0x00000000; + + do{ + // find all EX chiplets of the proc + TARGETING::TargetHandleList l_exTargetList; + TARGETING::getChildChiplets( l_exTargetList, + i_target, + TARGETING::TYPE_EX, + false); // return all + + //Sort through cores + for ( TargetHandleList::const_iterator + l_iterEX = l_exTargetList.begin(); + l_iterEX != l_exTargetList.end(); + ++l_iterEX ) + { + // make a local copy of the EX target + const TARGETING::Target* l_ex_target = *l_iterEX; + + + if( !(l_ex_target-> + getAttr<TARGETING::ATTR_HWAS_STATE>().present) ) + { + // not present, so skip and continue + continue; + } + + + uint8_t chipUnit = l_ex_target-> + getAttr<TARGETING::ATTR_CHIP_UNIT>(); + + if(l_ex_target-> + getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + o_exMask |= (0x00008000 >> chipUnit); + exCount++; + + if(exCount >= i_maxExs) + { + break; + } + } + else + { + //If non-functional due to FCO or Manual gard, + //add it to list of exs to include if + //more are needed + + deconfigByEid = l_ex_target-> + getAttr<TARGETING::ATTR_HWAS_STATE>(). + deconfiguredByEid; + if( + // FCO + (deconfigByEid == + HWAS::DeconfigGard::DECONFIGURED_BY_FIELD_CORE_OVERRIDE) + || // Manual GARD + (deconfigByEid == + HWAS::DeconfigGard::DECONFIGURED_BY_MANUAL_GARD) + ) + { + manGuardExs |= (0x00008000 >> chipUnit); + } + } + } // end ex target loop + + if(exCount >= i_maxExs) + { + //We've found enough, break out of function + break; + } + + //Look for more 'good' exs. + manGuardExs = trimBitMask(manGuardExs, + i_maxExs-exCount); + o_exMask |= manGuardExs; + TRACUCOMP( g_trac_sbe,INFO_MRK"selectBestCores: trimBitMask manGuardExs=0x%.8X", + manGuardExs); + + }while(0); + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"selectBestCores(o_exMask=0x%.8X)", + o_exMask); + + return err; + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t getSetMVPDVersion(TARGETING::Target* i_target, + opType_t i_op, + mvpdSbKeyword_t& io_sb_keyword) + { + errlHndl_t err = NULL; + size_t vpdSize = 0; + + TRACUCOMP( g_trac_sbe, + ENTER_MRK"getSetMVPDVersion(i_op=%d)", i_op ); + + do{ + // Read SB Keyword which contains SBE version and dirty bit + // information + // Note: First read with NULL for o_buffer sets vpdSize to the + // correct length + err = deviceRead( i_target, + NULL, + vpdSize, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::SB ) ); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSetMVPDVersion() - MVPD " + "failure getting SB keywordw size HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + if(vpdSize != MVPD_SB_RECORD_SIZE) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSetMVPDVersion() - MVPD SB " + "keyword wrong length HUID=0x%.8X, length=0x.2X, " + "expected=0x.2x", + TARGETING::get_huid(i_target), vpdSize, + MVPD_SB_RECORD_SIZE); + /*@ + * @errortype + * @moduleid SBE_GETSET_MVPD_VERSION + * @reasoncode SBE_MVPD_LEN_INVALID + * @userdata1 Discovered VPD Size + * @userdata2 Expected VPD Size + * @devdesc SB Keyword in MVPD has invalid size + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_GETSET_MVPD_VERSION, + SBE_MVPD_LEN_INVALID, + TO_UINT64(vpdSize), + TO_UINT64(MVPD_SB_RECORD_SIZE)); + ErrlUserDetailsTarget(i_target + ).addToLog(err); + err->collectTrace(SBE_COMP_NAME, 256); + err->addProcedureCallout( HWAS::EPUB_PRC_SP_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_MED ); + + break; + } + + if(i_op == MVPDOP_READ) + { + err = deviceRead( i_target, + reinterpret_cast<void*>( &io_sb_keyword ), + vpdSize, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::SB ) ); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSetMVPDVersion() - MVPD " + "failure reading SB keyword data HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + TRACDBIN(g_trac_sbe, "MVPD:SB", &io_sb_keyword, vpdSize); + + } + else //write + { + err = deviceWrite( i_target, + reinterpret_cast<void*>( &io_sb_keyword ), + vpdSize, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::SB ) ); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSetMVPDVersion() - MVPD " + "failure writing SB keyword data HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + } + + }while(0); + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"getSetMVPDVersion()" ); + + return err; + } + +///////////////////////////////////////////////////////////////////// + errlHndl_t readPNORVersion(void*& i_pnorImgHdrPtr, + sbe_image_version_t& o_version) + { + errlHndl_t err = NULL; + TRACDCOMP( g_trac_sbe, + ENTER_MRK"readPNORVersion()" ); + + do{ + // @todo RTC 34080 - support Secure Boot Header + + //For Non-secure systems, version is prefixed with + //'VERSION\0' in ASCII in the 4k header. The official + //protocol is to scan for VERSION, then grab the value + //that follows. + + char* tmpPtr = static_cast<char*>(i_pnorImgHdrPtr); + + + //Last reasonable offset is (Version size + + //size of eyecatcher) bytes from end of Page. + char* endPtr = tmpPtr +(4*KILOBYTE) - + sizeof(sbe_image_version_t&) - + sizeof(NONSECURE_VER_EYECATCH); + + // Increment pointer sizeof(uint64_t) because eyecatcher + // must be 8-byte alligned + for(; tmpPtr<endPtr; tmpPtr+=sizeof(uint64_t)) + { + if(*(reinterpret_cast<uint64_t*>(tmpPtr)) == + NONSECURE_VER_EYECATCH) + { + //increment 8 more bytes and break out + tmpPtr+=sizeof(uint64_t); + break; + } + } + + if(tmpPtr < endPtr) + { + memcpy(reinterpret_cast<void*>( &o_version ), + tmpPtr, + sizeof(o_version)); + } + else + { + + TRACFCOMP( g_trac_sbe, ERR_MRK"readPNORVersion() - VERSION not found in SBE image in PNOR"); + /*@ + * @errortype + * @moduleid SBE_READ_PNOR_VERSION + * @reasoncode SBE_VERSION_NOT_FOUND + * @userdata1 Not Used + * @userdata2 Not Used + * @devdesc Image Version not found in PNOR + * SBE image. + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_READ_PNOR_VERSION, + SBE_VERSION_NOT_FOUND, + 0, 0); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_SP_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + } + + }while(0); + + TRACDCOMP( g_trac_sbe, + EXIT_MRK"readPNORVersion()" ); + + return err; + } + +///////////////////////////////////////////////////////////////////// + errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target, + sbeSeepromSide_t& o_bootSide) + { + TRACUCOMP( g_trac_sbe, + ENTER_MRK"getSbeBootSeeprom()" ); + + errlHndl_t err = NULL; + uint64_t scomData = 0x0; + + o_bootSide = SBE_SEEPROM0; + + do{ + + size_t op_size = sizeof(scomData); + err = deviceRead( i_target, + &scomData, + op_size, + DEVICE_SCOM_ADDRESS(SBE_VITAL_REG_0x0005001C) ); + if( err ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeBootSeeprom() -Error " + "reading SBE VITAL REG (0x%.8X) from Target :" + "HUID=0x%.8X", + SBE_VITAL_REG_0x0005001C, + TARGETING::get_huid(i_target)); + break; + } + if(scomData & SBE_BOOT_SELECT_MASK) + { + o_bootSide = SBE_SEEPROM1; + } + + }while(0); + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"getSbeBootSeeprom(): o_bootSide=0x%X", o_bootSide ); + + return err; + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t getSbeInfoState(sbeTargetState_t& io_sbeState) + { + + TRACDCOMP( g_trac_sbe, + ENTER_MRK"getSbeInfoState(): HUID=0x%.8X", + TARGETING::get_huid(io_sbeState.target)); + + + errlHndl_t err = NULL; + + do{ + + /************************************************************/ + /* Set Target Properties (target_is_master previously set) */ + /************************************************************/ + io_sbeState.ec = io_sbeState.target->getAttr<TARGETING::ATTR_EC>(); + + + /*******************************************/ + /* Get PNOR SBE Version Information */ + /*******************************************/ + void* sbePnorPtr = NULL; + size_t sbePnorImageSize = 0; + sbe_image_version_t tmp_pnorVersion; + + err = findSBEInPnor(io_sbeState.target, + sbePnorPtr, + sbePnorImageSize, + &tmp_pnorVersion); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - " + "Error getting SBE Version from PNOR"); + break; + } + + // copy tmp_pnorVersion to the main structure + memcpy ( &io_sbeState.pnorVersion, + &tmp_pnorVersion, + sizeof(tmp_pnorVersion)); + + + /*******************************************/ + /* Customize SBE Image from PNOR and */ + /* Calculate CRC of the image */ + /*******************************************/ + size_t sbeImgSize = 0; + err = procCustomizeSbeImg(io_sbeState.target, + sbePnorPtr, //SBE vaddr in PNOR + FIXED_SEEPROM_WORK_SPACE, //max size + reinterpret_cast<void*> + (SBE_IMG_VADDR), //destination + sbeImgSize); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - " + "Error from procCustomizeSbeImg()"); + break; + } + + io_sbeState.customizedImage_size = sbeImgSize; + io_sbeState.customizedImage_crc = + Util::crc32_calc(reinterpret_cast<void*> + (SBE_IMG_VADDR), + sbeImgSize) ; + + TRACUCOMP( g_trac_sbe, "getSbeInfoState() - procCustomizeSbeImg(): " + "maxSize=0x%X, actSize=0x%X, crc=0x%X", + FIXED_SEEPROM_WORK_SPACE, sbeImgSize, + io_sbeState.customizedImage_crc); + + + + /*******************************************/ + /* Get MVPD SBE Version Information */ + /*******************************************/ + err = getSetMVPDVersion(io_sbeState.target, + MVPDOP_READ, + io_sbeState.mvpdSbKeyword); + if(err) + { + //If MVPD is bad, commit the error and move to the next proc + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - " + "Error reading version from MVPD"); + break; + } + + + // Determine Permanent Side from flag in MVPD + if(SEEPROM_0_PERMANENT_VALUE == + (io_sbeState.mvpdSbKeyword.flags & PERMANENT_FLAG_MASK)) + { + io_sbeState.permanent_seeprom_side = SBE_SEEPROM0; + } + else // Side 1 must be permanent + { + io_sbeState.permanent_seeprom_side = SBE_SEEPROM1; + } + + + /*******************************************/ + /* Get SEEPROM A SBE Version Information */ + /*******************************************/ + err = getSeepromSideVersion(io_sbeState.target, + EEPROM::SBE_PRIMARY, + io_sbeState.seeprom_0_ver, + io_sbeState.seeprom_0_ver_ECC_fail); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " + "getting SBE Information from SEEPROM A (0x%X)", + EEPROM::SBE_PRIMARY); + break; + } + + TRACDBIN(g_trac_sbe, "getSbeInfoState-spA", + &(io_sbeState.seeprom_0_ver), + sizeof(sbeVersion_t)); + + /*******************************************/ + /* Get SEEPROM B SBE Version Information */ + /*******************************************/ + err = getSeepromSideVersion(io_sbeState.target, + EEPROM::SBE_BACKUP, + io_sbeState.seeprom_1_ver, + io_sbeState.seeprom_1_ver_ECC_fail); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " + "getting SBE Information from SEEPROM B (0x%X)", + EEPROM::SBE_BACKUP); + break; + } + + + TRACDBIN(g_trac_sbe, "getSbeInfoState-spB", + &(io_sbeState.seeprom_1_ver), + sizeof(sbeVersion_t)); + + /***********************************************/ + /* Determine which SEEPROM System Booted On */ + /***********************************************/ + //Get Current (boot) Side + sbeSeepromSide_t tmp_cur_side = SBE_SEEPROM_INVALID; + err = getSbeBootSeeprom(io_sbeState.target, tmp_cur_side); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error returned from getSbeBootSeeprom()"); + break; + } + io_sbeState.cur_seeprom_side = tmp_cur_side; + if (io_sbeState.cur_seeprom_side == SBE_SEEPROM0) + { + io_sbeState.alt_seeprom_side = SBE_SEEPROM1; + } + else if ( io_sbeState.cur_seeprom_side == SBE_SEEPROM1) + { + io_sbeState.alt_seeprom_side = SBE_SEEPROM0; + } + else + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error: " + "Unexpected cur_seeprom_side value = 0x%X, ", + io_sbeState.cur_seeprom_side); + + /*@ + * @errortype + * @moduleid SBE_GET_TARGET_INFO_STATE + * @reasoncode SBE_INVALID_SEEPROM_SIDE + * @userdata1 Temporary Current Side + * @userdata2 SBE State Current Side + * @devdesc Invalid Boot SEEPROM Side Found + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_GET_TARGET_INFO_STATE, + SBE_INVALID_SEEPROM_SIDE, + tmp_cur_side, + io_sbeState.cur_seeprom_side); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + + break; + } + + TRACUCOMP( g_trac_sbe,"getSbeInfoState() - cur=0x%X, alt=0x%X", + io_sbeState.cur_seeprom_side, + io_sbeState.alt_seeprom_side); + + }while(0); + + return err; + + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t getSeepromSideVersion(TARGETING::Target* i_target, + EEPROM::eeprom_chip_types_t i_seepromSide, + sbeSeepromVersionInfo_t& o_info, + bool& o_seeprom_ver_ECC_fail) + { + + TRACUCOMP( g_trac_sbe, + ENTER_MRK"getSeepromSideVersion(): HUID=0x%.8X, side:%d", + TARGETING::get_huid(i_target), i_seepromSide); + + errlHndl_t err = NULL; + PNOR::ECC::eccStatus eccStatus = PNOR::ECC::CLEAN; + o_seeprom_ver_ECC_fail = false; + + size_t sbeInfoSize_ECC = (sizeof(sbeSeepromVersionInfo_t)*9)/8; + size_t sbeInfoSize_ECC_aligned = ALIGN_8(sbeInfoSize_ECC); + + // Create data buffer of larger size + // NOTE: EEPROM read will fill in smaller, unaligned size + uint8_t * tmp_data_ECC = static_cast<uint8_t*>( + malloc(sbeInfoSize_ECC_aligned)); + + do{ + + /*******************************************/ + /* Read SBE Version SBE Version Information */ + /*******************************************/ + + // Clear Buffer + memset( tmp_data_ECC, 0, sbeInfoSize_ECC_aligned ); + + //Read SBE Versions + err = deviceRead( i_target, + tmp_data_ECC, + sbeInfoSize_ECC, + DEVICE_EEPROM_ADDRESS( + i_seepromSide, + SBE_VERSION_SEEPROM_ADDRESS)); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSeepromSideVersion() - Error " + "reading SBE Version from Seeprom 0x%X, HUID=0x%.8X", + i_seepromSide, TARGETING::get_huid(i_target)); + break; + } + + TRACDBIN(g_trac_sbe, + "getSeepromSideVersion()- tmp_data_ECC (not-aligned)", + tmp_data_ECC, + sbeInfoSize_ECC); + + TRACDBIN(g_trac_sbe, + "getSeepromSideVersion()- tmp_data_ECC (aligned)", + tmp_data_ECC, + sbeInfoSize_ECC_aligned); + + + // Clear destination + memset( &o_info, 0, sizeof(o_info) ); + + + // Remove ECC + eccStatus = PNOR::ECC::removeECC( + tmp_data_ECC, + reinterpret_cast<uint8_t*>(&o_info), + sizeof(o_info)); + + TRACUCOMP( g_trac_sbe, "getSeepromSideVersion(): eccStatus=%d, " + "sizeof o_info=%d, sI_ECC=%d, sI_ECC_aligned=%d", + eccStatus, sizeof(o_info), sbeInfoSize_ECC, + sbeInfoSize_ECC_aligned); + + // Handle Uncorrectable ECC - no error log: + // clear data and set o_seeprom_ver_ECC_fail=true + if ( eccStatus == PNOR::ECC::UNCORRECTABLE ) + { + + TRACFCOMP( g_trac_sbe,ERR_MRK"getSeepromSideVersion() - ECC " + "ERROR: eccStatus=%d, side=%d, sizeof o_info=%d, " + "sI_ECC=%d, sI_ECC_aligned=%d", + eccStatus, i_seepromSide, sizeof(o_info), + sbeInfoSize_ECC, sbeInfoSize_ECC_aligned); + + memset( &o_info, 0, sizeof(o_info)); + o_seeprom_ver_ECC_fail = true; + + TRACFCOMP( g_trac_sbe, "getSeepromSideVersion(): clearing out " + "version data (o_info) for side %d and returning " + "o_seeprom_ver_ECC_fail as true (%d)", + i_seepromSide, o_seeprom_ver_ECC_fail); + } + + TRACDBIN(g_trac_sbe, + "getSeepromSideVersion: data (no ECC)", + &o_info, + sizeof(o_info)); + + }while(0); + + // Free allocated memory + free(tmp_data_ECC); + + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"getSeepromSideVersion: o_seeprom_ver_ECC_fail=%d", + o_seeprom_ver_ECC_fail ); + + return err; + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t updateSeepromSide(sbeTargetState_t i_sbeState) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"updateSeepromSide(): HUID=0x%.8X", + TARGETING::get_huid(i_sbeState.target)); + errlHndl_t err = NULL; + int64_t rc = 0; + + int64_t rc_readBack_ECC_memcmp = 0; + PNOR::ECC::eccStatus eccStatus = PNOR::ECC::CLEAN; + + // This struct is always 8-byte aligned + size_t sbeInfoSize = sizeof(sbeSeepromVersionInfo_t); + size_t sbeInfoSize_ECC = (sbeInfoSize*9)/8; + + + // Buffers for reading/writing SBE Version Information + uint8_t * sbeInfo_data = static_cast<uint8_t*>( + malloc(sbeInfoSize)); + + uint8_t * sbeInfo_data_ECC = static_cast<uint8_t*>( + malloc(sbeInfoSize_ECC)); + + uint8_t * sbeInfo_data_readBack = static_cast<uint8_t*>( + malloc(sbeInfoSize)); + + uint8_t * sbeInfo_data_ECC_readBack = static_cast<uint8_t*>( + malloc(sbeInfoSize_ECC)); + + + do{ + + + /*******************************************/ + /* Update SBE Version Information */ + /*******************************************/ + + // The new version has already been created + memcpy(sbeInfo_data, &i_sbeState.new_seeprom_ver, sbeInfoSize); + + // Inject ECC to Data + memset( sbeInfo_data_ECC, 0, sbeInfoSize_ECC); + PNOR::ECC::injectECC(sbeInfo_data, sbeInfoSize, sbeInfo_data_ECC); + + TRACDBIN( g_trac_sbe, "updateSeepromSide: Info", + sbeInfo_data, sbeInfoSize); + TRACDBIN( g_trac_sbe, "updateSeepromSide: Info ECC", + sbeInfo_data_ECC, sbeInfoSize_ECC); + + err = deviceWrite( i_sbeState.target, + sbeInfo_data_ECC, + sbeInfoSize_ECC, + DEVICE_EEPROM_ADDRESS( + i_sbeState.seeprom_side_to_update, + SBE_VERSION_SEEPROM_ADDRESS)); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"updateSeepromSide() - Error " + "Writing SBE Version Info: HUID=0x%.8X, side=%d", + TARGETING::get_huid(i_sbeState.target), + i_sbeState.seeprom_side_to_update); + break; + } + + + // In an effort to avoid an infinite loop of updates, if there + // was an ECC error when reading this SBE Version Information + // while collecting data, read back this data to ensure there + // isn't a permanent ECC error on the SEEPROM + if ( i_sbeState.new_readBack_check == true ) + { + + // Read Back Version Information + err = deviceRead( i_sbeState.target, + sbeInfo_data_ECC_readBack, + sbeInfoSize_ECC, + DEVICE_EEPROM_ADDRESS( + i_sbeState.seeprom_side_to_update, + SBE_VERSION_SEEPROM_ADDRESS)); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"updateSeepromSide() - Error " + "Reading Back SBE Version Info: HUID=0x%.8X, " + "size=%d", + TARGETING::get_huid(i_sbeState.target), + i_sbeState.seeprom_side_to_update); + break; + } + + // Compare ECC data + rc_readBack_ECC_memcmp = memcmp( sbeInfo_data_ECC, + sbeInfo_data_ECC_readBack, + sbeInfoSize_ECC); + + + // Remove ECC + eccStatus = PNOR::ECC::removeECC( sbeInfo_data_ECC_readBack, + sbeInfo_data_readBack, + sbeInfoSize); + + + TRACUCOMP( g_trac_sbe, "updateSeepromSide(): eccStatus=%d, " + "sizeof sI=%d, sI_ECC=%d, rc_ECC=%d", + eccStatus, sbeInfoSize, sbeInfoSize_ECC, + rc_readBack_ECC_memcmp); + + // Fail if uncorrectable ECC or any data miscompare + if ( ( eccStatus == PNOR::ECC::UNCORRECTABLE ) || + ( rc_readBack_ECC_memcmp != 0 ) + ) + { + + // There is an ECC issue with this SEEPROM + + TRACFCOMP( g_trac_sbe,ERR_MRK"updateSeepromSide() - ECC " + "ERROR or Data Miscimpare On SBE Version Read " + "Back: eccStatus=%d, rc_ECC=%d, " + "sI=%d, sI_ECC=%d, HUID=0x%.8X, side=%d", + eccStatus, rc_readBack_ECC_memcmp, + sbeInfoSize, sbeInfoSize_ECC, + TARGETING::get_huid(i_sbeState.target), + i_sbeState.seeprom_side_to_update); + + + /*@ + * @errortype + * @moduleid SBE_GET_SEEPROM_INFO + * @reasoncode SBE_ECC_FAIL + * @userdata1[0:15] ECC Status + * @userdata1[16:31] SEEPROM Side + * @userdata1[32:47] RC on Data Compare with ECC + * @userdata1[48:63] <unused> + * @userdata2[0:31] Size - No Ecc + * @userdata2[32:63] Size - ECC + * @devdesc ECC or Data Miscompare Fail Reading Back + * SBE Verion Information + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_UPDATE_SEEPROMS, + SBE_ECC_FAIL, + FOUR_UINT16_TO_UINT64( + eccStatus, + i_sbeState.seeprom_side_to_update, + rc_readBack_ECC_memcmp, + 0x0), + TWO_UINT32_TO_UINT64(sbeInfoSize, + sbeInfoSize_ECC)); + + err->collectTrace(SBE_COMP_NAME); + err->addHwCallout( i_sbeState.target, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DELAYED_DECONFIG, + HWAS::GARD_Predictive ); + + + ErrlUserDetailsTarget(i_sbeState.target).addToLog(err); + + break; + } + + } + + /*******************************************/ + /* Update SBE with Customized Image */ + /*******************************************/ + // The Customized Image For This Target Still Resides In + // The SBE Update VMM Space: SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE + + + // Inject ECC + // clear out back half of page block to use as temp space + // for ECC injected SBE Image. + rc = mm_remove_pages(RELEASE, + reinterpret_cast<void*> + (SBE_ECC_IMG_VADDR), + SBE_ECC_IMG_MAX_SIZE); + if( rc ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"updateSeepromSide() - Error " + "from mm_remove_pages : rc=%d, HUID=0x%.8X.", + rc, TARGETING::get_huid(i_sbeState.target) ); + /*@ + * @errortype + * @moduleid SBE_UPDATE_SEEPROMS + * @reasoncode SBE_REMOVE_PAGES_FOR_EC + * @userdata1 Requested Address + * @userdata2 rc from mm_remove_pages + * @devdesc updateProcessorSbeSeeproms> mm_remove_pages + * RELEASE failed + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_UPDATE_SEEPROMS, + SBE_REMOVE_PAGES_FOR_EC, + TO_UINT64(SBE_ECC_IMG_VADDR), + TO_UINT64(rc)); + //Target isn't directly related to fail, but could be useful + // to see how far we got before failing. + ErrlUserDetailsTarget(i_sbeState.target + ).addToLog(err); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + break; + } + + + //align size, calculate ECC size + size_t sbeImgSize = ALIGN_8(i_sbeState.customizedImage_size); + size_t sbeEccImgSize = static_cast<size_t>(sbeImgSize*9/8); + + + assert(sbeEccImgSize <= SBE_ECC_IMG_MAX_SIZE, + "updateSeepromSide() SBE Image with ECC too large"); + + TRACUCOMP( g_trac_sbe, INFO_MRK"updateSeepromSide(): " + "SBE_VADDR=0x%.16X, ECC_VADDR=0x%.16X, size=0x%.8X, " + "eccSize=0x%.8X", + SBE_IMG_VADDR, + SBE_ECC_IMG_VADDR, + sbeImgSize, + sbeEccImgSize ); + + PNOR::ECC::injectECC(reinterpret_cast<uint8_t*>(SBE_IMG_VADDR), + sbeImgSize, + reinterpret_cast<uint8_t*> + (SBE_ECC_IMG_VADDR)); + + TRACDBIN(g_trac_sbe,"updateSeepromSide()-start of IMG - no ECC", + reinterpret_cast<void*>(SBE_IMG_VADDR), 0x80); + TRACDBIN(g_trac_sbe,"updateSeepromSide()-start of IMG - ECC", + reinterpret_cast<void*>(SBE_ECC_IMG_VADDR), 0x80); + + + //Write new data to seeprom + TRACFCOMP( g_trac_sbe, INFO_MRK"updateSeepromSide(): Write New " + "SBE Image for Target 0x%X to Seeprom %d", + TARGETING::get_huid(i_sbeState.target), + i_sbeState.seeprom_side_to_update ); + + //Write image to indicated side + err = deviceWrite(i_sbeState.target, + reinterpret_cast<void*> + (SBE_ECC_IMG_VADDR), + sbeEccImgSize, + DEVICE_EEPROM_ADDRESS( + i_sbeState.seeprom_side_to_update, + SBE_IMAGE_SEEPROM_ADDRESS)); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"updateSeepromSide() - Error " + "writing new SBE image to size=%d. HUID=0x%.8X." + "SBE_VADDR=0x%.16X, ECC_VADDR=0x%.16X, size=0x%.8X, " + "eccSize=0x%.8X, EEPROM offset=0x%X", + i_sbeState.seeprom_side_to_update, + TARGETING::get_huid(i_sbeState.target), + SBE_IMG_VADDR, SBE_ECC_IMG_VADDR, sbeImgSize, + sbeEccImgSize, SBE_IMAGE_SEEPROM_ADDRESS); + break; + } + + }while(0); + + // Free allocated memory + free( sbeInfo_data ); + free( sbeInfo_data_ECC); + free( sbeInfo_data_readBack ); + free( sbeInfo_data_ECC_readBack ); + + return err; + + + } + + + +///////////////////////////////////////////////////////////////////// + errlHndl_t getTargetUpdateActions(sbeTargetState_t& io_sbeState) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"getTargetUpdateActions()"); + errlHndl_t err = NULL; + + bool seeprom_0_isDirty = false; + bool seeprom_1_isDirty = false; + bool current_side_isDirty = false; + bool alt_side_isDirty = false; + + + do{ + + + + /**************************************************************/ + /* Compare SEEPROM 0 with PNOR and Customized Image CRC -- */ + /* -- dirty or clean? */ + /**************************************************************/ + if ( + // Check PNOR and SEEPROM 0 Version + (0 != memcmp(&(io_sbeState.pnorVersion), + &(io_sbeState.seeprom_0_ver.image_version), + SBE_IMAGE_VERSION_SIZE)) + || + // Check CRC and SEEPROM 0 CRC + (0 != memcmp(&(io_sbeState.customizedImage_crc), + &(io_sbeState.seeprom_0_ver.data_crc), + SBE_DATA_CRC_SIZE)) + ) + { + seeprom_0_isDirty = true; + } + + + + /**************************************************************/ + /* Compare SEEPROM 1 with PNOR and Customized Image CRC -- */ + /* -- dirty or clean? */ + /**************************************************************/ + if ( + // Check PNOR and SEEPROM 1 Version + (0 != memcmp(&(io_sbeState.pnorVersion), + &(io_sbeState.seeprom_1_ver.image_version), + SBE_IMAGE_VERSION_SIZE)) + || + // Check CRC and SEEPROM 1 CRC + (0 != memcmp(&(io_sbeState.customizedImage_crc), + &(io_sbeState.seeprom_1_ver.data_crc), + SBE_DATA_CRC_SIZE)) + ) + { + seeprom_1_isDirty = true; + } + + + + /**************************************************************/ + /* Determine what side to update */ + /**************************************************************/ + + //If all clean, we are done: + if((!seeprom_0_isDirty) && + (!seeprom_1_isDirty)) + { + break; + } + + //Need to update something + if( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) + { + current_side_isDirty = seeprom_0_isDirty; + alt_side_isDirty = seeprom_1_isDirty; + } + else + { + current_side_isDirty = seeprom_1_isDirty; + alt_side_isDirty = seeprom_0_isDirty; + } + + + // Set system_situation - bits defined in sbe_update.H + uint8_t system_situation = 0x00; + + // Bit 0: current_side is permanent (0) or temp (1) + // -- defaulted to 0 (cur=perm) above + if ( io_sbeState.cur_seeprom_side != + io_sbeState.permanent_seeprom_side ) + { + system_situation |= SITUATION_CUR_IS_TEMP; + } + + // Bit 1: current_side clean (0) or dirty (1) + // -- defaulted to 0 (clean) above + if ( current_side_isDirty ) + { + system_situation |= SITUATION_CUR_IS_DIRTY; + } + + // Bit 2: alt_side is clean (0) or dirty (1) + if ( alt_side_isDirty ) + { + system_situation |= SITUATION_ALT_IS_DIRTY; + } + + + // Call function to update actions + decisionTreeForUpdates(io_sbeState, system_situation); + + TRACUCOMP( g_trac_sbe, "getTargetUpdateActions() - system_situation" + "= 0x%.2X, actions=0x%.8X, Update EEPROM=0x%X", + system_situation, + io_sbeState.update_actions, + io_sbeState.seeprom_side_to_update); + + + /**************************************************************/ + /* Setup new SBE Image Version Info */ + /**************************************************************/ + // Setup new SBE Image Version Info + memset(&(io_sbeState.new_seeprom_ver), + 0x0, + sizeof(sbeSeepromVersionInfo_t)); + + + io_sbeState.new_seeprom_ver.struct_version = + SBE_SEEPROM_STRUCT_VERSION; + + memcpy( &(io_sbeState.new_seeprom_ver.image_version), + &(io_sbeState.pnorVersion), + SBE_IMAGE_VERSION_SIZE); + + memcpy( &(io_sbeState.new_seeprom_ver.data_crc), + &(io_sbeState.customizedImage_crc), + SBE_DATA_CRC_SIZE); + + // If there was an ECC fail on either SEEPROM, do a read-back + // Check when writing this information to the SEEPROM + io_sbeState.new_readBack_check = ( + io_sbeState.seeprom_0_ver_ECC_fail || + io_sbeState.seeprom_1_ver_ECC_fail); + + + TRACDBIN( g_trac_sbe, + "getTargetUpdateActions() - New SBE Version Info", + &(io_sbeState.new_seeprom_ver), + sizeof(sbeSeepromVersionInfo_t)); + + /**************************************************************/ + /* Update MVPD Struct to write back */ + /**************************************************************/ + + // Note: mvpdSbKeyword.flags updated above + memset(&(io_sbeState.mvpdSbKeyword), + 0, + sizeof(sbeSeepromVersionInfo_t)); + + if ( io_sbeState.seeprom_side_to_update == EEPROM::SBE_PRIMARY ) + { + memcpy( &(io_sbeState.mvpdSbKeyword.seeprom_0_data_crc), + &(io_sbeState.customizedImage_crc), + SBE_DATA_CRC_SIZE); + + memcpy( &(io_sbeState.mvpdSbKeyword.seeprom_0_short_version), + &(io_sbeState.pnorVersion), + SBE_MVPD_SHORT_IMAGE_VERSION_SIZE); + } + else // EEPROM::SBE_Backup + { + memcpy( &(io_sbeState.mvpdSbKeyword.seeprom_1_data_crc), + &(io_sbeState.customizedImage_crc), + SBE_DATA_CRC_SIZE); + + memcpy( &(io_sbeState.mvpdSbKeyword.seeprom_1_short_version), + &(io_sbeState.pnorVersion), + SBE_MVPD_SHORT_IMAGE_VERSION_SIZE); + } + + + + + + + }while(0); + + return err; + + + } + +///////////////////////////////////////////////////////////////////// + void decisionTreeForUpdates(sbeTargetState_t& io_sbeState, + uint8_t i_system_situation) + { + + + uint32_t l_actions = CLEAR_ACTIONS; + io_sbeState.update_actions = CLEAR_ACTIONS; + io_sbeState.seeprom_side_to_update = EEPROM::LAST_CHIP_TYPE; + + + do{ + + // To be safe, we're only look at the bits defined in sbe_update.H + i_system_situation &= SITUATION_ALL_BITS_MASK; + + // @todo RTC 47033 set bit 1 in MVPD SB flag byte to + // represent the which SEEPROM the FSP should reboot from + + + switch ( i_system_situation ) + { + case ( SITUATION_CUR_IS_TEMP | + SITUATION_CUR_IS_DIRTY | + SITUATION_ALT_IS_DIRTY ) : + + // 0xE0: cur=temp, cur=dirty, alt=dirty + // Treat like 0xC0 + // not sure why we booted off of temp + + case ( SITUATION_CUR_IS_TEMP | + SITUATION_CUR_IS_DIRTY | + SITUATION_ALT_IS_CLEAN ) : + + + // 0xC0: cur=temp, cur=dirty, alt=clean + // Bad path: we shouldn't be booting to dirty side + // Update Alt and re-IPL to it + // Update MVPD flag: make cur=perm (because we know it + // works a bit) + + l_actions |= IPL_RESTART; + l_actions |= DO_UPDATE; + + // Set Update side to alt + io_sbeState.seeprom_side_to_update = + ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; + + // Update MVPD flag make cur=perm + ( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) ? + // clear bit 0 + io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK + : //set bit 0 + io_sbeState.mvpdSbKeyword.flags |= PERMANENT_FLAG_MASK; + + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "cur=temp/dirty. Update alt. Re-IPL. " + "Update MVPD flag. " + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + + break; + + case ( SITUATION_CUR_IS_TEMP | + SITUATION_CUR_IS_CLEAN | + SITUATION_ALT_IS_DIRTY ) : + + // 0xA0: cur=temp, cur=clean, alt=dirty + // Common 2nd step of Code Update path + // Update Alt and Continue IPL + // Update MVPD flag: make cur=perm + + l_actions |= DO_UPDATE; + + // Set Update side to alt + io_sbeState.seeprom_side_to_update = + ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; + + + // MVPD flag Update + // Update MVPD flag make cur=perm + ( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) ? + // clear bit 0 + io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK + : //set bit 0 + io_sbeState.mvpdSbKeyword.flags |= PERMANENT_FLAG_MASK; + + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "cur=temp/clean, alt=dirty. " + "Update alt. Continue IPL. Update MVPD flag." + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + + + case ( SITUATION_CUR_IS_TEMP | + SITUATION_CUR_IS_CLEAN | + SITUATION_ALT_IS_CLEAN ) : + + // 0x80: cur=temp, cur=clean, alt=clean + // Should've broke earlier -- both sides are clean, + // but handle just in case + // Not sure why cur=temp, but do nothing + + l_actions = CLEAR_ACTIONS; + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "Both sides clean-no updates. cur was temp. " + "Continue IPL. (d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + + + case ( SITUATION_CUR_IS_PERM | + SITUATION_CUR_IS_DIRTY | + SITUATION_ALT_IS_DIRTY ) : + + // 0x60: cur=perm, cur=dirty, alt=dirty + // Common situation: likely first step of code update + // Update alt and re-ipl + l_actions |= IPL_RESTART; + l_actions |= DO_UPDATE; + + // Set Update side to alt + io_sbeState.seeprom_side_to_update = + ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "cur=perm/dirty, alt=dirty. Update alt. re-IPL. " + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + + + case ( SITUATION_CUR_IS_PERM | + SITUATION_CUR_IS_DIRTY | + SITUATION_ALT_IS_CLEAN ) : + + // 0x40: cur=perm, cur=dirty, alt=clean + // @todo RTC 40733 - Ask FSP if we just asked for re-IPL + // for now just continue IPL + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "cur=perm/dirty, alt=clean. Continue IPL. " + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + break; + + + case ( SITUATION_CUR_IS_PERM | + SITUATION_CUR_IS_CLEAN | + SITUATION_ALT_IS_DIRTY ) : + + // 0x20: cur=perm, cur=clean, alt=dirty + // Not sure why alt is dirty, but update alt and + // continue IPL + + l_actions |= DO_UPDATE; + + // Set Update side to alt + io_sbeState.seeprom_side_to_update = + ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "cur=perm/clean, alt=dirty. " + "Update alt. Continue IPL. " + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + + + case ( SITUATION_CUR_IS_PERM | + SITUATION_CUR_IS_CLEAN | + SITUATION_ALT_IS_CLEAN ) : + + // 0x0: cur=perm, cur=clean, alt=clean + // Should've broke earlier -- both sides are clean, + // but handle just in case + l_actions = CLEAR_ACTIONS; + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "Both sides clean-no updates. cur was temp. " + "Continue IPL. (d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + + default: + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "Unsupported Scenario. Just Continue IPL. " + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + } + + + // Set actions + io_sbeState.update_actions = static_cast<sbeUpdateActions_t> + (l_actions); + + TRACUCOMP( g_trac_sbe, "decisionTreeForUpdates() - i_system_situation= " + "0x%.2X, actions=0x%.8X, Update EEPROM=0x%X, doU=%d, " + "reIpl=%d", + i_system_situation, + io_sbeState.update_actions, + io_sbeState.seeprom_side_to_update, + io_sbeState.update_actions && DO_UPDATE, + io_sbeState.update_actions && IPL_RESTART); + + }while(0); + + return; + + + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t performUpdateActions(sbeTargetState_t& io_sbeState) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"performUpdateActions()"); + errlHndl_t err = NULL; + + do{ + + + /**************************************************************/ + /* Update Actions: */ + /* 1) Update SEEPROM */ + /* 2) Update MVPD */ + /**************************************************************/ + + /**************************************************************/ + /* 1) Update SEEPROM */ + /**************************************************************/ + err = updateSeepromSide(io_sbeState); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"performUpdateActions() - " + "updateProcessorSbeSeeproms() failed. HUID=0x%.8X.", + TARGETING::get_huid(io_sbeState.target)); + continue; + } + + /**************************************************************/ + /* 2) Update MVPD */ + /**************************************************************/ + //Update MVPD anytime we do any sort of SBE Update. + err = getSetMVPDVersion(io_sbeState.target, + MVPDOP_WRITE, + io_sbeState.mvpdSbKeyword); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"performUpdateActions() - " + "Error Updating MVPD with new SBE Image Info " + "HUID=0x%.8X, rc=0x%.4x", + TARGETING::get_huid(io_sbeState.target), + err->reasonCode()); + break; + } + + + + }while(0); + + return err; + + + } + +///////////////////////////////////////////////////////////////////// + // @todo RTC 47033 - Likely to remove this function because creating a + // CRC from the customized image seems more efficient. + errlHndl_t getDataCrc(TARGETING::Target* i_target, + uint32_t& o_data_crc) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"getDataCrc"); + + errlHndl_t err = NULL; + size_t data_size = 0; + uint8_t* data_ptr = NULL; + uint8_t index = 0; + + size_t mvpd_pdG_size = 0; + uint8_t* mvpd_pdG_data_ptr = NULL; + size_t mvpd_pdR_size = 0; + uint8_t* mvpd_pdR_data_ptr = NULL; + + o_data_crc = 0x0; + + do{ + + + /*******************************************/ + /* Get #G Ring Data from MVPD */ + /*******************************************/ + // Note: First read with NULL for o_buffer sets vpdSize to the + // correct length + err = deviceRead( i_target, + NULL, + mvpd_pdG_size, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::pdG ) ); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getDataCrc() - MVPD failure getting pdG keyword size HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + // Create buffer to capture the data + mvpd_pdG_data_ptr = static_cast<uint8_t*>(malloc(mvpd_pdG_size)); + + err = deviceRead( i_target, + mvpd_pdG_data_ptr, + mvpd_pdG_size, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::pdG ) ); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getDataCrc() - MVPD failure read pdG data HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + + /*******************************************/ + /* Get #R Ring Data from MVPD */ + /*******************************************/ + // Note: First read with NULL for o_buffer sets vpdSize to the + // correct length + err = deviceRead( i_target, + NULL, + mvpd_pdR_size, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::pdR ) ); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getDataCrc() - MVPD failure getting pdR keyword size HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + // Create buffer to capture the data + mvpd_pdR_data_ptr = static_cast<uint8_t*>(malloc(mvpd_pdR_size)); + + err = deviceRead( i_target, + mvpd_pdR_data_ptr, + mvpd_pdR_size, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::pdR ) ); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getDataCrc() - MVPD failure read pdG data HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + + /**********************************************/ + /* Concatenate the Data and compute the CRC */ + /**********************************************/ + // Add up all the sizes and create a buffer + data_size = mvpd_pdG_size + mvpd_pdR_size; + data_ptr = static_cast<uint8_t*>(malloc(data_size)); + + + memcpy( data_ptr, mvpd_pdG_data_ptr, mvpd_pdG_size); + index = mvpd_pdG_size; + + memcpy( &(data_ptr[index]), mvpd_pdR_data_ptr, mvpd_pdR_size); + + o_data_crc = Util::crc32_calc(data_ptr, data_size); + + + }while(0); + + // Free allocated memory + free(mvpd_pdG_data_ptr); + free(mvpd_pdR_data_ptr); + + + TRACUCOMP( g_trac_sbe, EXIT_MRK"getDataCrc: o_data_crc= 0x%.4x, " + "pdG_size=%d, pdR_size=%d", + o_data_crc, mvpd_pdG_size, mvpd_pdR_size); + + return err; + + } + + + +///////////////////////////////////////////////////////////////////// + uint32_t trimBitMask(uint32_t i_mask, + size_t i_maxBits) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"trimBitMask(i_mask=0x%.8X, i_maxBits=0x%.8X)", + i_mask, i_maxBits); + uint32_t retMask = i_mask; + + + while(__builtin_popcount(retMask) > static_cast<int32_t>(i_maxBits)) + { + retMask ^= 0x1 << static_cast<uint32_t>(__builtin_ctz(retMask)); + } + + TRACDCOMP( g_trac_sbe, + EXIT_MRK"trimBitMask(): retMask=0x%.8X", + retMask); + + return retMask; + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t createSbeImageVmmSpace(void) + { + + TRACDCOMP( g_trac_sbe, + ENTER_MRK"createSbeImageVmmSpace"); + + int64_t rc = 0; + errlHndl_t err = NULL; + + do{ + + //Make sure procedure constants keep within expected range. + assert((FIXED_SEEPROM_WORK_SPACE <= VMM_SBE_UPDATE_SIZE/2), + "createSbeImageVmmSpace() FIXED_SEEPROM_WORK_SPACE too large"); + assert((FIXED_RING_BUF_SIZE <= VMM_SBE_UPDATE_SIZE/4), + "createSbeImageVmmSpace() FIXED_RING_BUF_SIZE too large"); + + + // Create a memory block to serve as XIP Customize scratch space + // NOTE: using mm_alloc_block since this code is running before we + // have mainstore and we must have contiguous blocks of memory for + // the customize procedure to use. + rc = mm_alloc_block( NULL, + reinterpret_cast<void*> + (VMM_VADDR_SBE_UPDATE), + VMM_SBE_UPDATE_SIZE); + + if( rc ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"createSbeImageVmmSpace() - " + "Error from mm_alloc_block : rc=%d", rc ); + /*@ + * @errortype + * @moduleid SBE_CREATE_TEST_SPACE + * @reasoncode SBE_ALLOC_BLOCK_FAIL + * @userdata1 Requested Address + * @userdata2 rc from mm_alloc_block + * @devdesc updateProcessorSbeSeeproms> Error + * from mm_alloc_block + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_CREATE_TEST_SPACE, + SBE_ALLOC_BLOCK_FAIL, + TO_UINT64(VMM_VADDR_SBE_UPDATE), + TO_UINT64(rc)); + + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + + break; + } + + rc = mm_set_permission(reinterpret_cast<void*> + (VMM_VADDR_SBE_UPDATE), + VMM_SBE_UPDATE_SIZE, + WRITABLE | ALLOCATE_FROM_ZERO ); + if( rc ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"createSbeImageVmmSpace() - Error from mm_set_permission : rc=%d", rc ); + /*@ + * @errortype + * @moduleid SBE_CREATE_TEST_SPACE + * @reasoncode SBE_SET_PERMISSION_FAIL + * @userdata1 Requested Address + * @userdata2 rc from mm_set_permission + * @devdesc updateProcessorSbeSeeproms> Error from + * mm_set_permission + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_CREATE_TEST_SPACE, + SBE_SET_PERMISSION_FAIL, + TO_UINT64(VMM_VADDR_SBE_UPDATE), + TO_UINT64(rc)); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + break; + } + + }while(0); + + TRACDCOMP( g_trac_sbe, + EXIT_MRK"createSbeImageVmmSpace() - rc =0x%X", rc); + + return err; + + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t cleanupSbeImageVmmSpace(void) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"cleanupSbeImageVmmSpace"); + + errlHndl_t err = NULL; + int64_t rc = 0; + + do{ + + //release all pages in page block to ensure we + //start with clean state + rc = mm_remove_pages(RELEASE, + reinterpret_cast<void*> + (VMM_VADDR_SBE_UPDATE), + VMM_SBE_UPDATE_SIZE); + if( rc ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"cleanupSbeImageVmmSpace() - " + "Error from mm_remove_pages : rc=%d", rc ); + /*@ + * @errortype + * @moduleid SBE_CLEANUP_TEST_SPACE + * @reasoncode SBE_REMOVE_PAGES_FAIL + * @userdata1 Requested Address + * @userdata2 rc from mm_remove_pages + * @devdesc updateProcessorSbeSeeproms> mm_remove_pages + * RELEASE failed + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_CLEANUP_TEST_SPACE, + SBE_REMOVE_PAGES_FAIL, + TO_UINT64(VMM_VADDR_SBE_UPDATE), + TO_UINT64(rc)); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + } + + }while(0); + + + TRACDCOMP( g_trac_sbe, + EXIT_MRK"cleanupSbeImageVmmSpace() - rc =0x%X", rc); + + return err; + + } + + +} //end SBE Namespace diff --git a/src/usr/sbe/sbe_update.H b/src/usr/sbe/sbe_update.H new file mode 100644 index 000000000..bb161dfd0 --- /dev/null +++ b/src/usr/sbe/sbe_update.H @@ -0,0 +1,439 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbe/sbe_update.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 __SBE_SBE_UPDATE_H +#define __SBE_SBE_UPDATE_H + + +#include <stdint.h> +#include <builtins.h> +#include <errl/errlentry.H> +#include <pnor/pnorif.H> +#include <vmmconst.h> +#include <targeting/common/targetservice.H> +#include <i2c/eepromif.H> + +namespace SBE +{ + /******************************************/ + /* Constants */ + /******************************************/ + // Size of CRC used for version checking + const size_t SBE_DATA_CRC_SIZE = 4; // 4 bytes (32 bits) + + // Using only first 20 bytes of 64-byte sbe_image_version + const size_t SBE_MVPD_SHORT_IMAGE_VERSION_SIZE = 20; + + // Version of Struct stored in SEEPROM + const uint32_t SBE_SEEPROM_STRUCT_VERSION = 0x00000001; + + // Used for locations of SBE_Version and SBE Image on a SEEPROM + const uint64_t SBE_IMAGE_SEEPROM_ADDRESS = 0x400; // 1KB + const uint64_t SBE_VERSION_SEEPROM_ADDRESS = 0x300; // 1KB - 256B + + //Used to read SBE Boot Side from processor + const uint64_t SBE_VITAL_REG_0x0005001C = 0x005001C; + const uint64_t SBE_BOOT_SELECT_MASK = 0x0080000000000000; + + // PNOR SBE and SBEC Partition constants + const uint32_t MAX_SBE_ENTRIES = 9; + const uint32_t SBETOC_EYECATCH = 0x53424500; //'SBE\0' + const uint64_t NONSECURE_VER_EYECATCH = 0x56455253494F4E00; //'VERSION\0' + const uint32_t SUPPORTED_TOC_VER = 0x00000001; + + // MVPD SB Keyword contants + const size_t MVPD_SB_RECORD_SIZE = 49; + const uint8_t PERMANENT_FLAG_MASK = 0x80; + // PERMANENT FLAG = 0 -> indicates 0 is permanent. + const uint8_t SEEPROM_0_PERMANENT_VALUE = 0x00; + const uint8_t SEEPROM_1_PERMANENT_VALUE = 0x80; + // @todo RTC 47033 - add support for bit 1 (0x40): temp boot side + + + // Situation constants -- bits numbered from left to right + const uint8_t SITUATION_ALL_BITS_MASK = 0xE0; + // Bit 0: current side is permanent (=0) or temp (=1) + const uint8_t SITUATION_CUR_IS_PERM = 0x00; + const uint8_t SITUATION_CUR_IS_TEMP = 0x80; + + // Bit 1: current_side clean (=0) or dirty (=1) + const uint8_t SITUATION_CUR_IS_CLEAN = 0x00; + const uint8_t SITUATION_CUR_IS_DIRTY = 0x40; + + // Bit 2: alt side clean (=0) or dirty (=1) + const uint8_t SITUATION_ALT_IS_CLEAN = 0x00; + const uint8_t SITUATION_ALT_IS_DIRTY = 0x20; + + + /******************************************/ + /* Enums */ + /******************************************/ + // Used for MVPD function + enum opType_t + { + MVPDOP_UNKNOWN, // Invalid + MVPDOP_READ, // Read version data from MVPD + MVPDOP_WRITE, // Write version data to MVPD + }; + + // Used to keep track of perm/temp, and cur/alt + enum sbeSeepromSide_t + { + SBE_SEEPROM0, // corresponds to EEPROM::SBE_PRIMARY + SBE_SEEPROM1, // corresponts to EEPROM::SBE_BACKUP + SBE_SEEPROM_INVALID, + }; + + // Actions can be combined + enum sbeUpdateActions_t + { + CLEAR_ACTIONS = 0x00000000, + DO_UPDATE = 0x00000001, + IPL_RESTART = 0x00000002, + CALLOUT_SBE_CODE = 0x00000004, + UNSUPPORTED_SITUATION = 0x00000008, + }; + + + /******************************************/ + /* Structs */ + /******************************************/ + + /** + * @brief Struct containing version information stored on SBE SEEPROMs + * + * NOTE: For ECC purposes, this must be 8-byte aligned, + * so pad data if necessary + * struct_version 1: size = 4+64+4 = 72 (aligned) + */ + struct sbeSeepromVersionInfo_t + { + uint32_t struct_version; + uint8_t image_version[SBE_IMAGE_VERSION_SIZE]; + uint8_t data_crc[SBE_DATA_CRC_SIZE]; + } PACKED; + + + /** + * @brief Struct of individual SBE entry in SBE and SBEC + * Table of Contents in PNOR partitions + */ + struct sbeTocEntry_t + { + uint32_t ec; // Chip EC, right aligned + uint32_t offset; // Offset within partition, in bytes + uint32_t size; // Size of image, in bytes + } PACKED; + + /** + * @brief Layout of Table of Contents at beginning of SBE and + * SBEC Partitions in PNOR + */ + struct sbeToc_t + { + uint32_t eyeCatch; // Expected to contain 'SBE\0' + uint32_t tocVersion; // Version of SBE TOC + sbeTocEntry_t entries[MAX_SBE_ENTRIES]; // Image entries + } PACKED; + + /** + * @brief Layout of SB keyword in MVPD + */ + struct mvpdSbKeyword_t + { + uint8_t flags; // 1 byte for various flags + + uint8_t seeprom_0_data_crc[SBE_DATA_CRC_SIZE]; + uint8_t seeprom_0_short_version[SBE_MVPD_SHORT_IMAGE_VERSION_SIZE]; + + uint8_t seeprom_1_data_crc[SBE_DATA_CRC_SIZE]; + uint8_t seeprom_1_short_version[SBE_MVPD_SHORT_IMAGE_VERSION_SIZE]; + } PACKED; + + + /** + * @brief Contains the SBE state for a given target + */ + struct sbeTargetState_t + { + + // Target Information + TARGETING::Target* target; + bool target_is_master; + uint8_t ec; + + // Current Target SBE State Information + sbe_image_version_t pnorVersion; + mvpdSbKeyword_t mvpdSbKeyword; + + sbeSeepromVersionInfo_t seeprom_0_ver; + sbeSeepromVersionInfo_t seeprom_1_ver; + + bool seeprom_0_ver_ECC_fail; + bool seeprom_1_ver_ECC_fail; + + sbeSeepromSide_t cur_seeprom_side; // aka 'booted' side + sbeSeepromSide_t alt_seeprom_side; + sbeSeepromSide_t permanent_seeprom_side; + + // Customized Image Information for this Target + size_t customizedImage_size; + uint32_t customizedImage_crc; + + // Update Fields and New Fields to be Written to the Target + sbeUpdateActions_t update_actions; + EEPROM::eeprom_chip_types_t seeprom_side_to_update; + + sbeSeepromVersionInfo_t new_seeprom_ver; + bool new_readBack_check; + + }; + + + + /******************************************/ + /* Functions -- High Level Functions */ + /******************************************/ + + /** + * @brief Collects SBE Information for a specifc target + * + * @param[io/out] io_sbeState Struct containing SBE State of the target + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getSbeInfoState(sbeTargetState_t& io_sbeState); + + /** + * @brief Analyze and Determine Update Actions for a specific target + * + * @param[io/out] io_sbeState Struct containing SBE State of the target + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getTargetUpdateActions(sbeTargetState_t& io_sbeState); + + /** + * @brief Performs the Update Actions for a specific target + * + * @param[io/out] io_sbeState Struct containing SBE State of the target + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t performUpdateActions(sbeTargetState_t& io_sbeState); + + + /******************************************/ + /* Functions -- System Access */ + /******************************************/ + + /** + * @brief Read or Write SB Keyword in MVPD + * + * @param[in] i_target Target processor + * + * @param[in] i_op Indicates read or write + * + * @param[io/out] io_sb_keyword Pointer to MVPD SBE Keyword struct + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getSetMVPDVersion(TARGETING::Target* i_target, + opType_t i_op, + mvpdSbKeyword_t& io_sb_keyword); + + + /** + * @brief Read SBE Version from PNOR + * + * @param[in] i_pnorImgHdrPtr Pointer to Image Header in PNOR + * + * @param[out] o_version Pointer to SBE Version struct + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t readPNORVersion(void*& i_pnorImgHdrPtr, + sbe_image_version_t& o_version); + + + /** + * @brief Customize SBE Image for current Processor + * + * @param[in] i_target Target processor to customize + * + * @param[in] i_sbePnorPtr Pointer to SBE Image in PNOR + * Expected that this pointer was found with + * findSBEInPnor() function and is past any + * image header + * + * @param[in] i_maxImgSize Maximum size of customized image + * + * @param[out] io_imgPtr Pointer to SBE image in memory + * Memory from this pointer through + * i_maxImgSize is expected to be pre-alloacted + * + * @param[out] o_actImgSize Actual size of the customized image + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t procCustomizeSbeImg(TARGETING::Target* i_target, + void* i_sbePnorPtr, + size_t i_maxImgSize, + void* io_imgPtr, + size_t& o_actImgSize); + + /** + @brief Collect data for CRC, Concatenate the data, then compute the CRC + * + * @param[in] i_target Target processor + * + * @param[out] o_data_crc CRC computed from concatenated collected data + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getDataCrc(TARGETING::Target* i_target, + uint32_t& o_data_crc); + + + /** + * @brief Determines which Seeprom was used to boot the SBE + * + * @param[in] i_target Target processor to customize + * + * @param[out] o_bootSide The Seeprom the SBE booted from + * + * @return errlHndl_t Error log handle on failure. + */ + + errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target, + sbeSeepromSide_t& o_bootSide); + + + /** + * @brief Collects Version information from a specific SEEPROM + * + * @param[in] i_target Target processor to customize + * + * @param[in] i_seepromSide The SEEPROM on the target that to collect + * the information from + * + * @param[out] o_info Struct containing the SBE Version Information + * + * @param[out] o_seeprom_ver_ECC_fail Reports if there was an ECC erorr on + * the collected information + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getSeepromSideVersion(TARGETING::Target* i_target, + EEPROM::eeprom_chip_types_t i_seepromSide, + sbeSeepromVersionInfo_t& o_info, + bool& o_seeprom_ver_ECC_fail); + + /** + * @brief Updates a specific SEEPROM + * + * @param[io/out] io_sbeState Struct containing SBE State of the target + * and the information to be used for updating + * the SBE State of the target + */ + errlHndl_t updateSeepromSide(sbeTargetState_t i_sbeState); + + + + /******************************************/ + /* Functions -- Helper Functions */ + /******************************************/ + + /** + * @brief Determines the Update Actions for a specific target situation + * + * @param[io/out] io_sbeState Struct containing SBE State of the target + * and is updated based on the situation + * + * @param[in] i_system_situation SBE Situation of the target that requires + * analysis to determine Update Actions + * + * @return void + */ + void decisionTreeForUpdates(sbeTargetState_t& io_sbeState, + uint8_t i_system_situation); + + /** + * @brief Creates the memory space needed for SBE Image Customization + * by allocating and setting permissions on VMM_VADDR_SBE_UPDATE + * area defined in vmmconst.H + * + * @param[in] void + * + * @return void + */ + errlHndl_t createSbeImageVmmSpace(void); + + /** + * @brief Cleans up memory space needed for SBE Image Customization + * + * @param[in] void + * + * @return void + */ + errlHndl_t cleanupSbeImageVmmSpace(void); + + /** + * @brief Select best cores to include in SBE Image. + * The output is used to indicate to p8_xip_customize which cores + * should be included in the SBE image. + * + * @param[in] i_target Target processor to use for core selection + * + * @param[in] i_maxCores Maximum number of cores to select for inclusion + * in the SBE Image + * + * @param[out] o_coreMask Core Mask for the target that does not exceed + * the maximum number of cores + * NOTE: bits 16:31 = EX0:EX15 + * This value is used as input into + * p8_xip_customize.C + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t selectBestCores(TARGETING::Target* i_target, + size_t i_maxCores, + uint32_t& o_coreMask); + + + /** + * @brief Reduces bits set in a bit mask until there is a + * a maximum number of bits set + * + * @param[in] i_mask Starting mask to be reduced + * + * @param[in] i_maxBits Maximum number of bits that the + * returned Bit Mask can contain + * + * @return uint32_t Bit Mask + */ + uint32_t trimBitMask(uint32_t i_mask, + size_t i_maxBits); + + +} //end namespace SBE +#endif diff --git a/src/usr/sbe/test/makefile b/src/usr/sbe/test/makefile new file mode 100644 index 000000000..4190b0625 --- /dev/null +++ b/src/usr/sbe/test/makefile @@ -0,0 +1,28 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/sbe/test/makefile $ +# +# 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 +ROOTPATH = ../../../.. + +MODULE = testsbe +TESTS = *.H + +include ${ROOTPATH}/config.mk diff --git a/src/usr/sbe/test/sbeupdatetest.H b/src/usr/sbe/test/sbeupdatetest.H new file mode 100644 index 000000000..e92dc6d4c --- /dev/null +++ b/src/usr/sbe/test/sbeupdatetest.H @@ -0,0 +1,777 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbe/test/sbeupdatetest.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 __SBEUPDATETEST_H +#define __SBEUPDATETEST_H +/** + * @file sbeupdatetest.H + * + * @brief Test cases for SBE Update code + */ +#include <sys/time.h> + +#include <cxxtest/TestSuite.H> +#include <errl/errlmanager.H> +#include <errl/errlentry.H> +#include <devicefw/driverif.H> +#include <vfs/vfs.H> +#include <targeting/common/utilFilter.H> +#include <sbe/sbeif.H> +#include "../sbe_update.H" + + +extern trace_desc_t* g_trac_sbe; + +// Macros for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + +const char SBE_BUILD_WINK_NAME[30] = "libbuild_winkle_images.so"; +const char SBE_LIBRARY_NAME[16] = "libsbe.so"; + + +using namespace SBE; + + +void getTargetList( TARGETING::TYPE i_targetType, + TARGETING::TargetHandleList & o_targetList, + bool i_functional ) // if true: return functional targets +{ + + + TARGETING::getAllChips(o_targetList, + i_targetType, + i_functional); + + if ( o_targetList.size() == 0 ) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"getTargetList() - Found Zero (%d) Targets of " + "type 0x%X", + o_targetList.size(), i_targetType ); + } + + TRACDCOMP( g_trac_sbe, + "getTargetList() - found %d Targets of type 0x%X", + o_targetList.size(), i_targetType ); + + return; +} + +TARGETING::Target* getFunctionalTarget(TARGETING::TYPE i_targetType) +{ + TARGETING::Target * theTarget = NULL; + TRACDCOMP( g_trac_sbe, + "getFunctionalTarget() - Finding Target of Type 0x%0x", + i_targetType ); + + do { + // Get the Processor targets + TARGETING::TargetHandleList targetList; + getTargetList( i_targetType, targetList, true ); + + if( ( 0 == targetList.size() ) || + ( NULL == targetList[0] ) ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getFunctionalTarget() - Couldn't " + "find functional Target of Type 0x%0x (list.size=%d)", + i_targetType, targetList.size()); + continue; // continue because have no valid targets + } + + // List is of functional targets, so just return the first one + theTarget = targetList[0]; + + }while(0); + + TRACDCOMP( g_trac_sbe, + "getFunctionalTarget() - Returning Target 0x%0x of Type 0x%0x", + TARGETING::get_huid(theTarget), i_targetType ); + + return theTarget; + +} + + +errlHndl_t loadSbeModule(bool& o_loaded) +{ + errlHndl_t err = NULL; + o_loaded = false; + + if(!VFS::module_is_loaded(SBE_LIBRARY_NAME)) + { + err = VFS::module_load(SBE_LIBRARY_NAME); + if(err) + { + // Don't use g_trac_sbe - libsbe might not be loaded + TS_FAIL("loadSbeModule() - %s load failed", SBE_LIBRARY_NAME ); + + } + else + { + o_loaded = true; + } + } + + // This module is needed for certain HW procedure (like p8_xip_customize()) + if(!VFS::module_is_loaded(SBE_BUILD_WINK_NAME)) + { + err = VFS::module_load(SBE_BUILD_WINK_NAME); + if(err) + { + // Don't use g_trac_sbe - libsbe might not be loaded + TS_FAIL("loadSbeModule() - %s load failed", SBE_BUILD_WINK_NAME); + } + else + { + o_loaded = true; + } + } + + return err; +} + +errlHndl_t unloadSbeModule() +{ + errlHndl_t err = NULL; + + err = VFS::module_unload(SBE_LIBRARY_NAME); + if(err) + { + // Don't use g_trac_sbe - libsbe might be unloaded + TS_FAIL("unloadSbeModule() - %s unload failed", SBE_LIBRARY_NAME ); + + // No break or return - still try and unload other module + } + + err = VFS::module_unload(SBE_BUILD_WINK_NAME); + if(err) + { + // Don't use g_trac_sbe - libsbe might be unloaded + TS_FAIL("unloadSbeModule() - %s unload failed", SBE_BUILD_WINK_NAME); + } + + return err; +} + + +class SBEUpdateTest: public CxxTest::TestSuite +{ + public: + + /** + * @brief This function will test __trimCoreMask + */ + void testTrimBitMask( void ) + { + + uint64_t fails = 0x0; + uint64_t total = 0x0; + + do{ + + TRACFCOMP( g_trac_sbe, + ENTER_MRK"testTrimBitMask()" ); + + struct + { + uint32_t inMask; + uint32_t maxBits; + uint32_t outMask; + } testData[] = + { + {0xFFFFFFFF, 10, 0xFFC00000}, + {0xFFFFFFFF, 32, 0xFFFFFFFF}, + {0x0000FF00, 4, 0x0000F000}, + {0x0000FF00, 8, 0x0000FF00}, + {0x0000FF50, 16, 0x0000FF50}, + {0x000000FF, 5, 0x000000F8}, + {0x000000FF, 8, 0x000000FF}, + }; + const uint32_t NUM_TESTS = sizeof(testData)/sizeof(testData[0]); + + uint32_t retMask = 0; + + for(uint32_t i=0; i < NUM_TESTS; i++) + { + retMask = trimBitMask(testData[i].inMask, + testData[i].maxBits); + total++; + if(retMask != testData[i].outMask) + { + fails++; + TRACFCOMP( g_trac_sbe, ERR_MRK"testTrimBitMask() - i=%d, " + "retMask=0x%.8X, expMask=0x%.8X", + i, retMask, testData[i].outMask); + TS_FAIL("testTrimBitMask() - Return data did not match " + "expected data."); + } + } + + }while(0); + + TRACFCOMP( g_trac_sbe, + EXIT_MRK"testTrimBitMask - %d/%d fails", + fails, total ); + } + + /** + * @brief This function will test SBE Update's ability + * to find SBE images in PNOR + */ + + void testFindSbeInPnor ( void ) + { + errlHndl_t err = NULL; + uint64_t fails = 0x0; + uint64_t total = 0x0; + + TARGETING::Target* theTarget = NULL; + void* sbeImgPtr = NULL; + size_t sbeImgSize = 0; + sbe_image_version_t version; + + do{ + + TRACFCOMP( g_trac_sbe, + ENTER_MRK"testFindSbeInPnor()" ); + + /****************************************************/ + /* Find a valid Processor */ + /****************************************************/ + theTarget = getFunctionalTarget(TARGETING::TYPE_PROC); + if(theTarget == NULL) + { + total++; + fails++; + TS_FAIL("testReadSbeFromPnor() - No Functional Proc Targets found!"); + break; + } + + total++; + err = findSBEInPnor(theTarget, + sbeImgPtr, + sbeImgSize, + &version); + + if(err || (sbeImgPtr == NULL) || (sbeImgSize == 0) ) + { + fails++; + TRACFCOMP( g_trac_sbe, ERR_MRK"testFindSbeInPnor() - failure " + "finding Proc SBE image for uid=0x%X, ec=0x%.2X" + "sbeImgPtr=%p, sbeImgSize=0x%x", + TARGETING::get_huid(theTarget), + theTarget->getAttr<TARGETING::ATTR_EC>(), + sbeImgPtr, sbeImgSize ); + TS_FAIL("testFindSbeInPnor() -failure finding SBE image!"); + errlCommit( err, + SBE_COMP_ID ); + + } + TRACDBIN(g_trac_sbe, "testFindSbeInPnor()-Proc PNOR Version", &version, sizeof(version)); + TRACDBIN(g_trac_sbe, "testFindSbeInPnor()-Proc PNOR Image", sbeImgPtr, 0x80); + + + /****************************************************/ + /* Find a valid MemBuf */ + /****************************************************/ + theTarget = getFunctionalTarget(TARGETING::TYPE_MEMBUF); + if(theTarget == NULL) + { + total++; + fails++; + TS_FAIL("testReadSbeFromPnor() - No Functional MemBuf Targets found!"); + break; + } + + total++; + err = findSBEInPnor(theTarget, + sbeImgPtr, + sbeImgSize, + &version); + + if(err || (sbeImgPtr == NULL) || (sbeImgSize == 0) ) + { + fails++; + TRACFCOMP( g_trac_sbe, ERR_MRK"testFindSbeInPnor() - failure " + "finding MemBuf SBE image for uid=0x%X, ec=0x%.2X, " + "sbeImgPtr=%p, sbeImgSize=0x%x", + TARGETING::get_huid(theTarget), + theTarget->getAttr<TARGETING::ATTR_EC>(), + sbeImgPtr, sbeImgSize ); + TS_FAIL("testFindSbeInPnor() -failure finding SBE image!"); + errlCommit( err, + SBE_COMP_ID ); + + } + TRACDBIN(g_trac_sbe, "testFindSbeInPnor()-MEMBUF PNOR Version", &version, sizeof(version)); + TRACDBIN(g_trac_sbe, "testFindSbeInPnor()-MEMBUF PNOR Image", sbeImgPtr, 0x80); + + + /****************************************************/ + /* Verify invalid target Type is not found */ + /****************************************************/ + // test with system target -- safe that this target is configured + TARGETING::TargetService & tS = TARGETING::targetService(); + tS.getTopLevelTarget( theTarget ); + if(theTarget == NULL) + { + total++; + fails++; + TS_FAIL("testFindSbeInPnor() - System target Not Found!"); + break; + } + + total++; + err = findSBEInPnor(theTarget, + sbeImgPtr, + sbeImgSize); + + if(err) + { + TRACFCOMP( g_trac_sbe, "testFindSbeInPnor() - Did not " + "find system-target SBE image as expected: " + "uid=0x%X, err=0x%X", + TARGETING::get_huid(theTarget), + err->reasonCode() ); + delete err; + err = NULL; + } + else + { + fails++; + TRACFCOMP( g_trac_sbe, ERR_MRK"testFindSbeInPnor() - Fail " + " expected when searching for invalid target " + "(Xbus): uid=0x%X, ec=0x%.2X", + TARGETING::get_huid(theTarget), + theTarget->getAttr<TARGETING::ATTR_EC>() ); + + TS_FAIL("testFindSbeInPnor() - Fail expected when searching for invalid EC level!"); + errlCommit( err, + SBE_COMP_ID ); + } + + TRACFCOMP( g_trac_sbe, + EXIT_MRK"testFindSbeInPnor - %d/%d fails", + fails, total ); + + }while(0); + + } + + + /** + * @brief This function will run through the functions used to collect + * SBE information on a single target, determine if that target + * needs to be updated, and perform the update. + */ + void testSbeUpdateTarget ( void ) + { + + errlHndl_t err = NULL; + errlHndl_t err_cleanup = NULL; + + uint64_t fails = 0x0; + uint64_t total = 0x0; + sbeTargetState_t sbeState; + + do{ + + /****************************************************/ + /* Get Functional Target and Load SBE Module */ + /****************************************************/ + TARGETING::Target * theTarget = + getFunctionalTarget(TARGETING::TYPE_PROC); + if(theTarget == NULL) + { + total++; + fails++; + TS_FAIL("testSbeUpdateTarget() - No Functional Targets found!"); + break; + } + + TRACFCOMP( g_trac_sbe, + ENTER_MRK"testSbeUpdateTarget()" ); + + uint8_t local_ec = theTarget->getAttr<TARGETING::ATTR_EC>(); + + err = createSbeImageVmmSpace(); + if(theTarget == NULL) + { + total++; + fails++; + TS_FAIL("testSbeUpdateTarget() - Call to createSbeImageVmmSpace() failed"); + break; + } + + + /****************************************************/ + /* Get SBE Info State */ + /****************************************************/ + // Clear struct + memset(&sbeState, 0, sizeof(sbeState)); + + // Must set struct's target field + sbeState.target = theTarget; + + // set bad ec just for comparison to local_ec later + sbeState.ec = 0xFF; + + + total++; + err = getSbeInfoState(sbeState); + if(err) + { + fails++; + TS_FAIL("testSbeUpdateTarget() - call getSbeInfoState() failed."); + break; + } + + + /****************************************************/ + /* Compare/Display SBE Version Information */ + /****************************************************/ + + // Quick EC check + if (local_ec != sbeState.ec) + { + fails++; + TS_FAIL("testSbeUpdateTarget() - Bad ec check: local=0x%X, other=0x%X", local_ec, sbeState); + break; + } + + // Display sbeState + TRACUCOMP( g_trac_sbe, + "testSbeUpdateTarget() Info For Target 0x%X ec=0x%X " + "cur=0x%X alt=0x%X, ECC_fail 0/1=%d/%d, isMaster=%d " + "Custom Image Size=0x%X, CRC=0x%X", + TARGETING::get_huid(sbeState.target), sbeState.ec, + sbeState.cur_seeprom_side, sbeState.alt_seeprom_side, + sbeState.seeprom_0_ver_ECC_fail, + sbeState.seeprom_1_ver_ECC_fail, + sbeState.target_is_master, + sbeState.customizedImage_size, + sbeState.customizedImage_crc); + + TRACDBIN( g_trac_sbe, "testSbeUpdateTarget()-pnorVersion", + &sbeState.pnorVersion, sizeof(sbe_image_version_t)); + TRACDBIN( g_trac_sbe, "testSbeUpdateTarget()-mvpdSbKeyword", + &sbeState.mvpdSbKeyword, sizeof(mvpdSbeVersion_t)); + TRACDBIN( g_trac_sbe, "testSbeUpdateTarget()-seeprom_0_ver", + &sbeState.seeprom_0_ver, + sizeof(sbeSeepromVersionInfo_t)); + TRACDBIN( g_trac_sbe, "testSbeUpdateTarget()-seeprom_1_ver", + &sbeState.seeprom_1_ver, + sizeof(sbeSeepromVersionInfo_t)); + + + /****************************************************/ + /* CRC Calculation */ + /****************************************************/ + uint32_t new_data_crc = 0; + total++; + + err = getDataCrc(theTarget, new_data_crc); + if(err) + { + fails++; + TS_FAIL("testSbeUpdateTarget() - getDataCrc() failed"); + break; + } + + TRACUCOMP( g_trac_sbe, "testSbeUpdateTarget(): getDataCrc(): data_crc=0x%.4x", + new_data_crc); + + /****************************************************/ + /* Get Target Update Actions */ + /****************************************************/ + + total++; + err = getTargetUpdateActions(sbeState); + if(err) + { + fails++; + TS_FAIL("testSbeUpdateTarget() - getTargetUpdateActions() failed"); + break; + } + + + /****************************************************/ + /* Update SBE Backup */ + /****************************************************/ + // force backup to SEEPROM 1 just in case + if ( !(sbeState.update_actions & DO_UPDATE ) ) + { + sbeState.seeprom_side_to_update = EEPROM::SBE_BACKUP; + } + total++; + + err = performUpdateActions(sbeState); + if(err) + { + fails++; + TS_FAIL("testSbeUpdateTarget() - performUpdateActions() failed."); + break; + } + + + }while(0); + + err_cleanup = cleanupSbeImageVmmSpace(); + if(err_cleanup) + { + total++; + fails++; + TS_FAIL("testSbeUpdateTarget() -Call to cleanupSbeImageVmmSpace() failed."); + errlCommit( err_cleanup, SBE_COMP_ID ); + + } + + TRACFCOMP( g_trac_sbe, + EXIT_MRK"testSbeUpdateTarget() - %d/%d fails", + fails, total ); + } + + + + /** + * @brief This function will call decisionTreeForUpdates() and make + sure the correct update action is returned for a specific + situation. + */ + void testSbeDecisionTree ( void ) + { + + uint64_t fails = 0x0; + uint64_t total = 0x0; + + sbeTargetState_t sbeState; + + struct + { + // Inputs + uint8_t i_situation; + sbeSeepromSide_t i_cur; // current_seeprom_side + uint8_t i_flags; // mvpdSbKeyword.flags + + // Expected Output + sbeUpdateActions_t o_update_actions; + EEPROM::eeprom_chip_types_t o_seeprom; + uint8_t o_flags; // mvpdSbKeyword.flags + + } testData[] = + { + + // case 0xE0: cur=temp, cur=dirty, alt=dirty + // Arbitrarily set cur side to 0 (therefore perm set to 1) + // - update alt=1 + // - make cur=perm + // - re-IPL + { 0xE0, SBE_SEEPROM0, 0x80, + static_cast<sbeUpdateActions_t>(DO_UPDATE|IPL_RESTART), + EEPROM::SBE_BACKUP, 0x00 }, + + + // case 0xC0: cur=temp, cur=dirty, alt=dirty + // Arbitrarily set cur side to 1 (therefore perm set to 0) + // - update alt=0 + // - make cur=perm + // - re-IPL + { 0xC0, SBE_SEEPROM1, 0x00, + static_cast<sbeUpdateActions_t>(DO_UPDATE|IPL_RESTART), + EEPROM::SBE_PRIMARY, 0x80 }, + + // case 0xA0: cur=temp, cur=clean, alt=dirty + // Arbitarily Set cur side to 1 (therefore perm set to 0) + // - update alt=0 + // - make cur=perm + // - Continue IPL + { 0xA0, SBE_SEEPROM1, 0x00, + static_cast<sbeUpdateActions_t>(DO_UPDATE), + EEPROM::SBE_PRIMARY, 0x80 }, + + // case 0x80: cur=temp, cur=clean, alt=clean + // Arbitrarily set cur side to 1 (therefore perm set to 0) + // - No updates + // - Continue IPL + { 0x80, SBE_SEEPROM1, 0x00, + static_cast<sbeUpdateActions_t>(CLEAR_ACTIONS), + EEPROM::LAST_CHIP_TYPE, 0x00 }, + + // case 0x60: cur=perm, cur=dirty, alt=dirty + // Arbitrarily set cur side to 0 (therefore perm set to 0) + // - update alt=1 + // - re-IPL + { 0x60, SBE_SEEPROM0, 0x00, + static_cast<sbeUpdateActions_t>(DO_UPDATE|IPL_RESTART), + EEPROM::SBE_BACKUP, 0x00 }, + + // case 0x40: cur=temp, cur=dirty, alt=clean + // @todo RTC 47033 - Ask FSP if we just re-IPLed, but just + // continue IPL now + // Arbitrarily set cur side to 1 (therefore perm set to 1) + // No Updates + // Continue IPL + { 0x40, SBE_SEEPROM1, 0x80, + static_cast<sbeUpdateActions_t>(CLEAR_ACTIONS), + EEPROM::LAST_CHIP_TYPE, 0x80 }, + + // case 0x20: cur=perm, cur=clean, alt=dirty + // Arbitrarily set cur side to 0 (therefore perm set to 0) + // - update alt=1 + // - Continue IPL + { 0x20, SBE_SEEPROM0, 0x00, + static_cast<sbeUpdateActions_t>(DO_UPDATE), + EEPROM::SBE_BACKUP, 0x00 }, + + // case 0x00: cur=perm, cur=clean, alt=clean + // Arbitrarily set cur side to 0 (therefore perm set to 0) + // - No Updates + // - Continue IPL + // NOTE: this will test that right-most-bit is ignored: + // so techincally case 0x01, which should be = case 0x00 + { 0x01, SBE_SEEPROM0, 0x00, + static_cast<sbeUpdateActions_t>(CLEAR_ACTIONS), + EEPROM::LAST_CHIP_TYPE, 0x00 }, + + }; + + const uint32_t NUM_CMDS = sizeof(testData)/sizeof(testData[0]); + + + do{ + + TRACFCOMP( g_trac_sbe, + ENTER_MRK"testSbeDecisionTree()" ); + + + // Loop through each situation + for( uint32_t i = 0; i < NUM_CMDS; i++ ) + { + + sbeState.update_actions = CLEAR_ACTIONS; + + /****************************************************/ + /* Set Input Values */ + /****************************************************/ + sbeState.cur_seeprom_side = testData[i].i_cur; + + sbeState.alt_seeprom_side = + ( ( testData[i].i_cur == SBE_SEEPROM0 ) + ? SBE_SEEPROM1 : SBE_SEEPROM0 ); + + sbeState.mvpdSbKeyword.flags = testData[i].i_flags; + + + /****************************************************/ + /* Get Target Update Actions */ + /****************************************************/ + total++; + SBE::decisionTreeForUpdates(sbeState, + testData[i].i_situation); + + + /****************************************************/ + /* Check Output Values */ + /****************************************************/ + if (( testData[i].o_update_actions != sbeState.update_actions ) + || + ( testData[i].o_seeprom != sbeState.seeprom_side_to_update ) + || + ( testData[i].o_flags != sbeState.mvpdSbKeyword.flags ) + ) + { + fails++; + + TRACFCOMP( g_trac_sbe, ERR_MRK"testSbeDecisionTree() - " + "Fail! Unexpected results for situation=0x%.2X (i=%d): " + "Inputs: cur=%d, flags=0x%.2X", + testData[i].i_situation, i, + testData[i].i_cur, testData[i].i_flags); + + TRACFCOMP( g_trac_sbe, ERR_MRK"testSbeDecisionTree() - " + "Expected/Returned: update_actions=0x%.4X/0x%.4x, " + "update seeprom=%d/%d, flags=0x%.2X/0x%.2X", + testData[i].o_update_actions, sbeState.update_actions, + testData[i].o_seeprom, sbeState.seeprom_side_to_update, + testData[i].o_flags, sbeState.mvpdSbKeyword.flags); + + TS_FAIL("testSbeDecisionTree() - Fail! Unexpected results for pass %d, situation=0x%.2X", i, testData[i].i_situation); + + // Don't break - complete the remaining tests + } + + } // end of for-loop + + }while(0); + + TRACFCOMP( g_trac_sbe, EXIT_MRK + EXIT_MRK"testSbeDecisionTree() - %d/%d fails", + fails, total ); + } + + + /** + * @brief Constructor + */ + SBEUpdateTest() : CxxTest::TestSuite() + { + errlHndl_t err = NULL; + uint64_t fails = 0x0; + uint64_t total = 0x0; + bool sbe_loaded = false; + + err = loadSbeModule(sbe_loaded); + if(err) + { + total++; + fails++; + TS_FAIL("SBEUpdateTest() - Constuctor: failed to load modules"); + errlCommit( err, SBE_COMP_ID ); + } + + }; + + + /** + * @brief Destructor + */ + ~SBEUpdateTest() + { + errlHndl_t err = NULL; + uint64_t fails = 0x0; + uint64_t total = 0x0; + + err = unloadSbeModule(); + if(err) + { + total++; + fails++; + TS_FAIL("~SBEUpdateTest() - Destuctor: failed to load modules"); + errlCommit( err, SBE_COMP_ID ); + } + + }; + +}; + +#endif diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index 2b06b940b..14d8cb757 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -5811,6 +5811,26 @@ firmware notes: Used as override attribute for pstate procedure </attribute> <attribute> + <id>SBE_IMAGE_MINIMUM_VALID_EXS</id> + <description> + The minimum number of valid EXs that is required to be used when + customizing a SBE image. The customization will fail if it cannot + create an image with at least this many EXs. + </description> + <simpleType> + <uint8_t> + <default>3</default> + </uint8_t> + </simpleType> + <persistency>non-volatile</persistency> + <readable/> + <hwpfToHbAttrMap> + <id>ATTR_SBE_IMAGE_MINIMUM_VALID_EXS</id> + <macro>DIRECT</macro> + </hwpfToHbAttrMap> +</attribute> + +<attribute> <id>PROC_PSI_UNTRUSTED_BAR0_BASE_ADDR</id> <description> PSI Untrusted BAR0 base address (secure mode) @@ -5932,10 +5952,10 @@ firmware notes: Used as override attribute for pstate procedure <id>PROC_SECURITY_SETUP_VECTOR</id> <description> Secureboot 64-bit proc_sbe_security_setup_vector used - by proc_sbe_security_setup.S. 0s are an unsecure SBE image + by proc_sbe_security_setup.S. 0s are an unsecure SBE image creator: platform firmware notes: - 64-bit proc_sbe_security_setup_vector + 64-bit proc_sbe_security_setup_vector </description> <simpleType> <uint64_t> @@ -9498,7 +9518,7 @@ Measured in GB</description> </description> <simpleType> <uint8_t> - <default>4</default> + <default>2</default> </uint8_t> </simpleType> <persistency>non-volatile</persistency> diff --git a/src/usr/targeting/common/xmltohb/simics_MURANO.system.xml b/src/usr/targeting/common/xmltohb/simics_MURANO.system.xml index 84ca82f95..b8bb37d6b 100644 --- a/src/usr/targeting/common/xmltohb/simics_MURANO.system.xml +++ b/src/usr/targeting/common/xmltohb/simics_MURANO.system.xml @@ -75,7 +75,7 @@ </attribute> <attribute> <id>FREQ_PROC_REFCLOCK</id> - <default>200</default> + <default>133</default> </attribute> <attribute> <id>FREQ_MEM_REFCLOCK</id> @@ -87,11 +87,11 @@ </attribute> <attribute> <id>FREQ_PB</id> - <default>0x960</default> + <default>0x7D0</default> </attribute> <attribute> <id>FREQ_X</id> - <default>0x12C0</default> + <default>0xFA0</default> </attribute> <attribute> <id>FREQ_A</id> diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml index 9fdfa1f37..9120f4ae9 100644 --- a/src/usr/targeting/common/xmltohb/target_types.xml +++ b/src/usr/targeting/common/xmltohb/target_types.xml @@ -149,6 +149,7 @@ <attribute><id>SBE_IMAGE_OFFSET</id></attribute> <attribute><id>BOOT_VOLTAGE</id></attribute> <attribute><id>SYNC_BETWEEN_STEPS</id></attribute> + <attribute><id>SBE_IMAGE_MINIMUM_VALID_EXS</id></attribute> <!-- End sbe_config_update attributes --> <!-- proc_select_boot_master attributes --> <attribute><id>PROC_SELECT_BOOT_MASTER</id></attribute> @@ -398,7 +399,7 @@ <attribute><id>SBE_SEEPROM_I2C_PORT</id></attribute> <attribute><id>PNOR_I2C_ADDRESS_BYTES</id></attribute> <!-- End Supporting poreve_memory_attributes.xml --> -<!-- TODO RTC 62291. This next attribute moves to hostboot only +<!-- TODO RTC 82688. This next attribute moves to hostboot only with this story --> <attribute><id>PROC_SECURITY_SETUP_VECTOR</id></attribute> |

