1
votes

According to U-Boot's README.enetaddr "Usage" section:

If the hardware design mandates that the MAC address is stored in some special place (like EEPROM etc...), then the board specific init code (such as the board-specific misc_init_r() function) is responsible for locating the MAC address(es) and initializing the respective environment variable(s) from it. Note that this shall be done if, and only if, the environment does not already contain these environment variables, i.e. existing variable definitions must not be overwritten.

During runtime, the ethernet layer will use the environment variables to sync the MAC addresses to the ethernet structures. All ethernet driver code should then only use the enetaddr member of the eth_device structure. This is done on every network command, so the ethernet copies will stay in sync.

Let us suppose a device has an EEPROM containing a universally administered MAC address and that the device's misc_init_r() function reads that MAC address and writes it to an environment variable (e.g. "ethaddr") if and only if the environment variable doesn't exist. Let us also suppose that the environment is later saved by the U-Boot saveenv command, and moreover, that the whole system is running off a removable storage device such as an SD card, where the U-Boot environment is also saved.

EDIT

In my case, I am in the above situation for a new custom board which has a "MAC address EEPROM" from Micronix containing a unique, universally administered MAC address, and the board's only available storage location for a saved U-Boot environment is the SD card from which it boots. I have the following code for the board-specific misc_init_r() function:

#include <common.h>

#ifndef CONFIG_SPL_BUILD
static int my_board_read_mac(uchar *mac)
{
    int ret;

    /* EEPROM is at bus 0. */
    ret = i2c_set_bus_num(0);
    if (ret) {
        printf("Cannot select EEPROM I2C bus - err %d\n", ret);
        return ret;
    }
    /* EEPROM is at address 0x50.  MAC address is at offset 0xfa. */
    ret = eeprom_read(0x50, 0xfa, mac, 6);
    if (ret) {
        printf("Cannot read I2C EEPROM - err %d\n", ret);
        return ret;
    }
    return 0;
}

static int my_board_do_mac(void)
{
    int ret;
    uchar mac[6];

    ret = my_board_read_mac(mac);
    if (ret) {
        printf("Failed to read MAC address - err %d\n", ret);
        return ret;
    }
    if (!is_valid_ethaddr(mac)) {
        printf("Read invalid MAC address %pM\n", mac);
        return -EINVAL;
    }
    if (!getenv("ethaddr")) {
        return eth_setenv_enetaddr("ethaddr", mac);
    }
    return 0;
}

int misc_init_r(void)
{
    int ret;

    ret = my_board_do_mac();
    if (ret) {
        printf("Failed to set MAC address - err %d\n", ret);
    }
    return 0;
}
#endif

My question is: If the SD card is removed from the original device and placed into a similar device (with a different universally administered MAC address in its EEPROM), will the new device use the original device's MAC address rather than it's own, unique MAC address? If so, what is the best way to prevent that from happening?

EDIT2

What I'm looking for is some way to set the MAC address automatically, but not to "pollute" any copy of the environment saved on the SD card with this board specific MAC address. I.e. I want the MAC address to remain tied to the board, rather than to the SD card.

1
This really doesn't appear to be programming related... you might want to edit to clarify.user1228

1 Answers

2
votes

The answer is that this becomes a policy question. The non-default environment (so, what gets saved to someplace when you use saveenv) is intended to be instance-specific. This is why generally speaking board code will see if ethaddr is set, and if so, not try and derive one.

When you move from board to board you can use env default -f -a to restore the running environment to the built-in defaults.

If you want to share the same SD card between multiple boards then you need to come up with a policy to manage this situation.