diff options
Diffstat (limited to 'src/build/buildpnor/bpm-utils')
-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 |
3 files changed, 694 insertions, 0 deletions
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) |