root/trunk/libffado/src/fireworks/fireworks_firmware.cpp

Revision 2803, 15.6 kB (checked in by jwoithe, 3 years ago)

Cosmetic: capitalise "L" in "Linux".

"Linux" is a proper noun so it should start with a capital letter. These
changes are almost all within comments.

This patch was originally proposed by pander on the ffado-devel mailing
list. It has been expanded to cover all similar cases to maintain
consistency throughout the source tree.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free FireWire (pro-)audio drivers for Linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
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.
13  *
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.
18  *
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/>.
21  *
22  */
23
24 #include "fireworks_device.h"
25 #include "fireworks_firmware.h"
26 #include "efc/efc_avc_cmd.h"
27 #include "efc/efc_cmd.h"
28 #include "efc/efc_cmds_flash.h"
29
30 #include "libieee1394/configrom.h"
31 #include "libieee1394/vendor_model_ids.h"
32
33 #include <string>
34 #include <sstream>
35 #include <iostream>
36 #include <fstream>
37 #include <cstring>
38
39 #define DAT_EXTENSION "dat"
40
41 // device id's
42 #define AUDIOFIRE2          0x000af2
43 #define AUDIOFIRE4          0x000af4
44 #define AUDIOFIRE8          0x000af8
45 #define AUDIOFIRE12         0x00af12
46 #define AUDIOFIRE12HD       0x0af12d
47 #define FWHDMI              0x00afd1
48 #define ONYX400F            0x00400f
49 #define ONYX1200F           0x01200f
50 #define FIREWORKS8          0x0000f8
51
52 using namespace std;
53
54 template <class T>
55 bool from_string(T& t,
56                  const std::string& s,
57                  std::ios_base& (*f)(std::ios_base&))
58 {
59   std::istringstream iss(s);
60   return !(iss >> f >> t).fail();
61 }
62
63 // These classes provide support for reading/writing the firmware on
64 // echo fireworks based devices
65 namespace FireWorks {
66
67 IMPL_DEBUG_MODULE( Firmware, Firmware, DEBUG_LEVEL_NORMAL );
68 IMPL_DEBUG_MODULE( FirmwareUtil, FirmwareUtil, DEBUG_LEVEL_NORMAL );
69
70 // the firmware class
71
72 // some generic string generation functions
73 const char *Firmware::eDatTypeToString(const enum Firmware::eDatType type) {
74     switch (type) {
75         case eDT_DspCode:
76             return "Dsp Code";
77         case eDT_IceLynxCode:
78             return "IceLynx Code";
79         case eDT_Data:
80             return "Data";
81         case eDT_FPGACode:
82             return "FPGA Code";
83         case eDT_DeviceName:
84             return "Device Name";
85         default:
86             return "invalid";
87     }
88 }
89
90 const enum Firmware::eDatType Firmware::intToeDatType(int type) {
91     switch (type) {
92         case (int)eDT_DspCode: return eDT_DspCode;
93         case (int)eDT_IceLynxCode: return eDT_IceLynxCode;
94         case (int)eDT_Data: return eDT_Data;
95         case (int)eDT_FPGACode: return eDT_FPGACode;
96         case (int)eDT_DeviceName: return eDT_DeviceName;
97         default:
98             return eDT_Invalid;
99     }
100 }
101
102 Firmware::Firmware()
103 : m_source( "none" )
104 , m_Type ( eDT_Invalid )
105 , m_flash_offset_address ( 0 )
106 , m_length_quads ( 0 )
107 , m_CRC32 ( 0 )
108 , m_checksum ( 0 )
109 , m_version ( 0 )
110 , m_append_crc ( false )
111 , m_footprint_quads ( 0 )
112 , m_data( NULL )
113 , m_valid( false )
114 {
115 }
116
117 Firmware::Firmware(const Firmware& f) {
118     debugOutput(DEBUG_LEVEL_VERBOSE, "copy constructor\n");
119     m_source = f.m_source;
120     m_Type = f.m_Type;
121     m_flash_offset_address = f.m_flash_offset_address;
122     m_length_quads = f.m_length_quads;
123     m_CRC32 = f.m_CRC32;
124     m_checksum = f.m_checksum;
125     m_version = f.m_version;
126     m_append_crc = f.m_append_crc;
127     m_footprint_quads = f.m_footprint_quads;
128     m_valid = f.m_valid;
129     m_data = new uint32_t[m_length_quads];
130
131     memcpy(m_data, f.m_data, m_length_quads*sizeof(uint32_t));
132 }
133
134 Firmware& Firmware::operator=(const Firmware& f) {
135     debugOutput(DEBUG_LEVEL_VERBOSE, "assignment\n");
136     if (this != &f) {  // make sure not same object
137         // assign new vars
138         m_source = f.m_source;
139         m_Type = f.m_Type;
140         m_flash_offset_address = f.m_flash_offset_address;
141         m_length_quads = f.m_length_quads;
142         m_CRC32 = f.m_CRC32;
143         m_checksum = f.m_checksum;
144         m_version = f.m_version;
145         m_append_crc = f.m_append_crc;
146         m_footprint_quads = f.m_footprint_quads;
147         m_valid = f.m_valid;
148
149         // replace dynamic data
150         delete [] m_data;
151         m_data = new uint32_t[m_length_quads];
152         memcpy(m_data, f.m_data, m_length_quads*sizeof(uint32_t));
153     }
154     return *this;    // Return ref for multiple assignment
155 }
156
157 Firmware::~Firmware()
158 {
159     if (m_data) delete[] m_data;
160 }
161
162 void
163 Firmware::show()
164 {
165     #ifdef DEBUG
166     debugOutput(DEBUG_LEVEL_NORMAL, "Firmware from %s\n", m_source.c_str());
167     debugOutput(DEBUG_LEVEL_NORMAL, " Valid?               : %s\n", (m_valid?"Yes":"No"));
168     debugOutput(DEBUG_LEVEL_NORMAL, " Type                 : %s\n", eDatTypeToString(m_Type));
169     if (m_Type == eDT_Invalid) return;
170
171     unsigned int version_major = (m_version & 0xFF000000) >> 24;
172     unsigned int version_minor = (m_version & 0x00FF0000) >> 16;
173     unsigned int version_build = (m_version & 0x0000FFFF);
174     debugOutput(DEBUG_LEVEL_NORMAL, " Address Offset       : 0x%08X\n", m_flash_offset_address);
175     debugOutput(DEBUG_LEVEL_NORMAL, " Length (Quadlets)    : 0x%08X\n", m_length_quads);
176     debugOutput(DEBUG_LEVEL_NORMAL, " CRC 32               : 0x%08X\n", m_CRC32);
177     debugOutput(DEBUG_LEVEL_NORMAL, " Checksum             : 0x%08X\n", m_checksum);
178     debugOutput(DEBUG_LEVEL_NORMAL, " Firmware version     : %02u.%02u.%02u (0x%08X)\n",
179                                     version_major, version_minor, version_build, m_version);
180     debugOutput(DEBUG_LEVEL_NORMAL, " Append CRC           : %s\n", (m_append_crc?"Yes":"No"));
181     debugOutput(DEBUG_LEVEL_NORMAL, " Footprint (Quadlets) : 0x%08X\n", m_footprint_quads);
182     #endif
183 }
184
185 bool
186 Firmware::operator==(const Firmware& f)
187 {
188     debugOutput(DEBUG_LEVEL_VERBOSE, "Comparing header...\n");
189     if(m_flash_offset_address != f.m_flash_offset_address) {
190         debugOutput(DEBUG_LEVEL_VERBOSE,
191                     "Flash address differs: %08X != %08X\n",
192                     m_flash_offset_address, f.m_flash_offset_address);
193         return false;
194     }
195     if(m_length_quads != f.m_length_quads) {
196         debugOutput(DEBUG_LEVEL_VERBOSE,
197                     "Flash length differs: %08X != %08X\n",
198                     m_length_quads, f.m_length_quads);
199         return false;
200     }
201     if(m_data == NULL && f.m_data == NULL) {
202         debugOutput(DEBUG_LEVEL_VERBOSE,
203                     "both firmwares have no data\n");
204         return true;
205     }
206     if(m_data == NULL || f.m_data == NULL) {
207         debugOutput(DEBUG_LEVEL_VERBOSE,
208                     "one of the firmwares has no data: %p != %p\n",
209                     m_data, f.m_data);
210         return false;
211     }
212    
213     debugOutput(DEBUG_LEVEL_VERBOSE, "Comparing data...\n");
214     bool retval = true;
215     for(unsigned int i=0; i<m_length_quads; i++) {
216         if(m_data[i] != f.m_data[i]) {
217             debugOutput(DEBUG_LEVEL_VERBOSE,
218                         " POS 0x%08X: %08X != %08X\n",
219                         i, m_data[i], f.m_data[i]);
220             retval = false;
221         }
222     }
223     return retval;
224 }
225
226 bool
227 Firmware::loadFile(std::string filename)
228 {
229     debugOutput(DEBUG_LEVEL_VERBOSE, "Loading firmware from file %s\n", filename.c_str());
230     fstream fwfile;
231    
232     debugOutput(DEBUG_LEVEL_VERBOSE, " Loading file...\n");
233     fwfile.open( filename.c_str(), ios::in | ios::ate);
234     if ( !fwfile.is_open() ) {
235         debugError("Could not open file.\n");
236         return false;
237     }
238     // get file size
239     int size;
240     size = (int)fwfile.tellg();
241    
242     if( size > ECHO_FIRMWARE_FILE_MAX_LENGTH_BYTES) {
243         debugError("File too large (%d bytes).\n", size);
244         return false;
245     }
246    
247     debugOutput(DEBUG_LEVEL_VERBOSE, " Checking magic...\n");
248     // read magic
249     if( size < ECHO_FIRMWARE_MAGIC_LENGTH_BYTES) {
250         debugError("File too small (%d bytes) to contain the magic header.\n", size);
251         return false;
252     }
253    
254     fwfile.seekg (0, ios::beg);
255     getline(fwfile, m_magic);
256     // get rid of the DOS-Style end of line
257     string::size_type loc = m_magic.find( '\r' );
258     if( loc != string::npos ) {
259         m_magic.erase(loc);
260     }
261     loc = m_magic.find( '\n' );
262     if( loc != string::npos ) {
263         m_magic.erase(loc);
264     }
265    
266     // check the magic
267     if (m_magic != ECHO_FIRMWARE_MAGIC) {
268         debugError("Magic was '%s' but should have been '%s'\n",
269                     m_magic.c_str(), ECHO_FIRMWARE_MAGIC);
270         return false;
271     }
272
273     debugOutput(DEBUG_LEVEL_VERBOSE, "   magic OK...\n");
274    
275     debugOutput(DEBUG_LEVEL_VERBOSE, " Reading header...\n");
276     // read header
277     if( size < ECHO_FIRMWARE_MAGIC_LENGTH_BYTES + ECHO_FIRMWARE_HEADER_LENGTH_BYTES) {
278         debugError("File too small to contain the header.\n");
279         return false;
280     }
281    
282     for (int i=0; i < ECHO_FIRMWARE_HEADER_LENGTH_QUADLETS; i++) {
283         std::string buffer;
284         getline(fwfile, buffer);
285         // get rid of the DOS-Style end of line
286         string::size_type loc = buffer.find( '\r' );
287         if( loc != string::npos ) {
288             buffer.erase(loc);
289         }
290         loc = buffer.find( '\n' );
291         if( loc != string::npos ) {
292             buffer.erase(loc);
293         }
294        
295         if (!from_string<uint32_t>(m_header[i], buffer, std::hex)) {
296             debugWarning("Could not convert '%s' to uint32_t\n", buffer.c_str());
297             return false;
298         }
299        
300         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "   Header %02d: %08X\n",
301                     i, m_header[i]);
302     }
303
304     m_Type                  = intToeDatType(m_header[0]);
305     m_flash_offset_address  = m_header[1];
306     m_length_quads          = m_header[2];
307     m_CRC32                 = m_header[3];
308     m_checksum              = m_header[4];
309     m_version               = m_header[5];
310     m_append_crc            = m_header[6] != 0;
311     m_footprint_quads       = m_header[7];
312     debugOutput(DEBUG_LEVEL_VERBOSE, "  header ok...\n");
313
314     debugOutput(DEBUG_LEVEL_VERBOSE, " Reading data...\n");
315     delete[] m_data;
316     m_data = new uint32_t[m_length_quads];
317     if(m_data == NULL) {
318         debugError("could not allocate memory for firmware\n");
319         return false;
320     }
321     for (uint32_t i=0; i < m_length_quads; i++) {
322         std::string buffer;
323         getline(fwfile, buffer);
324         // get rid of the DOS-Style end of line
325         string::size_type loc = buffer.find( '\r' );
326         if( loc != string::npos ) {
327             buffer.erase(loc);
328         }
329         loc = buffer.find( '\n' );
330         if( loc != string::npos ) {
331             buffer.erase(loc);
332         }
333        
334         if (!from_string<uint32_t>(m_data[i], buffer, std::hex)) {
335             debugWarning("Could not convert '%s' to uint32_t\n", buffer.c_str());
336             return false;
337         }
338        
339         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "   Data %02d: %08X\n",
340                     i, m_data[i]);
341     }
342     debugOutput(DEBUG_LEVEL_VERBOSE, "  data ok...\n");
343     fwfile.close();
344
345     m_source = filename;
346     m_valid = true;
347     return true;
348 }
349
350 bool
351 Firmware::loadFromMemory(uint32_t *data, uint32_t addr, uint32_t len) {
352     m_valid = false;
353
354     // mark it as invalid for now
355     m_Type                  = eDT_Invalid;
356
357     // set some values (FIXME)
358     m_flash_offset_address  = addr;
359     m_length_quads          = len;
360     m_CRC32                 = 0;
361     m_checksum              = 0;
362     m_version               = 0;
363     m_append_crc            = false;
364     m_footprint_quads       = 0;
365
366     // delete any old data
367     delete[] m_data;
368     m_data = new uint32_t[len];
369     if(m_data == NULL) {
370         debugError("could not allocate memory for firmware\n");
371         return false;
372     }
373     // copy data
374     memcpy(m_data, data, len*sizeof(uint32_t));
375
376     return true;
377 }
378
379 uint32_t
380 Firmware::getWriteDataLen() {
381     uint32_t retval = 0;
382     if((m_append_crc != 0) && (m_length_quads < m_footprint_quads)) {
383         retval += m_footprint_quads;
384     } else {
385         retval += m_length_quads;
386     }
387     return retval;
388 }
389
390 bool
391 Firmware::getWriteData(uint32_t *buff) {
392     // copy the payload data
393     memcpy(buff, m_data, m_length_quads*4);
394     // if necessary, add crc/version
395     if((m_append_crc != 0) && (m_length_quads < m_footprint_quads)) {
396         debugOutput(DEBUG_LEVEL_VERBOSE, "appending CRC and version\n");
397         buff[m_footprint_quads - 1] = m_CRC32;
398         buff[m_footprint_quads - 2] = m_version;
399     }
400     return true;
401 }
402
403 void
404 Firmware::dumpData()
405 {
406     debugWarning("-- char dump --");
407     hexDump((unsigned char*)m_data, m_length_quads*4);
408 /*   
409     debugWarning("-- quadlet dump --");
410     hexDumpQuadlets(m_data, m_length_quads);*/
411
412 }
413
414
415 // the firmware loader helper class
416 const char *Af2Dats[] =
417 {
418     "Fireworks3"
419 };
420
421 const char *Af4Dats[] =
422 {
423     "Fireworks3"
424 };
425
426 const char *Af8Dats[] =
427 {
428     "bootstrap",
429     "audiofire8",
430     "audiofire8_E",
431     "FireworksARM"
432 };
433
434 const char *Af12Dats[] =
435 {
436     "bootstrap",
437     "audiofire12",
438     "audiofire12_E",
439     "FireworksARM"
440 };
441
442 FirmwareUtil::FirmwareUtil(FireWorks::Device& p)
443 : m_Parent(p)
444 {
445
446     struct dat_list datlists[4] =
447     {
448             { FW_VENDORID_ECHO, AUDIOFIRE2,    0x04010000, 1, Af2Dats },
449             { FW_VENDORID_ECHO, AUDIOFIRE4,    0x04010000, 1, Af4Dats },
450             { FW_VENDORID_ECHO, AUDIOFIRE8,    0x04010000, 4, Af8Dats },
451             { FW_VENDORID_ECHO, AUDIOFIRE12,    0x04010000, 4, Af12Dats }
452     };
453
454     assert(sizeof(datlists) <= sizeof(m_datlists));
455     memset(&m_datlists, 0, sizeof(m_datlists));
456     memcpy(&m_datlists, &datlists, sizeof(datlists));
457 }
458
459 FirmwareUtil::~FirmwareUtil()
460 {
461 }
462
463 bool
464 FirmwareUtil::isValidForDevice(Firmware f)
465 {
466     std::string src = f.getSourceString();
467
468     uint32_t vendor = m_Parent.getConfigRom().getNodeVendorId();
469     uint32_t model = m_Parent.getConfigRom().getModelId();
470
471     for (unsigned int i=0; i<ECHO_FIRMWARE_NUM_BOXTYPES; i++) {
472         if(m_datlists[i].boxtype == model
473            && m_datlists[i].vendorid == vendor)
474         {
475             for(int j=0; j<m_datlists[i].count; j++) {
476                 std::string cmpstring = m_datlists[i].filenames[j];
477                 cmpstring += ".dat";
478                 std::string::size_type loc = src.find( cmpstring, 0 );
479                 if( loc != std::string::npos ) {
480                     debugOutput(DEBUG_LEVEL_VERBOSE, "found filename\n");
481                     return true;
482                     break;
483                  }
484             }
485         }
486     }
487     debugOutput(DEBUG_LEVEL_VERBOSE, "file not for this device\n");
488     return false;
489 }
490
491 Firmware
492 FirmwareUtil::getFirmwareFromDevice(uint32_t start, uint32_t len)
493 {
494     if(len == 0) {
495         debugError("Invalid length: %u\n", len);
496         return Firmware();
497     }
498
499     uint32_t data[len];
500     Firmware f = Firmware();
501
502     if(!m_Parent.readFlash(start, len, data)) {
503         debugError("Flash read failed\n");
504         return f;
505     }
506
507     if(!f.loadFromMemory(data, start, len)) {
508         debugError("Could not load firmware from memory dump\n");
509     }
510
511     return f;
512 }
513
514 bool
515 FirmwareUtil::writeFirmwareToDevice(Firmware f)
516 {
517     uint32_t start_addr = f.getAddress();
518     uint32_t writelen = f.getWriteDataLen();
519     uint32_t buff[writelen * 4];
520     if (!f.getWriteData(buff)) {
521         debugError("Could not prepare data for writing to the device\n");
522         return false;
523     }
524     if(!m_Parent.writeFlash(start_addr, writelen, buff)) {
525         debugError("Writing to flash failed.\n");
526         return false;
527     }
528     return true;
529 }
530
531 bool
532 FirmwareUtil::eraseBlocks(uint32_t start_address, unsigned int nb_quads)
533 {
534     return m_Parent.eraseFlashBlocks(start_address, nb_quads);
535 }
536
537 void
538 FirmwareUtil::show()
539 {
540     debugOutput(DEBUG_LEVEL_NORMAL, "FirmwareUtil\n");
541 }
542
543 } // FireWorks
Note: See TracBrowser for help on using the browser.