1--------------------------------- 2 Ethernet Address (MAC) Handling 3--------------------------------- 4 5There are a variety of places in U-Boot where the MAC address is used, parsed, 6and stored. This document covers proper usage of each location and the moving 7of data between them. 8 9----------- 10 Locations 11----------- 12 13Here are the places where MAC addresses might be stored: 14 15 - board-specific location (eeprom, dedicated flash, ...) 16 Note: only used when mandatory due to hardware design etc... 17 18 - environment ("ethaddr", "eth1addr", ...) (see CONFIG_ETHADDR) 19 Note: this is the preferred way to permanently store MAC addresses 20 21 - ethernet data (struct eth_device -> enetaddr) 22 Note: these are temporary copies of the MAC address which exist only 23 after the respective init steps have run and only to make usage 24 in other places easier (to avoid constant env lookup/parsing) 25 26 - struct bd_info and/or device tree 27 Note: these are temporary copies of the MAC address only for the 28 purpose of passing this information to an OS kernel we are about 29 to boot 30 31Correct flow of setting up the MAC address (summarized): 32 331. Read from hardware in initialize() function 342. Read from environment in net/eth.c after initialize() 353. Give priority to the value in the environment if a conflict 364. Program the address into hardware if the following conditions are met: 37 a) The relevant driver has a 'write_addr' function 38 b) The user hasn't set an 'ethmacskip' environment variable 39 c) The address is valid (unicast, not all-zeros) 40 41Previous behavior had the MAC address always being programmed into hardware 42in the device's init() function. 43 44------- 45 Usage 46------- 47 48If the hardware design mandates that the MAC address is stored in some special 49place (like EEPROM etc...), then the board specific init code (such as the 50board-specific misc_init_r() function) is responsible for locating the MAC 51address(es) and initializing the respective environment variable(s) from it. 52Note that this shall be done if, and only if, the environment does not already 53contain these environment variables, i.e. existing variable definitions must 54not be overwritten. 55 56During runtime, the ethernet layer will use the environment variables to sync 57the MAC addresses to the ethernet structures. All ethernet driver code should 58then only use the enetaddr member of the eth_device structure. This is done 59on every network command, so the ethernet copies will stay in sync. 60 61Any other code that wishes to access the MAC address should query the 62environment directly. The helper functions documented below should make 63working with this storage much smoother. 64 65--------- 66 Helpers 67--------- 68 69To assist in the management of these layers, a few helper functions exist. You 70should use these rather than attempt to do any kind of parsing/manipulation 71yourself as many common errors have arisen in the past. 72 73 * void eth_parse_enetaddr(const char *addr, uchar *enetaddr); 74 75Convert a string representation of a MAC address to the binary version. 76char *addr = "00:11:22:33:44:55"; 77uchar enetaddr[6]; 78eth_parse_enetaddr(addr, enetaddr); 79/* enetaddr now equals { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } */ 80 81 * int eth_getenv_enetaddr(char *name, uchar *enetaddr); 82 83Look up an environment variable and convert the stored address. If the address 84is valid, then the function returns 1. Otherwise, the function returns 0. In 85all cases, the enetaddr memory is initialized. If the env var is not found, 86then it is set to all zeros. The common function is_valid_ether_addr() is used 87to determine address validity. 88uchar enetaddr[6]; 89if (!eth_getenv_enetaddr("ethaddr", enetaddr)) { 90 /* "ethaddr" is not set in the environment */ 91 ... try and setup "ethaddr" in the env ... 92} 93/* enetaddr is now set to the value stored in the ethaddr env var */ 94 95 * int eth_setenv_enetaddr(char *name, const uchar *enetaddr); 96 97Store the MAC address into the named environment variable. The return value is 98the same as the setenv() function. 99uchar enetaddr[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; 100eth_setenv_enetaddr("ethaddr", enetaddr); 101/* the "ethaddr" env var should now be set to "00:11:22:33:44:55" */ 102 103 * the %pM format modifier 104 105The %pM format modifier can be used with any standard printf function to format 106the binary 6 byte array representation of a MAC address. 107uchar enetaddr[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; 108printf("The MAC is %pM\n", enetaddr); 109 110char buf[20]; 111sprintf(buf, "%pM", enetaddr); 112/* the buf variable is now set to "00:11:22:33:44:55" */ 113