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

Revision 1053, 12.6 kB (checked in by ppalmers, 14 years ago)

fix small debug message bug

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 "downloader.h"
26
27 #include "src/fireworks/fireworks_device.h"
28 #include "src/fireworks/fireworks_firmware.h"
29
30 #include "libieee1394/configrom.h"
31 #include "libieee1394/ieee1394service.h"
32
33 #include "debugmodule/debugmodule.h"
34
35 #include "devicemanager.h"
36
37 #include <iostream>
38
39 #include <string.h>
40 #include <string>
41
42 #define MAGIC_THAT_SAYS_I_KNOW_WHAT_IM_DOING 0x001807198000LL
43
44 using namespace FireWorks;
45
46 DECLARE_GLOBAL_DEBUG_MODULE;
47
48 ////////////////////////////////////////////////
49 // arg parsing
50 ////////////////////////////////////////////////
51 const char *argp_program_version = "fireworks-downloader 0.2";
52 const char *argp_program_bug_address = "<ffado-devel@lists.sf.net>";
53 const char *doc = "fireworks-downloader -- firmware downloader application for ECHO Fireworks devices\n\n"
54                     "OPERATIONS:\n"
55                     "           list\n"
56                     "              Lists devices on the bus\n"
57                     "           display\n"
58                     "              Display information about a device and it's firmware\n"
59                     "           info FILE\n"
60                     "              Display information about the firmware contained in FILE\n"
61                     "           upload FILE\n"
62                     "              Upload the firmware contained in FILE to the device\n"
63                     "           download FILE START_ADDR LEN\n"
64                     "              Download the flash contents from the device to FILE\n"
65                     "              Starts at address START_ADDR and reads LEN quadlets\n"
66                     "           verify FILE\n"
67                     "              Verify that the firmware contained in the device corresponds\n"
68                     "              to the one contained in FILE\n"
69                     ;
70
71 static struct argp_option _options[] = {
72     {"verbose",   'v', "LEVEL",     0,  "Produce verbose output (set level 0-10)" },
73     {"guid",      'g', "GUID",      0,  "GUID of the target device" },
74     {"port",      'p', "PORT",      0,  "Port to use" },
75     {"magic",     'm', "MAGIC",     0,  "A magic number you have to obtain before this code will work."
76                                         "Specifying it means that you accept the risks that come with this tool."},
77     { 0 }
78 };
79 struct argp_option* options = _options;
80
81 int
82 main( int argc, char** argv )
83 {
84     using namespace std;
85
86     memset(args, 0, sizeof(args));
87
88     args->guid = 0xFFFFFFFFFFFFFFFFLL;
89     argp_parse (argp, argc, argv, 0, 0, args);
90
91     setDebugLevel(args->verbose);
92
93     errno = 0;
94     int node_id = -1;
95
96     fb_octlet_t guid = args->guid;
97
98     if(args->nargs < 1) {
99         argp_help(argp, stderr, ARGP_HELP_USAGE | ARGP_HELP_LONG | ARGP_HELP_DOC, argv[0]);
100         exit(-1);
101     }
102
103     if(args->magic != MAGIC_THAT_SAYS_I_KNOW_WHAT_IM_DOING) {
104         printMessage("Magic number not correct. Please specify the correct magic using the '-m' option.\n");
105         printMessage("Manipulating firmware can cause your device to magically stop working (a.k.a. 'bricking').\n");
106         printMessage("Specifying the magic number indicates that you accept the risks involved\n");
107         printMessage("with using this tool. The magic number can be found in the source code.\n");
108         return -1;
109     } else {
110         printMessage("YOU HAVE SPECIFIED THE CORRECT MAGIC NUMBER.\n");
111         printMessage("HENCE YOU ACCEPT THE RISKS INVOLVED.\n");
112     }
113
114     // first do the operations for which we don't need a device
115     if ( strcmp( args->args[0], "info" ) == 0 ) {
116         if (!args->args[1] ) {
117             printMessage("FILE argument is missing\n");
118             return -1;
119         }
120         std::string str( args->args[1] );
121
122         // load the file
123         Firmware f = Firmware();
124         f.setVerboseLevel( args->verbose );
125        
126         if (!f.loadFile(str)) {
127             printMessage("Could not load firmware\n");
128             return -1;
129         }
130         f.show();
131         return 0;
132     } else if ( strcmp( args->args[0], "dumpinfo" ) == 0 ) {
133         if (!args->args[1] ) {
134             printMessage("FILE argument is missing\n");
135             return -1;
136         }
137         std::string str( args->args[1] );
138
139         // load the file
140         Firmware f = Firmware();
141         f.setVerboseLevel( args->verbose );
142        
143         if (!f.loadFile(str)) {
144             printMessage("Could not load firmware\n");
145             return -1;
146         }
147         f.show();
148         f.dumpData();
149         return 0;
150     } else if ( strcmp( args->args[0], "list" ) == 0 ) {
151         printDeviceList();
152         exit(0);
153     }
154
155     // we need a device, so find the specified device
156     if (guid == 0xFFFFFFFFFFFFFFFFLL) {
157         printMessage("No GUID specified\n");
158         exit(-1);
159     }
160
161     Ieee1394Service service;
162     if ( !service.initialize( args->port ) ) {
163         printMessage("Could not initialize IEEE 1394 service\n");
164         return -1;
165     }
166     service.setVerboseLevel( args->verbose );
167  
168     for (int i = 0; i < service.getNodeCount(); i++) {
169         ConfigRom configRom(service, i);
170         configRom.initialize();
171        
172         if (configRom.getGuid() == guid) {
173             node_id = configRom.getNodeId();
174             break;
175         }
176     }
177
178     if (node_id < 0) {
179         printMessage("Could not find device with GUID 0x%016llX\n", guid);
180         return -1;
181     }
182
183     ConfigRom *configRom = new ConfigRom(service, node_id );
184     if (configRom == NULL) {
185         printMessage("Could not create ConfigRom\n");
186         return -1;
187     }
188     configRom->setVerboseLevel( args->verbose );
189
190     if ( !configRom->initialize() ) {
191         printMessage( "Could not read config rom from device (node id %d).\n",
192                     node_id );
193         delete configRom;
194         return -1;
195     }
196
197     if ( !FireWorks::Device::probe(*configRom) ) {
198         printMessage( "Device with node id %d is not an ECHO FireWorks device.\n",
199                     node_id );
200         delete configRom;
201         return -1;
202     }
203    
204     DeviceManager d = DeviceManager();
205     Device *dev = new Device(d, std::auto_ptr<ConfigRom>(configRom) );
206     if (dev == NULL) {
207         printMessage("Could not create FireWorks::Device\n");
208         delete configRom;
209         return -1;
210     }
211     dev->setVerboseLevel(args->verbose);
212
213     if ( strcmp( args->args[0], "display" ) == 0 ) {
214         // nothing to do
215         if (args->verbose < DEBUG_LEVEL_INFO) {
216             dev->setVerboseLevel(DEBUG_LEVEL_INFO);
217         }
218         dev->showDevice();
219     } else if (strcmp( args->args[0], "download" ) == 0) {
220         if (args->nargs < 3) {
221             printMessage("Address range not specified\n");
222             delete dev;
223             return -1;
224         }
225         errno = 0;
226         uint32_t start_addr = strtol(args->args[2], NULL, 0);       
227         if (errno) {
228             printMessage("start address parsing failed: %s\n",
229                        strerror(errno));
230             delete dev;
231             return errno;
232         }
233         uint32_t len = strtol(args->args[3], NULL, 0);
234         if (errno) {
235             printMessage("length parsing failed: %s\n",
236                        strerror(errno));
237             delete dev;
238             return errno;
239         }
240        
241         // create the firmware util class
242         FirmwareUtil util = FirmwareUtil(*dev);
243         util.setVerboseLevel( args->verbose );
244        
245         Firmware f = util.getFirmwareFromDevice(start_addr, len);
246         f.setVerboseLevel( args->verbose );
247         f.show();
248         f.dumpData();
249         printMessage("Saving to file not yet supported.\n");
250     } else if (strcmp( args->args[0], "verify" ) == 0) {
251         if (!args->args[1] ) {
252             printMessage("FILE argument is missing\n");
253             delete dev;
254             return -1;
255         }
256         std::string str( args->args[1] );
257
258         printMessage("Verifying device versus file: %s\n", str.c_str());
259
260         printMessage(" loading file...\n");
261         // load the file
262         Firmware ref = Firmware();
263         ref.setVerboseLevel( args->verbose );
264        
265         if (!ref.loadFile(str)) {
266             printMessage("Could not load firmware from file\n");
267             delete dev;
268             return -1;
269         }
270
271         // get the flash position from the loaded file
272         uint32_t start_addr = ref.getAddress();
273         uint32_t len = ref.getLength();
274
275         // create the firmware util class
276         FirmwareUtil util = FirmwareUtil(*dev);
277         util.setVerboseLevel( args->verbose );
278        
279         printMessage(" reading device...\n");
280         // read the corresponding part of the device
281         Firmware f = util.getFirmwareFromDevice(start_addr, len);
282         f.setVerboseLevel( args->verbose );
283         f.show();
284        
285         printMessage(" comparing...\n");
286         // compare the two images
287         if(!(f == ref)) {
288             printMessage(" => Verify failed. Device content not the same as file content.\n");
289             delete dev;
290             return -1;
291         } else {
292             printMessage(" => Verify successful. Device content identical to file content.\n");
293         }
294     } else if (strcmp( args->args[0], "upload" ) == 0) {
295         if (!args->args[1] ) {
296             printMessage("FILE argument is missing\n");
297             delete dev;
298             return -1;
299         }
300         std::string str( args->args[1] );
301
302         // create the firmware util class
303         FirmwareUtil util = FirmwareUtil(*dev);
304         util.setVerboseLevel( args->verbose );
305
306         printMessage("Uploading %s to device\n", str.c_str());
307
308         printMessage(" loading file...\n");
309         // load the file
310         Firmware ref = Firmware();
311         ref.setVerboseLevel( args->verbose );
312        
313         if (!ref.loadFile(str)) {
314             printMessage("  Could not load firmware from file\n");
315             delete dev;
316             return -1;
317         }
318
319         printMessage(" checking file...\n");
320         if(!ref.isValid()) {
321             printMessage("  Firmware not valid\n");
322             delete dev;
323             return -1;
324         }
325
326         if(!util.isValidForDevice(ref)) {
327             printMessage("  Firmware not valid for this device\n");
328             delete dev;
329             return -1;
330         }
331         printMessage("  seems to be valid firmware for this device...\n");
332
333         // get the flash position from the loaded file
334         uint32_t start_addr = ref.getAddress();
335         uint32_t len = ref.getLength();
336
337         printMessage(" lock flash...\n");
338         if (!dev->lockFlash(true)) {
339             printMessage("  Could not lock flash\n");
340             delete dev;
341             return -1;
342         }
343
344         printMessage(" erasing memory...\n");
345         if (!util.eraseBlocks(start_addr, len)) {
346             printMessage("  Could not erase memory\n");
347             delete dev;
348             return -1;
349         }
350
351         printMessage(" uploading to device...\n");
352         if (!util.writeFirmwareToDevice(ref)) {
353             printMessage("  Could not write firmware to device\n");
354             delete dev;
355             return -1;
356         }
357
358         printMessage(" unlock flash...\n");
359         if (!dev->lockFlash(false)) {
360             printMessage("  Could not unlock flash\n");
361             delete dev;
362             return -1;
363         }
364
365         // now verify
366         printMessage(" verify...\n");
367
368
369         printMessage("  reading device...\n");
370         // read the corresponding part of the device
371         Firmware f = util.getFirmwareFromDevice(start_addr, len);
372         f.setVerboseLevel( args->verbose );
373         f.show();
374        
375         printMessage("  comparing...\n");
376         // compare the two images
377         if(!(f == ref)) {
378             printMessage(" => Verify failed. Firmware upload failed.\n");
379             delete dev;
380             return -1;
381         } else {
382             printMessage(" => Verify successful. Firmware upload successful.\n");
383         }
384     }  else {
385         printMessage("Unknown operation\n");
386     }
387
388     delete dev;
389     return 0;
390 }
Note: See TracBrowser for help on using the browser.