xref: /openbmc/u-boot/doc/README.enetaddr (revision 0adb5b761f4c789ae47d8abb015f5e017263d3f2)
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()
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.
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,
90*0adb5b76SJoe Hershbergerthen it is set to all zeros.  The common function is_valid_ethaddr() 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