Friday, January 20, 2012

PandaBoard: get persistent MAC address by default

The PandaBoard/PandaBoard ES, as the BeagleBoard too, don't have a EEPROM on the (USB-) network card to store the MAC address. That's why you get a new MAC and subsequently a new IP address with each boot. You can set the MAC manually via e.g. 'ifconfig eth0 hw ether 01:23:45:67:78:01' or also automatically via the network scripts.

The other solution would be to generate a MAC on OMAP (version > 2) machines by reusing another unique hardware identifier. There is already an old patch written by Mark Crichton for the BeagleBoard. And there was also an patch on the kernel mailing list from Andy Green and some related discussion, but none of them got into the kernel.  The problem was that if there are more than one card in the system without EEPROM they all would get the same MAC address. That sounds reasonable to me while I'm not sure that something like this will happen with a high chance out in the field. And since there are objections against exporting the OMAP die ID to the sysfs there is no simple way to handle the MAC generation in userspace (e.g. via udev).

While investigating how u-boot handle the no-EEPROM problem, I've found out that the u-boot code already contain functions to generate a persistent MAC for such devices. The MAC gets also exported to the u-boot environment as usbethaddr. That's why I wrote a patch for the smsc95xx kernel driver (based on a patch from Sebastien Jan) to take a module parameter to set the MAC address via the kernel command line. With this patch the driver takes the following parameter: macaddr=01:23:45:67:89:ab;[tgt-netdevname] and assign the given MAC address to the first device in the system without a MAC on the EEPROM. If there is more than one device without EEPROM you can add the netdevice name to the parameter - separated by a ';' - to assign it to a special device (e.g. for eth0: macaddr=01:23:45:67:89:ab;eth0). If there is no MAC given, the device still gets a random MAC as before.

After patching and installing your kernel, you need to change the u-boot config to pass the $usbethaddr from the environment along to the kernel cmdline. I used a uEnv.txt file (on my boot partition) instead of the legacy/obsolete boot.scr, since you simply can change the file without call mkimage after each change. That's the content of the uEnv.txt file I currently use to set the MAC of my PandaBoard ES:

bootargs=root=/dev/mmcblk0p2 rw rootwait rootfstype=ext3 console=ttyO2,115200n8 vram=16M omapfb.vram=0:16M
bootcmd=mmc rescan ; setenv bootargs ${bootargs} smsc95xx.macaddr="${usbethaddr}" ; fatload mmc 0 0x82000000 uImage; bootm 0x82000000
You can find the patch here, I plan to include it into the openSUSE OMAP2+ kernel and to send it upstream as soon as I have some reports back that it also works for others. You can find an kernel RPM for openSUSE Factory here.