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 <boolean.h>
23 #include "dvdisaster.h"
24 
25 static GaloisTables *gt = NULL;		/* for L-EC Reed-Solomon */
26 static ReedSolomonTables *rt = NULL;
27 
Init_LEC_Correct(void)28 bool Init_LEC_Correct(void)
29 {
30  gt = CreateGaloisTables(0x11d);
31  rt = CreateReedSolomonTables(gt, 0, 1, 10);
32 
33  return(1);
34 }
35 
Kill_LEC_Correct(void)36 void Kill_LEC_Correct(void)
37 {
38  FreeGaloisTables(gt);
39  FreeReedSolomonTables(rt);
40 }
41 
42 /***
43  *** CD level CRC calculation
44  ***/
45 
46 /*
47  * Test raw sector against its 32bit CRC.
48  * Returns true if frame is good.
49  */
50 
CheckEDC(const unsigned char * cd_frame,bool xa_mode)51 int CheckEDC(const unsigned char *cd_frame, bool xa_mode)
52 {
53  unsigned int expected_crc, real_crc;
54  unsigned int crc_base = xa_mode ? 2072 : 2064;
55 
56  expected_crc = cd_frame[crc_base + 0] << 0;
57  expected_crc |= cd_frame[crc_base + 1] << 8;
58  expected_crc |= cd_frame[crc_base + 2] << 16;
59  expected_crc |= cd_frame[crc_base + 3] << 24;
60 
61  if(xa_mode)
62   real_crc = EDCCrc32(cd_frame+16, 2056);
63  else
64   real_crc = EDCCrc32(cd_frame, 2064);
65 
66  if(expected_crc == real_crc)
67   return(1);
68  else
69  {
70   //printf("Bad EDC CRC:  Calculated:  %08x,  Recorded:  %08x\n", real_crc, expected_crc);
71   return(0);
72  }
73 }
74 
75 /***
76  *** A very simple L-EC error correction.
77  ***
78  * Perform just one pass over the Q and P vectors to see if everything
79  * is okay respectively correct minor errors. This is pretty much the
80  * same stuff the drive is supposed to do in the final L-EC stage.
81  */
82 
simple_lec(unsigned char * frame)83 static int simple_lec(unsigned char *frame)
84 {
85    unsigned char byte_state[2352];
86    unsigned char p_vector[P_VECTOR_SIZE];
87    unsigned char q_vector[Q_VECTOR_SIZE];
88    unsigned char p_state[P_VECTOR_SIZE];
89    int erasures[Q_VECTOR_SIZE], erasure_count;
90    int ignore[2];
91    int p_failures, q_failures;
92    int p_corrected, q_corrected;
93    int p,q;
94 
95    /* Setup */
96 
97    memset(byte_state, 0, 2352);
98 
99    p_failures = q_failures = 0;
100    p_corrected = q_corrected = 0;
101 
102    /* Perform Q-Parity error correction */
103 
104    for(q=0; q<N_Q_VECTORS; q++)
105    {  int err;
106 
107       /* We have no erasure information for Q vectors */
108 
109      GetQVector(frame, q_vector, q);
110      err = DecodePQ(rt, q_vector, Q_PADDING, ignore, 0);
111 
112      /* See what we've got */
113 
114      if(err < 0)  /* Uncorrectable. Mark bytes are erasure. */
115      {  q_failures++;
116         FillQVector(byte_state, 1, q);
117      }
118      else         /* Correctable */
119      {  if(err == 1 || err == 2) /* Store back corrected vector */
120 	{  SetQVector(frame, q_vector, q);
121 	   q_corrected++;
122 	}
123      }
124    }
125 
126    /* Perform P-Parity error correction */
127 
128    for(p=0; p<N_P_VECTORS; p++)
129    {  int err,i;
130 
131       /* Try error correction without erasure information */
132 
133       GetPVector(frame, p_vector, p);
134       err = DecodePQ(rt, p_vector, P_PADDING, ignore, 0);
135 
136       /* If unsuccessful, try again using erasures.
137 	 Erasure information is uncertain, so try this last. */
138 
139       if(err < 0 || err > 2)
140       {  GetPVector(byte_state, p_state, p);
141 	 erasure_count = 0;
142 
143 	 for(i=0; i<P_VECTOR_SIZE; i++)
144 	   if(p_state[i])
145 	     erasures[erasure_count++] = i;
146 
147 	 if(erasure_count > 0 && erasure_count <= 2)
148 	 {  GetPVector(frame, p_vector, p);
149 	    err = DecodePQ(rt, p_vector, P_PADDING, erasures, erasure_count);
150 	 }
151       }
152 
153       /* See what we've got */
154 
155       if(err < 0)  /* Uncorrectable. */
156       {  p_failures++;
157       }
158       else         /* Correctable. */
159       {  if(err == 1 || err == 2) /* Store back corrected vector */
160 	 {  SetPVector(frame, p_vector, p);
161 	    p_corrected++;
162 	 }
163       }
164    }
165 
166    /* Sum up */
167 
168    if(q_failures || p_failures || q_corrected || p_corrected)
169    {
170      return 1;
171    }
172 
173    return 0;
174 }
175 
176 /***
177  *** Validate CD raw sector
178  ***/
179 
ValidateRawSector(unsigned char * frame,bool xaMode)180 int ValidateRawSector(unsigned char *frame, bool xaMode)
181 {
182  int lec_did_sth = false;
183 
184   /* Do simple L-EC.
185      It seems that drives stop their internal L-EC as soon as the
186      EDC is okay, so we may see uncorrected errors in the parity bytes.
187      Since we are also interested in the user data only and doing the
188      L-EC is expensive, we skip our L-EC as well when the EDC is fine. */
189 
190   if(!CheckEDC(frame, xaMode))
191   {
192    unsigned char header[4];
193 
194    if(xaMode)
195    {
196     memcpy(header, frame + 12, 4);
197     memset(frame + 12, 0, 4);
198    }
199 
200    lec_did_sth = simple_lec(frame);
201 
202    if(xaMode)
203     memcpy(frame + 12, header, 4);
204   }
205 
206   /* Test internal sector checksum again */
207   if(!CheckEDC(frame, xaMode))
208    /* EDC failure in RAW sector */
209    return false;
210 
211   return true;
212 }
213 
214