1 /* dvdisaster: Additional error correction for optical media.
2 * Copyright (C) 2004-2007 Carsten Gnoerlich.
3 * Project home page: http://www.dvdisaster.com
4 * Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
19 * or direct your browser at http://www.gnu.org.
20 */
21
22 #include <stdint.h>
23 #include <string.h>
24 #include "recover-raw.h"
25 #include "l-ec.h"
26 #include "edc_crc32.h"
27 #include "galois.h"
28
29 static GaloisTables *gt = NULL; /* for L-EC Reed-Solomon */
30 static ReedSolomonTables *rt = NULL;
31
Init_LEC_Correct(void)32 bool Init_LEC_Correct(void)
33 {
34 gt = CreateGaloisTables(0x11d);
35 rt = CreateReedSolomonTables(gt, 0, 1, 10);
36
37 return(1);
38 }
39
Kill_LEC_Correct(void)40 void Kill_LEC_Correct(void)
41 {
42 FreeGaloisTables(gt);
43 FreeReedSolomonTables(rt);
44 }
45
46 /***
47 *** CD level CRC calculation
48 ***/
49
50 /*
51 * Test raw sector against its 32bit CRC.
52 * Returns TRUE if frame is good.
53 */
54
CheckEDC(const unsigned char * cd_frame,bool xa_mode)55 int CheckEDC(const unsigned char *cd_frame, bool xa_mode)
56 {
57 unsigned int expected_crc, real_crc;
58 unsigned int crc_base = xa_mode ? 2072 : 2064;
59
60 expected_crc = cd_frame[crc_base + 0] << 0;
61 expected_crc |= cd_frame[crc_base + 1] << 8;
62 expected_crc |= cd_frame[crc_base + 2] << 16;
63 expected_crc |= cd_frame[crc_base + 3] << 24;
64
65 if(xa_mode)
66 real_crc = EDCCrc32(cd_frame+16, 2056);
67 else
68 real_crc = EDCCrc32(cd_frame, 2064);
69
70 if(expected_crc == real_crc)
71 return(1);
72
73 //printf("Bad EDC CRC: Calculated: %08x, Recorded: %08x\n", real_crc, expected_crc);
74 return(0);
75 }
76
77 /***
78 *** A very simple L-EC error correction.
79 ***
80 * Perform just one pass over the Q and P vectors to see if everything
81 * is okay respectively correct minor errors. This is pretty much the
82 * same stuff the drive is supposed to do in the final L-EC stage.
83 */
84
simple_lec(unsigned char * frame)85 static int simple_lec(unsigned char *frame)
86 {
87 unsigned char byte_state[2352];
88 unsigned char p_vector[P_VECTOR_SIZE];
89 unsigned char q_vector[Q_VECTOR_SIZE];
90 unsigned char p_state[P_VECTOR_SIZE];
91 int erasures[Q_VECTOR_SIZE], erasure_count;
92 int ignore[2];
93 int p_failures, q_failures;
94 int p_corrected, q_corrected;
95 int p,q;
96
97 /* Setup */
98
99 memset(byte_state, 0, 2352);
100
101 p_failures = q_failures = 0;
102 p_corrected = q_corrected = 0;
103
104 /* Perform Q-Parity error correction */
105
106 for(q=0; q<N_Q_VECTORS; q++)
107 {
108 int err;
109
110 /* We have no erasure information for Q vectors */
111
112 GetQVector(frame, q_vector, q);
113 err = DecodePQ(rt, q_vector, Q_PADDING, ignore, 0);
114
115 /* See what we've got */
116
117 if(err < 0) /* Uncorrectable. Mark bytes are erasure. */
118 { q_failures++;
119 FillQVector(byte_state, 1, q);
120 }
121 else /* Correctable */
122 {
123 if(err == 1 || err == 2) /* Store back corrected vector */
124 {
125 SetQVector(frame, q_vector, q);
126 q_corrected++;
127 }
128 }
129 }
130
131 /* Perform P-Parity error correction */
132 for(p=0; p<N_P_VECTORS; p++)
133 {
134 int err,i;
135
136 /* Try error correction without erasure information */
137
138 GetPVector(frame, p_vector, p);
139 err = DecodePQ(rt, p_vector, P_PADDING, ignore, 0);
140
141 /* If unsuccessful, try again using erasures.
142 Erasure information is uncertain, so try this last. */
143
144 if(err < 0 || err > 2)
145 {
146 GetPVector(byte_state, p_state, p);
147 erasure_count = 0;
148
149 for(i=0; i<P_VECTOR_SIZE; i++)
150 if(p_state[i])
151 erasures[erasure_count++] = i;
152
153 if(erasure_count > 0 && erasure_count <= 2)
154 {
155 GetPVector(frame, p_vector, p);
156 err = DecodePQ(rt, p_vector, P_PADDING, erasures, erasure_count);
157 }
158 }
159
160 /* See what we've got */
161
162 if(err < 0) /* Uncorrectable. */
163 p_failures++;
164 else /* Correctable. */
165 {
166 if(err == 1 || err == 2) /* Store back corrected vector */
167 { SetPVector(frame, p_vector, p);
168 p_corrected++;
169 }
170 }
171 }
172
173 /* Sum up */
174
175 if(q_failures || p_failures || q_corrected || p_corrected)
176 return 1;
177
178 return 0;
179 }
180
181 /***
182 *** Validate CD raw sector
183 ***/
184
ValidateRawSector(unsigned char * frame,bool xaMode)185 int ValidateRawSector(unsigned char *frame, bool xaMode)
186 {
187 int lec_did_sth = false;
188
189 // Silence GCC warning
190 (void)lec_did_sth;
191
192 /* Do simple L-EC.
193 It seems that drives stop their internal L-EC as soon as the
194 EDC is okay, so we may see uncorrected errors in the parity bytes.
195 Since we are also interested in the user data only and doing the
196 L-EC is expensive, we skip our L-EC as well when the EDC is fine. */
197
198 if(!CheckEDC(frame, xaMode))
199 lec_did_sth = simple_lec(frame);
200 /* Test internal sector checksum again */
201
202 /* EDC failure in RAW sector */
203 if(!CheckEDC(frame, xaMode))
204 return false;
205
206 return true;
207 }
208