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 /***
26 *** Conversion between little and big endian words.
27 *** Only suitable for non performance critical code.
28 */
29
30 /*
31 * Swap bytes in a 32 bit word to convert between little and big endian.
32 */
33
34 guint32 SwapBytes32(guint32 in)
35 {
36 return
37 ((in & 0xff000000) >> 24)
38 | ((in & 0x00ff0000) >> 8)
39 | ((in & 0x0000ff00) << 8)
40 | ((in & 0x000000ff) << 24);
41 }
42
doIOTest()43 guint64 SwapBytes64(guint64 in)
44 {
45 return
46 ((in & 0xff00000000000000ull) >> 56)
47 | ((in & 0x00ff000000000000ull) >> 40)
48 | ((in & 0x0000ff0000000000ull) >> 24)
49 | ((in & 0x000000ff00000000ull) >> 8)
50 | ((in & 0x00000000ff000000ull) << 8)
51 | ((in & 0x0000000000ff0000ull) << 24)
52 | ((in & 0x000000000000ff00ull) << 40)
53 | ((in & 0x00000000000000ffull) << 56);
54 }
55
56 /***
57 *** Convert the EccHeader structure between different endians.
58 ***/
59
60 /*
61 * A debugging function for printing the Ecc header.
62 */
63
64 void print_hex(char *label, guint8 *values, int n)
main(int,char **)65 { PrintCLI(label);
66
67 while(n--)
68 PrintCLI("%02x ",*values++);
69
70 PrintCLI("\n");
71 }
72
73 void PrintEccHeader(EccHeader *eh)
74 { char buf[16];
75
76 PrintCLI(_("\nContents of Ecc Header:\n\n"));
77
78 strncpy(buf, (char*)eh->cookie, 12); buf[12] = 0;
79 PrintCLI("cookie %s\n",buf);
80 strncpy(buf, (char*)eh->method, 4); buf[4] = 0;
81 PrintCLI("method %s\n",buf);
82 print_hex("methodFlags ", (guint8*)eh->methodFlags, 4);
83 print_hex("mediumFP ", eh->mediumFP, 16);
84 print_hex("mediumSum ", eh->mediumSum, 16);
85 print_hex("eccSum ", eh->eccSum, 16);
86 print_hex("sectors ", eh->sectors, 8);
87 PrintCLI("sectors (native) %lld\n", uchar_to_gint64(eh->sectors));
88 PrintCLI("dataBytes %8x\n", eh->dataBytes);
89 PrintCLI("eccBytes %8x\n", eh->eccBytes);
90 PrintCLI("creatorVersion %8x\n", eh->creatorVersion);
91 PrintCLI("neededVersion %8x\n", eh->neededVersion);
92 PrintCLI("fpSector %8x\n", eh->fpSector);
93 PrintCLI("selfCRC %8x\n", eh->selfCRC);
94 print_hex("crcSum ", eh->crcSum, 16);
95 PrintCLI("inLast %8x\n", eh->inLast);
96 PrintCLI("sectorsPerLayer %lld\n", eh->sectorsPerLayer);
97 PrintCLI("sectorsAddedByEcc %lld\n", eh->sectorsAddedByEcc);
98
99 PrintCLI("\n");
100 }
101
102 void print_crc_block(CrcBlock *cb)
103 { char buf[16];
104
105 PrintCLI("\nContents of CrcBlock:\n\n");
106
107 strncpy(buf, (char*)cb->cookie, 12); buf[12] = 0;
108 PrintCLI("cookie %s\n",buf);
109 strncpy(buf, (char*)cb->method, 4); buf[4] = 0;
110 PrintCLI("method %s\n",buf);
111 print_hex("methodFlags ", (guint8*)cb->methodFlags, 4);
112 PrintCLI("creatorVersion %8x\n", cb->creatorVersion);
113 PrintCLI("neededVersion %8x\n", cb->neededVersion);
114 PrintCLI("fpSector %8x\n", cb->fpSector);
115 print_hex("mediumFP ", cb->mediumFP, 16);
116 print_hex("mediumSum ", cb->mediumSum, 16);
117 PrintCLI("dataSectors %ll16x\n ",cb->dataSectors);
118 PrintCLI("inLast %8x\n", cb->inLast);
119 PrintCLI("dataBytes %8x\n", cb->dataBytes);
120 PrintCLI("eccBytes %8x\n", cb->eccBytes);
121 PrintCLI("sectorsPerLayer %lld\n", cb->sectorsPerLayer);
122 PrintCLI("selfCRC %8x\n", cb->selfCRC);
123
124 PrintCLI("\n");
125 }
126 /*
127 * This is the most annoying part of the endian conversions.
128 */
129
130 //#define VERBOSE
131
132 void SwapEccHeaderBytes(EccHeader *eh)
133 {
134 #ifdef VERBOSE
135 printf("before swap:\n");
136 print_ecc_header(eh);
137 #endif
138
139 eh->dataBytes = SwapBytes32(eh->dataBytes);
140 eh->eccBytes = SwapBytes32(eh->eccBytes);
141 eh->creatorVersion = SwapBytes32(eh->creatorVersion);
142 eh->neededVersion = SwapBytes32(eh->neededVersion);
143 eh->fpSector = SwapBytes32(eh->fpSector);
144 eh->inLast = SwapBytes32(eh->inLast);
145 eh->sectorsPerLayer = SwapBytes64(eh->sectorsPerLayer);
146 eh->sectorsAddedByEcc = SwapBytes64(eh->sectorsAddedByEcc);
147 #ifdef VERBOSE
148 printf("after swap:\n");
149 print_ecc_header(eh);
150 #endif
151 }
152
153 void SwapCrcBlockBytes(CrcBlock *cb)
154 {
155 #ifdef VERBOSE
156 printf("before swap:\n");
157 print_crc_block(cb);
158 #endif
159
160 cb->creatorVersion = SwapBytes32(cb->creatorVersion);
161 cb->neededVersion = SwapBytes32(cb->neededVersion);
162 cb->fpSector = SwapBytes32(cb->fpSector);
163 cb->dataSectors = SwapBytes64(cb->dataSectors);
164 cb->inLast = SwapBytes32(cb->inLast);
165 cb->dataBytes = SwapBytes32(cb->dataBytes);
166 cb->eccBytes = SwapBytes32(cb->eccBytes);
167 cb->sectorsPerLayer = SwapBytes64(cb->sectorsPerLayer);
168 #ifdef VERBOSE
169 printf("after swap:\n");
170 print_crc_block(cb);
171 #endif
172 }
173
174 void SwapDefectiveHeaderBytes(DefectiveSectorHeader *dsh)
175 {
176 dsh->lba = SwapBytes64(dsh->lba);
177 dsh->sectorSize = SwapBytes32(dsh->sectorSize);
178 dsh->properties = SwapBytes32(dsh->properties);
179 dsh->dshFormat = SwapBytes32(dsh->dshFormat);
180 dsh->nSectors = SwapBytes32(dsh->nSectors);
181 }
182