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