Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there Linux or U-Boot support to read a MAC address from a chip at startup?

My company builds custom hardware in such low quantities that it doesn't make financial sense to buy a whole block of MAC addresses. What chip, if any, could I design into my embedded Linux board that could be used to automatically assign a globally unique MAC address at startup?

I've searched for Linux and u-boot driver support for MAC chips and EUI-48 chips, but come up empty. MicroChip part number 24AA02E48 is an I2C chip that holds an EUI-48 address suitable as a MAC address. There is also DS2502-48, a serial 1-wire chip that we've previously used by writing a separate u-boot application to read its MAC address, and assign it to the U-Boot ethaddr environment variable, but that was a manual step that I want to eliminate. The 1-wire timing was so tight that the u-boot application occasionally failed to properly read the MAC address, so we never fully automated the process.

Is there any Linux or u-boot driver than can be configured to read a MAC address chip automatically at startup?

like image 383
edj Avatar asked Feb 05 '23 14:02

edj


2 Answers

As far as I know, you don't need a chip at all. The standards for MAC allow you to generate a "locally administered" MAC address which falls short of guaranteed global uniqueness. For small manufacturers like yourself, that's nearly always good enough, which is why the standards allow it.

Just be sure to follow those standards when picking a number, such as setting the U/L bit to "1" to guarantee that it cannot match a registered address (U/L bit == "0"). A "tl;dr" way to generate a valid local MAC address is to make the first three pairs "02:00:00:" and the last three pairs random hex digits; but if you're building hardware, I suggest taking the time to read the standards or at least the Wikipedia page.

In the event of a coincidental clash in the the pseudo-random digits, if at all possible give the customer a way to change your default MAC choice. Even if you have a registered address, it's still good to let the customer change it. Sometimes admins will tweak MAC's in ways that make routing and/or load-balancing easier, and very occasoinally they need to dodge a MAC generated by someone who thought it was OK to hard-code "00:00:00:00:00:00" or pick 12 random hex digits.

As for reading the MAC from Linux drivers or U-Boot, I don't know about your device, but I find it easiest to use U-Boot because it works at a lower level. U-Boot stores the MAC's it finds in the environment variables "ethaddr", "eth1addr", and "eth2addr". The command "printenv" is one way to view them. Here's an example from a board that happens to be in front of me right now:

U-Boot# printenv ethaddr eth1addr eth2addr
ethaddr=98:5d:ad:43:dd:38
eth1addr=98:5d:ad:43:dd:3a
## Error: "eth2addr" not defined

The U-Boot command "bdinfo" might also be useful. Again from the board in front of me:

U-Boot# bdinfo
arch_number = 0x0000106E
boot_params = 0x80000100
DRAM bank   = 0x00000000
-> start    = 0x80000000
-> size     = 0x20000000
eth0name    = cpsw
ethaddr     = 98:5d:ad:43:dd:38
current eth = cpsw
ip_addr     = <NULL>
baudrate    = 115200 bps
TLB addr    = 0x9FFF0000
relocaddr   = 0x9F753000
reloc off   = 0x1EF53000
irq_sp      = 0x9F332F38
sp start    = 0x9F332F28

U-Boot even includes an optional "gen_eth_addr" tool to generate valid locally administered addresses. Here's a usage example, excerpted from their wiki page at: https://www.denx.de/wiki/DULG/WhereCanIGetAValidMACAddress

$ make tools/gen_eth_addr
cc     tools/gen_eth_addr.c   -o tools/gen_eth_addr
$ tools/gen_eth_addr
ba:d0:4a:9c:4e:ce
like image 164
William Dye Avatar answered Feb 07 '23 08:02

William Dye


Having exactly the same problem, I could succesfully use this snippet. It reads MAC address from a I2c eeprom somewhere in memory and builds the string for "ethaddr" variable. Obviously, you need to "run setup_eth" somewhere, I did in in "preboot". I hope it helps.

#ethernet related setup
setup_eth=run readmac buildmac
#read mac address from eeprom
readmac=i2c dev 0; i2c read 50 FA.1 6 $loadaddr
#build the ethaddr variable
#not very nice, but does the job
buildmac=\
e=" "; sep=" " \
for i in 0 1 2 3 4 5 ; do\
setexpr x $loadaddr + $i\
setexpr.b b *$x\
e="$e$sep$b"\
sep=":"\
done &&\
setenv ethaddr $e
like image 44
Gabriel C. Avatar answered Feb 07 '23 09:02

Gabriel C.