xref: /openbmc/u-boot/doc/README.enetaddr (revision a4145534)
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 hardware in the device's init() function.
37
38If somebody wants to subvert the design philosophy, this can be done
39in the board-specific board_eth_init() function by calling eth_init()
40after all the NICs have been registered.
41
42-------
43 Usage
44-------
45
46If the hardware design mandates that the MAC address is stored in some special
47place (like EEPROM etc...), then the board specific init code (such as the
48board-specific misc_init_r() function) is responsible for locating the MAC
49address(es) and initializing the respective environment variable(s) from it.
50Note that this shall be done if, and only if, the environment does not already
51contain these environment variables, i.e. existing variable definitions must
52not be overwritten.
53
54During runtime, the ethernet layer will use the environment variables to sync
55the MAC addresses to the ethernet structures.  All ethernet driver code should
56then only use the enetaddr member of the eth_device structure.  This is done
57on every network command, so the ethernet copies will stay in sync.
58
59Any other code that wishes to access the MAC address should query the
60environment directly.  The helper functions documented below should make
61working with this storage much smoother.
62
63---------
64 Helpers
65---------
66
67To assist in the management of these layers, a few helper functions exist.  You
68should use these rather than attempt to do any kind of parsing/manipulation
69yourself as many common errors have arisen in the past.
70
71	* void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
72
73Convert a string representation of a MAC address to the binary version.
74char *addr = "00:11:22:33:44:55";
75uchar enetaddr[6];
76eth_parse_enetaddr(addr, enetaddr);
77/* enetaddr now equals { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } */
78
79	* int eth_getenv_enetaddr(char *name, uchar *enetaddr);
80
81Look up an environment variable and convert the stored address.  If the address
82is valid, then the function returns 1.  Otherwise, the function returns 0.  In
83all cases, the enetaddr memory is initialized.  If the env var is not found,
84then it is set to all zeros.  The common function is_valid_ether_addr() is used
85to determine address validity.
86uchar enetaddr[6];
87if (!eth_getenv_enetaddr("ethaddr", enetaddr)) {
88	/* "ethaddr" is not set in the environment */
89	... try and setup "ethaddr" in the env ...
90}
91/* enetaddr is now set to the value stored in the ethaddr env var */
92
93	* int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
94
95Store the MAC address into the named environment variable.  The return value is
96the same as the setenv() function.
97uchar enetaddr[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
98eth_setenv_enetaddr("ethaddr", enetaddr);
99/* the "ethaddr" env var should now be set to "00:11:22:33:44:55" */
100
101	* the %pM format modifier
102
103The %pM format modifier can be used with any standard printf function to format
104the binary 6 byte array representation of a MAC address.
105uchar enetaddr[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
106printf("The MAC is %pM\n", enetaddr);
107
108char buf[20];
109sprintf(buf, "%pM", enetaddr);
110/* the buf variable is now set to "00:11:22:33:44:55" */
111