Annotation of qemu/roms/SLOF/romfs/tools/create_crc.c, revision 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.