diff options
Diffstat (limited to 'src/build')
57 files changed, 4695 insertions, 479 deletions
diff --git a/src/build/beam/core/assert.C b/src/build/beam/core/assert.C index c7186668f..183e1847d 100644 --- a/src/build/beam/core/assert.C +++ b/src/build/beam/core/assert.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2019 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -20,5 +22,7 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +// cppcheck-suppress syntaxError >>>ERROR5___assert_d9b551657c952063 + >>>ERROR5___assert_941b08c17c952063 diff --git a/src/build/beam/core/pagemgr.C b/src/build/beam/core/pagemgr.C index 54779d750..2cde4394d 100644 --- a/src/build/beam/core/pagemgr.C +++ b/src/build/beam/core/pagemgr.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2019 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -20,5 +22,6 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +// cppcheck-suppress syntaxError >>>MISTAKE5__initialize_7639026bb95510e7 >>>MISTAKE5__initialize_2d381016b95510e7 diff --git a/src/build/beam/core/stacksegment.C b/src/build/beam/core/stacksegment.C index cfc2cf308..e7bd9eb21 100644 --- a/src/build/beam/core/stacksegment.C +++ b/src/build/beam/core/stacksegment.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2019 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -20,4 +22,5 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +// cppcheck-suppress syntaxError >>>ERROR8_~StackSegment_b791f4a2ac177b6 diff --git a/src/build/beam/hwp/mvpdRingFuncs.C b/src/build/beam/hwp/mvpdRingFuncs.C index 5c113e990..50f58dc83 100644 --- a/src/build/beam/hwp/mvpdRingFuncs.C +++ b/src/build/beam/hwp/mvpdRingFuncs.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ +/* Contributors Listed Below - COPYRIGHT 2012,2019 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -20,5 +22,6 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +// cppcheck-suppress syntaxError >>>MISTAKE17_mbvpdValidateRecordKeyword_d149f58f1505 >>>MISTAKE5_mbvpdRingFunc_b48fca4f6c313e21 diff --git a/src/build/beam/i2c/i2c.C b/src/build/beam/i2c/i2c.C index 6bc1a97f4..1d2632b8f 100644 --- a/src/build/beam/i2c/i2c.C +++ b/src/build/beam/i2c/i2c.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2019 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -20,4 +22,6 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +// cppcheck-suppress syntaxError >>>MISTAKE17_i2cSetupMasters_8697e17e1505 + diff --git a/src/build/beam/prdf/prdfBitKey.C b/src/build/beam/prdf/prdfBitKey.C index b1618ebe9..0d9d67938 100644 --- a/src/build/beam/prdf/prdfBitKey.C +++ b/src/build/beam/prdf/prdfBitKey.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2019 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -20,5 +22,6 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +// cppcheck-suppress syntaxError >>>MISTAKE17_operator==_f7028aed1505 >>>MISTAKE17_operator==_70cd34271505 diff --git a/src/build/beam/prdf/prdfPegasusConfigurator.C b/src/build/beam/prdf/prdfPegasusConfigurator.C index 956ed90b2..e19a1b881 100644 --- a/src/build/beam/prdf/prdfPegasusConfigurator.C +++ b/src/build/beam/prdf/prdfPegasusConfigurator.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2019 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -20,5 +22,6 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +// cppcheck-suppress syntaxError >>>MISTAKE17_addPllDomainsToSystem_954f5e401505 >>>MISTAKE17_addPllDomainsToSystem_c01c04751505 diff --git a/src/build/beam/targeting/targetservice.C b/src/build/beam/targeting/targetservice.C index 4e069351d..029876273 100644 --- a/src/build/beam/targeting/targetservice.C +++ b/src/build/beam/targeting/targetservice.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -20,5 +22,6 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +// cppcheck-suppress syntaxError >>>MISTAKE5_queryMasterProcChipTargetHandle_2745d8d11505 >>>MISTAKE5_queryMasterProcChipTargetHandle_da38b67e1505 diff --git a/src/build/buildpnor/PnorUtils.pm b/src/build/buildpnor/PnorUtils.pm index 3a8d22df2..e5ecbb150 100644 --- a/src/build/buildpnor/PnorUtils.pm +++ b/src/build/buildpnor/PnorUtils.pm @@ -39,6 +39,7 @@ my $TRAC_ERR = 0; my $g_trace = 1; use XML::Simple; + ################################################################################ # Set PREFERRED_PARSER to XML::Parser. Otherwise it uses XML::SAX which contains # bugs that result in XML parse errors that can be fixed by adjusting white- @@ -53,7 +54,8 @@ use constant PAGE_SIZE => 4096; ################################################################################ sub loadPnorLayout { - my ($i_pnorFile, $i_pnorLayoutRef, $i_physicalOffsets, $i_testRun) = @_; + my ($i_pnorFile, $i_pnorLayoutRef, $i_physicalOffsets, $i_testRun, + $i_outputLayoutLocation) = @_; my $this_func = (caller(0))[3]; unless(-e $i_pnorFile) @@ -90,6 +92,10 @@ sub loadPnorLayout my $numOfSides = scalar (@{$metadataEl->{side}}); my $sideSize = ($imageSize)/($numOfSides); + my $currOffset = 0; + my $sectionNum = 0; + my $isStartingPartition = 1; + trace(2, " $this_func: metadata: imageSize = $imageSize, blockSize=$blockSize, arrangement = $arrangement, numOfSides: $numOfSides, sideSize: $sideSize, tocSize: $tocSize"); #determine the TOC offsets from the arrangement and side Information @@ -170,9 +176,44 @@ sub loadPnorLayout $physicalOffset = getNumber($physicalOffset); $physicalRegionSize = getNumber($physicalRegionSize); + # if at first section, set starting offset + if ($isStartingPartition == 1) + { + $currOffset = $physicalOffset; + $isStartingPartition = 0; + } + + # if physical offset does not exist, calculate it and create new element + my $hexOffset; + if ($physicalOffset == 0) + { + $physicalOffset = $currOffset; + $hexOffset = sprintf("0x%X", $physicalOffset); + trace(3, "$this_func: Calculated physicalOffset = $physicalOffset, for eyeCatch = $eyeCatch"); + push @{$xml->{section}->[$sectionNum]->{physicalOffset}}, $hexOffset; + $currOffset = $currOffset + $physicalRegionSize; + } + else + { + # if sections overlap, throw error + if ($physicalOffset < $currOffset) + { + $hexOffset = sprintf("0x%X", $physicalOffset); + die "ERROR: Collision between sections detected at offset ".$hexOffset.""; + } + $currOffset = $physicalOffset + $physicalRegionSize; + } + $sectionNum = $sectionNum + 1; + + # align partition by minimum boundary + if ($currOffset % PAGE_SIZE != 0) + { + $currOffset = $currOffset + (PAGE_SIZE - $currOffset % PAGE_SIZE); + } + if($physicalRegionSize + $physicalOffset > $imageSize) { - die "ERROR: $this_func: Image size ($imageSize) smaller than $eyeCatch's offset + $eyeCatch's size (".($physicalOffset + $physicalRegionSize)."). Aborting! "; + die "ERROR: $this_func: Image size ($imageSize) smaller than ".$eyeCatch."'s offset + ".$eyeCatch."'s size (".($physicalOffset + $physicalRegionSize)."). Aborting! "; } if (exists $$i_pnorLayoutRef{sections}{$physicalOffset}) @@ -215,6 +256,42 @@ sub loadPnorLayout checkForOverlap($i_pnorLayoutRef); } + # Write xml with offsets to new file if $i_outputLayoutLocation + # argument is supplied + if (defined $i_outputLayoutLocation && $i_outputLayoutLocation ne "") + { + my $filename = basename($i_pnorFile, ".xml"); + $filename = "${i_outputLayoutLocation}/${filename}WithOffsets.xml"; + + # writing to new file with error handling + eval + { + print XMLout($xml, RootName => "pnor", OutputFile => $filename); + 1; + } + or do + { + my $err = $@; + die "ERROR: $this_func: Failed to create new XML file with corrected offsets, error = $err"; + }; + + # Write out a helper file for our simics scripts + print "\nlocation = " . ${i_outputLayoutLocation} . "\n"; + my $simfilename = "${i_outputLayoutLocation}/simpnor.py"; + open(SIM_FILE,'>',$simfilename) or die("($simfilename) could not be opened."); + print SIM_FILE "def hb_get_pnor_offset(partname):\n"; + print SIM_FILE " toc_dict={}\n"; + #Iterate over the <section> elements. + foreach my $sectionEl (@{$xml->{section}}) + { + my $eyeCatch = $sectionEl->{eyeCatch}[0]; + my $physicalOffset = $sectionEl->{physicalOffset}[0]; + print SIM_FILE " toc_dict[\"$eyeCatch\"]=$physicalOffset\n"; + } + print SIM_FILE " return toc_dict[partname]\n"; + close SIM_FILE; + } + return 0; } @@ -353,6 +430,8 @@ sub checkSpaceConstraints my %sectionHash = %{$$i_pnorLayoutRef{sections}}; + print "Note: the following metrics are not a true representation of section utilization, since some sections are substantially padded before applying ECC\n"; + for $key ( keys %{$i_binFiles}) { my $filesize = -s $$i_binFiles{$key}; @@ -366,18 +445,17 @@ sub checkSpaceConstraints my $eyeCatch = $sectionHash{$layoutKey}{eyeCatch}; my $physicalRegionSize = $sectionHash{$layoutKey}{physicalRegionSize}; - my $pctUtilized = sprintf("%.2f", $filesize / $physicalRegionSize * 100); my $freeBytes = $physicalRegionSize - $filesize; - print "$eyeCatch is $pctUtilized% utilized ($freeBytes of $physicalRegionSize bytes free)\n"; + print "$eyeCatch section size: $physicalRegionSize, bytes used: $filesize, bytes unused: $freeBytes\n"; if($filesize > $physicalRegionSize) { # If this is a test run increase HBI size by PAGE_SIZE until all test # cases fit - if ($testRun && $eyeCatch eq "HBI") + if ( $testRun && ($eyeCatch eq "HBI") ) { - print "$this_func: Adjusting HBI size - ran out of space for test cases\n"; - adjustHbiPhysSize(\%sectionHash, $layoutKey, $filesize); + print "Adjusting HBI size - ran out of space for test cases\n"; + adjustSecPhysSize(\%sectionHash, $layoutKey, $filesize); } else { @@ -388,36 +466,43 @@ sub checkSpaceConstraints trace(1, "Done checkSpaceConstraints"); } - -############################################################################### -# adjustHbiPhysSize - Adjust HBI physical size when running test cases and fix -# up physical offsets of partitions after it -################################################################################ -sub adjustHbiPhysSize +# sub adjustSecPhysSize +# +# Adjust section physical size when running test cases and fix up physical +# offsets between partitions (for example HBI and all partitions that follow) +# +# @param [in] i_sectionHashRef - PNOR layout as a hash table reference +# @param [in] i_initPartKey - key of initial partition whose physical size will +# be adjusted +# @param [in] i_filesize - final file size of partition (note: actual final size +# may be larger than this as the size is adjusted by increments of PAGE_SIZE) +# @return - N/A +# +sub adjustSecPhysSize { - my ($i_sectionHashRef, $i_hbiKey, $i_filesize) = @_; + my ($i_sectionHashRef, $i_initPartKey, $i_filesize) = @_; my $this_func = (caller(0))[3]; my %sectionHash = %$i_sectionHashRef; - # Increment HBI physical size by PAGE_SIZE until the HBI file can fit - my $hbi_old = $sectionHash{$i_hbiKey}{physicalRegionSize}; - while ($i_filesize > $sectionHash{$i_hbiKey}{physicalRegionSize}) + # Increment initial partition physical size by PAGE_SIZE until the initial + # partition file can fit + my $initPart_old = $sectionHash{$i_initPartKey}{physicalRegionSize}; + while ($i_filesize > $sectionHash{$i_initPartKey}{physicalRegionSize}) { - $sectionHash{$i_hbiKey}{physicalRegionSize} += PAGE_SIZE; + $sectionHash{$i_initPartKey}{physicalRegionSize} += PAGE_SIZE; } - my $hbi_move = $sectionHash{$i_hbiKey}{physicalRegionSize} - $hbi_old; - my $hbi_end = $sectionHash{$i_hbiKey}{physicalRegionSize} + $hbi_move; + my $initPart_move = $sectionHash{$i_initPartKey}{physicalRegionSize} - $initPart_old; - # Fix up physical offset affected by HBI size change + # Fix up physical offsets affected by initial partition size change foreach my $section (keys %sectionHash) { - # Only fix partitions after HBI + # Only fix partitions after initial partition if ( $sectionHash{$section}{physicalOffset} > - $sectionHash{$i_hbiKey}{physicalOffset} ) + $sectionHash{$i_initPartKey}{physicalOffset} ) { my $origoffset = $sectionHash{$section}{physicalOffset}; - $sectionHash{$section}{physicalOffset} += $hbi_move; + $sectionHash{$section}{physicalOffset} += $initPart_move; trace(3, "$this_func: Section $sectionHash{$section}{eyeCatch} : " . sprintf("%X",$origoffset) . " --> " . sprintf("%X",$sectionHash{$section}{physicalOffset})); } else @@ -562,7 +647,6 @@ sub checkForOverlap } } - ############################################################################### # Display Pnor Layout - Display XML pnor layout more simply ################################################################################ diff --git a/src/build/buildpnor/bpm-utils/LICENSE_PROLOG b/src/build/buildpnor/bpm-utils/LICENSE_PROLOG new file mode 100644 index 000000000..e57b55f75 --- /dev/null +++ b/src/build/buildpnor/bpm-utils/LICENSE_PROLOG @@ -0,0 +1,24 @@ +This is an automatically generated prolog. + +$SOURCE_BEGIN_TAG $filename $SOURCE_END_TAG + +OpenPOWER $projectName Project + +$copyrightStr $copyrightYear +$copyright_Contributors + +Copyright (c) 2019 SMART Modular Technologies, Inc. +All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + diff --git a/src/build/buildpnor/bpm-utils/imageCrc.c b/src/build/buildpnor/bpm-utils/imageCrc.c new file mode 100644 index 000000000..8df98a2d3 --- /dev/null +++ b/src/build/buildpnor/bpm-utils/imageCrc.c @@ -0,0 +1,479 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/build/buildpnor/bpm-utils/imageCrc.c $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2019 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Copyright (c) 2019 SMART Modular Technologies, Inc. */ +/* All Rights Reserved. */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +//#define DEBUG + +// +// The BPM / SCAP firmware images always will be in one of +// the two address ranges: +// +// Range:(0xA000 - 0xFFFF). Start = 0xA000; Length = 0x6000 (24K) +// Range:(0x8000 - 0xFFFF). Start = 0x8000; Length = 0x8000 (32K) +// +#define FW_MAINIMAGE_START_ADDRESS_8000 (0x8000) +#define FW_MAINIMAGE_START_ADDRESS_A000 (0xA000) +#define FW_MAINIMAGE_LAST_ADDRESS (0xFFFF) + +// +// Maximum possible length of the firmware image +// +#define FW_MAINIMAGE_MAX_LENGTH (0x8000) +#define CRC_SIGNATURE_LO (0xAA) +#define CRC_SIGNATURE_HI (0x55) + +#define ADDRESS_CRC_SIGNATURE (0xFF7A) // @FF7A = 0xAA, @FF7B = 0x55 +#define ADDRESS_IMAGE_START (0xFF7C) // @FF7C = Start_Lo, @FF7D = Start_Hi +#define ADDRESS_IMAGE_CRC (0xFF7E) // @FF7E = CRC_Lo, @FF7F = CRC_Hi +#define ADDRESS_RESET_VECTOR (0xFFFE) // @FFFE, FFFF +#define LENGTH_IMAGE_CRC (0x2) + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; + +typedef struct _CRC_CONTEXT { + uint16_t mainImageStartAddress; + uint16_t mainImageTotalLength; +} CRC_CONTEXT; + +typedef struct _OFFSET_LIST { + uint32_t count; + uint32_t offset[4]; +} OFFSET_LIST; + +char* readNextHex(const char* pLine, uint32_t *value); + +uint16_t resetCrc(void); + +uint16_t updateCrc(uint8_t byte); + +uint16_t calculateCrc(uint8_t* pData, int length); + +bool +parseLine(const char* pLine, + uint32_t *mMemoryAddress, + CRC_CONTEXT *context, + uint8_t *mainImageData); + +uint16_t mCrc = 0; + +void +dumpImageData(uint8_t *data, uint32_t dataLength, OFFSET_LIST *offsetToSkipList) +{ + bool dontPrint = false; + + uint32_t i, c; + uint32_t offsetToSkipCount = 0; + + if (offsetToSkipList != NULL) { + offsetToSkipCount = offsetToSkipList->count; + } + + printf("MainImageData:\n"); + + for (i = 1; i < dataLength - 1; ++i) { + + // + // Don't print some of the offsets, when requested + // + dontPrint = false; + for (c = 0; c < offsetToSkipCount; c++) { + if ((i - 1) == offsetToSkipList->offset[c]) { + dontPrint = true; + break; + } + } + + if (dontPrint) { + printf(" "); + } else { + printf(" %02x", data[i - 1]); + } + + if ((i % 16) == 0) { + printf("\n"); + } + } + + printf("\n"); +} + +uint16_t +resetCrc(void) +{ + mCrc = 0xFFFF; + return mCrc; +} + +uint16_t +updateCrc(uint8_t byte) +{ + bool x; + int i; + + for (i = 0; i < 8; ++i) { + x = ((mCrc & 0x8000 ? 1 : 0) ^ (byte & 0x80 ? 1 : 0)) ? true : false; + mCrc <<= 1; + if (x) + mCrc ^= 0x1021; + byte <<= 1; + } + return mCrc; +} + +uint16_t +calculateCrc(uint8_t* pData, int length) +{ + //resetCrc(); + for (; length; --length, ++pData) { + updateCrc(*pData); + } + return mCrc; +} + +char* +readNextHex(const char* pLine, uint32_t *pValue) +{ + uint32_t value = 0; + + // Skip leading white space + while (*pLine != '\0' && *pLine <= ' ') { + ++pLine; + } + + if (*pLine == '\0') + return NULL; + + while (true) { + if (*pLine >= '0' && *pLine <= '9') { + value <<= 4; + value += *pLine - '0'; + } else if (*pLine >= 'a' && *pLine <= 'f') { + value <<= 4; + value += 0xa + *pLine - 'a'; + } else if (*pLine >= 'A' && *pLine <= 'F') { + value <<= 4; + value += 0xA + *pLine - 'A'; + } else { + break; + } + ++pLine; + } + + *pValue = value; + return (char*)pLine; +} + +bool +parseLine(const char* pLine, + uint32_t *mMemoryAddress, + CRC_CONTEXT *context, + uint8_t *mainImageData) +{ + uint8_t data[0x100]; + int dataLength = 0; + uint32_t value; + + uint32_t offsetToCopy = 0; +#ifdef DEBUG + int i; +#endif + + if (*pLine == '@') { + // This is a memory address + if (readNextHex(pLine + 1, &value) != NULL) { + *mMemoryAddress = (uint16_t) value; +#ifdef DEBUG + printf("@Memory Address: 0x%x\n", *mMemoryAddress); +#endif // DEBUG + + // + // Initialize the Context when the firmware image + // start address is detected. + // + if ((*mMemoryAddress == FW_MAINIMAGE_START_ADDRESS_8000) || + (*mMemoryAddress == FW_MAINIMAGE_START_ADDRESS_A000)) { + + context->mainImageStartAddress = value; + context->mainImageTotalLength = (FW_MAINIMAGE_LAST_ADDRESS - value) + 1; + + printf("Context: Image Start Address = 0x%x; Image Length = %d (0x%x) \n", + context->mainImageStartAddress, context->mainImageTotalLength, context->mainImageTotalLength); + } + } + + } else if (*pLine == 'q' || *pLine == 'Q') { +#ifdef DEBUG + printf("Done\n"); + printf("Memory Address: 0x%x\n", *mMemoryAddress); +#endif // DEBUG + return true; + } else { + do { + pLine = readNextHex(pLine, &value); + + if (pLine != NULL) { + data[dataLength++] = value; + } + + } while (pLine != NULL); + + if (dataLength & 1) { + // Keep even byte alignment by padding + data[dataLength++] = 0xFF; + } + +#ifdef DEBUG + printf("Write data (%04x) dataLength (0x%x):", + *mMemoryAddress, dataLength); + for (i = 0; i < dataLength; ++i) { + printf(" %02x", data[i]); + } + printf("\n"); +#endif // DEBUG + + // + // added by rananth to calculate the CRC of the main image data. + // + if ((*mMemoryAddress >= context->mainImageStartAddress) && + (*mMemoryAddress < + (context->mainImageStartAddress + context->mainImageTotalLength))) + { + + if ( (context->mainImageStartAddress != 0) + && (context->mainImageTotalLength != 0) && + (mainImageData != NULL)) { + + // + // Copy the main image data bytes (Range: @8000, 0x8000) to the + // passed in data buffer. + // + offsetToCopy = *mMemoryAddress - context->mainImageStartAddress; + memcpy(mainImageData + offsetToCopy, data, dataLength); + +#ifdef DEBUG + printf("Copy data (%04x) dataLength (0x%x):", + offsetToCopy, dataLength); + printf("\n"); +#endif // DEBUG + + } + } + + *mMemoryAddress += dataLength; + } + + return true; +} + + +int +ProcessFile(char *pFilename, bool verbose) +{ + char buffer[0x100]; + int length; + int line; + + uint8_t *mainImageData = 0; + + uint32_t mMemoryAddress = 0; + uint32_t crc = 0; + uint32_t offsetToSkip; + uint32_t offsetToInsert; + uint32_t firstPortion = 0; + uint32_t secondPortion = 0; + + CRC_CONTEXT context; + OFFSET_LIST offsetList; + + // Count the number of lines in the file and use that for progress + FILE* pFile = fopen(pFilename, "r"); + if (!pFile) { + printf("Unable to open file %s\n", pFilename); + return false; + } + for (line = 0; !feof(pFile); ++line) { + if (fgets(buffer, sizeof(buffer), pFile) == NULL) { + break; + } + } + + + // Rewind to the beginning of the file + fseek(pFile, 0, SEEK_SET); + + // + // allocate memory for the main image data + // + mainImageData = (uint8_t *) malloc(FW_MAINIMAGE_MAX_LENGTH); + memset(mainImageData, 0xFF, FW_MAINIMAGE_MAX_LENGTH); + + memset(&context, 0, sizeof(CRC_CONTEXT)); + + // Process the lines + for (line = 0; !feof(pFile); ++line) { + if (fgets(buffer, sizeof(buffer), pFile) == NULL) { + break; + } + + length = strlen(buffer); + + // Strip off any terminating carriage return/line feed + for (; length > 0 && buffer[length - 1] < ' '; --length); + buffer[length] = '\0'; + + if ( !parseLine((const char*) buffer, + &mMemoryAddress, + &context, + mainImageData) ) { + printf("False returned by parseLine \n"); + break; + } + } + + if (verbose) { + + printf("==============================================\n"); + printf("Dump & CRC before selective skip (@FF7E, 2) (@FFFE, 2) \n"); + printf("==============================================\n"); + + dumpImageData(mainImageData, context.mainImageTotalLength, NULL); + + crc = calculateCrc(mainImageData, context.mainImageTotalLength); + + printf("Total Length = %d (0x%x). Final CRC = 0x%x \n", + context.mainImageTotalLength, context.mainImageTotalLength, crc); + + } + + // + // Insert the Signature (if not already present) + // + offsetToInsert = ADDRESS_CRC_SIGNATURE - context.mainImageStartAddress; + if (mainImageData[offsetToInsert] != CRC_SIGNATURE_LO) { + mainImageData[offsetToInsert] = CRC_SIGNATURE_LO; + } + + if (mainImageData[offsetToInsert + 1] = CRC_SIGNATURE_HI) { + mainImageData[offsetToInsert + 1] = CRC_SIGNATURE_HI; + } + + offsetToInsert = ADDRESS_IMAGE_START - context.mainImageStartAddress; + mainImageData[offsetToInsert] = (context.mainImageStartAddress & 0xFF); // Lo Byte + mainImageData[offsetToInsert + 1] = (context.mainImageStartAddress & 0xFF00) >> 8; // Hi Byte + + // + // Skip the following locations for CRC calculation. + // + // 1. @FF7E, 2 + // 2. @FFFE, 2 + // + offsetToSkip = ADDRESS_IMAGE_CRC - context.mainImageStartAddress; + mainImageData[offsetToSkip] = 0xFF; + mainImageData[offsetToSkip + 1] = 0xFF; + + offsetToSkip = ADDRESS_RESET_VECTOR - context.mainImageStartAddress; + mainImageData[offsetToSkip] = 0xFF; + mainImageData[offsetToSkip + 1] = 0xFF; + + printf("\n"); + printf("====================================================================================\n"); + printf("Dump & CRC after Insert (@FF7A, 2) (@FF7C, 2) & Selective skip (@FF7E, 2) (@FFFE, 2) \n"); + printf("====================================================================================\n"); + + memset(&offsetList, 0, sizeof(OFFSET_LIST)); + offsetList.count = 4; + offsetList.offset[0] = ADDRESS_IMAGE_CRC - context.mainImageStartAddress; + offsetList.offset[1] = ADDRESS_IMAGE_CRC - context.mainImageStartAddress + 1; + offsetList.offset[2] = ADDRESS_RESET_VECTOR - context.mainImageStartAddress; + offsetList.offset[3] = ADDRESS_RESET_VECTOR - context.mainImageStartAddress + 1; + + if (verbose) { + dumpImageData(mainImageData, context.mainImageTotalLength, &offsetList); + } + + // Reset + resetCrc(); + + firstPortion = ADDRESS_IMAGE_CRC - context.mainImageStartAddress; + secondPortion = ADDRESS_RESET_VECTOR - (ADDRESS_IMAGE_CRC + LENGTH_IMAGE_CRC); + + printf("firstPortion: Start = 0x%x Length = %d (0x%x)\n", 0, firstPortion, firstPortion); + printf("secondPortion: Start = 0x%x Length = %d (0x%x)\n", firstPortion + 2, secondPortion, secondPortion); + + crc = calculateCrc(mainImageData, firstPortion); + crc = calculateCrc(mainImageData + firstPortion + 2, secondPortion); + + printf("Total Length = %d (0x%x). Final CRC = 0x%x \n", + (firstPortion + secondPortion), (firstPortion + secondPortion), crc); + + // + // Generate the CRC signature lines to be inserted to the firmware image file + // + printf("---\n"); + printf("@%x\n", ADDRESS_CRC_SIGNATURE); + printf("%02x %02x %02x %02x %02x %02x \n", + mainImageData[ADDRESS_CRC_SIGNATURE - context.mainImageStartAddress], + mainImageData[ADDRESS_CRC_SIGNATURE - context.mainImageStartAddress + 1], + mainImageData[ADDRESS_IMAGE_START - context.mainImageStartAddress], + mainImageData[ADDRESS_IMAGE_START - context.mainImageStartAddress + 1], + (crc & 0xFF), + ((crc & 0xFF00) >> 8)); + printf("---\n"); + + + free(mainImageData); + fclose(pFile); +} + + +int main(int argc, char *argv[]) +{ + bool verbose = false; + + if (argc < 2) { + printf("Usage: %s <filename> [-v]\n", argv[0]); + return -1; + } + + if (argc > 2) { + if (!strcmp(argv[2], "-v")) { + verbose = true; + } + } + + printf("Processing %s. Verbose=%d \n", argv[1], verbose); + + resetCrc(); + ProcessFile(argv[1], verbose); + return 0; +} diff --git a/src/build/buildpnor/bpm-utils/insertBpmFwCrc.py b/src/build/buildpnor/bpm-utils/insertBpmFwCrc.py new file mode 100755 index 000000000..0631ec5d2 --- /dev/null +++ b/src/build/buildpnor/bpm-utils/insertBpmFwCrc.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/buildpnor/bpm-utils/insertBpmFwCrc.py $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2019 +# [+] International Business Machines Corp. +# +# +# Copyright (c) 2019 SMART Modular Technologies, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# IBM_PROLOG_END_TAG + +import os, sys, time, datetime, glob +from subprocess import Popen, PIPE +import shlex + +# +# Function to insert the CRC signature in the +# firmware image file, inFile, and to generate the +# signature file, outFile. +# +def InsertCrcSignature(inFile, outFile, crcProgram): + + # + # Open the outFile + # + try: + print("\nOpening outFile = %s" % outFile) + outFileObj = open(outFile, "w") + except Exception as e: + print "\nException {0} occured, args: {1!r}".format(type(e).__name__, e.args) + sys.exit(999) + + # + # Read from the inFile and copy the data to the outFile. + # + # At the right address, insert the SignatureFile data + # @FF7A + # AA 55 [Start_Lo] [Start_Hi] [Crc_Lo] [Crc_Hi] + # + # generated from the imageCrc tool, to the outFile. + # + # The address insertion has to be in the proper ascending order of + # addresses given in the inFile in to the outFile. + # + # For example the outFile should have the following: + # ================================================= + # ... + # @8000 / @A000 << The firmware start address is always either one of them. + # .... + # .... + # @FF7A <<<< The "@" addresses must be in ascending order in the Firmware Image file. + # AA 55 [Start_Lo] [Start_Hi] [Crc_Lo] [Crc_Hi] + # + # .... + # @FFDA + # .... + + # Call imageCrc here + proc = Popen([crcProgram, inFile], stdout=PIPE, stderr=PIPE) + out,err = proc.communicate() + exitCode = proc.returncode + + if exitCode: + print "\nCRC generation using imageCrc utility for {0} failed, below are stdout and stderr".format(inFile) + print "Command stdout - \n{0}".format(out) + print "Command stderr - \n{0}".format(err) + sys.exit(999) + else: + print "\nCRC generation using imageCrc utility successful" + print "Command output - \n{0}".format(out) + + # Parse through output of imageCrc and get addr and signature + splitLines_crc = out.splitlines() + for counter in range(0, len(splitLines_crc)): + + if splitLines_crc[counter].startswith("@"): + crcAddressLine = splitLines_crc[counter] + crcSignature = splitLines_crc[counter+1].strip().upper() + + # Open infile here + # Keep reading infile lines, when read address > the address in signature, + # insert signature there + try: + crcWritten = 0 + print("\nOpening inFile = %s and writing to outFile now..." % inFile) + with open(inFile, "r") as ins: + # + # TODO: Have the logic to insert the signature from the + # SignatureFile inserted at the correct location in the + # outFile. + # + + for line in ins: + if line.startswith("@"): + inputFileAddr = line.strip() + # If crc already in input file, check if it is equal to calculate value + # If equal, write only once, if not equal, write calculated value + if crcWritten == 0 and inputFileAddr == crcAddressLine: + outFileObj.write(line.strip()+' \n') + if ins.next().upper() == crcSignature: + print "Correct crc already present at {0} in input file, will skip writing calculated crc again to output file".format(inputFileAddr) + else: + print "Incorrect crc present at {0} in input file, will write calculated crc {1} to output file".format(inputFileAddr, crcSignature) + outFileObj.write(crcSignature+' \n') + crcWritten = 1 + continue + # If crc not present, then write calculated value + elif crcWritten == 0 and inputFileAddr > crcAddressLine: + outFileObj.write(crcAddressLine+'\n') + outFileObj.write(crcSignature+' \n') + crcWritten = 1 + outFileObj.write(inputFileAddr.strip()+'\n') + else: + outFileObj.write(line.strip()+' \n') + + except Exception as e: + print "\nException {0} occured, args: {1!r}".format(type(e).__name__, e.args) + sys.exit(999) + + print("\nClosing Files\n") + outFileObj.close() + +## End of insertCrcSignature ######### + + +# +# Main +# +if __name__ == '__main__': + + inFile="" + outFile="" + crcProgram="" + + if (len(sys.argv) < 4): + print "\nUsage: %s <IN FILE> <OUT FILE> <CRC PROGRAM>\n" % sys.argv[0] + sys.exit(1) + else: + # + # Name of the firmware image file without the signature + # + inFile = sys.argv[1] + if '/' not in inFile: + inFile = os.getcwd() + '/' + inFile + + if not os.path.exists(inFile) or os.path.getsize(inFile) == 0: + print "\nInput File {0} does not exist or is zero in size".format(inFile) + # + # Name of the firmware image file to be generated with the signature + # + outFile = sys.argv[2] + if '/' not in outFile: + outFile = os.getcwd() + '/' + outFile + + if os.path.exists(outFile): + print "\nOutput File {0} already exists, will be overwritten".format(outFile) + + # + # Name of the CRC calculation program to be used to calculate the + # firmware image CRC + # + crcProgram = sys.argv[3] + if '/' not in crcProgram: + crcProgram = os.getcwd() + '/' + crcProgram + + if not os.path.exists(crcProgram) or os.path.getsize(crcProgram) == 0: + print "\nCRC Program {0} does not exist or is zero in size".format(crcProgram) + + # + # Call the function to insert the CRC signature + # + InsertCrcSignature(inFile, outFile, crcProgram) diff --git a/src/build/buildpnor/buildBpmFlashImages.pl b/src/build/buildpnor/buildBpmFlashImages.pl new file mode 100755 index 000000000..72219e3d9 --- /dev/null +++ b/src/build/buildpnor/buildBpmFlashImages.pl @@ -0,0 +1,878 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/buildpnor/buildBpmFlashImages.pl $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2019 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +use strict; +use warnings; +use File::Basename; +use Getopt::Long; +use Pod::Usage; + +my $progName = File::Basename::basename $0; +my $outputDir="."; +my $bpmUtilScript="./bpm-utils/insertBpmFwCrc.py"; +my $bpmCrcProgram="./bpm-utils/imageCrc"; +my @files; +my $cfgHelp=0; +my $cfgMan=0; +my $verbose=0; + +GetOptions("output-dir=s" => \$outputDir, + "bpm-util-script=s" => \$bpmUtilScript, + "bpm-crc-program=s" => \$bpmCrcProgram, + "image=s" => \@files, + "help" => \$cfgHelp, + "verbose" => \$verbose, + "man" => \$cfgMan ) || pod2usage(-verbose => 0); + +pod2usage(-verbose => 1) if $cfgHelp; +pod2usage(-verbose => 2) if $cfgMan; + +# Verify that there aren't any duplicate files in the array of input file names. +# This is done by creating an anonymous hash of all the file names and comparing +# the number of keys in the hash to the number of files in @files. If they are +# not equal then there is a duplicate file of the same name in the input file +# array. +if (keys %{{ map {$_, 1} @files }} != @files) +{ + die "One or more non-unique --image arguments supplied"; +} + +# Verify that there are no duplicate image files of different versions in the +# input --image arguments. This is done by creating an anonymous hash of all the +# output file names that would be generated based on the images given and then +# comparing the number of keys in that hash to the number of original file +# names. If the number keys and elements of @files aren't equal then there are +# two images for the same NVDIMM type of different versions present in the +# input and this is not allowed. +if (keys %{{map { (generateOutputNameAndVersion($_))[0], 1} @files}} != @files) +{ + die "One or more --image arguments are different versions of the same ". + "image. Please remove the unused versions."; +} + +if($verbose) +{ + print "Output dir = $outputDir\n"; + print "Input images:\n"; +} + +for my $file (@files) +{ + if ($verbose) + { + print " $file\n"; + } + + generateConfigImage($file,$outputDir); + generateFirmwareImage($file,$outputDir); +} + +################################################################################ +# @brief Processes an input file to pull information from its name and content +# to be used when preparing the output file's binary image. This function +# will only emit the binaries for the firmware portion of the BPM update. +# The final binary will be organized in the following way: +# Byte 1: Major version number (MM) +# Byte 2: Minor version number (mm) +# Byte 3-4: N number of blocks in the file (NN NN) +# Byte 5-EOF: Blocks of the form: +# BLOCK_SIZE Byte 1: X number of bytes in block excluding +# this byte. (XX) +# ADDRESS_OFFSET Byte 2-3: Original address offset of the +# first data byte. (AD DR) +# DATA_BYTES Byte 4-X: Firmware data bytes (DD) +# +# Example file output: +# 01 03 00 01 06 80 00 6a 14 31 80 +# MM mm NN NN XX AD DR DD DD DD DD +# +# @param[in] i_fileName Name of file +# @param[in] i_outputDir Dir to emit binary to +# +# @return N/A +################################################################################ +sub generateFirmwareImage +{ + my ($i_fileName, $i_outputDir) = @_; + my $this_func = (caller(0))[3]; + + my $intermediateFileName = generateIntermediateImage($i_fileName,$i_outputDir); + + open my $inputFileHandle, '<:encoding(UTF-8)', $intermediateFileName + or die "Failed to open $intermediateFileName"; + + my ($name, @version) = generateOutputNameAndVersion($i_fileName); + + my $imageFile = $i_outputDir . "/" . $name . "FW.bin"; + + open my $outputFileHandle, '>:raw', $imageFile + or die "Failed to open $imageFile"; + + # Indicates whether or not we're in the firmware section of the image file. + my $inFirmwareSection = undef; + + # Keep track of the number of blocks we'll be writing to the output file. + my $numberOfBlocks = 0; + + # This is the starting address of the first byte of the payload data. + my $currentAddress = 0; + + # The address offsets in the file are prefixed with the @ symbol. + use constant ADDRESS_LINE => "\@"; + use constant FW_START_ADDRESS_8000 => "\@8000"; + use constant FW_START_ADDRESS_A000 => "\@A000"; + + # Spec for BPM updates says that the maximum size for the data portion of + # the payload is 16 bytes + use constant MAXIMUM_DATA_BYTES_FOR_PAYLOAD => 16; + + # Ensure that the diamond operator ( <> ) is searching for \n to determine + # where the end of a line is in the image file. + local $/ = "\n"; + + my $blocks = undef; + while (my $line = <$inputFileHandle>) + { + # Strip off the end-of-line character \n and optionally \r if it exists. + # Since the image files were created on a windows OS and this script + # runs on linux this will not be handled properly by chomp. + $line =~ s/\r?\n$//; + + # The end of the firmware data section is marked by a 'q' + if (substr($line, 0, 1) eq "q") + { + last; + } + + # There are two possible addresses where the firmware data section can + # start: @8000 or @A000. Ignore all data until we reach either of those + # addresses since it's only after that, that the firmware data begins. + if (substr($line, 0, 1) eq ADDRESS_LINE) + { + $currentAddress = hex substr($line, 1, 4); + if ($verbose) + { + printf("Found address offset: 0x%04x\n", $currentAddress); + } + + if ( ($line eq FW_START_ADDRESS_8000) + || ($line eq FW_START_ADDRESS_A000)) + { + $inFirmwareSection = 1; + } + next; + } + + # Don't process lines that aren't firmware data. + if (not $inFirmwareSection) + { + next; + } + + # Process the line into blocks of the form: size, address offset, bytes + # Size: The size of the block. + # Note: The size here is only the size of the block itself. It does not + # have any correspondence to the final payload size which will be + # calculated during payload construction in hostboot code. + # Address offset: The address offset of the first byte of payload data. + # This will be reused during payload construction in + # hostboot code. + # Bytes: The payload data. This is the firmware data to be written to + # the BPM. + + # The length of the payload data. The maximum size of payload data is 16 + # bytes which is conveniently the maximum size of any line in the file + # minus spaces and carriage return/line feeds. + my $dataLength = calculateDataLength($line); + + if ($dataLength > MAXIMUM_DATA_BYTES_FOR_PAYLOAD) + { + die "$dataLength exceeds the maximum size for the data portion of" . + "the payload (". MAXIMUM_DATA_BYTES_FOR_PAYLOAD .")"; + } + + # total size of the block is the number of bytes from the dataLength + # plus two more for the address size. + my $blockSize = $dataLength + 2; + + # Pack the block size + # uint8_t + $blocks .= pack("C", $blockSize); + + # Pack the starting address offset of the firmware data bytes + # uint16_t + $blocks .= pack("n", $currentAddress); + + # Pack the payload data. + # Since the line is a string where each byte is an ASCII representation + # of the hex data separated by spaces, we must split the line by the + # space character and then write each byte string one at a time. Hence, + # the template "(H2)*". Each element is processed with the H2 part and + # the * just says to do this for all elements in the array emitted by + # split. + $blocks .= pack("(H2)*", split(/ /, $line)); + + # Increment the address offset by the number of firmware data + # bytes processed. + $currentAddress += $dataLength; + + ++$numberOfBlocks; + } + + if ($verbose) + { + print "number of blocks: $numberOfBlocks\n"; + } + + if (!defined($blocks)) + { + die "Unable to process image file: $intermediateFileName"; + } + + # Write the version information to the file. + print $outputFileHandle pack("(H2)*", @version) + or die "Failed to write to output file: $imageFile"; + + # Write the number of blocks in the file. + # uint16_t + print $outputFileHandle pack("n", $numberOfBlocks) + or die "Failed to write to output file: $imageFile"; + + # Write the blocks to the file + print $outputFileHandle $blocks + or die "Failed to write to output file: $imageFile"; + + close $inputFileHandle + or die "Failed to close input file: $intermediateFileName"; + unlink $intermediateFileName + or die "Failed to remove temporary file $intermediateFileName"; + close $outputFileHandle + or die "Failed to close output file: $imageFile"; +} + +################################################################################ +# @brief Processes an input file to pull information from its name and content +# to be used when preparing the output file's binary image. This function +# will only emit the binaries for the configuration data portion of the +# BPM update. +# The final binary will be organized in the following way: +# Byte 1: Major version number (MM) +# Byte 2: Minor version number (mm) +# Byte 3: N number of fragments in the file (NN) +# Byte 4-EOF: Fragments of the form: +# FRAGMENT_SIZE Byte 1: X number of bytes in fragment data +# section. (XX) +# INDEX_OFFSET Byte 2-3: Each BPM's config section is unique +# to itself. So, during update the +# contents of a BPM's config data +# will be dumped into a buffer. +# These bytes will be used as an +# offset into that buffer from which +# overwritting will take place. +# (IN DX) +# DATA_BYTES Byte 4-X: Configuration data bytes (DD) +# +# Example file output: +# 01 05 01 04 01 28 6a 14 31 80 +# MM mm NN XX IN DX DD DD DD DD +# +# @algorithm Each BPM has a config data section unique to itself so the data +# on each BPM must be dumped into a buffer and then "merged" with +# the config data from the update. The config data section is +# divided into 4 segments. A, B, C, and D. These segments appear +# in reverse order. Since it is known which "fragments" of each +# segment has to be updated this function will extract those +# fragments from the update file and organize them as described +# above so that hostboot can handle the rest. +# +# SegmentDataFromBPM: Copy of the segment data taken from the BPM (dump) +# +# SegmentDataFromFWImage: Copy of the segment data from the firmware image file. +# This could be the firmware image to be upgraded to or +# to be downgraded to. These are what will become +# fragments. +# +# Segment Address Data Source +# ===================================== +# D 1800 - 187F <---- [SegmentDataFromFWImage: 1800 - 187F] +# +# C 1880 - 18FF <---- [SegmentDataFromBPM: 1880 - 18FF] +# +# B 1900 - 197F <---- [SegmentDataFromBPM: 1900 - 1927] +# [SegmentDataFromFWImage: 1928 - 1979] +# [SegmentDataFromBPM: 197A - 197D] +# [SegmentDataFromFWImage: 197E - 197F] +# +# A 1980 - 19FF <---- [SegmentDataFromBPM: 1980 - 19FF] +# +# @param[in] i_fileName Name of file +# @param[in] i_outputDir Dir to emit binary to +# +# @return N/A +################################################################################ +sub generateConfigImage +{ + my ($i_fileName, $i_outputDir) = @_; + my $this_func = (caller(0))[3]; + + open my $inputFileHandle, '<:encoding(UTF-8)', $i_fileName + or die "Failed to open $i_fileName"; + + my ($name, @version) = generateOutputNameAndVersion($i_fileName); + + my $imageFile = $i_outputDir . "/" . $name . "CONFIG.bin"; + + open my $outputFileHandle, '>:raw', $imageFile + or die "Failed to open $imageFile"; + + # Indicates whether or not we're in the config section of the image file. + my $inConfigSection = undef; + + # Keep track of the number of fragments we'll be writing to the output file. + my $numberOfFragments = 0; + + # Used to keep track of which byte is the current byte being looked at in + # the file. + my $currentAddress = 0; + + # The address offsets in the file are prefixed with the @ symbol. + use constant ADDRESS_LINE => "\@"; + use constant CONFIG_START_ADDRESS_MARKER => "\@1800"; + use constant CONFIG_START_ADDRESS => 0x1800; + + # Segment data start addresses relative to config data start address. + use constant SEGMENT_D_START_ADDRESS => 0x000; + use constant SEGMENT_C_START_ADDRESS => 0x080; + use constant SEGMENT_B_START_ADDRESS => 0x100; + use constant SEGMENT_A_START_ADDRESS => 0x180; + + # Spec for BPM updates says that the maximum size for the data portion of + # the payload is 16 bytes + use constant MAXIMUM_DATA_BYTES_FOR_PAYLOAD => 16; + + my $fragments = undef; + my $fragmentData = undef; + my $fragmentSize = 0; + + # The offset into the segment data where the fragment data will be written. + # In hostboot code, this will be a 512 byte buffer that holds a dump of the + # BPM's unique segment data. + my $fragmentOffset = SEGMENT_D_START_ADDRESS; + + # Ensure that the diamond operator ( <> ) is searching for \n to determine + # where the end of a line is in the image file. + local $/ = "\n"; + + while (my $line = <$inputFileHandle>) + { + # Strip off the end-of-line character \n and optionally \r if it exists. + # Since the image files were created on a windows OS and this script + # runs on linux this will not be handled properly by chomp. + $line =~ s/\r?\n$//; + + # Look for @1800 starting address marker. + # + # If found, start reading the data from the file until the next "@" + # marker or "q" starting markers are found. + # + # It is possible that the input file might not have the distinct @1800 + # marker. In that case, the [currentAddress] variable is used to track + # the 0x1800 address in the input file. + if (substr($line, 0, 1) eq "q") + { + last; + } + + if (substr($line, 0, 1) eq ADDRESS_LINE) + { + $currentAddress = hex substr($line, 1); + if ($verbose) + { + printf("Found address offset: 0x%04x\n", $currentAddress); + } + + if ($line eq CONFIG_START_ADDRESS_MARKER) + { + $inConfigSection = 1; + } + next; + } + + # Process the line into fragments of the form: size, address offset, + # and bytes. + # + # Size: The size of the fragment data. + # Note: The size only corresponds to the size of the fragment data + # itself. In hostboot code, this size will indicate how much of + # the BPM's segment data will be overwritten for the given + # fragment. + # Address offset: The address offset of the start byte of segment data. + # This will be used to determine where to start + # overwritting segment data from the BPM config dump. + # Bytes: The bytes to write to the BPM config data dump buffer. + + # The length of the line. The maximum size of any line is 16 bytes. + my $dataLength = calculateDataLength($line); + + if ($dataLength > MAXIMUM_DATA_BYTES_FOR_PAYLOAD) + { + die "$dataLength exceeds the maximum size for the data portion of" . + "the payload (". MAXIMUM_DATA_BYTES_FOR_PAYLOAD .")"; + } + + # If the CONFIG_START_ADDRESS_MARKER is missing from the file then this + # will serve as the backup method to locating the config data within the + # image file. Otherwise, this will always evaluate to false. + if (($currentAddress + $dataLength) == CONFIG_START_ADDRESS) + { + # The next line is the start of the config data section of the + # image. So, skip the current line and move into the config section. + $inConfigSection = 1; + $currentAddress += $dataLength; + next; + } + + # Don't process lines that aren't config data. + if (not $inConfigSection) + { + next; + } + + # Create Segment D fragment. For Segment D, the entire segment is + # required to be updated during the firmware update. So, create a + # fragment that encompasses the whole segment. + if ($currentAddress < CONFIG_START_ADDRESS + SEGMENT_C_START_ADDRESS) + { + # Increase the fragmentSize by the amount being appended to the + # fragment. + $fragmentSize += $dataLength; + + # Pack the fragment data. + # Since the line is a string where each byte is an ASCII + # representation of the hex data separated by spaces, we + # must split the line by the space character and then write + # each byte string one at a time. Hence, the template + # "(H2)*". Each element is processed with the H2 part and + # the * just says to do this for all elements in the array + # emitted by split. + $fragmentData .= pack("(H2)*", split(/ /, $line)); + + if($currentAddress == + (CONFIG_START_ADDRESS + SEGMENT_C_START_ADDRESS - 0x10)) + { + $fragments .= createFragment($fragmentSize, + $fragmentOffset, + $fragmentData, + $numberOfFragments); + } + } + # Segment C is skipped over implicitly since there is no segment data in + # segment C that needs to be applied to the BPM. + elsif ( ($currentAddress >= + (CONFIG_START_ADDRESS + SEGMENT_B_START_ADDRESS)) + && ($currentAddress < + (CONFIG_START_ADDRESS + SEGMENT_A_START_ADDRESS))) + { + # Work on Segment B data. There will be two fragments created for + # this segment. + # Fragment 1: [0x1928 - 0x1979] + # Fragment 2: [0x197E - 0x197F] + my $createFragment = 0; + + # According to SMART's documentation, each segment must be 8 lines + # of 16 byte rows. Since we are searching for a specific region in + # segment B to create a fragment from we bound the fragment packing + # code by the borders of that region. + if ( ($currentAddress >= + (CONFIG_START_ADDRESS + SEGMENT_B_START_ADDRESS + 0x20)) + && ($currentAddress < + (CONFIG_START_ADDRESS + SEGMENT_B_START_ADDRESS + 0x80))) + { + # Only need bytes from [0x1928 to 0x1979] to form Fragment 1. + # If we are not on the bounds of the fragment then we can simply + # pack the data and update the size. + # Otherwise, we must do some extra trimming. + if ($currentAddress == + (CONFIG_START_ADDRESS + SEGMENT_B_START_ADDRESS + 0x20)) + { + # This is the begining of Fragment 1's range. Trim off the + # bytes with offsets less than 0x1928. + + # Set the fragmentOffset to the start of the range + $fragmentOffset = SEGMENT_B_START_ADDRESS + + 0x28; + + # Split the line into individual bytes and only pack + # required bytes. + my @bytes = split(/ /, $line); + + # Drop the first eight bytes since they aren't in the range. + splice @bytes, 0, 8; + + $fragmentSize += scalar @bytes; + + $fragmentData .= pack("(H2)*", @bytes); + + # Since this is the begining of Fragment 1, there is still + # data left to be appended to this fragment. So don't call + # createFragment(). + } + elsif ($currentAddress == + (CONFIG_START_ADDRESS + SEGMENT_B_START_ADDRESS + 0x70)) + { + # This is the last line in the range of Fragment 1 and the + # only line where Fragment 2 data is. So, trimming is + # required to finalize Fragment 1 and create Fragment 2. + + # Start by finishing off Fragment 1. + # Split the line into individual bytes and only pack + # required bytes. + my @bytes = split(/ /, $line); + + # Drop the last six bytes since they aren't + # in range [0x1928-0x1979] + splice @bytes, 10, 6; + + $fragmentSize += scalar @bytes; + + $fragmentData .= pack("(H2)*", @bytes); + + # Now that Fragment 1 is completed, create the fragment and + # append it to the list of fragments. + $fragments .= createFragment($fragmentSize, + $fragmentOffset, + $fragmentData, + $numberOfFragments); + + # Now work on Fragment 2. + # Only need bytes from [0x197E to 0x197F] to form Fragment 2 + + # Set the fragmentOffset + $fragmentOffset = SEGMENT_B_START_ADDRESS + + 0x7E; + + # Split the line into individual bytes and only pack + # required bytes. + @bytes = split(/ /, $line); + + # Drop the first 14 bytes since they aren't in + # range [0x197E to 0x197F] + splice @bytes, 0, 14; + + $fragmentSize += scalar @bytes; + + $fragmentData .= pack("(H2)*", @bytes); + + # Fragment 2 is complete. Create the fragment and append to + # list of fragments. + $fragments .= createFragment($fragmentSize, + $fragmentOffset, + $fragmentData, + $numberOfFragments); + + } + else + { + # We are not on a fragment boundary, so append the full line + # of data to Fragment 1. + + # Increase the fragmentSize by the amount being appended to + # the fragment. + $fragmentSize += $dataLength; + + # Pack the fragment data. + # Since the line is a string where each byte is an ASCII + # representation of the hex data separated by spaces, we + # must split the line by the space character and then write + # each byte string one at a time. Hence, the template + # "(H2)*". Each element is processed with the H2 part and + # the * just says to do this for all elements in the array + # emitted by split. + $fragmentData .= pack("(H2)*", split(/ /, $line)); + } + } + } + elsif ($currentAddress >= + (CONFIG_START_ADDRESS + SEGMENT_A_START_ADDRESS)) + { + # Don't need to create fragments in Segment A. + last; + } + + # Increment the address offset by the number of firmware data + # bytes processed. + $currentAddress += $dataLength; + } + + if ($verbose) + { + print "number of fragments: $numberOfFragments\n"; + } + + if (!defined($fragments)) + { + die "Unable to process image file: $i_fileName"; + } + + # Write the version information to the file. + print $outputFileHandle pack("(H2)*", @version) + or die "Failed to write to output file: $imageFile"; + + # Write the number of fragments in the file. + # uint16_t + print $outputFileHandle pack("n", $numberOfFragments) + or die "Failed to write to output file: $imageFile"; + + # Write the fragments to the file + print $outputFileHandle $fragments + or die "Failed to write to output file: $imageFile"; + + close $inputFileHandle + or die "Failed to close input file: $i_fileName"; + close $outputFileHandle + or die "Failed to close output file: $imageFile"; +} + +################################################################################ +# @brief Transforms the input file name into the output file name and extracts +# the version info from the file name since that info is not present in +# the image file itself. +# +# @param[in] i_fileName Name of file +# +# @return An array that contains the filename as the first +# element and the version info array as the second. +################################################################################ +sub generateOutputNameAndVersion +{ + # Input Parameter + my $i_fileName = shift; + + # Parse the file name into its filename, path, and suffix. + my ($name, $path, $suffix) = fileparse($i_fileName, ".txt"); + + # Split the filename by underscore to access the information contained in + # the file name. + # According to the spec an example filename would be of the form: + # S R C A80 6 2 IBM H 01 1 B _FULL_ FW_Rev1.03_02282019.txt + # ^ ^ ^ + # 1: Number of NVDIMM interfaces (1 = 32GB, 2 = 16GB) + # _FULL_: The image contains the firmware and configuration data. + # Rev1.03: Version of this image file + my @fileNameComponents = split(/_/, $name); + + # The NVDIMM interface types supported + my %nvdimmTypes = ( 1 => "32GB", + 2 => "16GB", ); + + # Extract the NVDIMM Interface number from filename + my $nvdimmInterfaceNumber = substr($fileNameComponents[0], -2, 1); + + # Convert interface number to the appropriate human-readable type + my $nvdimmType = ""; + if (exists($nvdimmTypes{$nvdimmInterfaceNumber})) + { + $nvdimmType = $nvdimmTypes{$nvdimmInterfaceNumber}; + } + else + { + die "NVDIMM Interface Type $nvdimmInterfaceNumber Unsupported"; + } + + # Extract the version from the filename and convert it to a two one byte hex + # strings. + my @versionComponents = split(/\./, $name); + my @version = + sprintf("%.2X", substr($versionComponents[0], -2, 2) =~ /([0-9]+)/g); + push(@version, + sprintf("%.2X", substr($versionComponents[1], 0, 2) =~ /([0-9]+)/g)); + + + if ($verbose) + { + print "\tNVDIMM Type -> ". $nvdimmType ."\n"; + print "\tVersion Info -> Major: " . $version[0] . + " Minor: " . $version[1] . "\n"; + } + + return ($nvdimmType."-NVDIMM-BPM-", @version); + +} + +################################################################################ +# @brief Processes input image file to generate CRC signature, firmware start +# address, and calculated CRC bytes at address marker @FF7A. This +# function simply calls SMART's supplied python script to perform the +# operations. This intermediate file is only used during the firmware +# binary generation. +# +# @param[in] i_fileName Name of file +# +# @return txt file name The temporary file that has the calculated CRC +################################################################################ +sub generateIntermediateImage +{ + my ($i_fileName, $i_outputDir) = @_; + + # Parse the file name into its filename, path, and suffix. + my ($name, $path, $suffix) = fileparse($i_fileName, ".txt"); + + # Parse the file name into its filename, path, and suffix. + my ($utilName, $utilPath, $utilSuffix) = fileparse($bpmUtilScript, ".txt"); + + my $intermediateFileName = $i_outputDir . $name . ".crc"; + + # Call the python script which will insert the CRC + my $pythonReturn = system($bpmUtilScript, + $i_fileName, + $intermediateFileName, + $bpmCrcProgram); + + return $intermediateFileName; + +} + +################################################################################ +# @brief Creates a new fragment by packing the fragment size, offset, and data; +# then it cleans up the fragment parameters so that the caller doesn't +# have to. +# +# @param[in] io_fragmentSize The size of the fragment data section. +# @param[in] i_fragmentOffset The offset into the BPM config dump buffer +# that this fragment should begin overwritting +# at. +# @param[in] io_fragmentData The partial config segment data from the +# flash image to be written to the BPM during +# the update procedure. +# @param[in] io_numberOfFragments This parameter incremented by this function +# so the caller can keep track of how many +# fragments have been created so far. However, +# due to the messiness of perl syntax this +# parameter is created as a visual reference +# only and not used directly. +# +# @return The created fragment +################################################################################ +sub createFragment +{ + my ($io_fragmentSize, + $i_fragmentOffset, + $io_fragmentData, + $io_numberOfFragments) = @_; + + # Pack the fragment size + # uint8_t + my $fragment .= pack("C", $io_fragmentSize); + + # Pack the BPM dump offset. + # uint16_t + $fragment .= pack("n", $i_fragmentOffset); + + # Pack the fragment data + $fragment .= $io_fragmentData; + + # Keep track of number of fragments in output + $_[3]++; # $io_numberOfFragments + + # Reset variables + $_[2] = undef; # $io_fragmentData + $_[0] = 0; # $io_fragmentSize + + return $fragment; +} + +################################################################################ +# @brief Calculates the data length of the line by stripping all spaces for it +# dividing by the number of bytes on the line. +# +# @param[in] i_line The line to calculate the length on. +# +# @return The number of bytes on the line (length). +################################################################################ +sub calculateDataLength +{ + my $i_line = shift; + + # Strip all the spaces from the line. + $i_line =~ s/\s+//g; + + # Each line is plain text where each byte is separated by spaces. + # To determine how many bytes are on the line, divide by characters per byte + use constant CHARS_PER_BYTE => 2; + my $dataLength = length($i_line) / CHARS_PER_BYTE; + + return $dataLength; +} + +__END__ + +=head1 NAME + +buildBpmFlashImage.pl + +=head1 SYNOPSIS + +buildBpmFlashImage.pl [..] + +=head1 OPTIONS + +=over 8 + +=item B<--help> + +Prints a brief help message and exits. + +=item B<--man> + +Prints the manual page and exits. + +=item B<--output-dir> + +Path to directory to emit the output files to. + +=item B<--image> + +File containing a BPM flash update script. More than one --image +argument can be provided. If no images are supplied, the script will do +nothing. + +=back + +=head1 DESCRIPTION + +B<buildBpmFlashImage.pl> will process a set of one or more BPM flash update +scripts in .txt format by transforming the lines of text into blocks of binary +data of the form BLOCK_SIZE, ADDRESS_OFFSET, PAYLOAD. The final binary output by +this script will have the first 2 bytes be the version info (first byte Major, +second Minor), then followed by two bytes that give the number of blocks in the +file, and the remainder of the file will be blocks organized in the following +way: + +BLOCK_SIZE is the number of bytes following the BLOCK_SIZE byte. +ADDRESS_OFFSET is the offset the PAYLOAD data originally came from within the .txt file. +PAYLOAD is the data, along with the ADDRESS_OFFSET, that will be used to construct the payloads to send to the BPM to perform the update. + +=cut diff --git a/src/build/buildpnor/buildpnor.pl b/src/build/buildpnor/buildpnor.pl index 227e8fe0f..eb76f868f 100755 --- a/src/build/buildpnor/buildpnor.pl +++ b/src/build/buildpnor/buildpnor.pl @@ -6,7 +6,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2018 +# Contributors Listed Below - COPYRIGHT 2012,2019 # [+] International Business Machines Corp. # # @@ -56,6 +56,7 @@ my %SideOptions = ( B => "B", sideless => "sideless", ); +my $editedLayoutLocation = ""; if ($#ARGV < 0) { usage(); @@ -95,6 +96,10 @@ for (my $i=0; $i < $#ARGV + 1; $i++) elsif($ARGV[$i] =~ /--test/) { $testRun = 1; } + elsif($ARGV[$i] =~ /--editedLayoutLocation/) { + $editedLayoutLocation = $ARGV[++$i]; + trace(2, "Location where the edited layout file will be placed: $editedLayoutLocation"); + } else { traceErr("Unrecognized Input: $ARGV[$i]"); exit 1; @@ -112,7 +117,8 @@ if (-e $pnorBinName) } #Load PNOR Layout XML file -loadPnorLayout($pnorLayoutFile, \%pnorLayout, \%PhysicalOffsets, $testRun); +loadPnorLayout($pnorLayoutFile, \%pnorLayout, \%PhysicalOffsets, $testRun, + $editedLayoutLocation); #Verify all the section files exist verifyFilesExist(\%pnorLayout, \%binFiles); @@ -621,6 +627,7 @@ print <<"ENDUSAGE"; --fpartCmd invoke string for executing the fpart tool --fcpCmd invoke string for executing the fcp tool --test Output test-only sections. + --editedLayoutLocation <directory> Location to place edited layout file Current Limitations: --TOC Records must be 4 or 8 bytes in length diff --git a/src/build/buildpnor/defaultPnorLayout.xml b/src/build/buildpnor/defaultPnorLayout.xml index bb59a60fa..6e7c88e3d 100644 --- a/src/build/buildpnor/defaultPnorLayout.xml +++ b/src/build/buildpnor/defaultPnorLayout.xml @@ -89,7 +89,6 @@ Layout Description <section> <description>Guard Data (20K)</description> <eyeCatch>GUARD</eyeCatch> - <physicalOffset>0x2C000</physicalOffset> <physicalRegionSize>0x5000</physicalRegionSize> <side>sideless</side> <ecc/> @@ -98,7 +97,7 @@ Layout Description <description>DIMM JEDEC (288K)</description> <eyeCatch>DJVPD</eyeCatch> <!--NOTE: MUST update standalone.simics if offset changes --> - <physicalOffset>0x31000</physicalOffset> + <physicalOffset>0x31000</physicalOffset> <physicalRegionSize>0x48000</physicalRegionSize> <side>sideless</side> <ecc/> @@ -124,7 +123,6 @@ Layout Description <section> <description>Hostboot Base (1MB)</description> <eyeCatch>HBB</eyeCatch> - <physicalOffset>0x151000</physicalOffset> <physicalRegionSize>0x100000</physicalRegionSize> <side>sideless</side> <sha512Version/> @@ -133,7 +131,6 @@ Layout Description <section> <description>Hostboot Data (2MB)</description> <eyeCatch>HBD</eyeCatch> - <physicalOffset>0x251000</physicalOffset> <physicalRegionSize>0x200000</physicalRegionSize> <sha512Version/> <side>sideless</side> @@ -142,7 +139,6 @@ Layout Description <section> <description>Hostboot Extended image (14.22MB w/o ECC)</description> <eyeCatch>HBI</eyeCatch> - <physicalOffset>0x451000</physicalOffset> <physicalRegionSize>0x1000000</physicalRegionSize> <sha512Version/> <side>sideless</side> @@ -151,7 +147,6 @@ Layout Description <section> <description>SBE-IPL (Staging Area) (752K)</description> <eyeCatch>SBE</eyeCatch> - <physicalOffset>0x1451000</physicalOffset> <physicalRegionSize>0xBC000</physicalRegionSize> <sha512perEC/> <sha512Version/> @@ -161,7 +156,6 @@ Layout Description <section> <description>HCODE Ref Image (1.125MB)</description> <eyeCatch>HCODE</eyeCatch> - <physicalOffset>0x150D000</physicalOffset> <physicalRegionSize>0x120000</physicalRegionSize> <sha512Version/> <side>sideless</side> @@ -170,17 +164,15 @@ Layout Description <section> <description>Hostboot Runtime Services for Sapphire (7.0MB)</description> <eyeCatch>HBRT</eyeCatch> - <physicalOffset>0x162D000</physicalOffset> <physicalRegionSize>0x700000</physicalRegionSize> <sha512Version/> <side>sideless</side> <ecc/> </section> <section> - <description>Payload (19.875MB)</description> + <description>Payload (6MB)</description> <eyeCatch>PAYLOAD</eyeCatch> - <physicalOffset>0x1D2D000</physicalOffset> - <physicalRegionSize>0x13E0000</physicalRegionSize> + <physicalRegionSize>0x0600000</physicalRegionSize> <sha512Version/> <side>sideless</side> <ecc/> @@ -188,7 +180,6 @@ Layout Description <section> <description>Special PNOR Test Space (36K)</description> <eyeCatch>TEST</eyeCatch> - <physicalOffset>0x310D000</physicalOffset> <physicalRegionSize>0x9000</physicalRegionSize> <testonly/> <side>sideless</side> @@ -199,7 +190,6 @@ Layout Description from skipping header. Signing is forced in build pnor phase --> <description>Special PNOR Test Space with Header (36K)</description> <eyeCatch>TESTRO</eyeCatch> - <physicalOffset>0x3116000</physicalOffset> <physicalRegionSize>0x9000</physicalRegionSize> <side>sideless</side> <testonly/> @@ -210,7 +200,6 @@ Layout Description <section> <description>Hostboot Bootloader (28K)</description> <eyeCatch>HBBL</eyeCatch> - <physicalOffset>0x311F000</physicalOffset> <!-- Physical Size includes Header rounded to ECC valid size --> <!-- Max size of actual HBBL content is 20K and 22.5K with ECC --> <physicalRegionSize>0x7000</physicalRegionSize> @@ -219,17 +208,8 @@ Layout Description <ecc/> </section> <section> - <description>Global Data (36K)</description> - <eyeCatch>GLOBAL</eyeCatch> - <physicalOffset>0x3126000</physicalOffset> - <physicalRegionSize>0x9000</physicalRegionSize> - <side>sideless</side> - <ecc/> - </section> - <section> <description>Ref Image Ring Overrides (20K)</description> <eyeCatch>RINGOVD</eyeCatch> - <physicalOffset>0x312F000</physicalOffset> <physicalRegionSize>0x5000</physicalRegionSize> <side>sideless</side> <ecc/> @@ -237,7 +217,6 @@ Layout Description <section> <description>SecureBoot Key Transition Partition (16K)</description> <eyeCatch>SBKT</eyeCatch> - <physicalOffset>0x3134000</physicalOffset> <physicalRegionSize>0x4000</physicalRegionSize> <side>sideless</side> <ecc/> @@ -245,7 +224,6 @@ Layout Description <section> <description>OCC Lid (1.125M)</description> <eyeCatch>OCC</eyeCatch> - <physicalOffset>0x3138000</physicalOffset> <physicalRegionSize>0x120000</physicalRegionSize> <sha512Version/> <side>sideless</side> @@ -256,7 +234,6 @@ Layout Description <!-- We need 266KB per module sort, going to support 40 tables by default, plus ECC --> <eyeCatch>WOFDATA</eyeCatch> - <physicalOffset>0x3258000</physicalOffset> <!-- TODO RTC: 208004 Reduced by MB total to allow HBI + tests to fit in PNOR, need to increase back 1 MB once HBI size @@ -269,7 +246,6 @@ Layout Description <section> <description>FIRDATA (12K)</description> <eyeCatch>FIRDATA</eyeCatch> - <physicalOffset>0x3E58000</physicalOffset> <physicalRegionSize>0x3000</physicalRegionSize> <side>sideless</side> <ecc/> @@ -277,7 +253,6 @@ Layout Description <section> <description>Memory Data (128K)</description> <eyeCatch>MEMD</eyeCatch> - <physicalOffset>0x3E5B000</physicalOffset> <physicalRegionSize>0x20000</physicalRegionSize> <side>sideless</side> <sha512Version/> @@ -286,7 +261,6 @@ Layout Description <section> <description>Secureboot Test Load (12K)</description> <eyeCatch>TESTLOAD</eyeCatch> - <physicalOffset>0x3E7B000</physicalOffset> <physicalRegionSize>0x3000</physicalRegionSize> <side>sideless</side> <sha512Version/> @@ -295,7 +269,6 @@ Layout Description <section> <description>Centaur Hw Ref Image (12K)</description> <eyeCatch>CENHWIMG</eyeCatch> - <physicalOffset>0x3E7E000</physicalOffset> <physicalRegionSize>0x3000</physicalRegionSize> <sha512Version/> <side>sideless</side> @@ -304,7 +277,6 @@ Layout Description <section> <description>Secure Boot (144K)</description> <eyeCatch>SECBOOT</eyeCatch> - <physicalOffset>0x3E81000</physicalOffset> <physicalRegionSize>0x24000</physicalRegionSize> <side>sideless</side> <ecc/> @@ -313,7 +285,6 @@ Layout Description <section> <description>Open CAPI Memory Buffer (OCMB) Firmware (300K)</description> <eyeCatch>OCMBFW</eyeCatch> - <physicalOffset>0x3EA5000</physicalOffset> <physicalRegionSize>0x4B000</physicalRegionSize> <side>sideless</side> <sha512Version/> @@ -323,7 +294,6 @@ Layout Description <section> <description>HDAT Data (16K)</description> <eyeCatch>HDAT</eyeCatch> - <physicalOffset>0x3EF0000</physicalOffset> <physicalRegionSize>0x4000</physicalRegionSize> <side>sideless</side> <sha512Version/> diff --git a/src/build/buildpnor/genPnorImages.pl b/src/build/buildpnor/genPnorImages.pl index 4782b7e8f..cc3b4f5e9 100755 --- a/src/build/buildpnor/genPnorImages.pl +++ b/src/build/buildpnor/genPnorImages.pl @@ -61,6 +61,11 @@ my $programName = File::Basename::basename $0; my @systemBinFiles = (); my %pnorLayout = (); my %PhysicalOffsets = (); +my %partitionUtilHash; + +# percentage utilization threshold, if crossed display warning message +# that partition is almost full +use constant CRITICAL_THRESHOLD => 85.00; # Truncate SHA to n bytes use constant SHA_TRUNCATE_SIZE => 32; @@ -74,6 +79,7 @@ use constant VFS_MODULE_TABLE_MAX_SIZE => VFS_EXTENDED_MODULE_MAX # Flag parameter string passed into signing tools # Note spaces before/after are critical. use constant OP_SIGNING_FLAG => " --flags "; +use constant SW_FLAG_HAS_A_HPT => 0x80000000; # Security bits HW flag strings use constant OP_BUILD_FLAG => 0x80000000; use constant FIPS_BUILD_FLAG => 0x40000000; @@ -120,6 +126,7 @@ my $sign_mode = $DEVELOPMENT; my $hwKeyHashFile = ""; my $hb_standalone=""; my $buildType=""; +my $editedLayoutLocation=""; # @TODO RTC 170650: Set default to 0 after all environments provide external # control over this policy, plus remove '!' from 'lab-security-override' @@ -142,6 +149,7 @@ GetOptions("binDir:s" => \$bin_dir, "lab-security-override!" => \$labSecurityOverride, "emit-eccless" => \$emitEccless, "build-type:s" => \$buildType, + "editedLayoutLocation:s" => \$editedLayoutLocation, "help" => \$help); if ($help) @@ -385,7 +393,8 @@ if ($build_all && $secureboot) } #Load PNOR Layout XML file -loadPnorLayout($pnorLayoutFile, \%pnorLayout, \%PhysicalOffsets, $testRun); +loadPnorLayout($pnorLayoutFile, \%pnorLayout, \%PhysicalOffsets, $testRun, + $editedLayoutLocation); # Generate final images for each system's bin files. foreach my $binFilesCSV (@systemBinFiles) @@ -408,6 +417,17 @@ foreach my $binFilesCSV (@systemBinFiles) manipulateImages(\%pnorLayout, \%binFiles, $system_target); } +# display percentage utilization data for each eyecatch +foreach my $key (keys %partitionUtilHash) { + + print "$key is $partitionUtilHash{$key}{pctUtilized} utilized ($partitionUtilHash{$key}{freeBytes} of $partitionUtilHash{$key}{physicalRegionSize} bytes free)\n"; + + # if percentage is greater than critical threshold, surface warning + if ($partitionUtilHash{$key}{pctUtilized} > CRITICAL_THRESHOLD) { + print "Warning: Percent utilization for $key shows that partition is almost full.\n"; + } +} + ################################################################################ # Subroutines ################################################################################ @@ -451,6 +471,7 @@ sub partitionDepSort ################################################################################ # manipulateImages - Perform any ECC/padding/sha/signing manipulations ################################################################################ + sub manipulateImages { my ($i_pnorLayoutRef, $i_binFilesRef, $system_target) = @_; @@ -464,7 +485,10 @@ sub manipulateImages # Partitions that have a hash page table at the beginning of the section # for secureboot purposes. - my %hashPageTablePartitions = (HBI => 1); + # TODO: add back SBE and HCODE as per story 209485 + my %hashPageTablePartitions = (HBI => 1, + WOFDATA => 1, + MEMD => 1); if($ENV{'RM_HASH_PAGE_TABLE'}) { undef %hashPageTablePartitions; @@ -483,7 +507,16 @@ sub manipulateImages instructionStartStackPointer => 0); my $layoutKey = findLayoutKeyByEyeCatch($key, \%$i_pnorLayoutRef); + + # Skip if binary file isn't included in the PNOR layout file + if ($layoutKey eq -1) + { + print "Warning: skipping $key since it is NOT in the PNOR layout file\n"; + next; + } + my $eyeCatch = $sectionHash{$layoutKey}{eyeCatch}; + my $physicalRegionSize = $sectionHash{$layoutKey}{physicalRegionSize}; my %tempImages = ( HDR_PHASE => "$bin_dir/$parallelPrefix.$eyeCatch.temp.hdr.bin", TEMP_SHA_IMG => "$bin_dir/$parallelPrefix.$eyeCatch.temp.sha.bin", @@ -506,24 +539,23 @@ sub manipulateImages # Sections that have secureboot support. Secureboot still must be # enabled for secureboot actions on these partitions to occur. my $isNormalSecure = ($eyeCatch eq "HBBL"); - $isNormalSecure ||= ($eyeCatch eq "SBE"); - $isNormalSecure ||= ($eyeCatch eq "MEMD"); $isNormalSecure ||= ($eyeCatch eq "HBRT"); $isNormalSecure ||= ($eyeCatch eq "PAYLOAD"); $isNormalSecure ||= ($eyeCatch eq "OCC"); - $isNormalSecure ||= ($eyeCatch eq "CAPP"); $isNormalSecure ||= ($eyeCatch eq "BOOTKERNEL"); - $isNormalSecure ||= ($eyeCatch eq "HCODE"); - $isNormalSecure ||= ($eyeCatch eq "CENHWIMG"); - $isNormalSecure ||= ($eyeCatch eq "WOFDATA"); $isNormalSecure ||= ($eyeCatch eq "IMA_CATALOG"); $isNormalSecure ||= ($eyeCatch eq "TESTRO"); $isNormalSecure ||= ($eyeCatch eq "TESTLOAD"); $isNormalSecure ||= ($eyeCatch eq "VERSION"); + $isNormalSecure ||= ($eyeCatch eq "CENHWIMG"); + $isNormalSecure ||= ($eyeCatch eq "SBE"); + $isNormalSecure ||= ($eyeCatch eq "HCODE"); my $isSpecialSecure = ($eyeCatch eq "HBB"); $isSpecialSecure ||= ($eyeCatch eq "HBD"); $isSpecialSecure ||= ($eyeCatch eq "HBI"); + $isSpecialSecure ||= ($eyeCatch eq "WOFDATA"); + $isSpecialSecure ||= ($eyeCatch eq "MEMD"); # Used to indicate security is supported in firmware my $secureSupported = $isNormalSecure || $isSpecialSecure; @@ -662,6 +694,9 @@ sub manipulateImages else { run_command("cp $tempImages{hashPageTable} $tempImages{PAYLOAD_TEXT}"); + # Hash table generated so need to set sw-flags + my $hex_sw_flag = sprintf("0x%08X", SW_FLAG_HAS_A_HPT); + $CUR_OPEN_SIGN_REQUEST .= " --sw-flags $hex_sw_flag "; } run_command("$CUR_OPEN_SIGN_REQUEST " @@ -734,6 +769,22 @@ sub manipulateImages setCallerHwHdrFields(\%callerHwHdrFields, $tempImages{HDR_PHASE}); + + # store binary file size + header size in hash + + # If section will passed through ecc, include this in size calculation + if( ($sectionHash{$layoutKey}{ecc} eq "yes") ) + { + $partitionUtilHash{$eyeCatch}{logicalFileSize} = $callerHwHdrFields{totalContainerSize} * (9/8); + } + else + { + $partitionUtilHash{$eyeCatch}{logicalFileSize} = $callerHwHdrFields{totalContainerSize}; + } + $partitionUtilHash{$eyeCatch}{pctUtilized} = sprintf("%.2f", $partitionUtilHash{$eyeCatch}{logicalFileSize} / $physicalRegionSize * 100); + $partitionUtilHash{$eyeCatch}{freeBytes} = $physicalRegionSize - $partitionUtilHash{$eyeCatch}{logicalFileSize}; + $partitionUtilHash{$eyeCatch}{physicalRegionSize} = $physicalRegionSize; + # Padding Phase if ($eyeCatch eq "HBI" && $testRun) { @@ -1258,6 +1309,7 @@ print <<"ENDUSAGE"; switch (separated with a space and not including the single quotes). OpenPower is the default. + --editedLayoutLocation <directory> Location to place edited layout file Current Limitations: - Issues with dependency on ENGD build for certain files such as SBE. This is why [--build-all | --install-all ] are used. diff --git a/src/build/buildpnor/memd_creation.pl b/src/build/buildpnor/memd_creation.pl index c4f551b03..b33981ad6 100755 --- a/src/build/buildpnor/memd_creation.pl +++ b/src/build/buildpnor/memd_creation.pl @@ -66,7 +66,7 @@ pod2usage(-verbose => 2) if $man; if($memd_dir) { print "Reading files from $memd_dir\n"; - @memd_files = glob($memd_dir . '/*'); + @memd_files = glob($memd_dir . '/*vpd'); } elsif(@memd_files) { diff --git a/src/build/buildpnor/pkgOcmbFw.pl b/src/build/buildpnor/pkgOcmbFw.pl index eb5d8f953..b7fdb90cf 100755 --- a/src/build/buildpnor/pkgOcmbFw.pl +++ b/src/build/buildpnor/pkgOcmbFw.pl @@ -89,6 +89,13 @@ # ############################################################################### +# ******************WARNING********************** +# +# THIS FILE MUST BE KEPT IN SYNC WITH +# src/include/usr/expupd/ocmbFwImage_const.H +# +# ******************WARNING********************** + use strict; use File::Basename; use Digest::SHA qw(sha512); diff --git a/src/build/buildpnor/pnorLayoutAxone.xml b/src/build/buildpnor/pnorLayoutAxone.xml index 150bab112..274439a39 100644 --- a/src/build/buildpnor/pnorLayoutAxone.xml +++ b/src/build/buildpnor/pnorLayoutAxone.xml @@ -86,26 +86,31 @@ Layout Description <ecc/> </section> <section> + <!-- NOTE must be before images that are likely to change like HBI, + also mustupdate standalone.simics if EECACHE offset changes--> + <description>Eeprom Cache(512K)</description> + <eyeCatch>EECACHE</eyeCatch> + <physicalOffset>0x2C000</physicalOffset> + <physicalRegionSize>0x80000</physicalRegionSize> + <side>sideless</side> + <ecc/> + </section> + <section> <description>Guard Data (20K)</description> <eyeCatch>GUARD</eyeCatch> - <physicalOffset>0x2C000</physicalOffset> <physicalRegionSize>0x5000</physicalRegionSize> <side>sideless</side> <ecc/> </section> <section> - <description>Module VPD (576K)</description> - <eyeCatch>MVPD</eyeCatch> - <!--NOTE: MUST update standalone.simics if offset changes --> - <physicalOffset>0x31000</physicalOffset> - <physicalRegionSize>0x90000</physicalRegionSize> + <description>Attributes</description> + <eyeCatch>ATTR_TMP</eyeCatch> + <physicalRegionSize>0x4000</physicalRegionSize> <side>sideless</side> - <ecc/> </section> <section> <description>Hostboot Base (1MB)</description> <eyeCatch>HBB</eyeCatch> - <physicalOffset>0xC1000</physicalOffset> <physicalRegionSize>0x100000</physicalRegionSize> <side>sideless</side> <sha512Version/> @@ -114,17 +119,15 @@ Layout Description <section> <description>Hostboot Data (2MB)</description> <eyeCatch>HBD</eyeCatch> - <physicalOffset>0x1C1000</physicalOffset> <physicalRegionSize>0x200000</physicalRegionSize> <sha512Version/> <side>sideless</side> <ecc/> </section> <section> - <description>Hostboot Extended image (14.22MB w/o ECC)</description> + <description>Hostboot Extended image (17.77MB w/o ECC)</description> <eyeCatch>HBI</eyeCatch> - <physicalOffset>0x3C1000</physicalOffset> - <physicalRegionSize>0x1000000</physicalRegionSize> + <physicalRegionSize>0x1400000</physicalRegionSize> <sha512Version/> <side>sideless</side> <ecc/> @@ -132,7 +135,6 @@ Layout Description <section> <description>SBE-IPL (Staging Area) (752K)</description> <eyeCatch>SBE</eyeCatch> - <physicalOffset>0x13C1000</physicalOffset> <physicalRegionSize>0xBC000</physicalRegionSize> <sha512perEC/> <sha512Version/> @@ -142,26 +144,23 @@ Layout Description <section> <description>HCODE Ref Image (1.125MB)</description> <eyeCatch>HCODE</eyeCatch> - <physicalOffset>0x147D000</physicalOffset> <physicalRegionSize>0x120000</physicalRegionSize> <sha512Version/> <side>sideless</side> <ecc/> </section> <section> - <description>Hostboot Runtime Services for Sapphire (7.0MB)</description> + <description>Hostboot Runtime Services for Sapphire (8.0MB)</description> <eyeCatch>HBRT</eyeCatch> - <physicalOffset>0x159D000</physicalOffset> - <physicalRegionSize>0x700000</physicalRegionSize> + <physicalRegionSize>0x800000</physicalRegionSize> <sha512Version/> <side>sideless</side> <ecc/> </section> <section> - <description>Payload (19.875MB)</description> + <description>Payload (16KB)</description> <eyeCatch>PAYLOAD</eyeCatch> - <physicalOffset>0x1C9D000</physicalOffset> - <physicalRegionSize>0x13E0000</physicalRegionSize> + <physicalRegionSize>0x4000</physicalRegionSize> <sha512Version/> <side>sideless</side> <ecc/> @@ -169,7 +168,6 @@ Layout Description <section> <description>Special PNOR Test Space (36K)</description> <eyeCatch>TEST</eyeCatch> - <physicalOffset>0x307D000</physicalOffset> <physicalRegionSize>0x9000</physicalRegionSize> <testonly/> <side>sideless</side> @@ -180,7 +178,6 @@ Layout Description from skipping header. Signing is forced in build pnor phase --> <description>Special PNOR Test Space with Header (36K)</description> <eyeCatch>TESTRO</eyeCatch> - <physicalOffset>0x3086000</physicalOffset> <physicalRegionSize>0x9000</physicalRegionSize> <side>sideless</side> <testonly/> @@ -191,7 +188,6 @@ Layout Description <section> <description>Hostboot Bootloader (28K)</description> <eyeCatch>HBBL</eyeCatch> - <physicalOffset>0x308F000</physicalOffset> <!-- Physical Size includes Header rounded to ECC valid size --> <!-- Max size of actual HBBL content is 20K and 22.5K with ECC --> <physicalRegionSize>0x7000</physicalRegionSize> @@ -200,17 +196,8 @@ Layout Description <ecc/> </section> <section> - <description>Global Data (36K)</description> - <eyeCatch>GLOBAL</eyeCatch> - <physicalOffset>0x3096000</physicalOffset> - <physicalRegionSize>0x9000</physicalRegionSize> - <side>sideless</side> - <ecc/> - </section> - <section> <description>Ref Image Ring Overrides (20K)</description> <eyeCatch>RINGOVD</eyeCatch> - <physicalOffset>0x309F000</physicalOffset> <physicalRegionSize>0x5000</physicalRegionSize> <side>sideless</side> <ecc/> @@ -218,7 +205,6 @@ Layout Description <section> <description>SecureBoot Key Transition Partition (16K)</description> <eyeCatch>SBKT</eyeCatch> - <physicalOffset>0x30A4000</physicalOffset> <physicalRegionSize>0x4000</physicalRegionSize> <side>sideless</side> <ecc/> @@ -226,18 +212,16 @@ Layout Description <section> <description>OCC Lid (1.125M)</description> <eyeCatch>OCC</eyeCatch> - <physicalOffset>0x30A8000</physicalOffset> <physicalRegionSize>0x120000</physicalRegionSize> <sha512Version/> <side>sideless</side> <ecc/> </section> <section> - <description>VFRT data for WOF (12MB)</description> + <description>VFRT data for WOF (6MB)</description> <!-- We need 266KB per module sort, going to support 40 tables by default, plus ECC --> <eyeCatch>WOFDATA</eyeCatch> - <physicalOffset>0x31C8000</physicalOffset> <physicalRegionSize>0x600000</physicalRegionSize> <side>sideless</side> <sha512Version/> @@ -246,52 +230,30 @@ Layout Description <section> <description>FIRDATA (12K)</description> <eyeCatch>FIRDATA</eyeCatch> - <physicalOffset>0x37C8000</physicalOffset> <physicalRegionSize>0x3000</physicalRegionSize> <side>sideless</side> <ecc/> </section> <section> - <description>Memory Data (128K)</description> - <eyeCatch>MEMD</eyeCatch> - <physicalOffset>0x37CB000</physicalOffset> - <physicalRegionSize>0x20000</physicalRegionSize> - <side>sideless</side> - <sha512Version/> - <ecc/> - </section> - <section> <description>Secureboot Test Load (12K)</description> <eyeCatch>TESTLOAD</eyeCatch> - <physicalOffset>0x37EB000</physicalOffset> <physicalRegionSize>0x3000</physicalRegionSize> <side>sideless</side> <sha512Version/> <ecc/> </section> <section> - <description>Centaur Hw Ref Image (12K)</description> - <eyeCatch>CENHWIMG</eyeCatch> - <physicalOffset>0x37EE000</physicalOffset> - <physicalRegionSize>0x3000</physicalRegionSize> - <sha512Version/> - <side>sideless</side> - <ecc/> - </section> - <section> <description>Secure Boot (144K)</description> <eyeCatch>SECBOOT</eyeCatch> - <physicalOffset>0x37F1000</physicalOffset> <physicalRegionSize>0x24000</physicalRegionSize> <side>sideless</side> <ecc/> <preserved/> </section> <section> - <description>Open CAPI Memory Buffer (OCMB) Firmware (300K)</description> + <description>Open CAPI Memory Buffer (OCMB) Firmware (1164K)</description> <eyeCatch>OCMBFW</eyeCatch> - <physicalOffset>0x3815000</physicalOffset> - <physicalRegionSize>0x4B000</physicalRegionSize> + <physicalRegionSize>0x123000</physicalRegionSize> <side>sideless</side> <sha512Version/> <readOnly/> @@ -300,18 +262,9 @@ Layout Description <section> <description>HDAT Data (16K)</description> <eyeCatch>HDAT</eyeCatch> - <physicalOffset>0x3860000</physicalOffset> <physicalRegionSize>0x4000</physicalRegionSize> <side>sideless</side> <sha512Version/> <ecc/> </section> - <section> - <description>Eeprom Cache(512K)</description> - <eyeCatch>EECACHE</eyeCatch> - <physicalOffset>0x3864000</physicalOffset> - <physicalRegionSize>0x80000</physicalRegionSize> - <side>sideless</side> - <ecc/> - </section> </pnor> diff --git a/src/build/buildpnor/pnorLayoutFSP.xml b/src/build/buildpnor/pnorLayoutFSP.xml index a842001c3..9569e479f 100644 --- a/src/build/buildpnor/pnorLayoutFSP.xml +++ b/src/build/buildpnor/pnorLayoutFSP.xml @@ -168,10 +168,10 @@ Layout Description - Used when building an FSP driver <ecc/> </section> <section> - <description>Hostboot Runtime Services for Sapphire (6MB)</description> + <description>Hostboot Runtime Services for Sapphire (8MB)</description> <eyeCatch>HBRT</eyeCatch> <physicalOffset>0x162D000</physicalOffset> - <physicalRegionSize>0x600000</physicalRegionSize> + <physicalRegionSize>0x800000</physicalRegionSize> <sha512Version/> <side>sideless</side> <ecc/> @@ -179,7 +179,7 @@ Layout Description - Used when building an FSP driver <section> <description>Hostboot Bootloader (28K)</description> <eyeCatch>HBBL</eyeCatch> - <physicalOffset>0x1C2D000</physicalOffset> + <physicalOffset>0x1E2D000</physicalOffset> <!-- Physical Size includes Header rounded to ECC valid size --> <!-- Max size of actual HBBL content is 20K and 22.5K with ECC --> <physicalRegionSize>0x7000</physicalRegionSize> @@ -188,17 +188,9 @@ Layout Description - Used when building an FSP driver <ecc/> </section> <section> - <description>Global Data (36K)</description> - <eyeCatch>GLOBAL</eyeCatch> - <physicalOffset>0x1C34000</physicalOffset> - <physicalRegionSize>0x9000</physicalRegionSize> - <side>sideless</side> - <ecc/> - </section> - <section> <description>Ref Image Ring Overrides (20K)</description> <eyeCatch>RINGOVD</eyeCatch> - <physicalOffset>0x1C3D000</physicalOffset> + <physicalOffset>0x1E34000</physicalOffset> <physicalRegionSize>0x5000</physicalRegionSize> <side>sideless</side> <ecc/> @@ -206,7 +198,7 @@ Layout Description - Used when building an FSP driver <section> <description>SecureBoot Key Transition Partition (16K)</description> <eyeCatch>SBKT</eyeCatch> - <physicalOffset>0x1C42000</physicalOffset> + <physicalOffset>0x1E39000</physicalOffset> <physicalRegionSize>0x4000</physicalRegionSize> <sha512Version/> <side>sideless</side> @@ -215,7 +207,7 @@ Layout Description - Used when building an FSP driver <section> <description>OCC Lid (1.125M)</description> <eyeCatch>OCC</eyeCatch> - <physicalOffset>0x1C46000</physicalOffset> + <physicalOffset>0x1E3D000</physicalOffset> <physicalRegionSize>0x120000</physicalRegionSize> <sha512Version/> <side>sideless</side> @@ -226,7 +218,7 @@ Layout Description - Used when building an FSP driver <!-- We need 266KB per module sort, going to support 40 tables by default, plus ECC --> <eyeCatch>WOFDATA</eyeCatch> - <physicalOffset>0x1D66000</physicalOffset> + <physicalOffset>0x1F5D000</physicalOffset> <physicalRegionSize>0xC00000</physicalRegionSize> <side>sideless</side> <sha512Version/> @@ -235,7 +227,7 @@ Layout Description - Used when building an FSP driver <section> <description>Memory Data (128K)</description> <eyeCatch>MEMD</eyeCatch> - <physicalOffset>0x2966000</physicalOffset> + <physicalOffset>0x2B5D000</physicalOffset> <physicalRegionSize>0x20000</physicalRegionSize> <side>sideless</side> <sha512Version/> @@ -244,7 +236,7 @@ Layout Description - Used when building an FSP driver <section> <description>Centaur Hw Ref Image (12K)</description> <eyeCatch>CENHWIMG</eyeCatch> - <physicalOffset>0x2986000</physicalOffset> + <physicalOffset>0x2B7D000</physicalOffset> <physicalRegionSize>0x3000</physicalRegionSize> <sha512Version/> <side>sideless</side> @@ -253,7 +245,7 @@ Layout Description - Used when building an FSP driver <section> <description>Secure Boot (144K)</description> <eyeCatch>SECBOOT</eyeCatch> - <physicalOffset>0x2989000</physicalOffset> + <physicalOffset>0x2B80000</physicalOffset> <physicalRegionSize>0x24000</physicalRegionSize> <side>sideless</side> <ecc/> @@ -262,7 +254,7 @@ Layout Description - Used when building an FSP driver <section> <description>Open CAPI Memory Buffer (OCMB) Firmware (300K)</description> <eyeCatch>OCMBFW</eyeCatch> - <physicalOffset>0x29AD000</physicalOffset> + <physicalOffset>0x2BA4000</physicalOffset> <physicalRegionSize>0x4B000</physicalRegionSize> <side>sideless</side> <sha512Version/> diff --git a/src/build/citest/autocitest b/src/build/citest/autocitest index 0cb8d078f..3e29c414f 100755 --- a/src/build/citest/autocitest +++ b/src/build/citest/autocitest @@ -154,8 +154,11 @@ waitkb timestamp=`date +'%H:%M:%S'` echo "$timestamp Starting autosample test..." -# see simics license usage -tail -n 500 /afs/rch/usr4/dlarson/public/stats/lic_usage.txt | grep hindsight +# see simics license usage. +hindsight_license=$(echo "hindsight_usage-"`date +%Y`-`date +%B`".log") +# show last 4 hours. Gives alittle insight to license usage trends. +#This log file is added to every twenty minutes. There are spaces between each line. 4x2x3=24 lines +tail -n 24 /gsa/ausgsa/projects/s/simics_test/license_logs/$hindsight_license # Run set up in current shell echo "run autosimsetup.." @@ -333,10 +336,11 @@ while [ $(($modsstarted)) -lt 1 -o $(($modsstarted)) -ne $(($modscompleted)) ]; sleep 20 ((loopcount++)) # increment loopcount echo "loopcount = $loopcount" - + date +'%H:%M:%S' echo "modscompleted log command" - echo "autosim $NOWIN --simcmd \"print ((system_cmp0.phys_mem).read 0x$mods_completed_addr 0x08)\" 1> $SBXHOME/modscompleted.log 2> /dev/null" - autosim $NOWIN --simcmd "print ((system_cmp0.phys_mem).read 0x$mods_completed_addr 0x08)" 1> $SBXHOME/modscompleted.log 2> /dev/null + echo "autosim $NOWIN --simcmd \"print ((system_cmp0.phys_mem).read 0x$mods_completed_addr 0x08)\" 1> $SBXHOME/modscompleted.log 2> /dev/null" + autosim $NOWIN --simcmd "print ((system_cmp0.phys_mem).read 0x$mods_completed_addr 0x08)" 1> $SBXHOME/modscompleted.log 2> /dev/null + date +'%H:%M:%S' echo echo "modscompleted command" @@ -344,9 +348,11 @@ while [ $(($modsstarted)) -lt 1 -o $(($modsstarted)) -ne $(($modscompleted)) ]; modscompleted=`cat $SBXHOME/modscompleted.log | awk '/0x/ {print strtonum($1)}'` echo + date +'%H:%M:%S' echo "modsstarted log command" - echo "autosim $NOWIN --simcmd \"print ((system_cmp0.phys_mem).read 0x$mods_started_addr 0x08)\" 1> $SBXHOME/modsstarted.log 2> /dev/null" - autosim $NOWIN --simcmd "print ((system_cmp0.phys_mem).read 0x$mods_started_addr 0x08)" 1> $SBXHOME/modsstarted.log 2> /dev/null + echo "autosim $NOWIN --simcmd \"print ((system_cmp0.phys_mem).read 0x$mods_started_addr 0x08)\" 1> $SBXHOME/modsstarted.log 2> /dev/null" + autosim $NOWIN --simcmd "print ((system_cmp0.phys_mem).read 0x$mods_started_addr 0x08)" 1> $SBXHOME/modsstarted.log 2> /dev/null + date +'%H:%M:%S' echo echo "modsstarted command" @@ -356,18 +362,35 @@ while [ $(($modsstarted)) -lt 1 -o $(($modsstarted)) -ne $(($modscompleted)) ]; echo "ModulesStarted:ModulesCompleted => $modsstarted:$modscompleted" - # @TODO RTC:149210 temporary fix for autosim hangs on real code errors. For some reason - # when we hit an actual bug and simics halts, the autosim commands hang - # causing this loop to take >8 hours. - if [ -z $modsstarted ] && [ -z $modscompleted ]; then - echo "ERROR: autosim hanging on real code errors, temporarily catching early" - echo "See archived hbTracMerg for more info" - exit 1 + # For code coverage, sometimes simics takes a while to respond as it dumps data. + # Allow it to continue if this condition is seen. + if [[ -z "${HOSTBOOT_PROFILE}" ]]; then + # @TODO RTC:149210 temporary fix for autosim hangs on real code errors. For some reason + # when we hit an actual bug and simics halts, the autosim commands hang + # causing this loop to take >8 hours. + if [ -z $modsstarted ] && [ -z $modscompleted ]; then + echo "ERROR: autosim hanging on real code errors, temporarily catching early" + echo "See archived hbTracMerg for more info" + exit 1 + fi + fi + + if [[ -z "${HOSTBOOT_PROFILE}" ]]; then + if [[ "$CHIP" == "AXONE" ]]; then + # 75 minutes for axone + loop_timeout=225 + else + # 50 minutes by default + loop_timeout=150 + fi + else + # Increase timeout to 166 minutes for code coverage + loop_timeout=500 fi - if [ "$loopcount" -ge 150 ]; then + if [ "$loopcount" -ge "$loop_timeout" ]; then timestamp=`date +'%H:%M:%S'` - echo "$timestamp ERROR: timed out after 50 minutes waiting for until test completion" + echo "$timestamp ERROR: timed out waiting for until test completion" autosim $NOWIN --simcmd "hb-Ps with-backtrace" timeout=$(($modsstarted - $modscompleted)) break @@ -467,6 +490,15 @@ if [ $? -ne 0 ] ; then echo "ERROR: Unable to run $?" fi +if [[ ! -z "${HOSTBOOT_PROFILE}" ]]; then + # After simics test are complete, dump data. + echo "====> hb-Gcov..." + autosim $NOWIN --simcmd "hb-Gcov" --timeout 300 + if [ $? -ne 0 ] ; then + echo "ERROR: Unable to run $?" + fi +fi + ######################################################## ## done. Stop the simulation ######################################################## diff --git a/src/build/citest/build-script b/src/build/citest/build-script index 7510d76c9..7198ed5b2 100755 --- a/src/build/citest/build-script +++ b/src/build/citest/build-script @@ -24,10 +24,62 @@ # # IBM_PROLOG_END_TAG +usage=" +$(basename "$0") [-h|--help] [--skipCxxTests] [--skipCopyrightCheck] + +Description: + The original use of this script was for the Hostboot standalone CI job, + so by default it will run a copyright check, then compile hostboot and + populate an ODE sandbox and run the CXX test suite in standalone simics. + + Flags have been added to skip the copyright checks and the cxx tests + for cases where we only want to get a populated sandbox. + +Expectations: + This script is expected to be ran from the top level of the + hostboot directory. (ie src/build/citest/build-script <params>). It will + look at env variables PROJECT_ROOT, WORKSPACE, SANDBOXNAME, SANDBOXROOT, + CHIP, PNOR, CONFIG_FILE, and HOSTBOOT_PROFILE. + +Optional Flags: + -h|--help shows this help text + --skipCxxTests skips the execution of the cxx test suite + --skipCopyrightCheck skips the execution of the copyright check +" + if [ -z $PROJECT_ROOT ]; then source "$WORKSPACE/env.bash" fi +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + --skipCopyrightCheck) + SKIP_CR_CHECK=1 + shift # past argument + ;; + --skipCxxTests) + SKIP_CXX_TESTS=1 + shift # past argument + ;; + -h|--help) + echo "$usage" + exit 0 + ;; + *) + echo " +!!! Invalid argument \"$1\" passed into ${0} !!!!" + echo "$usage" + exit 22 + ;; +esac +done + +echo "SKIP_CR_CHECK = ${SKIP_CR_CHECK}" +echo "SKIP_CXX_TESTS = ${SKIP_CXX_TESTS}" + source "$PROJECT_ROOT/src/build/citest/setup-env" echo "#--------------------------------" echo "SANDBOXROOT=$SANDBOXROOT" @@ -41,32 +93,49 @@ echo "#--------------------------------" # Force simics into Secure Mode export SECURITY_HW_POLICY="1" -# Check copyright. -check-copyright > copyright.log 2>&1 -if [ $? -eq 0 ]; then - echo "----Copyright check succeeded." - cat copyright.log -else - echo "----Copyright check failed." - cat copyright.log - exit -1 +if [ -z "$SKIP_CR_CHECK" ]; then + # Check copyright. + check-copyright > copyright.log 2>&1 + if [ $? -eq 0 ]; then + echo "----Copyright check succeeded." + cat copyright.log + else + echo "----Copyright check failed." + cat copyright.log + exit -1 + fi fi - # Create simics sandbox. create-sandbox > create-sandbox.log 2>&1 & CREATESANDBOX_PID=$! -my_date=$(date) -# Build Hostboot. +# normal build is empty quotes +build_opt="" +# code coverage +if [[ ! -z "${HOSTBOOT_PROFILE}" ]]; then + build_opt="gcov" +# static analysis +elif [[ ! -z "${HOSTBOOT_CPPCHECK}" ]]; then + build_opt="cppcheck" + COMPILE_ONLY=1 +fi +# Build Hostboot +start_time=$(date) echo "#--------------------------------" -printf "\n\n$(date): STARTED running \"make -j32\"\n\n" +printf "\n\n$(date): STARTED running \"make -j32 $build_opt\"\n\n" echo "#--------------------------------" -make -j32 || exit -1 +make -j32 $build_opt || exit -1 +make_rc=$? echo "#--------------------------------" -printf "\n\nrc=$?: $(date): FINISHED running (\"make -j32\" was started at $my_date)\n\n" +printf "\n\nrc=$make_rc: $(date): FINISHED running (\"make -j32 $build_opt\" was started at $start_time)\n\n" echo "#--------------------------------" +if [[ ! -z "${COMPILE_ONLY}" ]]; then + echo "Compile only" + exit $make_rc +fi + # Check sandbox create completion. wait $CREATESANDBOX_PID if [ $? -eq 0 ]; then @@ -79,48 +148,62 @@ else fi # Add Hostboot files to simics sandbox. -my_date=$(date) +start_time=$(date) echo "#--------------------------------" -printf "\n\n$(date): STARTED running populate-sandbox....\n\n" +printf "\n\n$start_time: STARTED running populate-sandbox....\n\n" echo "#--------------------------------" populate-sandbox || exit -1 echo "#--------------------------------" -printf "\n\nrc=$?: $(date): FINISHED running (\"populate-sandbox\" was started at $my_date)\n\n" +printf "\n\nrc=$?: $(date): FINISHED running (\"populate-sandbox\" was started at $start_time)\n\n" echo "#--------------------------------" -if [ "$CHIP" == "FSPBUILD" ]; -then - # Start errl parser building. - my_date=$(date) - printf "\n\n$(date): STARTED running \"build-errl-parsers\"\n\n" - build-errl-parsers > errl-parsers.log 2>&1 & - ERRLPARSERS_PID=$! - - # Check errl parser completion. - wait $ERRLPARSERS_PID - if [ $? -ne 0 ]; then - echo "----Error parsers failed." - cat errl-parsers.log - exit -1 - else - printf "\n\n$(date): FINISHED running (\"build-errl-parsers\" was started at $my_date)\n\n" - fi - - -else - printf "2) CHIP=$CHIP" - echo "CHIP3=$CHIP" - - - # Start CxxTest Simics execution. - my_date=$(date) - echo "#--------------------------------" - printf "\n\n$(date): STARTED running cxxtest-start.sh....\n\n" - echo "#--------------------------------" - cxxtest-start.sh || exit -1 - echo "#--------------------------------" - printf "\n\nrc=$?: $(date): FINISHED running (\"cxxtest-start.sh\" was started at $my_date)\n\n" - echo "#--------------------------------" +if [ -z "$SKIP_CXX_TESTS" ]; then + + if [ "$CHIP" == "FSPBUILD" ]; then + # Start errl parser building. + start_time=$(date) + printf "\n\n$start_time: STARTED running \"build-errl-parsers\"\n\n" + build-errl-parsers > errl-parsers.log 2>&1 & + ERRLPARSERS_PID=$! + + # Check errl parser completion. + wait $ERRLPARSERS_PID + if [ $? -ne 0 ]; then + echo "----Error parsers failed." + cat errl-parsers.log + exit -1 + else + printf "\n\n$(date): FINISHED running (\"build-errl-parsers\" was started at $start_time)\n\n" + fi + + + else + printf "2) CHIP=$CHIP" + echo "CHIP3=$CHIP" + + # Start CxxTest Simics execution. + start_time=$(date) + echo "#--------------------------------" + printf "\n\n$start_time: STARTED running cxxtest-start.sh....\n\n" + echo "#--------------------------------" + cxxtest-start.sh || exit -1 + echo "#--------------------------------" + printf "\n\nrc=$?: $(date): FINISHED running (\"cxxtest-start.sh\" was started at $start_time)\n\n" + echo "#--------------------------------" + + fi fi +if [[ ! -z "${HOSTBOOT_PROFILE}" ]]; then + # Generate the code coverage report. Located obj/gcov_report + # Jenkins will artifact and can display html report + start_time=$(date) + echo "#--------------------------------" + printf "\n\n$start_time: STARTED running \"make lcov\"\n\n" + echo "#--------------------------------" + make lcov || exit -1 + echo "#--------------------------------" + printf "\n\nrc=$?: $(date): FINISHED running (\"make lcov\" was started at $start_time)\n\n" + echo "#--------------------------------" +fi diff --git a/src/build/citest/create-sandbox b/src/build/citest/create-sandbox index 0018e4422..b07158f02 100755 --- a/src/build/citest/create-sandbox +++ b/src/build/citest/create-sandbox @@ -78,11 +78,15 @@ if [ "$MACHINE" != "NIMBUS" ] && [ "$MACHINE" != "CUMULUS" ] && \ [ "$MACHINE" != "CUMULUS_CDIMM" ] && [ "$MACHINE" != "FSPBUILD" ]; then SIMICS_LEVEL=`cat ${PROJECT_ROOT}/src/build/citest/etc/simbuild` + EECACHE_PREBUILT=`cat ${PROJECT_ROOT}/src/build/citest/etc/eecache_prebuilt` echo "mkdir -p ${SANDBOXBASE}/simics" execute_in_sandbox "mkdir -p ${SANDBOXBASE}/simics" "ppc" echo "tar ${SIMICS_LEVEL} -C ${SANDBOXBASE}/simics/" execute_in_sandbox "tar -xf ${SIMICS_LEVEL} -C ${SANDBOXBASE}/simics/" "ppc" + echo "cd ${SANDBOXBASE}/simics/ && ./INSTALL.sh" execute_in_sandbox "cd ${SANDBOXBASE}/simics/ && ./INSTALL.sh" "ppc" + echo "cp ${EECACHE_PREBUILT} ${SANDBOXBASE}/simics/eecache_prebuilt.bin.ecc" + execute_in_sandbox "cp ${EECACHE_PREBUILT} ${SANDBOXBASE}/simics/eecache_prebuilt.bin.ecc" "ppc" else execute_in_sandbox "start_simics -no_start -machine $MACHINE -batch_mode" \ "ppc" || exit -1 diff --git a/src/build/citest/cxxtest-start.sh b/src/build/citest/cxxtest-start.sh index dcb25c201..b34c744d8 100755 --- a/src/build/citest/cxxtest-start.sh +++ b/src/build/citest/cxxtest-start.sh @@ -38,7 +38,7 @@ if [ "$MACHINE" != "NIMBUS" ] && [ "$MACHINE" != "CUMULUS" ] && \ [ "$MACHINE" != "CUMULUS_CDIMM" ] && [ "$MACHINE" != "FSPBUILD" ]; then export PATH=$PATH:$SANDBOXBASE/simics/ - export START_SIMICS_CMD="runsim -m $MACHINE hb_script_to_run=$SANDBOXBASE/obj/ppc/simu/scripts/hbfw/startup.simics pnor_img=$SANDBOXBASE/obj/ppc/hbfw/img/axone.pnor sbe_seeprom_img=$SANDBOXBASE/images/ppc/lab/flash/sbe_seeprom_p9a_10.bin.ecc num_procs=1 vpd_proc=vpd/images/99a8c3fe4e5c74798f5bd4212f3d9a2a" + export START_SIMICS_CMD="runsim -m $MACHINE hb_script_to_run=$SANDBOXBASE/obj/ppc/simu/scripts/hbfw/startup.simics pnor_img=$SANDBOXBASE/obj/ppc/hbfw/img/axone.pnor sbe_seeprom_img=$SANDBOXBASE/images/ppc/lab/flash/sbe_seeprom_p9a_10.bin.ecc num_procs=2 enable_lpc_console=TRUE" fi # Front end to autocitest - script to execute unit tests under simics. diff --git a/src/build/citest/etc/bbuild b/src/build/citest/etc/bbuild index 873e0f4bd..a6ac16e07 100644 --- a/src/build/citest/etc/bbuild +++ b/src/build/citest/etc/bbuild @@ -1 +1 @@ -/esw/fips930/Builds/b0121a_1904.930 +/esw/fips940/Builds/b0516a_1921.940 diff --git a/src/build/citest/etc/cppcheck b/src/build/citest/etc/cppcheck new file mode 100644 index 000000000..f92ac3604 --- /dev/null +++ b/src/build/citest/etc/cppcheck @@ -0,0 +1,27 @@ +#!/bin/bash +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/citest/etc/cppcheck $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2019 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +export CPPCHECK_COMMIT="4939e0c3086151033bd491bb2df72f7728a4c037" diff --git a/src/build/citest/etc/eecache_prebuilt b/src/build/citest/etc/eecache_prebuilt new file mode 100644 index 000000000..e7ff59666 --- /dev/null +++ b/src/build/citest/etc/eecache_prebuilt @@ -0,0 +1 @@ +/gsa/ausgsa/projects/h/hostboot/eecache_prebuilt/10_02_19_eecache_prebuilt.bin.ecc diff --git a/src/build/citest/etc/simbuild b/src/build/citest/etc/simbuild index 31d4a6f2e..ba464d4c5 100644 --- a/src/build/citest/etc/simbuild +++ b/src/build/citest/etc/simbuild @@ -1 +1 @@ -/gsa/ausgsa/projects/h/hostboot/simbuild/04_08_19_973eb4_simics.tar.gz +/gsa/ausgsa/projects/h/hostboot/simbuild/axone/2019-11-11_f0c353_simics.tar.gz diff --git a/src/build/citest/etc/workarounds.postsimsetup b/src/build/citest/etc/workarounds.postsimsetup index d904f6c3b..26cc2bd03 100755 --- a/src/build/citest/etc/workarounds.postsimsetup +++ b/src/build/citest/etc/workarounds.postsimsetup @@ -6,7 +6,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2011,2019 +# Contributors Listed Below - COPYRIGHT 2011,2020 # [+] International Business Machines Corp. # # @@ -39,5 +39,8 @@ mkdir -p $sb/simu/configs/ grep -v PROC_EC $BACKING_BUILD/src/simu/configs/P9_NIMBUS.config > $sb/simu/configs/P9_NIMBUS.config echo "SETENV PROC_EC 22" >> $sb/simu/configs/P9_NIMBUS.config +# TODO RTC:215621 +# remove when simics gets dimmspd.dat updated +mkdir -p $sb/../simics/import/vpd/ +cp /gsa/ausgsa/projects/h/hostboot/.binary_cache/data/f6f5b778c406883e1b392b311350a1e83583e15a $sb/../simics/import/vpd/dimmspd.dat -########################################################################## diff --git a/src/build/citest/setup-env b/src/build/citest/setup-env index 21133ef67..e82032d8a 100755 --- a/src/build/citest/setup-env +++ b/src/build/citest/setup-env @@ -26,6 +26,7 @@ export CITESTPATH=${PROJECT_ROOT}/src/build/citest export PATH=${CITESTPATH}:${PATH} +export CXXPATH=/opt/rh/devtoolset-3/root/usr/bin # Determine backing build. export BACKING_BUILD=`cat ${CITESTPATH}/etc/bbuild` diff --git a/src/build/configs/simics_axone.config b/src/build/configs/simics_axone.config index 3d044edcc..c3f33e583 100644 --- a/src/build/configs/simics_axone.config +++ b/src/build/configs/simics_axone.config @@ -1,35 +1,27 @@ -# Force DJVPD read/write to use EEPROM layer instead of VPD cache -set DJVPD_READ_FROM_HW -set DJVPD_WRITE_TO_HW -unset DJVPD_READ_FROM_PNOR -unset DJVPD_WRITE_TO_PNOR - -# Force MEMVPD read/write to PNOR ( No actual hardware ) -set MEMVPD_READ_FROM_PNOR -set MEMVPD_WRITE_TO_PNOR -unset MEMVPD_READ_FROM_HW -unset MEMVPD_WRITE_TO_HW - -# Force MVPD read/write to use EEPROM layer instead of VPD cache -# (not working because shoddy MVPD currently) -#set MVPD_READ_FROM_HW -#set MVPD_WRITE_TO_HW -set MVPD_READ_FROM_PNOR -set MVPD_WRITE_TO_PNOR +# Have Planar VPD +set HAVE_PVPD + +# Don't have any memory buffer VPD +unset HAVE_MBVPD #set to run cxx testcases during boot unset EARLY_TESTCASES -#skip enabling checkstop analysis until OCC is ready in simics -unset IPLTIME_CHECKSTOP_ANALYSIS +#Enable checkstop analysis for IPL failures +set IPLTIME_CHECKSTOP_ANALYSIS #enable EEPROM caching set SUPPORT_EEPROM_CACHING -#Try to keep a list of things this does -# - skipping setting voltages in istep 8.12, nothing on other side of AVSbus -# in simics currently. +# Allows us to put in workarounds specifically for Axone bringup set AXONE_BRING_UP # Set this to pull in Axone on code (such as P9A/EXP MSS code) -set AXONE
\ No newline at end of file +set AXONE + +# Enable Console +set CONSOLE +set CONSOLE_OUTPUT_ERRORDISPLAY + +# OMIs were introduced in Axone and will be in P10 also +set SUPPORT_OMI diff --git a/src/build/debug/Hostboot/BlTrace.pm b/src/build/debug/Hostboot/BlTrace.pm index 5fd8baf18..9d9dc9988 100644 --- a/src/build/debug/Hostboot/BlTrace.pm +++ b/src/build/debug/Hostboot/BlTrace.pm @@ -83,6 +83,7 @@ my %traceText = ( "FA" => "PNOR Access getHBBSection findTOC no HBB section", "FB" => "main verifyBaseImage failed", "FC" => "main verifyBaseImage secure rom invalid", + "FD" => "PNOR Access findTOC handleMMIO LPC ERR returned", ); sub formatTrace diff --git a/src/build/debug/Hostboot/Dump.pm b/src/build/debug/Hostboot/Dump.pm index 705638aa2..90b445df9 100755 --- a/src/build/debug/Hostboot/Dump.pm +++ b/src/build/debug/Hostboot/Dump.pm @@ -6,7 +6,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2018 +# Contributors Listed Below - COPYRIGHT 2012,2019 # [+] International Business Machines Corp. # # @@ -106,6 +106,13 @@ sub main $debug = 1; } + # Parse 'quiet' option. + my $quiet = 0; + if (defined $args->{"quiet"}) + { + $quiet = 1; + } + # Check for a different output directory my $outdir = "./"; if (defined $args->{"outdir"}) @@ -128,7 +135,7 @@ sub main open( OUTFH, ">$hbDumpFile" ) or die "can't open $hbDumpFile: $!\n"; binmode(OUTFH); - ::userDisplay "Using HRMOR=". ::getHRMOR() . "\n"; + ::userDisplay "Using HRMOR=". sprintf("0x%X",::getHRMOR()) . "\n"; # Read memory regions and output to file. foreach my $state (@{$memory_states{int $memstate}}) @@ -152,7 +159,7 @@ sub main $curlength = $length_remaining; } - ::userDisplay (sprintf "...%x@%x\n", $curlength, $curstart); + ::userDisplay (sprintf "...%x@%x\n", $curlength, $curstart) if !$quiet; my $data = ::readData($curstart, $curlength); seek OUTFH, $curstart, SEEK_SET; @@ -187,6 +194,7 @@ sub helpInfo options => { "outdir=<path>" => ["Output directory for dump file"], "debug" => ["More debug output."], + "quiet" => ["Less output."], }, ); } diff --git a/src/build/debug/Hostboot/Gcov.pm b/src/build/debug/Hostboot/Gcov.pm index 84df2f9f9..48e71d66b 100755 --- a/src/build/debug/Hostboot/Gcov.pm +++ b/src/build/debug/Hostboot/Gcov.pm @@ -1,4 +1,3 @@ -#!/usr/bin/perl # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # @@ -6,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2015 +# Contributors Listed Below - COPYRIGHT 2012,2019 # [+] International Business Machines Corp. # # @@ -23,15 +22,18 @@ # permissions and limitations under the License. # # IBM_PROLOG_END_TAG +#!/usr/bin/perl use strict; +use warnings; use File::Path; use File::Basename; +use IO::Handle; package Hostboot::Gcov; use Hostboot::_DebugFrameworkVMM qw(NotFound NotPresent getPhysicalAddr); use Exporter; -our @EXPORT_OK = ('main'); +our @EXPORT_OK = ('init', 'main', 'parseGcovInfo'); # NOTE: # @@ -50,26 +52,37 @@ our @EXPORT_OK = ('main'); use constant GCOV_EXTENDED_IMAGE_ADDRESS => (1024 * 1024 * 1024); use constant GCOV_INFO_HEAD_SYMBOLNAME => "_gcov_info_head"; +use constant GCOV_INFO_MAGIC_SYMBOLNAME => "_gcov_info_magic"; +use constant GCOV_MAGIC_IDENTIFIER => 0xbeefb055; -use constant GCOV_INFO_VERSION_OFFSET => 0; -use constant GCOV_INFO_NEXT_OFFSET => GCOV_INFO_VERSION_OFFSET + 8; -use constant GCOV_INFO_TIMESTAMP_OFFSET => GCOV_INFO_NEXT_OFFSET + 8; -use constant GCOV_INFO_FILENAME_OFFSET => GCOV_INFO_TIMESTAMP_OFFSET + 8; -use constant GCOV_INFO_NFUNCTIONS_OFFSET => GCOV_INFO_FILENAME_OFFSET + 8; -use constant GCOV_INFO_FUNCTIONS_OFFSET => GCOV_INFO_NFUNCTIONS_OFFSET + 8; -use constant GCOV_INFO_CTRMASK_OFFSET => GCOV_INFO_FUNCTIONS_OFFSET + 8; -use constant GCOV_INFO_COUNTS_OFFSET => GCOV_INFO_CTRMASK_OFFSET + 8; - -use constant GCOV_FNINFO_IDENT_OFFSET => 0; -use constant GCOV_FNINFO_CHECKSUM_OFFSET => GCOV_FNINFO_IDENT_OFFSET + 4; -use constant GCOV_FNINFO_NCTRS_OFFSET => GCOV_FNINFO_CHECKSUM_OFFSET + 4; +use constant GCOV_COUNTERS_492 => 9; +use constant SIZEOF_PTR => 8; +use constant SIZEOF_UINT64 => 8; -use constant GCOV_CTRINFO_COUNT_OFFSET => 0; -use constant GCOV_CTRINFO_VALUEPTR_OFFSET => GCOV_CTRINFO_COUNT_OFFSET + 8; - -use constant GCOV_GCDA_MAGIC_VALUE => 0x67636461; use constant GCOV_FUNCTION_TAG => 0x01000000; use constant GCOV_COUNTERS_TAG => 0x01a10000; +use constant GCOV_PROGRAM_SUMMARY_TAG => 0xa3000000; + +use constant GCOV_GCDA_MAGIC_VALUE => 0x67636461; + +# See gcov.h for the structs (gcov_info, gcov_fn_info) from which +# these offsets derive + +use constant GCOV_INFO_VERSION_OFFSET_492 => 0; +use constant GCOV_INFO_NEXT_OFFSET_492 => 8; +use constant GCOV_INFO_TIMESTAMP_OFFSET_492 => 16; +use constant GCOV_INFO_FILENAME_OFFSET_492 => 24; +use constant GCOV_INFO_MERGE_OFFSET_492 => 32; +use constant GCOV_INFO_N_FUNCTIONS_OFFSET_492 => 32 + (9 * 8); +use constant GCOV_INFO_FUNCTIONS_OFFSET_492 => GCOV_INFO_N_FUNCTIONS_OFFSET_492 + 8; + +use constant GCOV_FN_INFO_IDENT_OFFSET_492 => 8; +use constant GCOV_FN_INFO_LINENO_CHECKSUM_OFFSET_492 => 12; +use constant GCOV_FN_INFO_CFG_CHECKSUM_OFFSET_492 => 16; +use constant GCOV_FN_INFO_CTR_INFO_OFFSET_492 => 24; + +use constant GCOV_CTR_INFO_NUM_OFFSET_492 => 0; +use constant GCOV_CTR_INFO_VALUES_OFFSET_492 => 8; # In memory format: # GCC creates a 'gcov_info' structure for each .o file. The info @@ -134,20 +147,43 @@ use constant GCOV_COUNTERS_TAG => 0x01a10000; # uint64_ts, containing instrumented counts, for the preceeding function. # Global of where we want the output to go. -our $output_dir; our $debug_mode; +our $hbicore_extended_bin_file; +our $hbicore_extended_bin_file_size; BEGIN { $debug_mode = 0; - $output_dir = ""; } -return 1; + +sub init +{ + # TODO: We need to figure out how to handle reading data from + # HBB/HBRT for when those are instrumented. One hurdle is being + # able to determine from an address what module it belongs to, + # because HBB/HBI/HBRT are not necessarily laid out in memory as + # they are in PNOR or anywhere else. + + my $hbicore_extended_bin_fname = "$ENV{SANDBOXROOT}/$ENV{SANDBOXNAME}/src/hbfw/img/hostboot_extended.bin"; + + userDebug("Opening " . $hbicore_extended_bin_fname . " for HBI\n"); + + unless (open($hbicore_extended_bin_file, "< $hbicore_extended_bin_fname")) { + ::userDisplay "Failed to open $hbicore_extended_bin_fname, exiting\n"; + return 0; + } + + binmode($hbicore_extended_bin_file); + + $hbicore_extended_bin_file_size = -s $hbicore_extended_bin_fname; + + return 1; +} sub main { - # Pick a new output directory based on the time. - $output_dir = sprintf "gcov.output.%d/", time; - File::Path::mkpath($output_dir); + if (!init()) { + return; + } # Find all the hostboot modules. my @modules = getModules(); @@ -160,7 +196,10 @@ sub main my $pwd = `pwd`; chomp $pwd; - ::userDisplay "GCOV output written to: $pwd/$output_dir\n"; + + close $hbicore_extended_bin_file or die; + + ::userDisplay("GCOV info extraction complete.\n"); } sub parseModuleGcov @@ -168,8 +207,23 @@ sub parseModuleGcov my $module = shift; ::userDisplay "Extracting GCOV info for ".$module."\n"; + # Search for magic symbol. + my ($gcov_magic, $unused) = + ::findSymbolAddress($module.GCOV_INFO_MAGIC_SYMBOLNAME); + + if (!defined($gcov_magic)) + { + $gcov_magic = 0; + } + + if ($gcov_magic == 0 || read32($gcov_magic, 1) != GCOV_MAGIC_IDENTIFIER) + { + ::userDisplay "\tgcov_magic at address " . (sprintf "0x%x", $gcov_magic) . " is incorrect. Skipped.\n"; + return; + } + # Search for gcov_info chain symbol. - my ($gcov_info, $unused) = + my ($gcov_info, $unused2) = ::findSymbolAddress($module.GCOV_INFO_HEAD_SYMBOLNAME); userDebug("\tFound info at 0x" . (sprintf "%x", $gcov_info) . "\n"); @@ -181,7 +235,7 @@ sub parseModuleGcov if (($gcov_info eq NotFound) || ($gcov_info eq NotPresent)) { - ::userDisplay "\tModule data is not present.\n"; + ::userDisplay "\tModule data is not present, module might have been unloaded, skipping.\n"; return; } } @@ -189,7 +243,7 @@ sub parseModuleGcov # Check that we found the gcov_info chain. if ($gcov_info == 0) { - ::userDisplay "\tUnable to find gcov_info chain. Skipped.\n"; + ::userDisplay "\tUnable to find gcov_info chain, module might hvae been unloaded. Skipping.\n"; return; } @@ -202,39 +256,44 @@ sub parseGcovInfo my $info_ptr = shift; return if (0 eq $info_ptr); - my $filename = readStr(read64($info_ptr + GCOV_INFO_FILENAME_OFFSET)); - userDebug("\tFile = ".$filename."\n"); + userDebug("\tReading filename pointer from offset " . (sprintf "0x%x", ($info_ptr + GCOV_INFO_FILENAME_OFFSET_492)) . "\n"); - my $version = read32($info_ptr + GCOV_INFO_VERSION_OFFSET); - my $stamp = read32($info_ptr + GCOV_INFO_TIMESTAMP_OFFSET); + my $filename_addr = read64($info_ptr + GCOV_INFO_FILENAME_OFFSET_492); - my $func_count = read32($info_ptr + GCOV_INFO_NFUNCTIONS_OFFSET); - userDebug("\tFunction Count = ".$func_count."\n"); + userDebug("\tReading filename from offset " . (sprintf "0x%x", $filename_addr) . "\n"); - my $funcs = read64($info_ptr + GCOV_INFO_FUNCTIONS_OFFSET); - userDebug("\tFunc Address = ".(sprintf "%x", $funcs)."\n"); + my $filename = readStr($filename_addr); - my $ctrmask = read32($info_ptr + GCOV_INFO_CTRMASK_OFFSET); - if ($ctrmask % 2) # Check that COUNTER_ARCS is turned on. - { - # COUNTER_ARCS is on. Create file, find arc-values array, - # parse functions. + if ($filename) { + ::userDisplay("\tFile = ".$filename."\n"); - my $fd = createGcovFile($filename, $version, $stamp); + my $version = read32($info_ptr + GCOV_INFO_VERSION_OFFSET_492); + my $stamp = read32($info_ptr + GCOV_INFO_TIMESTAMP_OFFSET_492); - my $arcs_ptr = read64($info_ptr + GCOV_INFO_COUNTS_OFFSET + - GCOV_CTRINFO_VALUEPTR_OFFSET); - parseGcovFuncs($fd, $funcs, $func_count, $ctrmask, $arcs_ptr); + my $func_count = read32($info_ptr + GCOV_INFO_N_FUNCTIONS_OFFSET_492); + userDebug("\tFunction Count = ".$func_count."\n"); - close $fd; - } - else - { - userDebug("COUNTER_ARCS is missing!\n"); + my $funcs = read64($info_ptr + GCOV_INFO_FUNCTIONS_OFFSET_492, 1); + + if ($funcs ne NotFound && $funcs ne NotPresent) { + userDebug("\tFunc Address = ".(sprintf "0x%x", $funcs)."\n"); + + if ($version ne NotFound && $stamp ne NotFound && $func_count ne NotFound) { + my $fd = createGcovFile($filename, $version, $stamp); + + parseGcovFuncs($fd, $funcs, $func_count); + + close $fd or die $!; + } + } else { + userDebug("\tFunc Address is NULL, skipping\n"); + } + } else { + userDebug("\tCannot read filename, skipping\n"); } # Look for next .o in gcov_info chain, parse. - my $next = read64($info_ptr + GCOV_INFO_NEXT_OFFSET); + my $next = read64($info_ptr + GCOV_INFO_NEXT_OFFSET_492); parseGcovInfo($next); } @@ -243,62 +302,95 @@ sub parseGcovFuncs my $fd = shift; my $func_ptr = shift; my $func_count = shift; - my $mask = shift; - my $val_ptr = shift; - my $fn_offset = 0; + my $GCOV_COUNTERS_SUMMABLE_492 = 1; - # Need to calculate the number of counters based on the bits on in - # the 'mask'. This is used to determine the size of the function - # descriptor object. - my $counters = 0; - { - my $_mask = $mask; + print $fd pack('l', GCOV_PROGRAM_SUMMARY_TAG); # data.program.header.tag - while (0 != $_mask) - { - $counters++; - $_mask = ($_mask >> 1); - } - } + # for each GCOV_COUNTERS_SUMMABLE we have ten int32 (num, runs, and bitvector{8}) + # plus three int64 (sum, max, sum_max) i.e. 10 + 3*2 + # data.unit.header.length is the number of int32's we have following. + print $fd pack('l', 1 + $GCOV_COUNTERS_SUMMABLE_492 * (10 + 3 * 2)); # data.unit.header.length; - userDebug("\tCounters = ".$counters."\n"); + print $fd pack('l', 0); # data.summary:object.checksum (must be 0 according to docs) - # Round up the counter count to the nearest two for alignment of the - # function descriptor object. - if ($counters % 2) - { - $counters++; - } - my $func_size = GCOV_FNINFO_CHECKSUM_OFFSET + 4 * $counters; + for (my $i = 0; $i < $GCOV_COUNTERS_SUMMABLE_492; $i++) { + print $fd pack('l', 0); # data.summary:object.count-summary.num + print $fd pack('l', 0); # data.summary:object.count-summary.runs + print $fd pack('l', 0); # data.summary:object.count-summary.sum@lo + print $fd pack('l', 0); # data.summary:object.count-summary.sum@hi + print $fd pack('l', 0); # data.summary:object.count-summary.max@lo + print $fd pack('l', 0); # data.summary:object.count-summary.max@hi + print $fd pack('l', 0); # data.summary:object.count-summary.sum_max@lo + print $fd pack('l', 0); # data.summary:object.count-summary.sum_max@hi - userDebug("\tFunction size = ".$func_size."\n"); + print $fd pack('l8', (0) x 8); # data.summary:object.count-summary.histogram.bitvector{8} + } # Iterate through the functions and parse. for(my $function = 0; $function < $func_count; $function++) { - my $func_off = ($func_ptr + $func_size * $function); - my $ident = read32($func_off + GCOV_FNINFO_IDENT_OFFSET); - my $chksum = read32($func_off + GCOV_FNINFO_CHECKSUM_OFFSET); + userDebug("\tFunction $function of $func_count\n"); + + my $fn_info_ptr = read64($func_ptr + SIZEOF_PTR*$function, 1); + + if (($fn_info_ptr eq NotFound) || ($fn_info_ptr eq NotPresent)) + { + userDebug("\tCannot read function info pointer, skipping\n"); + next; + } + + userDebug("\tfn_info_ptr = " . (sprintf "%x", $fn_info_ptr) . "\n"); + + my $ident = read32($fn_info_ptr + GCOV_FN_INFO_IDENT_OFFSET_492, 1); + my $lineno_chksum = read32($fn_info_ptr + GCOV_FN_INFO_LINENO_CHECKSUM_OFFSET_492, 1); + my $cfg_chksum = read32($fn_info_ptr + GCOV_FN_INFO_CFG_CHECKSUM_OFFSET_492, 1); + my $ctr_info_ptr = $fn_info_ptr + GCOV_FN_INFO_CTR_INFO_OFFSET_492; + + if ($ident eq NotFound + || $lineno_chksum eq NotFound + || $cfg_chksum eq NotFound) + { + userDebug("Skipping because fn_info structure members are not readable\n"); + next; + } + + my $num_ctrs = read32($ctr_info_ptr + GCOV_CTR_INFO_NUM_OFFSET_492, 1); + my $ctrs_ptr = read64($ctr_info_ptr + GCOV_CTR_INFO_VALUES_OFFSET_492, 1); + + if ($ctrs_ptr eq NotFound || $num_ctrs eq NotFound) + { + userDebug("Skipping because counters length isn't mapped\n"); + next; + } - userDebug("Ident = ".(sprintf "%x", $ident)."\n"); - userDebug("Chksum = ".(sprintf "%x", $chksum)."\n"); + my $counters = readData($ctrs_ptr, SIZEOF_UINT64 * $num_ctrs); + + userDebug("Ident = ".(sprintf "0x%x", $ident)."\n"); + userDebug("lineno Chksum = ".(sprintf "0x%x", $lineno_chksum)."\n"); + userDebug("cfg Chksum = ".(sprintf "0x%x", $cfg_chksum)."\n"); + userDebug("Num counters = ".(sprintf "%d", $num_ctrs)."\n"); + userDebug("ctrs_ptr = ".(sprintf "0x%x", $ctrs_ptr)."\n"); + + if (($counters eq NotFound) || ($counters eq NotPresent)) + { + userDebug("Skipping because counter data not resident in memory\n"); + next; + } print $fd pack('l', GCOV_FUNCTION_TAG); # Write function tag. - print $fd pack('l', 2); # Write size = 2. + print $fd pack('l', 3); # Write size = 3. print $fd pack('l', $ident); # Write ident. - print $fd pack('l', $chksum); # Write checksum. - - my $nctr_val = read32($func_off + GCOV_FNINFO_NCTRS_OFFSET); - userDebug("N-Counters = ".$nctr_val."\n"); + print $fd pack('l', $lineno_chksum); # Write checksum. + print $fd pack('l', $cfg_chksum); # Write checksum. print $fd pack('l', GCOV_COUNTERS_TAG); # Write counter tag. - print $fd pack('l', $nctr_val * 2); # Write counter length. + print $fd pack('l', $num_ctrs * 2); # Write counter length. # Read each counter value, output. # Read as one big block for performance reasons. - my $counters = readData($val_ptr + 8*($fn_offset), 8 * $nctr_val); - for(my $v_idx = 0; $v_idx < $nctr_val; $v_idx++) + + for(my $v_idx = 0; $v_idx < $num_ctrs; $v_idx++) { my $val = substr $counters, 0, 8; $counters = substr $counters, 8; @@ -306,15 +398,34 @@ sub parseGcovFuncs $val = unpack("Q", $val); userDebug("\tValue[$v_idx] = ".$val."\n"); + my $preex_read_low = read($fd, my $low_word, 4); + my $preex_read_high = read($fd, my $high_word, 4); + + if (!defined($preex_read_low) or !(defined($preex_read_high))) { + die; + } + my $preex_read = $preex_read_low + $preex_read_high; + + if ($preex_read == 8) + { + my $preex_val = (unpack("l", $high_word) << 32) | unpack("l", $low_word); + + $val += $preex_val; + } + + if ($preex_read > 0) + { + seek $fd, -$preex_read, 1; + } + else + { + seek $fd, 0, 2; + } + print $fd pack('l', $val & 0xFFFFFFFF); # Write lower word. print $fd pack('l', $val >> 32) ; # Write upper word. } - - # We used up a number of counters, so move the offset forward for - # the next function. - $fn_offset += $nctr_val; } - } # The *.gcda filename found in the gcov_info struct is an absolute path to @@ -330,16 +441,25 @@ sub createGcovFile my $version = shift; my $stamp = shift; - # Change *./../obj/ into obj/, prepend output_dir. - $name =~ s/.*\/obj\//obj\//; - $name = $output_dir.$name; - - # Make sure everything after 'obj/' exists (create subdirs). - my $dir = File::Basename::dirname($name); - File::Path::mkpath($dir); + # if the file exists then we update it, if not we create it + my $GCOVFILE; + if (-e $name) + { + if (!open($GCOVFILE, "+<$name")) + { + ::userDisplay("Failed to open $name for reading/writing gcov information\n"); + die; + } + } + else + { + if (!open($GCOVFILE, "+>$name")) + { + ::userDisplay("Failed to open $name for writing gcov information\n"); + die; + } + } - # Create file. - open(my $GCOVFILE, "> $name"); binmode($GCOVFILE); # Write out header. @@ -377,6 +497,22 @@ sub isVirtualAddress return ($addr >= GCOV_EXTENDED_IMAGE_ADDRESS); } +sub readExtImage +{ + my $addr = shift; + my $amount = shift; + + if ($addr + $amount >= $hbicore_extended_bin_file_size) { + return NotFound; + } + + seek $hbicore_extended_bin_file, $addr, 0; + + read $hbicore_extended_bin_file, my ($contents), $amount; + + return $contents; +} + # Utility to read a block of data from eithr memory or using the extended # image file as a fallback if not present in memory. use constant PAGESIZE => 4096; @@ -401,8 +537,13 @@ sub readData my $paddr = getPhysicalAddr($addr); if ((NotFound eq $paddr) || (NotPresent eq $paddr)) { - $paddr = $addr - GCOV_EXTENDED_IMAGE_ADDRESS; - $result = $result.::readExtImage($paddr, $amount); + my $tmpdata = readExtImage($addr - GCOV_EXTENDED_IMAGE_ADDRESS, $amount); + + if ($tmpdata eq NotFound) { + return NotFound; + } + + $result = $result . $tmpdata; } else { @@ -423,14 +564,27 @@ sub readData sub read64 { my $addr = shift; + my $fallback = shift; + my $old_addr = $addr; if (isVirtualAddress($addr)) { $addr = getPhysicalAddr($addr); if ((NotFound eq $addr) || (NotPresent eq $addr)) { + userDebug((sprintf "0x%x", $old_addr). " not translatable 2\n"); + + if (!$fallback) { + return NotFound; + } + $addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS; - my $result = ::readExtImage($addr, 8); + my $result = readExtImage($addr, 8); + + if ($result eq NotFound) { + return NotFound; + } + if (::littleendian()) { $result = reverse($result); } return unpack("Q", $result); } @@ -444,14 +598,25 @@ sub read64 sub read32 { my $addr = shift; + my $fallback = shift; + my $old_addr = $addr; if (isVirtualAddress($addr)) { $addr = getPhysicalAddr($addr); if ((NotFound eq $addr) || (NotPresent eq $addr)) { + userDebug((sprintf "0x%x", $old_addr). "not translatable 3\n"); + + if (!$fallback) { + return NotFound; + } + $addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS; - my $result = ::readExtImage($addr, 4); + my $result = readExtImage($addr, 4); + if ($result eq NotFound) { + return NotFound; + } if (::littleendian()) { $result = reverse($result); } return unpack("L", $result); } @@ -471,8 +636,10 @@ sub read8 $addr = getPhysicalAddr($addr); if ((NotFound eq $addr) || (NotPresent eq $addr)) { + userDebug((sprintf "0x%x", $addr). "not translatable 4\n"); + $addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS; - my $result = ::readExtImage($addr, 1); + my $result = readExtImage($addr, 1); return unpack("C", $result); } } @@ -486,31 +653,82 @@ sub readStr { my $addr = shift; my $old_addr = $addr; + if (isVirtualAddress($addr)) { - $addr = $addr - GCOV_EXTENDED_IMAGE_ADDRESS; + userDebug("it is a virtual address, addr is " . (sprintf "%x", $addr) . "\n"); + my $phys_addr = getPhysicalAddr($addr); - # Virtual address, so need to read 1 byte at a time from the file. - my $string = ""; - my $byte = 0; - - do + if ((NotFound eq $phys_addr) || (NotPresent eq $phys_addr)) { - $byte = ::readExtImage($addr,1); - $addr = $addr + 1; + userDebug("Translation not found, reading from pnor\n"); + # Virtual address, so need to read 1 byte at a time from the file. + my $string = ""; + my $byte = 0; - if (unpack("C",$byte) eq 0) + do { - return $string; - } + $byte = readExtImage($addr - GCOV_EXTENDED_IMAGE_ADDRESS, 1); - $string = $string.$byte; + if ($byte eq NotFound) + { + return ""; + } - } while (1) + $addr = $addr + 1; + + if (unpack("C",$byte) eq 0) + { + return $string; + } + + $string = $string.$byte; + } while (1); + } + else + { + my $string = ""; + my $byte = 0; + + do + { + if (($addr & 0xfff) == 0) + { + # we have to recalculate the physical address + # whenever we cross a page boundary + $phys_addr = getPhysicalAddr($addr); + + if ((NotFound eq $phys_addr) || (NotPresent eq $phys_addr)) + { + userDebug((sprintf "0x%x", $addr). "not translatable 10\n"); + return ""; + } + } + + $byte = read8($phys_addr); + + if ($byte eq NotFound) + { + userDebug("Cannot read byte from physical address\n"); + return ""; + } + + $addr += 1; + $phys_addr += 1; + + if ($byte != 0) + { + $string = $string . pack("C", $byte); + } + } while ($byte != 0); + + return $string; + } } else { - ::readStr($addr); + userDebug("it is NOT a virtual address\n"); + return ::readStr($addr); } } @@ -531,3 +749,5 @@ sub helpInfo intro => [ "Extracts the GCOV information."], ); } + +1; # Last expression in a perl module must be truthy. diff --git a/src/build/debug/Hostboot/GcovModuleUnload.pm b/src/build/debug/Hostboot/GcovModuleUnload.pm new file mode 100644 index 000000000..1a411cc3c --- /dev/null +++ b/src/build/debug/Hostboot/GcovModuleUnload.pm @@ -0,0 +1,69 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/debug/Hostboot/GcovModuleUnload.pm $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2019 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +#!/usr/bin/perl +use strict; +use File::Path; +use File::Basename; + +package Hostboot::GcovModuleUnload; +use Hostboot::Gcov qw(parseGcovInfo init); + +use Exporter; +our @EXPORT_OK = ('main', 'parseGcovInfo'); + +sub main +{ + my ($packName, $args) = @_; + + my $gcov_info_address = $args->{"address"}; + + ::userDisplay("Dumping gcov module info from " . (sprintf "0x%x", $gcov_info_address) . "\n"); + + if ($gcov_info_address <= 0) { + ::userDisplay("Can't dump from NULL\n"); + return -1; + } + + if (!Hostboot::Gcov::init()) { + return -2; + } + + Hostboot::Gcov::parseGcovInfo($gcov_info_address); + + ::userDisplay("Done.\n"); + + return 0; +} + +# Debug tool help info. +sub helpInfo +{ + my %info = ( + name => "GcovModuleUnload", + intro => [ "Extracts the GCOV information from modules as they are being unloaded."], + ); +} + +1; # Last expression in a perl module must be truthy. diff --git a/src/build/debug/Hostboot/PrintVMM.pm b/src/build/debug/Hostboot/PrintVMM.pm index 476262d93..57a57a9e2 100644 --- a/src/build/debug/Hostboot/PrintVMM.pm +++ b/src/build/debug/Hostboot/PrintVMM.pm @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2018 +# Contributors Listed Below - COPYRIGHT 2012,2020 # [+] International Business Machines Corp. # # @@ -73,7 +73,7 @@ sub main my @segment_manager_addr = ::findPointer("SGMNTMGR", "Singleton<SegmentManager>::instance()::instance"); - if (not defined @segment_manager_addr) + if (not @segment_manager_addr) { ::userDisplay " VirtualToPhy: Cannot find Device Segment symbol.\n"; die; } diff --git a/src/build/debug/Hostboot/_DebugFrameworkVMM.pm b/src/build/debug/Hostboot/_DebugFrameworkVMM.pm index 128df4ec7..ca323bd32 100755 --- a/src/build/debug/Hostboot/_DebugFrameworkVMM.pm +++ b/src/build/debug/Hostboot/_DebugFrameworkVMM.pm @@ -6,7 +6,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2018 +# Contributors Listed Below - COPYRIGHT 2012,2020 # [+] International Business Machines Corp. # # @@ -404,7 +404,7 @@ sub getPhysicalAddr "Singleton<SegmentManager>::instance()::instance"); - if (not defined @segment_manager_addr) + if (not @segment_manager_addr) { ::userDisplay " VirtualToPhy: Cannot find SegmentManager symbol.\n"; return NotFound; diff --git a/src/build/debug/eSEL.pl b/src/build/debug/eSEL.pl index ddce72f50..ed9ef2335 100755 --- a/src/build/debug/eSEL.pl +++ b/src/build/debug/eSEL.pl @@ -6,7 +6,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2017,2018 +# Contributors Listed Below - COPYRIGHT 2017,2019 # [+] International Business Machines Corp. # # @@ -588,6 +588,11 @@ sub DecodeObmcEselData $timestamp_found = 1; last; } + elsif($next_line =~ /timestamp/) + { + $timestamp_found = 2; + last; + } elsif($next_line =~ /ESEL/ or $next_line =~ /20 00 04/) # found the next ESEL { @@ -601,16 +606,35 @@ sub DecodeObmcEselData if($timestamp_found) { - # strip the "Timestamp", commas, spaces, and the newline - $next_line =~ s/"Timestamp"://g; - $next_line =~ s/,//g; - $next_line =~ s/ //g; - chomp $next_line; - - # convert to date/time (we are given the timestamp in ms, so divide - # by 1000 to get s). - $timestamp = + if($timestamp_found == 1) + { + # strip the "Timestamp", commas, spaces, and the newline + $next_line =~ s/"Timestamp"://g; + $next_line =~ s/,//g; + $next_line =~ s/ //g; + chomp $next_line; + + # convert to date/time (we are given the timestamp in ms, so divide + # by 1000 to get s). + $timestamp = strftime("%m/%d/%Y %H:%M:%S", localtime($next_line/1000)); + } + elsif($timestamp_found == 2) + { + # Field format :: "timestamp": "2019-10-31 10:20:50" + $next_line =~ s/"timestamp"://g; + $next_line =~ s/"//g; #drop the quotes + my @tmp1 = split( " ", $next_line ); #break the date and time apart + my @df = split( /-/, $tmp1[0] ); #break up the date fields + # Convert to :: 11/05/2019 12:25:41 + $timestamp = "$df[1]/$df[2]/$df[0] $tmp1[1]"; + ($debug) && print "timestamp> $timestamp \n"; + } + else + { + die "Bad timestamp\n"; + } + ($debug) && print "Timestamp for ESEL #$esel_record_count:$next_line\n"; ($debug) && print "Decoded timestamp for ESEL #$esel_record_count:$timestamp\n"; diff --git a/src/build/debug/ffdcExpander b/src/build/debug/ffdcExpander new file mode 100755 index 000000000..95f7c970f --- /dev/null +++ b/src/build/debug/ffdcExpander @@ -0,0 +1,727 @@ +#!/bin/sh +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/debug/ffdcExpander $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2013,2020 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + + +############################################################################### +# @file ffdcExpander +# This shell script takes a SYSDUMP file and extracts various debug elements. +# The caller has the option to post artifacts to a defect. +# +# The starting point for this script is at the end of the file. +############################################################################### + +############################################################################### +# Some helpful constants +############################################################################### +FFDC_GUNZIP_TOOL="/bin/gunzip" +FFDC_DUMP_PARSER="/esw/bin/dumpparser" + + +############################################################################### +# Some global variables +############################################################################### +FFDC_3RD_PARTY_SCRIPT_DIR="/gsa/ausgsa/projects/h/hostboot/optools/" # Location of files updatecq.pl, cqcmd.pl and Slurp.pm +FFDC_SCRIPT_NAME=$(basename "${0}") # Cache the name of this script +FFDC_SCRIPT_DIR=$(dirname "${0}") # Location of this script and supporting scripts +FFDC_SCRIPT_DIR="${FFDC_SCRIPT_DIR}/" +FFDC_SYSDUMP_FILE_GZ="" # format SYSDUMP.13020B8.20000001.20190725181300.gz +FFDC_SYSDUMP_FILE="" # format SYSDUMP.13020B8.20000001.20190725181300 +FFDC_HB_DUMP_FILE=""; # format hb.dump.SYSDUMP.13020B8.20000001.20190725181300 +FFDC_FSP_DRIVER_DIR="" # format '/esw/fips922/Builds/b0724a_1931.922' +FFDC_FSP_DRIVER="" # format 'fips922', 'fips950' , etc +FFDC_FSP_BUILD_TAG="" # format b0724a_1931.922 +FFDC_DEFECT_NUM="" # format 'SW123456', 'sw123456', 'Sw123456' or 'sW123456' +FFDC_DEFECT_NUM_CHARS="8" # The number of characters expected in defect including 'SW' +FFDC_CWD="`pwd -P`/" # The current working directory +FFDC_DEST_DIR="${FFDC_CWD}" # The destination directory of artifacts, default to CWD +FFDC_CQ_USER="" # The CQ user ID +FFDC_CQ_PASS="" # The CQ password +FFDC_RETURN_VALUE="0" # The return value. Default to success '0' +FFDC_TIME_STAMP="" # A time stamp is generated to make the files unique + +############################################################################### +# Print the usage line +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### +function _ffdcUsage_() +{ + echo "" + echo " Usage: ${FFDC_SCRIPT_NAME} -g <FFDC_SYSDUMP_FILE.gz> | -s <FFDC_SYSDUMP_FILE> |" + echo " -h <HB_FFDC_SYSDUMP_FILE> -b <FSP_BUILD_TAG>" + echo " [ OPTIONS ]" + echo "" + echo " OPTIONS: [ -d <DEST_DIR> ] [ -a <DEFECT_NUM> ] [ -t ]" + echo " -t attach a time stamp to the artifacts" + echo "" + echo " Examples: ${FFDC_SCRIPT_NAME} -g SYSDUMP.13020B8.20000001.20190725181300.raw67117184.gz" + echo " ${FFDC_SCRIPT_NAME} -s SYSDUMP.13020B8.20000001.20190725181300.raw67117184" + echo " ${FFDC_SCRIPT_NAME} -h hb.dump.SYSDUMP.13020B8.20000001.20190725181300 -b b0724a_1931.922" + echo " ${FFDC_SCRIPT_NAME} -s SYSDUMP.13020B8.20000001.20190725181300.raw67117184 -a SW123456 -t" + echo " ${FFDC_SCRIPT_NAME} -s SYSDUMP.13020B8.20000001.20190725181300.raw67117184 -d dir" + echo "" + return 0; # Return success +} + +############################################################################### +# @brief Get the caller's options and validate them +# +# @param [in] $* - All of the caller's inputs after name of script +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### +function _getUserInputOptionsAndValidate_() +{ + # Default caller options + CALLER_SYSDUMP_FILE_GZ="" + CALLER_SYSDUMP_FILE="" + CALLER_HB_DUMP_FILE="" + CALLER_FSP_BUILD_TAG="" + CALLER_DEST_DIR="" + CALLER_REQUESTS_TIME_STAMP="" + + # Get caller's options + FFDC_RETURN_VALUE="22" # Default to 'Invalid argument' + MANDATORY_OPTION_CHOSEN="0" + echo "" + while getopts ts:g:h:b:d:a: option + do + if [ -n "${option}" ]; then + FFDC_RETURN_VALUE="0"; # Found an argument + fi + case "${option}" + in + t) CALLER_REQUESTS_TIME_STAMP=1;; + s) CALLER_SYSDUMP_FILE=${OPTARG}; MANDATORY_OPTION_CHOSEN="1";; + g) CALLER_SYSDUMP_FILE_GZ=${OPTARG}; MANDATORY_OPTION_CHOSEN="1";; + h) CALLER_HB_DUMP_FILE=${OPTARG}; MANDATORY_OPTION_CHOSEN="1";; + b) CALLER_FSP_BUILD_TAG=${OPTARG};; + d) CALLER_DEST_DIR=${OPTARG};; + a) CALLER_DEFECT_NUM=${OPTARG};; + \?) FFDC_RETURN_VALUE=22;; + :) FFDC_RETURN_VALUE=22;; + esac + done + + # If call to getopts not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + _ffdcUsage_ + return $FFDC_RETURN_VALUE; + fi + + # Check for a valid option chosen + if [ "$MANDATORY_OPTION_CHOSEN" == "0" ]; then + _ffdcUsage_ + return $FFDC_RETURN_VALUE; + fi + + # Check for nonsensical options + if [ -n "${CALLER_SYSDUMP_FILE}" ] && [ -n "${CALLER_SYSDUMP_FILE_GZ}" ]; then + echo " ERROR: Incompatible options: options -g and -s can't be used together"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ] && [ -n "${CALLER_HB_DUMP_FILE}" ]; then + echo " ERROR: Incompatible options: options -g and -h can't be used together"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ] && [ -n "${CALLER_FSP_BUILD_TAG}" ]; then + echo " ERROR: Incompatible options: options -g and -b can't be used together"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + if [ -n "${CALLER_SYSDUMP_FILE}" ] && [ -n "${CALLER_FSP_BUILD_TAG}" ]; then + echo " ERROR: Incompatible options: options -s and -b can't be used together"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + if [ -n "${CALLER_SYSDUMP_FILE}" ] && [ -n "${CALLER_HB_DUMP_FILE}" ]; then + echo " ERROR: Incompatible options: options -s and -h can't be used together"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + # Verify that if caller is passing in a HB dump file, they must supply the build tag + if [ -n "${CALLER_HB_DUMP_FILE}" ] && [ -z "${CALLER_FSP_BUILD_TAG}" ]; then + echo " ERROR: Must supply a -b option with the -h option"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + if [ -z "${CALLER_HB_DUMP_FILE}" ] && [ -n "${CALLER_FSP_BUILD_TAG}" ]; then + echo " ERROR: Must supply a -h option with the -b option"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + # If caller requests a time stamp, option -t, then oblige + if [ "$CALLER_REQUESTS_TIME_STAMP" == "1" ]; then + FFDC_TIME_STAMP=$(date +%s) + FFDC_TIME_STAMP="_${FFDC_TIME_STAMP}" + fi + + # If caller supplied a gzippped SYSDUMP file, option -g, then confirm it exists + if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ]; then + if [ ! -e "${CALLER_SYSDUMP_FILE_GZ}" ]; then + echo " gzipped SYSDUMP file (${CALLER_SYSDUMP_FILE_GZ}) not found"; + return 22; # return 'Invalid argument' + fi + + # Check if file given is a gzipped file, verify that it ends in .gz + if [[ "${CALLER_SYSDUMP_FILE_GZ}" != *\.gz ]]; then + echo " "; + echo " WARNING: It appears that file (${CALLER_SYSDUMP_FILE_GZ}) is not a gzipped file" + while true; do + echo "" + read -p " Do you wish to continue with file [Y/N] ? " yn + case $yn in + [Yy] ) break;; + [Nn] ) echo " ÂŻ\_(?)_/ÂŻ exiting ..."; echo ""; return 22;; # return 'Invalid argument' + * ) echo " Please answer [Y]es or [N]o.";; + esac + done + fi + + # Save caller's gzippped SYSDUMP file, option -g + FFDC_SYSDUMP_FILE_GZ="$CALLER_SYSDUMP_FILE_GZ" + + ## Add an absolute path to the gzipped file, if not already an absolute path + # Check the first character to see if starting with absolute path + FIRST_CHAR="${FFDC_SYSDUMP_FILE_GZ:0:1}" + # If first char not a '/' then append an absolute path + if [ "${FIRST_CHAR}" != "/" ]; then + FFDC_SYSDUMP_FILE_GZ="${FFDC_CWD}${FFDC_SYSDUMP_FILE_GZ}" + fi + fi # end if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ]; then + + + # If caller supplied a SYSDUMP file, option -f, then confirm it exists + if [ -n "${CALLER_SYSDUMP_FILE}" ]; then + if [ ! -e "${CALLER_SYSDUMP_FILE}" ]; then + echo " SYSDUMP file (${CALLER_SYSDUMP_FILE}) not found"; + return 22; # return 'Invalid argument' + fi + + # Save caller's SYSDUMP file, option -f + FFDC_SYSDUMP_FILE="${CALLER_SYSDUMP_FILE}" + + ## Add an absolute path to the gzipped file, if not already an absolute path + # Check the first character to see if starting with absolute path + FIRST_CHAR="${FFDC_SYSDUMP_FILE:0:1}" + # If first char not a '/' then append an absolute path + if [ "${FIRST_CHAR}" != "/" ]; then + FFDC_SYSDUMP_FILE="${FFDC_CWD}${FFDC_SYSDUMP_FILE}" + fi + fi # end if [ -n "${CALLER_SYSDUMP_FILE}" ]; then + + + # If caller supplied a HB dump file, option -h, then confirm it exists + if [ -n "${CALLER_HB_DUMP_FILE}" ]; then + if [ ! -e "${CALLER_HB_DUMP_FILE}" ]; then + echo " HB dump file (${CALLER_HB_DUMP_FILE}) not found"; + return 22; # return 'Invalid argument' + fi + + # Save caller's HB dump file, option -h + FFDC_HB_DUMP_FILE="${CALLER_HB_DUMP_FILE}" + + ## Add an absolute path to the HB dump file, if not already an absolute path + # Check the first character to see if starting with absolute path + FIRST_CHAR="${FFDC_HB_DUMP_FILE:0:1}" + # If first char not a '/' then append an absolute path + if [ "${FIRST_CHAR}" != "/" ]; then + FFDC_HB_DUMP_FILE="${FFDC_CWD}${FFDC_HB_DUMP_FILE}" + fi + fi # end if [ -n "${CALLER_HB_DUMP_FILE}" ]; then + + + # If caller supplied an FSP build tag, option -b, then validate it + if [ -n "${CALLER_FSP_BUILD_TAG}" ]; then + # Extrapolate the FSP Build Release from the FSP build tag + if [[ "${CALLER_FSP_BUILD_TAG}" = *"."* ]]; then + FIPS_VERS=$(echo ${CALLER_FSP_BUILD_TAG} | \cut -d"." -f 2) + if [ -n "${FIPS_VERS}" ]; then + FFDC_FSP_DRIVER="fips${FIPS_VERS}" + else + echo " "; + echo " Build tag (${CALLER_FSP_BUILD_TAG}) appears to be in wrong format"; + echo " Cannot extrapolate the FIPS version from build tag"; + return 22; # return 'Invalid argument' + fi + else + echo " "; + echo " Build tag (${CALLER_FSP_BUILD_TAG}) appears to be in wrong format"; + echo " Cannot extrapolate the FIPS version from build tag"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi # end if [[ "${CALLER_FSP_BUILD_TAG}" = *"."* ]]; then + + # Save the caller's FSP build tag + FFDC_FSP_BUILD_TAG="${CALLER_FSP_BUILD_TAG}" + + # Save the caller's FSP build tag with the directory to it + FFDC_FSP_DRIVER_DIR="/esw/${FFDC_FSP_DRIVER}/Builds/${CALLER_FSP_BUILD_TAG}" + fi # end if [ -n "${CALLER_FSP_BUILD_TAG}" ]; then + + # If caller supplied a defect, option -a, just confirm it is in the correct + # nomenclature and format + if [ -n "${CALLER_DEFECT_NUM}" ]; then + + FFDC_DEFECT_NUM=$(echo ${CALLER_DEFECT_NUM^^}) + if [[ $FFDC_DEFECT_NUM != SW* ]]; then + echo " ERROR: software defect must be preceded with 'SW'"; + echo " "; + return 22; # return 'Invalid argument' + fi + + NUM_CHARS=${#FFDC_DEFECT_NUM} + if [[ "${NUM_CHARS}" -ne "${FFDC_DEFECT_NUM_CHARS}" ]]; then + echo " ERROR: software defect must have a total of ${FFDC_DEFECT_NUM_CHARS} characters, including 'SW'"; + echo " "; + return 22; # return 'Invalid argument' + fi + + INTEGER_PART=$(echo ${CALLER_DEFECT_NUM} | sed "s/^SW//g") + REG_EXP='^[0-9]+$' + if ! [[ $INTEGER_PART =~ $REG_EXP ]]; then + echo " ERROR: the characters (${INTEGER_PART}) that follow 'SW' must be an integer"; + echo " "; + return 22; # return 'Invalid argument' + fi + + # Prompt username and password for CQ + _queryUserPassword_; + FFDC_RETURN_VALUE=$? + if [ "${FFDC_RETURN_VALUE}" != "0" ]; then + echo "" + return ${FFDC_RETURN_VALUE}; # Return failure + fi + fi # end # If caller supplied a defect, option -a, ... + + + # If caller supplied a destination directory, option -d, then confirm it + # exists and determine if it is a relative path or absolute path + if [ -n "${CALLER_DEST_DIR}" ]; then + if [ ! -e "${CALLER_DEST_DIR}" ]; then + echo " Destination directory (${CALLER_DEST_DIR}) not found"; + while true; do + echo "" + read -p " Do you wish to ceate it [Y/N] ? " yn + case $yn in + [Yy] ) break;; + [Nn] ) echo " ÂŻ\_(?)_/ÂŻ exiting ..."; echo ""; return 22;; # return 'Invalid argument' + * ) echo " Please answer [Y]es or [N]o.";; + esac + done + + mkdir -p ${CALLER_DEST_DIR} + FFDC_RETURN_VALUE=$? + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + echo "" + return $FFDC_RETURN_VALUE; # Propagate failure + fi + echo " Destination directory (${CALLER_DEST_DIR}) created"; + echo "" + fi + + # Save caller's destination directory option + FFDC_DEST_DIR="$CALLER_DEST_DIR" + NUM_CHARS=$((${#FFDC_DEST_DIR}-1)) + LAST_CHAR="${FFDC_DEST_DIR:$NUM_CHARS:1}" + # If last char not a '/' then append a '/' + if [ "${LAST_CHAR}" != "/" ]; then + FFDC_DEST_DIR="${FFDC_DEST_DIR}/" + fi + + ## Add an absolute path to the destination directory, if it is not + ## already an absolute path. + # Inspect the first character to determine path is absolute or not + FIRST_CHAR="${FFDC_DEST_DIR:0:1}" + # If first char not a '/' then append an absolute path + if [ "${FIRST_CHAR}" != "/" ]; then + FFDC_DEST_DIR="${FFDC_CWD}${FFDC_DEST_DIR}" + fi + fi # end if [ -n "${CALLER_DEST_DIR}" ]; then + + return 0; # Return success +} + +############################################################################### +# @brief Query caller for user name and password +############################################################################### +function _queryUserPassword_() +{ + if [ -n "${FFDC_DEFECT_NUM}" ]; then + read -p 'CQ Username: ' FFDC_CQ_USER + read -sp 'CQ Password: ' FFDC_CQ_PASS + fi + + return 0; +} + +############################################################################### +# @brief Unzip the system dump file +# +# Example: unzip SYSDUMP.13020B8.20000001.20190725181300.raw67117184.gz => +# SYSDUMP.13020B8.20000001.20190725181300.raw67117184 +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### +function _unzipSysDumpFile_() +{ + # Verify that we can get to the dumpparser script + if [[ ! -e "${FFDC_GUNZIP_TOOL}" ]]; then + echo "" + echo " ERROR: Could not find gunzip tool ${FFDC_GUNZIP_TOOL}" + echo "" + return 2; # Return 'No such file or directory' + fi + + ## Extrapolate the SYSDUMP file from the gzipped file + # Remove any directories and only get the file name + FFDC_SYSDUMP_FILE=$(echo ${FFDC_SYSDUMP_FILE_GZ} | awk -F / '{ print $NF }') + # Remove the '.gz' from the gzipped file + FFDC_SYSDUMP_FILE=$(echo ${FFDC_SYSDUMP_FILE} | sed "s/\.gz$//") + # Prepend the caller's directory + FFDC_SYSDUMP_FILE="${FFDC_DEST_DIR}${FFDC_SYSDUMP_FILE}" + + # Check if the SYSDUMP file already exists, if so, ask caller if they wish + # to overwrite it + if [[ -e "${FFDC_SYSDUMP_FILE}" ]]; then + echo "" + echo " SYSDUMP file (${FFDC_SYSDUMP_FILE}) already exists ..." + while true; do + echo "" + read -p " Do you wish to override the file and continue [Y/N] ? " yn + case $yn in + [Yy] ) break;; + [Nn] ) echo " Skipping call to ${FFDC_GUNZIP_TOOL} ..."; echo ""; return 0;; + * ) echo " Please answer [Y]es or [N]o.";; + esac + done + fi + + # Unzip the gzipped SYSDUMP file + echo "" + echo " ${FFDC_GUNZIP_TOOL} -c ${FFDC_SYSDUMP_FILE_GZ} > ${FFDC_SYSDUMP_FILE}" + `${FFDC_GUNZIP_TOOL} -c ${FFDC_SYSDUMP_FILE_GZ} > ${FFDC_SYSDUMP_FILE}` + FFDC_RETURN_VALUE=$? + if [ "${FFDC_RETURN_VALUE}" != "0" ]; then + echo "" + return ${FFDC_RETURN_VALUE}; # Return failure + fi + + return 0; # Return success +} + + +############################################################################### +# @brief Extract the HB system dump file from the SYSDUMP file +# +# Example: /esw/bin/dumpparser -extMem SYSDUMP.13020B8.20000001.20190725181300.raw67117184 => +# hb.dump.SYSDUMP.13020B8.20000001.20190725181300 +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### +function _extractHbSysDumpFile_() +{ + # Verify that we can get to the dump parser script + if [[ ! -e "${FFDC_DUMP_PARSER}" ]]; then + echo "" + echo " ERROR: Could not find parser ${FFDC_DUMP_PARSER}" + echo "" + return 2; # Return 'No such file or directory' + fi + + ## Extrapolate the HB dump file name from the SYSDUMP file + # Remove any directories and only get the file name + FFDC_HB_DUMP_FILE=$(echo ${FFDC_SYSDUMP_FILE} | awk -F / '{ print $NF }') + # Remove the .gz from the SYSDUMP, if it exists + FFDC_HB_DUMP_FILE=$(echo ${FFDC_HB_DUMP_FILE} | sed "s/\.gz$//") + # Remove the postpended '.rawxxx' from the SYSDUMP file, if it exists + FFDC_HB_DUMP_FILE=$(echo ${FFDC_HB_DUMP_FILE} | sed "s/\.raw.*$//") + # Prepend 'hb.dump.' to file + FFDC_HB_DUMP_FILE=$(echo ${FFDC_HB_DUMP_FILE} | sed "s/^/hb.dump./") + # Prepend the caller's directory + FFDC_HB_DUMP_FILE="${FFDC_DEST_DIR}${FFDC_HB_DUMP_FILE}" + + # Extract the the FSP build info from the SYSDUMP file + FSP_BUILD_INFO=$(${FFDC_DUMP_PARSER} -a ${FFDC_SYSDUMP_FILE} | grep "Driver is" | awk '{ print $4 }') + + # Extract the the FSP driver info from the FSP build info + FFDC_FSP_DRIVER=$(echo ${FSP_BUILD_INFO} | awk -F / '{ print $1 }') + + # Extract the FSP build tag info from the FSP build info + FFDC_FSP_BUILD_TAG=$(echo ${FSP_BUILD_INFO} | awk -F / '{ print $2 }') + + # Create a path to FSP build driver info + FFDC_FSP_DRIVER_DIR="/esw/${FFDC_FSP_DRIVER}/Builds/${FFDC_FSP_BUILD_TAG}" + + # Check if the HB dump file already exists, if so, ask caller if they wish + # to overwrite it + if [[ -e "${FFDC_HB_DUMP_FILE}" ]]; then + echo "" + echo " HB system dump file (${FFDC_HB_DUMP_FILE}) already exists ..." + while true; do + echo "" + read -p " Do you wish to override the file and continue [Y/N] ? " yn + case $yn in + [Yy] ) break;; + [Nn] ) echo " Skipping call to ${FFDC_DUMP_PARSER} ..."; return 0;; + * ) echo " Please answer [Y]es or [N]o.";; + esac + done + fi + + # Change directory to user supplied directory + \cd -P ${FFDC_DEST_DIR} ; + + # Parse out the HB dump file using the dump parser + echo "" + echo " ${FFDC_DUMP_PARSER} -extMem ${FFDC_SYSDUMP_FILE}" + ${FFDC_DUMP_PARSER} -extMem ${FFDC_SYSDUMP_FILE} + + FFDC_RETURN_VALUE=$? + if [ "${FFDC_RETURN_VALUE}" != "0" ]; then + # Return back to current working directory + \cd -P ${FFDC_CWD} + echo "" + return ${FFDC_RETURN_VALUE}; # Return failure + fi + + echo " Created file ${FFDC_HB_DUMP_FILE}" + + # Return back to current working directory + \cd -P ${FFDC_CWD} + + return 0; # Return success +} + + +############################################################################### +# @brief Set the path to the fsp-trace tool +# +# @return 0 +############################################################################### +function _setFSPTracePath_() +{ + FFDC_FSP_PATH="/esw/$FFDC_FSP_DRIVER/Builds/built/images/nfs/x86.nfp/bin/" + echo "" + echo " Using fsp-trace tool: ${FFDC_FSP_PATH}fsp-trace" + PATH=${FFDC_FSP_PATH}:$PATH + + # Verify that we can get to the dump parser script + if [[ ! -e "${FFDC_FSP_PATH}fsp-trace" ]]; then + echo "" + echo " ERROR: Could not find fsp trace ${FFDC_DUMP_PARSER}" + echo "" + return 2; # Return 'No such file or directory' + fi + + echo "PATH=${FFDC_FSP_PATH}:\$PATH" >> ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + + return 0; # Return success +} + +############################################################################### +# @brief Extract various HB dump info +# +# @param [in] $1 The HB tools directory +# @param [in] $2 Path to the hb-dump-debug tools directory +############################################################################### +function _getInfoFromHBDump_() +{ + echo "" + echo " Extracting the Trace information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Trace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}TRACE${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Trace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}TRACE${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the Printk information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Printk --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PRINTK${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Printk --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PRINTK${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the Errl information (Component/PLID list) from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Errl --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Errl --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the Errl information (Detailed listing of all Error Logs) from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Errl --tool-options='display=all' --file=${FFDC_HB_DUMP_FILE} >> ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Errl --tool-options='display=all' --file=${FFDC_HB_DUMP_FILE} >> ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the Ps information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Ps --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Ps --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the Ps information from HB dump with backtrace ..." + echo " running: $1 --img-path=$2/ --tool=Ps --tool-options="with-backtrace" --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS_BACKTRACE${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Ps --tool-options="with-backtrace" --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS_BACKTRACE${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the MemStats information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Ps --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}MEMSTATS${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=MemStats --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}MEMSTATS${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the PageMgr information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=PageMgr --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PAGEMGR${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=PageMgr --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PAGEMGR${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the BlTrace information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=BlTrace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}BLTRACE${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=BlTrace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}BLTRACE${FFDC_TIME_STAMP} +} + +############################################################################### +# @brief Extract various HB dump info and post to defect, if caller wishes to +############################################################################### +function _getInfoFromHBDumpAndPost_() +{ + _setFSPTracePath_ + FFDC_RETURN_VALUE=$? + # If call to _setFSPTracePath_ not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + return $FFDC_RETURN_VALUE; + fi + + HB_TOOLS_DIR=$FFDC_FSP_DRIVER_DIR/obj/x86.nfp/hbfw/simics + HB_DUMP_DEBUG=$HB_TOOLS_DIR/hb-dump-debug + _getInfoFromHBDump_ $HB_DUMP_DEBUG $HB_TOOLS_DIR + + # If supplied a defect number, then post a comment to the defect and add + # the generated dump files as attachments + if [ -n "${FFDC_DEFECT_NUM}" ]; then + PATH=${FFDC_3RD_PARTY_SCRIPT_DIR}:$PATH + CQFILE=${FFDC_3RD_PARTY_SCRIPT_DIR}updatecq.pl + + echo "" + echo -e "\n Adding attachment TRACE${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}TRACE${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS -s "Hostboot dump files stored at $FFDC_DEST_DIR" + + echo -e "\n Adding attachment PRINTK${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PRINTK${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment ERRL${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment PS${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PS${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment PS_BACKTRACE${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PS_BACKTRACE${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment MEMSTATS${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}MEMSTATS${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment PAGEMGR${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PAGEMGR${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment BLTRACE${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}BLTRACE${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + fi +} + + +############################################################################### +# @brief The main. The real starting place of this script +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### +function ffdcExpanderMain() +{ + # Get user input options and validate + _getUserInputOptionsAndValidate_ $* + FFDC_RETURN_VALUE=$? + # If call to _getUserInputOptionsAndValidate_ not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + return $FFDC_RETURN_VALUE; + fi + + + # If caller supplied a gzipped file then unzip it + if [ -n "${FFDC_SYSDUMP_FILE_GZ}" ]; then + _unzipSysDumpFile_ + FFDC_RETURN_VALUE=$? + fi + # If call to _unzipSysDumpFile_ not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + return $FFDC_RETURN_VALUE; + fi + + + # If caller supplied a SYSDUMP file then extract HB dump file + if [ -n "${FFDC_SYSDUMP_FILE}" ]; then + _extractHbSysDumpFile_ ${FFDC_SYSDUMP_FILE} + FFDC_RETURN_VALUE=$? + fi + # If call to _extractHbSysDumpFile_ not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + return $FFDC_RETURN_VALUE; + fi + + + # If caller supplied a HB dump file and a FSP build tag, then retrieve HB info + if [ -n "${FFDC_HB_DUMP_FILE}" ] && [ -n "${FFDC_FSP_DRIVER_DIR}" ]; then + # Save the FSP build tag as a file for the caller's benefit + touch ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + # Add some info data to the file + echo ${FFDC_FSP_BUILD_TAG} > ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + echo ${FFDC_FSP_DRIVER} >> ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + echo ${FFDC_FSP_DRIVER_DIR} >> ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + + _getInfoFromHBDumpAndPost_ ${FFDC_HB_DUMP_FILE} ${FFDC_FSP_DRIVER_DIR}; + FFDC_RETURN_VALUE=$? + fi + # If call to _getInfoFromHBDumpAndPost_ not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + return $FFDC_RETURN_VALUE; + fi + + echo "" + return 0; +} + + +############################################################################### +# @brief Call the main starting function, ffdcExpanderMain, the beginning point +# of this script +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### + +ffdcExpanderMain $* +exit $?; + diff --git a/src/build/debug/simics-debug-framework.py b/src/build/debug/simics-debug-framework.py index 3176f8cba..fd90806bb 100644 --- a/src/build/debug/simics-debug-framework.py +++ b/src/build/debug/simics-debug-framework.py @@ -516,7 +516,7 @@ def magic_instruction_callback(user_arg, cpu, arg): # Stop the simulation, much like a hard-coded breakpoint SIM_break_simulation( "Simulation stopped. (hap 7007)" ) - if arg == 7008: + if arg == 7008: # MAGIC_RANDOM cpu.r3 = random.randint(1, 0xffffffffffffffffL) if arg == 7009: # MAGIC_MEMORYLEAK_FUNCTION @@ -525,6 +525,10 @@ def magic_instruction_callback(user_arg, cpu, arg): if arg == 7011: #MAGIC_SIMICS_CHECK cpu.r3 = 1 print "TimeManager::cv_isSimicsRunning = true" + # Clear the dump flag in case it was still set from a previous boot + # (this call happens only 1 time and it is very early in the boot) + if( os.environ.has_key('HB_DUMP_COMPLETE') ): + del os.environ['HB_DUMP_COMPLETE'] if arg == 7012: # MAGIC_LOAD_PAYLOAD #For P9 the Payload load is much faster due to PNOR @@ -537,6 +541,17 @@ def magic_instruction_callback(user_arg, cpu, arg): #SIM_run_alone( run_command, cmd ) print "MAGIC_LOAD_PAYLOAD not implemented\n"; + if arg == 7014: # MAGIC_HB_DUMP + # Collect a hostboot dump + # (no args) + + # Make sure we only do 1 dump even though every thread will TI + if( not os.environ.has_key('HB_DUMP_COMPLETE') ): + print "Generating Hostboot Dump for TI" + os.environ['HB_DUMP_COMPLETE']="1" + cmd1 = "hb-Dump quiet" + SIM_run_alone(run_command, cmd1 ) + if arg == 7018: # MAGIC_BREAK_ON_ERROR # Stop the simulation if an env var is set if( os.environ.has_key('HB_BREAK_ON_ERROR') ): @@ -573,6 +588,7 @@ def magic_instruction_callback(user_arg, cpu, arg): percent_s = "%s" dateCommand = "shell \" date +'%s > TRACE REGS: %d %d' \""%(percent_s,first_num,second_num) SIM_run_alone(run_command, dateCommand ) + if arg == 7022: # MAGIC_SET_LOG_LEVEL if( not os.environ.has_key('ENABLE_HB_SIMICS_LOGS') ): #print("Skipping Hostboot Simics Logging because ENABLE_HB_SIMICS_LOGS is not set") @@ -745,7 +761,9 @@ def magic_instruction_callback(user_arg, cpu, arg): #file = open("hb_trace_debug.dat", "a") #file.write("%s\n" % (saveCommand)) #file.close() - + if arg == 7056: # MAGIC_GCOV_DUMP_NOW + print('Gcov dumping chain from 0x%x' % (cpu.r3,)) + SIM_run_alone(run_command, 'hb-GcovModuleUnload "address=%d"' % (cpu.r3,)) # Continuous trace: Clear these files. rc = os.system( "rm -f hbTracMERG" ) @@ -769,4 +787,3 @@ SIM_hap_add_callback_range( "Core_Magic_Instruction", magic_instruction_callback # Run the registration automatically whenever this script is loaded. register_hb_debug_framework_tools() - diff --git a/src/build/linker/genlist.C b/src/build/linker/genlist.C index 053f7aaa2..d89fbfaa6 100644 --- a/src/build/linker/genlist.C +++ b/src/build/linker/genlist.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2015 */ +/* Contributors Listed Below - COPYRIGHT 2013,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -95,6 +95,19 @@ string g_imageName; * call binutils tools. */ char* g_crossPrefix = NULL; + /** Whether we should use cached objdump files (true) or redump the + ELF objects (false). */ +bool use_cached_objdump = false; + + /** Print status messages */ +bool verbose = false; + +#define VFPRINTF(...) \ + do { \ + if (verbose) \ + fprintf(__VA_ARGS__); \ + } while (0) + int main(int argc, char** argv) { // Only parameter allowed is the name of the base image. @@ -103,6 +116,16 @@ int main(int argc, char** argv) print_usage(); } + verbose = getenv("BUILD_VERBOSE") != NULL; + + use_cached_objdump = getenv("BUILD_FAST") != NULL; + + if (use_cached_objdump) { + VFPRINTF(stderr, "Using cached OBJDUMP output\n"); + } else { + VFPRINTF(stderr, "Using fresh OBJDUMP output\n"); + } + // Get base image name from parameters. g_imageName = argv[1]; add_image_subdir(g_imageName); @@ -310,18 +333,42 @@ void* read_module_content(void* input) // Assumes they are in the same subdirectory. string module_path = g_imageName.substr(0, g_imageName.rfind('/') + 1) + module; + const string objdump_path = + g_imageName.substr(0, g_imageName.rfind('/') + 1) + "/objdump/" + module; + + FILE* pipe = NULL; - // Create the 'objdump' command for finding all the symbols and start as - // a sub-process. - // -d - Disassemble sections containing code. - // -C - Intersparse C code. - // -S - Demangle symbol names. - // -j .text, .data, .rodata - Only dump those 3 sections. - string command = string(g_crossPrefix) + - string("objdump -dCS -j .text -j .data -j .rodata ") + - module_path; - FILE* pipe = popen(command.c_str(), "r"); - if (NULL == pipe) return NULL; + VFPRINTF(stderr, "GENLIST: Processing %s\n", module_path.c_str()); + + if (use_cached_objdump) { + string bzcat_command = "bzcat " + objdump_path + ".objdump"; + pipe = popen(bzcat_command.c_str(), "r"); + + if (NULL == pipe) { + VFPRINTF(stderr, "GENLIST: Failed to run %s, falling back to live dump\n", + bzcat_command.c_str()); + } + } + + if (pipe == NULL) { + // Create the 'objdump' command for finding all the symbols and start as + // a sub-process. + // -d - Disassemble sections containing code. + // -C - Intersparse C code. + // -S - Demangle symbol names. + // -j .text, .data, .rodata - Only dump those 3 sections. + string objdump_command = string(g_crossPrefix) + + string("objdump -dCS -j .text -j .data -j .rodata ") + + module_path; + + pipe = popen(objdump_command.c_str(), "r"); + + if (NULL == pipe) { + fprintf(stderr, "GENLIST: Failed to open pipe for objdump: %s\n", + objdump_command.c_str()); + return NULL; + } + } // Start result string and add module start header. string result; diff --git a/src/build/linker/linker.C b/src/build/linker/linker.C index a9a9d0f5e..6a8854d83 100644 --- a/src/build/linker/linker.C +++ b/src/build/linker/linker.C @@ -112,6 +112,8 @@ struct Section size_t size; bfd_byte* data; + + Section() : name(""), vma_offset(0), size(0), data(NULL) {} }; /** @@ -123,6 +125,7 @@ struct Object string name; //!< full path name of file bfd* image; //!< bfd image of object Section text; //!< text section of binary + Section sfpr; //!< sfpr section of binary Section rodata; //!< rodata section of binary Section data; //!< data section of binary map<string, Symbol> symbols; //!< symbol map @@ -203,7 +206,7 @@ struct Object /** * CTOR default */ - Object() : image(NULL), text(), rodata(), data(), offset(0), + Object() : image(NULL), text(), rodata(), data(), sfpr(), offset(0), base_addr(0), iv_output(NULL), tls_module(-1) {} @@ -213,7 +216,7 @@ struct Object * @param[in] i_out : output FILE handle */ Object(unsigned long i_baseAddr, FILE* i_out) - : image(NULL), text(), rodata(), data(), offset(0), + : image(NULL), text(), rodata(), data(), sfpr(), offset(0), base_addr(i_baseAddr), iv_output(i_out), tls_module(-1) {} }; @@ -439,6 +442,8 @@ int main(int argc, char** argv) // A contained member value might be something like // _ZZ3fooE3bar. string sym_name = string((i->c_str())+1); + const char* gcovstr = "__gcov"; + size_t gcovstrlen = strlen(gcovstr); cout << "Checking weak symbol: " << *i << endl; @@ -451,6 +456,12 @@ int main(int argc, char** argv) == j->find("traceData_codeInfo")) && (*i != *j)) { + if (strncmp((*j).c_str(), + gcovstr, + gcovstrlen)==0) + { + continue; + } cout << "\tDuplicate member found: " << *j << endl; throw std::runtime_error( string("Duplicate weak symbol with contained " @@ -586,6 +597,11 @@ bool Object::read_object(const char* i_file) { s = &this->text; } + else if (string(".sfpr") == + bfd_get_section_name(image, image_section)) + { + s = &this->sfpr; + } else if (string(".rodata") == bfd_get_section_name(image, image_section)) { @@ -640,6 +656,16 @@ bool Object::write_object() cout << strerror(error) << endl; } + // Output sfpr section. + fseek(iv_output, offset + sfpr.vma_offset, SEEK_SET); + if ((0 != sfpr.size) && + (sfpr.size != fwrite(sfpr.data, 1, sfpr.size, iv_output))) + { + int error = errno; + cout << "Error writing to output for sfpr." << endl; + cout << strerror(error) << endl; + } + // Output RODATA section. fseek(iv_output, offset + rodata.vma_offset, SEEK_SET); if ((0 != rodata.size) && diff --git a/src/build/mkrules/cc.rules.mk b/src/build/mkrules/cc.rules.mk index c89995f82..409166e29 100644 --- a/src/build/mkrules/cc.rules.mk +++ b/src/build/mkrules/cc.rules.mk @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2013,2017 +# Contributors Listed Below - COPYRIGHT 2013,2019 # [+] International Business Machines Corp. # # @@ -31,22 +31,71 @@ $(OBJDIR)/%.list : $(OBJDIR)/%.o $(C2) " OBJDUMP $(notdir $<)" $(C1)$(OBJDUMP) -rdlCS $< > $@ +# SOURCE_FILE and INCLUDE_DIRS are variables that are either absolute +# paths to the .C file being compiled and the include directories if +# we're building with gcov, or else they are relative paths +# otherwise. The key thing to remember is that they are lazily +# expanded, so they're relevant to whatever rule they're used in. We +# don't want to always have absolute paths because of build +# performance and because it causes the build output with +# BUILD_VERBOSE to be larger and less readable. +ifdef HOSTBOOT_PROFILE +SOURCE_FILE=$(shell readlink -f $<) +INCLUDE_DIRS=$(shell $(ROOTPATH)/src/build/tools/cflags.sh $(INCFLAGS)) +else +SOURCE_FILE=$< +INCLUDE_DIRS=$(INCFLAGS) +endif + +# TODO RTC 215692 +# The following script is used to run the cppcheck tool when enabled. If one +# cppcheck error is found, the make process will stop here, the error will be +# printed out to the terminal and stored in a file .`basename $<`.cppcheck in +# the directory where the original file is located +ifdef DOCPPCHECK + CXX_PRINT=$(C2) " CPPCHECK $(notdir $<)" + # NoteL Error code 127 means that the command timed-out. We do not fail + # for timeouts + CXX_CPPCHECK_COMMAND=$(C1) set -o pipefail && cd `dirname $<` && timeout 2m $(CXX_CHECK) `basename $<` 2>&1 | tee .`basename $<`.cppcheck; exit_code=$$? ; \ + if [ "$$exit_code" -ne 1 ]; then \ + rm -f .`basename $<`.cppcheck; \ + if [ "$$exit_code" -eq 127 ]; then \ + exit_code=0; \ + fi; \ + fi; exit "$$exit_code" + C_CPPCHECK_COMMAND=$(C1) set -o pipefail && cd `dirname $<` && timeout 2m $(C_CHECK) `basename $<` 2>&1 | tee .`basename $<`.cppcheck; exit_code=$$? ; \ + if [ "$$exit_code" -ne 1 ]; then \ + rm -f .`basename $<`.cppcheck; \ + if [ "$$exit_code" -eq 127 ]; then \ + exit_code=0; \ + fi; \ + fi; exit "$$exit_code" +else + CXX_PRINT= + CXX_CPPCHECK_COMMAND= + C_CPPCHECK_COMMAND= +endif + $(OBJDIR)/%.o : %.C @mkdir -p $(OBJDIR) $(C2) " CXX $(notdir $<)" - $(C1)$(CXX) -c $(call FLAGS_FILTER, $(CXXFLAGS), $<) $< \ - -o $@.trace $(INCFLAGS) -iquote . + $(C1)$(CXX) -c $(call FLAGS_FILTER, $(CXXFLAGS), $<) $(SOURCE_FILE) \ + -o $@.trace $(INCLUDE_DIRS) -iquote . $(C1)$(TRACE_HASHER) $@ $(TRACE_FLAGS) @rm $@.trace + $(CXX_PRINT) + $(CXX_CPPCHECK_COMMAND) # Compiling *.cc files $(OBJDIR)/%.o : %.cc @mkdir -p $(OBJDIR) $(C2) " CXX $(notdir $<)" - $(C1)$(CXX) -c $(CXXFLAGS) $< -o $@.trace $(INCFLAGS) -iquote . + $(C1)$(CXX) -c $(CXXFLAGS) $(SOURCE_FILE) -o $@.trace \ + $(INCLUDE_DIRS) -iquote . $(C1)$(TRACE_HASHER) $@ $(TRACE_FLAGS) @rm $@.trace - + $(CXX_PRINT) + $(CXX_CPPCHECK_COMMAND) $(OBJDIR)/%.o : %.c @mkdir -p $(OBJDIR) @@ -54,12 +103,16 @@ $(OBJDIR)/%.o : %.c # CC_OVERRIDE is set in the makefile of the component ifndef CC_OVERRIDE $(C2) " CC $(notdir $<)" - $(C1)$(CC) -c $(call FLAGS_FILTER, $(CFLAGS), $<) $< \ - -o $@.trace $(INCFLAGS) -iquote . + $(C1)$(CC) -c $(call FLAGS_FILTER, $(CFLAGS), $<) $(SOURCE_FILE) \ + -o $@.trace $(INCLUDE_DIRS) -iquote . + $(CXX_PRINT) + $(C_CPPCHECK_COMMAND) else $(C2) " CXX $(notdir $<)" - $(C1)$(CXX) -c $(call FLAGS_FILTER, $(CXXFLAGS), $<) $< \ - -o $@.trace $(INCFLAGS) -iquote . + $(C1)$(CXX) -c $(call FLAGS_FILTER, $(CXXFLAGS), $<) $(SOURCE_FILE) \ + -o $@.trace $(INCLUDE_DIRS) -iquote . + $(CXX_PRINT) + $(CXX_CPPCHECK_COMMAND) endif $(C1)$(TRACE_HASHER) $@ $(TRACE_FLAGS) @rm $@.trace diff --git a/src/build/mkrules/cflags.env.mk b/src/build/mkrules/cflags.env.mk index 04ff6fedd..cb25561f8 100644 --- a/src/build/mkrules/cflags.env.mk +++ b/src/build/mkrules/cflags.env.mk @@ -28,7 +28,7 @@ # Description: # Configuration of the compiler, linker, etc. flags. -OPT_LEVEL ?= -O3 +OPT_LEVEL ?= -Os ifdef MODULE COMMONFLAGS += -fPIC -Bsymbolic -Bsymbolic-functions @@ -38,6 +38,8 @@ CFLAGS += -DNO_INITIALIZER_LIST CFLAGS += -D__FAPI endif +# Force all files to pull in the CONFIG_ variables +CFLAGS += -include config.h COMMONFLAGS += $(OPT_LEVEL) -nostdlib CFLAGS += $(COMMONFLAGS) -mcpu=power7 -nostdinc -g -mno-vsx -mno-altivec\ diff --git a/src/build/mkrules/dist.targets.mk b/src/build/mkrules/dist.targets.mk index 0d592b838..c925f25b5 100755 --- a/src/build/mkrules/dist.targets.mk +++ b/src/build/mkrules/dist.targets.mk @@ -304,6 +304,9 @@ fsp.tar_CONTENTS = \ src/build/buildpnor/genfakeheader.pl \ src/build/buildpnor/genPnorImages.pl \ src/build/buildpnor/buildUcdFlashImages.pl \ + src/build/buildpnor/buildBpmFlashImages.pl \ + src/build/buildpnor/bpm-utils/insertBpmFwCrc.py \ + src/build/buildpnor/bpm-utils/imageCrc.c \ src/build/buildpnor/PnorUtils.pm \ src/build/buildpnor/imprintHwKeyHash \ src/build/buildpnor/pkgOcmbFw.pl \ @@ -357,7 +360,8 @@ fsp.tar_CONTENTS = \ src/include/usr/hwas/common/hwasCallout.H:hwas/ \ src/include/usr/devicefw/driverif.H:devicefw/ \ src/include/usr/devicefw/userif.H:devicefw/ \ - obj/genfiles/plugins/errludattribute.H:plugins/ \ + obj/genfiles/plugins/errludattributeP_gen.H:plugins/ \ + src/usr/errl/plugins/errludattributeP.H:plugins/ \ obj/genfiles/plugins/errludtarget.H:plugins/ \ $(addsuffix :plugins/,\ $(call ROOTPATH_WILDCARD,obj/genfiles/plugins/hbfwSrcParse*.C)) \ diff --git a/src/build/mkrules/gcov.env.mk b/src/build/mkrules/gcov.env.mk index 8ddcd3ef6..edce52a24 100644 --- a/src/build/mkrules/gcov.env.mk +++ b/src/build/mkrules/gcov.env.mk @@ -5,7 +5,9 @@ # # OpenPOWER HostBoot Project # -# COPYRIGHT International Business Machines Corp. 2013,2014 +# Contributors Listed Below - COPYRIGHT 2013,2019 +# [+] International Business Machines Corp. +# # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -26,21 +28,44 @@ # Configuration of the GCOV settings. GCOVDIR = $(ROOTPATH)/obj/gcov +vpath %.C $(ROOTPATH)/src/sys/prof ifdef MODULE -GCOVNAME = $(MODULE).lcov + +# Don't profile HBRT modules to keep size down +ifdef HOSTBOOT_RUNTIME +HOSTBOOT_PROFILE= +endif + +## We don't want certain modules to be profiled (HBB, HBRT). + +# This is replacing spaces with colons so that we can get an exact +# match on the module name in the list of unprofilable modules with +# findstring, which otherwise would find matches on "partial" +# substrings (i.e. we don't want to deprofile module ABC just because +# module ABCD is blacklisted, so we create a blacklist of modules +# separated by colons and search for :ABC:). +null := +MODULE_PROFILE_BLACKLIST:=:$(subst ${null} ${null},:,$(BASE_MODULES_GCOV_BLACKLIST) $(RUNTIME_MODULES_GCOV_BLACKLIST)): + +ifneq (,$(findstring :$(MODULE):,$(MODULE_PROFILE_BLACKLIST))) +HOSTBOOT_PROFILE= +endif + +GCOVNAME := $(MODULE).lcov + ifndef TESTS ifdef HOSTBOOT_PROFILE -vpath %.C $(ROOTPATH)/src/sys/prof OBJS := gcov.o $(OBJS) endif endif else -GCOVNAME = $(notdir $(shell pwd)).lcov +GCOVNAME := $(notdir $(shell pwd)).lcov endif -## Disable coverage on test cases, any directory that sets -## HOSTBOOT_PROFILE_NO_INSTRUMENT or any file that has 'gcov' in the name. +## Disable coverage on test cases or any directory that sets +## HOSTBOOT_PROFILE_NO_INSTRUMENT + ifndef TESTS ifdef HOSTBOOT_PROFILE ifndef HOSTBOOT_PROFILE_NO_INSTRUMENT @@ -59,5 +84,16 @@ endif ## Reduce the optimization level when profiling is enabled to ensure the ## base image fits in 512k still. ifdef HOSTBOOT_PROFILE -OPT_LEVEL = -Os +# We're not doing this right now because it causes linker errors in +# various parts of hostboot with or without gcov (i.e. functions that +# the code relies on being inlined are not; some const statics that +# aren't defined in a compilation unit have linker references, etc.) +# and it also causes the image to be generated incorrectly (symbol +# names are wrong, calls to functions named things like __savegpr_rXX +# are emitted but the functions themselves aren't and so you end up +# jumping into an area of zeroes, ...). We should come back to this +# later and fix, we might be able to profile more of hostboot with the +# space savings that -Os could give. + +#OPT_LEVEL = -Os endif diff --git a/src/build/mkrules/hbfw/img/makefile b/src/build/mkrules/hbfw/img/makefile index 269a52ce5..114cb6384 100755 --- a/src/build/mkrules/hbfw/img/makefile +++ b/src/build/mkrules/hbfw/img/makefile @@ -65,6 +65,7 @@ SBEI_OBJPATH = ${HBFW_OBJPATH:S/hbfw\/img/sbei\/sbfw\/img/g} ENGD_WOFPATH = ${HBFW_OBJPATH:S/hbfw\/img/engd\/wofdata/g} ENGD_MEMDPATH = ${HBFW_OBJPATH:S/hbfw\/img/engd\/memd/g} HBFW_SIMPATH = ${HBFW_OBJPATH:S/img/simics/g} +EDITED_LAYOUT_PATH = ${DUMMY:!pwd!} ################################################# # Copy Hostboot binary images to obj dir to be grabbed # during build flash pass and consumption by HWSV. @@ -113,7 +114,6 @@ TESTRO_FINAL_IMG = TESTRO.bin TESTLOAD_FINAL_IMG = TESTLOAD.bin HBEL_FINAL_IMG = HBEL.bin GUARD_FINAL_IMG = GUARD.bin -GLOBAL_FINAL_IMG = GLOBAL.bin DJVPD_FINAL_IMG = DJVPD.bin MVPD_FINAL_IMG = MVPD.bin CVPD_FINAL_IMG = CVPD.bin @@ -126,7 +126,7 @@ EECACHE_FINAL_IMG = EECACHE.bin OCMBFW_FINAL_IMG = OCMBFW.bin FINAL_OUTPUT_IMAGES = ${HBBL_FINAL_IMG} ${HBB_FINAL_IMG} ${HBI_FINAL_IMG} \ ${HBRT_FINAL_IMG} ${TEST_FINAL_IMG} ${TESTRO_FINAL_IMG} \ - ${HBEL_FINAL_IMG} ${GUARD_FINAL_IMG} ${GLOBAL_FINAL_IMG} \ + ${HBEL_FINAL_IMG} ${GUARD_FINAL_IMG} \ ${DJVPD_FINAL_IMG} ${MVPD_FINAL_IMG} ${CVPD_FINAL_IMG} \ ${PAYLOAD_FINAL_IMG} ${RINGOVD_FINAL_IMG} ${SBKT_FINAL_IMG} \ ${FIRDATA_FINAL_IMG} ${MEMD_FINAL_IMG} ${EECACHE_FINAL_IMG} \ @@ -214,26 +214,28 @@ BUILD_TYPE_PARAMS = --build-type fspbuild .endif # Decide which images to use for each PNOR layout -GEN_COMMON_BIN_FILES = HBBL=${HBBL_IMG},HBB=${HBB_IMG},HBI=${HBI_IMG},HBRT=${HBRT_IMG},HBEL=EMPTY,GUARD=EMPTY,GLOBAL=EMPTY,MVPD=EMPTY,RINGOVD=EMPTY,SBKT=EMPTY +GEN_COMMON_BIN_FILES = HBBL=${HBBL_IMG},HBB=${HBB_IMG},HBI=${HBI_IMG},HBRT=${HBRT_IMG},HBEL=EMPTY,GUARD=EMPTY,RINGOVD=EMPTY,SBKT=EMPTY GEN_STANDALONE_BIN_FILES = ${GEN_COMMON_BIN_FILES},TEST=EMPTY,TESTRO=EMPTY,TESTLOAD=EMPTY,PAYLOAD=EMPTY,FIRDATA=EMPTY .if (${FAKEPNOR} == "") # Parameters passed into GEN_PNOR_IMAGE_SCRIPT. .if (${PNOR_LAYOUT_SELECTED} == "STANDALONE") - GEN_DEFAULT_BIN_FILES = ${GEN_STANDALONE_BIN_FILES},MEMD=${${ZZ_MEMD_IMG}:P},CVPD=EMPTY,DJVPD=EMPTY + GEN_DEFAULT_BIN_FILES = ${GEN_STANDALONE_BIN_FILES},MEMD=${${ZZ_MEMD_IMG}:P},CVPD=EMPTY,DJVPD=EMPTY,MVPD=EMPTY .elif(${PNOR_LAYOUT_SELECTED} == "AXONE") - GEN_DEFAULT_BIN_FILES = ${GEN_STANDALONE_BIN_FILES},EECACHE=EMPTY,MEMD=${${ZZ_MEMD_IMG}:P},OCMBFW=${${OCMBFW_IMG}:P} + GEN_DEFAULT_BIN_FILES = ${GEN_STANDALONE_BIN_FILES},EECACHE=EMPTY,OCMBFW=${${OCMBFW_IMG}:P} .else - GEN_DEFAULT_BIN_FILES = ${GEN_COMMON_BIN_FILES},MEMD=${${ZZ_MEMD_IMG}:P},CVPD=EMPTY,DJVPD=EMPTY + GEN_DEFAULT_BIN_FILES = ${GEN_COMMON_BIN_FILES},MEMD=${${ZZ_MEMD_IMG}:P},CVPD=EMPTY,DJVPD=EMPTY,MVPD=EMPTY .endif DEFAULT_PARAMS = --build-all --emit-eccless ${TARGET_TEST:b--test} ${HB_STANDALONE:b--hb-standalone} \ ${CONFIG_SECUREBOOT:b--secureboot} --systemBinFiles ${GEN_DEFAULT_BIN_FILES} \ --pnorLayout ${PNOR_LAYOUT} ${KEY_TRANSITION_PARAMS} ${CORRUPT_PARAMS} \ - --hwKeyHashFile ${IMPRINT_HW_KEY_HASH} + --hwKeyHashFile ${IMPRINT_HW_KEY_HASH} \ + --editedLayoutLocation ${EDITED_LAYOUT_PATH} .else PNOR_LAYOUT = ${pnorLayoutFake.xml:P} # Parameters passed into GEN_PNOR_IMAGE_SCRIPT. GEN_DEFAULT_BIN_FILES = HBI=${HBI_IMG},HBEL=EMPTY,MVPD=${${VPO_FAKE_MVPD}:P},DJVPD=${${VPO_FAKE_DJVPD}:P},FIRDATA=EMPTY,MEMD=EMPTY - DEFAULT_PARAMS = --systemBinFiles ${GEN_DEFAULT_BIN_FILES} --pnorLayout ${PNOR_LAYOUT} + DEFAULT_PARAMS = --systemBinFiles ${GEN_DEFAULT_BIN_FILES} --pnorLayout ${PNOR_LAYOUT} \ + --editedLayoutLocation ${EDITED_LAYOUT_PATH} .endif # rule to update hostboot image tags for custom CFM image, only enabled @@ -375,7 +377,6 @@ AXONE_HCODE_IMG = ${ENGD_SRCPATH:Fp9a.hw_ref_image.bin} CUMULUS_CENHWIMG_IMG = ${ENGD_SRCPATH:Fcen.hw_ref_image.bin} NIMBUS_CENHWIMG_IMG = cen.hw_ref_image.bin.fake -AXONE_CENHWIMG_IMG = cen.hw_ref_image.bin.fake NIMBUS_OCC_IMG = ${bb}/images/ppc/lab/fs/p9le/rootfs/opt/extucode/81e00430.lid CUMULUS_OCC_IMG = ${bb}/images/ppc/lab/fs/p9le/rootfs/opt/extucode/81e00430.lid AXONE_OCC_IMG = ${bb}/images/ppc/lab/fs/p9le/rootfs/opt/extucode/81e00430.lid @@ -389,6 +390,8 @@ ZEPPELIN_MEMD_IMG = ${ENGD_MEMDPATH:Fzeppelin_memd_output.dat} FLEETWOOD_MEMD_IMG = ${ENGD_MEMDPATH:Ffleetwood_memd_output.dat} ZZ_HBD_IMG = ${HBFW_TARGPATH:FZZ_hb_targeting.bin} ZZ2U_HBD_IMG = ${HBFW_TARGPATH:FZZ-2U_hb_targeting.bin} +ZZGEN4_HBD_IMG = ${HBFW_TARGPATH:FZZ-GEN4_hb_targeting.bin} +ZZ2UGEN4_HBD_IMG = ${HBFW_TARGPATH:FZZ-2U-GEN4_hb_targeting.bin} ZEPPELIN_HBD_IMG = ${HBFW_TARGPATH:FZEPPELIN_hb_targeting.bin} # Create list of images for each node (in node order) # genPnorImages will handle multiple HBD=binfile pairs @@ -409,7 +412,6 @@ CUMULUS_HCODE_FINAL_IMG = CUMULUS.HCODE.bin AXONE_HCODE_FINAL_IMG = AXONE.HCODE.bin CUMULUS_CENHWIMG_FINAL_IMG = CUMULUS.CENHWIMG.bin NIMBUS_CENHWIMG_FINAL_IMG = NIMBUS.CENHWIMG.bin -AXONE_CENHWIMG_FINAL_IMG = AXONE.CENHWIMG.bin NIMBUS_SBE_FINAL_IMG = NIMBUS.SBE.bin CUMULUS_SBE_FINAL_IMG = CUMULUS.SBE.bin AXONE_SBE_FINAL_IMG = AXONE.SBE.bin @@ -428,7 +430,8 @@ ZZ_HBD_FINAL_IMG = ZZ.HBD.bin ZEPPELIN_HBD_FINAL_IMG = ZEPPELIN.HBD.bin FLEETWOOD_HBD_FINAL_IMGS = FLEETWOOD.HBD_NODE_0.bin,FLEETWOOD.HBD_NODE_1.bin,FLEETWOOD.HBD_NODE_2.bin,FLEETWOOD.HBD_NODE_3.bin,FLEETWOOD_MST.HBD_NODE_0.bin,FLEETWOOD_2N.HBD_NODE_0.bin,FLEETWOOD_2N.HBD_NODE_1.bin,FLEETWOOD_2N.HBD_NODE_2.bin,FLEETWOOD_2N.HBD_NODE_3.bin ZZ2U_HBD_FINAL_IMG = ZZ-2U.HBD.bin - +ZZGEN4_HBD_FINAL_IMG = ZZ-GEN4.HBD.bin +ZZ2UGEN4_HBD_FINAL_IMG = ZZ-2U-GEN4.HBD.bin # Decide which PNOR to build @@ -438,18 +441,20 @@ ZZ2U_HBD_FINAL_IMG = ZZ-2U.HBD.bin GEN_NIMBUS_BIN_FILES = NIMBUS:SBE=${${NIMBUS_SBE_IMG}:P},HCODE=${${NIMBUS_HCODE_IMG}:P},OCC=${${NIMBUS_OCC_IMG}:P},HBD=${${NIMBUS_HBD_IMG}:P},CENHWIMG=${NIMBUS_CENHWIMG_IMG} GEN_CUMULUS_BIN_FILES = CUMULUS:SBE=${${CUMULUS_SBE_IMG}:P},HCODE=${${CUMULUS_HCODE_IMG}:P},OCC=${${CUMULUS_OCC_IMG}:P},HBD=${${CUMULUS_HBD_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P} GEN_CUMULUS_CDIMM_BIN_FILES = CUMULUS_CDIMM:SBE=${${CUMULUS_SBE_IMG}:P},HCODE=${${CUMULUS_HCODE_IMG}:P},OCC=${${CUMULUS_OCC_IMG}:P},HBD=${${CUMULUS_CDIMM_HBD_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P} - GEN_AXONE_BIN_FILES = AXONE:SBE=${${AXONE_SBE_IMG}:P},HCODE=${${AXONE_HCODE_IMG}:P},OCC=${${AXONE_OCC_IMG}:P},HBD=${${AXONE_HBD_IMG}:P},CENHWIMG=${AXONE_CENHWIMG_IMG} + GEN_AXONE_BIN_FILES = AXONE:SBE=${${AXONE_SBE_IMG}:P},HCODE=${${AXONE_HCODE_IMG}:P},OCC=${${AXONE_OCC_IMG}:P},HBD=${${AXONE_HBD_IMG}:P} .else GEN_NIMBUS_BIN_FILES = NIMBUS:SBE=${${NIMBUS_SBE_IMG}:P},HCODE=${${NIMBUS_HCODE_IMG}:P},OCC=${${NIMBUS_OCC_IMG}:P},HBD=${${NIMBUS_HBD_IMG}:P},CENHWIMG=${NIMBUS_CENHWIMG_IMG} GEN_CUMULUS_BIN_FILES = CUMULUS:SBE=${${CUMULUS_SBE_IMG}:P},HCODE=${${CUMULUS_HCODE_IMG}:P},OCC=${${CUMULUS_OCC_IMG}:P},HBD=${${CUMULUS_HBD_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P} GEN_CUMULUS_CDIMM_BIN_FILES = CUMULUS_CDIMM:SBE=${${CUMULUS_SBE_IMG}:P},HCODE=${${CUMULUS_HCODE_IMG}:P},OCC=${${CUMULUS_OCC_IMG}:P},HBD=${${CUMULUS_CDIMM_HBD_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P} - GEN_AXONE_BIN_FILES = AXONE:SBE=${${AXONE_SBE_IMG}:P},HCODE=${${AXONE_HCODE_IMG}:P},OCC=${${AXONE_OCC_IMG}:P},HBD=${${AXONE_HBD_IMG}:P},CENHWIMG=${AXONE_CENHWIMG_IMG} + GEN_AXONE_BIN_FILES = AXONE:SBE=${${AXONE_SBE_IMG}:P},HCODE=${${AXONE_HCODE_IMG}:P},OCC=${${AXONE_OCC_IMG}:P},HBD=${${AXONE_HBD_IMG}:P} .endif GEN_ZZ_BIN_FILES = ZZ:WOFDATA=${${ZZ_WOFDATA_IMG}:P},MEMD=${${ZZ_MEMD_IMG}:P},HBD=${${ZZ_HBD_IMG}:P} GEN_ZEPPELIN_BIN_FILES = ZEPPELIN:WOFDATA=${${ZEPPELIN_WOFDATA_IMG}:P},MEMD=${${ZEPPELIN_MEMD_IMG}:P},HBD=${${ZEPPELIN_HBD_IMG}:P} GEN_FLEETWOOD_BIN_FILES = FLEETWOOD:WOFDATA=${${FLEETWOOD_WOFDATA_IMG}:P},MEMD=${${FLEETWOOD_MEMD_IMG}:P},${FLEETWOOD_HBD_IMGS} GEN_ZZ2U_BIN_FILES = ZZ-2U:WOFDATA=${${ZZ_WOFDATA_IMG}:P},MEMD=${${ZZ_MEMD_IMG}:P},HBD=${${ZZ2U_HBD_IMG}:P} + GEN_ZZGEN4_BIN_FILES = ZZ-GEN4:WOFDATA=${${ZZ_WOFDATA_IMG}:P},MEMD=${${ZZ_MEMD_IMG}:P},HBD=${${ZZGEN4_HBD_IMG}:P} + GEN_ZZ2UGEN4_BIN_FILES = ZZ-2U-GEN4:WOFDATA=${${ZZ_WOFDATA_IMG}:P},MEMD=${${ZZ_MEMD_IMG}:P},HBD=${${ZZ2UGEN4_HBD_IMG}:P} SYSTEM_SPECIFIC_PARAMS = --install-all --emit-eccless ${TARGET_TEST:b--test} ${CONFIG_SECUREBOOT:b--secureboot} \ --pnorLayout ${PNOR_LAYOUT} ${CORRUPT_PARAMS} ${HB_STANDALONE:b--hb-standalone} \ @@ -461,18 +466,22 @@ ZZ2U_HBD_FINAL_IMG = ZZ-2U.HBD.bin --systemBinFiles ${GEN_ZEPPELIN_BIN_FILES} \ --systemBinFiles ${GEN_FLEETWOOD_BIN_FILES} \ --systemBinFiles ${GEN_ZZ2U_BIN_FILES} \ - --hwKeyHashFile ${IMPRINT_HW_KEY_HASH} + --systemBinFiles ${GEN_ZZGEN4_BIN_FILES} \ + --systemBinFiles ${GEN_ZZ2UGEN4_BIN_FILES} \ + --hwKeyHashFile ${IMPRINT_HW_KEY_HASH} \ + --editedLayoutLocation ${EDITED_LAYOUT_PATH} .else # Parameters passed into GEN_PNOR_IMAGE_SCRIPT. GEN_NIMBUS_BIN_FILES = NIMBUS:HCODE=${${NIMBUS_HCODE_IMG}:P},HBD=${${NIMBUS_VPO_HBD_IMG}:P},CENHWIMG=EMPTY GEN_CUMULUS_BIN_FILES = CUMULUS:HCODE=${${CUMULUS_HCODE_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P} GEN_CUMULUS_CDIMM_BIN_FILES = CUMULUS:HCODE=${${CUMULUS_HCODE_IMG}:P},CENHWIMG=${${CUMULUS_CENHWIMG_IMG}:P} - GEN_AXONE_BIN_FILES = AXONE:HCODE=${${AXONE_HCODE_IMG}:P},HBD=${${AXONE_VPO_HBD_IMG}:P},CENHWIMG=EMPTY + GEN_AXONE_BIN_FILES = AXONE:HCODE=${${AXONE_HCODE_IMG}:P},HBD=${${AXONE_VPO_HBD_IMG}:P} SYSTEM_SPECIFIC_PARAMS = --pnorLayout ${PNOR_LAYOUT} \ --systemBinFiles ${GEN_NIMBUS_BIN_FILES} \ --systemBinFiles ${GEN_CUMULUS_BIN_FILES} \ --systemBinFiles ${GEN_AXONE_BIN_FILES} \ - --systemBinFiles ${GEN_CUMULUS_CDIMM_BIN_FILES} + --systemBinFiles ${GEN_CUMULUS_CDIMM_BIN_FILES} \ + --editedLayoutLocation ${EDITED_LAYOUT_PATH} .endif gen_system_specific_images_bypass_cache : dump-secureboot-config @@ -493,14 +502,14 @@ gen_system_specific_images: build_sbe_partitions .PMAKE .if (${PNOR_LAYOUT_SELECTED} == "FSP") - HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},GLOBAL=${GLOBAL_FINAL_IMG},MVPD=${MVPD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG} + HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG} .else - HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},TEST=${TEST_FINAL_IMG},TESTRO=${TESTRO_FINAL_IMG},TESTLOAD=${TESTLOAD_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},GLOBAL=${GLOBAL_FINAL_IMG},PAYLOAD=${PAYLOAD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG},FIRDATA=${FIRDATA_FINAL_IMG} + HOSTBOOT_DEFAULT_SECTIONS = HBBL=${HBBL_FINAL_IMG},HBB=${HBB_FINAL_IMG},HBI=${HBI_FINAL_IMG},HBRT=${HBRT_FINAL_IMG},TEST=${TEST_FINAL_IMG},TESTRO=${TESTRO_FINAL_IMG},TESTLOAD=${TESTLOAD_FINAL_IMG},HBEL=${HBEL_FINAL_IMG},GUARD=${GUARD_FINAL_IMG},PAYLOAD=${PAYLOAD_FINAL_IMG},RINGOVD=${RINGOVD_FINAL_IMG},SBKT=${SBKT_FINAL_IMG},FIRDATA=${FIRDATA_FINAL_IMG} .endif -NIMBUS_SECT = HBD=${NIMBUS_HBD_FINAL_IMG},SBE=${NIMBUS_SBE_FINAL_IMG},HCODE=${NIMBUS_HCODE_FINAL_IMG},OCC=${NIMBUS_OCC_FINAL_IMG},WOFDATA=${ZZ_WOFDATA_FINAL_IMG},CENHWIMG=${NIMBUS_CENHWIMG_FINAL_IMG},MEMD=${ZZ_MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG} -CUMULUS_SECT = HBD=${CUMULUS_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${ZEPPELIN_MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG} -CUMULUS_CDIMM_SECT = HBD=${CUMULUS_CDIMM_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG} -AXONE_SECT = HBD=${AXONE_HBD_FINAL_IMG},SBE=${AXONE_SBE_FINAL_IMG},HCODE=${AXONE_HCODE_FINAL_IMG},OCC=${AXONE_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${AXONE_CENHWIMG_FINAL_IMG},EECACHE=${EECACHE_FINAL_IMG},FIRDATA=${FIRDATA_FINAL_IMG},MEMD=${MEMD_FINAL_IMG},OCMBFW=${OCMBFW_FINAL_IMG} +NIMBUS_SECT = HBD=${NIMBUS_HBD_FINAL_IMG},SBE=${NIMBUS_SBE_FINAL_IMG},HCODE=${NIMBUS_HCODE_FINAL_IMG},OCC=${NIMBUS_OCC_FINAL_IMG},WOFDATA=${ZZ_WOFDATA_FINAL_IMG},CENHWIMG=${NIMBUS_CENHWIMG_FINAL_IMG},MEMD=${ZZ_MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG} +CUMULUS_SECT = HBD=${CUMULUS_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${ZEPPELIN_MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG} +CUMULUS_CDIMM_SECT = HBD=${CUMULUS_CDIMM_HBD_FINAL_IMG},SBE=${CUMULUS_SBE_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},OCC=${CUMULUS_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG},MEMD=${MEMD_FINAL_IMG},CVPD=${CVPD_FINAL_IMG},DJVPD=${DJVPD_FINAL_IMG},MVPD=${MVPD_FINAL_IMG} +AXONE_SECT = HBD=${AXONE_HBD_FINAL_IMG},SBE=${AXONE_SBE_FINAL_IMG},HCODE=${AXONE_HCODE_FINAL_IMG},OCC=${AXONE_OCC_FINAL_IMG},WOFDATA=${ZEPPELIN_WOFDATA_FINAL_IMG},EECACHE=${EECACHE_FINAL_IMG},FIRDATA=${FIRDATA_FINAL_IMG},OCMBFW=${OCMBFW_FINAL_IMG} .if (${PNOR_LAYOUT_SELECTED} == "AXONE") @@ -525,7 +534,7 @@ PNOR_IMG_INFO = \ NIMBUS_SECT = HBD=${NIMBUS_HBD_FINAL_IMG},HCODE=${NIMBUS_HCODE_FINAL_IMG},CENHWIMG=${NIMBUS_CENHWIMG_FINAL_IMG} CUMULUS_SECT = HBD=${CUMULUS_HBD_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG} CUMULUS_CDIMM_SECT = HBD=${CUMULUS_CDIMM_HBD_FINAL_IMG},HCODE=${CUMULUS_HCODE_FINAL_IMG},CENHWIMG=${CUMULUS_CENHWIMG_FINAL_IMG} - AXONE_SECT = HBD=${AXONE_HBD_FINAL_IMG},HCODE=${AXONE_HCODE_FINAL_IMG},CENHWIMG=${AXONE_CENHWIMG_FINAL_IMG} + AXONE_SECT = HBD=${AXONE_HBD_FINAL_IMG},HCODE=${AXONE_HCODE_FINAL_IMG} PNOR_IMG_INFO = \ ${FAKEPNOR}:${PNOR_LAYOUT}:${NIMBUS_SECT}:${CUMULUS_SECT}:${CUMULUS_CDIMM_SECT},${HOSTBOOT_DEFAULT_SECTIONS},${AXONE_SECT} \ ${FIPS_PNOR_INFO} @@ -562,7 +571,8 @@ ${IMAGE_TARGET}: ${IMAGE_LAYOUT} ${IMAGE_BINS} ${PNOR_BUILD_SCRIPT} ${FAKEPNOR} == ${IMAGE_TARGET}) ${PNOR_BUILD_SCRIPT} --pnorOutBin ${IMAGE_TARGET} \ ${TARGET_TEST:b--test} --pnorLayout ${IMAGE_LAYOUT} \ - ${IMAGE_BIN_OPTION} --fpartCmd "fpart" --fcpCmd "fcp" + ${IMAGE_BIN_OPTION} --fpartCmd "fpart" --fcpCmd "fcp" \ + --editedLayoutLocation ${EDITED_LAYOUT_PATH} .endif .endif diff --git a/src/build/mkrules/images.rules.mk b/src/build/mkrules/images.rules.mk index 2a611b030..c6b863d89 100644 --- a/src/build/mkrules/images.rules.mk +++ b/src/build/mkrules/images.rules.mk @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2013,2017 +# Contributors Listed Below - COPYRIGHT 2013,2019 # [+] International Business Machines Corp. # # @@ -27,14 +27,49 @@ # Description: # Rules for linking the Hostboot binary images using the custom linker. +# Folder to store *.objdump files in +OBJDUMP_FOLDER := $(IMGDIR)/objdump + +# Clean up after ourselves +clean: clean-objdump + +.PHONY: clean-objdump +clean-objdump: + $(C2) " MAKE objdump CLEAN" + $(C1)rm -rf $(OBJDUMP_FOLDER) + ifdef IMGS _IMGS = $(addprefix $(IMGDIR)/, $(IMGS)) IMAGES += $(addsuffix .bin, $(_IMGS)) $(addsuffix .elf, $(_IMGS)) +ifdef BUILD_FAST +OBJDUMP_MODULES := $(sort $(foreach img, $(IMGS), $($(img)_MODULES) $($(img)_EXTENDED_MODULES))) + +OBJDUMP_BIN_TARGETS := $(addsuffix .elf.objdump, $(IMGS)) +OBJDUMP_LIB_TARGETS := $(addsuffix .so.objdump, $(OBJDUMP_MODULES)) + +OBJDUMP_TARGETS := $(addprefix $(OBJDUMP_FOLDER)/lib, $(OBJDUMP_LIB_TARGETS)) +OBJDUMP_TARGETS += $(addprefix $(OBJDUMP_FOLDER)/, $(OBJDUMP_BIN_TARGETS)) + +# Tell make not to delete our objdumps +.SECONDARY: $(OBJDUMP_TARGETS) +endif + IMAGE_PASS_POST += $(addsuffix .list.bz2, $(_IMGS)) $(addsuffix .syms, $(_IMGS)) CLEAN_TARGETS += $(addsuffix .list.bz2, $(_IMGS)) $(addsuffix .syms, $(_IMGS)) CLEAN_TARGETS += $(addsuffix .lnkout.bz2, $(addprefix $(IMGDIR)/., $(IMGS))) +$(OBJDUMP_FOLDER): + mkdir -p $@ + +$(OBJDUMP_FOLDER)/%.so.objdump: $(IMGDIR)/%.so $(OBJDUMP_FOLDER) + $(C2) " OBJDUMP $(notdir $*)" + $(C1)$(OBJDUMP) -dCS -j .text -j .data -j .rodata $< | bzip2 >$@ + +$(OBJDUMP_FOLDER)/%.elf.objdump: $(IMGDIR)/%.elf $(OBJDUMP_FOLDER) + $(C2) " OBJDUMP $(notdir $*)" + $(C1)$(OBJDUMP) -dCS -j .text -j .data -j .rodata $< | bzip2 >$@ + define ELF_template $$(IMGDIR)/$(1).elf: $$(addprefix $$(OBJDIR)/, $$($(1)_OBJECTS)) \ $$(ROOTPATH)/src/$$($(1)_LDFILE) @@ -63,7 +98,7 @@ $(IMGDIR)/%.bin: $(IMGDIR)/%.elf \ | bzip2 -zc > $(IMGDIR)/.$*.lnkout.bz2' $(C1)$(ROOTPATH)/src/build/tools/addimgid $@ $< -$(IMGDIR)/%.list.bz2 $(IMGDIR)/%.syms: $(IMGDIR)/%.bin +$(IMGDIR)/%.list.bz2 $(IMGDIR)/%.syms: $(IMGDIR)/%.bin $(OBJDUMP_TARGETS) $(C2) " GENLIST $(notdir $*)" $(C1)(cd $(ROOTPATH)&& \ src/build/linker/gensyms $*.bin \ diff --git a/src/build/simics/standalone.simics b/src/build/simics/standalone.simics index 39a382303..c785dfc44 100755 --- a/src/build/simics/standalone.simics +++ b/src/build/simics/standalone.simics @@ -9,10 +9,17 @@ if not defined hb_skip_vpd_preload {$hb_skip_vpd_preload = 0} if ($hb_mode == 0) { # Axone and beyond - # this number is no longer provided we have to look it up - $num_dimms = (dec (list-length((get-master-procs)[0].get-dimms))) + # There is no VPD cache on Axone + $hb_skip_vpd_preload = 1; } +# Load up the pnor parsing function +try { + add-directory $hb_pnor_dir + run-python-file (lookup-file simpnor.py) + echo "Loaded simpnor.py" +} except { "No simpnor.py found, using hardcoding PNOR offsets." } + # Preload VPD in PNOR unless told not to if ($hb_skip_vpd_preload == 0) { @@ -24,8 +31,7 @@ if ($hb_skip_vpd_preload == 0) { $procChipType=(get-object-list p9_proc)[0]->chip_type python "os.environ['HB_PROC_CHIP_TYPE'] = \""+$procChipType+"\"" } else { - $procChipType=($hb_masterproc)->chip_type - python "os.environ['HB_PROC_CHIP_TYPE'] = \""+$procChipType+"\"" + python "os.environ['HB_PROC_CHIP_TYPE'] = \""+$proc_chip_type+"\"" } @@ -54,6 +60,36 @@ if ($hb_skip_vpd_preload == 0) { } except { echo "ERROR: Failed to preload VPD into PNOR." } } +if ($hb_mode == 0) { + $eccPreload = (lookup-file "%simics%/eecache_prebuilt.bin.ecc") + # NOTE must change offset if PNOR layout changes EECACHE offsets + echo " - Loading prebuilt EECACHE "+$eccPreload+" at 0x2C000 in PNOR" + ($hb_pnor).load-file $eccPreload 0x2C000 +} + +# Look for attribute overrides to load +try { + $attr_tmp = (lookup-file "ATTR_TMP") + try { + @simenv.attr_tmp_addr = hb_get_pnor_offset("ATTR_TMP") + } except { + $attr_tmp_addr = 0x000B2000 + } + echo " - Loading ATTR_TMP "+$attr_tmp+" at "+$attr_tmp_addr+" in PNOR" + ($hb_pnor).load-file $attr_tmp $attr_tmp_addr +} except { echo "No attribute overrides found." } + +# Look for a guard file to load +try { + $guard = (lookup-file "GUARD") + try { + @simenv.guard_addr = hb_get_pnor_offset("GUARD") + } except { + $guard_addr = 0x000AC000 + } + echo " - Loading GUARD "+$guard+" at "+$guard_addr+" in PNOR" + ($hb_pnor).load-file $guard $guard_addr +} except { echo "No gard records found." } # Turn on all processor cec-chips if ($hb_mode == 1) { @@ -108,3 +144,51 @@ if ($hb_mode == 1) { ($hb_masterproc_cecchip).invoke parallel_store FSIMBOX 0x01 "80000000" 32 ($hb_masterproc_cecchip).invoke parallel_store FSIMBOX 0x08 "00080000" 32 } + +############################### +#Initialize Explorer Registers +############################### +if ($hb_mode == 0) { #Only do this on Axone and later models that have Explorer chip + + # IDEC register consumed by Hostboot + # UCHIP(0x2134)=0x110600D2 + # TODO RTC: 215621 Remove workarounds after simics gets updated + set-class-attr ocmb mscc_regs_xcbi_chip_info 0x110600D2 + + # Loop over all explorer chips + foreach $obj in (get-object-list ocmb -all){ + + # RAM1 image ID consumed by Hostboot + # UCHIP(0x2200)=0x00000000 + $obj->mscc_regs_xcbi_ram1[0] = 0x00000000 + + # RAM1 hash value registers consumed by Hostboot + # This matches the hash of zero-filled 4k file. + $obj->mscc_regs_xcbi_ram1[1] = 0x2D23913D + $obj->mscc_regs_xcbi_ram1[2] = 0x3759EF01 + $obj->mscc_regs_xcbi_ram1[3] = 0x704A86B4 + $obj->mscc_regs_xcbi_ram1[4] = 0xBEE3AC8A + $obj->mscc_regs_xcbi_ram1[5] = 0x29002313 + $obj->mscc_regs_xcbi_ram1[6] = 0xECC98A74 + $obj->mscc_regs_xcbi_ram1[7] = 0x24425A78 + $obj->mscc_regs_xcbi_ram1[8] = 0x170F2195 + $obj->mscc_regs_xcbi_ram1[9] = 0x77822FD7 + $obj->mscc_regs_xcbi_ram1[10] = 0x7E4AE963 + $obj->mscc_regs_xcbi_ram1[11] = 0x13547696 + $obj->mscc_regs_xcbi_ram1[12] = 0xAD7D5949 + $obj->mscc_regs_xcbi_ram1[13] = 0xB58E12D5 + $obj->mscc_regs_xcbi_ram1[14] = 0x063EF2EE + $obj->mscc_regs_xcbi_ram1[15] = 0x063B5957 + $obj->mscc_regs_xcbi_ram1[16] = 0x40A3A12D + + # Allow for testing MMIO HW failures + # Forces write access to TRACE_TRDATA_CONFIG_0 to fail + # in src/usr/mmio/test/mmiotest.H + # NOTE: address is left shifted 3 and has MMIO + # offset (0x100000000) added. + $obj->mmio_regs_mmioerr = 0x0000000140082018 + + } +} + + diff --git a/src/build/simics/startup.simics b/src/build/simics/startup.simics index a6534be01..440e9562b 100755 --- a/src/build/simics/startup.simics +++ b/src/build/simics/startup.simics @@ -48,7 +48,8 @@ if ($hb_mode == 1) { } }else{ - $hb_machine = "AXONE" + # simics now provides us the chip type (starting w/ p9a ) + $hb_machine = $proc_chip_type } python "os.environ['HB_MACHINE'] = \""+$hb_machine+"\"" @@ -98,9 +99,9 @@ if ($hb_mode == 1) { ($cc).seeprom3.seeprom3_image.set 0x3FED9 0x5A5A5A5A 8 -l } } else { - foreach $cc in (get-object-list proc_hb_standalone) { - ($cc).seeprom1_image.set 0x3FED9 0x5A5A5A5A 8 -l - ($cc).seeprom3_image.set 0x3FED9 0x5A5A5A5A 8 -l + foreach $proc in (get-all-procs) { + ($proc.get-seeprom 1).set 0x3FED9 0x5A5A5A5A 8 -l + ($proc.get-seeprom 3).set 0x3FED9 0x5A5A5A5A 8 -l } } @@ -112,6 +113,7 @@ try { run-python-file (lookup-file hbfw/hb-simdebug.py) } except { echo "ERROR: Failed to load Hostboot debug tools (hb-simdebug.py)" } + # Determine security state $hw_security=(shell "echo $SECURITY_HW_POLICY") if($hw_security == "") { @@ -133,13 +135,27 @@ if($hw_security == "1") { $jumperApplied=FALSE } -# Load jumper state to each processor -foreach $procX in (get-object-list p9_proc) { - +if ($hb_machine == "p9a") { # Set logical jumper state in SIMICS based on HW policy # "TRUE"=jumper applied(security disabled, default) # "FALSE"=jumper removed(security enabled) - (($procX)->secure_jumper=$jumperApplied) + + # Load jumper state to the master processor + $hb_masterproc.set-secure-jumper value = $jumperApplied + + # Load jumper state to all slave processors + foreach $procS in ($hb_masterproc.get-slave-procs) { + $procS.set-secure-jumper value = $jumperApplied + } +} else { + # Load jumper state to each processor + foreach $procX in (get-object-list p9_proc) { + + # Set logical jumper state in SIMICS based on HW policy + # "TRUE"=jumper applied(security disabled, default) + # "FALSE"=jumper removed(security enabled) + (($procX)->secure_jumper=$jumperApplied) + } } if ($hb_mode == 0) { diff --git a/src/build/tools/addCopyright b/src/build/tools/addCopyright index 81e871010..1a172a49b 100755 --- a/src/build/tools/addCopyright +++ b/src/build/tools/addCopyright @@ -96,6 +96,9 @@ use constant LICENSE_PROLOG => "LICENSE_PROLOG"; # When adding a new company add constant here and to %fileContributorsCompany use constant IBM => 'International Business Machines Corp.'; use constant GOOGLE => 'Google Inc.'; +use constant INSPUR => 'Inspur Power Systems Corp.'; +use constant SUPERMICRO => 'Super Micro Computer, Inc.'; +use constant YADRO => 'YADRO'; # Create mapping for git contrubitors to companies my %fileContributorsCompany = ( @@ -103,6 +106,9 @@ my %fileContributorsCompany = ( "ozlabs.org" => IBM, "google.com" => GOOGLE, "Google Shared Technology" => GOOGLE, + "inspur.com" => INSPUR, + "supermicro.com" => SUPERMICRO, + "yadro.com" => YADRO, ); #------------------------------------------------------------------------------ diff --git a/src/build/tools/build-cppcheck b/src/build/tools/build-cppcheck new file mode 100755 index 000000000..8e19ed429 --- /dev/null +++ b/src/build/tools/build-cppcheck @@ -0,0 +1,95 @@ +#!/bin/bash -e +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/tools/build-cppcheck $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2019 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +source $PROJECT_ROOT/src/build/citest/etc/cppcheck + +update_toolconfig(){ + echo "commit: $CPPCHECK_COMMIT" + echo "gcc version: $(gcc -dumpversion)" + echo "S: $(uname -o)" + echo "arch: $(uname -m)" + echo "$(lsb_release -i)" + echo "$(lsb_release -r)" +} + +if [ -n "${OPENPOWER_BUILD}" ]; then + exit +fi + +cd $PROJECT_ROOT/src/build/tools + +if [[ ! -d "cpptools" ]]; then + mkdir cpptools +fi + +cd cpptools +if [[ ! -d "cppcheck" ]]; then + # cppcheck folder does not exist, clone repo for the first time + git clone git@github.com:danmar/cppcheck.git + cd cppcheck + git reset --hard $CPPCHECK_COMMIT #update to cppcheck commit + update_toolconfig >.cpp_toollevel + SHOULDMAKE=1 +else + cd cppcheck + if ! cmp -s .cpp_toollevel <(update_toolconfig) ; then + # cppcheck repo is not at the + # level set in $PROJECT_ROOT/src/build/citest/etc/cppcheck + if ! git fetch origin; then + cd $PROJECT_ROOT/src/build/tools/cpptools + rm -rf cppcheck + git clone git@github.com:danmar/cppcheck.git + cd cppcheck + fi + git reset --hard $CPPCHECK_COMMIT + update_toolconfig >.cpp_toollevel + + SHOULDMAKE=1 + fi + if [[ ! -f "cppcheck" ]]; then + SHOULDMAKE=1 + fi +fi + +if [ "${SHOULDMAKE}" ]; then + + # Check if CXX is set, if it is not then try to find it with CXXPATH + # if CXXPATH does not exist, default to host's g++ + if [ -z "$CXX" ]; then + if [ -z "${CXXPATH}" ]; then + export CXX=g++ + else + export CXX=${CXXPATH}/g++ + fi + fi + + make + +fi + +cd $PROJECT_ROOT + + diff --git a/src/build/tools/cflags.sh b/src/build/tools/cflags.sh new file mode 100755 index 000000000..0ca39f374 --- /dev/null +++ b/src/build/tools/cflags.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/tools/cflags.sh $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2019 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +# The purpose of this script is to convert a series of GCC compiler +# flags into an equivalent series of flags, but which use absolute +# paths for include directories (i.e. the "-I" flag) instead of +# relative paths. We have to do this when GCOV is in use, because it +# stupidly puts data files in one path but stores paths inside the +# data files that are relative to some other path. When GCOV then +# tries to read the source files via these relative paths, it can't +# find the files. We correct this by converting all paths to source +# and header files to absolute paths. + +if [ ! "$HOSTBOOT_PROFILE" ] ; then + echo "$@" + exit +fi + +make_path_abs () { + local ABSPATH + ABSPATH=$(readlink -f "$1") + + if [ $? -ne 0 ] ; then + ABSPATH="$1" + fi + + echo -n "$ABSPATH" +} + +while [ "$#" -gt 0 ] ; do + FLAG="$1" + + if [ "$FLAG" = "-I" ] ; then + shift + echo -n "-I $(make_path_abs "$1") " + elif [ "${FLAG:0:2}" = "-I" ] ; then + echo -n "-I $(make_path_abs "${FLAG:2}") " + else + echo -n "$FLAG " + fi + + shift +done + +echo diff --git a/src/build/tools/eecache_editor.pl b/src/build/tools/eecache_editor.pl new file mode 100755 index 000000000..262f56376 --- /dev/null +++ b/src/build/tools/eecache_editor.pl @@ -0,0 +1,802 @@ +#!/usr/local/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/tools/eecache_editor.pl $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2019 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +use strict; +use Getopt::Long; +use File::Copy; + + +binmode STDOUT, ':bytes'; + +my $pnorBinaryPath = ""; +my $eecacheBinaryPath = ""; +my $newImagePath = ""; +my $outFilePath = "./eecache_editor_output.dat"; +my $masterHuid = 0; +my $port = 0; +my $engine = 0; +my $devAddr = 0; +my $muxHuid = 0; +my $muxSelect = 0xFF; +my $eepromSize = 0; +my $usage = 0; +my $uniqueId = ""; +my $verbose = 0; +my $onlyValid = 0; +my $clearEepromData = 0; +my $overwrite = 0; +my $summary = 0; +my $devOffset = 0xFFFF; # initialized to invalid offset + +# Goals of this tool: +# +# ** Handle both entire PNOR image as well as single EECACHE section as input ** +# +# 1) Given masterHuid, port, engine, devAddr, muxSelect lookup cached EEPROM value and replace +# it with a given binary file. (File size must be <= allocated space) +# +# 2) Given a binary pnor/eecache. Print summary of cached eeproms +# +# 3) Zero out a given cached eeprom +# +# 4) Extract the contents for a given masterHuid, port, engine, devAddr, muxSelect + +use constant VERSION_1_TOC_ENTRY_SIZE_BYTES => 17; +use constant VERSION_1_TOC_ENTRY_SIZE_BITS => (VERSION_1_TOC_ENTRY_SIZE_BYTES * 8) ; +use constant VERSION_1_NUM_ENTRIES => 50; +use constant VERSION_1_TOC_SIZE => (VERSION_1_TOC_ENTRY_SIZE_BYTES * VERSION_1_NUM_ENTRIES) + 5; + +use constant VERSION_2_TOC_ENTRY_SIZE_BYTES => 18; +use constant VERSION_2_TOC_ENTRY_SIZE_BITS => (VERSION_2_TOC_ENTRY_SIZE_BYTES * 8) ; +use constant VERSION_2_NUM_ENTRIES => 50; +use constant VERSION_2_TOC_SIZE => (VERSION_2_TOC_ENTRY_SIZE_BYTES * VERSION_2_NUM_ENTRIES) + 5; + +use constant VERSION_LATEST => 2; + +use constant EEPROM_ACCESS_I2C => 1; +use constant EEPROM_ACCESS_SPI => 2; + + + +my $eecacheVersion = VERSION_LATEST; + +GetOptions("pnor:s" => \$pnorBinaryPath, + "eecache:s" => \$eecacheBinaryPath, + "newImage:s" => \$newImagePath, + "newFile:s" => \$newImagePath, + "out:s" => \$outFilePath, + "of:s" => \$outFilePath, + "masterHuid:o" => \$masterHuid, + "port:o" => \$port, + "engine:o" => \$engine, + "devAddr:o" => \$devAddr, + "muxSelect:o" => \$muxSelect, + "eepromSize:o" => \$eepromSize, + "uniqueId:s" => \$uniqueId, + "devOffset:o" => \$devOffset, + "version:o" => \$eecacheVersion, + "onlyValid" => \$onlyValid, + "overwrite" => \$overwrite, + "clear" => \$clearEepromData, + "verbose" => \$verbose, + "usage" => \$usage, + "help" => \$usage, + "h" => \$usage); + +sub print_help() +{ + print "--------- EECACHE Editor Tool V 2.0 ---------\n"; + print "\n"; + print "Mandatory:\n\n"; + + print " --eecache Path to ECC-less eeprom cache section of PNOR (IE : EECACHE.bin )\n\n"; + + print "Optional:\n\n"; + + print " --clear If a matching eeprom is found, clear out its contents\n"; + print " --devAddr Device address of desired EEPROM\n"; + print " --devOffset Offset (KB) of where record begins in eeprom for SPI access\n"; + print " --engine Engine of I2C/SPI Master desired EEPROM exists on\n"; + print " --masterHuid HUID of the I2C/SPI Master Target\n"; + print " --muxSelect Mux Select (if needed) defaults to 0xFF \n"; + print " --onlyValid If printing summary, only print valid eeprom caches\n"; + print " --out Full path to desired out file, if not provided defaults to ./eecache_editor_output.dat\n"; + print " --port Port of I2C Master desired EEPROM exists on\n"; + print " --uniqueId Combination of unique I2C Slave information, alternative to passing\n"; + print " information in 1 thing at a time\n"; + print " --version Version of eecache (default to latest if this isn't provided)\n"; + print " --verbose Print extra information \n"; + print " --help Print this information \n"; + print "\n "; + print "Examples: \n\n"; + print " # prints out info about all eeproms in EECACHE.bin\n"; + print " eecache_editor.pl --eecache EECACHE.bin\n"; + print "\n"; + print " # (I2C) lookup eeprom matching input params and write contents of that EEPROM's cached data to outfile \n"; + print " eecache_editor.pl --eecache EECACHE.bin --version 1 --port 0 --engine 3 --muxSelect 8 --devAddr 0xa0 --masterHuid 0x50000\n"; + print "\n"; + print " # (I2C) lookup eeprom matching input params and clear the contents ( manipulate input binary )\n"; + print " eecache_editor.pl --eecache EECACHE.bin --port 0 --engine 3 --muxSelect 8 --devAddr 0xa0 --masterHuid 0x50000 --clear\n"; + print "\n"; + print " # (I2C) lookup eeprom matching input params and write new image's contents to offset in EECACHE where matching eeprom data exists ( manipulate input binary )\n"; + print " eecache_editor.pl --eecache EECACHE.bin --port 0 --engine 3 --muxSelect 8 --devAddr 0xa0 --masterHuid 0x50000 --newImage newSPD.dat\n"; + print "\n"; + print " # (SPI) lookup eeprom matching input params and write contents of that EEPROM's cached data to outfile \n"; + print " eecache_editor.pl --eecache EECACHE.bin --engine 3 --devOffset 0xc0 --masterHuid 0x50000\n"; + print "\n"; + print " # (SPI) lookup eeprom matching input params and clear the contents ( manipulate input binary )\n"; + print " eecache_editor.pl --eecache EECACHE.bin --engine 3 --devOffset 0xc0 --masterHuid 0x50000 --clear\n"; + print "\n"; + print " # (SPI) lookup eeprom matching input params and write new image's contents to offset in EECACHE where matching eeprom data exists ( manipulate input binary )\n"; + print " eecache_editor.pl --eecache EECACHE.bin --engine 3 --devOffset 0xc0 --masterHuid 0x50000 --newImage newSPD.dat\n"; + print "---------------------------------------------\n"; +} + +if( $usage ) +{ + print_help(); + exit 0; +} + +if( ($pnorBinaryPath eq "") && + ($eecacheBinaryPath eq "")) +{ + # Print error saying we need one of these filled in + print "ERROR Neither PNOR binary nor EECACHE section binary passed in. Cannot continue.\n\n"; + print_help(); + exit 0; +} + +# if PNOR is not empty, ignore eecacheBinary , we will +# output a full updated pnor since we were provided a pnor. +# but if no pnor is provided , we will just return and EECACHE sections +my $inputIsEntirePnor = 0; +if( $pnorBinaryPath ne "") +{ + $inputIsEntirePnor = 1; +} + +if($newImagePath ne "") +{ + $overwrite = 1; +} + +if ($eecacheVersion > VERSION_LATEST) +{ + print "ERROR: --version $eecacheVersion is greater than max ".VERSION_LATEST."\n\n"; + print_help(); + exit 0; +} + +if ($uniqueId eq "") +{ + if ($eecacheVersion == VERSION_LATEST) + { + # devOffset is specific to SPI access so check to see if it is valid + if ($devOffset != 0xFFFF) + { + $uniqueId = sprintf ("%.02X", EEPROM_ACCESS_SPI); + $uniqueId .= sprintf ("%.08X", $masterHuid); + $uniqueId .= sprintf ("%.02X", $engine); + $uniqueId .= sprintf ("%.04X", $devOffset); + $uniqueId .= "00"; # blank byte + } + else + { + $uniqueId = sprintf ("%.02X", EEPROM_ACCESS_I2C); + $uniqueId .= sprintf ("%.08X", $masterHuid); + $uniqueId .= sprintf ("%.02X", $port); + $uniqueId .= sprintf ("%.02X", $engine); + $uniqueId .= sprintf ("%.02X", $devAddr); + $uniqueId .= sprintf ("%.02X", $muxSelect); + } + } + elsif ($eecacheVersion == 1) + { + $uniqueId .= sprintf ("%.08X", $masterHuid); + $uniqueId .= sprintf ("%.02X", $port); + $uniqueId .= sprintf ("%.02X", $engine); + $uniqueId .= sprintf ("%.02X", $devAddr); + $uniqueId .= sprintf ("%.02X", $muxSelect); + } +} + +my $displayOnly = 0; + +unless (isUniqueIdValid($uniqueId)) +{ + if( $clearEepromData ) + { + print_help(); + print "\n ERROR: Detecting that user is trying to --clear data without providing what info on what eeprom to clear. Exiting. \n\n"; + exit 0; + } + $displayOnly = 1; + $verbose = 1; +} +else +{ + print "\nUnique ID we are looking up: 0x$uniqueId \n\n" ; +} + +# setup input and output files +my $input_fh; +my $output_fh; + +my $new_fh; + +if($inputIsEntirePnor) +{ + open $input_fh, '<', $pnorBinaryPath or die "failed to open $pnorBinaryPath: $!\n"; + if($overwrite) + { + open $output_fh, '>', $pnorBinaryPath or die "failed to open $pnorBinaryPath: $!\n"; + } + else + { + open $output_fh, '>', $outFilePath or die "failed to open $outFilePath: $!\n"; + } +} +else +{ + open $input_fh, '+<:raw', $eecacheBinaryPath or die "failed to open $eecacheBinaryPath: $!\n"; + if($overwrite) + { + $output_fh = $input_fh; + } + else + { + open $output_fh, '+>:raw', $outFilePath or die "failed to open $outFilePath: $!\n"; + copy($eecacheBinaryPath, $outFilePath) ; + } +} + +if($newImagePath ne "") +{ + open $new_fh, '<', $newImagePath or die "failed to open $newImagePath: $!\n"; +} + + + +# at this point we should know what we are trying to accomplish : +# +# IF ($displayOnly != 0) THEN we will only print a summary +# +# ELSE IF ($newImagePath != "") THEN we will write new contents if matching section found +# +# ELSE IF ($clear != 0) THEN clear the contents if matching section found +# +# ELSE if matching section found, then write contents to outfile + + + +# TODO handle entire PNOR +if($inputIsEntirePnor) +{ + #find EECACHE offset , seek to there +} +else +{ + # Parse the larger binary blob to get just the Table of Contents + my $eecacheTOC = readEecacheToc($input_fh); + + # The hashRef you key back has members: offset and size + # This represents offset and size of eeprom data in given + # binary. + my $hashRef = parseEecacheToc($eecacheTOC, $uniqueId); + + # if we are doing displayOnly then we are done, we can skip the following logic + if(!$displayOnly) + { + # If the offset is 0, then no match was found + if($hashRef->{'entry_offset'} != 0) + { + if($newImagePath ne "") # if a new image is available try to load it in + { + my $new_file_size = -s $newImagePath ; + my $new_file_data; + read($new_fh, $new_file_data, $new_file_size ); + + # Verify the new image is the correct size + if( $new_file_size != $hashRef->{'entry_size'}) + { + print "ERROR incorrect size, EECACHE is reporting size to be".$hashRef->{'entry_size'}."bytes but file proved is only".$new_file_size." bytes\n"; + exit 0; + } + + # seek to the offset inside EEACHE where this eeprom's cache lives + # and write the new file contents + seek($output_fh, $hashRef->{'entry_offset'} , 0); + print $output_fh $new_file_data; + } + elsif($clearEepromData) # if we are told to clear the data do that + { + print "Attempting Clearing starting at $hashRef->{'entry_offset'} $hashRef->{'header_offset'}!!!!!!!!\n"; + my $byteOfOnes = pack("H2", "FF") ; + my $byteOfZeroes = pack("H2", "00") ; + seek($output_fh, $hashRef->{'entry_offset'} , 0); + for(my $i = 0; $i < $hashRef->{'entry_size'}; $i++) + { + print $output_fh $byteOfOnes; + } + + # seek($output_fh, $hashRef->{'header_offset'} + 16, 0); + # print $output_fh $byteOfZeroes; + } + else + { + seek($input_fh, $hashRef->{'entry_offset'} , 0); + my $cur_pos = tell $input_fh; + print "reading $hashRef->{'entry_size'} from $cur_pos\n "; + my $cachedData; + read($input_fh, $cachedData, $hashRef->{'entry_size'}); + print $output_fh $cachedData; + } + } + } +} + +close $input_fh; +close $output_fh; + +# End of Main +exit 0; + + +# Start Subroutines + +sub readEecacheToc { + my $eecache_fh = shift; + + my $start_location = tell $eecache_fh; + + my $eecache_toc_version = 0; + + read($eecache_fh, $eecache_toc_version, 1) == 1 or die "failed to read single byte from eecache file handle"; + $eecache_toc_version = unpack 'C', $eecache_toc_version; + + my $eecache_toc; + + if( $eecache_toc_version == 1 ) + { + seek($eecache_fh, $start_location, 0); + read($eecache_fh, $eecache_toc, VERSION_1_TOC_SIZE) or die "failed to read ".VERSION_1_TOC_SIZE." bytes from eecache file handle"; ; + } + elsif ( $eecache_toc_version == 2) + { + seek($eecache_fh, $start_location, 0); + read($eecache_fh, $eecache_toc, VERSION_2_TOC_SIZE) or die "failed to read ".VERSION_2_TOC_SIZE." bytes from eecache file handle"; ; + } + else + { + die "Failed to find valid TOC, version found = $eecache_toc_version. Latest version this tool supports is ".VERSION_LATEST; + } + + return $eecache_toc; +} + +# Brief : Takes in binary blob representing EECACHE table of contents, as well as +# a uniqueID to match against, returns hash that contains size and offset of +# cached eeprom data inside EEACHE section +# +# If verbose is set, + +sub parseEecacheToc { + my $eecacheTOC = shift; + my $idToMatch = shift; + + # figure out what version of EECACHE header exists + my $headerVersion = 0; + my $tocEntrySizeBytes = 0; + my $tocEntries = 0; + + my ($version) = unpack('H2', "$eecacheTOC"); + if ($version == 0x01) + { + $headerVersion = 1; + $tocEntrySizeBytes = VERSION_1_TOC_ENTRY_SIZE_BYTES; + $tocEntries = VERSION_1_NUM_ENTRIES; + } + elsif ($version == 0x02) + { + $headerVersion = 2; + $tocEntrySizeBytes = VERSION_2_TOC_ENTRY_SIZE_BYTES; + $tocEntries = VERSION_2_NUM_ENTRIES; + } + else + { + die "Unsupported PNOR EECACHE level $version"; + } + + # verify uniqueId was built against same version as PNOR's EECACHE + if (isUniqueIdValid($uniqueId)) + { + unless (($headerVersion == $eecacheVersion)) + { + die "PNOR EECACHE version $headerVersion is not same as expected EECACHE version $eecacheVersion!" . + "Maybe changed expected with --version option"; + } + } + + # header entries start after on 6th byte + my $headerEntryOffset = 5; + + # this will end up being the return value + my %entryInfo; + $entryInfo{entry_offset} = 0; + $entryInfo{entry_size} = 0; + $entryInfo{header_offset} = 0; + + my $totalEntryCount = 0; + my $validEntryCount = 0; + + my $matchSummaryString = ""; + + # Some common variables between header versions + my $internal_offset = 0xFFFF; + my $cached_copy_valid = 0; + my $cached_copy_size = 0; + my $entry_size = 0; + my $entry_offset = 0; + my $bitFieldByte = 0; # last byte of header + my $entryUniqueID = "FFFFFFFFFFFFFFFF"; + + use Class::Struct; + + struct I2C_Entry_t => { + i2c_master_huid => '$', + port => '$', + engine => '$', + devAddr => '$', + mux_select => '$', + }; + + struct SPI_Entry_t => { + spi_master_huid => '$', + engine => '$', + offset_KB => '$', + }; + + for(my $i = 0; $i < $tocEntries; $i++) + { + my $eepromAccess = EEPROM_ACCESS_I2C; + my $master_eeprom = 0xFF; # default to invalid master eeprom + + my $entry = substr $eecacheTOC, $headerEntryOffset, $tocEntrySizeBytes; + + # update offset right away so we dont forget + $headerEntryOffset += $tocEntrySizeBytes; + my $entry_data; + + if ($headerVersion == 1) + { + ###### VERSION 1 ######## + # struct completeRecord + # { + # uint32_t i2c_master_huid; // HUID of i2c Master + # uint8_t port; // I2C Port + # uint8_t engine; // I2C Engine + # uint8_t devAddr; // I2C Device Address + # uint8_t mux_select; // Some I2C devices are behind a mux, this says + # // what setting on the mux is required + # uint32_t cache_copy_size; // Size of data saved in cache (in KB) + # uint32_t internal_offset; // offset from start of EECACHE section where cached + # // data exists + # uint8_t cached_copy_valid : 1, // This bit is set when we think the contents of the + # // cache is valid. + # unused : 7; + # + # } PACKED completeRecord; + # + # struct uniqueRecord + # { + # uint8_t uniqueID [NUM_BYTE_UNIQUE_ID]; + # uint8_t metaData [sizeof(completeRecord) - NUM_BYTE_UNIQUE_ID]; + # } PACKED uniqueRecord; + + # unpack according to src/include/usr/i2c/eeprom_const.H ( pasted above) + my @entryFields = unpack('H8 H2 H2 H2 H2 H8 H8 H2', "$entry"); + + $entryUniqueID = "@entryFields[0]@entryFields[1]@entryFields[2]@entryFields[3]@entryFields[4]"; + $eepromAccess = EEPROM_ACCESS_I2C; + $entry_data = I2C_Entry_t->new(); + $entry_data->i2c_master_huid( @entryFields[0] ); + $entry_data->port ( @entryFields[1] ); + $entry_data->engine ( @entryFields[2] ); + $entry_data->devAddr ( @entryFields[3] ); + $entry_data->mux_select ( @entryFields[4] ); + $bitFieldByte = @entryFields[7]; + $cached_copy_valid = (hex( "0x".@entryFields[7]) & 0x80) >> 7; + + + # if the entry ID is FFFFFFFFFFFFFFFF this indicates + # that the entry is not filled out + if($entryUniqueID == "FFFFFFFFFFFFFFFF") + { + next; + } + $cached_copy_size = @entryFields[5]; + $internal_offset = @entryFields[6]; + } + elsif ($headerVersion == 2) + { + ###### VERSION 2 ######## + # struct completeRecord + # { + # EepromAccessMethodType accessType; // how to access record + # union eepromAccess_t + # { + # struct i2cAccess_t + # { + # uint32_t i2c_master_huid; // HUID of i2c Master + # uint8_t port; // I2C Port + # uint8_t engine; // I2C Engine + # uint8_t devAddr; // I2C Device Address + # uint8_t mux_select; // Some I2C devices are behind a mux, this says + # // what setting on the mux is required + # } PACKED i2cAccess; + # struct spiAccess_t + # { + # uint32_t spi_master_huid; // HUID of SPI master + # uint8_t engine; // engine specific to eeprom + # uint16_t offset_KB; // offset in KB of where record begins in eeprom + # } PACKED spiAccess; + # } PACKED eepromAccess; + # uint32_t cache_copy_size; // Size of data saved in cache (in KB) + # uint32_t internal_offset; // offset from start of EECACHE section where cached + # // data exists + # uint8_t cached_copy_valid : 1, // This bit is set when we think the contents of the + # // cache is valid. + # master_eeprom : 1, // This bit marks this record as the master one (i.e. look at this one for change) + # unused : 6; + # + # } PACKED completeRecord; + # + # struct uniqueRecord + # { + # uint8_t uniqueID [NUM_BYTE_UNIQUE_ID]; + # uint8_t metaData [sizeof(completeRecord) - NUM_BYTE_UNIQUE_ID]; + # } PACKED uniqueRecord; + + ($eepromAccess) = unpack('H2', "$entry"); + if ($eepromAccess == EEPROM_ACCESS_I2C) + { + # unpack according to src/include/usr/i2c/eeprom_const.H ( pasted above) + my @entryFields = unpack('H2 H8 H2 H2 H2 H2 H8 H8 H2', "$entry"); + + $entryUniqueID = "@entryFields[0]@entryFields[1]@entryFields[2]@entryFields[3]@entryFields[4]@entryFields[5]"; + + $entry_data = I2C_Entry_t->new(); + $entry_data->i2c_master_huid( @entryFields[1] ); + $entry_data->port( @entryFields[2] ); + $entry_data->engine( @entryFields[3] ); + $entry_data->devAddr( @entryFields[4] ); + $entry_data->mux_select( @entryFields[5] ); + + $cached_copy_size = @entryFields[6]; + $internal_offset = @entryFields[7]; + + $bitFieldByte = @entryFields[8]; + $cached_copy_valid = (hex("0x".@entryFields[8]) & 0x80) >> 7; + $master_eeprom = (hex("0x".@entryFields[8]) & 0x40) >> 6; + } + elsif ($eepromAccess == EEPROM_ACCESS_SPI) + { + # unpack according to src/include/usr/i2c/eeprom_const.H ( pasted above) + my @entryFields = unpack('H2 H8 H2 H4 H2 H8 H8 H2', "$entry"); + + $entryUniqueID = "@entryFields[0]@entryFields[1]@entryFields[2]@entryFields[3]00"; + + $entry_data = SPI_Entry_t->new(); + $entry_data->spi_master_huid( @entryFields[1] ); + $entry_data->engine( @entryFields[2] ); + $entry_data->offset_KB( @entryFields[3] ); + + # @entryField[4] is just filler + + $cached_copy_size = @entryFields[5]; + $internal_offset = @entryFields[6]; + + $bitFieldByte = @entryFields[7]; + $cached_copy_valid = (hex("0x".@entryFields[7]) & 0x80) >> 7; + $master_eeprom = (hex("0x".@entryFields[7]) & 0x40) >> 6; + } + else + { + # entry is not filled out if eepromAccess is not I2C or SPI + next; + } + } + + $totalEntryCount++; + + if(uc $entryUniqueID eq uc $idToMatch) + { + $entryInfo{entry_offset} = $internal_offset; + $entryInfo{entry_size} = $cached_copy_size * 1024; # KB to Bytes + $entryInfo{header_offset} = $headerEntryOffset - $tocEntrySizeBytes; + + $matchSummaryString = "ENTRY FOUND ...\n"; + if ($eepromAccess == EEPROM_ACCESS_I2C) + { + if ($headerVersion >= 2) + { + $matchSummaryString .= + "accessType = 0x".$eepromAccess." I2C ACCESS\n"; + } + $matchSummaryString .= + "Master I2C Huid = 0x". $entry_data->i2c_master_huid ."\n". + "Port = 0x". $entry_data->port ."\n". + "Engine = 0x". $entry_data->engine ."\n". + "Device Address = 0x". $entry_data->devAddr ."\n". + "Mux Select = 0x". $entry_data->mux_select ."\n". + "Size of Cached Copy (KB) = 0x$cached_copy_size\n". + "Offset within EECACHE = 0x$internal_offset\n". + "Cached copy valid ? = 0x$cached_copy_valid (1st bit of 0x$bitFieldByte)\n"; + } + else # EEPROM_ACCESS_SPI + { + if ($headerVersion >= 2) + { + $matchSummaryString .= + "accessType = 0x".$eepromAccess." SPI ACCESS\n"; + } + $matchSummaryString .= + "Master SPI Huid = 0x". $entry_data->spi_master_huid ."\n". + "Engine = 0x". $entry_data->engine ."\n". + "Offset in EEPROM = 0x". $entry_data->offset_KB ."\n". + "Size of Cached Copy (KB) = 0x$cached_copy_size\n". + "Offset within EECACHE = 0x$internal_offset\n". + "Cached copy valid ? = $cached_copy_valid (1st bit of 0x$bitFieldByte)\n"; + } + if ($master_eeprom != 0xFF) + { + $matchSummaryString .= + "EEPROM master ? = $master_eeprom (2nd bit of 0x$bitFieldByte)\n"; + } + $matchSummaryString .= + "unique ID = 0x$entryUniqueID \n\n"; + + if(!$verbose) + { + last; + } + } + + if( !$cached_copy_valid ) + { + # skip if this entry is not valid and told to just + # print valid only entries + if($onlyValid) + { + next; + } + } + else + { + $validEntryCount++; + } + + my $entryString = ""; + if ($eepromAccess == EEPROM_ACCESS_I2C) + { + if ($headerVersion >= 2) + { + $entryString .= + "accessType = 0x".$eepromAccess." I2C ACCESS\n"; + } + $entryString .= + "Master I2C Huid = 0x". $entry_data->i2c_master_huid ."\n". + "Port = 0x". $entry_data->port ."\n". + "Engine = 0x". $entry_data->engine ."\n". + "Device Address = 0x". $entry_data->devAddr ."\n". + "Mux Select = 0x". $entry_data->mux_select ."\n". + "Size of Cached Copy (KB) = 0x$cached_copy_size\n". + "Offset within EECACHE = 0x$internal_offset\n". + "Cached copy valid ? = $cached_copy_valid (1st bit of 0x$bitFieldByte)\n"; + } + else + { + if ($headerVersion >= 2) + { + $entryString .= + "accessType = 0x".$eepromAccess." SPI ACCESS\n"; + } + $entryString .= + "Master SPI Huid = 0x". $entry_data->spi_master_huid ."\n". + "Engine = 0x". $entry_data->engine ."\n". + "Offset in EEPROM = 0x". $entry_data->offset_KB ."\n". + "Size of Cached Copy (KB) = 0x$cached_copy_size\n". + "Offset within EECACHE = 0x$internal_offset\n". + "Cached copy valid ? = $cached_copy_valid (1st bit of 0x$bitFieldByte)\n"; + } + + if ($master_eeprom != 0xFF) + { + $entryString .= + "EEPROM master ? = $master_eeprom (2nd bit of 0x$bitFieldByte)\n"; + } + $entryString .= + "unique ID = 0x$entryUniqueID \n\n"; + + printVerbose($entryString); + } + + printVerbose( + "Summary :\n". + " Total Entry Count : $totalEntryCount \n". + " Valid Entry Count : $validEntryCount \n". + " Max Possible Entries : $tocEntries\n\n"); + + if($matchSummaryString ne "") + { + print $matchSummaryString; + } + else + { + # Skip failure message if not looking for a unique id match + if (isUniqueIdValid($uniqueId)) + { + print "No Match Found! \n\n"; + } + } + + return \%entryInfo; +} + + +sub findEepromRecordOffset { + + + +} + +sub printVerbose { + + my $string = shift; + + if($verbose) + { + print $string; + } +} + +sub isUniqueIdValid +{ + my ($uniqueId) = @_; + + if( (($eecacheVersion == 1) && ($uniqueId == "00000000000000FF")) || + (($eecacheVersion == 2) && ($uniqueId == "0100000000000000FF")) || + (($eecacheVersion == 2) && ($uniqueId == "020000000000000000")) ) + { + return 0; + } + else + { + return 1; + } +} + diff --git a/src/build/tools/hb b/src/build/tools/hb index 9576adb0f..9e7e38a48 100755 --- a/src/build/tools/hb +++ b/src/build/tools/hb @@ -39,6 +39,7 @@ execute_in_sandbox() echo $1 > ${SANDBOXBASE}/src/sandbox_execute_cmd chmod 700 ${SANDBOXBASE}/src/sandbox_execute_cmd + echo "Sandbox :: $1" ${WORKON_CMD} -c ./sandbox_execute_cmd @@ -356,14 +357,16 @@ hb_simsetup() DRIVER=`cat ${PROJECT_ROOT}/src/build/citest/etc/bbuild` SIMICS_LEVEL=`cat ${PROJECT_ROOT}/src/build/citest/etc/simbuild` + EECACHE_PREBUILT=`cat ${PROJECT_ROOT}/src/build/citest/etc/eecache_prebuilt` needs_machine_variable if [ "${MACHINE}" == "AXONE" ]; then - echo "mkdir -p ${SANDBOXBASE}/simics" execute_in_sandbox "mkdir -p ${SANDBOXBASE}/simics" "ppc" - echo "tar ${SIMICS_LEVEL} -C ${SANDBOXBASE}/simics/" execute_in_sandbox "tar -xf ${SIMICS_LEVEL} -C ${SANDBOXBASE}/simics/" "ppc" + echo "cd ${SANDBOXBASE}/simics/ && ./INSTALL.sh" execute_in_sandbox "cd ${SANDBOXBASE}/simics/ && ./INSTALL.sh" "ppc" + echo "cp ${EECACHE_PREBUILT} ${SANDBOXBASE}/simics/eecache_prebuilt.bin.ecc" + execute_in_sandbox "cp ${EECACHE_PREBUILT} ${SANDBOXBASE}/simics/eecache_prebuilt.bin.ecc" "ppc" else execute_in_sandbox "start_simics -no_start -machine ${MACHINE}" "ppc" fi @@ -424,8 +427,19 @@ hb_startsimics() #export MYDIR=$bb/obj/ppc/hbfw/simics/startup.simics #then /runsim -m axone -o hb_script_to_run=$MYDIR export MY_DIR="${SANDBOXBASE}/obj/ppc/simu/scripts/hbfw" - echo "cd ${SANDBOXBASE}/simics/ && ./runsim -m ${MACHINE} hb_script_to_run=${MY_DIR}/startup.simics pnor_img=${MY_DIR}/../../../hbfw/img/axone.pnor sbe_seeprom_img=${SANDBOXBASE}/images/ppc/lab/flash/sbe_seeprom_p9a_10.bin.ecc num_procs=1 vpd_proc=vpd/images/99a8c3fe4e5c74798f5bd4212f3d9a2a" - execute_in_sandbox "cd ${SANDBOXBASE}/simics/ && ./runsim -m ${MACHINE} hb_script_to_run=${MY_DIR}/startup.simics pnor_img=${MY_DIR}/../../../hbfw/img/axone.pnor sbe_seeprom_img=${SANDBOXBASE}/images/ppc/lab/flash/sbe_seeprom_p9a_10.bin.ecc num_procs=1 vpd_proc=vpd/images/99a8c3fe4e5c74798f5bd4212f3d9a2a" "ppc" + # If '-nre' was passed in as a flag, then do not vexec + # also, if $POOL is defined, this indicates are already in + # a vexec shell so do not vexec + if [ "$*" = "-nre" ] || [ ! -z ${POOL} ]; then + VEXEC_STR=" vexec" + else + VEXEC_STR="" + fi + export RUNSIMCMD="cd ${SANDBOXBASE}/simics/ &&${VEXEC_STR} ./runsim -m ${MACHINE} hb_script_to_run=${MY_DIR}/startup.simics pnor_img=${MY_DIR}/../../../hbfw/img/axone.pnor sbe_seeprom_img=${SANDBOXBASE}/images/ppc/lab/flash/sbe_seeprom_p9a_10.bin.ecc num_procs=2 enable_lpc_console=TRUE hb_pnor_dir=${MY_DIR}/../../../hbfw/img/" + echo "**********" + echo $RUNSIMCMD + echo "**********" + execute_in_sandbox "${RUNSIMCMD} ${SIMICSOPTIONS}" "ppc" else execute_in_sandbox \ "start_simics -machine ${MACHINE} ${SIMICSOPTIONS} $*" "ppc" diff --git a/src/build/tools/listdeps.pl b/src/build/tools/listdeps.pl index 9bad71ef9..2eaf7a6ad 100755 --- a/src/build/tools/listdeps.pl +++ b/src/build/tools/listdeps.pl @@ -229,6 +229,7 @@ my $resident_modules = { "libexpaccess.so" => '1', "libnvdimm.so" => '1', "libmmio.so" => '1', + "libsmf.so" => '1', }; # A list of the dependent libraries in each istep. diff --git a/src/build/tools/pre-commit b/src/build/tools/pre-commit index 3dc621bb3..ccf02b80a 100755 --- a/src/build/tools/pre-commit +++ b/src/build/tools/pre-commit @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # @@ -6,7 +6,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2011,2017 +# Contributors Listed Below - COPYRIGHT 2011,2019 # [+] International Business Machines Corp. # # @@ -35,3 +35,48 @@ else echo "For more info run './hb --help'" exit -1 fi + +# Run cppcheck if variable is set, if not exit here +if [[ $DOCPPCHECK -ne 1 ]]; then + exit 0 +fi + +echo "Running CPPCHECK" + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # This is the hash of the default empty tree in Git. + # If for some reason HEAD is not set, then diff'ing against this is like + # diff'ing against the very first commit. + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +${TOOLSDIR}/build-cppcheck +CPPCHECKTOOL=${TOOLSDIR}/cpptools/cppcheck/cppcheck +CPPCHECKFLAGS="--inline-suppr --error-exitcode=1" +CPPCHECK=" ${CPPCHECKTOOL} ${CPPCHECKFLAGS}" + +for file in $(git diff-index --cached $against | \ + grep -E '[MA].*\.(C|c|cpp|cc|cxx)$' | cut -f 2) +do + + dir="$(dirname $file)" + filename="$(basename $file)" + + # TODO RTC 215692 + # The following command checks for cppcheck errors. All cppcheck errors are + # printed to the terminal and stored to a file .${filename}.cppcheck. + set -o pipefail && cd ${dir} && timeout 2m ${CPPCHECK} $filename 2>&1 | tee .${filename}.cppcheck; exit_code=$?; \ + if [ "$exit_code" -ne 1 ]; then \ + # If exit code does not equal 1 (which is the error code when a cppcheck + # error is found) delete the created .cppcheck file. + # Note that time-out fails with error code 127. + rm -f .${filename}.cppcheck; \ + fi + cd $PROJECT_ROOT + +done + +exit 0 |