root/branches/libfreebob-downloader/src/bebob/bebob_dl_bcd.cpp

Revision 271, 9.2 kB (checked in by wagi, 17 years ago)

2006-06-21 Daniel Wagner <wagi@monom.org>

  • freebob-downloader first version added
Line 
1 /* bebob_dl_bcd.cpp
2  * Copyright (C) 2006 by Daniel Wagner
3  *
4  * This file is part of FreeBoB.
5  *
6  * FreeBoB 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  * FreeBoB is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBoB; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "bebob_dl_bcd.h"
22
23 #include <cstdio>
24
25 namespace BeBoB {
26     enum {
27         BCDMagic = 0x446f4362,
28     };
29
30     // XXX not very nice tool box function?
31     std::string makeString( fb_octlet_t v )
32     {
33         std::string s;
34
35         for ( unsigned int i=0; i<sizeof( v ); ++i ) {
36             s += reinterpret_cast<char*> ( &v )[i];
37         }
38
39         return s;
40     }
41
42     std::string makeDate( fb_octlet_t v )
43     {
44         std::string s;
45         char* vc = reinterpret_cast<char*> ( &v );
46
47         s += vc[6];
48         s += vc[7];
49         s += '.';
50         s += vc[4];
51         s += vc[5];
52         s += '.';
53         s += vc[0];
54         s += vc[1];
55         s += vc[2];
56         s += vc[3];
57
58         return s;
59     }
60
61     std::string makeTime( fb_octlet_t v )
62     {
63         std::string s;
64         char* vc = reinterpret_cast<char*>( &v );
65
66         s += vc[0];
67         s += vc[1];
68         s += ':';
69         s += vc[2];
70         s += vc[3];
71         s += ':';
72         s += vc[4];
73         s += vc[5];
74         s += vc[6];
75         s += vc[7];
76
77         return s;
78     }
79
80     enum {
81         BCDFileVersionOffset = 0x28,
82
83         V0HeaderCRCOffset    = 0x2c,
84         V0HeaderSize         = 0x60,
85
86         V1HeaderCRC0ffset    = 0x2c,
87         V1HeaderSize         = 0x70,
88     };
89
90     IMPL_DEBUG_MODULE( BCD, BCD, DEBUG_LEVEL_NORMAL );
91 };
92
93 BeBoB::BCD::BCD( std::string filename )
94     : m_file( 0 )
95     , m_filename( filename )
96     , m_bcd_version( -1 )
97     , m_softwareDate( 0 )
98     , m_softwareTime( 0 )
99     , m_softwareId( 0 )
100     , m_softwareVersion( 0 )
101     , m_imageBaseAddress( 0 )
102     , m_imageLength( 0 )
103     , m_imageOffset( 0 )
104     , m_imageCRC( 0 )
105     , m_cneLength( 0 )
106     , m_cneOffset( 0 )
107     , m_cneCRC( 0 )
108 {
109     initCRC32Table();
110 }
111
112 BeBoB::BCD::~BCD()
113 {
114     if ( m_file ) {
115         fclose( m_file );
116     }
117 }
118
119 bool
120 BeBoB::BCD::parse()
121 {
122     using namespace std;
123
124     m_file = fopen( m_filename.c_str(), "r" );
125     if ( !m_file ) {
126         debugError( "parse: Could not open file '%s'\n",
127                     m_filename.c_str() );
128         return false;
129     }
130
131     fb_quadlet_t identifier;
132     size_t bytes_read = fread( &identifier, 1, sizeof( identifier ), m_file );
133     if ( bytes_read  != sizeof( identifier ) ) {
134         debugError( "parse: 4 bytes read failed at position 0\n" );
135         return false;
136     }
137
138     if ( identifier != BCDMagic ) {
139         debugError( "parse: File has not BCD header magic, 0x%08x expected, "
140                     "0x%08x found\n", BCDMagic, identifier );
141         return false;
142     }
143
144     if ( fseek( m_file, BCDFileVersionOffset, SEEK_SET ) == -1 ) {
145         debugError( "parse: fseek failed\n" );
146         return false;
147     }
148
149     bytes_read = fread( &m_bcd_version, 1, sizeof( fb_quadlet_t ), m_file );
150     if ( bytes_read != sizeof( fb_quadlet_t ) ) {
151         debugError( "parse: %d bytes read at position %d failed\n",
152                     sizeof( fb_quadlet_t ),
153                     BCDFileVersionOffset );
154         return false;
155     }
156
157     unsigned int headerSize = 0;
158     unsigned int crcOffset = 0;
159     switch( m_bcd_version ) {
160     case 0:
161         headerSize = V0HeaderSize;
162         crcOffset = V0HeaderCRCOffset;
163         break;
164     case 1:
165         headerSize = V1HeaderSize;
166         crcOffset = V1HeaderCRC0ffset;
167         break;
168     default:
169         debugError( "parse: Unknown BCD file version %d found\n",
170                     m_bcd_version );
171         return false;
172     }
173
174     if ( !checkHeaderCRC( crcOffset, headerSize ) ) {
175         debugError( "parse: Header CRC check failed\n" );
176         return false;
177     }
178
179     if ( !readHeaderInfo() ) {
180         debugError( "parse: Could not read all header info\n" );
181         return false;
182     }
183
184     return true;
185 }
186
187 bool
188 BeBoB::BCD::readHeaderInfo()
189 {
190     if ( !read( 0x08, &m_softwareDate ) ) {
191         return false;
192     }
193     if ( !read( 0x10, &m_softwareTime ) ) {
194         return false;
195     }
196     if ( !read( 0x18, &m_softwareId ) ) {
197         return false;
198     }
199     if ( !read( 0x1c, &m_softwareVersion ) ) {
200         return false;
201     }
202     if ( !read( 0x30, &m_imageOffset ) ) {
203         return false;
204     }
205     if ( !read( 0x34, &m_imageBaseAddress ) ) {
206         return false;
207     }
208     if ( !read( 0x38, &m_imageLength ) ) {
209         return false;
210     }
211     if ( !read( 0x3c, &m_imageCRC ) ) {
212         return false;
213     }
214     if ( !read( 0x50, &m_cneOffset ) ) {
215         return false;
216     }
217     if ( !read( 0x58, &m_cneLength ) ) {
218         return false;
219     }
220     if ( !read( 0x5c, &m_cneCRC ) ) {
221         return false;
222     }
223     return true;
224 }
225
226 bool
227 BeBoB::BCD::read( int addr, fb_quadlet_t* q )
228 {
229     if ( std::fseek( m_file, addr, SEEK_SET ) == -1 ) {
230         debugError( "read: seek to position 0x%08x failed\n", addr );
231         return false;
232     }
233
234     size_t bytes_read = std::fread( q, 1, sizeof( *q ), m_file );
235     if ( bytes_read  != sizeof( *q ) ) {
236         debugError( "read: %d byte read failed at position 0x%08x\n",
237                     sizeof( *q ),  addr );
238         return false;
239     }
240
241     return true;
242 }
243
244 bool
245 BeBoB::BCD::read( int addr, fb_octlet_t* o )
246 {
247     if ( std::fseek( m_file, addr, SEEK_SET ) == -1 ) {
248         debugError( "read: seek to position 0x%08x failed\n", addr );
249         return false;
250     }
251
252     size_t bytes_read = std::fread( o, 1, sizeof( *o ), m_file );
253     if ( bytes_read  != sizeof( *o ) ) {
254         debugError( "read: %d byte read failed at position 0x%08x\n",
255                     sizeof( *o ), addr );
256         return false;
257     }
258
259     return true;
260 }
261
262 bool
263 BeBoB::BCD::read( int addr, unsigned char* b, size_t len )
264 {
265     if ( std::fseek( m_file, addr, SEEK_SET ) == -1 ) {
266         debugError( "read: seek to position 0x%08x failed\n", addr );
267         return false;
268     }
269
270     size_t bytes_read = std::fread( b, 1, len, m_file );
271     if ( bytes_read  != len ) {
272         debugError( "read: %d byte read failed at position 0x%08x\n",
273                     len, addr );
274         return false;
275     }
276
277     return true;
278 }
279
280 void
281 BeBoB::BCD::initCRC32Table()
282 {
283     unsigned long polynomial = 0x04c11db7;
284
285     for ( int i = 0; i <= 0xff; ++i ) {
286         crc32_table[i] = reflect( i, 8 ) << 24;
287         for ( int j = 0; j < 8; ++j ) {
288             crc32_table[i] =
289                 (crc32_table[i] << 1)
290                 ^ (crc32_table[i] & (1 << 31) ? polynomial : 0);
291         }
292         crc32_table[i] = reflect( crc32_table[i], 32 );
293     }
294 }
295
296 unsigned long
297 BeBoB::BCD::reflect( unsigned long ref, char ch )
298 {
299     unsigned long value = 0;
300
301     for ( int i = 1; i < (ch + 1); ++i ) {
302         if(ref & 1) {
303             value |= 1 << (ch - i);
304         }
305         ref >>= 1;
306     }
307     return value;
308 }
309
310 unsigned int
311 BeBoB::BCD::getCRC( unsigned char* text, size_t len )
312 {
313     unsigned long crc = 0xffffffff;
314     unsigned char* buffer;
315
316     buffer = text;
317     while ( len-- ) {
318         crc = (crc >> 8) ^ crc32_table[(crc & 0xff) ^ *buffer++];
319     }
320
321     return crc ^ 0xffffffff;
322 }
323
324 bool
325 BeBoB::BCD::checkHeaderCRC( unsigned int crcOffset, unsigned int headerSize )
326 {
327     fb_quadlet_t headerCRC;
328     if ( !read( crcOffset, &headerCRC ) ) {
329         debugError( "checkHeaderCRC: Could not read header CRC\n" );
330         return false;
331     }
332
333     const int headerLength = headerSize;
334     unsigned char buf[headerLength];
335     if ( !read( 0x00, buf, headerLength ) ) {
336         debugError( "checkHeaderCRC: Could not read complete header from file\n" );
337         return false;
338     }
339     buf[crcOffset+0] = 0x00;
340     buf[crcOffset+1] = 0x00;
341     buf[crcOffset+2] = 0x00;
342     buf[crcOffset+3] = 0x00;
343
344     fb_quadlet_t calcCRC = getCRC( buf, headerLength );
345     if ( headerCRC != calcCRC ) {
346         debugError( "checkHeaderCRC: CRC check failed, 0x%08x expected, "
347                     "0x%08x calculated\n", headerCRC, calcCRC );
348         return false;
349     }
350
351     return true;
352 }
353
354 void
355 BeBoB::BCD::displayInfo()
356 {
357     using namespace std;
358
359     printf( "BCD Info\n" );
360     printf( "\tBCD File Version\t%d\n", m_bcd_version );
361     printf( "\tSoftware Date:\t\t%s, %s\n",
362             makeDate(m_softwareDate ).c_str(),
363             makeTime( m_softwareTime ).c_str() );
364     printf( "\tSoftware Version:\t0x%08x\n", m_softwareVersion );
365     printf( "\tSoftware Id:\t\t0x%08x\n", m_softwareId );
366     printf( "\tImage Offset:\t\t0x%08x\n", m_imageOffset );
367     printf( "\tImage Base Address:\t0x%08x\n", m_imageBaseAddress );
368     printf( "\tImage Length:\t\t0x%08x\n", m_imageLength );
369     printf( "\tImage CRC:\t\t0x%08x\n", m_imageCRC );
370     printf( "\tCNE Length:\t\t0x%08x\n", m_cneLength );
371     printf( "\tCNE Offset:\t\t0x%08x\n", m_cneOffset );
372     printf( "\tCNE CRC:\t\t0x%08x\n", m_cneCRC );
373 }
374
Note: See TracBrowser for help on using the browser.