Configuring Ubuntu to deal with an ARM board with U-Boot via USB
Abstract
We have a board on which an AllWinner ARM processor is running Linux. The bootloader is U-boot
and we have to use the USB port to flash it.
When flashing the device for the first time, after loading the bootloader via FEL protocol, we need to use tftp to load the SPL (Secondary program Loader) image and the uboot version for use with the spl.
Unfortunately, a couple of issues in the default Ubuntu configuration prevent us from doing this apparently simple operation in a straight way, and we need to tweak some system configuration file.
The issue
After using the sunxi-fel tool to run the bootloader in memory, we need to use the tftp protocol to load the uboot image and other files in order to flash them into the NAND memory.
Uboot can use different ways to do this, but in our setup we have only have the USB cable between the host pc and the device.
Uboot has been compiled with support for usb device, ethernet over usb and tftp protocol.
When launching the tftp command from uboot, a ethernet over usb interface is enabled and the linux kernel on the host pc assign a network device to it.
Since systemd 196, the usual “usbX” name aren’t used anymore, but instead a “predictable network name” is used instead, so the new interface will take a name like “enp0s34e66c2”. Not very predictable, from the user perspective.
If we don’t want to install a DHCP server (it can screw the local network if not properly installed), the problems arises. Since the use of NetworkManager applet, we can’t assign an IP to a network device anymore, because the NetworkManager configure it based on the Mac Address, and sometimes uboot assigns a random mac address to the new device.
So, we the only option I found so far is to disable the NetworkManager completely, but that doesn’t seem a big deal.
The solution
The solution requires three steps:
- disable the NetworkManager for the usb device only.
This way, we prevent NetworkManager from trying to configure the interface. 2. disable the “predictable network name” for the specific usb device.
So, even if we change the Usb port, the name will be really “predictable”, something like “usbX
” instead of “enpXYZ
”. 3. configure a static ip address for the ethernet device
Using/etc/network/interfaces
as we used to do beforesystemd
196.
Disable NetworkManager
Our “non predictable” device name will be “usbX”, so we’re going to disable the NetworkManager for “usb?” device patterns. Let’s change the /etc/NetworkManager/NetworkManager.conf
file, by adding this to the “[device]
” section:
[devices]
match-device=interface-name:usb
managed=0
Disable the “predictable network names” for the device
We’re going to use udev
to change this configuration. I have a special udev rule file for my device, that is identified by ProductId 0x1234 and VendorId 0x5678.
So let’s create the udev rule in /etc/udev/rules.d/99-mydevice.rules
SUBSYSTEM=="net", ACTION=="add", ATTRS{idVendor}=="5678", ATTRS{idProduct}=="1234", NAME="usb0"
There might be other lines, if for example you need to assign groups to the newly created device nodes. This is beyond the scope of this article, of course.
Configuring the network
This is the old way to configure networks before systemd
196.
So let’s add the following lines to the /etc/network/interfaces
file.
allow-hotplug usb0
iface usb0 inet static
address 10.0.0.1
netmask 255.0.0.0
Note that we could have used a dhcp server bound to the usb network interface instead. But usb0
doesn’t exists until it has been enabled by the board itself, so it might be difficult to configure the dhcp server without binding it to all the networks (0.0.0.0
), and this may screw up the local network, if you don’t filter out responses using netfilter
.
So I guess this is the easiest way to allow booting the board.
08/01/2020 Update
On Linux Mint 19, it seems the line allow-hotplug usb0
is needed, otherwise the interface will not be automatically configured with the defined IP.
08/04/2022 Update
On my Ubuntu 20, that didn’t work. It took me a long time to figure out what was wrong, but I finally found it.
First, you need to ensure that the ifupdown
plugin is enabled by NetworkManager, for this reason check that
you have the following line in /etc/NetworkManager/NetworkManager.conf
:
[main]
plugins=ifupdown,keyfile
Then, check that management of ifupdown interfaces are indeed enabled in NetworkManager! Seems trivial but it’s not.
In the same file you need to have
[ifupdown]
managed=true
Otherwise it will never work.