[U-Boot] [PATCH v2 1/2] net: Add a command to access the EEPROM from ethernet devices

Alban Bedel alban.bedel at avionic-design.de
Thu Oct 9 13:42:49 CEST 2014


Many ethernet devices use an EEPROM to store various settings, most
commonly the device MAC address. But on some devices it can contains
a lot more, for example USB device might also have many USB related
parameters.

This commit add a set of commands to read/write this EEPROM, write a
default configuration and read/write the device MAC address. The
defaults command allow priming the EEPROM for devices that need more
than just a MAC address in the EEPROM.

Signed-off-by: Alban Bedel <alban.bedel at avionic-design.de>
---
v2: * No changes since v1
---
 common/cmd_net.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/net.h    |  28 ++++++++++++
 net/eth.c        |  46 +++++++++++++++++++
 3 files changed, 208 insertions(+)

diff --git a/common/cmd_net.c b/common/cmd_net.c
index 09489d4..f4952d5 100644
--- a/common/cmd_net.c
+++ b/common/cmd_net.c
@@ -445,3 +445,137 @@ U_BOOT_CMD(
 );
 
 #endif  /* CONFIG_CMD_LINK_LOCAL */
+
+#if defined(CONFIG_CMD_ETH_EEPROM)
+static int do_eth_eeprom_rw(struct eth_device *dev,
+			int argc, char * const argv[])
+{
+	ulong addr, offset, length = 1;
+
+	if (argc < 4)
+		return CMD_RET_USAGE;
+
+	addr = simple_strtoul(argv[2], NULL, 16);
+	offset = simple_strtoul(argv[3], NULL, 16);
+	if (argc > 4)
+		length = simple_strtoul(argv[4], NULL, 16);
+
+	if (!strcmp(argv[0], "write")) {
+		if (eth_eeprom_write(dev, offset, length, (void *)addr)) {
+			printf("EEPROM write failed\n");
+			return CMD_RET_FAILURE;
+		}
+		return CMD_RET_SUCCESS;
+	} else if (!strcmp(argv[0], "read")) {
+		if (eth_eeprom_read(dev, offset, length, (void *)addr)) {
+			printf("EEPROM read failed\n");
+			return CMD_RET_FAILURE;
+		}
+		return CMD_RET_SUCCESS;
+	}
+
+	return CMD_RET_USAGE;
+}
+
+static int do_eth_eeprom_defaults(struct eth_device *dev,
+				int argc, char * const argv[])
+{
+	if (eth_eeprom_defaults(dev)) {
+		printf("EEPROM write failed\n");
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_eth_eeprom_set_mac(struct eth_device *dev,
+				int argc, char * const argv[])
+{
+	u8 mac[6];
+
+	if (argc < 3)
+		return CMD_RET_USAGE;
+
+	eth_parse_enetaddr(argv[2], mac);
+	if (!is_valid_ether_addr(mac)) {
+		printf("Invalid mac address given\n");
+		return CMD_RET_FAILURE;
+	}
+
+	printf("Writing MAC to EEPROM ....\n");
+	if (eth_eeprom_write_mac(dev, mac)) {
+		printf("EEPROM write failed\n");
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_eth_eeprom_show_mac(struct eth_device *dev,
+				int argc, char * const argv[])
+{
+	u8 data[6];
+
+	if (eth_eeprom_read_mac(dev, data)) {
+		printf("EEPROM read failed\n");
+		return CMD_RET_FAILURE;
+	}
+
+	printf("%pM\n", data);
+	if (!is_valid_ether_addr(data))
+		printf("Warning: MAC address is not valid!\n");
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_eth_eeprom(cmd_tbl_t *cmdtp, int flag, int argc,
+			char * const argv[])
+{
+	struct eth_device *dev;
+	char *endp = NULL;
+	int index;
+
+	if (argc < 3)
+		return CMD_RET_USAGE;
+
+	/* Get the ethernet device, by ID or by name */
+	index = (int) simple_strtoul(argv[2], &endp, 16);
+	if (endp > argv[2])
+		dev = eth_get_dev_by_index(index);
+	else
+		dev = eth_get_dev_by_name(argv[2]);
+
+	if (!dev) {
+		printf("Ethernet device not found\n");
+		return CMD_RET_FAILURE;
+	}
+
+	if (!strcmp(argv[1], "read") || !strcmp(argv[1], "write"))
+		return do_eth_eeprom_rw(dev, argc - 1, argv + 1);
+	if (!strcmp(argv[1], "defaults"))
+		return do_eth_eeprom_defaults(dev, argc - 1, argv + 1);
+	if (!strcmp(argv[1], "set_mac"))
+		return do_eth_eeprom_set_mac(dev, argc - 1, argv + 1);
+	if (!strcmp(argv[1], "show_mac"))
+		return do_eth_eeprom_show_mac(dev, argc - 1, argv + 1);
+
+	printf("Unknown sub command: %s\n", argv[1]);
+
+	return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+	eth_eeprom,	6,	0,	do_eth_eeprom,
+	"access the EEPROM of ethernet devices",
+	"read dev addr off [size]\n"
+	"    - read 'size' bytes starting at offset 'off' to memory address 'addr'.\n"
+	"eth_eeprom write dev addr off [size]\n"
+	"    - write 'size' bytes starting at offset 'off' from memory address 'addr'.\n"
+	"eth_eeprom defaults dev\n"
+	"    - write default settings in the EEPROM.\n"
+	"eth_eeprom set_mac dev mac\n"
+	"    - set the MAC address in the EEPROM to 'mac'\n"
+	"eth_eeprom show_mac dev\n"
+	"    - read the MAC address from the EEPROM."
+);
+#endif
diff --git a/include/net.h b/include/net.h
index 735b0b9..39ea848 100644
--- a/include/net.h
+++ b/include/net.h
@@ -92,6 +92,25 @@ struct eth_device {
 	int (*mcast) (struct eth_device *, const u8 *enetaddr, u8 set);
 #endif
 	int  (*write_hwaddr) (struct eth_device *);
+#ifdef CONFIG_CMD_ETH_EEPROM
+	/* Read data from the ethernet device eeprom */
+	int (*eeprom_read)(struct eth_device *,
+			   u32 offset, u32 length, u8 *data);
+	/* Write data to the ethernet device eeprom */
+	int (*eeprom_write)(struct eth_device *,
+			    u32 offset, u32 length, u8 *data);
+	/* Write the default settings to the eeprom */
+	int (*eeprom_defaults)(struct eth_device *);
+	/* Read the MAC stored in the eeprom, if not implemented
+	 * the MAC is assumed to be at the given offset. */
+	int (*eeprom_read_mac)(struct eth_device *, u8 *enetaddr);
+	/* Write the MAC in the eeprom, if not implemented
+	 * the MAC is assumed to be at the given offset. */
+	int (*eeprom_write_mac)(struct eth_device *, u8 *enetaddr);
+	/* Offset of the MAC address for the default implementation.
+	 * Set to a negative value if the MAC is not in the EEPROM. */
+	int eeprom_mac_offset;
+#endif
 	struct eth_device *next;
 	int index;
 	void *priv;
@@ -172,6 +191,15 @@ int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
 u32 ether_crc(size_t len, unsigned char const *p);
 #endif
 
+#ifdef CONFIG_CMD_ETH_EEPROM
+int eth_eeprom_read(struct eth_device *dev, u32 offset,
+		    u32 length, u8 *data);
+int eth_eeprom_write(struct eth_device *dev, u32 offset,
+		     u32 length, u8 *data);
+int eth_eeprom_defaults(struct eth_device *dev);
+int eth_eeprom_read_mac(struct eth_device *, u8 *enetaddr);
+int eth_eeprom_write_mac(struct eth_device *, u8 *enetaddr);
+#endif
 
 /**********************************************************************/
 /*
diff --git a/net/eth.c b/net/eth.c
index 76ffa05..2cde72c 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -542,3 +542,49 @@ char *eth_get_name(void)
 {
 	return eth_current ? eth_current->name : "unknown";
 }
+
+#ifdef CONFIG_CMD_ETH_EEPROM
+int eth_eeprom_read(struct eth_device *dev, u32 offset,
+		    u32 length, u8 *data)
+{
+	return dev->eeprom_read ?
+		dev->eeprom_read(dev, offset, length, data) :
+		-ENOSYS;
+}
+
+int eth_eeprom_write(struct eth_device *dev, u32 offset,
+		     u32 length, u8 *data)
+{
+	return dev->eeprom_write ?
+		dev->eeprom_write(dev, offset, length, data) :
+		-ENOSYS;
+}
+
+int eth_eeprom_defaults(struct eth_device *dev)
+{
+	return dev->eeprom_defaults ? dev->eeprom_defaults(dev) :
+		-ENOSYS;
+}
+
+int eth_eeprom_read_mac(struct eth_device *dev, u8 *enetaddr)
+{
+	if (dev->eeprom_read_mac)
+		return dev->eeprom_read_mac(dev, enetaddr);
+
+	return dev->eeprom_mac_offset >= 0 ?
+		eth_eeprom_read(dev, dev->eeprom_mac_offset,
+				6, enetaddr) :
+		-ENOSYS;
+}
+
+int eth_eeprom_write_mac(struct eth_device *dev, u8 *enetaddr)
+{
+	if (dev->eeprom_write_mac)
+		return dev->eeprom_write_mac(dev, enetaddr);
+
+	return dev->eeprom_mac_offset >= 0 ?
+		eth_eeprom_write(dev, dev->eeprom_mac_offset,
+				 6, enetaddr) :
+		-ENOSYS;
+}
+#endif
-- 
2.1.1



More information about the U-Boot mailing list