[U-Boot] [PATCHv2 12/21] arm: sunxi: Expose function to generate sunxi-specific a MAC address

Olliver Schinagl oliver at schinagl.nl
Mon Apr 10 15:33:47 UTC 2017


Expose the function to generate a MAC adddress based on the serial number.
This can then later be moved completly out of the sunxi board specific stuff.

The setup_environment quirky function still exists as it is still used
to fixup the FDT for drivers that need the MAC address available in the
FDT. Once that is changed, we can clean up some more.

Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
---
 arch/arm/include/asm/arch-sunxi/sys_proto.h |   2 +
 board/sunxi/board.c                         | 145 ++++++++++++++++++----------
 2 files changed, 94 insertions(+), 53 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/sys_proto.h b/arch/arm/include/asm/arch-sunxi/sys_proto.h
index a373319a2b..98effbf5c6 100644
--- a/arch/arm/include/asm/arch-sunxi/sys_proto.h
+++ b/arch/arm/include/asm/arch-sunxi/sys_proto.h
@@ -30,4 +30,6 @@ void eth_init_board(void);
 static inline void eth_init_board(void) {}
 #endif
 
+int sunxi_gen_hwaddr(const int seq, unsigned char *enetaddr);
+
 #endif
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 53656383d5..4ea6dc3828 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -21,6 +21,7 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/spl.h>
+#include <asm/arch/sys_proto.h>
 #include <asm/arch/usb_phy.h>
 #ifndef CONFIG_ARM64
 #include <asm/armv7.h>
@@ -564,6 +565,72 @@ int g_dnl_board_usb_cable_connected(void)
 }
 #endif
 
+static int sunxi_get_board_serial(unsigned int *serial)
+{
+	int ret;
+
+	ret = sunxi_get_sid(serial);
+	if (!ret || serial[0])
+		return -ENOSYS;
+
+	/*
+	 * The single words 1 - 3 of the SID have quite a few bits
+	 * which are the same on many models, so we take a crc32
+	 * of all 3 words, to get a more unique value.
+	 *
+	 * Note we only do this on newer SoCs as we cannot change
+	 * the algorithm on older SoCs since those have been using
+	 * fixed mac-addresses/serial based on only using word 3 for a
+	 * long time and changing a fixed mac-address/serial with an
+	 * u-boot update is not good.
+	 */
+#if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \
+    !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \
+    !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33)
+	serial[3] = crc32(0, (unsigned char *)&serial[1], 12);
+#endif
+
+	return 0;
+}
+
+ /*
+  * Generate a MAC address based on device index and the serial number.
+  * The first half of the of the first octet holds the eth index.
+  *
+  * In the second octet we forcefully mark the MAC address to a locally
+  * administered MAC address.
+  *
+  */
+int sunxi_gen_hwaddr(const int seq, unsigned char *enetaddr)
+{
+	uint8_t mac_addr[ARP_HLEN] = { 0x00 };
+	unsigned int serial[4];
+	int ret;
+
+	if (!enetaddr || (seq < 0))
+		return -ENOSYS;
+
+	ret = sunxi_get_board_serial(serial);
+	if (!ret)
+		return ret;
+
+	/* Ensure the NIC specific bytes of the mac are not all 0 */
+	if ((serial[3] & 0xffffff) == 0)
+		serial[3] |= 0x800000;
+
+	mac_addr[0] = (seq << 4);
+	mac_addr[1] = (serial[0] >>  0) & 0xff;
+	mac_addr[2] = (serial[3] >> 24) & 0xff;
+	mac_addr[3] = (serial[3] >> 16) & 0xff;
+	mac_addr[4] = (serial[3] >>  8) & 0xff;
+	mac_addr[5] = (serial[3] >>  0) & 0xff;
+
+	set_local_ethaddr(mac_addr);
+	memcpy(enetaddr, mac_addr, ARP_HLEN);
+
+	return 0;
+}
+
 #ifdef CONFIG_SERIAL_TAG
 void get_board_serial(struct tag_serialnr *serialnr)
 {
@@ -623,71 +690,35 @@ static void parse_spl_header(const uint32_t spl_addr)
  */
 static void setup_environment(const void *fdt)
 {
-	char serial_string[17] = { 0 };
-	unsigned int sid[4];
-	uint8_t mac_addr[6];
-	char ethaddr[16];
+	uint8_t enetaddr[ARP_HLEN];
+	char ethaddr[ETH_ENETADDR_ENV_NAME_LEN];
 	int i, ret;
 
-	ret = sunxi_get_sid(sid);
-	if (ret == 0 && sid[0] != 0) {
-		/*
-		 * The single words 1 - 3 of the SID have quite a few bits
-		 * which are the same on many models, so we take a crc32
-		 * of all 3 words, to get a more unique value.
-		 *
-		 * Note we only do this on newer SoCs as we cannot change
-		 * the algorithm on older SoCs since those have been using
-		 * fixed mac-addresses based on only using word 3 for a
-		 * long time and changing a fixed mac-address with an
-		 * u-boot update is not good.
-		 */
-#if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \
-    !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \
-    !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33)
-		sid[3] = crc32(0, (unsigned char *)&sid[1], 12);
-#endif
-
-		/* Ensure the NIC specific bytes of the mac are not all 0 */
-		if ((sid[3] & 0xffffff) == 0)
-			sid[3] |= 0x800000;
-
-		for (i = 0; i < 4; i++) {
-			sprintf(ethaddr, "ethernet%d", i);
-			if (!fdt_get_alias(fdt, ethaddr))
-				continue;
-
-			if (i == 0)
-				strcpy(ethaddr, "ethaddr");
-			else
-				sprintf(ethaddr, "eth%daddr", i);
-
-			if (getenv(ethaddr))
-				continue;
+	for (i = 0; i < 4; i++) {
+		sprintf(ethaddr, "ethernet%d", i);
+		if (!fdt_get_alias(fdt, ethaddr))
+			continue;
 
-			/* Non OUI / registered MAC address */
-			mac_addr[0] = (i << 4) | 0x02;
-			mac_addr[1] = (sid[0] >>  0) & 0xff;
-			mac_addr[2] = (sid[3] >> 24) & 0xff;
-			mac_addr[3] = (sid[3] >> 16) & 0xff;
-			mac_addr[4] = (sid[3] >>  8) & 0xff;
-			mac_addr[5] = (sid[3] >>  0) & 0xff;
+		if (i == 0)
+			strcpy(ethaddr, "ethaddr");
+		else
+			sprintf(ethaddr, "eth%daddr", i);
 
-			eth_setenv_enetaddr(ethaddr, mac_addr);
-		}
+		if (getenv(ethaddr))
+			continue;
 
-		if (!getenv("serial#")) {
-			snprintf(serial_string, sizeof(serial_string),
-				"%08x%08x", sid[0], sid[3]);
+		ret = sunxi_gen_hwaddr(i, enetaddr);
+		if (!ret)
+			return;
 
-			setenv("serial#", serial_string);
-		}
+		eth_setenv_enetaddr(ethaddr, enetaddr);
 	}
 }
 
 int misc_init_r(void)
 {
 	__maybe_unused int ret;
+	unsigned int serial[4];
 
 	setenv("fel_booted", NULL);
 	setenv("fel_scriptaddr", NULL);
@@ -698,6 +729,14 @@ int misc_init_r(void)
 	}
 
 	setup_environment(gd->fdt_blob);
+	if (!getenv("serial#") && sunxi_get_board_serial(serial)) {
+		char serial_string[17] = { 0 };
+
+		snprintf(serial_string, sizeof(serial_string),
+			 "%08x%08x", serial[0], serial[3]);
+
+		setenv("serial#", serial_string);
+	}
 
 #ifndef CONFIG_MACH_SUN9I
 	ret = sunxi_usb_phy_probe();
-- 
2.11.0



More information about the U-Boot mailing list