fw_printenv config for AllWinner devices

The u-boot suite of tools has a very handy tool allowing you to work with the u-boot environment from Linux user space. There are two complications with this on the Allwinner SoCs, first the version of the u-boot tools that Debian ships don’t support the mmc card.

You’ll need an up to date version of u-boot git tree either directly from denx or the linux-sunxi project. Downloading and setting up the git u-boot tree is well documented so I’m not going to cover it here, but the fw_printenv tool isn’t built by default so you need to build it.

make env

The fw_printenv tool is found in the tools/env directory, copy it somewhere useful.

sudo install -m 755 tools/env/fw_printenv /usr/local/bin/

To write to the u-boot environment you also need to create a symlink from fw_printenv to fw_setenv.

sudo ln -s /usr/local/bin/fw_printenv /usr/local/bin/fw_setenv

The second problem is making a working configuration file. The configuration file only needs a single line in it to tell fw_printenv where to look (the offset from the start of the device) for the u-boot environment and how big it is. The complication is they need to be in bytes and given in hex, to calculate the offset and size I used the sd layout from the sunxi wiki and a bit of maths in bc to convert it to hex.

To calculate the offset, multiply the number (1088) of blocks by the block size (512 bytes) and then convert it to base16 (ie hex)

echo "obase=16; 1088*512 "| bc

To calculate the size of the u-boot environment repeat the process but this time with the number (128) of blocks by the block size (1024 bytes) and again convert it to base16.

echo "obase=16; 128*1024 "| bc

Finally put the numbers we have calculated in to the configuration file /etc/fw_env.config

# Device to access      offset          env size
/dev/mmcblk0            0x88000         0x20000

You should now be able to run fw_printenv and get your environment printed out, if the error “Warning: Bad CRC, using default environment” then your u-boot setup is different and you shouldn’t use fw_setenv.

Create a bootable SD for a Cubietruck

Assuming you have followed the last post you should now have a directory with a Debian armhf root filesystem in. The next stage is to build a bootable SD card image to actually boot your Cubietruck from.

The Allwinner SoC doesn’t have a bios in the way a x86 computer does and the boot process is made up of a number of stages, for full details see the Rhombus Tech website. The parts that we care about are the SPL and u-boot which are written to the SD card 8 blocks in, u-boot then loads a kernel called uImage from the first partition.

I extracted the kernel, modules and firmware from a Linaro image, which is part of the Cubietruck lubuntu tutorial. I did this because Debian doesn’t currently have a working Allwinner kernel and I intended to build a main line kernel anyway. The files I used are listed below.

Name Desc URL
u-boot u-boot with spl download
bootfs uImage, uEnv.txt, script.bin download
rootfs rootfs download

Once you have got the files downloaded you need to put the bootloader on the SD card and transfer the rootfs.

First of all set the directory that the rootfs you have made previously or downloaded.

targetdir=rootfs

This is the tar command to exact the modules and firmware, to the correct places in the rootfs directory. This assumes you have downloaded the Linaro rootfs file or my file.

sudo tar xvfz rootfs-part2.tar.gz -C $targetdir lib/modules lib/firmware

Setup modules to autoload at boottime, these modules are for the GPIO pins, the graphics and the wireless+bluetooth adapter. These modules are for the 3.4 sunxi kernel.

cat <<EOT > $targetdir/etc/modules
gpio_sunxi
pwm_sunxi
sunxi_gmac
disp
lcd
hdmi
ump
mali
bcmdhd
EOT

Now we need to actually put things on the SD card, be careful with dd it can and will wipe your harddisk if you make a mistake. In my case I had an SD card reader so I set things to point at that slot only by using the by-id links from udev. These by-id links which include the serial number which helped to avoid mistakes. The following commands assume you have done the same and are using by-id links.

card='/dev/disk/by-id/usb-Generic_Ultra_HS-SD_MMC_F120A600A9CB-0:0'

Blank the first 1MB of the card

dd if=/dev/zero of=${card} bs=1M count=1

Write u-boot and spl to the correct spot on the SD card.

dd if=u-boot-sunxi-with-spl-ct-20131102.bin of=$card bs=1024 seek=8

Build a partition table with 256M of boot space and the rest in a single large partition.

cat <<EOT | sfdisk --force --in-order -uS $card
2048,524288,L
526336,,L
EOT

Format and mount the first partition of the SD card

mkfs.ext2 ${card}-part1
mkdir -p /run/cubietruck-part1
mount  ${card}-part1 /run/cubietruck-part1

Extract the kernel and support files from the Linaro bootfs download

tar -C /run/cubietruck-part1 -xvf bootfs-part1.tar.gz
umount /run/cubietruck-part1
rmdir /run/cubietruck-part1

Finally format the second partition of the SD card and copy over the rootfs you have built

mkfs.ext4 ${card}-part2
mkdir -p /run/cubietruck-part2
mount  ${card}-part2 /run/cubietruck-part2
rsync -avxPHS $targetdir/ /run/cubietruck-part2/

And un-mount the card before ejecting it

umount /run/cubietruck-part1
rmdir /run/cubietruck-part1
eject $card

Building a pure Debian armhf rootfs

There are lots of filesystems images for various Debian flavours on ARM developer boards like the Cubietruck floating about. Most of these images are large binary files of unknown providence and even compressed take a while to download. There is a better way of making a root image for your new ARM board, just build it on your own normal workstation directly from the Debian repos with debootstrap using the magic of QEMU.

First install the support packages on your workstation:

sudo apt-get install qemu-user-static debootstrap binfmt-support

You will need about 500MB of space in a directory for the image, choose the version of Debian in this case we are building a wheezy image.

targetdir=rootfs
distro=wheezy

Lets get going building the first stage of the rootfs image from the Debian mirrors, this will take a few minutes and downloads about 200MB.

mkdir $targetdir
sudo debootstrap --arch=armhf --foreign $distro $targetdir

Next copy the the qemu-arm-static binary into the right place for the binfmt packages to find it and copy in resolv.conf from the host.

sudo cp /usr/bin/qemu-arm-static $targetdir/usr/bin/
sudo cp /etc/resolv.conf $targetdir/etc

We now have a very basic armhf rootfs in a directory, the next stages take place inside a chroot of that directory.

sudo chroot $targetdir

Inside the chroot we need to set up the environment again

distro=wheezy
export LANG=C

Now we need to complete the second stage of debootstrap to install the packages downloaded earlier

/debootstrap/debootstrap --second-stage

Once the package installation has finished, setup some basic support files

cat <<EOT > /etc/apt/sources.list
deb http://ftp.uk.debian.org/debian $distro main contrib non-free
deb-src http://ftp.uk.debian.org/debian $distro main contrib non-free
deb http://ftp.uk.debian.org/debian $distro-updates main contrib non-free
deb-src http://ftp.uk.debian.org/debian $distro-updates main contrib non-free
deb http://security.debian.org/debian-security $distro/updates main contrib non-free
deb-src http://security.debian.org/debian-security $distro/updates main contrib non-free
EOT

cat <<EOT > /etc/apt/apt.conf.d/71-no-recommends
APT::Install-Recommends "0";
APT::Install-Suggests "0";
EOT

Pull in the latest apt database from the Debian mirrors

apt-get update

Install the locales package otherwise dpkg scripts, note in jessie you may need to install the dialog package as well.

apt-get install locales dialog
dpkg-reconfigure locales

Install some additional packages inside the chroot, an ssh server for network access and ntp because many boards don’t have a functional RTC.

apt-get install openssh-server ntpdate

Set a root password so you can login via ssh or the console

passwd

Build a basic network interfaces file so that the board will DHCP on eth0

echo <<EOT >> /etc/network/interfaces
allow-hotplug eth0
iface eth0 inet dhcp
EOT

Set the hostname

echo debian-armhf > /etc/hostname

Enable the serial console, Debian sysvinit way

echo T0:2345:respawn:/sbin/getty -L ttyS0 115200 vt100 >> /etc/inittab

We are done inside the chroot, so quit the chroot shell

exit

Tidy up the support files

sudo rm $targetdir/etc/resolv.conf
sudo rm $targetdir/usr/bin/qemu-arm-static

You now have a root file system for pretty much any armhf machine but next you need to make a bootable sd card image. I’ll cover that in the next post, there are other howtos to assemble the bootable card.