Sep 24, 2014

Minimal Zedboard rootfs produced by buildroot

In my previous attempts at creating a functional GUI platform on Linaro Ubuntu desktop distribution, I learned that there is just too much going on in a large Linux distribution to really understand a problem and troubleshoot it.  Therefore, this is a bottom-up approach to creating a root file system.

Get Buildroot

Packages required by Buildroot (for xconfig--the QT4 GUI; GTK GUI option requires GTK2+ dev packages, which I don't want to bother with):
sudo apt-get install \
build-essential gawk bison flex gettext texinfo patch gzip bzip2 perl tar wget cpio python unzip rsync libqt4-dev

Get the buildroot source.
$ git clone git://git.buildroot.net/buildroot

And then switch over to the latest stable branch (which is 2014.08 right now)
$ git checkout 2014.08
$ git pull . 2014.08

Configure Buildroot

Spencer Gilliland already checked in a config for Zedboard, so I compared it with what I did in the "Ubuntu on Zedboard" tutorial.
BR2_arm=y
BR2_cortex_a9=y
BR2_ARM_ENABLE_NEON=y
BR2_KERNEL_HEADERS_VERSION=y
BR2_DEFAULT_KERNEL_VERSION="3.8"
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_3_8=y
BR2_TARGET_GENERIC_GETTY_PORT="ttyPS0"
From the Avnet "Ubuntu on Zedboard" tutorial I went through, the kernel from ADI is version 3.15.  ttyPS0 matches the console device used in "Ubuntu on Zedboard" tutorial.
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_GIT=y
BR2_LINUX_KERNEL_CUSTOM_REPO_URL= "git://github.com/Xilinx/linux-xlnx.git"
BR2_LINUX_KERNEL_CUSTOM_REPO_VERSION= "xilinx-v2014.1"
BR2_LINUX_KERNEL_DEFCONFIG="xilinx_zynq"
BR2_LINUX_KERNEL_UIMAGE_LOADADDR="0x8000"
Note the CUSTOM_GIT; I need the kernel from ADI https://github.com/analogdevicesinc/linux.git xcomm_zynq branch.  DEFCONFIG target is zynq_xcomm_adv7511.  uImage is made with mkimage produced from U-boot (then soft lined to /usr/bin/mkimage).  Load addr is the same.
BR2_LINUX_KERNEL_DTS_SUPPORT=y
BR2_LINUX_KERNEL_INTREE_DTS_NAME="zynq-zed"
In "Ubuntu on Zedboard" tutorial, the DTB file produced was zynq-zed-adv7511.dtb, was renamed to devicetree.dtb in the SD card BOOT partition.
BR2_TARGET_ROOTFS_CPIO=y
BR2_TARGET_ROOTFS_CPIO_GZIP=y
BR2_TARGET_ROOTFS_CPIO_UIMAGE=y
Root file system
BR2_TARGET_UBOOT=y
BR2_TARGET_UBOOT_BOARDNAME="zynq_zed"
BR2_TARGET_UBOOT_CUSTOM_GIT=y
BR2_TARGET_UBOOT_CUSTOM_REPO_URL= "git://github.com/Xilinx/u-boot-xlnx.git"
BR2_TARGET_UBOOT_CUSTOM_REPO_VERSION= "xilinx-v2014.1"
BR2_TARGET_UBOOT_FORMAT_IMG=y
BR2_TARGET_UBOOT_SPL=y
BR2_TARGET_UBOOT_SPL_NAME="boot.bin"
The git repository is the same as "Ubuntu on Zedboard" tutorial, but this branch is newer than the 2013.4 used in "Ubuntu on Zedboard" tutorial.  Config target is the same.  It would be nice if there is a way to specify the default bootargs (like maxcpus=1 that I will need to specify eventually).

Buildroot should NOT create the boot.bin for Zynq, because it has no way to insert the bitstream file into boot.bin.
Note that the toolchain was NOT specified above.

Fire up the config tool
$ make xconfig

Load the above config in the xconfig GUI (menu --> File --> Load).  Going through the items, I saw some strange choices:
  • Target options
    • Target ABI: shouldn't it be EABIhf rather than EABI (default)?  No unless the toolchain actually uses EABIhf as well, which the XSDK (Sourcery Codebench) toolchain doesn't.  This blog (dated 2010) discussed the feature to my satisfaction; soft float still uses the FP HW, but the arguments are passed through the integer registers rather than special registers for FP.
    • Shouldn't the floating point strategy be NEON, rather than Soft float, which (according to the above blog) speeds up the floating point register use in function calls?  The risk is not in rebuilding the toolchain in buildroot, but whether all the SW I need have been ported to EABIhf.  I decided not to take the risk, but only in the 2nd pass.
So for the 1st pass, here are the options I am using that are different than configs/zedboard_defconfig:
  • Build options
    • Compile cache disabled.  This may be helpful later when the packages are debugged on my system.
    • gcc optimization level: I changed from "size" to "level 3", because there is plenty of storage, but the CPU is relatively slow.
  • Toolchain: I tried to use Xilinx SDK as the external tool, but it did not work out, so left it at Buildroot toolchain
    • Kernel headers: I tried to specify Linux version 3.15.0, but this failed, so I just specified Linux 3.16.x kernel headers and cross my finger.
    • C library: uClibc
  • System configuration
    • System hostname: zed
    • System banner: "Welcome to Zedboard!"
    • Root password: I changed from the empty (no password) to something else
    • Check "install timezone info"
      • default local time: America/Los_Angeles
    • Path to users tables: /mnt/work/zynq/BR2/ROOTFS_USERS_TABLES, which looks like this:
      foo -1 wheel -1 =<password> /home/foo /bin/sh - Foo user 
  • Kernel
    • Change kernel version from "Custom Git repository" to "Local directory", because I want to use my own defconfig (named zynq_xcomm_adv7511_nfs, for NFS root filesystem) which cannot be checked into the original git source (ADI github account).  For now, I am keeping a clone of the ADI Zynq kernel at /mnt/work/zynq/kernel.
    • Load address (unchanged): 0x8000
    • Device tree support
      • DTS source file name: zynq-zed-adv7511
  • Target packages
    • Shell and utilities: screen, sudo, vi (note that vi will bin in /bin rather than /usr/bin, so that you have to make a symbolic link for visudo command later)
  • Filesystem images
    • Uncheck "cpio the root filesystem (for use as an initial RAM filesystem), because I want to NFS export the root filesystem for now.
    • When I also unchecked "tar the root filesystem", I did not get ANY root file system (output/target LOOKS like RFS, but in that folder, there is a file THIS_IS_NOT_YOUR_ROOT_FILESYSTEM).
  • Bootloaders: U-Boot
    • U-Boot board name: zynq_zed
    • Custom repository version: xilinx-v2013.4
    • U-Boot binary format: u-boot.elf
    • Uncheck "U-Boot SPL support", because I am using Xilinx FSBL (necessary for AMP).
    • Environment image: I should "saveenv" on u-boot shell, and then copy that text file to the host, and use this feature.

Build

Save the changes (menu --> File --> Save As) to .config file, then kick off make.  The build went smoothly until building u-boot, then just stopped without any error.  I CD'ed into the u-boot folder and just ran make there to finish building u-boot, then came back to the top of the buildroot and retried make again, which went through this time.  The build products are in output/images folder:
$ file output/images/*
output/images/rootfs.tar:           POSIX tar archive (GNU)
output/images/u-boot:               ELF 32-bit LSB  shared object, ARM, EABI5 version 1 (SYSV), statically linked, not stripped
output/images/uImage:               u-boot legacy uImage, Linux-3.15.0, Linux/ARM, OS Kernel Image (Not compressed), 3124128 bytes, Wed Sep 24 19:50:31 2014, Load Address: 0x00008000, Entry Point: 0x00008000, Header CRC: 0xB6EDEAD5, Data CRC: 0xC213B552
output/images/zynq-zed-adv7511.dtb: data

Recall in "Ubuntu on Zedboard" tutorial, I renamed a few files when copying to the SD card:
  • u-boot to u-boot.elf, for the Xilinx FSBL to find it in the boot partition
  • zynq-zed-adv7511.dtb to devicetree.dtb , because that is the filename u-boot is looks for

Buildroot imperfection induced chores

It looks like Buildroot ignored my request for u-boot.elf, and I will have to write a post-build script to rename the zynq-zed-adv7511.dtb to devicetree.dtb, and untar the rootfs.tar in the /export/root folder.  For the first time, do it manually.

Recall setting up the NFS export on the development host in another blog entry.  Let's copy the boot.bin from XSDK (generated for the "Ubuntu on Zedboard" tutorial, u-boot.elf, uImage, and devicetree.dtb to an SD card's FAT32 BOOT partition first, and then wipe out the ext4 rootfs partition I used to use for the root file system, to make sure I don't accidentally use that root file system.

The rootfs.tar generated by buildroot was extracted to the NFS export (as root, not just with sudo), and when I booted the Zedboard, I was able to log in finally as the user I created in ROOTFS_USERS_TABLES, which looks like this:

foo -1 wheel -1 =<clear passwd> /home/foo /bin/sh - Foo user

Add group wheel to sudoers

The group "wheel" is a choice made to easily allow "foo" into the sudoers file, which already has a COMMENTED OUT entry:

## Uncomment to allow members of group wheel to execute any command
# %wheel ALL=(ALL) ALL                                                          
## Same thing without a password                                   
# %wheel ALL=(ALL) NOPASSWD: ALL

All I have to do is uncomment either of the above lines for user foo to get sudo, but there doesn't seem to be a sudoers template file in <BR2>/system/skeleton, so I went straight to the template in to sudo package: <BR2>/output/target/etc/sudoers, which CAN be erased when you blow away output/build.

Add DNS server

If I specify "ip=dhcp" to the kernel boot args, the target SHOULD get a name server through DHCP, as in this dmesg snippet:

IP-Config: Got DHCP answer from 192.168.1.1, my address is 192.168.1.9
IP-Config: Complete:
     device=eth0, hwaddr=00:0a:35:00:01:22, ipaddr=192.168.1.9, mask=255.255.255.0, gw=192.168.1.1
     host=192.168.1.9, domain=, nis-domain=(none)
     bootserver=0.0.0.0, rootserver=192.168.1.2, rootpath=
     nameserver0=192.168.1.1

Unfortunately, the nameserver0 value does not seem to make its way to the /etc/resolv.conf, because Buildroot creates the /etc/resolv.conf as a softlink to /tmp/resolv.conf, which does NOT exist, even after booting.  I can work around this by changing /exports/root/zed/etc/resolv.conf softlink into a file containing a single line:

nameserver 192.168.1.1

I tried to change the file in <BR2>/output/target/skeleton/etc, but that was overwritten for some reason.

Once the DNS works, I can run ntpdate on the target to correct the time, like this:

# ntpdate ntp.ubuntu.com
 7 Dec 22:50:05 ntpdate[798]: step time server 91.189.94.4 offset 1417992459.172424 sec

I can probably put this command in cron (or dcron, if using busybox).  TODO.

Boot the target

When I pop in the SD card into the Zedboard's SD card slot, with the boot mode pin set to 5'b01100, the targets boots up all the way to user shell in about 20 seconds:
...
VFS: Mounted root (nfs filesystem) on device 0:12.
devtmpfs: mounted
Freeing unused kernel memory: 204K (c0612000 - c0645000)
Starting logging: OK
Initializing random number generator... random: dd urandom read with 32 bits of entropy available
done.
Starting network...
ip: RTNETLINK answers: File exists

Welcome to Zeboard!
zed login: foo
Password: 

No comments:

Post a Comment