blob: f9264859866c1ca57cd927b00d96e3960fbad756 [file] [log] [blame]
Mike Frysinger6ff41372009-02-11 14:12:34 -05001---------------------------------
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
Joe Hershberger92ac5202015-05-04 14:55:14 -050018 - environment ("ethaddr", "eth1addr", ...)
Mike Frysinger6ff41372009-02-11 14:12:34 -050019 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
Heiko Schocher8e64d6e2010-03-31 08:34:51 +020031Correct 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()
Rob Herringc88ef3c2012-04-14 18:06:49 +0000353. The environment variable will be compared to the driver initialized
36 struct eth_device->enetaddr. If they differ, a warning is printed, and the
37 environment variable will be used unchanged.
38 If the environment variable is not set, it will be initialized from
39 eth_device->enetaddr, and a warning will be printed.
Joe Hershbergerbef10142015-05-04 14:55:13 -050040 If both are invalid and CONFIG_NET_RANDOM_ETHADDR is defined, a random,
41 locally-assigned MAC is written to eth_device->enetaddr.
Ben Warrenecee9322010-04-26 11:11:46 -0700424. Program the address into hardware if the following conditions are met:
43 a) The relevant driver has a 'write_addr' function
44 b) The user hasn't set an 'ethmacskip' environment variable
45 c) The address is valid (unicast, not all-zeros)
Heiko Schocher8e64d6e2010-03-31 08:34:51 +020046
Ben Warrenecee9322010-04-26 11:11:46 -070047Previous behavior had the MAC address always being programmed into hardware
48in the device's init() function.
Heiko Schocher8e64d6e2010-03-31 08:34:51 +020049
Mike Frysinger6ff41372009-02-11 14:12:34 -050050-------
51 Usage
52-------
53
54If the hardware design mandates that the MAC address is stored in some special
55place (like EEPROM etc...), then the board specific init code (such as the
56board-specific misc_init_r() function) is responsible for locating the MAC
57address(es) and initializing the respective environment variable(s) from it.
58Note that this shall be done if, and only if, the environment does not already
59contain these environment variables, i.e. existing variable definitions must
60not be overwritten.
61
62During runtime, the ethernet layer will use the environment variables to sync
63the MAC addresses to the ethernet structures. All ethernet driver code should
64then only use the enetaddr member of the eth_device structure. This is done
65on every network command, so the ethernet copies will stay in sync.
66
67Any other code that wishes to access the MAC address should query the
68environment directly. The helper functions documented below should make
69working with this storage much smoother.
70
71---------
72 Helpers
73---------
74
75To assist in the management of these layers, a few helper functions exist. You
76should use these rather than attempt to do any kind of parsing/manipulation
77yourself as many common errors have arisen in the past.
78
79 * void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
80
81Convert a string representation of a MAC address to the binary version.
82char *addr = "00:11:22:33:44:55";
83uchar enetaddr[6];
84eth_parse_enetaddr(addr, enetaddr);
85/* enetaddr now equals { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } */
86
Simon Glass35affd72017-08-03 12:22:14 -060087 * int eth_env_get_enetaddr(char *name, uchar *enetaddr);
Mike Frysinger6ff41372009-02-11 14:12:34 -050088
89Look up an environment variable and convert the stored address. If the address
90is valid, then the function returns 1. Otherwise, the function returns 0. In
91all cases, the enetaddr memory is initialized. If the env var is not found,
Joe Hershberger0adb5b72015-04-08 01:41:04 -050092then it is set to all zeros. The common function is_valid_ethaddr() is used
Mike Frysinger6ff41372009-02-11 14:12:34 -050093to determine address validity.
94uchar enetaddr[6];
Simon Glass35affd72017-08-03 12:22:14 -060095if (!eth_env_get_enetaddr("ethaddr", enetaddr)) {
Mike Frysinger6ff41372009-02-11 14:12:34 -050096 /* "ethaddr" is not set in the environment */
97 ... try and setup "ethaddr" in the env ...
98}
99/* enetaddr is now set to the value stored in the ethaddr env var */
100
Simon Glassfd1e9592017-08-03 12:22:11 -0600101 * int eth_env_set_enetaddr(char *name, const uchar *enetaddr);
Mike Frysinger6ff41372009-02-11 14:12:34 -0500102
103Store the MAC address into the named environment variable. The return value is
Simon Glass382bee52017-08-03 12:22:09 -0600104the same as the env_set() function.
Mike Frysinger6ff41372009-02-11 14:12:34 -0500105uchar enetaddr[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
Simon Glassfd1e9592017-08-03 12:22:11 -0600106eth_env_set_enetaddr("ethaddr", enetaddr);
Mike Frysinger6ff41372009-02-11 14:12:34 -0500107/* the "ethaddr" env var should now be set to "00:11:22:33:44:55" */
108
109 * the %pM format modifier
110
111The %pM format modifier can be used with any standard printf function to format
112the binary 6 byte array representation of a MAC address.
113uchar enetaddr[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
114printf("The MAC is %pM\n", enetaddr);
115
116char buf[20];
117sprintf(buf, "%pM", enetaddr);
118/* the buf variable is now set to "00:11:22:33:44:55" */