root/trunk/libffado/support/firmware/fireworks-downloader.cpp

Revision 1763, 16.2 kB (checked in by ppalmers, 11 years ago)

Merged revisions 1536,1541,1544-1546,1549,1554-1562,1571,1579-1581,1618,1632,1634-1635,1661,1677-1679,1703-1704,1715,1720-1723,1743-1745,1755 via svnmerge from
svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0

Also fix remaining format string warnings.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2005-2008 by Daniel Wagner
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "fbtypes.h"
26 #include "downloader.h"
27
28 #include "config.h"
29
30 #include "src/fireworks/fireworks_device.h"
31 #include "src/fireworks/fireworks_firmware.h"
32 #include "src/fireworks/fireworks_session_block.h"
33
34 #include "libieee1394/configrom.h"
35 #include "libieee1394/ieee1394service.h"
36 #include "libutil/Configuration.h"
37
38 #include "debugmodule/debugmodule.h"
39
40 #include "devicemanager.h"
41 #include "version.h"
42
43 #include <iostream>
44 #include <string>
45 #include <cstring>
46 #include <cstdlib>
47
48 #define MAGIC_THAT_SAYS_I_KNOW_WHAT_IM_DOING 0x001807198000LL
49
50 using namespace FireWorks;
51
52 DECLARE_GLOBAL_DEBUG_MODULE;
53
54 ////////////////////////////////////////////////
55 // arg parsing
56 ////////////////////////////////////////////////
57 const char *argp_program_version = "fireworks-downloader 0.3";
58 const char *argp_program_bug_address = "<ffado-devel@lists.sf.net>";
59 const char *doc = "fireworks-downloader -- firmware downloader application for ECHO Fireworks devices\n\n"
60                     "OPERATIONS:\n"
61                     "           list\n"
62                     "              Lists devices on the bus\n"
63                     "           display\n"
64                     "              Display information about a device and it's firmware\n"
65                     "           info FILE\n"
66                     "              Display information about the firmware contained in FILE\n"
67                     "           upload FILE\n"
68                     "              Upload the firmware contained in FILE to the device\n"
69                     "           download FILE START_ADDR LEN\n"
70                     "              Download the flash contents from the device to FILE\n"
71                     "              Starts at address START_ADDR and reads LEN quadlets\n"
72                     "           verify FILE\n"
73                     "              Verify that the firmware contained in the device corresponds\n"
74                     "              to the one contained in FILE\n"
75                     "           session_display\n"
76                     "              show information about the session on the device\n"
77                     "           session_info FILE\n"
78                     "              show information about the session in FILE\n"
79                     "           session_download FILE\n"
80                     "              Download the session content from the device to FILE\n"
81                     "           session_upload FILE\n"
82                     "              Upload the session from FILE to the device\n"
83                     ;
84
85 static struct argp_option _options[] = {
86     {"verbose",   'v', "LEVEL",     0,  "Produce verbose output (set level 0-10)" },
87     {"guid",      'g', "GUID",      0,  "GUID of the target device" },
88     {"port",      'p', "PORT",      0,  "Port to use" },
89     {"magic",     'm', "MAGIC",     0,  "A magic number you have to obtain before this code will work."
90                                         "Specifying it means that you accept the risks that come with this tool."},
91     { 0 }
92 };
93 struct argp_option* options = _options;
94
95 int
96 main( int argc, char** argv )
97 {
98     using namespace std;
99
100     printf("-----------------------------------------------\n");
101     printf("ECHO FireWorks platform firmware downloader\n");
102     printf("Part of the FFADO project -- www.ffado.org\n");
103     printf("Version: %s\n", PACKAGE_VERSION);
104     printf("(C) 2008, Pieter Palmers\n");
105     printf("This program comes with ABSOLUTELY NO WARRANTY.\n");
106     printf("-----------------------------------------------\n\n");
107
108     memset(args, 0, sizeof(args));
109
110     args->guid = 0xFFFFFFFFFFFFFFFFLL;
111     argp_parse (argp, argc, argv, 0, 0, args);
112
113     setDebugLevel(args->verbose);
114
115     errno = 0;
116     int node_id = -1;
117
118     fb_octlet_t guid = args->guid;
119
120     if(args->nargs < 1) {
121         argp_help(argp, stderr, ARGP_HELP_USAGE | ARGP_HELP_LONG | ARGP_HELP_DOC, argv[0]);
122         exit(-1);
123     }
124
125     if(args->magic != MAGIC_THAT_SAYS_I_KNOW_WHAT_IM_DOING) {
126         printf("Magic number not correct. Please specify the correct magic using the '-m' option.\n");
127         printf("Manipulating firmware can cause your device to magically stop working (a.k.a. 'bricking').\n");
128         printf("Specifying the magic number indicates that you accept the risks involved\n");
129         printf("with using this tool. The magic number can be found in the source code.\n\n");
130         return -1;
131     } else {
132         printf("YOU HAVE SPECIFIED THE CORRECT MAGIC NUMBER.\n");
133         printf("HENCE YOU ACCEPT THE RISKS INVOLVED.\n");
134     }
135
136     // first do the operations for which we don't need a device
137     if ( strcmp( args->args[0], "info" ) == 0 ) {
138         if (!args->args[1] ) {
139             printMessage("FILE argument is missing\n");
140             return -1;
141         }
142         std::string str( args->args[1] );
143
144         // load the file
145         Firmware f = Firmware();
146         f.setVerboseLevel( args->verbose );
147        
148         if (!f.loadFile(str)) {
149             printMessage("Could not load firmware\n");
150             return -1;
151         }
152         f.show();
153         return 0;
154     } else if ( strcmp( args->args[0], "dumpinfo" ) == 0 ) {
155         if (!args->args[1] ) {
156             printMessage("FILE argument is missing\n");
157             return -1;
158         }
159         std::string str( args->args[1] );
160
161         // load the file
162         Firmware f = Firmware();
163         f.setVerboseLevel( args->verbose );
164        
165         if (!f.loadFile(str)) {
166             printMessage("Could not load firmware\n");
167             return -1;
168         }
169         f.show();
170         f.dumpData();
171         return 0;
172     } else if ( strcmp( args->args[0], "session_info" ) == 0 ) {
173         if (!args->args[1] ) {
174             printMessage("FILE argument is missing\n");
175             return -1;
176         }
177         std::string str( args->args[1] );
178
179         // load the file
180         Session s = Session();
181         s.setVerboseLevel( args->verbose );
182
183         if (!s.loadFromFile(str)) {
184             printMessage("Could not load session\n");
185             return -1;
186         }
187         s.show();
188         return 0;
189     } else if ( strcmp( args->args[0], "list" ) == 0 ) {
190         printDeviceList();
191         exit(0);
192     }
193
194     // we need a device, so find the specified device
195     if (guid == 0xFFFFFFFFFFFFFFFFLL) {
196         printMessage("No GUID specified\n");
197         exit(-1);
198     }
199
200     Ieee1394Service service;
201     if ( !service.initialize( args->port ) ) {
202         printMessage("Could not initialize IEEE 1394 service\n");
203         return -1;
204     }
205     service.setVerboseLevel( args->verbose );
206  
207     for (int i = 0; i < service.getNodeCount(); i++) {
208         ConfigRom configRom(service, i);
209         configRom.initialize();
210         if (configRom.getGuid() == guid) {
211             node_id = configRom.getNodeId();
212             break;
213         }
214     }
215
216     if (node_id < 0) {
217         printMessage("Could not find device with GUID 0x%016"PRIX64"\n", guid);
218         return -1;
219     }
220
221     ConfigRom *configRom = new ConfigRom(service, node_id );
222     if (configRom == NULL) {
223         printMessage("Could not create ConfigRom\n");
224         return -1;
225     }
226     configRom->setVerboseLevel( args->verbose );
227
228     if ( !configRom->initialize() ) {
229         printMessage( "Could not read config rom from device (node id %d).\n",
230                     node_id );
231         delete configRom;
232         return -1;
233     }
234
235     Util::Configuration c;
236     c.openFile( USER_CONFIG_FILE, Util::Configuration::eFM_ReadOnly );
237     c.openFile( SYSTEM_CONFIG_FILE, Util::Configuration::eFM_ReadOnly );
238
239     if ( !FireWorks::Device::probe(c, *configRom) ) {
240         printMessage( "Device with node id %d is not an ECHO FireWorks device.\n",
241                     node_id );
242         delete configRom;
243         return -1;
244     }
245
246     DeviceManager d = DeviceManager();
247     Device *dev = new Device(d, std::auto_ptr<ConfigRom>(configRom) );
248     if (dev == NULL) {
249         printMessage("Could not create FireWorks::Device\n");
250         delete configRom;
251         return -1;
252     }
253     dev->setVerboseLevel(args->verbose);
254
255     if ( strcmp( args->args[0], "display" ) == 0 ) {
256         // nothing to do
257         if (args->verbose < DEBUG_LEVEL_INFO) {
258             dev->setVerboseLevel(DEBUG_LEVEL_INFO);
259         }
260         dev->showDevice();
261     } else if (strcmp( args->args[0], "download" ) == 0) {
262         if (args->nargs < 3) {
263             printMessage("Address range not specified\n");
264             delete dev;
265             return -1;
266         }
267         errno = 0;
268         uint32_t start_addr = strtol(args->args[2], NULL, 0);       
269         if (errno) {
270             printMessage("start address parsing failed: %s\n",
271                        strerror(errno));
272             delete dev;
273             return errno;
274         }
275         uint32_t len = strtol(args->args[3], NULL, 0);
276         if (errno) {
277             printMessage("length parsing failed: %s\n",
278                        strerror(errno));
279             delete dev;
280             return errno;
281         }
282        
283         // create the firmware util class
284         FirmwareUtil util = FirmwareUtil(*dev);
285         util.setVerboseLevel( args->verbose );
286        
287         Firmware f = util.getFirmwareFromDevice(start_addr, len);
288         f.setVerboseLevel( args->verbose );
289         f.show();
290         f.dumpData();
291         printMessage("Saving to file not yet supported.\n");
292     } else if (strcmp( args->args[0], "verify" ) == 0) {
293         if (!args->args[1] ) {
294             printMessage("FILE argument is missing\n");
295             delete dev;
296             return -1;
297         }
298         std::string str( args->args[1] );
299
300         printMessage("Verifying device versus file: %s\n", str.c_str());
301
302         printMessage(" loading file...\n");
303         // load the file
304         Firmware ref = Firmware();
305         ref.setVerboseLevel( args->verbose );
306        
307         if (!ref.loadFile(str)) {
308             printMessage("Could not load firmware from file\n");
309             delete dev;
310             return -1;
311         }
312
313         // get the flash position from the loaded file
314         uint32_t start_addr = ref.getAddress();
315         uint32_t len = ref.getLength();
316
317         // create the firmware util class
318         FirmwareUtil util = FirmwareUtil(*dev);
319         util.setVerboseLevel( args->verbose );
320        
321         printMessage(" reading device...\n");
322         // read the corresponding part of the device
323         Firmware f = util.getFirmwareFromDevice(start_addr, len);
324         f.setVerboseLevel( args->verbose );
325         f.show();
326        
327         printMessage(" comparing...\n");
328         // compare the two images
329         if(!(f == ref)) {
330             printMessage(" => Verify failed. Device content not the same as file content.\n");
331             delete dev;
332             return -1;
333         } else {
334             printMessage(" => Verify successful. Device content identical to file content.\n");
335         }
336     } else if (strcmp( args->args[0], "upload" ) == 0) {
337         if (!args->args[1] ) {
338             printMessage("FILE argument is missing\n");
339             delete dev;
340             return -1;
341         }
342         std::string str( args->args[1] );
343
344         // create the firmware util class
345         FirmwareUtil util = FirmwareUtil(*dev);
346         util.setVerboseLevel( args->verbose );
347
348         printMessage("Uploading %s to device\n", str.c_str());
349
350         printMessage(" loading file...\n");
351         // load the file
352         Firmware ref = Firmware();
353         ref.setVerboseLevel( args->verbose );
354        
355         if (!ref.loadFile(str)) {
356             printMessage("  Could not load firmware from file\n");
357             delete dev;
358             return -1;
359         }
360
361         printMessage(" checking file...\n");
362         if(!ref.isValid()) {
363             printMessage("  Firmware not valid\n");
364             delete dev;
365             return -1;
366         }
367
368         if(!util.isValidForDevice(ref)) {
369             printMessage("  Firmware not valid for this device\n");
370             delete dev;
371             return -1;
372         }
373         printMessage("  seems to be valid firmware for this device...\n");
374
375         // get the flash position from the loaded file
376         uint32_t start_addr = ref.getAddress();
377         uint32_t len = ref.getLength();
378
379         printMessage(" lock flash...\n");
380         if (!dev->lockFlash(true)) {
381             printMessage("  Could not lock flash\n");
382             delete dev;
383             return -1;
384         }
385
386         printMessage(" erasing memory...\n");
387         if (!util.eraseBlocks(start_addr, len)) {
388             printMessage("  Could not erase memory\n");
389             delete dev;
390             return -1;
391         }
392
393         printMessage(" uploading to device...\n");
394         if (!util.writeFirmwareToDevice(ref)) {
395             printMessage("  Could not write firmware to device\n");
396             delete dev;
397             return -1;
398         }
399
400         printMessage(" unlock flash...\n");
401         if (!dev->lockFlash(false)) {
402             printMessage("  Could not unlock flash\n");
403             delete dev;
404             return -1;
405         }
406
407         // now verify
408         printMessage(" verify...\n");
409
410
411         printMessage("  reading device...\n");
412         // read the corresponding part of the device
413         Firmware f = util.getFirmwareFromDevice(start_addr, len);
414         f.setVerboseLevel( args->verbose );
415         f.show();
416        
417         printMessage("  comparing...\n");
418         // compare the two images
419         if(!(f == ref)) {
420             printMessage(" => Verify failed. Firmware upload failed.\n");
421             delete dev;
422             return -1;
423         } else {
424             printMessage(" => Verify successful. Firmware upload successful.\n");
425         }
426     } else if ( strcmp( args->args[0], "session_display" ) == 0 ) {
427         // load the session
428         Session s = Session();
429         s.setVerboseLevel( args->verbose );
430
431         if (!s.loadFromDevice(*dev)) {
432             printMessage("Could not load session\n");
433             return -1;
434         }
435         s.show();
436     } else if ( strcmp( args->args[0], "session_download" ) == 0 ) {
437         if (!args->args[1] ) {
438             printMessage("FILE argument is missing\n");
439             delete dev;
440             return -1;
441         }
442         std::string str( args->args[1] );
443
444         printMessage("Downloading session to file: %s\n", str.c_str());
445
446         printMessage(" loading session...\n");
447         // load the session
448         Session s = Session();
449         s.setVerboseLevel( args->verbose );
450
451         if (!s.loadFromDevice(*dev)) {
452             printMessage("Could not load session from device\n");
453             return -1;
454         }
455
456         printMessage(" saving session...\n");
457         if (!s.saveToFile(str)) {
458             printMessage("Could not save session to file\n");
459             return -1;
460         }
461     } else if ( strcmp( args->args[0], "session_upload" ) == 0 ) {
462         if (!args->args[1] ) {
463             printMessage("FILE argument is missing\n");
464             delete dev;
465             return -1;
466         }
467         std::string str( args->args[1] );
468
469         printMessage("Uploading session from file: %s\n", str.c_str());
470
471         printMessage(" loading session...\n");
472         // load the session
473         Session s = Session();
474         s.setVerboseLevel( args->verbose );
475         if (!s.loadFromFile(str)) {
476             printMessage("Could not load session from file\n");
477             return -1;
478         }
479
480         printMessage(" saving session...\n");
481         if (!s.saveToDevice(*dev)) {
482             printMessage("Could not save session to device\n");
483             return -1;
484         }
485
486     }  else {
487         printMessage("Unknown operation\n");
488     }
489
490     delete dev;
491     return 0;
492 }
Note: See TracBrowser for help on using the browser.