1 /* dvdisaster: Additional error correction for optical media.
2 * Copyright (C) 2004-2015 Carsten Gnoerlich.
3 *
4 * Email: carsten@dvdisaster.org -or- cgnoerlich@fsfe.org
5 * Project homepage: http://www.dvdisaster.org
6 *
7 * This file is part of dvdisaster.
8 *
9 * dvdisaster is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * dvdisaster is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with dvdisaster. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "dvdisaster.h"
24
25 #include "rs03-includes.h"
26
27
28 /***
29 *** Read and buffer CRC information from RS03 file
30 ***/
31
main(int,char **)32 CrcBuf *RS03GetCrcBuf(Image *image)
33 { RS03CksumClosure *csc;
34 CrcBuf *cbuf;
35 RS03Layout *lay;
36 EccHeader *eh;
37 AlignedBuffer *ab = CreateAlignedBuffer(2048);
38 guint32 *crc_buf = (guint32*)ab->buf;
39 gint64 block_idx[256];
40 gint64 crc_sector,s;
41 int i;
42 int crc_valid = 1;
43
44 /* Allocate buffer for ascending sector order CRCs */
45
46 if(image->eccFileHeader)
47 { eh = image->eccFileHeader;
48 csc = (RS03CksumClosure*)image->eccFileMethod->ckSumClosure;
49
50 lay = CalcRS03Layout(image, ECC_FILE);
51 cbuf = CreateCrcBuf((lay->ndata-1)*lay->sectorsPerLayer);
52 }
53 else
54 { eh = image->eccHeader;
55 csc = (RS03CksumClosure*)image->eccMethod->ckSumClosure;
56 lay = CalcRS03Layout(image, ECC_IMAGE);
57 cbuf = CreateCrcBuf((lay->ndata-1)*lay->sectorsPerLayer);
58 }
59
60 csc->signatureErrors=0;
61 if(csc->lay) g_free(csc->lay);
62 csc->lay = lay;
63
64 /* First sector containing crc data */
65
66 crc_sector = lay->firstCrcPos;
67
68 /* Initialize ecc block index pointers.
69 Note that CRC blocks are shifted by one
70 (each ECC block contains the CRC for the next ECC block) */
71
72 for(s=0, i=0; i<lay->ndata; s+=lay->sectorsPerLayer, i++)
73 block_idx[i] = s+1;
74
75 /* Cycle through the ecc blocks.
76 Each ecc block contains the CRCs for the following ecc block;
77 these are rearranged in ascending sector order. */
78
79 for(s=0; s<lay->sectorsPerLayer; s++)
80 { int err;
81
82 /* Get CRC sector for current ecc block */
83
84 if(image->eccFile && image->eccFileState == ECCFILE_PRESENT) /* read from separate ecc file */
85 { if(!LargeSeek(image->eccFile, (gint64)(2048*(lay->firstCrcPos+s))))
86 CreateMissingSector(ab->buf, crc_sector, image->imageFP, FINGERPRINT_SECTOR, NULL);
87 else
88 if(LargeRead(image->eccFile, ab->buf, 2048) != 2048)
89 CreateMissingSector(ab->buf, crc_sector, image->imageFP, FINGERPRINT_SECTOR, NULL);
90 }
91 else /* read from augmented image */
92 { int n = ImageReadSectors(image, ab->buf, crc_sector, 1);
93 if(n!=1)
94 CreateMissingSector(ab->buf, crc_sector, image->imageFP, FINGERPRINT_SECTOR, NULL);
95 }
96
97 err = CheckForMissingSector(ab->buf, crc_sector, eh->mediumFP, eh->fpSector);
98 #if 0
99 if(err != SECTOR_PRESENT)
100 { int source_type;
101
102 if(image->eccFile && image->eccFileState == ECCFILE_PRESENT)
103 source_type = SOURCE_ECCFILE;
104 else source_type = image->type == IMAGE_FILE ? SOURCE_IMAGE : SOURCE_MEDIUM;
105
106 if(!unrecoverable_sectors && err != SECTOR_MISSING)
107 PrintLog("\n");
108 ExplainMissingSector(ab->buf, crc_sector, err, source_type, &unrecoverable_sectors);
109 }
110 #endif
111 crc_sector++;
112 crc_valid = (err == SECTOR_PRESENT);
113
114 /* Check the CrcBlock data structure */
115
116 if(crc_valid)
117 { CrcBlock *cb = (CrcBlock*)ab->buf;
118
119 if( memcmp(cb->cookie, "*dvdisaster*", 12)
120 ||memcmp(cb->method, "RS03", 4))
121 { crc_valid = FALSE;
122 csc->signatureErrors++;
123 }
124 else
125 { guint32 recorded_crc = cb->selfCRC;
126 guint32 real_crc;
127
128 #ifdef HAVE_BIG_ENDIAN
129 cb->selfCRC = 0x47504c00;
130 #else
131 cb->selfCRC = 0x4c5047;
132 #endif
133
134 real_crc = Crc32((unsigned char*)cb, 2048);
135
136 if(real_crc != recorded_crc)
137 { crc_valid = FALSE;
138 csc->signatureErrors++;
139 }
140 }
141 }
142
143 /* Go through all data sectors of current ecc block;
144 distribute the CRC values */
145
146 for(i=0; i<lay->ndata-1; i++)
147 {
148 /* CRC sums for the first ecc block are contained in the last
149 CRC sector. Wrap the block_idx accordingly. */
150
151 if(s == lay->sectorsPerLayer-1)
152 block_idx[i] = i*lay->sectorsPerLayer;
153
154 /* Sort crc into appropriate place if CRC block is valid */
155
156 if(crc_valid)
157 { cbuf->crcbuf[block_idx[i]] = crc_buf[i];
158 SetBit(cbuf->valid,block_idx[i]);
159 }
160
161 block_idx[i]++;
162 }
163 }
164
165 FreeAlignedBuffer(ab);
166 return cbuf;
167 }
168
169 /***
170 *** Read one or more image sectors from the .iso file.
171 ***/
172
173 void RS03ReadSectors(Image *image, RS03Layout *lay, unsigned char *buf,
174 gint64 layer, gint64 layer_sector, gint64 how_many, int flags)
175 { LargeFile *target_file = NULL;
176 gint64 start_sector=0;
177 gint64 stop_sector=0;
178 gint64 byte_size = how_many * 2048;
179 gint64 img_file_sector_size;
180 gint64 ecc_file_sector_size=0;
181 gint64 target_file_sector_size;
182 int in_last;
183 gint64 n;
184
185 if(layer < 0 || layer > 255)
186 Stop("RS03ReadSectors: layer %lld out of range 0 .. 255\n", layer);
187 if(layer_sector < 0 || layer_sector >= lay->sectorsPerLayer)
188 Stop("RS03ReadSectors: offset %lld out of range 0 .. %lld)\n",
189 layer_sector, lay->sectorsPerLayer-1);
190
191 /* "Image" file size may not be a multiple of 2048 */
192
193 in_last = image->file->size % 2048;
194 img_file_sector_size = image->file->size/2048;
195 if(in_last) img_file_sector_size++;
196
197 /* Ignore trailing garbage in the image file */
198
199 if(lay->target == ECC_FILE)
200 { /* If the image is longer as expected in the ecc file,
201 truncate sizes to the values recorded in the ecc file. */
202 if(img_file_sector_size > lay->dataSectors)
203 { img_file_sector_size = lay->dataSectors;
204 in_last = lay->eh->inLast;
205 }
206
207 /* If the image has the right sector size, but contains
208 a few bytes more in this sector as expected, truncate
209 the value. However if the last sector contains some
210 bytes less than expected, keep the smaller value
211 to prevent reading past the image later on. */
212 if( img_file_sector_size == lay->dataSectors
213 && in_last > lay->eh->inLast)
214 { in_last = lay->eh->inLast;
215 }
216
217 /* Ecc file size is currently considered to be a multiple
218 of the sector size (which is normally the case).
219 If the ecc file is tuncated by a few bytes,
220 the last incomplete sector is ignored. */
221
222 ecc_file_sector_size = image->eccFile->size/2048;
223 }
224
225 /* Read out of the data layer */
226
227 if(layer < lay->ndata-1)
228 { if(!(flags & RS03_READ_DATA))
229 Stop("RS03ReadSectors: trying to read data layer, but flag not set\n");
230
231 start_sector = layer*lay->sectorsPerLayer + layer_sector;
232 stop_sector = start_sector + how_many - 1;
233
234 if(stop_sector >= (layer+1)*lay->sectorsPerLayer)
235 Stop("RS03ReadSectors: range %lld..%lld crosses layer boundary\n",
236 start_sector, stop_sector);
237 target_file = image->file;
238 }
239
240 /* Read out of the crc layer */
241
242 if(layer == lay->ndata-1)
243 { if(!(flags & RS03_READ_CRC))
244 Stop("RS03ReadSectors: trying to read crc layer, but flag not set\n");
245
246 start_sector = lay->firstCrcPos + layer_sector;
247 stop_sector = start_sector + how_many - 1;
248
249 if(lay->target == ECC_IMAGE)
250 target_file = image->file;
251 else target_file = image->eccFile;
252 }
253
254 /*** Read out of the ecc layers */
255
256 target_file_sector_size = img_file_sector_size;
257
258 if(layer >= lay->ndata)
259 { if(!(flags & RS03_READ_ECC))
260 Stop("RS03ReadSectors: trying to read ecc layer, but flag not set\n");
261
262 start_sector = lay->firstEccPos + (layer-lay->ndata)*lay->sectorsPerLayer + layer_sector;
263 stop_sector = start_sector + how_many - 1;
264
265 if(lay->target == ECC_IMAGE)
266 target_file = image->file;
267 else
268 { target_file = image->eccFile;
269 target_file_sector_size = ecc_file_sector_size;
270 in_last = 0; /* Ecc file size if always a multiple of 2048 */
271 }
272 }
273
274 /* Reading beyond the image returns
275 - dead sectors if the image was truncated
276 - padding sectors if the real end of the image is exceeded.
277 Create them in memory; shorten read range accordingly */
278
279 if(stop_sector >= target_file_sector_size)
280 { unsigned char *bufptr = buf;
281 char *volume_label = NULL;
282 guint64 expected_sectors;
283
284 #if 0 //FIXME
285 if(rc->image->isoInfo && rc->image->isoInfo->volumeLabel[0])
286 rc->volumeLabel = g_strdup(rc->image->isoInfo->volumeLabel);
287 #endif
288
289 if(lay->target == ECC_FILE)
290 expected_sectors = lay->dataSectors;
291 else
292 expected_sectors = lay->totalSectors;
293
294 for(n=start_sector; n<=stop_sector; n++)
295 {
296 if(n>=target_file_sector_size)
297 { guint8 *fp = lay->eh ? lay->eh->mediumFP : NULL;
298 if(n>=expected_sectors)
299 { CreatePaddingSector(bufptr, n, fp, FINGERPRINT_SECTOR);
300 }
301 else
302 { CreateMissingSector(bufptr, n, fp, FINGERPRINT_SECTOR, volume_label);
303 }
304 byte_size -= 2048;
305 }
306 bufptr += 2048;
307 }
308 }
309
310 if(byte_size<=0)
311 return;
312
313 /* Image with ecc files may have an incomplete last sector.
314 Deal with it appropriately. */
315
316 if(lay->target == ECC_FILE && in_last)
317 { if(start_sector <= target_file_sector_size-1
318 && target_file_sector_size-1 <= stop_sector)
319 {
320 memset(buf, 0, byte_size);
321 byte_size = byte_size - 2048 + in_last;
322 }
323 }
324
325 /* All sectors are consecutively readable in image case */
326
327 if(!LargeSeek(target_file, (gint64)(2048*start_sector)))
328 Stop(_("Failed seeking to sector %lld in image: %s"),
329 start_sector, strerror(errno));
330
331 n = LargeRead(target_file, buf, byte_size);
332 if(n != byte_size)
333 Stop(_("Failed reading sector %lld in image: %s"),
334 start_sector, strerror(errno));
335 }
336
337 /***
338 *** Calculate position of n-th sector of the given layer in the image.
339 ***/
340
341 gint64 RS03SectorIndex(RS03Layout *lay, gint64 layer, gint64 n)
342 {
343 if(lay->target == ECC_IMAGE)
344 return layer*lay->sectorsPerLayer+n;
345
346 /* Image portion in ecc file case */
347
348 if(layer < lay->ndata-1)
349 return layer*lay->sectorsPerLayer+n;
350
351 /* Layers located in the ecc file */
352
353 if(layer == lay->ndata-1) /* CRC layer */
354 return lay->firstCrcPos + n;
355
356 /* Ecc layers */
357
358 return lay->firstEccPos + (layer-lay->ndata)*lay->sectorsPerLayer + n;
359 }
360
361
362 /***
363 *** Calculation of the image layout
364 ***/
365
366 static int get_roots(gint64 data_sectors, gint64 medium_capacity)
367 { gint64 sectors_per_layer = medium_capacity/GF_FIELDMAX;
368 int ndata = (data_sectors + 2 +sectors_per_layer - 1) / sectors_per_layer;
369
370 return GF_FIELDMAX - ndata - 1;
371 }
372
373 static gint64 ecc_file_size(gint64 sectors, int nr)
374 { int nd = GF_FIELDMAX - nr;
375 gint64 bytesize;
376
377 bytesize = 4096 + 2048*(nr+1)*((sectors+nd-1)/nd);
378
379 return (bytesize+0xfffff)/0x100000; /* size in MiB */
380 }
381
382
383 RS03Layout *CalcRS03Layout(Image *image, int target)
384 { RS03Layout *lay = g_malloc0(sizeof(RS03Layout));
385
386 /* See if layout has already been cached in the image */
387
388 if(image->cachedLayout)
389 { RS03Layout *ptr = (RS03Layout*)image->cachedLayout;
390 if(strncmp((char*)(ptr->eh->method), "RS03", 4))
391 { Verbose("CalcRS03Layout(): removed cached layout from other codec\n");
392 g_free(image->cachedLayout);
393 }
394 else
395 { if(((RS03Layout*)image->cachedLayout)->target != target)
396 { Verbose("CalcRS03Layout(): removed cached layout from RS03, wrong target\n");
397 g_free(image->cachedLayout);
398 }
399 { Verbose("CalcRS03Layout(): returning cached layout (%s)\n",
400 ((RS03Layout*)image->cachedLayout)->target == ECC_FILE ? "file" : "augmented");
401 memcpy(lay, image->cachedLayout, sizeof(RS03Layout));
402 return lay;
403 }
404 }
405 }
406
407 lay->target = target;
408
409 /* We are going to create an error correction file */
410
411 if(target == ECC_FILE)
412 { guint64 filesize;
413 int n_roots = 0;
414 char last = 0;
415
416 lay->eh = image->eccFileHeader;
417
418 if(lay->eh) /* Header given; get number of roots from there */
419 { n_roots = lay->eh->eccBytes;
420 lay->dataSectors = uchar_to_gint64(lay->eh->sectors);
421 lay->inLast = lay->eh->inLast;
422 }
423 else /* Calculate number of roots */
424 {
425 /* Calculate image size in sectors */
426
427 if(!LargeStat(Closure->imageName, &filesize))
428 Stop(_("Image file %s not present."),Closure->imageName);
429
430 CalcSectors(filesize, &lay->dataSectors, &lay->inLast);
431
432 /* Calculate wanted redundancy from Closure->redundancy */
433
434 if(Closure->redundancy) /* get last char of redundancy parameter */
435 { int len = strlen(Closure->redundancy);
436
437 if(len) last = Closure->redundancy[len-1];
438 }
439
440 switch(last)
441 { case '%':
442 { double p = atof(Closure->redundancy);
443
444 if(p<3.2 || p>200.0)
445 Stop(_("Redundancy %4.1f%% out of useful range [3.2%%..200%%]"),p);
446 n_roots = (int)round((GF_FIELDMAX*p) / (100.0+p));
447 break;
448 }
449 case 'm':
450 { gint64 ecc_size;
451
452 ecc_size = strtoll(Closure->redundancy, NULL, 10);
453 if( ecc_size < ecc_file_size(lay->dataSectors, 8)
454 || ecc_size > ecc_file_size(lay->dataSectors, 170))
455 Stop(_("Ecc file size %lldm out of useful range [%lld .. %lld]"),
456 ecc_size,
457 ecc_file_size(lay->dataSectors, 8),
458 ecc_file_size(lay->dataSectors, 170));
459
460 for(n_roots=170; n_roots>8; n_roots--)
461 if(ecc_size >= ecc_file_size(lay->dataSectors, n_roots))
462 break;
463 break;
464 }
465
466 default:
467 if(!Closure->redundancy || !strcmp(Closure->redundancy, "normal")) n_roots = 32;
468 else if(!strcmp(Closure->redundancy, "high")) n_roots = 64;
469 else n_roots = atoi(Closure->redundancy);
470 break;
471 }
472 }
473
474 if(n_roots < 8 || n_roots > 170)
475 Stop(_("Redundancy %d out of useful range [8..170]."),n_roots);
476
477 /* Now we have settled for the number of roots,
478 so calculate the layout. */
479
480 lay->dataPadding = 0; /* always zero for ecc files */
481 lay->nroots = n_roots;
482 lay->ndata = GF_FIELDMAX - n_roots;
483
484 lay->sectorsPerLayer = (lay->dataSectors + lay->ndata - 2)/(lay->ndata-1);
485 lay->totalSectors = lay->dataSectors + 2 + (lay->nroots+1)*lay->sectorsPerLayer;
486
487 lay->mediumCapacity = 0; /* unused for ecc files */
488 lay->eccHeaderPos = 0;
489 lay->firstCrcPos = 2;
490 lay->firstEccPos = lay->firstCrcPos + lay->sectorsPerLayer;
491 lay->redundancy = ((double)lay->nroots*100.0)/(double)lay->ndata;
492 }
493
494 /* We are going to augment an image file */
495
496 if(target == ECC_IMAGE)
497 { gint64 dataSectors;
498
499 /* Determine smallest possible medium format which
500 can hold the image plus at least 8 roots for ecc.
501 Overriding the medium size via --debug is not recommended
502 as it may render the image irrecoverable in the error case. */
503
504 lay->eh = image->eccHeader;
505
506 if(lay->eh)
507 { dataSectors = uchar_to_gint64(lay->eh->sectors);
508 }
509 else
510 { dataSectors = image->sectorSize;
511 if(Closure->debugMode && Closure->mediumSize)
512 { if(dataSectors >= Closure->mediumSize)
513 Stop(_("Medium size smaller than image size (%lld < %lld)"), Closure->mediumSize, dataSectors);
514 lay->mediumCapacity = Closure->mediumSize;
515 }
516 else
517 { if(get_roots(dataSectors, CDR_SIZE) >= 8)
518 lay->mediumCapacity = CDR_SIZE; /* CDR */
519 else if(get_roots(dataSectors, DVD_SL_SIZE) >= 8)
520 lay->mediumCapacity = DVD_SL_SIZE; /* Single layered DVD */
521 else if(get_roots(dataSectors, DVD_DL_SIZE) >= 8)
522 lay->mediumCapacity = DVD_DL_SIZE; /* Double layered DVD */
523 else if(get_roots(dataSectors, BD_SL_SIZE) >= 8)
524 lay->mediumCapacity = BD_SL_SIZE; /* Single layered BD */
525 else lay->mediumCapacity = BD_DL_SIZE; /* Double layered BD */
526 }
527 }
528
529 /* Calculate the image layout */
530
531 if(lay->eh) lay->sectorsPerLayer = lay->eh->sectorsPerLayer;
532 else lay->sectorsPerLayer = lay->mediumCapacity/GF_FIELDMAX;
533 lay->dataSectors = dataSectors;
534 lay->totalSectors = GF_FIELDMAX*lay->sectorsPerLayer;
535
536 lay->ndata = (dataSectors + 2 + lay->sectorsPerLayer - 1) / lay->sectorsPerLayer;
537 if(lay->ndata < 84) /* we clip redundancy at 170 roots */
538 { Verbose("Redundancy clipped from %d to %d\n", lay->ndata, 84);
539 lay->ndata = 84;
540 }
541 lay->dataPadding = lay->ndata * lay->sectorsPerLayer - lay->dataSectors - 2;
542 lay->ndata++; /* CRC layer is also protected and counted as part of the data portion */
543 lay->nroots = GF_FIELDMAX-lay->ndata;
544 lay->redundancy = ((double)lay->nroots*100.0)/(double)lay->ndata;
545
546 lay->eccHeaderPos = lay->dataSectors;
547 lay->firstCrcPos = (lay->ndata-1)*lay->sectorsPerLayer;
548 lay->firstEccPos = lay->firstCrcPos + lay->sectorsPerLayer;
549 }
550
551 /* Debugging output */
552
553 if(target == ECC_FILE)
554 Verbose("Calculated layout for RS03 file:\n");
555 else Verbose("Calculated layout for RS03 image:\n");
556
557 Verbose("data sectors = %lld\n", lay->dataSectors);
558 Verbose("data padding = %lld\n", lay->dataPadding);
559 Verbose("layer size = %lld\n", lay->sectorsPerLayer);
560 Verbose("total sectors = %lld\n", lay->totalSectors);
561 Verbose("medium capacity = %lld\n", lay->mediumCapacity);
562 Verbose("header position = %lld\n", lay->eccHeaderPos);
563 Verbose("first CRC sector = %lld\n", lay->firstCrcPos);
564 Verbose("first ECC sector = %lld\n", lay->firstEccPos);
565 Verbose("ndata = %d\n", lay->ndata);
566 Verbose("nroots = %d (%4.1f%%)\n", lay->nroots, lay->redundancy);
567 Verbose("\n");
568
569 image->cachedLayout = g_malloc(sizeof(RS03Layout));
570 memcpy(image->cachedLayout, lay, sizeof(RS03Layout));
571
572 return lay;
573 }
574
575 /*
576 * Determine expected size of image.
577 * In case of ecc files, only the iso image size is reported.
578 */
579
580 guint64 RS03ExpectedImageSize(Image *image)
581 { EccHeader *eh=image->eccHeader;
582 guint64 size = 0;
583
584 if(!eh && image->eccFileHeader)
585 eh=image->eccFileHeader;
586
587 if(!eh) return 0;
588
589 if(eh->methodFlags[0] & MFLAG_ECC_FILE)
590 size = uchar_to_gint64(eh->sectors); /* ecc file */
591 else
592 size = 255*eh->sectorsPerLayer; /* augmented image */
593
594 return size;
595 }
596
597
598 /***
599 *** Write the RS03 header into the image.
600 ***/
601
602 void WriteRS03Header(LargeFile *file, RS03Layout *lay, EccHeader *eh)
603 { int n;
604
605 if(!LargeSeek(file, 2048*lay->eccHeaderPos))
606 Stop(_("Failed seeking to ecc header at %lld: %s\n"), lay->eccHeaderPos, strerror(errno));
607
608 n = LargeWrite(file, eh, sizeof(EccHeader));
609 if(n != sizeof(EccHeader))
610 Stop(_("Failed writing ecc header at %lld: %s\n"), lay->eccHeaderPos, strerror(errno));
611 }
612
613 /***
614 *** Reconstruct the RS03 header from a CRC block
615 ***/
616
617 void ReconstructRS03Header(EccHeader *eh, CrcBlock *cb)
618 { int i;
619
620 #ifdef HAVE_BIG_ENDIAN
621 SwapCrcBlockBytes(cb);
622 #endif
623
624 memset(eh, 0, sizeof(EccHeader));
625
626 memcpy(eh->cookie, "*dvdisaster*", 12);
627 memcpy(eh->method, "RS03", 4);
628 for(i=0; i<4; i++)
629 eh->methodFlags[i] = cb->methodFlags[i];
630 memcpy(eh->mediumFP, cb->mediumFP, 16);
631 memcpy(eh->mediumSum, cb->mediumSum, 16);
632 gint64_to_uchar(eh->sectors, cb->dataSectors);
633 eh->dataBytes = cb->dataBytes;
634 eh->eccBytes = cb->eccBytes;
635 eh->creatorVersion = cb->creatorVersion;
636 eh->neededVersion = cb->neededVersion;
637 eh->fpSector = cb->fpSector;
638 eh->inLast = cb->inLast;
639 eh->sectorsPerLayer = cb->sectorsPerLayer;
640
641 eh->selfCRC = 0x4c5047;
642
643 #ifdef HAVE_BIG_ENDIAN
644 eh->selfCRC = 0x47504c00;
645 #endif
646
647 eh->selfCRC = Crc32((unsigned char*)eh, 4096);
648 }
649