3 Broadcom Sonics Silicon Backplane bus SPROM data modification tool
5 Copyright (c) 2006-2007 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);
296 sprom[SPROM_ANTENNA_GAIN + 0] = (v & 0xFF);
299 sprom[SPROM_ANTENNA_GAIN + 1] = (v & 0xFF);
302 sprom[SPROM_PA0B0 + 0] = (v & 0x00FF);
303 sprom[SPROM_PA0B0 + 1] = (v & 0xFF00) >> 8;
306 sprom[SPROM_PA0B1 + 0] = (v & 0x00FF);
307 sprom[SPROM_PA0B1 + 1] = (v & 0xFF00) >> 8;
310 sprom[SPROM_PA0B2 + 0] = (v & 0x00FF);
311 sprom[SPROM_PA0B2 + 1] = (v & 0xFF00) >> 8;
314 sprom[SPROM_PA1B0 + 0] = (v & 0x00FF);
315 sprom[SPROM_PA1B0 + 1] = (v & 0xFF00) >> 8;
318 sprom[SPROM_PA1B1 + 0] = (v & 0x00FF);
319 sprom[SPROM_PA1B1 + 1] = (v & 0xFF00) >> 8;
322 sprom[SPROM_PA1B2 + 0] = (v & 0x00FF);
323 sprom[SPROM_PA1B2 + 1] = (v & 0xFF00) >> 8;
326 sprom[SPROM_WL0GPIO0 + 0] = (v & 0xFF);
329 sprom[SPROM_WL0GPIO0 + 1] = (v & 0xFF);
332 sprom[SPROM_WL0GPIO2 + 0] = (v & 0xFF);
335 sprom[SPROM_WL0GPIO2 + 1] = (v & 0xFF);
338 sprom[SPROM_MAXPWR + 0] = (v & 0xFF);
341 sprom[SPROM_MAXPWR + 1] = (v & 0xFF);
344 sprom[SPROM_IDL_TSSI_TGT + 0] = (v & 0xFF);
347 sprom[SPROM_IDL_TSSI_TGT + 1] = (v & 0xFF);
351 sprom[SPROM_VERSION + 0] = (v & 0xFF);
353 sprom[SPROM4_VERSION + 0] = (v & 0xFF);
356 prerror("vparm->type internal error (0)\n");
363 static int modify_sprom(uint8_t *sprom)
365 struct cmdline_vparm *vparm;
370 for (i = 0; i < cmdargs.nr_vparm; i++) {
371 vparm = &(cmdargs.vparm[i]);
374 modify_value(sprom, vparm);
378 /* Recalculate the CRC. */
379 crc = sprom_crc(sprom);
380 sprom[sprom_size - 1] = crc;
386 static void display_value(const uint8_t *sprom,
387 struct cmdline_vparm *vparm)
394 switch (vparm->type) {
397 offset = vparm->u.raw.offset;
398 value = sprom[offset];
401 desc = "Subsystem product ID";
403 offset = SPROM4_SUBP;
406 value = sprom[offset + 0];
407 value |= sprom[offset + 1] << 8;
410 desc = "Subsystem vendor ID";
412 value = sprom[SPROM_SUBV + 0];
413 value |= sprom[SPROM_SUBV + 1] << 8;
416 desc = "PCI Product ID";
418 offset = SPROM4_PPID;
421 value = sprom[offset + 0];
422 value |= sprom[offset + 1] << 8;
425 desc = "High 16 bits of Boardflags";
427 offset = SPROM4_BOARDFLAGS + 2;
429 offset = SPROM_BFLHI;
430 value = sprom[offset + 0];
431 value |= sprom[offset + 1] << 8;
434 desc = "Low 16 bits of Boardflags";
436 offset = SPROM4_BOARDFLAGS;
438 offset = SPROM_BOARDFLAGS;
439 value = sprom[offset + 0];
440 value |= sprom[offset + 1] << 8;
443 desc = "MAC address for 802.11b/g";
445 offset = SPROM3_IL0MACADDR;
446 else if (sprom_rev == 4)
447 offset = SPROM4_IL0MACADDR;
449 offset = SPROM_IL0MACADDR;
453 desc = "MAC address for ethernet";
455 offset = SPROM3_ET0MACADDR;
456 else if (sprom_rev == 4)
457 offset = SPROM4_ET0MACADDR;
459 offset = SPROM_ET0MACADDR;
463 desc = "MAC address for 802.11a";
465 offset = SPROM3_ET1MACADDR;
466 else if (sprom_rev == 4)
467 offset = SPROM4_ET1MACADDR;
469 offset = SPROM_ET1MACADDR;
473 desc = "Ethernet phy settings (0)";
474 offset = SPROM_ETHPHY;
475 tmp = sprom[SPROM_ETHPHY + 0];
476 tmp |= sprom[SPROM_ETHPHY + 1] << 8;
477 value = (tmp & 0x001F);
480 desc = "Ethernet phy settings (1)";
481 offset = SPROM_ETHPHY;
482 tmp = sprom[SPROM_ETHPHY + 0];
483 tmp |= sprom[SPROM_ETHPHY + 1] << 8;
484 value = (tmp & 0x03E0) >> 5;
488 offset = SPROM_ETHPHY + 1;
490 if (sprom[SPROM_ETHPHY + 1] & (1 << 6))
495 offset = SPROM_ETHPHY + 1;
497 if (sprom[SPROM_ETHPHY + 1] & (1 << 7))
501 desc = "Board revision";
503 offset = SPROM4_BOARDREV;
505 offset = SPROM_BOARDREV;
506 value = sprom[offset + 0];
509 desc = "Locale / Country Code";
510 if (sprom_rev == 4) {
511 offset = SPROM4_COUNTRY;
512 value = sprom[offset] | (sprom[offset + 1] << 8);
514 offset = SPROM_BOARDREV;
515 value = (sprom[offset + 1] & 0x0F);
519 desc = "A PHY antenna 0 available";
521 if (sprom_rev == 4) {
522 offset = SPROM4_ANTAVAIL;
523 if (sprom[offset + 1] & 1)
526 offset = SPROM_BOARDREV;
528 if (sprom[offset + 2] & (1 << 6))
533 desc = "A PHY antenna 1 available";
535 if (sprom_rev == 4) {
536 offset = SPROM4_ANTAVAIL;
537 if (sprom[offset + 1] & 2)
540 offset = SPROM_BOARDREV;
542 if (sprom[offset + 2] & (1 << 7))
547 desc = "B/G PHY antenna 0 available";
549 if (sprom_rev == 4) {
550 offset = SPROM4_ANTAVAIL;
551 if (sprom[offset] & 1)
554 offset = SPROM_BOARDREV;
556 if (sprom[offset + 2] & (1 << 4))
561 desc = "B/G PHY antenna 1 available";
563 if (sprom_rev == 4) {
564 offset = SPROM4_ANTAVAIL;
565 if (sprom[offset] & 2)
568 offset = SPROM_BOARDREV;
570 if (sprom[offset + 2] & (1 << 5))
575 if (sprom_rev != 4) {
576 desc = "A PHY antenna gain";
577 offset = SPROM_ANTENNA_GAIN;
579 desc = "Antenna 1 Gain";
580 offset = SPROM4_ANTENNA_GAIN;
582 value = sprom[offset + 1];
585 if (sprom_rev != 4) {
586 desc = "B/G PHY antenna gain";
587 offset = SPROM_ANTENNA_GAIN;
589 desc = "Antenna 0 Gain";
590 offset = SPROM4_ANTENNA_GAIN;
592 value = sprom[offset];
596 offset = SPROM_PA0B0;
597 value = sprom[offset + 0];
598 value |= sprom[offset + 1] << 8;
602 offset = SPROM_PA0B1;
603 value = sprom[offset + 0];
604 value |= sprom[offset + 1] << 8;
608 offset = SPROM_PA0B2;
609 value = sprom[offset + 0];
610 value |= sprom[offset + 1] << 8;
614 offset = SPROM_PA1B0;
615 value = sprom[offset + 0];
616 value |= sprom[offset + 1] << 8;
620 offset = SPROM_PA1B1;
621 value = sprom[offset + 0];
622 value |= sprom[offset + 1] << 8;
626 offset = SPROM_PA1B2;
627 value = sprom[offset + 0];
628 value |= sprom[offset + 1] << 8;
631 desc = "LED 0 behaviour";
633 offset = SPROM_WL0GPIO0 + 0;
635 offset = SPROM4_WL0GPIO0 + 0;
636 value = sprom[offset];
639 desc = "LED 1 behaviour";
641 offset = SPROM_WL0GPIO0 + 1;
643 offset = SPROM4_WL0GPIO0 + 1;
644 value = sprom[offset];
647 desc = "LED 2 behaviour";
649 offset = SPROM_WL0GPIO2 + 0;
651 offset = SPROM4_WL0GPIO2 + 0;
652 value = sprom[offset];
655 desc = "LED 3 behaviour";
657 offset = SPROM_WL0GPIO2 + 1;
659 offset = SPROM4_WL0GPIO2 + 1;
660 value = sprom[offset];
663 desc = "A PHY max powerout";
665 offset = SPROM_MAXPWR + 1;
667 offset = SPROM4_MAXPWR + 1;
668 value = sprom[offset];
671 desc = "B/G PHY max powerout";
673 offset = SPROM_MAXPWR + 0;
675 offset = SPROM4_MAXPWR + 0;
676 value = sprom[offset];
679 desc = "A PHY idle TSSI target";
681 offset = SPROM_IDL_TSSI_TGT + 1;
683 offset = SPROM4_IDL_TSSI_TGT + 1;
684 value = sprom[offset];
687 desc = "B/G PHY idle TSSI target";
689 offset = SPROM_IDL_TSSI_TGT + 0;
691 offset = SPROM4_IDL_TSSI_TGT + 0;
692 value = sprom[offset];
695 desc = "SPROM version";
697 offset = SPROM_VERSION;
699 offset = SPROM4_VERSION;
700 value = sprom[offset];
703 prerror("vparm->type internal error (1)\n");
707 switch (vparm->bits) {
709 prdata("SPROM(0x%02X, %s) = %s\n",
710 offset, desc, value ? "ON" : "OFF");
713 prdata("SPROM(0x%02X, %s) = 0x%01X\n",
714 offset, desc, (value & 0xF));
717 prdata("SPROM(0x%02X, %s) = 0x%02X\n",
718 offset, desc, (value & 0xFF));
721 prdata("SPROM(0x%02X, %s) = 0x%04X\n",
722 offset, desc, (value & 0xFFFF));
726 const uint8_t *p = &(sprom[offset]);
728 prdata("SPROM(0x%02X, %s) = %02x:%02x:%02x:%02x:%02x:%02x\n",
730 p[1], p[0], p[3], p[2], p[5], p[4]);
734 prerror("vparm->bits internal error (%d)\n",
740 static int display_sprom(const uint8_t *sprom)
742 struct cmdline_vparm *vparm;
745 for (i = 0; i < cmdargs.nr_vparm; i++) {
746 vparm = &(cmdargs.vparm[i]);
749 display_value(sprom, vparm);
755 static int validate_input(const uint8_t *sprom)
757 uint8_t crc, expected_crc;
759 crc = sprom_crc(sprom);
760 expected_crc = sprom[sprom_size - 1];
762 if (crc != expected_crc) {
763 prerror("Corrupt input data (crc: 0x%02X, expected: 0x%02X)\n",
772 static int parse_input(uint8_t *sprom, char *buffer, size_t bsize)
777 unsigned long parsed;
778 char tmp[SPROM4_SIZE * 2 + 10] = { 0 };
780 if (cmdargs.bin_mode) {
781 /* The input buffer already contains
782 * the binary sprom data.
784 internal_error_on(bsize != SPROM_SIZE && bsize != SPROM4_SIZE);
785 memcpy(sprom, buffer, bsize);
790 input = strchr(buffer, ':');
793 inlen -= input - buffer;
797 if (inlen < SPROM_SIZE * 2) {
798 prerror("Input data too short\n");
801 for (cnt = 0; cnt < inlen / 2; cnt++) {
802 memcpy(tmp, input + cnt * 2, 2);
803 parsed = strtoul(tmp, NULL, 16);
804 sprom[cnt] = parsed & 0xFF;
806 /* check for "magic" data for V4 SPROM */
807 if (sprom[0x40] == 0x72 && sprom[0x41] == 0x53) {
808 sprom_rev = sprom[SPROM4_VERSION];
809 sprom_size = SPROM4_SIZE;
811 sprom_rev = sprom[SPROM_VERSION];
812 sprom_size = SPROM_SIZE;
815 if (cmdargs.verbose) {
816 hexdump_sprom(sprom, tmp, sizeof(tmp));
817 prinfo("Raw input: %s\n", tmp);
823 static int read_infile(int fd, char **buffer, size_t *bsize)
831 prerror("Could not stat input file.\n");
834 if (s.st_size == 0) {
835 prerror("No input data\n");
838 if (cmdargs.bin_mode) {
839 if (s.st_size != SPROM_SIZE && s.st_size != SPROM4_SIZE) {
840 prerror("The input data is no SPROM Binary data. "
841 "The size must be exactly %d (V1-3) "
843 "but it is %u bytes\n",
844 SPROM_SIZE, SPROM4_SIZE,
845 (unsigned int)(s.st_size));
849 if (s.st_size > 1024 * 1024) {
850 prerror("The input data does not look "
851 "like SPROM HEX data (too long).\n");
857 if (!cmdargs.bin_mode)
859 *buffer = malloce(*bsize);
860 r = read(fd, *buffer, s.st_size);
861 if (r != s.st_size) {
862 prerror("Could not read input data.\n");
865 if (!cmdargs.bin_mode)
871 static void close_infile(int fd)
877 static void close_outfile(int fd)
883 static int open_infile(int *fd)
888 *fd = open(cmdargs.infile, O_RDONLY);
890 prerror("Could not open --infile %s\n",
898 static int open_outfile(int *fd)
901 if (!cmdargs.outfile)
903 *fd = open(cmdargs.outfile, O_RDWR | O_CREAT, 0644);
905 prerror("Could not open --outfile %s\n",
913 static void print_banner(int forceprint)
915 const char *str = "Broadcom-SSB SPROM data modification tool version " VERSION "\n";
922 static void print_usage(int argc, char *argv[])
925 prdata("\nUsage: %s [OPTION]\n", argv[0]);
926 prdata(" -i|--input FILE Input file\n");
927 prdata(" -o|--output FILE Output file\n");
928 prdata(" -b|--binmode The Input data is plain binary data and Output will be binary\n");
929 prdata(" -V|--verbose Be verbose\n");
930 prdata(" -f|--force Override error checks\n");
931 prdata(" -v|--version Print version\n");
932 prdata(" -h|--help Print this help\n");
934 prdata("Value Parameters:\n");
936 prdata(" -s|--rawset OFF,VAL Set a VALue at a byte-OFFset\n");
937 prdata(" -g|--rawget OFF Get a value at a byte-OFFset\n");
939 prdata("Predefined values (for displaying (GET) or modification):\n");
940 prdata(" --subp [0xFFFF] Subsystem product ID for PCI\n");
941 prdata(" --subv [0xFFFF] Subsystem vendor ID for PCI\n");
942 prdata(" --ppid [0xFFFF] Product ID for PCI\n");
943 prdata(" --bflhi [0xFFFF] High 16 bits of boardflags (only if spromversion > 1)\n");
944 prdata(" --bfl [0xFFFF] Low 16 bits of boardflags\n");
945 prdata(" --bgmac [MAC-ADDR] MAC address for 802.11b/g\n");
946 prdata(" --etmac [MAC-ADDR] MAC address for ethernet, see b44 driver\n");
947 prdata(" --amac [MAC-ADDR] Mac address for 802.11a\n");
948 prdata(" --et0phy [0xFF]\n");
949 prdata(" --et1phy [0xFF]\n");
950 prdata(" --et0mdc [BOOL]\n");
951 prdata(" --et1mdc [BOOL]\n");
952 prdata(" --brev [0xFF] Board revision\n");
953 prdata(" --loc [0xF] Country code\n");
954 prdata(" --anta0 [BOOL] Antenna 0 available for A PHY\n");
955 prdata(" --anta1 [BOOL] Antenna 1 available for A PHY\n");
956 prdata(" --antbg0 [BOOL] Antenna 0 available for B/G PHY\n");
957 prdata(" --antbg1 [BOOL] Antenna 1 available for B/G PHY\n");
958 prdata(" --antga [0xFF] Antenna gain for A PHY\n");
959 prdata(" --antgbg [0xFF] Antenna gain for B/G PHY\n");
960 prdata(" --pa0b0 [0xFFFF]\n");
961 prdata(" --pa0b1 [0xFFFF]\n");
962 prdata(" --pa0b2 [0xFFFF]\n");
963 prdata(" --pa1b0 [0xFFFF]\n");
964 prdata(" --pa1b1 [0xFFFF]\n");
965 prdata(" --pa1b2 [0xFFFF]\n");
966 prdata(" --wl0gpio0 [0xFF] LED 0 behaviour\n");
967 prdata(" --wl0gpio1 [0xFF] LED 1 behaviour\n");
968 prdata(" --wl0gpio2 [0xFF] LED 2 behaviour\n");
969 prdata(" --wl0gpio3 [0xFF] LED 3 behaviour\n");
970 prdata(" --maxpa [0xFF] A PHY max power\n");
971 prdata(" --maxpbg [0xFF] B/G PHY max power\n");
972 prdata(" --itssia [0xFF] Idle tssi target for A PHY\n");
973 prdata(" --itssibg [0xFF] Idle tssi target for B/G PHY\n");
974 prdata(" --sver [0xFF] SPROM-version\n");
976 prdata(" -P|--print-all Display all values\n");
978 prdata(" BOOL is a boolean value. Either 0 or 1\n");
979 prdata(" 0xF.. is a hexadecimal value\n");
980 prdata(" MAC-ADDR is a MAC address in the format 00:00:00:00:00:00\n");
981 prdata(" If the value parameter is \"GET\", the value will be printed;\n");
982 prdata(" otherwise it is modified.\n");
986 #define ARG_NOMATCH 1
989 static int do_cmp_arg(char **argv, int *pos,
990 const char *template,
996 size_t arg_len, template_len;
999 next_arg = argv[*pos + 1];
1000 arg_len = strlen(arg);
1001 template_len = strlen(template);
1004 /* Maybe we have a merged parameter here.
1005 * A merged parameter is "-pfoobar" for example.
1007 if (allow_merged && arg_len > template_len) {
1008 if (memcmp(arg, template, template_len) == 0) {
1009 *param = arg + template_len;
1013 } else if (arg_len != template_len)
1017 if (strcmp(arg, template) == 0) {
1020 prerror("%s needs a parameter\n", arg);
1023 /* Skip the parameter on the next iteration. */
1032 /* Simple and lean command line argument parsing. */
1033 static int cmp_arg(char **argv, int *pos,
1034 const char *long_template,
1035 const char *short_template,
1040 if (long_template) {
1041 err = do_cmp_arg(argv, pos, long_template, 0, param);
1042 if (err == ARG_MATCH || err == ARG_ERROR)
1047 err = do_cmp_arg(argv, pos, short_template, 1, param);
1051 static int parse_err;
1053 static int arg_match(char **argv, int *i,
1054 const char *long_template,
1055 const char *short_template,
1060 res = cmp_arg(argv, i, long_template,
1061 short_template, param);
1062 if (res == ARG_ERROR) {
1066 return (res == ARG_MATCH);
1069 static int parse_value(const char *str,
1070 struct cmdline_vparm *vparm,
1076 vparm->bits = value_length_map[vparm->type];
1078 if (strcmp(str, "GET") == 0 || strcmp(str, "get") == 0) {
1082 if (vparm->bits == 1) {
1083 /* This is a boolean value. */
1084 if (strcmp(str, "0") == 0)
1086 else if (strcmp(str, "1") == 0)
1093 if (strncmp(str, "0x", 2) != 0)
1096 /* The following logic presents a problem because the offsets
1097 * for V4 SPROMs can be greater than 0xFF; however, the arguments
1098 * are parsed before the SPROM revision is known. To fix this
1099 * problem, if an input is expecting 0xFF-type input, then input
1100 * of 0xFFF will be permitted */
1101 for (i = 0; i < vparm->bits / 4; i++) {
1105 if (str[i] != '\0') {
1107 i++; /* add an extra character */
1112 v = strtoul(str, NULL, 16);
1120 prerror("%s value parsing error. Format: 0x", param);
1121 for (i = 0; i < vparm->bits / 4; i++)
1129 prerror("%s value parsing error. Format: 0 or 1 (boolean)\n", param);
1133 static int parse_mac(const char *str,
1134 struct cmdline_vparm *vparm,
1139 const char *in = str;
1140 uint8_t *out = vparm->u.mac;
1144 if (strcmp(str, "GET") == 0 || strcmp(str, "get") == 0) {
1149 for (i = 0; ; i++) {
1151 out[i] = strtoul(in, NULL, 16);
1155 if (in[1] != '\0' && in[2] != '\0')
1159 delim = strchr(in, ':');
1167 prerror("%s MAC parsing error. Format: 00:00:00:00:00:00\n", param);
1171 static int parse_rawset(const char *str,
1172 struct cmdline_vparm *vparm)
1179 vparm->type = VALUE_RAW;
1181 delim = strchr(str, ',');
1185 err = parse_value(str, vparm, NULL);
1188 offset = vparm->u.value;
1189 if (offset >= SPROM4_SIZE) {
1190 prerror("--rawset offset too big (>= 0x%02X)\n",
1194 err = parse_value(delim + 1, vparm, NULL);
1197 value = vparm->u.value;
1199 vparm->u.raw.value = value;
1200 vparm->u.raw.offset = offset;
1205 prerror("--rawset value parsing error. Format: 0xFF,0xFF "
1206 "(first Offset, second Value)\n");
1210 static int parse_rawget(const char *str,
1211 struct cmdline_vparm *vparm)
1216 vparm->type = VALUE_RAW;
1218 err = parse_value(str, vparm, "--rawget");
1221 offset = vparm->u.value;
1222 if (offset >= SPROM4_SIZE) {
1223 prerror("--rawget offset too big (>= 0x%02X)\n",
1228 vparm->u.raw.offset = offset;
1229 vparm->type = VALUE_RAW;
1235 static int generate_printall(void)
1237 struct cmdline_vparm *vparm;
1239 enum valuetype vt = VALUE_FIRST;
1241 count = VALUE_LAST - VALUE_FIRST + 1;
1242 for (i = 0; i < count; i++, vt++) {
1243 if (cmdargs.nr_vparm == MAX_VPARM) {
1244 prerror("Too many value parameters.\n");
1248 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1251 vparm->bits = value_length_map[vt];
1257 static int parse_args(int argc, char *argv[])
1259 struct cmdline_vparm *vparm;
1264 for (i = 1; i < argc; i++) {
1265 if (cmdargs.nr_vparm == MAX_VPARM) {
1266 prerror("Too many value parameters.\n");
1270 if (arg_match(argv, &i, "--version", "-v", 0)) {
1273 } else if (arg_match(argv, &i, "--help", "-h", 0)) {
1275 } else if (arg_match(argv, &i, "--input", "-i", ¶m)) {
1276 cmdargs.infile = param;
1277 } else if (arg_match(argv, &i, "--output", "-o", ¶m)) {
1278 cmdargs.outfile = param;
1279 } else if (arg_match(argv, &i, "--verbose", "-V", 0)) {
1280 cmdargs.verbose = 1;
1281 } else if (arg_match(argv, &i, "--force", "-n", 0)) {
1283 } else if (arg_match(argv, &i, "--binmode", "-b", 0)) {
1284 cmdargs.bin_mode = 1;
1287 } else if (arg_match(argv, &i, "--rawset", "-s", ¶m)) {
1288 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1289 err = parse_rawset(param, vparm);
1292 } else if (arg_match(argv, &i, "--rawget", "-g", ¶m)) {
1293 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1294 err = parse_rawget(param, vparm);
1299 } else if (arg_match(argv, &i, "--subp", 0, ¶m)) {
1300 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1301 vparm->type = VALUE_SUBP;
1302 err = parse_value(param, vparm, "--subp");
1305 } else if (arg_match(argv, &i, "--subv", 0, ¶m)) {
1306 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1307 vparm->type = VALUE_SUBV;
1308 err = parse_value(param, vparm, "--subv");
1311 } else if (arg_match(argv, &i, "--ppid", 0, ¶m)) {
1312 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1313 vparm->type = VALUE_PPID;
1314 err = parse_value(param, vparm, "--ppid");
1317 } else if (arg_match(argv, &i, "--bflhi", 0, ¶m)) {
1318 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1319 vparm->type = VALUE_BFLHI;
1320 err = parse_value(param, vparm, "--bflhi");
1323 } else if (arg_match(argv, &i, "--bfl", 0, ¶m)) {
1324 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1325 vparm->type = VALUE_BFL;
1326 err = parse_value(param, vparm, "--bfl");
1329 } else if (arg_match(argv, &i, "--bgmac", 0, ¶m)) {
1330 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1331 vparm->type = VALUE_BGMAC;
1332 err = parse_mac(param, vparm, "--bgmac");
1335 } else if (arg_match(argv, &i, "--etmac", 0, ¶m)) {
1336 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1337 vparm->type = VALUE_ETMAC;
1338 err = parse_mac(param, vparm, "--etmac");
1341 } else if (arg_match(argv, &i, "--amac", 0, ¶m)) {
1342 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1343 vparm->type = VALUE_AMAC;
1344 err = parse_mac(param, vparm, "--amac");
1347 } else if (arg_match(argv, &i, "--et0phy", 0, ¶m)) {
1348 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1349 vparm->type = VALUE_ET0PHY;
1350 err = parse_value(param, vparm, "--et0phy");
1353 } else if (arg_match(argv, &i, "--et1phy", 0, ¶m)) {
1354 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1355 vparm->type = VALUE_ET1PHY;
1356 err = parse_value(param, vparm, "--et1phy");
1359 } else if (arg_match(argv, &i, "--et0mdc", 0, ¶m)) {
1360 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1361 vparm->type = VALUE_ET0MDC;
1362 err = parse_value(param, vparm, "--et0mdc");
1365 } else if (arg_match(argv, &i, "--et1mdc", 0, ¶m)) {
1366 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1367 vparm->type = VALUE_ET1MDC;
1368 err = parse_value(param, vparm, "--et1mdc");
1371 } else if (arg_match(argv, &i, "--brev", 0, ¶m)) {
1372 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1373 vparm->type = VALUE_BREV;
1374 err = parse_value(param, vparm, "--brev");
1377 } else if (arg_match(argv, &i, "--loc", 0, ¶m)) {
1378 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1379 vparm->type = VALUE_LOC;
1380 err = parse_value(param, vparm, "--loc");
1383 } else if (arg_match(argv, &i, "--anta0", 0, ¶m)) {
1384 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1385 vparm->type = VALUE_ANTA0;
1386 err = parse_value(param, vparm, "--anta0");
1389 } else if (arg_match(argv, &i, "--anta1", 0, ¶m)) {
1390 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1391 vparm->type = VALUE_ANTA1;
1392 err = parse_value(param, vparm, "--anta1");
1395 } else if (arg_match(argv, &i, "--antbg0", 0, ¶m)) {
1396 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1397 vparm->type = VALUE_ANTBG0;
1398 err = parse_value(param, vparm, "--antbg0");
1401 } else if (arg_match(argv, &i, "--antbg1", 0, ¶m)) {
1402 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1403 vparm->type = VALUE_ANTBG1;
1404 err = parse_value(param, vparm, "--antbg1");
1407 } else if (arg_match(argv, &i, "--antga", 0, ¶m)) {
1408 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1409 vparm->type = VALUE_ANTGA;
1410 err = parse_value(param, vparm, "--antga");
1413 } else if (arg_match(argv, &i, "--antgbg", 0, ¶m)) {
1414 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1415 vparm->type = VALUE_ANTGBG;
1416 err = parse_value(param, vparm, "--antgbg");
1419 } else if (arg_match(argv, &i, "--pa0b0", 0, ¶m)) {
1420 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1421 vparm->type = VALUE_PA0B0;
1422 err = parse_value(param, vparm, "--pa0b0");
1425 } else if (arg_match(argv, &i, "--pa0b1", 0, ¶m)) {
1426 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1427 vparm->type = VALUE_PA0B1;
1428 err = parse_value(param, vparm, "--pa0b1");
1431 } else if (arg_match(argv, &i, "--pa0b2", 0, ¶m)) {
1432 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1433 vparm->type = VALUE_PA0B2;
1434 err = parse_value(param, vparm, "--pa0b2");
1437 } else if (arg_match(argv, &i, "--pa1b0", 0, ¶m)) {
1438 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1439 vparm->type = VALUE_PA1B0;
1440 err = parse_value(param, vparm, "--pa1b0");
1443 } else if (arg_match(argv, &i, "--pa1b1", 0, ¶m)) {
1444 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1445 vparm->type = VALUE_PA1B1;
1446 err = parse_value(param, vparm, "--pa1b1");
1449 } else if (arg_match(argv, &i, "--pa1b2", 0, ¶m)) {
1450 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1451 vparm->type = VALUE_PA1B2;
1452 err = parse_value(param, vparm, "--pa1b2");
1455 } else if (arg_match(argv, &i, "--wl0gpio0", 0, ¶m)) {
1456 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1457 vparm->type = VALUE_WL0GPIO0;
1458 err = parse_value(param, vparm, "--wl0gpio0");
1461 } else if (arg_match(argv, &i, "--wl0gpio1", 0, ¶m)) {
1462 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1463 vparm->type = VALUE_WL0GPIO1;
1464 err = parse_value(param, vparm, "--wl0gpio1");
1467 } else if (arg_match(argv, &i, "--wl0gpio2", 0, ¶m)) {
1468 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1469 vparm->type = VALUE_WL0GPIO2;
1470 err = parse_value(param, vparm, "--wl0gpio2");
1473 } else if (arg_match(argv, &i, "--wl0gpio3", 0, ¶m)) {
1474 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1475 vparm->type = VALUE_WL0GPIO3;
1476 err = parse_value(param, vparm, "--wl0gpio3");
1479 } else if (arg_match(argv, &i, "--maxpa", 0, ¶m)) {
1480 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1481 vparm->type = VALUE_MAXPA;
1482 err = parse_value(param, vparm, "--maxpa");
1485 } else if (arg_match(argv, &i, "--maxpbg", 0, ¶m)) {
1486 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1487 vparm->type = VALUE_MAXPBG;
1488 err = parse_value(param, vparm, "--maxpbg");
1491 } else if (arg_match(argv, &i, "--itssia", 0, ¶m)) {
1492 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1493 vparm->type = VALUE_ITSSIA;
1494 err = parse_value(param, vparm, "--itssia");
1497 } else if (arg_match(argv, &i, "--itssibg", 0, ¶m)) {
1498 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1499 vparm->type = VALUE_ITSSIBG;
1500 err = parse_value(param, vparm, "--itssibg");
1503 } else if (arg_match(argv, &i, "--sver", 0, ¶m)) {
1504 vparm = &(cmdargs.vparm[cmdargs.nr_vparm++]);
1505 vparm->type = VALUE_SVER;
1506 err = parse_value(param, vparm, "--sver");
1509 } else if (arg_match(argv, &i, "--print-all", "-P", 0)) {
1510 err = generate_printall();
1515 prerror("Unrecognized argument: %s\n", argv[i]);
1521 if (cmdargs.nr_vparm == 0) {
1522 prerror("No Value parameter given. See --help.\n");
1528 print_usage(argc, argv);
1534 int main(int argc, char **argv)
1538 uint8_t sprom[SPROM4_SIZE + 10];
1539 char *buffer = NULL;
1540 size_t buffer_size = 0;
1542 err = parse_args(argc, argv);
1549 prinfo("\nReading input from \"%s\"...\n",
1550 cmdargs.infile ? cmdargs.infile : "stdin");
1552 err = open_infile(&fd);
1555 err = read_infile(fd, &buffer, &buffer_size);
1559 err = parse_input(sprom, buffer, buffer_size);
1563 err = validate_input(sprom);
1567 err = display_sprom(sprom);
1570 err = modify_sprom(sprom);
1574 err = open_outfile(&fd);
1577 err = write_output(fd, sprom);
1581 prinfo("SPROM modified.\n");