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 186ff4137fSMike Frysinger - environment ("ethaddr", "eth1addr", ...) (see CONFIG_ETHADDR) 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() 35*c88ef3c1SRob Herring3. The environment variable will be compared to the driver initialized 36*c88ef3c1SRob Herring struct eth_device->enetaddr. If they differ, a warning is printed, and the 37*c88ef3c1SRob Herring environment variable will be used unchanged. 38*c88ef3c1SRob Herring If the environment variable is not set, it will be initialized from 39*c88ef3c1SRob Herring eth_device->enetaddr, and a warning will be printed. 40ecee9324SBen Warren4. Program the address into hardware if the following conditions are met: 41ecee9324SBen Warren a) The relevant driver has a 'write_addr' function 42ecee9324SBen Warren b) The user hasn't set an 'ethmacskip' environment variable 43ecee9324SBen Warren c) The address is valid (unicast, not all-zeros) 448e64d6efSHeiko Schocher 45ecee9324SBen WarrenPrevious behavior had the MAC address always being programmed into hardware 46ecee9324SBen Warrenin the device's init() function. 478e64d6efSHeiko Schocher 486ff4137fSMike Frysinger------- 496ff4137fSMike Frysinger Usage 506ff4137fSMike Frysinger------- 516ff4137fSMike Frysinger 526ff4137fSMike FrysingerIf the hardware design mandates that the MAC address is stored in some special 536ff4137fSMike Frysingerplace (like EEPROM etc...), then the board specific init code (such as the 546ff4137fSMike Frysingerboard-specific misc_init_r() function) is responsible for locating the MAC 556ff4137fSMike Frysingeraddress(es) and initializing the respective environment variable(s) from it. 566ff4137fSMike FrysingerNote that this shall be done if, and only if, the environment does not already 576ff4137fSMike Frysingercontain these environment variables, i.e. existing variable definitions must 586ff4137fSMike Frysingernot be overwritten. 596ff4137fSMike Frysinger 606ff4137fSMike FrysingerDuring runtime, the ethernet layer will use the environment variables to sync 616ff4137fSMike Frysingerthe MAC addresses to the ethernet structures. All ethernet driver code should 626ff4137fSMike Frysingerthen only use the enetaddr member of the eth_device structure. This is done 636ff4137fSMike Frysingeron every network command, so the ethernet copies will stay in sync. 646ff4137fSMike Frysinger 656ff4137fSMike FrysingerAny other code that wishes to access the MAC address should query the 666ff4137fSMike Frysingerenvironment directly. The helper functions documented below should make 676ff4137fSMike Frysingerworking with this storage much smoother. 686ff4137fSMike Frysinger 696ff4137fSMike Frysinger--------- 706ff4137fSMike Frysinger Helpers 716ff4137fSMike Frysinger--------- 726ff4137fSMike Frysinger 736ff4137fSMike FrysingerTo assist in the management of these layers, a few helper functions exist. You 746ff4137fSMike Frysingershould use these rather than attempt to do any kind of parsing/manipulation 756ff4137fSMike Frysingeryourself as many common errors have arisen in the past. 766ff4137fSMike Frysinger 776ff4137fSMike Frysinger * void eth_parse_enetaddr(const char *addr, uchar *enetaddr); 786ff4137fSMike Frysinger 796ff4137fSMike FrysingerConvert a string representation of a MAC address to the binary version. 806ff4137fSMike Frysingerchar *addr = "00:11:22:33:44:55"; 816ff4137fSMike Frysingeruchar enetaddr[6]; 826ff4137fSMike Frysingereth_parse_enetaddr(addr, enetaddr); 836ff4137fSMike Frysinger/* enetaddr now equals { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } */ 846ff4137fSMike Frysinger 856ff4137fSMike Frysinger * int eth_getenv_enetaddr(char *name, uchar *enetaddr); 866ff4137fSMike Frysinger 876ff4137fSMike FrysingerLook up an environment variable and convert the stored address. If the address 886ff4137fSMike Frysingeris valid, then the function returns 1. Otherwise, the function returns 0. In 896ff4137fSMike Frysingerall cases, the enetaddr memory is initialized. If the env var is not found, 906ff4137fSMike Frysingerthen it is set to all zeros. The common function is_valid_ether_addr() is used 916ff4137fSMike Frysingerto determine address validity. 926ff4137fSMike Frysingeruchar enetaddr[6]; 936ff4137fSMike Frysingerif (!eth_getenv_enetaddr("ethaddr", enetaddr)) { 946ff4137fSMike Frysinger /* "ethaddr" is not set in the environment */ 956ff4137fSMike Frysinger ... try and setup "ethaddr" in the env ... 966ff4137fSMike Frysinger} 976ff4137fSMike Frysinger/* enetaddr is now set to the value stored in the ethaddr env var */ 986ff4137fSMike Frysinger 996ff4137fSMike Frysinger * int eth_setenv_enetaddr(char *name, const uchar *enetaddr); 1006ff4137fSMike Frysinger 1016ff4137fSMike FrysingerStore the MAC address into the named environment variable. The return value is 1026ff4137fSMike Frysingerthe same as the setenv() function. 1036ff4137fSMike Frysingeruchar enetaddr[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; 1046ff4137fSMike Frysingereth_setenv_enetaddr("ethaddr", enetaddr); 1056ff4137fSMike Frysinger/* the "ethaddr" env var should now be set to "00:11:22:33:44:55" */ 1066ff4137fSMike Frysinger 1076ff4137fSMike Frysinger * the %pM format modifier 1086ff4137fSMike Frysinger 1096ff4137fSMike FrysingerThe %pM format modifier can be used with any standard printf function to format 1106ff4137fSMike Frysingerthe binary 6 byte array representation of a MAC address. 1116ff4137fSMike Frysingeruchar enetaddr[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; 1126ff4137fSMike Frysingerprintf("The MAC is %pM\n", enetaddr); 1136ff4137fSMike Frysinger 1146ff4137fSMike Frysingerchar buf[20]; 1156ff4137fSMike Frysingersprintf(buf, "%pM", enetaddr); 1166ff4137fSMike Frysinger/* the buf variable is now set to "00:11:22:33:44:55" */ 117