All I ever wanted
All I ever needed
Is here in my ARMs
Words are very unnecessary
They can only do harm
Recently I posted about Building a custom FreeBSD image for a RaspberryPi. In that post, I detailed how to download the official ARMV6 builds of FreeBSD and make the required changes before writing to an SD card that would boot in an RPi. In this post, I’m going to provide details on how to build a custom image using FreeBSD’s source code which allows the user the flexibility of modifying the kernel before hand instead of using the GENERIC kernel config.
For this, I’ll be using FreeBSD 10-STABLE in a VirtualBox VM on my MBP to build the image. Firstly, we’ll need to grab a copy of -head. We can store this in /usr/src/FreeBSD not to overwrite any custom changes to your existing source. We can do this using svn. If you do not have subversion installed, start at step 1, otherwise, skip to 2.
1. Install Subversion and download -head
# cd /usr/ports/deve/subversion && make install && make install clean
# svn co svn://svn.freebsd.org/base/head /usr/src/FreeBSD
# ln -s /usr/src /src
This may take a while depending on the speed of your connection. Once complete, you’ll be ready to rock.
2. Customise the Kernel
cd /src/sys/amd64/conf
sudo cp GENERIC RPI-B
At this point, you can open up RPI-B in your favourite editor and proceed to make any modifications you wish. Be sure to read the comments within the file and ensure you do not remove support for anything required. This is how you can easily be left with a kernel which doesn’t boot. When in doubt, refer to the FreeBSD Handbook!
3. Build and Install the Custom Kernel
Firstly, let’s create the directories we’ll be using:
# cd /usr/src/FreeBSD
# mkdir -p /mnt/rpi
# mkdir -p /src/FreeBSD/obj
Next, let’s set some of the environment variables we’ll require:
Originally, I had started writing up the steps required to build the source manually but then I came across the following ARMV6 build script which simplifies the entire build process. Grab the following script, add execution permissions and build away!
#!/bin/sh
set -e
# Change this
export GPU_MEM=128
export PI_USER=pi
export PI_USER_PASSWORD=raspberry
export SRCROOT=/src/FreeBSD/head
export MNTDIR=/mnt
export MAKEOBJDIRPREFIX=/src/FreeBSD/obj
export IMG=/src/FreeBSD/obj/bsd-pi.img
export TARGET_ARCH=armv6
export MAKESYSPATH=$SRCROOT/share/mk
export KERNCONF=RPI-B
if [ -z "$MNTDIR" ]; then
echo "MNTDIR is not set properly"
exit 1
fi
KERNEL=`realpath $MAKEOBJDIRPREFIX`/arm.armv6/`realpath $SRCROOT`/sys/$KERNCONF/kernel
UBLDR=`realpath $MAKEOBJDIRPREFIX`/arm.armv6/`realpath $SRCROOT`/sys/boot/arm/uboot/ubldr
DTB=`realpath $MAKEOBJDIRPREFIX`/arm.armv6/`realpath $SRCROOT`/sys/$KERNCONF/rpi.dtb
make -C $SRCROOT kernel-toolchain
make -C $SRCROOT KERNCONF=$KERNCONF WITH_FDT=yes buildkernel
make -C $SRCROOT MALLOC_PRODUCTION=yes buildworld
buildenv=`make -C $SRCROOT buildenvvars`
eval $buildenv make -C $SRCROOT/sys/boot clean
eval $buildenv make -C $SRCROOT/sys/boot obj
eval $buildenv make -C $SRCROOT/sys/boot UBLDR_LOADADDR=0x2000000 all
rm -f $IMG
dd if=/dev/zero of=$IMG bs=128M count=8
MDFILE=`mdconfig -a -f $IMG`
gpart create -s MBR ${MDFILE}
# Boot partition
gpart add -s 32m -t '!12' ${MDFILE}
gpart set -a active -i 1 ${MDFILE}
newfs_msdos -L boot -F 16 /dev/${MDFILE}s1
mount_msdosfs /dev/${MDFILE}s1 $MNTDIR
fetch -q -o - http://people.freebsd.org/~gonzo/arm/rpi/freebsd-uboot-20130201.tar.gz | tar -x -v -z -C $MNTDIR -f -
cat >> $MNTDIR/config.txt < $MNTDIR/boot/loader.rc
echo '/dev/mmcsd0s2a / ufs rw,noatime 1 1' > $MNTDIR/etc/fstab
cat > $MNTDIR/etc/rc.conf < $MNTDIR/etc/ttys <<__EOTTYS__
ttyv0 "/usr/libexec/getty Pc" xterm on secure
ttyv1 "/usr/libexec/getty Pc" xterm on secure
ttyv2 "/usr/libexec/getty Pc" xterm on secure
ttyv3 "/usr/libexec/getty Pc" xterm on secure
ttyv4 "/usr/libexec/getty Pc" xterm on secure
ttyv5 "/usr/libexec/getty Pc" xterm on secure
ttyv6 "/usr/libexec/getty Pc" xterm on secure
ttyu0 "/usr/libexec/getty 3wire.115200" dialup on secure
__EOTTYS__
echo $PI_USER_PASSWORD | pw -V $MNTDIR/etc useradd -h 0 -n $PI_USER -c "Raspberry Pi User" -s /bin/csh -m
pw -V $MNTDIR/etc groupmod wheel -m $PI_USER
PI_USER_UID=`pw -V $MNTDIR/etc usershow $PI_USER | cut -f 3 -d :`
PI_USER_GID=`pw -V $MNTDIR/etc usershow $PI_USER | cut -f 4 -d :`
mkdir -p $MNTDIR/home/$PI_USER
chown $PI_USER_UID:$PI_USER_GID $MNTDIR/home/$PI_USER
umount $MNTDIR
mdconfig -d -u $MDFILE
4. Write the image to your SD card
For this, I merely transferred the image to my Macbook and used DD to write it to my SD card. Alternitively, if you’d prefer to write the image directly from the VM, I posted instructions on how to do this last week.
When you firstly insert the disk into the SD card reader, OSX will automatically attempt to mount any partitions it recognises. In our case, it mounts the FAT32 partition. To ensure a write is successful, you’ll need to unmount this. You can either do this in Terminal.app or use DiskUtility to unmount the drive without ejecting it. To write the image to the SD card, perform the following:
osx# dd if=/Users/alan/rpi.img of=/dev/disk4 bs=1m
This will take a few minutes to successfully write. Once complete, eject the SD card and insert it into your RPi and boot. Ensue you have HDMI connected to see any error messages which may be displayed during the boot up process.