aboutsummaryrefslogtreecommitdiffstats
path: root/roms/SLOF/romfs/tools/create_crc.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/SLOF/romfs/tools/create_crc.c')
-rw-r--r--roms/SLOF/romfs/tools/create_crc.c199
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;
+}