|
|
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.