16ff4137fSMike Frysinger--------------------------------- 26ff4137fSMike Frysinger Ethernet Address (MAC) Handling 36ff4137fSMike Frysinger--------------------------------- 46ff4137fSMike Frysinger 56ff4137fSMike FrysingerThere are a variety of places in U-Boot where the MAC address is used, parsed, 66ff4137fSMike Frysingerand stored. This document covers proper usage of each location and the moving 76ff4137fSMike Frysingerof data between them. 86ff4137fSMike Frysinger 96ff4137fSMike Frysinger----------- 106ff4137fSMike Frysinger Locations 116ff4137fSMike Frysinger----------- 126ff4137fSMike Frysinger 136ff4137fSMike FrysingerHere are the places where MAC addresses might be stored: 146ff4137fSMike Frysinger 156ff4137fSMike Frysinger - board-specific location (eeprom, dedicated flash, ...) 166ff4137fSMike Frysinger Note: only used when mandatory due to hardware design etc... 176ff4137fSMike Frysinger 1892ac5208SJoe Hershberger - environment ("ethaddr", "eth1addr", ...) 196ff4137fSMike Frysinger Note: this is the preferred way to permanently store MAC addresses 206ff4137fSMike Frysinger 216ff4137fSMike Frysinger - ethernet data (struct eth_device -> enetaddr) 226ff4137fSMike Frysinger Note: these are temporary copies of the MAC address which exist only 236ff4137fSMike Frysinger after the respective init steps have run and only to make usage 246ff4137fSMike Frysinger in other places easier (to avoid constant env lookup/parsing) 256ff4137fSMike Frysinger 266ff4137fSMike Frysinger - struct bd_info and/or device tree 276ff4137fSMike Frysinger Note: these are temporary copies of the MAC address only for the 286ff4137fSMike Frysinger purpose of passing this information to an OS kernel we are about 296ff4137fSMike Frysinger to boot 306ff4137fSMike Frysinger 318e64d6efSHeiko SchocherCorrect flow of setting up the MAC address (summarized): 328e64d6efSHeiko Schocher 338e64d6efSHeiko Schocher1. Read from hardware in initialize() function 348e64d6efSHeiko Schocher2. Read from environment in net/eth.c after initialize() 35c88ef3c1SRob Herring3. The environment variable will be compared to the driver initialized 36c88ef3c1SRob Herring struct eth_device->enetaddr. If they differ, a warning is printed, and the 37c88ef3c1SRob Herring environment variable will be used unchanged. 38c88ef3c1SRob Herring If the environment variable is not set, it will be initialized from 39c88ef3c1SRob Herring eth_device->enetaddr, and a warning will be printed. 40bef1014bSJoe Hershberger If both are invalid and CONFIG_NET_RANDOM_ETHADDR is defined, a random, 41bef1014bSJoe Hershberger locally-assigned MAC is written to eth_device->enetaddr. 42ecee9324SBen Warren4. Program the address into hardware if the following conditions are met: 43ecee9324SBen Warren a) The relevant driver has a 'write_addr' function 44ecee9324SBen Warren b) The user hasn't set an 'ethmacskip' environment variable 45ecee9324SBen Warren c) The address is valid (unicast, not all-zeros) 468e64d6efSHeiko Schocher 47ecee9324SBen WarrenPrevious behavior had the MAC address always being programmed into hardware 48ecee9324SBen Warrenin the device's init() function. 498e64d6efSHeiko Schocher 506ff4137fSMike Frysinger------- 516ff4137fSMike Frysinger Usage 526ff4137fSMike Frysinger------- 536ff4137fSMike Frysinger 546ff4137fSMike FrysingerIf the hardware design mandates that the MAC address is stored in some special 556ff4137fSMike Frysingerplace (like EEPROM etc...), then the board specific init code (such as the 566ff4137fSMike Frysingerboard-specific misc_init_r() function) is responsible for locating the MAC 576ff4137fSMike Frysingeraddress(es) and initializing the respective environment variable(s) from it. 586ff4137fSMike FrysingerNote that this shall be done if, and only if, the environment does not already 596ff4137fSMike Frysingercontain these environment variables, i.e. existing variable definitions must 606ff4137fSMike Frysingernot be overwritten. 616ff4137fSMike Frysinger 626ff4137fSMike FrysingerDuring runtime, the ethernet layer will use the environment variables to sync 636ff4137fSMike Frysingerthe MAC addresses to the ethernet structures. All ethernet driver code should 646ff4137fSMike Frysingerthen only use the enetaddr member of the eth_device structure. This is done 656ff4137fSMike Frysingeron every network command, so the ethernet copies will stay in sync. 666ff4137fSMike Frysinger 676ff4137fSMike FrysingerAny other code that wishes to access the MAC address should query the 686ff4137fSMike Frysingerenvironment directly. The helper functions documented below should make 696ff4137fSMike Frysingerworking with this storage much smoother. 706ff4137fSMike Frysinger 716ff4137fSMike Frysinger--------- 726ff4137fSMike Frysinger Helpers 736ff4137fSMike Frysinger--------- 746ff4137fSMike Frysinger 756ff4137fSMike FrysingerTo assist in the management of these layers, a few helper functions exist. You 766ff4137fSMike Frysingershould use these rather than attempt to do any kind of parsing/manipulation 776ff4137fSMike Frysingeryourself as many common errors have arisen in the past. 786ff4137fSMike Frysinger 796ff4137fSMike Frysinger * void eth_parse_enetaddr(const char *addr, uchar *enetaddr); 806ff4137fSMike Frysinger 816ff4137fSMike FrysingerConvert a string representation of a MAC address to the binary version. 826ff4137fSMike Frysingerchar *addr = "00:11:22:33:44:55"; 836ff4137fSMike Frysingeruchar enetaddr[6]; 846ff4137fSMike Frysingereth_parse_enetaddr(addr, enetaddr); 856ff4137fSMike Frysinger/* enetaddr now equals { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } */ 866ff4137fSMike Frysinger 87*35affd7aSSimon Glass * int eth_env_get_enetaddr(char *name, uchar *enetaddr); 886ff4137fSMike Frysinger 896ff4137fSMike FrysingerLook up an environment variable and convert the stored address. If the address 906ff4137fSMike Frysingeris valid, then the function returns 1. Otherwise, the function returns 0. In 916ff4137fSMike Frysingerall cases, the enetaddr memory is initialized. If the env var is not found, 920adb5b76SJoe Hershbergerthen it is set to all zeros. The common function is_valid_ethaddr() is used 936ff4137fSMike Frysingerto determine address validity. 946ff4137fSMike Frysingeruchar enetaddr[6]; 95*35affd7aSSimon Glassif (!eth_env_get_enetaddr("ethaddr", enetaddr)) { 966ff4137fSMike Frysinger /* "ethaddr" is not set in the environment */ 976ff4137fSMike Frysinger ... try and setup "ethaddr" in the env ... 986ff4137fSMike Frysinger} 996ff4137fSMike Frysinger/* enetaddr is now set to the value stored in the ethaddr env var */ 1006ff4137fSMike Frysinger 101fd1e959eSSimon Glass * int eth_env_set_enetaddr(char *name, const uchar *enetaddr); 1026ff4137fSMike Frysinger 1036ff4137fSMike FrysingerStore the MAC address into the named environment variable. The return value is 104382bee57SSimon Glassthe same as the env_set() function. 1056ff4137fSMike Frysingeruchar enetaddr[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; 106fd1e959eSSimon Glasseth_env_set_enetaddr("ethaddr", enetaddr); 1076ff4137fSMike Frysinger/* the "ethaddr" env var should now be set to "00:11:22:33:44:55" */ 1086ff4137fSMike Frysinger 1096ff4137fSMike Frysinger * the %pM format modifier 1106ff4137fSMike Frysinger 1116ff4137fSMike FrysingerThe %pM format modifier can be used with any standard printf function to format 1126ff4137fSMike Frysingerthe binary 6 byte array representation of a MAC address. 1136ff4137fSMike Frysingeruchar enetaddr[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; 1146ff4137fSMike Frysingerprintf("The MAC is %pM\n", enetaddr); 1156ff4137fSMike Frysinger 1166ff4137fSMike Frysingerchar buf[20]; 1176ff4137fSMike Frysingersprintf(buf, "%pM", enetaddr); 1186ff4137fSMike Frysinger/* the buf variable is now set to "00:11:22:33:44:55" */ 119