diff options
Diffstat (limited to 'roms/SLOF/romfs/tools/create_crc.c')
-rw-r--r-- | roms/SLOF/romfs/tools/create_crc.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/roms/SLOF/romfs/tools/create_crc.c b/roms/SLOF/romfs/tools/create_crc.c new file mode 100644 index 000000000..abc373b9e --- /dev/null +++ b/roms/SLOF/romfs/tools/create_crc.c @@ -0,0 +1,199 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <assert.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <cfgparse.h> +#include <time.h> +#include <calculatecrc.h> +#include <product.h> +#include "createcrc.h" +#include "crclib.h" + +/* file length in bytes */ +static uint64_t ui64globalFileSize = 0; +/* space for the file stream >= 4MB + 4bytes */ +static unsigned char pucFileStream[4400000]; +/* header length in bytes */ +static uint64_t ui64globalHeaderSize = 0; +/* flag to filter detect the header in buildDataStream() */ +static int iglobalHeaderFlag = 1; + +static size_t min(size_t a, size_t b) +{ + return a < b ? a : b; +} + +/** + * Build the file image and store it as Data Stream of bytes + * calculate a first CRC for the first file and + * catch the position of this CRC + */ +int +buildDataStream(unsigned char *pucbuf, int size) +{ + if (ui64globalFileSize + size > sizeof(pucFileStream)) { + printf("Error: File size is too big!\n"); + return -1; + } + + /* copy the data into the destination buffer */ + memcpy(pucFileStream + ui64globalFileSize, pucbuf, size); + ui64globalFileSize += size; + + if (iglobalHeaderFlag == 1) { // catch header + + ui64globalHeaderSize = ui64globalFileSize; + iglobalHeaderFlag = 0; + } + + return 0; +} + +/** + * write Header.img + */ +int +createHeaderImage(int notime) +{ + int iCounter; + uint64_t ui64RomAddr, ui64DataAddr; + time_t caltime; + struct tm *tm; + char *pcVersion; + char dastr[16] = { 0, }; + unsigned long long da = 0; + + struct stH stHeader = { + .magic = FLASHFS_MAGIC, + .platform_name = FLASHFS_PLATFORM_MAGIC, + .platform_revision = FLASHFS_PLATFORM_REVISION, + .ui64FileEnd = -1, + }; + + /* read driver info */ + pcVersion = getenv("DRIVER_NAME"); + if (!pcVersion) + pcVersion = getenv("USER"); + if (!pcVersion) + pcVersion = "unknown"; + memcpy(stHeader.version, pcVersion, + min(strlen(pcVersion), sizeof(stHeader.version))); + + if (!notime) { + /* read time and write it into data stream */ + if ((caltime = time(NULL)) == -1) { + printf("time error\n"); + } + if ((tm = localtime(&caltime)) == NULL) { + printf("local time error\n"); + } + // length must be 13 instead 12 because of terminating + // NUL. Therefore uH.stH.platform_revison must be + // written later to overwrite the terminating NUL + if (strftime(dastr, 15, "0x%Y%m%d%H%M", tm) == 0) { + printf("strftime error\n"); + } + da = cpu_to_be64(strtoll(dastr, NULL, 16)); + } + memcpy(stHeader.date, &da, 8); + + /* read address of next file and address of header date, both are 64 bit values */ + ui64RomAddr = 0; + ui64DataAddr = 0; + for (iCounter = 0; iCounter < 8; iCounter++) { + /* addr of next file */ + ui64RomAddr = (ui64RomAddr << 8) + pucFileStream[FLASHFS_ROMADDR + iCounter]; + /* addr of header data */ + ui64DataAddr = (ui64DataAddr << 8) + pucFileStream[FLASHFS_DATADDR + iCounter]; + } + + /* calculate final flash-header-size and flash-file-size */ + /* calculate end addr of header */ + ui64globalHeaderSize = (uint32_t) ui64DataAddr + sizeof(stHeader); + /* cut 64 bit to place CRC for File-End */ + ui64globalHeaderSize -= 8; + /* add 64 bit to place CRC behind File-End */ + ui64globalFileSize += 8; + + if (ui64globalHeaderSize >= ui64RomAddr) { + printf("%s\n", "--- Header File to long"); + return 1; + } + + /* fill free space in Header with zeros */ + memset(&pucFileStream[ui64DataAddr], 0, (ui64RomAddr - ui64DataAddr)); + /* place data to header */ + memcpy(&pucFileStream[ui64DataAddr], &stHeader, sizeof(stHeader)); + + /* insert header length into data stream */ + *(uint64_t *) (pucFileStream + FLASHFS_HEADER_SIZE_ADDR) = + cpu_to_be64(ui64globalHeaderSize); + + /* insert flash length into data stream */ + *(uint64_t *) (pucFileStream + ui64DataAddr + FLASHFS_FILE_SIZE_ADDR) = + cpu_to_be64(ui64globalFileSize); + + /* insert zeros as placeholder for CRC */ + *(uint64_t *) (pucFileStream + ui64globalHeaderSize - 8) = 0; + *(uint64_t *) (pucFileStream + ui64globalFileSize - 8) = 0; + + return 0; +} + +/** + * insert header and file CRC into data stream + * do CRC check on header and file + * write data stream to disk + */ +int +writeDataStream(int iofd, int notime) +{ + uint64_t ui64FileCRC = 0, ui64HeaderCRC = 0, ui64RegisterMask; + unsigned int uiRegisterLength; + + if (0 != createHeaderImage(notime)) { + return 1; + } + + createCRCParameter(&ui64RegisterMask, &uiRegisterLength); + + /* calculate CRC */ + ui64HeaderCRC = checkCRC(pucFileStream, ui64globalHeaderSize, 0); + *(uint64_t *) (pucFileStream + ui64globalHeaderSize - 8) = + cpu_to_be64(ui64HeaderCRC); + + ui64FileCRC = checkCRC(pucFileStream, ui64globalFileSize, 0); + *(uint64_t *) (pucFileStream + ui64globalFileSize - 8) = + cpu_to_be64(ui64FileCRC); + + /* check CRC-implementation */ + ui64HeaderCRC = calCRCword(pucFileStream, ui64globalHeaderSize, 0); + ui64FileCRC = calCRCword(pucFileStream, ui64globalFileSize, 0); + + if ((ui64HeaderCRC != 0) || (ui64FileCRC != 0)) { + printf("\n\n %s \n %s \n\n", "CRCs not correct implemented.", + " ---> Data will not be written do disk."); + return -1; + } + + /* write file image to disk */ + if (0 < write(iofd, pucFileStream, ui64globalFileSize)) + return 0; + + printf("<< write failed >>\n"); + return -1; +} |