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