Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / romfs / tools / create_crc.c
diff --git a/qemu/roms/SLOF/romfs/tools/create_crc.c b/qemu/roms/SLOF/romfs/tools/create_crc.c
new file mode 100644 (file)
index 0000000..51f137d
--- /dev/null
@@ -0,0 +1,467 @@
+/******************************************************************************
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <cfgparse.h>
+#include <time.h>
+#include <calculatecrc.h>
+#include <product.h>
+#include "createcrc.h"
+
+int createHeaderImage(int);
+unsigned int calCRCEthernet32(unsigned char *TextPtr,
+                             unsigned long int TextLength,
+                             unsigned int AccumCRC);
+int createCRCParameter(uint64_t * ui64RegisterMask,
+                      unsigned int *iRegisterLength);
+uint64_t calCRCbyte(unsigned char *TextPtr, uint32_t Residual,
+                   uint64_t AccumCRC);
+uint64_t calCRCword(unsigned char *TextPtr, uint32_t Residual,
+                   uint64_t AccumCRC);
+uint64_t checkCRC(unsigned char *TextPtr, uint32_t Residual, uint64_t AccumCRC);
+
+/* 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 uint64_t ui64Generator1;
+
+/**
+ * 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;
+
+       union {
+               unsigned char pcArray[FLASHFS_HEADER_DATA_SIZE];
+               struct stH stHeader;
+       } uHeader;
+
+       /* initialize Header */
+       memset(uHeader.pcArray, 0x00, FLASHFS_HEADER_DATA_SIZE);
+
+       /* read driver info */
+       if (NULL != (pcVersion = getenv("DRIVER_NAME"))) {
+               strncpy(uHeader.stHeader.version, pcVersion, 16);
+       } else if (NULL != (pcVersion = getenv("USER"))) {
+               strncpy(uHeader.stHeader.version, pcVersion, 16);
+       } else if (pcVersion == NULL) {
+               strncpy(uHeader.stHeader.version, "No known user!", 16);
+       }
+
+       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(uHeader.stHeader.date, &da, 8);
+
+       /* write Magic value into data stream */
+       strncpy(uHeader.stHeader.magic, FLASHFS_MAGIC, 8);
+       /* write platform name into data stream */
+       strcpy(uHeader.stHeader.platform_name, FLASHFS_PLATFORM_MAGIC);
+       /* write platform revision into data stream */
+       strcpy(uHeader.stHeader.platform_revision, FLASHFS_PLATFORM_REVISION);
+
+
+       /* fill end of file info (8 bytes of FF) into data stream */
+       uHeader.stHeader.ui64FileEnd = -1;
+
+       /* 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 + (uint32_t) FLASHFS_HEADER_DATA_SIZE;
+       /* 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], uHeader.pcArray,
+              FLASHFS_HEADER_DATA_SIZE);
+
+       /* 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;
+}
+
+/**
+ * calculate standart ethernet 32 bit CRC
+ * generator polynome is 0x104C11DB7
+ * this algorithm can be used for encoding and decoding
+ */
+unsigned int
+calCRCEthernet32(unsigned char *TextPtr, unsigned long int TextLength,
+                unsigned int AccumCRC)
+{
+       const unsigned int CrcTableHigh[16] = {
+               0x00000000, 0x4C11DB70, 0x9823B6E0, 0xD4326D90,
+               0x34867077, 0x7897AB07, 0xACA5C697, 0xE0B41DE7,
+               0x690CE0EE, 0x251D3B9E, 0xF12F560E, 0xBD3E8D7E,
+               0x5D8A9099, 0x119B4BE9, 0xC5A92679, 0x89B8FD09
+       };
+       const unsigned CrcTableLow[16] = {
+               0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
+               0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
+               0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
+               0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
+       };
+
+       unsigned char *Buffer = TextPtr;
+       unsigned long int Residual = TextLength;
+
+
+       while (Residual > 0) {
+               unsigned int Temp = ((AccumCRC >> 24) ^ *Buffer) & 0x000000ff;
+               AccumCRC <<= 8;
+               AccumCRC ^= CrcTableHigh[Temp / 16];
+               AccumCRC ^= CrcTableLow[Temp % 16];
+               ++Buffer;
+               --Residual;
+       }
+       return AccumCRC;
+}
+
+/**
+ * create CRC Parameter:  CRC Polynome, Shiftregister Mask and length
+ *
+ *   ui64Generator[0] = 0;
+ *   ui64Generator[1] = 0x42F0E1EB;
+ *   ui64Generator[1] = (ui64Generator[1] << 32) + 0xA9EA3693;
+ *   iRegisterLength = 63;
+ *   ui64RegisterMask =  0xffffffff;
+ *   ui64RegisterMask = ((ui64RegisterMask) << 32) + 0xffffffff;
+ *
+ *    ucl=0x00000000ffffffff = Mask for 32 bit LSFR to cut down number of bits
+ *    in the variable to get the same length as LFSR
+ *
+ *    il = length of LSFR = degree of generator polynom reduce il by one to calculate the degree
+ *    of the highest register in LSFR
+ *
+ *    Examples:
+ *    CRC-16 for Tap:          x16 + x15 + x2 + 1
+ *     generator = 0x8005,     il = 16,        ucl = 0x000000000000FFFF
+ *
+ *    CRC-16 for Floppy:               x16 + x12 + x5 +1
+ *     generator = 0x1021,     il = 16,        ucl = 0x000000000000FFFF
+ *
+ *    CRC-32 for Ethernet:     x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
+ *     generator = 0x04C11DB7, il = 32,        ucl = 0x00000000FFFFFFFF
+ *
+ *    CRC-64 SP-TrEMBL x64 + x4 + x3 + x + 1 (maximal-length LFSR)
+ *     generator = 0x1B,       il = 64,        ucl = 0xFFFFFFFFFFFFFFFF
+ *
+ *    CRC-64 improved
+ *     x64 + x63 + x61 + x59 + x58 + x56 + x55 + x52 + x49 + x48 + x47 + x46+ x44 +
+ *     x41 + x37 + x36 + x34 + x32 + x31 + x28 + x26 + x23 + x22 + x19 + x16 + x13 +
+ *     x12 + x10 + x9 + x6 + x4 + x3 + 1
+ *     (see http://www.cs.ud.ac.uk/staff/D.Jones/crcbote.pdf)
+ *     generator = 0xAD93D23594C9362D,  il = 64,    ucl = 0xFFFFFFFFFFFFFFFF
+ *
+ *    CRC-64 DLT1 spec
+ *     x64 + x62 + x57 + x55 + x54 + x53 + x52 + x47 + x46 + x45 + x40 + x39 + x38 + x37 +
+ *     x35 + x33 + x32 + x31 + x29 + x27 + x24 + x23 + x22 + x21 + x19 + x17 + x13 + x12 +
+ *     x10 + x9 + x7 + x4 + x + 1
+ *     (see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-182.pdf  -> page63)
+ *     generator = 0x42F0E1EBA9EA3693
+ *
+ *    CRC-64 from internet G(x)= 1006003C000F0D50B
+ */
+int
+createCRCParameter(uint64_t * ui64RegisterMask, unsigned int *uiRegisterLength)
+{
+       enum Generators { Tape_16, Floppy_16, Ethernet_32, SPTrEMBL_64,
+               SPTrEMBL_improved_64, DLT1_64
+       };
+       enum Generators Generator;
+
+       Generator = CRC_METHODE;
+       switch (Generator) {
+       case Tape_16:{
+                       *ui64RegisterMask = 0x0000ffff;
+                       ui64Generator1 = 0x00008005;
+                       *uiRegisterLength = 16;
+                       break;
+               }
+       case Floppy_16:{
+                       *ui64RegisterMask = 0x0000ffff;
+                       ui64Generator1 = 0x00001021;
+                       *uiRegisterLength = 16;
+                       break;
+               }
+       case Ethernet_32:{
+                       *ui64RegisterMask = 0xffffffff;
+                       ui64Generator1 = 0x04C11DB7;
+                       *uiRegisterLength = 32;
+                       break;
+               }
+       case SPTrEMBL_64:{
+                       *ui64RegisterMask = 0xffffffff;
+                       *ui64RegisterMask =
+                           ((*ui64RegisterMask) << 32) + 0xffffffff;
+                       ui64Generator1 = 0x0000001B;
+                       *uiRegisterLength = 64;
+                       break;
+               }
+       case SPTrEMBL_improved_64:{
+                       *ui64RegisterMask = 0xffffffff;
+                       *ui64RegisterMask =
+                           ((*ui64RegisterMask) << 32) + 0xffffffff;
+                       ui64Generator1 = 0xAD93D235;
+                       ui64Generator1 = (ui64Generator1 << 32) + 0x94C9362D;
+                       *uiRegisterLength = 64;
+                       break;
+               }
+       case DLT1_64:{
+                       *ui64RegisterMask = 0xffffffff;
+                       *ui64RegisterMask =
+                           ((*ui64RegisterMask) << 32) + 0xffffffff;
+                       ui64Generator1 = 0x42F0E1EB;
+                       ui64Generator1 = (ui64Generator1 << 32) + 0xA9EA3693;
+                       *uiRegisterLength = 64;
+                       break;
+               }
+       }
+       (*uiRegisterLength)--;
+
+       return 0;
+}
+
+/**
+ *  Check CRC by using Linear Feadback Shift Register (LFSR)
+ */
+uint64_t
+calCRCbyte(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC)
+{
+
+       uint64_t ui64Mask, ui64Generator0;
+       uint8_t ui8Buffer;
+       unsigned int uiRegisterLength;
+       int iShift;
+
+       createCRCParameter(&ui64Mask, &uiRegisterLength);
+
+       ui8Buffer = (*cPtr);
+       while (ui32NoWords > 0) {
+               for (iShift = 7; iShift >= 0; iShift--) {
+
+                       ui64Generator0 = (AccumCRC >> uiRegisterLength);
+                       AccumCRC <<= 1;
+                       ui64Generator0 &= 0x01;
+                       ui64Generator0 = (0 - ui64Generator0);
+                       AccumCRC ^= (ui64Generator1 & ui64Generator0);
+               }
+               AccumCRC ^= ui8Buffer;
+               AccumCRC &= ui64Mask;
+               ui32NoWords -= 1;
+               cPtr += 1;
+               ui8Buffer = (*cPtr);
+       }
+       return AccumCRC;
+}
+
+/**
+ *  Check CRC by using Linear Feadback Shift Register (LFSR)
+ */
+uint64_t
+calCRCword(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC)
+{
+
+       uint64_t ui64Mask, ui64Generator0;
+       uint16_t ui16Buffer;
+       unsigned int uiRegisterLength;
+       int iShift;
+
+       createCRCParameter(&ui64Mask, &uiRegisterLength);
+
+       if ((ui32NoWords % 2) != 0) {
+               /* if Data string does not end at word boundery add one byte */
+               ui32NoWords++;
+               cPtr[ui32NoWords] = 0;
+       }
+       ui16Buffer = ((*(cPtr + 0)) * 256) + (*(cPtr + 1));
+       while (ui32NoWords > 0) {
+               for (iShift = 15; iShift >= 0; iShift--) {
+                       ui64Generator0 = (AccumCRC >> uiRegisterLength);
+                       AccumCRC <<= 1;
+                       ui64Generator0 &= 0x01;
+                       ui64Generator0 = (0 - ui64Generator0);
+                       AccumCRC ^= (ui64Generator1 & ui64Generator0);
+               }
+               AccumCRC ^= ui16Buffer;
+               AccumCRC &= ui64Mask;
+               ui32NoWords -= 2;
+               cPtr += 2;
+               ui16Buffer = ((*(cPtr + 0)) * 256) + (*(cPtr + 1));
+       }
+       return AccumCRC;
+}
+
+uint64_t
+checkCRC(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC)
+{
+
+       enum Generators { Ethernet_32 };
+       enum Generators Generator;
+       uint64_t ui64Buffer = AccumCRC;
+
+       Generator = CRC_METHODE;
+
+       switch (Generator) {
+       case Ethernet_32:{
+                       /* (ui32NoWords - 4),no need of 4 bytes 0x as
+                        * with shift-register method */
+                       AccumCRC =
+                           calCRCEthernet32(cPtr, (ui32NoWords - 4), AccumCRC);
+                       break;
+               }
+       default:{
+                       AccumCRC = calCRCword(cPtr, ui32NoWords, AccumCRC);
+                       break;
+               }
+       }
+
+       if (calCRCbyte(cPtr, ui32NoWords, ui64Buffer) != AccumCRC) {
+               printf("\n --- big Endian - small Endian problem --- \n");
+               AccumCRC--;
+       }
+
+       return (AccumCRC);
+}
+
+/**
+ *  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;
+}