|
|
1.1 ! root 1: /****************************************************************************** ! 2: * Copyright (c) 2004, 2008 IBM Corporation ! 3: * All rights reserved. ! 4: * This program and the accompanying materials ! 5: * are made available under the terms of the BSD License ! 6: * which accompanies this distribution, and is available at ! 7: * http://www.opensource.org/licenses/bsd-license.php ! 8: * ! 9: * Contributors: ! 10: * IBM Corporation - initial implementation ! 11: *****************************************************************************/ ! 12: ! 13: #include <stdint.h> ! 14: #include <stdio.h> ! 15: #include <stdlib.h> ! 16: #include <string.h> ! 17: #include <sys/types.h> ! 18: #include <sys/stat.h> ! 19: #include <netinet/in.h> ! 20: #include <fcntl.h> ! 21: #include <string.h> ! 22: #include <unistd.h> ! 23: #include <cfgparse.h> ! 24: #include <time.h> ! 25: #include <calculatecrc.h> ! 26: #include <product.h> ! 27: #include "createcrc.h" ! 28: ! 29: int createHeaderImage(int); ! 30: unsigned int calCRCEthernet32(unsigned char *TextPtr, ! 31: unsigned long int TextLength, ! 32: unsigned int AccumCRC); ! 33: int createCRCParameter(uint64_t * ui64RegisterMask, ! 34: unsigned int *iRegisterLength); ! 35: uint64_t calCRCbyte(unsigned char *TextPtr, uint32_t Residual, ! 36: uint64_t AccumCRC); ! 37: uint64_t calCRCword(unsigned char *TextPtr, uint32_t Residual, ! 38: uint64_t AccumCRC); ! 39: uint64_t checkCRC(unsigned char *TextPtr, uint32_t Residual, uint64_t AccumCRC); ! 40: ! 41: /* file length in bytes */ ! 42: static uint64_t ui64globalFileSize = 0; ! 43: /* space for the file stream >= 4MB + 4bytes */ ! 44: static unsigned char pucFileStream[4400000]; ! 45: /* header length in bytes */ ! 46: static uint64_t ui64globalHeaderSize = 0; ! 47: /* flag to filter detect the header in buildDataStream() */ ! 48: static int iglobalHeaderFlag = 1; ! 49: static uint64_t ui64Generator1; ! 50: ! 51: /** ! 52: * Build the file image and store it as Data Stream of bytes ! 53: * calculate a first CRC for the first file and ! 54: * catch the position of this CRC ! 55: */ ! 56: int ! 57: buildDataStream(unsigned char *pucbuf, int size) ! 58: { ! 59: if (ui64globalFileSize + size > sizeof(pucFileStream)) { ! 60: printf("Error: File size is too big!\n"); ! 61: return -1; ! 62: } ! 63: ! 64: /* copy the data into the destination buffer */ ! 65: memcpy(pucFileStream + ui64globalFileSize, pucbuf, size); ! 66: ui64globalFileSize += size; ! 67: ! 68: if (iglobalHeaderFlag == 1) { // catch header ! 69: ! 70: ui64globalHeaderSize = ui64globalFileSize; ! 71: iglobalHeaderFlag = 0; ! 72: } ! 73: ! 74: return 0; ! 75: } ! 76: ! 77: /** ! 78: * write Header.img ! 79: */ ! 80: int ! 81: createHeaderImage(int notime) ! 82: { ! 83: int iCounter; ! 84: uint64_t ui64RomAddr, ui64DataAddr; ! 85: time_t caltime; ! 86: struct tm *tm; ! 87: char *pcVersion; ! 88: char dastr[16] = { 0, }; ! 89: unsigned long long da = 0; ! 90: ! 91: union { ! 92: unsigned char pcArray[FLASHFS_HEADER_DATA_SIZE]; ! 93: struct stH stHeader; ! 94: } uHeader; ! 95: ! 96: /* initialize Header */ ! 97: memset(uHeader.pcArray, 0x00, FLASHFS_HEADER_DATA_SIZE); ! 98: ! 99: /* read driver info */ ! 100: if (NULL != (pcVersion = getenv("DRIVER_NAME"))) { ! 101: strncpy(uHeader.stHeader.version, pcVersion, 16); ! 102: } else if (NULL != (pcVersion = getenv("USER"))) { ! 103: strncpy(uHeader.stHeader.version, pcVersion, 16); ! 104: } else if (pcVersion == NULL) { ! 105: strncpy(uHeader.stHeader.version, "No known user!", 16); ! 106: } ! 107: ! 108: if (!notime) { ! 109: /* read time and write it into data stream */ ! 110: if ((caltime = time(NULL)) == -1) { ! 111: printf("time error\n"); ! 112: } ! 113: if ((tm = localtime(&caltime)) == NULL) { ! 114: printf("local time error\n"); ! 115: } ! 116: // length must be 13 instead 12 because of terminating ! 117: // NUL. Therefore uH.stH.platform_revison must be ! 118: // writen later to overwrite the terminating NUL ! 119: if (strftime(dastr, 15, "0x%Y%m%d%H%M", tm) == 0) { ! 120: printf("strftime error\n"); ! 121: } ! 122: da = cpu_to_be64(strtoll(dastr, NULL, 16)); ! 123: } ! 124: memcpy(uHeader.stHeader.date, &da, 8); ! 125: ! 126: /* write Magic value into data stream */ ! 127: strncpy(uHeader.stHeader.magic, FLASHFS_MAGIC, 8); ! 128: /* write platform name into data stream */ ! 129: strcpy(uHeader.stHeader.platform_name, FLASHFS_PLATFORM_MAGIC); ! 130: /* write platform revision into data stream */ ! 131: strcpy(uHeader.stHeader.platform_revision, FLASHFS_PLATFORM_REVISION); ! 132: ! 133: ! 134: /* fill end of file info (8 bytes of FF) into data stream */ ! 135: uHeader.stHeader.ui64FileEnd = -1; ! 136: ! 137: /* read address of next file and address of header date, both are 64 bit values */ ! 138: ui64RomAddr = 0; ! 139: ui64DataAddr = 0; ! 140: for (iCounter = 0; iCounter < 8; iCounter++) { ! 141: /* addr of next file */ ! 142: ui64RomAddr = (ui64RomAddr << 8) + pucFileStream[FLASHFS_ROMADDR + iCounter]; ! 143: /* addr of header data */ ! 144: ui64DataAddr = (ui64DataAddr << 8) + pucFileStream[FLASHFS_DATADDR + iCounter]; ! 145: } ! 146: ! 147: /* calculate final flash-header-size and flash-file-size */ ! 148: /* calculate end addr of header */ ! 149: ui64globalHeaderSize = (uint32_t) ui64DataAddr + (uint32_t) FLASHFS_HEADER_DATA_SIZE; ! 150: /* cut 64 bit to place CRC for File-End */ ! 151: ui64globalHeaderSize -= 8; ! 152: /* add 64 bit to place CRC behind File-End */ ! 153: ui64globalFileSize += 8; ! 154: ! 155: if (ui64globalHeaderSize >= ui64RomAddr) { ! 156: printf("%s\n", "--- Header File to long"); ! 157: return 1; ! 158: } ! 159: ! 160: /* fill free space in Header with zeros */ ! 161: memset(&pucFileStream[ui64DataAddr], 0, (ui64RomAddr - ui64DataAddr)); ! 162: /* place data to header */ ! 163: memcpy(&pucFileStream[ui64DataAddr], uHeader.pcArray, ! 164: FLASHFS_HEADER_DATA_SIZE); ! 165: ! 166: /* insert header length into data stream */ ! 167: *(uint64_t *) (pucFileStream + FLASHFS_HEADER_SIZE_ADDR) = ! 168: cpu_to_be64(ui64globalHeaderSize); ! 169: ! 170: /* insert flash length into data stream */ ! 171: *(uint64_t *) (pucFileStream + ui64DataAddr + FLASHFS_FILE_SIZE_ADDR) = ! 172: cpu_to_be64(ui64globalFileSize); ! 173: ! 174: /* insert zeros as placeholder for CRC */ ! 175: *(uint64_t *) (pucFileStream + ui64globalHeaderSize - 8) = 0; ! 176: *(uint64_t *) (pucFileStream + ui64globalFileSize - 8) = 0; ! 177: ! 178: return 0; ! 179: } ! 180: ! 181: /** ! 182: * calculate standart ethernet 32 bit CRC ! 183: * generator polynome is 0x104C11DB7 ! 184: * this algorithm can be used for encoding and decoding ! 185: */ ! 186: unsigned int ! 187: calCRCEthernet32(unsigned char *TextPtr, unsigned long int TextLength, ! 188: unsigned int AccumCRC) ! 189: { ! 190: const unsigned int CrcTableHigh[16] = { ! 191: 0x00000000, 0x4C11DB70, 0x9823B6E0, 0xD4326D90, ! 192: 0x34867077, 0x7897AB07, 0xACA5C697, 0xE0B41DE7, ! 193: 0x690CE0EE, 0x251D3B9E, 0xF12F560E, 0xBD3E8D7E, ! 194: 0x5D8A9099, 0x119B4BE9, 0xC5A92679, 0x89B8FD09 ! 195: }; ! 196: const unsigned CrcTableLow[16] = { ! 197: 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, ! 198: 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, ! 199: 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, ! 200: 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD ! 201: }; ! 202: ! 203: unsigned char *Buffer = TextPtr; ! 204: unsigned long int Residual = TextLength; ! 205: ! 206: ! 207: while (Residual > 0) { ! 208: unsigned int Temp = ((AccumCRC >> 24) ^ *Buffer) & 0x000000ff; ! 209: AccumCRC <<= 8; ! 210: AccumCRC ^= CrcTableHigh[Temp / 16]; ! 211: AccumCRC ^= CrcTableLow[Temp % 16]; ! 212: ++Buffer; ! 213: --Residual; ! 214: } ! 215: return AccumCRC; ! 216: } ! 217: ! 218: /** ! 219: * create CRC Parameter: CRC Polynome, Shiftregister Mask and length ! 220: * ! 221: * ui64Generator[0] = 0; ! 222: * ui64Generator[1] = 0x42F0E1EB; ! 223: * ui64Generator[1] = (ui64Generator[1] << 32) + 0xA9EA3693; ! 224: * iRegisterLength = 63; ! 225: * ui64RegisterMask = 0xffffffff; ! 226: * ui64RegisterMask = ((ui64RegisterMask) << 32) + 0xffffffff; ! 227: * ! 228: * ucl=0x00000000ffffffff = Mask for 32 bit LSFR to cut down number of bits ! 229: * in the variable to get the same length as LFSR ! 230: * ! 231: * il = length of LSFR = degree of generator polynom reduce il by one to calculate the degree ! 232: * of the highest register in LSFR ! 233: * ! 234: * Examples: ! 235: * CRC-16 for Tap: x16 + x15 + x2 + 1 ! 236: * generator = 0x8005, il = 16, ucl = 0x000000000000FFFF ! 237: * ! 238: * CRC-16 for Floppy: x16 + x12 + x5 +1 ! 239: * generator = 0x1021, il = 16, ucl = 0x000000000000FFFF ! 240: * ! 241: * CRC-32 for Ethernet: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 ! 242: * generator = 0x04C11DB7, il = 32, ucl = 0x00000000FFFFFFFF ! 243: * ! 244: * CRC-64 SP-TrEMBL x64 + x4 + x3 + x + 1 (maximal-length LFSR) ! 245: * generator = 0x1B, il = 64, ucl = 0xFFFFFFFFFFFFFFFF ! 246: * ! 247: * CRC-64 improved ! 248: * x64 + x63 + x61 + x59 + x58 + x56 + x55 + x52 + x49 + x48 + x47 + x46+ x44 + ! 249: * x41 + x37 + x36 + x34 + x32 + x31 + x28 + x26 + x23 + x22 + x19 + x16 + x13 + ! 250: * x12 + x10 + x9 + x6 + x4 + x3 + 1 ! 251: * (see http://www.cs.ud.ac.uk/staff/D.Jones/crcbote.pdf) ! 252: * generator = 0xAD93D23594C9362D, il = 64, ucl = 0xFFFFFFFFFFFFFFFF ! 253: * ! 254: * CRC-64 DLT1 spec ! 255: * x64 + x62 + x57 + x55 + x54 + x53 + x52 + x47 + x46 + x45 + x40 + x39 + x38 + x37 + ! 256: * x35 + x33 + x32 + x31 + x29 + x27 + x24 + x23 + x22 + x21 + x19 + x17 + x13 + x12 + ! 257: * x10 + x9 + x7 + x4 + x + 1 ! 258: * (see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-182.pdf -> page63) ! 259: * generator = 0x42F0E1EBA9EA3693 ! 260: * ! 261: * CRC-64 from internet G(x)= 1006003C000F0D50B ! 262: */ ! 263: int ! 264: createCRCParameter(uint64_t * ui64RegisterMask, unsigned int *uiRegisterLength) ! 265: { ! 266: enum Generators { Tape_16, Floppy_16, Ethernet_32, SPTrEMBL_64, ! 267: SPTrEMBL_improved_64, DLT1_64 ! 268: }; ! 269: enum Generators Generator; ! 270: ! 271: Generator = CRC_METHODE; ! 272: switch (Generator) { ! 273: case Tape_16:{ ! 274: *ui64RegisterMask = 0x0000ffff; ! 275: ui64Generator1 = 0x00008005; ! 276: *uiRegisterLength = 16; ! 277: break; ! 278: } ! 279: case Floppy_16:{ ! 280: *ui64RegisterMask = 0x0000ffff; ! 281: ui64Generator1 = 0x00001021; ! 282: *uiRegisterLength = 16; ! 283: break; ! 284: } ! 285: case Ethernet_32:{ ! 286: *ui64RegisterMask = 0xffffffff; ! 287: ui64Generator1 = 0x04C11DB7; ! 288: *uiRegisterLength = 32; ! 289: break; ! 290: } ! 291: case SPTrEMBL_64:{ ! 292: *ui64RegisterMask = 0xffffffff; ! 293: *ui64RegisterMask = ! 294: ((*ui64RegisterMask) << 32) + 0xffffffff; ! 295: ui64Generator1 = 0x0000001B; ! 296: *uiRegisterLength = 64; ! 297: break; ! 298: } ! 299: case SPTrEMBL_improved_64:{ ! 300: *ui64RegisterMask = 0xffffffff; ! 301: *ui64RegisterMask = ! 302: ((*ui64RegisterMask) << 32) + 0xffffffff; ! 303: ui64Generator1 = 0xAD93D235; ! 304: ui64Generator1 = (ui64Generator1 << 32) + 0x94C9362D; ! 305: *uiRegisterLength = 64; ! 306: break; ! 307: } ! 308: case DLT1_64:{ ! 309: *ui64RegisterMask = 0xffffffff; ! 310: *ui64RegisterMask = ! 311: ((*ui64RegisterMask) << 32) + 0xffffffff; ! 312: ui64Generator1 = 0x42F0E1EB; ! 313: ui64Generator1 = (ui64Generator1 << 32) + 0xA9EA3693; ! 314: *uiRegisterLength = 64; ! 315: break; ! 316: } ! 317: } ! 318: (*uiRegisterLength)--; ! 319: ! 320: return 0; ! 321: } ! 322: ! 323: /** ! 324: * Check CRC by using Linear Feadback Shift Register (LFSR) ! 325: */ ! 326: uint64_t ! 327: calCRCbyte(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC) ! 328: { ! 329: ! 330: uint64_t ui64Mask, ui64Generator0; ! 331: uint8_t ui8Buffer; ! 332: unsigned int uiRegisterLength; ! 333: int iShift; ! 334: ! 335: createCRCParameter(&ui64Mask, &uiRegisterLength); ! 336: ! 337: ui8Buffer = (*cPtr); ! 338: while (ui32NoWords > 0) { ! 339: for (iShift = 7; iShift >= 0; iShift--) { ! 340: ! 341: ui64Generator0 = (AccumCRC >> uiRegisterLength); ! 342: AccumCRC <<= 1; ! 343: ui64Generator0 &= 0x01; ! 344: ui64Generator0 = (0 - ui64Generator0); ! 345: AccumCRC ^= (ui64Generator1 & ui64Generator0); ! 346: } ! 347: AccumCRC ^= ui8Buffer; ! 348: AccumCRC &= ui64Mask; ! 349: ui32NoWords -= 1; ! 350: cPtr += 1; ! 351: ui8Buffer = (*cPtr); ! 352: } ! 353: return AccumCRC; ! 354: } ! 355: ! 356: /** ! 357: * Check CRC by using Linear Feadback Shift Register (LFSR) ! 358: */ ! 359: uint64_t ! 360: calCRCword(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC) ! 361: { ! 362: ! 363: uint64_t ui64Mask, ui64Generator0; ! 364: uint16_t ui16Buffer; ! 365: unsigned int uiRegisterLength; ! 366: int iShift; ! 367: ! 368: createCRCParameter(&ui64Mask, &uiRegisterLength); ! 369: ! 370: if ((ui32NoWords % 2) != 0) { ! 371: /* if Data string does not end at word boundery add one byte */ ! 372: ui32NoWords++; ! 373: cPtr[ui32NoWords] = 0; ! 374: } ! 375: ui16Buffer = ((*(cPtr + 0)) * 256) + (*(cPtr + 1)); ! 376: while (ui32NoWords > 0) { ! 377: for (iShift = 15; iShift >= 0; iShift--) { ! 378: ui64Generator0 = (AccumCRC >> uiRegisterLength); ! 379: AccumCRC <<= 1; ! 380: ui64Generator0 &= 0x01; ! 381: ui64Generator0 = (0 - ui64Generator0); ! 382: AccumCRC ^= (ui64Generator1 & ui64Generator0); ! 383: } ! 384: AccumCRC ^= ui16Buffer; ! 385: AccumCRC &= ui64Mask; ! 386: ui32NoWords -= 2; ! 387: cPtr += 2; ! 388: ui16Buffer = ((*(cPtr + 0)) * 256) + (*(cPtr + 1)); ! 389: } ! 390: return AccumCRC; ! 391: } ! 392: ! 393: uint64_t ! 394: checkCRC(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC) ! 395: { ! 396: ! 397: enum Generators { Ethernet_32 }; ! 398: enum Generators Generator; ! 399: uint64_t ui64Buffer = AccumCRC; ! 400: ! 401: Generator = CRC_METHODE; ! 402: ! 403: switch (Generator) { ! 404: case Ethernet_32:{ ! 405: /* (ui32NoWords - 4),no need of 4 bytes 0x as ! 406: * with shift-register method */ ! 407: AccumCRC = ! 408: calCRCEthernet32(cPtr, (ui32NoWords - 4), AccumCRC); ! 409: break; ! 410: } ! 411: default:{ ! 412: AccumCRC = calCRCword(cPtr, ui32NoWords, AccumCRC); ! 413: break; ! 414: } ! 415: } ! 416: ! 417: if (calCRCbyte(cPtr, ui32NoWords, ui64Buffer) != AccumCRC) { ! 418: printf("\n --- big Endian - small Endian problem --- \n"); ! 419: AccumCRC--; ! 420: } ! 421: ! 422: return (AccumCRC); ! 423: } ! 424: ! 425: /** ! 426: * insert header and file CRC into data stream ! 427: * do CRC check on header and file ! 428: * write data stream to disk ! 429: */ ! 430: int ! 431: writeDataStream(int iofd, int notime) ! 432: { ! 433: uint64_t ui64FileCRC = 0, ui64HeaderCRC = 0, ui64RegisterMask; ! 434: unsigned int uiRegisterLength; ! 435: ! 436: if (0 != createHeaderImage(notime)) { ! 437: return 1; ! 438: } ! 439: ! 440: createCRCParameter(&ui64RegisterMask, &uiRegisterLength); ! 441: ! 442: /* calculate CRC */ ! 443: ui64HeaderCRC = checkCRC(pucFileStream, ui64globalHeaderSize, 0); ! 444: *(uint64_t *) (pucFileStream + ui64globalHeaderSize - 8) = ! 445: cpu_to_be64(ui64HeaderCRC); ! 446: ! 447: ui64FileCRC = checkCRC(pucFileStream, ui64globalFileSize, 0); ! 448: *(uint64_t *) (pucFileStream + ui64globalFileSize - 8) = ! 449: cpu_to_be64(ui64FileCRC); ! 450: ! 451: /* check CRC-implementation */ ! 452: ui64HeaderCRC = calCRCword(pucFileStream, ui64globalHeaderSize, 0); ! 453: ui64FileCRC = calCRCword(pucFileStream, ui64globalFileSize, 0); ! 454: ! 455: if ((ui64HeaderCRC != 0) || (ui64FileCRC != 0)) { ! 456: printf("\n\n %s \n %s \n\n", "CRCs not correct implemented.", ! 457: " ---> Data will not be written do disk."); ! 458: return -1; ! 459: } ! 460: ! 461: /* write file image to disk */ ! 462: if (0 < write(iofd, pucFileStream, ui64globalFileSize)) ! 463: return 0; ! 464: ! 465: printf("<< write failed >>\n"); ! 466: return -1; ! 467: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.