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