3 Broadcom Sonics Silicon Backplane bus SPROM data modification tool
5 Copyright (c) 2006-2008 Michael Buesch <mb@bu3sch.de>
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.
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.
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 Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
24 #include "ssb_sprom.h"
34 struct cmdline_args cmdargs;
38 static int value_length_map[] = { /* value to number of bits */
78 static int hexdump_sprom(const uint8_t *sprom, char *buffer, size_t bsize)
82 for (i = 0; i < sprom_size; i++) {
83 pos += snprintf(buffer + pos, bsize - pos - 1,
84 "%02X", sprom[i] & 0xFF);
90 static uint8_t sprom_crc(const uint8_t *sprom)
95 for (i = 0; i < sprom_size - 1; i++)
96 crc = crc8(crc, sprom[i]);
102 static int write_output_binary(int fd, const uint8_t *sprom)
106 w = write(fd, sprom, sprom_size);
113 static int write_output_hex(int fd, const uint8_t *sprom)
116 char tmp[SPROM4_SIZE * 2 + 10] = { 0 };
118 hexdump_sprom(sprom, tmp, sizeof(tmp));
119 prinfo("Raw output: %s\n", tmp);
120 w = write(fd, tmp, sprom_size * 2);
127 static int write_output(int fd, const uint8_t *sprom)
131 if (cmdargs.outfile) {
132 err = ftruncate(fd, 0);
134 prerror("Could not truncate --outfile %s\n",
140 if (cmdargs.bin_mode)
141 err = write_output_binary(fd, sprom);
143 err = write_output_hex(fd, sprom);
145 prerror("Could not write output data.\n");
150 static int modify_value(uint8_t *sprom,
151 struct cmdline_vparm *vparm)
153 const uint16_t v = vparm->u.value;
157 switch (vparm->type) {
159 sprom[vparm->u.raw.offset] = vparm->u.raw.value;
163 offset = SPROM4_SUBP;
166 sprom[offset + 0] = (v & 0x00FF);
167 sprom[offset + 1] = (v & 0xFF00) >> 8;
170 sprom[SPROM_SUBV + 0] = (v & 0x00FF);
171 sprom[SPROM_SUBV + 1] = (v & 0xFF00) >> 8;
175 offset = SPROM4_PPID;
178 sprom[offset + 0] = (v & 0x00FF);
179 sprom[offset + 1] = (v & 0xFF00) >> 8;
182 sprom[SPROM_BFLHI + 0] = (v & 0x00FF);
183 sprom[SPROM_BFLHI + 1] = (v & 0xFF00) >> 8;
186 sprom[SPROM_BOARDFLAGS + 0] = (v & 0x00FF);
187 sprom[SPROM_BOARDFLAGS + 1] = (v & 0xFF00) >> 8;
191 offset = SPROM3_IL0MACADDR;
192 else if (sprom_rev == 4)
193 offset = SPROM4_IL0MACADDR;
195 offset = SPROM_IL0MACADDR;
196 sprom[offset + 1] = vparm->u.mac[0];
197 sprom[offset + 0] = vparm->u.mac[1];
198 sprom[offset + 3] = vparm->u.mac[2];
199 sprom[offset + 2] = vparm->u.mac[3];
200 sprom[offset + 5] = vparm->u.mac[4];
201 sprom[offset + 4] = vparm->u.mac[5];
205 offset = SPROM3_ET0MACADDR;
206 else if (sprom_rev == 4)
207 offset = SPROM4_ET0MACADDR;
209 offset = SPROM_ET0MACADDR;
210 sprom[offset + 1] = vparm->u.mac[0];
211 sprom[offset + 0] = vparm->u.mac[1];
212 sprom[offset + 3] = vparm->u.mac[2];
213 sprom[offset + 2] = vparm->u.mac[3];
214 sprom[offset + 5] = vparm->u.mac[4];
215 sprom[offset + 4] = vparm->u.mac[5];
219 offset = SPROM3_ET1MACADDR;
220 else if (sprom_rev == 4)
221 offset = SPROM4_ET1MACADDR;
223 offset = SPROM_ET1MACADDR;
224 sprom[offset + 1] = vparm->u.mac[0];
225 sprom[offset + 0] = vparm->u.mac[1];
226 sprom[offset + 3] = vparm->u.mac[2];
227 sprom[offset + 2] = vparm->u.mac[3];
228 sprom[offset + 5] = vparm->u.mac[4];
229 sprom[offset + 4] = vparm->u.mac[5];
232 tmp |= sprom[SPROM_ETHPHY + 0];
233 tmp |= sprom[SPROM_ETHPHY + 1] << 8;
234 tmp = ((tmp & 0x001F) | (v & 0x1F));
235 sprom[SPROM_ETHPHY + 0] = (tmp & 0x00FF);
236 sprom[SPROM_ETHPHY + 1] = (tmp & 0xFF00) >> 8;
239 tmp |= sprom[SPROM_ETHPHY + 0];
240 tmp |= sprom[SPROM_ETHPHY + 1] << 8;
241 tmp = ((tmp & 0x03E0) | ((v & 0x1F) << 5));
242 sprom[SPROM_ETHPHY + 0] = (tmp & 0x00FF);
243 sprom[SPROM_ETHPHY + 1] = (tmp & 0xFF00) >> 8;
246 sprom[SPROM_ETHPHY + 1] &= ~(1 << 6);
248 sprom[SPROM_ETHPHY + 1] |= (1 << 6);
251 sprom[SPROM_ETHPHY + 1] &= ~(1 << 7);
253 sprom[SPROM_ETHPHY + 1] |= (1 << 7);
257 sprom[SPROM4_BOARDREV + 0] = v;
259 sprom[SPROM_BOARDREV + 0] = v;
262 tmp = (sprom[SPROM_BOARDREV + 1] & 0xF0);
264 sprom[SPROM_BOARDREV + 1] = (tmp & 0xFF);
268 sprom[SPROM4_BOARDREV + 1] &= ~(1 << 6);
270 sprom[SPROM_BOARDREV + 1] &= ~(1 << 6);
272 if (sprom_rev == 4) {
274 sprom[SPROM4_BOARDREV + 1] |= ~(1 << 6);
276 sprom[SPROM_BOARDREV + 1] |= (1 << 6);
281 sprom[SPROM_BOARDREV + 1] &= ~(1 << 7);
283 sprom[SPROM_BOARDREV + 1] |= (1 << 7);
286 sprom[SPROM_BOARDREV + 1] &= ~(1 << 4);
288 sprom[SPROM_BOARDREV + 1] |= (1 << 4);
291 sprom[SPROM_BOARDREV + 1] &= ~(1 << 5);
293 sprom[SPROM_BOARDREV + 1] |= (1 << 5);
297 sprom[SPROM_ANTENNA_GAIN + 1] = (v & 0xFF);
299 sprom[SPROM4_ANTENNA_GAIN + 1] = (v & 0xFF);
303 sprom[SPROM_ANTENNA_GAIN] = (v & 0xFF);
305 sprom[SPROM4_ANTENNA_GAIN] = (v & 0xFF);
308 sprom[SPROM_PA0B0 + 0] = (v & 0x00FF);
309 sprom[SPROM_PA0B0 + 1] = (v & 0xFF00) >> 8;
312 sprom[SPROM_PA0B1 + 0] = (v & 0x00FF);
313 sprom[SPROM_PA0B1 + 1] = (v & 0xFF00) >> 8;
316 sprom[SPROM_PA0B2 + 0] = (v & 0x00FF);
317 sprom[SPROM_PA0B2 + 1] = (v & 0xFF00) >> 8;
320 sprom[SPROM_PA1B0 + 0] = (v & 0x00FF);
321 sprom[SPROM_PA1B0 + 1] = (v & 0xFF00) >> 8;
324 sprom[SPROM_PA1B1 + 0] = (v & 0x00FF);
325 sprom[SPROM_PA1B1 + 1] = (v & 0xFF00) >> 8;
328 sprom[SPROM_PA1B2 + 0] = (v & 0x00FF);
329 sprom[SPROM_PA1B2 + 1] = (v & 0xFF00) >> 8;
332 sprom[SPROM_WL0GPIO0 + 0] = (v & 0xFF);
335 sprom[SPROM_WL0GPIO0 + 1] = (v & 0xFF);
338 sprom[SPROM_WL0GPIO2 + 0] = (v & 0xFF);
341 sprom[SPROM_WL0GPIO2 + 1] = (v & 0xFF);
344 sprom[SPROM_MAXPWR + 0] = (v & 0xFF);
347 sprom[SPROM_MAXPWR + 1] = (v & 0xFF);
350 sprom[SPROM_IDL_TSSI_TGT + 0] = (v & 0xFF);
353 sprom[SPROM_IDL_TSSI_TGT + 1] = (v & 0xFF);
357 sprom[SPROM_VERSION + 0] = (v & 0xFF);
359 sprom[SPROM4_VERSION + 0] = (v & 0xFF);
362 prerror("vparm->type internal error (0)\n");
369 static int modify_sprom(uint8_t *sprom)
371 struct cmdline_vparm *vparm;
376 for (i = 0; i < cmdargs.nr_vparm; i++) {
377 vparm = &(cmdargs.vparm[i]);
380 modify_value(sprom, vparm);
384 /* Recalculate the CRC. */
385 crc = sprom_crc(sprom);
386 sprom[sprom_size - 1] = crc;
392 static void display_value(const uint8_t *sprom,
393 struct cmdline_vparm *vparm)
400 switch (vparm->type) {
403 offset = vparm->u.raw.offset;
404 value = sprom[offset];
407 desc = "Subsystem product ID";
409 offset = SPROM4_SUBP;
412 value = sprom[offset + 0];
413 value |= sprom[offset + 1] << 8;
416 desc = "Subsystem vendor ID";
418 value = sprom[SPROM_SUBV + 0];
419 value |= sprom[SPROM_SUBV + 1] << 8;
422 desc = "PCI Product ID";
424 offset = SPROM4_PPID;
427 value = sprom[offset + 0];
428 value |= sprom[offset + 1] << 8;
431 desc = "High 16 bits of Boardflags";
433 offset = SPROM4_BOARDFLAGS + 2;
435 offset = SPROM_BFLHI;
436 value = sprom[offset + 0];
437 value |= sprom[offset + 1] << 8;
440 desc = "Low 16 bits of Boardflags";
442 offset = SPROM4_BOARDFLAGS;
444 offset = SPROM_BOARDFLAGS;
445 value = sprom[offset + 0];
446 value |= sprom[offset + 1] << 8;
449 desc = "MAC address for 802.11b/g";
451 offset = SPROM3_IL0MACADDR;
452 else if (sprom_rev == 4)
453 offset = SPROM4_IL0MACADDR;
455 offset = SPROM_IL0MACADDR;
459 desc = "MAC address for ethernet";
461 offset = SPROM3_ET0MACADDR;
462 else if (sprom_rev == 4)
463 offset = SPROM4_ET0MACADDR;
465 offset = SPROM_ET0MACADDR;
469 desc = "MAC address for 802.11a";
471 offset = SPROM3_ET1MACADDR;
472 else if (sprom_rev == 4)
473 offset = SPROM4_ET1MACADDR;
475 offset = SPROM_ET1MACADDR;
479 desc = "Ethernet phy settings (0)";
480 offset = SPROM_ETHPHY;
481 tmp = sprom[SPROM_ETHPHY + 0];
482 tmp |= sprom[SPROM_ETHPHY + 1] << 8;
483 value = (tmp & 0x001F);
486 desc = "Ethernet phy settings (1)";
487 offset = SPROM_ETHPHY;
488 tmp = sprom[SPROM_ETHPHY + 0];
489 tmp |= sprom[SPROM_ETHPHY + 1] << 8;
490 value = (tmp & 0x03E0) >> 5;
494 offset = SPROM_ETHPHY + 1;
496 if (sprom[SPROM_ETHPHY + 1] & (1 << 6))
501 offset = SPROM_ETHPHY + 1;
503 if (sprom[SPROM_ETHPHY + 1] & (1 << 7))
507 desc = "Board revision";
509 offset = SPROM4_BOARDREV;
511 offset = SPROM_BOARDREV;
512 value = sprom[offset + 0];
515 desc = "Locale / Country Code";
516 if (sprom_rev == 4) {
517 offset = SPROM4_COUNTRY;
518 value = sprom[offset] | (sprom[offset + 1] << 8);
520 offset = SPROM_BOARDREV;
521 value = (sprom[offset + 1] & 0x0F);
525 desc = "A PHY antenna 0 available";
527 if (sprom_rev == 4) {
528 offset = SPROM4_ANTAVAIL;
529 if (sprom[offset + 1] & 1)
532 offset = SPROM_BOARDREV;
534 if (sprom[offset + 2] & (1 << 6))
539 desc = "A PHY antenna 1 available";
541 if (sprom_rev == 4) {
542 offset = SPROM4_ANTAVAIL;
543 if (sprom[offset + 1] & 2)
546 offset = SPROM_BOARDREV;
548 if (sprom[offset + 2] & (1 << 7))
553 desc = "B/G PHY antenna 0 available";
555 if (sprom_rev == 4) {
556 offset = SPROM4_ANTAVAIL;
557 if (sprom[offset] & 1)
560 offset = SPROM_BOARDREV;
562 if (sprom[offset + 2] & (1 << 4))
567 desc = "B/G PHY antenna 1 available";
569 if (sprom_rev == 4) {
570 offset = SPROM4_ANTAVAIL;
571 if (sprom[offset] & 2)
574 offset = SPROM_BOARDREV;
576 if (sprom[offset + 2] & (1 << 5))
581 if (sprom_rev != 4) {
582 desc = "A PHY antenna gain";
583 offset = SPROM_ANTENNA_GAIN;
585 desc = "Antenna 1 Gain";
586 offset = SPROM4_ANTENNA_GAIN;
588 value = sprom[offset + 1];
591 if (sprom_rev != 4) {
592 desc = "B/G PHY antenna gain";
593 offset = SPROM_ANTENNA_GAIN;
595 desc = "Antenna 0 Gain";
596 offset = SPROM4_ANTENNA_GAIN;
598 value = sprom[offset];
602 offset = SPROM_PA0B0;
603 value = sprom[offset + 0];
604 value |= sprom[offset + 1] << 8;
608 offset = SPROM_PA0B1;
609 value = sprom[offset + 0];
610 value |= sprom[offset + 1] << 8;
614 offset = SPROM_PA0B2;
615 value = sprom[offset + 0];
616 value |= sprom[offset + 1] << 8;
620 offset = SPROM_PA1B0;
621 value = sprom[offset + 0];
622 value |= sprom[offset + 1] << 8;
626 offset = SPROM_PA1B1;
627 value = sprom[offset + 0];
628 value |= sprom[offset + 1] << 8;
632 offset = SPROM_PA1B2;
633 value = sprom[offset + 0];
634 value |= sprom[offset + 1] << 8;
637 desc = "LED 0 behaviour";
639 offset = SPROM_WL0GPIO0 + 0;
641 offset = SPROM4_WL0GPIO0 + 0;
642 value = sprom[offset];
645 desc = "LED 1 behaviour";
647 offset = SPROM_WL0GPIO0 + 1;
649 offset = SPROM4_WL0GPIO0 + 1;
650 value = sprom[offset];
653 desc = "LED 2 behaviour";
655 offset = SPROM_WL0GPIO2 + 0;
657 offset = SPROM4_WL0GPIO2 + 0;
658 value = sprom[offset];
661 desc = "LED 3 behaviour";
663 offset = SPROM_WL0GPIO2 + 1;
665 offset = SPROM4_WL0GPIO2 + 1;
666 value = sprom[offset];
669 desc = "A PHY max powerout";
671 offset = SPROM_MAXPWR + 1;
673 offset = SPROM4_MAXPWR + 1;
674 value = sprom[offset];
677 desc = "B/G PHY max powerout";
679 offset = SPROM_MAXPWR + 0;
681 offset = SPROM4_MAXPWR + 0;
682 value = sprom[offset];
685 desc = "A PHY idle TSSI target";
687 offset = SPROM_IDL_TSSI_TGT + 1;
689 offset = SPROM4_IDL_TSSI_TGT + 1;
690 value = sprom[offset];
693 desc = "B/G PHY idle TSSI target";
695 offset = SPROM_IDL_TSSI_TGT + 0;
697 offset = SPROM4_IDL_TSSI_TGT + 0;
698 value = sprom[offset];
701 desc = "SPROM version";
703 offset = SPROM_VERSION;
705 offset = SPROM4_VERSION;
706 value = sprom[offset];
709 prerror("vparm->type internal error (1)\n");
713 switch (vparm->bits) {
715 prdata("SPROM(0x%02X, %s) = %s\n",
716 offset, desc, value ? "ON" : "OFF");
719 prdata("SPROM(0x%02X, %s) = 0x%01X\n",
720 offset, desc, (value & 0xF));
723 prdata("SPROM(0x%02X, %s) = 0x%02X\n",
724 offset, desc, (value & 0xFF));
727 prdata("SPROM(0x%02X, %s) = 0x%04X\n",
728 offset, desc, (value & 0xFFFF));
732 const uint8_t *p = &(sprom[offset]);
734 prdata("SPROM(0x%02X, %s) = %02x:%02x:%02x:%02x:%02x:%02x\n",
736 p[1], p[0], p[3], p[2], p[5], p[4]);
740 prerror("vparm->bits internal error (%d)\n",
746 static int display_sprom(const uint8_t *sprom)
748 struct cmdline_vparm *vparm;
751 for (i = 0; i < cmdargs.nr_vparm; i++) {
752 vparm = &(cmdargs.vparm[i]);
755 display_value(sprom, vparm);
761 static int validate_input(const uint8_t *sprom)
763 uint8_t crc, expected_crc;
765 crc = sprom_crc(sprom);
766 expected_crc = sprom[sprom_size - 1];
768 if (crc != expected_crc) {
769 prerror("Corrupt input data (crc: 0x%02X, expected: 0x%02X)\n",
778 static int parse_input(uint8_t *sprom, char *buffer, size_t bsize)
783 unsigned long parsed;
784 char tmp[SPROM4_SIZE * 2 + 10] = { 0 };
786 if (cmdargs.bin_mode) {
787 /* The input buffer already contains
788 * the binary sprom data.
790 internal_error_on(bsize != SPROM_SIZE && bsize != SPROM4_SIZE);
791 memcpy(sprom, buffer, bsize);
796 input = strchr(buffer, ':');
799 inlen -= input - buffer;
803 if (inlen < SPROM_SIZE * 2) {
804 prerror("Input data too short\n");
807 for (cnt = 0; cnt < inlen / 2; cnt++) {
808 memcpy(tmp, input + cnt * 2, 2);
809 parsed = strtoul(tmp, NULL, 16);
810 sprom[cnt] = parsed & 0xFF;
812 /* check for "magic" data for V4 SPROM */
813 if (sprom[0x40] == 0x72 && sprom[0x41] == 0x53) {
814 sprom_rev = sprom[SPROM4_VERSION];
815 sprom_size = SPROM4_SIZE;
817 sprom_rev = sprom[SPROM_VERSION];
818 sprom_size = SPROM_SIZE;
821 if (cmdargs.verbose) {
822 hexdump_sprom(sprom, tmp, sizeof(tmp));
823 prinfo("Raw input: %s\n", tmp);
829 static int read_infile(int fd, char **buffer, size_t *bsize)
837 prerror("Could not stat input file.\n");
840 if (s.st_size == 0) {
841 prerror("No input data\n");
844 if (cmdargs.bin_mode) {
845 if (s.st_size != SPROM_SIZE && s.st_size != SPROM4_SIZE) {
846 prerror("The input data is no SPROM Binary data. "
847 "The size must be exactly %d (V1-3) "
849 "but it is %u bytes\n",
850 SPROM_SIZE, SPROM4_SIZE,
851 (unsigned int)(s.st_size));
855 if (s.st_size > 1024 * 1024) {
856 prerror("The input data does not look "
857 "like SPROM HEX data (too long).\n");
863 if (!cmdargs.bin_mode)
865 *buffer = malloce(*bsize);
866 r = read(fd, *buffer, s.st_size);
867 if (r != s.st_size) {
868 prerror("Could not read input data.\n");
871 if (!cmdargs.bin_mode)
877 static void close_infile(int fd)
883 static void close_outfile(int fd)
889 static int open_infile(int *fd)
894 *fd = open(cmdargs.infile, O_RDONLY);
896 prerror("Could not open --infile %s\n",
904 static int open_outfile(int *fd)
907 if (!cmdargs.outfile)
909 *fd = open(cmdargs.outfile, O_RDWR | O_CREAT, 0644);
911 prerror("Could not open --outfile %s\n",
919 static void print_banner(int forceprint)
921 const char *str = "Broadcom-SSB SPROM data modification tool.\n"
923 "Copyright (C) Michael Buesch\n"
924 "Licensed under the GNU/GPL version 2 or later\n"
926 "DO NOT USE THIS TOOL. YOU WILL BRICK YOUR DEVICE.\n";
933 static void print_usage(int argc, char *argv[])
936 prdata("\nUsage: %s [OPTION]\n", argv[0]);
937 prdata(" -i|--input FILE Input file\n");
938 prdata(" -o|--output FILE Output file\n");
939 prdata(" -b|--binmode The Input data is plain binary data and Output will be binary\n");
940 prdata(" -V|--verbose Be verbose\n");
941 prdata(" -f|--force Override error checks\n");
942 prdata(" -v|--version Print version\n");
943 prdata(" -h|--help Print this help\n");
945 prdata("Value Parameters:\n");
947 prdata(" -s|--rawset OFF,VAL Set a VALue at a byte-OFFset\n");
948 prdata(" -g|--rawget OFF Get a value at a byte-OFFset\n");
950 prdata("Predefined values (for displaying (GET) or modification):\n");
951 prdata(" --subp [0xFFFF] Subsystem product ID for PCI\n");
952 prdata(" --subv [0xFFFF] Subsystem vendor ID for PCI\n");
953 prdata(" --ppid [0xFFFF] Product ID for PCI\n");
954 prdata(" --bflhi [0xFFFF] High 16 bits of boardflags (only if spromversion > 1)\n");
955 prdata(" --bfl [0xFFFF] Low 16 bits of boardflags\n");
956 prdata(" --bgmac [MAC-ADDR] MAC address for 802.11b/g\n");
957 prdata(" --etmac [MAC-ADDR] MAC address for ethernet, see b44 driver\n");
958 prdata(" --amac [MAC-ADDR] Mac address for 802.11a\n");
959 prdata(" --et0phy [0xFF]\n");
960 prdata(" --et1phy [0xFF]\n");
961 prdata(" --et0mdc [BOOL]\n");
962 prdata(" --et1mdc [BOOL]\n");
963 prdata(" --brev [0xFF] Board revision\n");
964 prdata(" --loc [0xF] Country code\n");
965 prdata(" --anta0 [BOOL] Antenna 0 available for A PHY\n");
966 prdata(" --anta1 [BOOL] Antenna 1 available for A PHY\n");
967 prdata(" --antbg0 [BOOL] Antenna 0 available for B/G PHY\n");
968 prdata(" --antbg1 [BOOL] Antenna 1 available for B/G PHY\n");
969 prdata(" --antga [0xFF] Antenna gain for A PHY\n");
970 prdata(" --antgbg [0xFF] Antenna gain for B/G PHY\n");
971 prdata(" --pa0b0 [0xFFFF]\n");
972 prdata(" --pa0b1 [0xFFFF]\n");
973 prdata(" --pa0b2 [0xFFFF]\n");
974 prdata(" --pa1b0 [0xFFFF]\n");
975 prdata(" --pa1b1 [0xFFFF]\n");
976 prdata(" --pa1b2 [0xFFFF]\n");
977 prdata(" --wl0gpio0 [0xFF] LED 0 behaviour\n");
978 prdata(" --wl0gpio1 [0xFF] LED 1 behaviour\n");
979 prdata(" --wl0gpio2 [0xFF] LED 2 behaviour\n");
980 prdata(" --wl0gpio3 [0xFF] LED 3 behaviour\n");
981 prdata(" --maxpa [0xFF] A PHY max power\n");
982 prdata(" --maxpbg [0xFF] B/G PHY max power\n");
983 prdata(" --itssia [0xFF] Idle tssi target for A PHY\n");
984 prdata(" --itssibg [0xFF] Idle tssi target for B/G PHY\n");
985 prdata(" --sver [0xFF] SPROM-version\n");
987 prdata(" -P|--print-all Display all values\n");
989 prdata(" BOOL is a boolean value. Either 0 or 1\n");
990 prdata(" 0xF.. is a hexadecimal value\n");
991 prdata(" MAC-ADDR is a MAC address in the format 00:00:00:00:00:00\n");
992 prdata(" If the value parameter is \"GET\", the value will be printed;\n");
993 prdata(" otherwise it is modified.\n");
997 #define ARG_NOMATCH 1
1000 static int do_cmp_arg(char **argv, int *pos,
1001 const char *template,
1007 size_t arg_len, template_len;
1010 next_arg = argv[*pos + 1];
1011 arg_len = strlen(arg);
1012 template_len = strlen(template);
1015 /* Maybe we have a merged parameter here.
1016 * A merged parameter is "-pfoobar" for example.
1018 if (allow_merged && arg_len > template_len) {
1019 if (memcmp(arg, template, template_len) == 0) {
1020 *param = arg + template_len;
1024 } else if (arg_len != template_len)
1028 if (strcmp(arg, template) == 0) {
1031 prerror("%s needs a parameter\n", arg);
1034 /* Skip the parameter on the next iteration. */
1043 /* Simple and lean command line argument parsing. */
1044 static int cmp_arg(char **argv, int *pos,
1045 const char *long_template,
1046 const char *short_template,
1051 if (long_template) {
1052 err = do_cmp_arg(argv, pos, long_template, 0, param);
1053 if (err == ARG_MATCH || err == ARG_ERROR)
1058 err = do_cmp_arg(argv, pos, short_template, 1, param);
1062 static int parse_err;
1064 static int arg_match(char **argv, int *i,
1065 const char *long_template,
1066 const char *short_template,
1071 res = cmp_arg(argv, i, long_template,
1072 short_template, param);
1073 if (res == ARG_ERROR) {
1077 return (res == ARG_MATCH);
1080 static int parse_value(const char *str,
1081 struct cmdline_vparm *vparm,
1087 vparm->bits = value_length_map[vparm->type];
1089 if (strcmp(str, "GET") == 0 || strcmp(str, "get") == 0) {
1093 if (vparm->bits == 1) {
1094 /* This is a boolean value. */
1095 if (strcmp(str, "0") == 0)
1097 else if (strcmp(str, "1") == 0)
1104 if (strncmp(str, "0x", 2) != 0)
1107 /* The following logic presents a problem because the offsets
1108 * for V4 SPROMs can be greater than 0xFF; however, the arguments
1109 * are parsed before the SPROM revision is known. To fix this
1110 * problem, if an input is expecting 0xFF-type input, then input
1111 * of 0xFFF will be permitted */
1112 for (i = 0; i < vparm->bits / 4; i++) {
1116 if (str[i] != '\0') {
1118 i++; /* add an extra character */
1123 v = strtoul(str, NULL, 16);
1131 prerror("%s value parsing error. Format: 0x", param);
1132 for (i = 0; i < vparm->bits / 4; i++)
1140 prerror("%s value parsing error. Format: 0 or 1 (boolean)\n", param);
1144 static int parse_mac(const char *str,
1145 struct cmdline_vparm *vparm,
1150 const char *in = str;
1151 uint8_t *out = vparm->u.mac;
1155 if (strcmp(str, "GET") == 0 || strcmp(str, "get") == 0) {
1160 for (i = 0; ; i++) {
1162 out[i] = strtoul(in, NULL, 16);
1166 if (in[1] != '\0' && in[2] != '\0')
1170 delim = strchr(in, ':');
1178 prerror("%s MAC parsing error. Format: 00:00:00:00:00:00\n", param);
1182 static int parse_rawset(const char *str,
1183 struct cmdline_vparm *vparm)
1190 vparm->type = VALUE_RAW;
1192 delim = strchr(str, ',');
1196 err = parse_value(str, vparm, NULL);
1199 offset = vparm->u.value;
1200 if (offset >= SPROM4_SIZE) {
1201 prerror("--rawset offset too big (>= 0x%02X)\n",
1205 err = parse_value(delim + 1, vparm, NULL);
1208 value = vparm->u.value;
1210 vparm->u.raw.value = value;
1211 vparm->u.raw.offset = offset;
1216 prerror("--rawset value parsing error. Format: 0xFF,0xFF "
1217 "(first Offset, second Value)\n");
1221 static int parse_rawget(const char *str,
1222 struct cmdline_vparm *vparm)
1227 vparm->type = VALUE_RAW;
1229 err = parse_value(str, vparm, "--rawget");
1232 offset = vparm->u.value;
1233 if (offset >= SPROM4_SIZE) {
1234 prerror("--rawget offset too big (>= 0x%02X)\n",
1239 vparm->u.raw.offset = offset;
1240 vparm->type = VALUE_RAW;
1246 static int generate_printall(void)
1248 struct cmdline_vparm *vparm;
1250 enum valuetype vt = VALUE_FIRST;
1252 count = VALUE_LAST - VALUE_FIRST + 1;
1253 for (i = 0; i < count; i++, vt++) {
1254 if (cmdargs.nr_vparm == MAX_VPARM) {
1255 prerror("Too many value parameters.\n");
1259 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1262 vparm->bits = value_length_map[vt];
1268 static int parse_args(int argc, char *argv[])
1270 struct cmdline_vparm *vparm;
1275 for (i = 1; i < argc; i++) {
1276 if (cmdargs.nr_vparm == MAX_VPARM) {
1277 prerror("Too many value parameters.\n");
1281 if (arg_match(argv, &i, "--version", "-v", 0)) {
1284 } else if (arg_match(argv, &i, "--help", "-h", 0)) {
1286 } else if (arg_match(argv, &i, "--input", "-i", ¶m)) {
1287 cmdargs.infile = param;
1288 } else if (arg_match(argv, &i, "--output", "-o", ¶m)) {
1289 cmdargs.outfile = param;
1290 } else if (arg_match(argv, &i, "--verbose", "-V", 0)) {
1291 cmdargs.verbose = 1;
1292 } else if (arg_match(argv, &i, "--force", "-n", 0)) {
1294 } else if (arg_match(argv, &i, "--binmode", "-b", 0)) {
1295 cmdargs.bin_mode = 1;
1298 } else if (arg_match(argv, &i, "--rawset", "-s", ¶m)) {
1299 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1300 err = parse_rawset(param, vparm);
1303 } else if (arg_match(argv, &i, "--rawget", "-g", ¶m)) {
1304 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1305 err = parse_rawget(param, vparm);
1310 } else if (arg_match(argv, &i, "--subp", 0, ¶m)) {
1311 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1312 vparm->type = VALUE_SUBP;
1313 err = parse_value(param, vparm, "--subp");
1316 } else if (arg_match(argv, &i, "--subv", 0, ¶m)) {
1317 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1318 vparm->type = VALUE_SUBV;
1319 err = parse_value(param, vparm, "--subv");
1322 } else if (arg_match(argv, &i, "--ppid", 0, ¶m)) {
1323 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1324 vparm->type = VALUE_PPID;
1325 err = parse_value(param, vparm, "--ppid");
1328 } else if (arg_match(argv, &i, "--bflhi", 0, ¶m)) {
1329 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1330 vparm->type = VALUE_BFLHI;
1331 err = parse_value(param, vparm, "--bflhi");
1334 } else if (arg_match(argv, &i, "--bfl", 0, ¶m)) {
1335 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1336 vparm->type = VALUE_BFL;
1337 err = parse_value(param, vparm, "--bfl");
1340 } else if (arg_match(argv, &i, "--bgmac", 0, ¶m)) {
1341 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1342 vparm->type = VALUE_BGMAC;
1343 err = parse_mac(param, vparm, "--bgmac");
1346 } else if (arg_match(argv, &i, "--etmac", 0, ¶m)) {
1347 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1348 vparm->type = VALUE_ETMAC;
1349 err = parse_mac(param, vparm, "--etmac");
1352 } else if (arg_match(argv, &i, "--amac", 0, ¶m)) {
1353 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1354 vparm->type = VALUE_AMAC;
1355 err = parse_mac(param, vparm, "--amac");
1358 } else if (arg_match(argv, &i, "--et0phy", 0, ¶m)) {
1359 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1360 vparm->type = VALUE_ET0PHY;
1361 err = parse_value(param, vparm, "--et0phy");
1364 } else if (arg_match(argv, &i, "--et1phy", 0, ¶m)) {
1365 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1366 vparm->type = VALUE_ET1PHY;
1367 err = parse_value(param, vparm, "--et1phy");
1370 } else if (arg_match(argv, &i, "--et0mdc", 0, ¶m)) {
1371 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1372 vparm->type = VALUE_ET0MDC;
1373 err = parse_value(param, vparm, "--et0mdc");
1376 } else if (arg_match(argv, &i, "--et1mdc", 0, ¶m)) {
1377 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1378 vparm->type = VALUE_ET1MDC;
1379 err = parse_value(param, vparm, "--et1mdc");
1382 } else if (arg_match(argv, &i, "--brev", 0, ¶m)) {
1383 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1384 vparm->type = VALUE_BREV;
1385 err = parse_value(param, vparm, "--brev");
1388 } else if (arg_match(argv, &i, "--loc", 0, ¶m)) {
1389 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1390 vparm->type = VALUE_LOC;
1391 err = parse_value(param, vparm, "--loc");
1394 } else if (arg_match(argv, &i, "--anta0", 0, ¶m)) {
1395 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1396 vparm->type = VALUE_ANTA0;
1397 err = parse_value(param, vparm, "--anta0");
1400 } else if (arg_match(argv, &i, "--anta1", 0, ¶m)) {
1401 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1402 vparm->type = VALUE_ANTA1;
1403 err = parse_value(param, vparm, "--anta1");
1406 } else if (arg_match(argv, &i, "--antbg0", 0, ¶m)) {
1407 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1408 vparm->type = VALUE_ANTBG0;
1409 err = parse_value(param, vparm, "--antbg0");
1412 } else if (arg_match(argv, &i, "--antbg1", 0, ¶m)) {
1413 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1414 vparm->type = VALUE_ANTBG1;
1415 err = parse_value(param, vparm, "--antbg1");
1418 } else if (arg_match(argv, &i, "--antga", 0, ¶m)) {
1419 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1420 vparm->type = VALUE_ANTGA;
1421 err = parse_value(param, vparm, "--antga");
1424 } else if (arg_match(argv, &i, "--antgbg", 0, ¶m)) {
1425 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1426 vparm->type = VALUE_ANTGBG;
1427 err = parse_value(param, vparm, "--antgbg");
1430 } else if (arg_match(argv, &i, "--pa0b0", 0, ¶m)) {
1431 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1432 vparm->type = VALUE_PA0B0;
1433 err = parse_value(param, vparm, "--pa0b0");
1436 } else if (arg_match(argv, &i, "--pa0b1", 0, ¶m)) {
1437 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1438 vparm->type = VALUE_PA0B1;
1439 err = parse_value(param, vparm, "--pa0b1");
1442 } else if (arg_match(argv, &i, "--pa0b2", 0, ¶m)) {
1443 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1444 vparm->type = VALUE_PA0B2;
1445 err = parse_value(param, vparm, "--pa0b2");
1448 } else if (arg_match(argv, &i, "--pa1b0", 0, ¶m)) {
1449 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1450 vparm->type = VALUE_PA1B0;
1451 err = parse_value(param, vparm, "--pa1b0");
1454 } else if (arg_match(argv, &i, "--pa1b1", 0, ¶m)) {
1455 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1456 vparm->type = VALUE_PA1B1;
1457 err = parse_value(param, vparm, "--pa1b1");
1460 } else if (arg_match(argv, &i, "--pa1b2", 0, ¶m)) {
1461 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1462 vparm->type = VALUE_PA1B2;
1463 err = parse_value(param, vparm, "--pa1b2");
1466 } else if (arg_match(argv, &i, "--wl0gpio0", 0, ¶m)) {
1467 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1468 vparm->type = VALUE_WL0GPIO0;
1469 err = parse_value(param, vparm, "--wl0gpio0");
1472 } else if (arg_match(argv, &i, "--wl0gpio1", 0, ¶m)) {
1473 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1474 vparm->type = VALUE_WL0GPIO1;
1475 err = parse_value(param, vparm, "--wl0gpio1");
1478 } else if (arg_match(argv, &i, "--wl0gpio2", 0, ¶m)) {
1479 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1480 vparm->type = VALUE_WL0GPIO2;
1481 err = parse_value(param, vparm, "--wl0gpio2");
1484 } else if (arg_match(argv, &i, "--wl0gpio3", 0, ¶m)) {
1485 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1486 vparm->type = VALUE_WL0GPIO3;
1487 err = parse_value(param, vparm, "--wl0gpio3");
1490 } else if (arg_match(argv, &i, "--maxpa", 0, ¶m)) {
1491 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1492 vparm->type = VALUE_MAXPA;
1493 err = parse_value(param, vparm, "--maxpa");
1496 } else if (arg_match(argv, &i, "--maxpbg", 0, ¶m)) {
1497 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1498 vparm->type = VALUE_MAXPBG;
1499 err = parse_value(param, vparm, "--maxpbg");
1502 } else if (arg_match(argv, &i, "--itssia", 0, ¶m)) {
1503 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1504 vparm->type = VALUE_ITSSIA;
1505 err = parse_value(param, vparm, "--itssia");
1508 } else if (arg_match(argv, &i, "--itssibg", 0, ¶m)) {
1509 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1510 vparm->type = VALUE_ITSSIBG;
1511 err = parse_value(param, vparm, "--itssibg");
1514 } else if (arg_match(argv, &i, "--sver", 0, ¶m)) {
1515 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1516 vparm->type = VALUE_SVER;
1517 err = parse_value(param, vparm, "--sver");
1520 } else if (arg_match(argv, &i, "--print-all", "-P", 0)) {
1521 err = generate_printall();
1526 prerror("Unrecognized argument: %s\n", argv[i]);
1532 if (cmdargs.nr_vparm == 0) {
1533 prerror("No Value parameter given. See --help.\n");
1539 print_usage(argc, argv);
1545 int main(int argc, char **argv)
1549 uint8_t sprom[SPROM4_SIZE + 10];
1550 char *buffer = NULL;
1551 size_t buffer_size = 0;
1553 err = parse_args(argc, argv);
1560 prinfo("\nReading input from \"%s\"...\n",
1561 cmdargs.infile ? cmdargs.infile : "stdin");
1563 err = open_infile(&fd);
1566 err = read_infile(fd, &buffer, &buffer_size);
1570 err = parse_input(sprom, buffer, buffer_size);
1574 err = validate_input(sprom);
1578 err = display_sprom(sprom);
1581 err = modify_sprom(sprom);
1585 err = open_outfile(&fd);
1588 err = write_output(fd, sprom);
1592 prinfo("SPROM modified.\n");