root/branches/libffado-2.0/support/firmware/fireworks-downloader.cpp

Revision 1722, 16.1 kB (checked in by ppalmers, 2 years ago)

fix format warnings for extreme debugging

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