Annotation of qemu/roms/SLOF/romfs/tools/create_crc.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.