Initial commit.
[b43-tools.git] / ssb_sprom / ssb_sprom.c
1 /*
2
3   Broadcom Sonics Silicon Backplane bus SPROM data modification tool
4
5   Copyright (c) 2006-2007 Michael Buesch <mb@bu3sch.de>
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; see the file COPYING.  If not, write to
19   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
20   Boston, MA 02110-1301, USA.
21
22 */
23
24 #include "ssb_sprom.h"
25 #include "utils.h"
26
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/stat.h>
32
33
34 struct cmdline_args cmdargs;
35
36 static int value_length_map[] = { /* value to number of bits */
37         [VALUE_RAW] = 8,
38         [VALUE_SUBP] = 16,
39         [VALUE_SUBV] = 16,
40         [VALUE_PPID] = 16,
41         [VALUE_BFLHI] = 16,
42         [VALUE_BFL] = 16,
43         [VALUE_BGMAC] = -1,
44         [VALUE_ETMAC] = -1,
45         [VALUE_AMAC] = -1,
46         [VALUE_ET0PHY] = 8,
47         [VALUE_ET1PHY] = 8,
48         [VALUE_ET0MDC] = 1,
49         [VALUE_ET1MDC] = 1,
50         [VALUE_BREV] = 8,
51         [VALUE_LOC] = 4,
52         [VALUE_ANTA0] = 1,
53         [VALUE_ANTA1] = 1,
54         [VALUE_ANTBG0] = 1,
55         [VALUE_ANTBG1] = 1,
56         [VALUE_ANTGA] = 8,
57         [VALUE_ANTGBG] = 8,
58         [VALUE_PA0B0] = 16,
59         [VALUE_PA0B1] = 16,
60         [VALUE_PA0B2] = 16,
61         [VALUE_PA1B0] = 16,
62         [VALUE_PA1B1] = 16,
63         [VALUE_PA1B2] = 16,
64         [VALUE_WL0GPIO0] = 8,
65         [VALUE_WL0GPIO1] = 8,
66         [VALUE_WL0GPIO2] = 8,
67         [VALUE_WL0GPIO3] = 8,
68         [VALUE_MAXPA] = 8,
69         [VALUE_MAXPBG] = 8,
70         [VALUE_ITSSIA] = 8,
71         [VALUE_ITSSIBG] = 8,
72         [VALUE_SVER] = 8,
73 };
74
75
76 static int hexdump_sprom(const uint8_t *sprom, char *buffer, size_t bsize)
77 {
78         int i, pos = 0;
79
80         for (i = 0; i < SPROM_SIZE; i++) {
81                 pos += snprintf(buffer + pos, bsize - pos - 1,
82                                 "%02X", sprom[i] & 0xFF);
83         }
84
85         return pos + 1;
86 }
87
88 static uint8_t sprom_crc(const uint8_t *sprom)
89 {
90         int i;
91         uint8_t crc = 0xFF;
92
93         for (i = 0; i < SPROM_SIZE - 1; i++)
94                 crc = crc8(crc, sprom[i]);
95         crc ^= 0xFF;
96
97         return crc;
98 }
99
100 static int write_output_binary(int fd, const uint8_t *sprom)
101 {
102         ssize_t w;
103
104         w = write(fd, sprom, SPROM_SIZE);
105         if (w < 0)
106                 return -1;
107
108         return 0;
109 }
110
111 static int write_output_hex(int fd, const uint8_t *sprom)
112 {
113         ssize_t w;
114         char tmp[SPROM_SIZE * 2 + 10] = { 0 };
115
116         hexdump_sprom(sprom, tmp, sizeof(tmp));
117         prinfo("Raw output:  %s\n", tmp);
118         w = write(fd, tmp, SPROM_SIZE * 2);
119         if (w < 0)
120                 return -1;
121
122         return 0;
123 }
124
125 static int write_output(int fd, const uint8_t *sprom)
126 {
127         int err;
128
129         if (cmdargs.outfile) {
130                 err = ftruncate(fd, 0);
131                 if (err) {
132                         prerror("Could not truncate --outfile %s\n",
133                                 cmdargs.outfile);
134                         return -1;
135                 }
136         }
137
138         if (cmdargs.bin_mode)
139                 err = write_output_binary(fd, sprom);
140         else
141                 err = write_output_hex(fd, sprom);
142         if (err)
143                 prerror("Could not write output data.\n");
144
145         return err;
146 }
147
148 static int modify_value(uint8_t *sprom,
149                         struct cmdline_vparm *vparm)
150 {
151         const uint16_t v = vparm->u.value;
152         uint16_t tmp = 0;
153
154         switch (vparm->type) {
155         case VALUE_RAW:
156                 sprom[vparm->u.raw.offset] = vparm->u.raw.value;
157                 break;
158         case VALUE_SUBP:
159                 sprom[SPROM_SUBP + 0] = (v & 0x00FF);
160                 sprom[SPROM_SUBP + 1] = (v & 0xFF00) >> 8;
161                 break;
162         case VALUE_SUBV:
163                 sprom[SPROM_SUBV + 0] = (v & 0x00FF);
164                 sprom[SPROM_SUBV + 1] = (v & 0xFF00) >> 8;
165                 break;
166         case VALUE_PPID:
167                 sprom[SPROM_PPID + 0] = (v & 0x00FF);
168                 sprom[SPROM_PPID + 1] = (v & 0xFF00) >> 8;
169                 break;
170         case VALUE_BFLHI:
171                 sprom[SPROM_BFLHI + 0] = (v & 0x00FF);
172                 sprom[SPROM_BFLHI + 1] = (v & 0xFF00) >> 8;
173                 break;
174         case VALUE_BFL:
175                 sprom[SPROM_BOARDFLAGS + 0] = (v & 0x00FF);
176                 sprom[SPROM_BOARDFLAGS + 1] = (v & 0xFF00) >> 8;
177                 break;
178         case VALUE_BGMAC:
179                 sprom[SPROM_IL0MACADDR + 1] = vparm->u.mac[0];
180                 sprom[SPROM_IL0MACADDR + 0] = vparm->u.mac[1];
181                 sprom[SPROM_IL0MACADDR + 3] = vparm->u.mac[2];
182                 sprom[SPROM_IL0MACADDR + 2] = vparm->u.mac[3];
183                 sprom[SPROM_IL0MACADDR + 5] = vparm->u.mac[4];
184                 sprom[SPROM_IL0MACADDR + 4] = vparm->u.mac[5];
185                 break;
186         case VALUE_ETMAC:
187                 sprom[SPROM_ET0MACADDR + 1] = vparm->u.mac[0];
188                 sprom[SPROM_ET0MACADDR + 0] = vparm->u.mac[1];
189                 sprom[SPROM_ET0MACADDR + 3] = vparm->u.mac[2];
190                 sprom[SPROM_ET0MACADDR + 2] = vparm->u.mac[3];
191                 sprom[SPROM_ET0MACADDR + 5] = vparm->u.mac[4];
192                 sprom[SPROM_ET0MACADDR + 4] = vparm->u.mac[5];
193                 break;
194         case VALUE_AMAC:
195                 sprom[SPROM_ET1MACADDR + 1] = vparm->u.mac[0];
196                 sprom[SPROM_ET1MACADDR + 0] = vparm->u.mac[1];
197                 sprom[SPROM_ET1MACADDR + 3] = vparm->u.mac[2];
198                 sprom[SPROM_ET1MACADDR + 2] = vparm->u.mac[3];
199                 sprom[SPROM_ET1MACADDR + 5] = vparm->u.mac[4];
200                 sprom[SPROM_ET1MACADDR + 4] = vparm->u.mac[5];
201                 break;
202         case VALUE_ET0PHY:
203                 tmp |= sprom[SPROM_ETHPHY + 0];
204                 tmp |= sprom[SPROM_ETHPHY + 1] << 8;
205                 tmp = ((tmp & 0x001F) | (v & 0x1F));
206                 sprom[SPROM_ETHPHY + 0] = (tmp & 0x00FF);
207                 sprom[SPROM_ETHPHY + 1] = (tmp & 0xFF00) >> 8;
208                 break;
209         case VALUE_ET1PHY:
210                 tmp |= sprom[SPROM_ETHPHY + 0];
211                 tmp |= sprom[SPROM_ETHPHY + 1] << 8;
212                 tmp = ((tmp & 0x03E0) | ((v & 0x1F) << 5));
213                 sprom[SPROM_ETHPHY + 0] = (tmp & 0x00FF);
214                 sprom[SPROM_ETHPHY + 1] = (tmp & 0xFF00) >> 8;
215                 break;
216         case VALUE_ET0MDC:
217                 sprom[SPROM_ETHPHY + 1] &= ~(1 << 6);
218                 if (v)
219                         sprom[SPROM_ETHPHY + 1] |= (1 << 6);
220                 break;
221         case VALUE_ET1MDC:
222                 sprom[SPROM_ETHPHY + 1] &= ~(1 << 7);
223                 if (v)
224                         sprom[SPROM_ETHPHY + 1] |= (1 << 7);
225                 break;
226         case VALUE_BREV:
227                 sprom[SPROM_BOARDREV + 0] = v;
228                 break;
229         case VALUE_LOC:
230                 tmp = (sprom[SPROM_BOARDREV + 1] & 0xF0);
231                 tmp |= (v & 0x0F);
232                 sprom[SPROM_BOARDREV + 1] = (tmp & 0xFF);
233                 break;
234         case VALUE_ANTA0:
235                 sprom[SPROM_BOARDREV + 1] &= ~(1 << 4);
236                 if (v)
237                         sprom[SPROM_BOARDREV + 1] |= (1 << 4);
238                 break;
239         case VALUE_ANTA1:
240                 sprom[SPROM_BOARDREV + 1] &= ~(1 << 5);
241                 if (v)
242                         sprom[SPROM_BOARDREV + 1] |= (1 << 5);
243                 break;
244         case VALUE_ANTBG0:
245                 sprom[SPROM_BOARDREV + 1] &= ~(1 << 6);
246                 if (v)
247                         sprom[SPROM_BOARDREV + 1] |= (1 << 6);
248                 break;
249         case VALUE_ANTBG1:
250                 sprom[SPROM_BOARDREV + 1] &= ~(1 << 7);
251                 if (v)
252                         sprom[SPROM_BOARDREV + 1] |= (1 << 7);
253                 break;
254         case VALUE_ANTGA:
255                 sprom[SPROM_ANTENNA_GAIN + 0] = (v & 0xFF);
256                 break;
257         case VALUE_ANTGBG:
258                 sprom[SPROM_ANTENNA_GAIN + 1] = (v & 0xFF);
259                 break;
260         case VALUE_PA0B0:
261                 sprom[SPROM_PA0B0 + 0] = (v & 0x00FF);
262                 sprom[SPROM_PA0B0 + 1] = (v & 0xFF00) >> 8;
263                 break;
264         case VALUE_PA0B1:
265                 sprom[SPROM_PA0B1 + 0] = (v & 0x00FF);
266                 sprom[SPROM_PA0B1 + 1] = (v & 0xFF00) >> 8;
267                 break;
268         case VALUE_PA0B2:
269                 sprom[SPROM_PA0B2 + 0] = (v & 0x00FF);
270                 sprom[SPROM_PA0B2 + 1] = (v & 0xFF00) >> 8;
271                 break;
272         case VALUE_PA1B0:
273                 sprom[SPROM_PA1B0 + 0] = (v & 0x00FF);
274                 sprom[SPROM_PA1B0 + 1] = (v & 0xFF00) >> 8;
275                 break;
276         case VALUE_PA1B1:
277                 sprom[SPROM_PA1B1 + 0] = (v & 0x00FF);
278                 sprom[SPROM_PA1B1 + 1] = (v & 0xFF00) >> 8;
279                 break;
280         case VALUE_PA1B2:
281                 sprom[SPROM_PA1B2 + 0] = (v & 0x00FF);
282                 sprom[SPROM_PA1B2 + 1] = (v & 0xFF00) >> 8;
283                 break;
284         case VALUE_WL0GPIO0:
285                 sprom[SPROM_WL0GPIO0 + 0] = (v & 0xFF);
286                 break;
287         case VALUE_WL0GPIO1:
288                 sprom[SPROM_WL0GPIO0 + 1] = (v & 0xFF);
289                 break;
290         case VALUE_WL0GPIO2:
291                 sprom[SPROM_WL0GPIO2 + 0] = (v & 0xFF);
292                 break;
293         case VALUE_WL0GPIO3:
294                 sprom[SPROM_WL0GPIO2 + 1] = (v & 0xFF);
295                 break;
296         case VALUE_MAXPA:
297                 sprom[SPROM_MAXPWR + 0] = (v & 0xFF);
298                 break;
299         case VALUE_MAXPBG:
300                 sprom[SPROM_MAXPWR + 1] = (v & 0xFF);
301                 break;
302         case VALUE_ITSSIA:
303                 sprom[SPROM_IDL_TSSI_TGT + 0] = (v & 0xFF);
304                 break;
305         case VALUE_ITSSIBG:
306                 sprom[SPROM_IDL_TSSI_TGT + 1] = (v & 0xFF);
307                 break;
308         case VALUE_SVER:
309                 sprom[SPROM_VERSION + 0] = (v & 0xFF);
310                 break;
311         default:
312                 prerror("vparm->type internal error (0)\n");
313                 exit(1);
314         }
315
316         return 0;
317 }
318
319 static int modify_sprom(uint8_t *sprom)
320 {
321         struct cmdline_vparm *vparm;
322         int i;
323         int modified = 0;
324         uint8_t crc;
325
326         for (i = 0; i < cmdargs.nr_vparm; i++) {
327                 vparm = &(cmdargs.vparm[i]);
328                 if (!vparm->set)
329                         continue;
330                 modify_value(sprom, vparm);
331                 modified = 1;
332         }
333         if (modified) {
334                 /* Recalculate the CRC. */
335                 crc = sprom_crc(sprom);
336                 sprom[SPROM_VERSION + 1] = crc;
337         }
338
339         return modified;
340 }
341
342 static void display_value(const uint8_t *sprom,
343                           struct cmdline_vparm *vparm)
344 {
345         const char *desc;
346         uint8_t offset;
347         uint16_t value;
348         uint16_t tmp;
349
350         switch (vparm->type) {
351         case VALUE_RAW:
352                 desc = "RAW";
353                 offset = vparm->u.raw.offset;
354                 value = sprom[offset];
355                 break;
356         case VALUE_SUBP:
357                 desc = "Subsytem product ID";
358                 offset = SPROM_SUBP;
359                 value = sprom[SPROM_SUBP + 0];
360                 value |= sprom[SPROM_SUBP + 1] << 8;
361                 break;
362         case VALUE_SUBV:
363                 desc = "Subsystem vendor ID";
364                 offset = SPROM_SUBV;
365                 value = sprom[SPROM_SUBV + 0];
366                 value |= sprom[SPROM_SUBV + 1] << 8;
367                 break;
368         case VALUE_PPID:
369                 desc = "PCI Product ID";
370                 offset = SPROM_PPID;
371                 value = sprom[SPROM_PPID + 0];
372                 value |= sprom[SPROM_PPID + 1] << 8;
373                 break;
374         case VALUE_BFLHI:
375                 desc = "High 16 bits of Boardflags";
376                 offset = SPROM_BFLHI;
377                 value = sprom[SPROM_BFLHI + 0];
378                 value |= sprom[SPROM_BFLHI + 1] << 8;
379                 break;
380         case VALUE_BFL:
381                 desc = "Low 16 bits of Boardflags";
382                 offset = SPROM_BOARDFLAGS;
383                 value = sprom[SPROM_BOARDFLAGS + 0];
384                 value |= sprom[SPROM_BOARDFLAGS + 1] << 8;
385                 break;
386         case VALUE_BGMAC:
387                 desc = "MAC address for 802.11b/g";
388                 offset = SPROM_IL0MACADDR;
389                 value = 0;
390                 break;
391         case VALUE_ETMAC:
392                 desc = "MAC address for ethernet";
393                 offset = SPROM_ET0MACADDR;
394                 value = 0;
395                 break;
396         case VALUE_AMAC:
397                 desc = "MAC address for 802.11a";
398                 offset = SPROM_ET1MACADDR;
399                 value = 0;
400                 break;
401         case VALUE_ET0PHY:
402                 desc = "Ethernet phy settings (0)";
403                 offset = SPROM_ETHPHY;
404                 tmp = sprom[SPROM_ETHPHY + 0];
405                 tmp |= sprom[SPROM_ETHPHY + 1] << 8;
406                 value = (tmp & 0x001F);
407                 break;
408         case VALUE_ET1PHY:
409                 desc = "Ethernet phy settings (1)";
410                 offset = SPROM_ETHPHY;
411                 tmp = sprom[SPROM_ETHPHY + 0];
412                 tmp |= sprom[SPROM_ETHPHY + 1] << 8;
413                 value = (tmp & 0x03E0) >> 5;
414                 break;
415         case VALUE_ET0MDC:
416                 desc = "et0mdcport";
417                 offset = SPROM_ETHPHY + 1;
418                 value = 0;
419                 if (sprom[SPROM_ETHPHY + 1] & (1 << 6))
420                         value = 1;
421                 break;
422         case VALUE_ET1MDC:
423                 desc = "et1mdcport";
424                 offset = SPROM_ETHPHY + 1;
425                 value = 0;
426                 if (sprom[SPROM_ETHPHY + 1] & (1 << 7))
427                         value = 1;
428                 break;
429         case VALUE_BREV:
430                 desc = "Board revision";
431                 offset = SPROM_BOARDREV;
432                 value = sprom[SPROM_BOARDREV + 0];
433                 break;
434         case VALUE_LOC:
435                 desc = "Locale / Country Code";
436                 offset = SPROM_BOARDREV + 1;
437                 value = (sprom[SPROM_BOARDREV + 1] & 0x0F);
438                 break;
439         case VALUE_ANTA0:
440                 desc = "A PHY antenna 0 available";
441                 offset = SPROM_BOARDREV + 1;
442                 value = 0;
443                 if (sprom[SPROM_BOARDREV + 1] & (1 << 4))
444                         value = 1;
445                 break;
446         case VALUE_ANTA1:
447                 desc = "A PHY antenna 1 available";
448                 offset = SPROM_BOARDREV + 1;
449                 value = 0;
450                 if (sprom[SPROM_BOARDREV + 1] & (1 << 5))
451                         value = 1;
452                 break;
453         case VALUE_ANTBG0:
454                 desc = "B/G PHY antenna 0 available";
455                 offset = SPROM_BOARDREV + 1;
456                 value = 0;
457                 if (sprom[SPROM_BOARDREV + 1] & (1 << 6))
458                         value = 1;
459                 break;
460         case VALUE_ANTBG1:
461                 desc = "B/G PHY antenna 1 available";
462                 offset = SPROM_BOARDREV + 1;
463                 value = 0;
464                 if (sprom[SPROM_BOARDREV + 1] & (1 << 7))
465                         value = 1;
466                 break;
467         case VALUE_ANTGA:
468                 desc = "A PHY antenna gain";
469                 offset = SPROM_ANTENNA_GAIN;
470                 value = sprom[SPROM_ANTENNA_GAIN];
471                 break;
472         case VALUE_ANTGBG:
473                 desc = "B/G PHY antenna gain";
474                 offset = SPROM_ANTENNA_GAIN + 1;
475                 value = sprom[SPROM_ANTENNA_GAIN + 1];
476                 break;
477         case VALUE_PA0B0:
478                 desc = "pa0b0";
479                 offset = SPROM_PA0B0;
480                 value = sprom[offset + 0];
481                 value |= sprom[offset + 1] << 8;
482                 break;
483         case VALUE_PA0B1:
484                 desc = "pa0b1";
485                 offset = SPROM_PA0B1;
486                 value = sprom[offset + 0];
487                 value |= sprom[offset + 1] << 8;
488                 break;
489         case VALUE_PA0B2:
490                 desc = "pa0b2";
491                 offset = SPROM_PA0B2;
492                 value = sprom[offset + 0];
493                 value |= sprom[offset + 1] << 8;
494                 break;
495         case VALUE_PA1B0:
496                 desc = "pa1b0";
497                 offset = SPROM_PA1B0;
498                 value = sprom[offset + 0];
499                 value |= sprom[offset + 1] << 8;
500                 break;
501         case VALUE_PA1B1:
502                 desc = "pa1b1";
503                 offset = SPROM_PA1B1;
504                 value = sprom[offset + 0];
505                 value |= sprom[offset + 1] << 8;
506                 break;
507         case VALUE_PA1B2:
508                 desc = "pa1b2";
509                 offset = SPROM_PA1B2;
510                 value = sprom[offset + 0];
511                 value |= sprom[offset + 1] << 8;
512                 break;
513         case VALUE_WL0GPIO0:
514                 desc = "LED 0 behaviour";
515                 offset = SPROM_WL0GPIO0 + 0;
516                 value = sprom[offset];
517                 break;
518         case VALUE_WL0GPIO1:
519                 desc = "LED 1 behaviour";
520                 offset = SPROM_WL0GPIO0 + 1;
521                 value = sprom[offset];
522                 break;
523         case VALUE_WL0GPIO2:
524                 desc = "LED 2 behaviour";
525                 offset = SPROM_WL0GPIO2 + 0;
526                 value = sprom[offset];
527                 break;
528         case VALUE_WL0GPIO3:
529                 desc = "LED 3 behaviour";
530                 offset = SPROM_WL0GPIO2 + 1;
531                 value = sprom[offset];
532                 break;
533         case VALUE_MAXPA:
534                 desc = "A PHY max powerout";
535                 offset = SPROM_MAXPWR + 0;
536                 value = sprom[offset];
537                 break;
538         case VALUE_MAXPBG:
539                 desc = "B/G PHY max powerout";
540                 offset = SPROM_MAXPWR + 1;
541                 value = sprom[offset];
542                 break;
543         case VALUE_ITSSIA:
544                 desc = "A PHY idle TSSI target";
545                 offset = SPROM_IDL_TSSI_TGT + 0;
546                 value = sprom[offset];
547                 break;
548         case VALUE_ITSSIBG:
549                 desc = "B/G PHY idle TSSI target";
550                 offset = SPROM_IDL_TSSI_TGT + 1;
551                 value = sprom[offset];
552                 break;
553         case VALUE_SVER:
554                 desc = "SPROM version";
555                 offset = SPROM_VERSION;
556                 value = sprom[offset];
557                 break;
558         default:
559                 prerror("vparm->type internal error (1)\n");
560                 exit(1);
561         }
562
563         switch (vparm->bits) {
564         case 1:
565                 prdata("SPROM(0x%02X, %s) = %s\n",
566                        offset, desc, value ? "ON" : "OFF");
567                 break;
568         case 4:
569                 prdata("SPROM(0x%02X, %s) = 0x%01X\n",
570                        offset, desc, (value & 0xF));
571                 break;
572         case 8:
573                 prdata("SPROM(0x%02X, %s) = 0x%02X\n",
574                        offset, desc, (value & 0xFF));
575                 break;
576         case 16:
577                 prdata("SPROM(0x%02X, %s) = 0x%04X\n",
578                        offset, desc, (value & 0xFFFF));
579                 break;
580         case -1: {
581                 /* MAC address. */
582                 const uint8_t *p = &(sprom[offset]);
583
584                 prdata("SPROM(0x%02X, %s) = %02x:%02x:%02x:%02x:%02x:%02x\n",
585                        offset, desc,
586                        p[1], p[0], p[3], p[2], p[5], p[4]);
587                 break;
588         }
589         default:
590                 prerror("vparm->bits internal error (%d)\n",
591                         vparm->bits);
592                 exit(1);
593         }
594 }
595
596 static int display_sprom(const uint8_t *sprom)
597 {
598         struct cmdline_vparm *vparm;
599         int i;
600
601         for (i = 0; i < cmdargs.nr_vparm; i++) {
602                 vparm = &(cmdargs.vparm[i]);
603                 if (vparm->set)
604                         continue;
605                 display_value(sprom, vparm);
606         }
607
608         return 0;
609 }
610
611 static int validate_input(const uint8_t *sprom)
612 {
613         uint8_t crc, expected_crc;
614
615         crc = sprom_crc(sprom);
616         expected_crc = sprom[SPROM_VERSION + 1];
617         if (crc != expected_crc) {
618                 prerror("Corrupt input data (crc: 0x%02X, expected: 0x%02X)\n",
619                         crc, expected_crc);
620                 if (!cmdargs.force)
621                         return 1;
622         }
623
624         return 0;
625 }
626
627 static int parse_input(uint8_t *sprom, char *buffer, size_t bsize)
628 {
629         char *input;
630         size_t inlen;
631         size_t cnt;
632         unsigned long parsed;
633         char tmp[SPROM_SIZE * 2 + 10] = { 0 };
634
635         if (cmdargs.bin_mode) {
636                 /* The input buffer already contains
637                  * the binary sprom data.
638                  */
639                 internal_error_on(bsize != SPROM_SIZE);
640                 memcpy(sprom, buffer, SPROM_SIZE);
641                 return 0;
642         }
643
644         inlen = bsize;
645         input = strchr(buffer, ':');
646         if (input) {
647                 input++;
648                 inlen -= input - buffer;
649         } else
650                 input = buffer;
651
652         if (inlen < SPROM_SIZE * 2) {
653                 prerror("Input data too short\n");
654                 return -1;
655         }
656         for (cnt = 0; cnt < SPROM_SIZE; cnt++) {
657                 memcpy(tmp, input + cnt * 2, 2);
658                 parsed = strtoul(tmp, NULL, 16);
659                 sprom[cnt] = parsed & 0xFF;
660         }
661
662         if (cmdargs.verbose) {
663                 hexdump_sprom(sprom, tmp, sizeof(tmp));
664                 prinfo("Raw input:  %s\n", tmp);
665         }
666
667         return 0;
668 }
669
670 static int read_infile(int fd, char **buffer, size_t *bsize)
671 {
672         struct stat s;
673         int err;
674         ssize_t r;
675
676         err = fstat(fd, &s);
677         if (err) {
678                 prerror("Could not stat input file.\n");
679                 return err;
680         }
681         if (s.st_size == 0) {
682                 prerror("No input data\n");
683                 return -1;
684         }
685         if (cmdargs.bin_mode) {
686                 if (s.st_size != SPROM_SIZE) {
687                         prerror("The input data is no SPROM Binary data. "
688                                 "The size must be exactly %d bytes, "
689                                 "but it is %u bytes\n",
690                                 SPROM_SIZE, (unsigned int)(s.st_size));
691                         return -1;
692                 }
693         } else {
694                 if (s.st_size > 1024 * 1024) {
695                         prerror("The input data does not look "
696                                 "like SPROM HEX data (too long).\n");
697                         return -1;
698                 }
699         }
700
701         *bsize = s.st_size;
702         if (!cmdargs.bin_mode)
703                 (*bsize)++;
704         *buffer = malloce(*bsize);
705         r = read(fd, *buffer, s.st_size);
706         if (r != s.st_size) {
707                 prerror("Could not read input data.\n");
708                 return -1;
709         }
710         if (!cmdargs.bin_mode)
711                 (*buffer)[r] = '\0';
712
713         return 0;
714 }
715
716 static void close_infile(int fd)
717 {
718         if (cmdargs.infile)
719                 close(fd);
720 }
721
722 static void close_outfile(int fd)
723 {
724         if (cmdargs.outfile)
725                 close(fd);
726 }
727
728 static int open_infile(int *fd)
729 {
730         *fd = STDIN_FILENO;
731         if (!cmdargs.infile)
732                 return 0;
733         *fd = open(cmdargs.infile, O_RDONLY);
734         if (*fd < 0) {
735                 prerror("Could not open --infile %s\n",
736                         cmdargs.infile);
737                 return -1;
738         }
739
740         return 0;
741 }
742
743 static int open_outfile(int *fd)
744 {
745         *fd = STDOUT_FILENO;
746         if (!cmdargs.outfile)
747                 return 0;
748         *fd = open(cmdargs.outfile, O_RDWR | O_CREAT, 0644);
749         if (*fd < 0) {
750                 prerror("Could not open --outfile %s\n",
751                         cmdargs.outfile);
752                 return -1;
753         }
754
755         return 0;
756 }
757
758 static void print_banner(int forceprint)
759 {
760         const char *str = "Broadcom-SSB SPROM data modification tool version " VERSION "\n";
761         if (forceprint)
762                 prdata(str);
763         else
764                 prinfo(str);
765 }
766
767 static void print_usage(int argc, char *argv[])
768 {
769         print_banner(1);
770         prdata("\nUsage: %s [OPTION]\n", argv[0]);
771         prdata("  -i|--input FILE       Input file\n");
772         prdata("  -o|--output FILE      Output file\n");
773         prdata("  -b|--binmode          The Input data is plain binary data and Output will be binary\n");
774         prdata("  -V|--verbose          Be verbose\n");
775         prdata("  -f|--force            Override error checks\n");
776         prdata("  -v|--version          Print version\n");
777         prdata("  -h|--help             Print this help\n");
778         prdata("\n");
779         prdata("Value Parameters:\n");
780         prdata("\n");
781         prdata("  -s|--rawset OFF,VAL   Set a VALue at a byte-OFFset\n");
782         prdata("  -g|--rawget OFF       Get a value at a byte-OFFset\n");
783         prdata("\n");
784         prdata("Predefined values (for displaying (GET) or modification):\n");
785         prdata("  --subp [0xFFFF]       Subsytem product ID for PCI\n");
786         prdata("  --subv [0xFFFF]       Subsystem vendor ID for PCI\n");
787         prdata("  --ppid [0xFFFF]       Product ID for PCI\n");
788         prdata("  --bflhi [0xFFFF]      High 16 bits of boardflags (only if spromversion > 1)\n");
789         prdata("  --bfl [0xFFFF]        Low 16 bits of boardflags\n");
790         prdata("  --bgmac [MAC-ADDR]    MAC address for 802.11b/g\n");
791         prdata("  --etmac [MAC-ADDR]    MAC address for ethernet, see b44 driver\n");
792         prdata("  --amac [MAC-ADDR]     Mac address for 802.11a\n");
793         prdata("  --et0phy [0xFF]\n");
794         prdata("  --et1phy [0xFF]\n");
795         prdata("  --et0mdc [BOOL]\n");
796         prdata("  --et1mdc [BOOL]\n");
797         prdata("  --brev [0xFF]         Board revision\n");
798         prdata("  --loc [0xF]           Country code\n");
799         prdata("  --anta0 [BOOL]        Antenna 0 available for A PHY\n");
800         prdata("  --anta1 [BOOL]        Antenna 1 available for A PHY\n");
801         prdata("  --antbg0 [BOOL]       Antenna 0 available for B/G PHY\n");
802         prdata("  --antbg1 [BOOL]       Antenna 1 available for B/G PHY\n");
803         prdata("  --antga [0xFF]        Antenna gain for A PHY\n");
804         prdata("  --antgbg [0xFF]       Antenna gain for B/G PHY\n");
805         prdata("  --pa0b0 [0xFFFF]\n");
806         prdata("  --pa0b1 [0xFFFF]\n");
807         prdata("  --pa0b2 [0xFFFF]\n");
808         prdata("  --pa1b0 [0xFFFF]\n");
809         prdata("  --pa1b1 [0xFFFF]\n");
810         prdata("  --pa1b2 [0xFFFF]\n");
811         prdata("  --wl0gpio0 [0xFF]     LED 0 behaviour\n");
812         prdata("  --wl0gpio1 [0xFF]     LED 1 behaviour\n");
813         prdata("  --wl0gpio2 [0xFF]     LED 2 behaviour\n");
814         prdata("  --wl0gpio3 [0xFF]     LED 3 behaviour\n");
815         prdata("  --maxpa [0xFF]        A PHY max power\n");
816         prdata("  --maxpbg [0xFF]       B/G PHY max power\n");
817         prdata("  --itssia [0xFF]       Idle tssi target for A PHY\n");
818         prdata("  --itssibg [0xFF]      Idle tssi target for B/G PHY\n");
819         prdata("  --sver [0xFF]         SPROM-version\n");
820         prdata("\n");
821         prdata("  -P|--print-all        Display all values\n");
822         prdata("\n");
823         prdata(" BOOL      is a boolean value. Either 0 or 1\n");
824         prdata(" 0xF..     is a hexadecimal value\n");
825         prdata(" MAC-ADDR  is a MAC address in the format 00:00:00:00:00:00\n");
826         prdata(" If the value parameter is \"GET\", the value will be printed;\n");
827         prdata(" otherwise it is modified.\n");
828 }
829
830 #define ARG_MATCH               0
831 #define ARG_NOMATCH             1
832 #define ARG_ERROR               -1
833
834 static int do_cmp_arg(char **argv, int *pos,
835                       const char *template,
836                       int allow_merged,
837                       char **param)
838 {
839         char *arg;
840         char *next_arg;
841         size_t arg_len, template_len;
842
843         arg = argv[*pos];
844         next_arg = argv[*pos + 1];
845         arg_len = strlen(arg);
846         template_len = strlen(template);
847
848         if (param) {
849                 /* Maybe we have a merged parameter here.
850                  * A merged parameter is "-pfoobar" for example.
851                  */
852                 if (allow_merged && arg_len > template_len) {
853                         if (memcmp(arg, template, template_len) == 0) {
854                                 *param = arg + template_len;
855                                 return ARG_MATCH;
856                         }
857                         return ARG_NOMATCH;
858                 } else if (arg_len != template_len)
859                         return ARG_NOMATCH;
860                 *param = next_arg;
861         }
862         if (strcmp(arg, template) == 0) {
863                 if (param) {
864                         /* Skip the parameter on the next iteration. */
865                         (*pos)++;
866                         if (*param == 0) {
867                                 prerror("%s needs a parameter\n", arg);
868                                 return ARG_ERROR;
869                         }
870                 }
871                 return ARG_MATCH;
872         }
873
874         return ARG_NOMATCH;
875 }
876
877 /* Simple and lean command line argument parsing. */
878 static int cmp_arg(char **argv, int *pos,
879                    const char *long_template,
880                    const char *short_template,
881                    char **param)
882 {
883         int err;
884
885         if (long_template) {
886                 err = do_cmp_arg(argv, pos, long_template, 0, param);
887                 if (err == ARG_MATCH || err == ARG_ERROR)
888                         return err;
889         }
890         err = ARG_NOMATCH;
891         if (short_template)
892                 err = do_cmp_arg(argv, pos, short_template, 1, param);
893         return err;
894 }
895
896 static int parse_err;
897
898 static int arg_match(char **argv, int *i,
899                      const char *long_template,
900                      const char *short_template,
901                      char **param)
902 {
903         int res;
904
905         res = cmp_arg(argv, i, long_template,
906                       short_template, param);
907         if (res == ARG_ERROR) {
908                 parse_err = 1;
909                 return 0;
910         }
911         return (res == ARG_MATCH);
912 }
913
914 static int parse_value(const char *str,
915                        struct cmdline_vparm *vparm,
916                        const char *param)
917 {
918         unsigned long v;
919         int i;
920
921         vparm->bits = value_length_map[vparm->type];
922         vparm->set = 1;
923         if (strcmp(str, "GET") == 0 || strcmp(str, "get") == 0) {
924                 vparm->set = 0;
925                 return 0;
926         }
927         if (vparm->bits == 1) {
928                 /* This is a boolean value. */
929                 if (strcmp(str, "0") == 0)
930                         vparm->u.value = 0;
931                 else if (strcmp(str, "1") == 0)
932                         vparm->u.value = 1;
933                 else
934                         goto error_bool;
935                 return 1;
936         }
937
938         if (strncmp(str, "0x", 2) != 0)
939                 goto error;
940         str += 2;
941         for (i = 0; i < vparm->bits / 4; i++) {
942                 if (str[i] == '\0')
943                         goto error;
944         }
945         if (str[i] != '\0')
946                 goto error;
947         errno = 0;
948         v = strtoul(str, NULL, 16);
949         if (errno)
950                 goto error;
951         vparm->u.value = v;
952
953         return 1;
954 error:
955         if (param) {
956                 prerror("%s value parsing error. Format: 0x", param);
957                 for (i = 0; i < vparm->bits / 4; i++)
958                         prerror("F");
959                 prerror("\n");
960         }
961         return -1;
962
963 error_bool:
964         if (param)
965                 prerror("%s value parsing error. Format: 0 or 1 (boolean)\n", param);
966         return -1;
967 }
968
969 static int parse_mac(const char *str,
970                      struct cmdline_vparm *vparm,
971                      const char *param)
972 {
973         int i;
974         char *delim;
975         const char *in = str;
976         uint8_t *out = vparm->u.mac;
977
978         vparm->bits = -1;
979         vparm->set = 1;
980         if (strcmp(str, "GET") == 0 || strcmp(str, "get") == 0) {
981                 vparm->set = 0;
982                 return 0;
983         }
984
985         for (i = 0; ; i++) {
986                 errno = 0;
987                 out[i] = strtoul(in, NULL, 16);
988                 if (errno)
989                         goto error;
990                 if (i == 5) {
991                         if (in[1] != '\0' && in[2] != '\0')
992                                 goto error;
993                         break;
994                 }
995                 delim = strchr(in, ':');
996                 if (!delim)
997                         goto error;
998                 in = delim + 1;
999         }
1000
1001         return 1;
1002 error:
1003         prerror("%s MAC parsing error. Format: 00:00:00:00:00:00\n", param);
1004         return -1;
1005 }
1006
1007 static int parse_rawset(const char *str,
1008                         struct cmdline_vparm *vparm)
1009 {
1010         char *delim;
1011         uint8_t value;
1012         uint8_t offset;
1013         int err;
1014
1015         vparm->type = VALUE_RAW;
1016
1017         delim = strchr(str, ',');
1018         if (!delim)
1019                 goto error;
1020         *delim = '\0';
1021         err = parse_value(str, vparm, NULL);
1022         if (err != 1)
1023                 goto error;
1024         offset = vparm->u.value;
1025         if (offset >= SPROM_SIZE) {
1026                 prerror("--rawset offset too big (>= 0x%02X)\n",
1027                         SPROM_SIZE);
1028                 return -1;
1029         }
1030         err = parse_value(delim + 1, vparm, NULL);
1031         if (err != 1)
1032                 goto error;
1033         value = vparm->u.value;
1034
1035         vparm->u.raw.value = value;
1036         vparm->u.raw.offset = offset;
1037         vparm->set = 1;
1038
1039         return 0;
1040 error:
1041         prerror("--rawset value parsing error. Format: 0xFF,0xFF "
1042                 "(first Offset, second Value)\n");
1043         return -1;
1044 }
1045
1046 static int parse_rawget(const char *str,
1047                         struct cmdline_vparm *vparm)
1048 {
1049         int err;
1050         uint8_t offset;
1051
1052         vparm->type = VALUE_RAW;
1053
1054         err = parse_value(str, vparm, "--rawget");
1055         if (err != 1)
1056                 return -1;
1057         offset = vparm->u.value;
1058         if (offset >= SPROM_SIZE) {
1059                 prerror("--rawget offset too big (>= 0x%02X)\n",
1060                         SPROM_SIZE);
1061                 return -1;
1062         }
1063
1064         vparm->u.raw.offset = offset;
1065         vparm->type = VALUE_RAW;
1066         vparm->set = 0;
1067
1068         return 0;
1069 }
1070
1071 static int generate_printall(void)
1072 {
1073         struct cmdline_vparm *vparm;
1074         int count, i;
1075         enum valuetype vt = VALUE_FIRST;
1076
1077         count = VALUE_LAST - VALUE_FIRST + 1;
1078         for (i = 0; i < count; i++, vt++) {
1079                 if (cmdargs.nr_vparm == MAX_VPARM) {
1080                         prerror("Too many value parameters.\n");
1081                         return -1;
1082                 }
1083
1084                 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1085                 vparm->type = vt;
1086                 vparm->set = 0;
1087                 vparm->bits = value_length_map[vt];
1088         }
1089
1090         return 0;
1091 }
1092
1093 static int parse_args(int argc, char *argv[])
1094 {
1095         struct cmdline_vparm *vparm;
1096         int i, err;
1097         char *param;
1098
1099         parse_err = 0;
1100         for (i = 1; i < argc; i++) {
1101                 if (cmdargs.nr_vparm == MAX_VPARM) {
1102                         prerror("Too many value parameters.\n");
1103                         return -1;
1104                 }
1105
1106                 if (arg_match(argv, &i, "--version", "-v", 0)) {
1107                         print_banner(1);
1108                         return 1;
1109                 } else if (arg_match(argv, &i, "--help", "-h", 0)) {
1110                         goto out_usage;
1111                 } else if (arg_match(argv, &i, "--input", "-i", &param)) {
1112                         cmdargs.infile = param;
1113                 } else if (arg_match(argv, &i, "--output", "-o", &param)) {
1114                         cmdargs.outfile = param;
1115                 } else if (arg_match(argv, &i, "--verbose", "-V", 0)) {
1116                         cmdargs.verbose = 1;
1117                 } else if (arg_match(argv, &i, "--force", "-n", 0)) {
1118                         cmdargs.force = 1;
1119                 } else if (arg_match(argv, &i, "--binmode", "-b", 0)) {
1120                         cmdargs.bin_mode = 1;
1121
1122
1123                 } else if (arg_match(argv, &i, "--rawset", "-s", &param)) {
1124                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1125                         err = parse_rawset(param, vparm);
1126                         if (err < 0)
1127                                 goto error;
1128                 } else if (arg_match(argv, &i, "--rawget", "-g", &param)) {
1129                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1130                         err = parse_rawget(param, vparm);
1131                         if (err < 0)
1132                                 goto error;
1133
1134
1135                 } else if (arg_match(argv, &i, "--subp", 0, &param)) {
1136                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1137                         vparm->type = VALUE_SUBP;
1138                         err = parse_value(param, vparm, "--subp");
1139                         if (err < 0)
1140                                 goto error;
1141                 } else if (arg_match(argv, &i, "--subv", 0, &param)) {
1142                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1143                         vparm->type = VALUE_SUBV;
1144                         err = parse_value(param, vparm, "--subv");
1145                         if (err < 0)
1146                                 goto error;
1147                 } else if (arg_match(argv, &i, "--ppid", 0, &param)) {
1148                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1149                         vparm->type = VALUE_PPID;
1150                         err = parse_value(param, vparm, "--ppid");
1151                         if (err < 0)
1152                                 goto error;
1153                 } else if (arg_match(argv, &i, "--bflhi", 0, &param)) {
1154                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1155                         vparm->type = VALUE_BFLHI;
1156                         err = parse_value(param, vparm, "--bflhi");
1157                         if (err < 0)
1158                                 goto error;
1159                 } else if (arg_match(argv, &i, "--bfl", 0, &param)) {
1160                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1161                         vparm->type = VALUE_BFL;
1162                         err = parse_value(param, vparm, "--bfl");
1163                         if (err < 0)
1164                                 goto error;
1165                 } else if (arg_match(argv, &i, "--bgmac", 0, &param)) {
1166                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1167                         vparm->type = VALUE_BGMAC;
1168                         err = parse_mac(param, vparm, "--bgmac");
1169                         if (err < 0)
1170                                 goto error;
1171                 } else if (arg_match(argv, &i, "--etmac", 0, &param)) {
1172                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1173                         vparm->type = VALUE_ETMAC;
1174                         err = parse_mac(param, vparm, "--etmac");
1175                         if (err < 0)
1176                                 goto error;
1177                 } else if (arg_match(argv, &i, "--amac", 0, &param)) {
1178                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1179                         vparm->type = VALUE_AMAC;
1180                         err = parse_mac(param, vparm, "--amac");
1181                         if (err < 0)
1182                                 goto error;
1183                 } else if (arg_match(argv, &i, "--et0phy", 0, &param)) {
1184                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1185                         vparm->type = VALUE_ET0PHY;
1186                         err = parse_value(param, vparm, "--et0phy");
1187                         if (err < 0)
1188                                 goto error;
1189                 } else if (arg_match(argv, &i, "--et1phy", 0, &param)) {
1190                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1191                         vparm->type = VALUE_ET1PHY;
1192                         err = parse_value(param, vparm, "--et1phy");
1193                         if (err < 0)
1194                                 goto error;
1195                 } else if (arg_match(argv, &i, "--et0mdc", 0, &param)) {
1196                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1197                         vparm->type = VALUE_ET0MDC;
1198                         err = parse_value(param, vparm, "--et0mdc");
1199                         if (err < 0)
1200                                 goto error;
1201                 } else if (arg_match(argv, &i, "--et1mdc", 0, &param)) {
1202                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1203                         vparm->type = VALUE_ET1MDC;
1204                         err = parse_value(param, vparm, "--et1mdc");
1205                         if (err < 0)
1206                                 goto error;
1207                 } else if (arg_match(argv, &i, "--brev", 0, &param)) {
1208                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1209                         vparm->type = VALUE_BREV;
1210                         err = parse_value(param, vparm, "--brev");
1211                         if (err < 0)
1212                                 goto error;
1213                 } else if (arg_match(argv, &i, "--loc", 0, &param)) {
1214                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1215                         vparm->type = VALUE_LOC;
1216                         err = parse_value(param, vparm, "--loc");
1217                         if (err < 0)
1218                                 goto error;
1219                 } else if (arg_match(argv, &i, "--anta0", 0, &param)) {
1220                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1221                         vparm->type = VALUE_ANTA0;
1222                         err = parse_value(param, vparm, "--anta0");
1223                         if (err < 0)
1224                                 goto error;
1225                 } else if (arg_match(argv, &i, "--anta1", 0, &param)) {
1226                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1227                         vparm->type = VALUE_ANTA1;
1228                         err = parse_value(param, vparm, "--anta1");
1229                         if (err < 0)
1230                                 goto error;
1231                 } else if (arg_match(argv, &i, "--antbg0", 0, &param)) {
1232                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1233                         vparm->type = VALUE_ANTBG0;
1234                         err = parse_value(param, vparm, "--antbg0");
1235                         if (err < 0)
1236                                 goto error;
1237                 } else if (arg_match(argv, &i, "--antbg1", 0, &param)) {
1238                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1239                         vparm->type = VALUE_ANTBG1;
1240                         err = parse_value(param, vparm, "--antbg1");
1241                         if (err < 0)
1242                                 goto error;
1243                 } else if (arg_match(argv, &i, "--antga", 0, &param)) {
1244                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1245                         vparm->type = VALUE_ANTGA;
1246                         err = parse_value(param, vparm, "--antga");
1247                         if (err < 0)
1248                                 goto error;
1249                 } else if (arg_match(argv, &i, "--antgbg", 0, &param)) {
1250                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1251                         vparm->type = VALUE_ANTGBG;
1252                         err = parse_value(param, vparm, "--antgbg");
1253                         if (err < 0)
1254                                 goto error;
1255                 } else if (arg_match(argv, &i, "--pa0b0", 0, &param)) {
1256                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1257                         vparm->type = VALUE_PA0B0;
1258                         err = parse_value(param, vparm, "--pa0b0");
1259                         if (err < 0)
1260                                 goto error;
1261                 } else if (arg_match(argv, &i, "--pa0b1", 0, &param)) {
1262                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1263                         vparm->type = VALUE_PA0B1;
1264                         err = parse_value(param, vparm, "--pa0b1");
1265                         if (err < 0)
1266                                 goto error;
1267                 } else if (arg_match(argv, &i, "--pa0b2", 0, &param)) {
1268                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1269                         vparm->type = VALUE_PA0B2;
1270                         err = parse_value(param, vparm, "--pa0b2");
1271                         if (err < 0)
1272                                 goto error;
1273                 } else if (arg_match(argv, &i, "--pa1b0", 0, &param)) {
1274                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1275                         vparm->type = VALUE_PA1B0;
1276                         err = parse_value(param, vparm, "--pa1b0");
1277                         if (err < 0)
1278                                 goto error;
1279                 } else if (arg_match(argv, &i, "--pa1b1", 0, &param)) {
1280                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1281                         vparm->type = VALUE_PA1B1;
1282                         err = parse_value(param, vparm, "--pa1b1");
1283                         if (err < 0)
1284                                 goto error;
1285                 } else if (arg_match(argv, &i, "--pa1b2", 0, &param)) {
1286                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1287                         vparm->type = VALUE_PA1B2;
1288                         err = parse_value(param, vparm, "--pa1b2");
1289                         if (err < 0)
1290                                 goto error;
1291                 } else if (arg_match(argv, &i, "--wl0gpio0", 0, &param)) {
1292                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1293                         vparm->type = VALUE_WL0GPIO0;
1294                         err = parse_value(param, vparm, "--wl0gpio0");
1295                         if (err < 0)
1296                                 goto error;
1297                 } else if (arg_match(argv, &i, "--wl0gpio1", 0, &param)) {
1298                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1299                         vparm->type = VALUE_WL0GPIO1;
1300                         err = parse_value(param, vparm, "--wl0gpio1");
1301                         if (err < 0)
1302                                 goto error;
1303                 } else if (arg_match(argv, &i, "--wl0gpio2", 0, &param)) {
1304                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1305                         vparm->type = VALUE_WL0GPIO2;
1306                         err = parse_value(param, vparm, "--wl0gpio2");
1307                         if (err < 0)
1308                                 goto error;
1309                 } else if (arg_match(argv, &i, "--wl0gpio3", 0, &param)) {
1310                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1311                         vparm->type = VALUE_WL0GPIO3;
1312                         err = parse_value(param, vparm, "--wl0gpio3");
1313                         if (err < 0)
1314                                 goto error;
1315                 } else if (arg_match(argv, &i, "--maxpa", 0, &param)) {
1316                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1317                         vparm->type = VALUE_MAXPA;
1318                         err = parse_value(param, vparm, "--maxpa");
1319                         if (err < 0)
1320                                 goto error;
1321                 } else if (arg_match(argv, &i, "--maxpbg", 0, &param)) {
1322                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1323                         vparm->type = VALUE_MAXPBG;
1324                         err = parse_value(param, vparm, "--maxpbg");
1325                         if (err < 0)
1326                                 goto error;
1327                 } else if (arg_match(argv, &i, "--itssia", 0, &param)) {
1328                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1329                         vparm->type = VALUE_ITSSIA;
1330                         err = parse_value(param, vparm, "--itssia");
1331                         if (err < 0)
1332                                 goto error;
1333                 } else if (arg_match(argv, &i, "--itssibg", 0, &param)) {
1334                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1335                         vparm->type = VALUE_ITSSIBG;
1336                         err = parse_value(param, vparm, "--itssibg");
1337                         if (err < 0)
1338                                 goto error;
1339                 } else if (arg_match(argv, &i, "--sver", 0, &param)) {
1340                         vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1341                         vparm->type = VALUE_SVER;
1342                         err = parse_value(param, vparm, "--sver");
1343                         if (err < 0)
1344                                 goto error;
1345                 } else if (arg_match(argv, &i, "--print-all", "-P", 0)) {
1346                         err = generate_printall();
1347                         if (err)
1348                                 goto error;
1349                 } else {
1350                         prerror("Unrecognized argument: %s\n", argv[i]);
1351                         goto out_usage;
1352                 }
1353                 if (parse_err)
1354                         goto out_usage;
1355         }
1356         if (cmdargs.nr_vparm == 0) {
1357                 prerror("No Value parameter given. See --help.\n");
1358                 return -1;
1359         }
1360         return 0;
1361
1362 out_usage:
1363         print_usage(argc, argv);
1364 error:
1365         return -1;      
1366 }
1367
1368
1369 int main(int argc, char **argv)
1370 {
1371         int err;
1372         int fd;
1373         uint8_t sprom[SPROM_SIZE];
1374         char *buffer = NULL;
1375         size_t buffer_size = 0;
1376
1377         err = parse_args(argc, argv);
1378         if (err == 1)
1379                 return 0;
1380         else if (err != 0)
1381                 goto out;
1382
1383         print_banner(0);
1384         prinfo("\nReading input from \"%s\"...\n",
1385                cmdargs.infile ? cmdargs.infile : "stdin");
1386
1387         err = open_infile(&fd);
1388         if (err)
1389                 goto out;
1390         err = read_infile(fd, &buffer, &buffer_size);
1391         close_infile(fd);
1392         if (err)
1393                 goto out;
1394         err = parse_input(sprom, buffer, buffer_size);
1395         free(buffer);
1396         if (err)
1397                 goto out;
1398         err = validate_input(sprom);
1399         if (err)
1400                 goto out;
1401
1402         err = display_sprom(sprom);
1403         if (err)
1404                 goto out;
1405         err = modify_sprom(sprom);
1406         if (err < 0)
1407                 goto out;
1408         if (err) {
1409                 err = open_outfile(&fd);
1410                 if (err)
1411                         goto out;
1412                 err = write_output(fd, sprom);
1413                 close_outfile(fd);
1414                 if (err)
1415                         goto out;
1416                 prinfo("SPROM modified.\n");
1417         }
1418 out:
1419         return err;
1420 }