From 1aa7e302a84bbf46a97bcfbb54b6b6d57de76cee Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Sun, 19 Dec 2021 13:55:33 +0000 Subject: [PATCH] feat(libfdt): add function to set MAC addresses The devicetree specification[1] defines the generic DT properties "mac-address" and "local-mac-address", that allow to set the MAC address for a network device. This is needed because many platform network devices do not define a method for obtaining a unique MAC address, and many devices lack the non-volatile storage to hold such a number. Some platforms (for instance Allwinner) derive the MAC address from another unique SoC property, for instance some serial number. To allow those MAC address to be set by TF-A, add a function that finds the DT node of a network device (by using the "ethernet" alias), then adding the "local-mac-address" property into that node, setting it to a user provided address. Platforms can use this function to generate MAC addresses in a platform specific way, and store them in the DT. DT consumers like U-Boot or the Linux kernel will automatically pick up the address from that property and program the MAC device accordingly. [1] https://devicetree-specification.readthedocs.io/en/latest/chapter4-device-bindings.html#local-mac-address-property Change-Id: I3f5766cc575fa9718f9ca23e8269b11495c43be2 Signed-off-by: Andre Przywara --- common/fdt_fixup.c | 41 ++++++++++++++++++++++++++++++++++++++ include/common/fdt_fixup.h | 2 ++ 2 files changed, 43 insertions(+) diff --git a/common/fdt_fixup.c b/common/fdt_fixup.c index de02b46e8..0ab50d8ab 100644 --- a/common/fdt_fixup.c +++ b/common/fdt_fixup.c @@ -479,3 +479,44 @@ int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores, (ac + sc + ac) * 4, val, sc * 4); } +/** + * fdt_set_mac_address () - store MAC address in device tree + * @dtb: pointer to the device tree blob in memory + * @eth_idx: number of Ethernet interface in /aliases node + * @mac_addr: pointer to 6 byte MAC address to store + * + * Use the generic local-mac-address property in a network device DT node + * to define the MAC address this device should be using. Many platform + * network devices lack device-specific non-volatile storage to hold this + * address, and leave it up to firmware to find and store a unique MAC + * address in the DT. + * The MAC address could be read from some board or firmware defined storage, + * or could be derived from some other unique property like a serial number. + * + * Return: 0 on success, a negative libfdt error value otherwise. + */ +int fdt_set_mac_address(void *dtb, unsigned int ethernet_idx, + const uint8_t *mac_addr) +{ + char eth_alias[12]; + const char *path; + int node; + + if (ethernet_idx > 9U) { + return -FDT_ERR_BADVALUE; + } + snprintf(eth_alias, sizeof(eth_alias), "ethernet%d", ethernet_idx); + + path = fdt_get_alias(dtb, eth_alias); + if (path == NULL) { + return -FDT_ERR_NOTFOUND; + } + + node = fdt_path_offset(dtb, path); + if (node < 0) { + ERROR("Path \"%s\" not found in DT: %d\n", path, node); + return node; + } + + return fdt_setprop(dtb, node, "local-mac-address", mac_addr, 6); +} diff --git a/include/common/fdt_fixup.h b/include/common/fdt_fixup.h index 7a590b2dc..0399ff50f 100644 --- a/include/common/fdt_fixup.h +++ b/include/common/fdt_fixup.h @@ -17,5 +17,7 @@ int fdt_add_cpus_node(void *dtb, unsigned int afflv0, unsigned int afflv1, unsigned int afflv2); int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores, uintptr_t gicr_base, unsigned int gicr_frame_size); +int fdt_set_mac_address(void *dtb, unsigned int ethernet_idx, + const uint8_t *mac_addr); #endif /* FDT_FIXUP_H */