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<x>" 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 <andre.przywara@arm.com>
This commit is contained in:
Andre Przywara 2021-12-19 13:55:33 +00:00 committed by Joanna Farley
parent 6fa8e72e7b
commit 1aa7e302a8
2 changed files with 43 additions and 0 deletions

View file

@ -479,3 +479,44 @@ int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores,
(ac + sc + ac) * 4, (ac + sc + ac) * 4,
val, sc * 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);
}

View file

@ -17,5 +17,7 @@ int fdt_add_cpus_node(void *dtb, unsigned int afflv0,
unsigned int afflv1, unsigned int afflv2); unsigned int afflv1, unsigned int afflv2);
int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores, uintptr_t gicr_base, int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores, uintptr_t gicr_base,
unsigned int gicr_frame_size); 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 */ #endif /* FDT_FIXUP_H */