diff options
Diffstat (limited to 'src/build/buildpnor')
-rw-r--r-- | src/build/buildpnor/PnorUtils.pm | 134 | ||||
-rw-r--r-- | src/build/buildpnor/bpm-utils/LICENSE_PROLOG | 24 | ||||
-rw-r--r-- | src/build/buildpnor/bpm-utils/imageCrc.c | 479 | ||||
-rwxr-xr-x | src/build/buildpnor/bpm-utils/insertBpmFwCrc.py | 191 | ||||
-rwxr-xr-x | src/build/buildpnor/buildBpmFlashImages.pl | 878 | ||||
-rwxr-xr-x | src/build/buildpnor/buildpnor.pl | 11 | ||||
-rw-r--r-- | src/build/buildpnor/defaultPnorLayout.xml | 36 | ||||
-rwxr-xr-x | src/build/buildpnor/genPnorImages.pl | 68 | ||||
-rwxr-xr-x | src/build/buildpnor/memd_creation.pl | 2 | ||||
-rwxr-xr-x | src/build/buildpnor/pkgOcmbFw.pl | 7 | ||||
-rw-r--r-- | src/build/buildpnor/pnorLayoutAxone.xml | 91 | ||||
-rw-r--r-- | src/build/buildpnor/pnorLayoutFSP.xml | 30 |
12 files changed, 1794 insertions, 157 deletions
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/> |