From 72e548d4c5669fbdc040c1b6edc6488433f5276d Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 11 Mar 2015 20:07:05 +0100 Subject: [PATCH] add setmac/showmac commands to setmac or showmac setmac [nobackup] setmac first do a backup of the calibration sector. It copys the sector to the sector before itself. This behavious can be overwritten by adding `nobackup`. showmac - show mac addreses. --- u-boot/common/Makefile | 2 +- u-boot/common/cmd_setmac.c | 259 ++++++++++++++++++++++++++++++++ u-boot/include/configs/common.h | 2 + 3 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 u-boot/common/cmd_setmac.c diff --git a/u-boot/common/Makefile b/u-boot/common/Makefile index 561104d614..91fe8e28e1 100644 --- a/u-boot/common/Makefile +++ b/u-boot/common/Makefile @@ -60,7 +60,7 @@ COBJS = main.o circbuf.o \ cmd_nand.o cmd_net.o cmd_nvedit.o \ cmd_pci.o cmd_pcmcia.o cmd_portio.o \ cmd_reginfo.o cmd_reiser.o cmd_scsi.o cmd_spi.o cmd_universe.o \ - cmd_vfd.o cmd_ethreg.o cmd_recovery.o cmd_bootcycle.o \ + cmd_vfd.o cmd_ethreg.o cmd_recovery.o cmd_bootcycle.o cmd_setmac.o \ command.o console.o devices.o dlmalloc.o \ environment.o env_common.o \ env_nand.o env_dataflash.o env_flash.o env_eeprom.o \ diff --git a/u-boot/common/cmd_setmac.c b/u-boot/common/cmd_setmac.c new file mode 100644 index 0000000000..394db4bb78 --- /dev/null +++ b/u-boot/common/cmd_setmac.c @@ -0,0 +1,259 @@ +/* + * (C) Copyright 2015 + * Alexander Couzens, lynxis@fe80.eu + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +#ifdef CFG_CMD_SETMAC + +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +static int mac_location[] = { + 0x0, /* eth0 */ + 0x6, /* eth1 */ + 0x1002, /* wlan0 */ +}; + +typedef unsigned char bool; +#define true 1 +#define false 0 + +/* from xyzmodem.c */ +// Validate a hex character +__inline__ static bool +_is_hex(char c) +{ + return (((c >= '0') && (c <= '9')) || + ((c >= 'A') && (c <= 'F')) || + ((c >= 'a') && (c <= 'f'))); +} + +/* from xyzmodem.c */ +// Convert a single hex nibble +__inline__ static u8 +_from_hex(char c) +{ + u8 ret = 0; + + if ((c >= '0') && (c <= '9')) { + ret = (c - '0'); + } else if ((c >= 'a') && (c <= 'f')) { + ret = (c - 'a' + 0x0a); + } else if ((c >= 'A') && (c <= 'F')) { + ret = (c - 'A' + 0x0A); + } + return ret; +} + + + +static int is_valid_mac_str(char *mac) +{ + /* mac must look like "00:11:22:33:44:55" */ + int i; + + if (strlen(mac) < 17) + return 0; + + for (i=0; i <=15 ; i+=3) { + if (!_is_hex(mac[i]) || !_is_hex(mac[i+1])) + return 0; + + /* check for colons - last group doesn't end with a colon*/ + if (i != 15 && mac[i+2] != ':') + return 0; + } + + return 1; +} + +static int parse_mac(u8 *dst, char *mac_str) { + int i; + int j; + + if (!is_valid_mac_str(mac_str)) + return 1; + + /* j = dst offset + * i = mac_str offset + */ + for (i=0, j=0; i<= 15; i+=3, j++) { + dst[j] = _from_hex(mac_str[i]) << 4 | _from_hex(mac_str[i + 1]); + } + return 0; +} + +/* copy calibration sector to the sector before calibration */ +static int backup_calibration(u8 *buffer) +{ + int rc = -1; + + /* read */ + memcpy(buffer, (void *)BOARDCAL, CFG_FLASH_SECTOR_SIZE); + + /* erase */ + rc = flash_erase(flash_info, CAL_SECTOR-1, CAL_SECTOR-1); + if (rc) { + printf("Backup failed because flash erase failed! rc %d\n", rc); + return 1; + } + + /* cp */ + rc = write_buff(flash_info, buffer, BOARDCAL-CFG_FLASH_SECTOR_SIZE, CFG_FLASH_SECTOR_SIZE); + if (rc) { + printf("Backup failed because write to flash failed! rc %d\n", rc); + return 1; + } + + /* compare */ + if (memcmp(buffer, (void *)BOARDCAL-CFG_FLASH_SECTOR_SIZE, CFG_FLASH_SECTOR_SIZE)) { + printf("Backup failed. Read back different value!\n"); + return 1; + } + + return 0; +} + +int write_mac(u8 *buffer, u8 macs[ARRAY_SIZE(mac_location)][ETH_ALEN]) +{ + int i; + int rc; + + /* read */ + memcpy(buffer, (void *)BOARDCAL, CFG_FLASH_SECTOR_SIZE); + + /* set macs */ + for(i=0; i [..] or set_mac [..] nobackup + * check if enough arguments given + */ + if (argc != (ARRAY_SIZE(mac_location)+1) && + argc != (ARRAY_SIZE(mac_location)+2)) + return CMD_RET_FAILURE; + + /* check if nobackup was given */ + if (argc == (ARRAY_SIZE(mac_location)+2)) { + if(!strncmp("nobackup", argv[argc-1], 8)) { + do_backup = false; + } else { + printf("Unknown argument %s!\n", argv[argc-1]); + return CMD_RET_FAILURE; + } + } + + /* all other arguments are mac address */ + for (i=0; i < ARRAY_SIZE(mac_location); i++) { + if (!is_valid_mac_str(argv[i+1])) { + printf("Invalid MAC address %s!\n", argv[i+1]); + return CMD_RET_FAILURE; + } + } + + /* parse macs and copy into macs */ + for (i=0; i < ARRAY_SIZE(mac_location); i++) { + if (parse_mac(macs[i], argv[i+1])) { + printf("Can not parse mac %s!\n", argv[i+1]); + return CMD_RET_FAILURE; + } + } + + if (do_backup) { + if (backup_calibration(buffer)) { + printf("Backup failed to the sector before calibration. Not updating calibration sector!"); + return CMD_RET_FAILURE; + } + } + + if (!write_mac(buffer, macs)) { + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +int do_showmac(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int i = 0; + u8 buffer[CFG_FLASH_SECTOR_SIZE]; + u8 *mac; + memcpy(buffer, (void *)BOARDCAL, CFG_FLASH_SECTOR_SIZE); + + for (i=0; i < ARRAY_SIZE(mac_location); i++) { + mac = buffer + mac_location[i]; + printf("mac %d = %02x:%02x:%02x:%02x:%02x:%02x\n", i, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + setmac, ARRAY_SIZE(mac_location)+2, 0, do_setmac, + "setmac - Set ethernet MAC addresses\n", + "setmac [ [nobackup]]\n" + " without arguments it shows actual configuration\n" + " mac address\n" + " mac address\n" + " mac address\n" + " mac address 00:aa:bb:cc:dd:ee\n" + " nobackup - don't do a backup in the sector before calibration" +); + +U_BOOT_CMD( + showmac, 1, 0, do_showmac, + "showmac - Show ethernet MAC addresses\n", +); + +#endif /* CFG_CMD_SETMAC */ diff --git a/u-boot/include/configs/common.h b/u-boot/include/configs/common.h index c8eed38d77..fbf7084999 100644 --- a/u-boot/include/configs/common.h +++ b/u-boot/include/configs/common.h @@ -6,6 +6,8 @@ */ #define CFG_FLASH_BASE 0x9f000000 +#define CFG_CMD_SETMAC + #ifdef COMPRESSED_UBOOT #define BOOTSTRAP_TEXT_BASE CFG_FLASH_BASE #define BOOTSTRAP_CFG_MONITOR_BASE BOOTSTRAP_TEXT_BASE