2 * Copyright (C) 2005-2008 by Daniel Wagner
4 * This file is part of FFADO
5 * FFADO = Free Firewire (pro-)audio drivers for linux
7 * FFADO is based upon FreeBoB
9 * This program 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 2 of the License, or
12 * (at your option) version 3 of the License.
14 * This program 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.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "bebob_dl_bcd.h"
30 BCDMagic
= 0x446f4362,
33 // XXX not very nice tool box function?
34 std::string
makeString( fb_octlet_t v
)
38 for ( unsigned int i
=0; i
<sizeof( v
); ++i
) {
39 s
+= reinterpret_cast<char*> ( &v
)[i
];
45 std::string
makeDate( fb_octlet_t v
)
48 char* vc
= reinterpret_cast<char*> ( &v
);
64 std::string
makeTime( fb_octlet_t v
)
67 char* vc
= reinterpret_cast<char*>( &v
);
84 BCDFileVersionOffset
= 0x28,
86 V0HeaderCRCOffset
= 0x2c,
89 V1HeaderCRC0ffset
= 0x2c,
93 IMPL_DEBUG_MODULE( BCD
, BCD
, DEBUG_LEVEL_NORMAL
);
96 BeBoB::BCD::BCD( std::string filename
)
98 , m_filename( filename
)
100 , m_softwareDate( 0 )
101 , m_softwareTime( 0 )
103 , m_softwareVersion( 0 )
106 , m_imageBaseAddress( 0 )
129 m_file
= fopen( m_filename
.c_str(), "r" );
131 debugError( "parse: Could not open file '%s'\n",
132 m_filename
.c_str() );
136 fb_quadlet_t identifier
;
137 size_t bytes_read
= fread( &identifier
, 1, sizeof( identifier
), m_file
);
138 if ( bytes_read
!= sizeof( identifier
) ) {
139 debugError( "parse: 4 bytes read failed at position 0\n" );
143 if ( identifier
!= BCDMagic
) {
144 debugError( "parse: File has not BCD header magic, 0x%08x expected, "
145 "0x%08x found\n", BCDMagic
, identifier
);
149 if ( fseek( m_file
, BCDFileVersionOffset
, SEEK_SET
) == -1 ) {
150 debugError( "parse: fseek failed\n" );
154 bytes_read
= fread( &m_bcd_version
, 1, sizeof( fb_quadlet_t
), m_file
);
155 if ( bytes_read
!= sizeof( fb_quadlet_t
) ) {
156 debugError( "parse: %zd bytes read at position %d failed\n",
157 sizeof( fb_quadlet_t
),
158 BCDFileVersionOffset
);
162 unsigned int headerSize
= 0;
163 unsigned int crcOffset
= 0;
164 switch( m_bcd_version
) {
166 headerSize
= V0HeaderSize
;
167 crcOffset
= V0HeaderCRCOffset
;
170 headerSize
= V1HeaderSize
;
171 crcOffset
= V1HeaderCRC0ffset
;
174 debugError( "parse: Unknown BCD file version %d found\n",
179 if ( !checkHeaderCRC( crcOffset
, headerSize
) ) {
180 debugError( "parse: Header CRC check failed\n" );
184 if ( !readHeaderInfo() ) {
185 debugError( "parse: Could not read all header info\n" );
193 BeBoB::BCD::readHeaderInfo()
195 if ( !read( 0x08, &m_softwareDate
) ) {
198 if ( !read( 0x10, &m_softwareTime
) ) {
201 if ( !read( 0x18, &m_softwareId
) ) {
204 if ( !read( 0x1c, &m_softwareVersion
) ) {
207 if ( !read( 0x20, &m_hardwareId
) ) {
210 if ( !read( 0x24, &m_vendorOUI
) ) {
213 if ( !read( 0x30, &m_imageOffset
) ) {
216 if ( !read( 0x34, &m_imageBaseAddress
) ) {
219 if ( !read( 0x38, &m_imageLength
) ) {
222 if ( !read( 0x3c, &m_imageCRC
) ) {
225 if ( !read( 0x50, &m_cneOffset
) ) {
228 if ( !read( 0x58, &m_cneLength
) ) {
231 if ( !read( 0x5c, &m_cneCRC
) ) {
238 BeBoB::BCD::read( int addr
, fb_quadlet_t
* q
)
240 if ( std::fseek( m_file
, addr
, SEEK_SET
) == -1 ) {
241 debugError( "read: seek to position 0x%08x failed\n", addr
);
245 size_t bytes_read
= std::fread( q
, 1, sizeof( *q
), m_file
);
246 if ( bytes_read
!= sizeof( *q
) ) {
247 debugError( "read: %zd byte read failed at position 0x%08x\n",
248 sizeof( *q
), addr
);
256 BeBoB::BCD::read( int addr
, fb_octlet_t
* o
)
258 if ( std::fseek( m_file
, addr
, SEEK_SET
) == -1 ) {
259 debugError( "read: seek to position 0x%08x failed\n", addr
);
263 size_t bytes_read
= std::fread( o
, 1, sizeof( *o
), m_file
);
264 if ( bytes_read
!= sizeof( *o
) ) {
265 debugError( "read: %zd byte read failed at position 0x%08x\n",
266 sizeof( *o
), addr
);
274 BeBoB::BCD::read( int addr
, unsigned char* b
, size_t len
)
276 if ( std::fseek( m_file
, addr
, SEEK_SET
) == -1 ) {
277 debugError( "read: seek to position 0x%08x failed\n", addr
);
281 size_t bytes_read
= std::fread( b
, 1, len
, m_file
);
282 if ( bytes_read
!= len
) {
283 debugError( "read: %zd byte read failed at position 0x%08x\n",
292 BeBoB::BCD::initCRC32Table()
294 unsigned long polynomial
= 0x04c11db7;
296 for ( int i
= 0; i
<= 0xff; ++i
) {
297 crc32_table
[i
] = reflect( i
, 8 ) << 24;
298 for ( int j
= 0; j
< 8; ++j
) {
300 (crc32_table
[i
] << 1)
301 ^ (crc32_table
[i
] & (1 << 31) ? polynomial
: 0);
303 crc32_table
[i
] = reflect( crc32_table
[i
], 32 );
308 BeBoB::BCD::reflect( unsigned long ref
, char ch
)
310 unsigned long value
= 0;
312 for ( int i
= 1; i
< (ch
+ 1); ++i
) {
314 value
|= 1 << (ch
- i
);
322 BeBoB::BCD::getCRC( unsigned char* text
, size_t len
)
324 unsigned long crc
= 0xffffffff;
325 unsigned char* buffer
;
329 crc
= (crc
>> 8) ^ crc32_table
[(crc
& 0xff) ^ *buffer
++];
332 return crc
^ 0xffffffff;
336 BeBoB::BCD::checkHeaderCRC( unsigned int crcOffset
, unsigned int headerSize
)
338 fb_quadlet_t headerCRC
;
339 if ( !read( crcOffset
, &headerCRC
) ) {
340 debugError( "checkHeaderCRC: Could not read header CRC\n" );
344 const int headerLength
= headerSize
;
345 unsigned char buf
[headerLength
];
346 if ( !read( 0x00, buf
, headerLength
) ) {
347 debugError( "checkHeaderCRC: Could not read complete header from file\n" );
350 buf
[crcOffset
+0] = 0x00;
351 buf
[crcOffset
+1] = 0x00;
352 buf
[crcOffset
+2] = 0x00;
353 buf
[crcOffset
+3] = 0x00;
355 fb_quadlet_t calcCRC
= getCRC( buf
, headerLength
);
356 if ( headerCRC
!= calcCRC
) {
357 debugError( "checkHeaderCRC: CRC check failed, 0x%08x expected, "
358 "0x%08x calculated\n", headerCRC
, calcCRC
);
366 BeBoB::BCD::displayInfo()
370 printf( "BCD Info\n" );
371 printf( "\tBCD File Version\t%d\n", m_bcd_version
);
372 printf( "\tSoftware Date:\t\t%s, %s\n",
373 makeDate( m_softwareDate
).c_str(),
374 makeTime( m_softwareTime
).c_str() );
375 printf( "\tSoftware Version:\t0x%08x\n", m_softwareVersion
);
376 printf( "\tSoftware Id:\t\t0x%08x\n", m_softwareId
);
377 printf( "\tHardware ID:\t\t0x%08x\n", m_hardwareId
);
378 printf( "\tVendor OUI:\t\t0x%08x\n", m_vendorOUI
);
379 printf( "\tImage Offset:\t\t0x%08x\n", m_imageOffset
);
380 printf( "\tImage Base Address:\t0x%08x\n", m_imageBaseAddress
);
381 printf( "\tImage Length:\t\t0x%08x\n", m_imageLength
);
382 printf( "\tImage CRC:\t\t0x%08x\n", m_imageCRC
);
383 printf( "\tCNE Length:\t\t0x%08x\n", m_cneLength
);
384 printf( "\tCNE Offset:\t\t0x%08x\n", m_cneOffset
);
385 printf( "\tCNE CRC:\t\t0x%08x\n", m_cneCRC
);