How to boot the A10 or A20 over the network

TFTP/NFS booting with the A10
You'll need a Linux box, a microSD card, a card reader and a serial console adapter for this tutorial. I've used VirtualBox on my Win8 x64 host with an Ubuntu 10.04 x64 guest and connected the SD card directly to the VM using the USB gateway feature of Virtualbox.

sudo add-apt-repository ppa:linaro-maintainers/toolchain
 * Install or build a GCC ARM toolchain for your Linux distribution. For Ubuntu 10.04 you can install a prebuilt toolchain like this very easily (newer Ubuntu version may have this pacakage by default):

sudo apt-get update

sudo apt-get install gcc-arm-linux-gnueabi

git clone https://github.com/linux-sunxi/u-boot-sunxi.git git checkout sunxi-current
 * Clone sunxi-current u-boot git repository:

make cubieboard_config make CROSS_COMPILE=arm-linux-gnueabi-
 * Go to the project directory and execute the build commands. Replace the board name in the first command with the one you're working with. I'm using Cubieboard in this example.

After finishing you'll find compiled files required for us at spl/u-boot-spl.bin and u-boot.bin.


 * Let's put them on an SD card to try out.


 * I've started with erasing my SD card, to be sure nothings conflicting with my setup. BEWARE! if you provide a wrong device address to of= you can easily erase sensitive data. Use dmesg to find out where the SD card is attached in the /dev tree. In my case SD card was /dev/sdb so I've executed:

dd if=/dev/zero of=/dev/sdb bs=1M
 * Wait for dd to fully overwrite your SD card.


 * Write the two loaders to the correct positions on the SD card. Again modify the -of device to yours! I'm executing these in the project root of uboot.

dd if=spl/sunxi-spl.bin of=/dev/sdb bs=1024 seek=8 conv=noerror,sync dd if=u-boot.bin of=/dev/sdb bs=1024 seek=32 conv=noerror,sync


 * SD Card is now ready to take for a spin. Put it into your board and connect your serial console and fire up a terminal on your host PC so you can interact with u-boot. Now power on the board. After booting you should see something like this:

U-Boot SPL 2013.01-05621-gb7b6374 (Jan 18 2013 - 23:01:07) Board: Cubieboard DRAM: 1024MB SUNXI SD/MMC: 0 U-Boot 2013.01-05621-gb7b6374 (Jan 18 2013 - 23:01:07) Allwinner Technology CPU:  SUNXI Family Board: Cubieboard I2C:  ready DRAM: 1 GiB MMC:  SUNXI SD/MMC: 0 In:   serial Out:  serial Err:  serial Net:  wemac Hit any key to stop autoboot: 0 sun4i#

I've stopped autoboot because we don't have any partitions on the SD card yet so it'll not succeed booting.


 * Let's bring up the ethernet interface.
 * First we must set the ethaddr variable to the MAC address of the NIC on the board. Probably you'll have no clue what's yours just like me. For testing purposes you can use something dummy like this:

sun4i#setenv ethaddr 12:34:56:78:99:aa


 * but please don't do this in production environment. I've also recommend you to use

sun4i#setenv autoload no


 * because by default once you execute the next 'dhcp' command and autoload is enabled it will automatically try to load an image from TFTP, named as the ip address in hex followed by .img, which is not really useful for us.


 * Let's save this config to the SD card so you won't have to type it again next time

sun4i#saveenv Saving Environment to MMC...   Writing to MMC(0)... done


 * Now request an IP address via DHCP. Connect your ethernet cable and type 'dhcp' into u-boots prompt.

sun4i#dhcp ENET Speed is 100 Mbps - FULL duplex connection BOOTP broadcast 1 DHCP client bound to address 192.168.1.206
 * Now you're ready to try out TFTP or NFS. I'm using TFTP in this example but NFS work similarly. See the u-boot manual or type 'help' into the u-boot terminal to get help on other commands.


 * You have to specify the server IP address where the TFTP server is running. You can pass this to the 'tftp' command or save it permanently in the environment:

setenv serverip 192.168.1.202 saveenv
 * Let's say you now have a TFTP server running on the IP address saved above and serving files and have a kernel named 'kernel' in the server file system. Type

tftp kernel to load it to the default address 0x50000000 in the SRAM:

sun4i#tftp kernel Using wemac device TFTP from server 192.168.1.202; our IP address is 192.168.1.206 Filename 'kernel'. Load address: 0x50000000 Loading: ################################################################# #################################################################            #################################################################             #################################################################             #################################################################             #################################################################             #################################################################             #################################################################             #################################################################             #################################################################             #################################################################             #################################################################             #####################################################             266.6 KiB/s done Bytes transferred = 4261224 (410568 hex)


 * Now if you've prepared the kernel for booting with u-boot's mkimage tool you can execute

bootm
 * to boot the kernel you've just downloaded. This is not really useful because the kernel has no rootfs to work with right now. You can download the rootfs similarly to the SRAM of the board or use an NFS share to host this. See the u-boot documentation to know how to do this.

Web resources

 * I've found this wiki page quite useful for explaining the kernel booting with u-boot: http://processors.wiki.ti.com/index.php/Booting_Linux_kernel_using_U-Boot


 * You can read more about mkimage's usage here: http://www.linuxfordevices.com/c/a/Linux-For-Devices-Articles/Introduction-to-Das-UBoot-the-universal-open-source-bootloader/


 * I followed this tutorial to fire up a TFTP server in Ubuntu: http://www.davidsudjiman.info/2006/03/27/installing-and-setting-tftpd-in-ubuntu/ I've installed this into to VM I'm compiling stuff to the Cubieboard and set Virtualbox to bridge the internal NIC adapter directly to my local network where the Cubieboard is also connected. This way i have a straight VM to Cubieboard development environment.

Booting Arch Linux from an NFS share

 * Prerequisites: build and install uboot as described in the previous part.
 * In this tutorial i'm going to load the kernel and script.bin from the NFS share aswell.
 * Build the kernel
 * You have to compile a custom kernel because you have to enable root NFS support to work with NFS mounted root filesystems.
 * Clone the kernel:

git clone https://github.com/linux-sunxi/linux-sunxi
 * Follow the build instructions described here: http://linux-sunxi.org/Linux#Building but before executing the second build command modify .config file in the kernel's source directory to contain the following lines:

CONFIG_IP_PNP=y CONFIG_ROOT_NFS=y
 * You might get some question from the next build command but you just have to say yes when it asks for the values above. You'll find the built kernel at arch/boot/uImage if you did everything right.


 * Prepare NFS share
 * I'm using Ubuntu 10.04 for this, you have to install the required package

apt-get install nfs-kernel-server
 * Create a share directory.

mkdir -p /var/nfsexport/arch/
 * Edit /etc/exports to include this directory. Put the following line to the end:

/var/nfsexport *(rw,sync,no_root_squash,no_subtree_check)
 * Finally restart the daemon

/etc/init.d/nfs-kernel-server restart
 * Copy required files
 * Copy uImage from the first step to /var/nfsexport/arch/
 * We have to build a script.bin file for the kernel to work properly. Clone the https://github.com/linux-sunxi/sunxi-boards and https://github.com/linux-sunxi/sunxi-tools repository and compile sunxi tools (make). After that you have to convert your boards fex file with the fex2bin you've just built. In my case:

./sunxi-tools/fex2bin sunxi-boards/sys_config/a10/cubieboard.fex > script.bin
 * Copy script.bin next to the kernel
 * Download and extract Arch rootfs image. I'm using the MeleA100 image from the Arch ARM Linux site. Extract it to the NFS export folder:

wget http://archlinuxarm.org/os/ArchLinuxARM-sun4i-latest.tar.gz  tar xzf ArchLinuxARM-sun4i-latest.tar.gz -C /var/nfsexport/arch/
 * Configure uboot
 * Boot into uboot with the serial console attached and halt autoboot by pressing a key
 * Modify bootargs. You have to replace serverip with your NFS server's IP.

setenv serverip  setenv bootcmd "nfs 0x43000000 ${serverip}:/var/nfsexport/arch/script.bin; nfs 0x48000000 ${serverip}:/var/nfsexport/arch/uImage; bootm 0x48000000" setenv bootargs "console=ttyS0,115200 noinitrd root=/dev/nfs nfsroot=${serverip}:/var/nfsexport/arch ip=${ipaddr}:${netmask}:${gatewayip}:::eth0" saveenv
 * Reset the board


 * Board will boot into Arch. You can log in with root/root.
 * Known bugs:
 * Reboot is not working; network interface is stopped but Arch wants to write something to the NFS mount which can't be done after that.
 * No output on HDMI but you can interact with Arch through the serial console or by using an SSH client and connect to the IP you've specified in uboot.