Intro
I was inspired by Otto's blog series of getting Debian Linux on the RIoTboard: Linux on the RIoTBoard Part 1: U-Boot. However I need Ubuntu instead.
Following are the steps to get a current Linux kernel (4.1) with Ubuntu 14.04 (should work with a more current version one too).
Requirements
I used Ubuntu 14.04 x86_64 to implement these instructions (actually it was a Virtual machine on VirtualBox).
Install Build dependencies:
sudo apt-get install git build-essential fakeroot kernel-package u-boot-tools lzop zlib1g-dev libncurses5-dev gcc-4.7-arm-linux-gnueabihf sudo ln -s arm-linux-gnueabihf-gcc-4.7 /usr/bin/arm-linux-gnueabihf-gcc
Please note the specific install of gcc 4.7. This is because the current version (as of 09/2015) in 14.04 of gcc 4.8 has a bug when building the Linux Kernel. Feel free to try 4.9 or a fixed 4.8.
The following is needed to chroot to arm based rootfs.
sudo apt-get install qemu-user-static
This is needed to help in the steps to create an sdcard image.
sudo apt-get install qemu-utils kpartx
Environment Variables
Here are environment variables used in the scripts that follow.
export ARCH=arm export CROSS_COMPILE=/usr/bin/arm-linux-gnueabihf- export RIOT_PATH=~/riotboard export RIOT_OUTPUT=$RIOT_PATH/output mkdir -p $RIOT_OUTPUT
U-Boot
Here are the steps to build version 2015.07 of U-boot:
cd $RIOT_PATH wget ftp://ftp.denx.de/pub/u-boot/u-boot-2015.07.tar.bz2 tar xjf u-boot-2015.07.tar.bz2 cd u-boot-2015.07 make riotboard_defconfig make cp u-boot.imx $RIOT_OUTPUT/. cd $RIOT_PATH
If you prefer to use the latest U-Boot or a different version see: SourceCode < U-Boot < DENX
Bootscript
The boot.scr is used by U-Boot to give it the boot arguments to pass to the kernel as well as were to find the kernel and DTB.
Please note this script is very basic and needs to know where you will be booting from. Change the DEVICE= line if you will be booting from eMMC or MicroSD instead. My eMMC is busted so I have to boot from uSD or SD.
mkdir -p $RIOT_PATH/bootscript cd $RIOT_PATH/bootscript # Device 0=SD, 1=MicroSD, 2=eMMC DEVICE=0 cat <<EOF > bootscript setenv bootargs console=ttymxc1,115200 nosmp video=mxcfb0:dev=hdmi,1280x720M@60,bpp=32 video=mxcfb1:off fbmem=10M vmalloc=400M rootwait root=/dev/mmcblk0p1 mmc dev $DEVICE ext4load mmc $DEVICE:1 10800000 /boot/zImage ext4load mmc $DEVICE:1 16800000 /boot/imx6dl-riotboard.dtb bootz 10800000 - 16800000 EOF mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "boot script" -d bootscript boot.scr cp boot.scr $RIOT_OUTPUT/. cd $RIOT_PATH
Kernel
I decided to use a specific released version (i.e. v4.1) of the kernel rather than the tip. Feel free to change the tag to switch to a different version or remove the -b option if you want to build the tip. I have not fully tested 4.1 but so far seems to work ok on the RIoTboard.
For detail on each step below see Otto's blog.
cd $RIOT_PATH git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git -b v4.1 cd linux make imx_v6_v7_defconfig # Do this next step if you need to change kernel config. make menuconfig # this next step will take a long time. You can try -j option to parallelize. make bzImage mkdir -p $RIOT_OUTPUT/boot sudo cp arch/arm/boot/zImage $RIOT_OUTPUT/boot/zImage make dtbs sudo cp arch/arm/boot/dts/imx6dl-riotboard.dtb $RIOT_OUTPUT/boot/imx6dl-riotboard.dtb make modules make modules_install INSTALL_MOD_PATH=$RIOT_OUTPUT make headers_install INSTALL_HDR_PATH=$RIOT_OUTPUT/usr cd $RIOT_OUTPUT tar -czf linux-kernel.tgz boot lib usr rm -rf boot lib usr
Root Filesystem
For the rootfs I decided to start from the official ubuntu release and customize it as opposed to building it completely like Otto showed in his blog for Debian. You can browse here: Index of /ubuntu-core/releases if you would like to pick a different ubuntu release. If you do, make sure to use an armhf one and update the customizations below in case they are different for your distro.
Unlike other steps above I am going to break this one down:
Get a starting rootfs
cd $RIOT_PATH mkdir -p $RIOT_OUTPUT/rootfs wget http://cdimage.ubuntu.com/ubuntu-core/releases/trusty/release/ubuntu-core-14.04-core-armhf.tar.gz sudo tar --numeric-owner -xzpf ubuntu-core-14.04-core-armhf.tar.gz -C $RIOT_OUTPUT/rootfs
Customize the rootfs
We will chroot to the arm rootfs to make some of the customizations.
# to enable arm emulation sudo cp /usr/bin/qemu-arm-static $RIOT_OUTPUT/rootfs/usr/bin/ # to enable dns lookups to work sudo cp /etc/resolv.conf $RIOT_OUTPUT/rootfs/etc sudo chroot $RIOT_OUTPUT/rootfs
Do your customizations. Feel free to adjust the stuff below to your needs. Please note not all of what I am doing below needs to be done from chroot (e.g the file editing and creations).
# setup a locale locale-gen en_US en_US.UTF-8 # Install any packages you want that are not in the core rootfs from Ubuntu.com apt-get -y install openssh-server ntpdate # Create users. The following adds usr/pw: ubuntu/ubuntu PASSWD=`openssl passwd -crypt ubuntu` /usr/sbin/useradd ubuntu -m -s /bin/bash -p $PASSWD # The stuff below can be done outside of chroot. Just make sure to adjust destination files if you do. # Enable the user to sudo without the need for pw. echo -e 'ubuntu\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers # Configure your network cat <<EOF >> /etc/network/interfaces auto eth0 iface eth0 inet dhcp EOF # Set the hostname echo riotboard > /etc/hostname # Enable login from the serial console cat <<EOF > /etc/init/serial-console.conf # serial-console - getty # # This service maintains a getty on console from the point the system is # started until it is shut down again. start on stopped rc RUNLEVEL=[2345] stop on runlevel [!2345] respawn exec /sbin/getty -L 115200 ttymxc1 vt100 EOF #setup fstab to mount the rootfs echo '/dev/mmcblk0p1 / auto errors=remount-ro 0 1' >> /etc/fstab
Clean up apt, exit chroot and remove the chroot setup files
# Clean up apt apt-get clean exit # Clean up files we added to enable chroot and dns sudo rm $RIOT_OUTPUT/rootfs/usr/bin/qemu-arm-static sudo rm $RIOT_OUTPUT/rootfs/etc/resolv.conf
Bundle up the rootfs:
cd $RIOT_OUTPUT/rootfs sudo tar -czpf ubuntu-trusty.tgz * sudo mv ubuntu-trusty.tgz $RIOT_OUTPUT/.
Create SD Card Image
Now we create the SD Card image that we will write to an SD card. You could even write this to the eMMC device (don't forget to change the boot script to load from device 2 if you do this). If you prefer you can use /dev/sdX instead of sdcard.img below if you want to write direct to the SD card instead of an image first.
cd $RIOT_OUTPUT # Create a file to hold the disk image qemu-img create sdcard.img 3600M # Partition the disk image leaving some room (10mb) for u-boot in front of the first partition. sfdisk --force -uM sdcard.img << EOF 10,,83 EOF # create devices from the disk image sudo kpartx -av sdcard.img # format the partition. Make sure to use the correct device from the previous command. mkfs.ext4 -j /dev/mapper/loop0p1 # create a mount point sudo mkdir -p /mnt/sdcard # Mount the partition we formatted. sudo mount -t ext4 /dev/mapper/loop0p1 /mnt/sdcard # Unpack the root fs and kernel sudo tar --numeric-owner -C /mnt/sdcard -zxpf ubuntu-trusty.tgz sudo tar --numeric-owner -C /mnt/sdcard -zxpf linux-kernel.tgz # Copy the boot script to the top level sudo cp boot.scr /mnt/sdcard/boot.scr # Unmount and clean up devices sudo umount /mnt/sdcard sudo kpartx -dv sdcard.img # put u-boot 2 blocks into the disk image. Don't leave out the notrunc option. dd if=u-boot.imx of=sdcard.img bs=512 seek=2 conv=notrunc
Now you can use dd or whatever tool you want to write the disk image to an SD card. Eg: sudo dd if=sdcard.img of=/dev/sdd bs=1m
Boot your SD Card
Plug the SD Card into the SD card slot. Set the switches 2,4,5,7 to OFF and the rest to ON to boot from SD.
If you are using a MicroSD, make sure to change the boot script to use device 1 instead of 0 and set the dip switches to 2,4,5,8 OFF and the rest ON.
Notes
See Otto's blog post mentioned above for how to use the MfgTool to write the above files to the eMMC flash from Windows as well as more detailed explanations to some of the stuff above..