Just some quick and dirty instructions on how I built a Beaglebone Black disk image from scratch. A big thanks to Robert C. Nelson for the Open Source tools and instructions at Linux Arm on Beaglebone Black that this relies on.

I am sharing the steps I performed here because I built a read-only root filesystem. It is not perfect as it throws a couple of errors during the boot sequence. But those errors are by no means fatal and can be ignored.

Setting up pre-requisites

Same packages are needed in order to build.

apt-get install git
git config --global user.email un@b.com
git config --global user.name "User Name"

Packages needed for the device tree compiler

apt-get install bison build-essential flex git-core

Packages needed for the kernel build

apt-get install device-tree-compiler lzma lzop u-boot-tools libncurses5-dev

For disk formatting.

apt-get install dosfstools

Setting up cross compile environment

Our build machine is Debian Wheezy x86_64. Linaro gcc is 32-bit and needs additional 32-bit binaries.

dpkg --add-architecture i386
apt-get update
apt-get install libc6:i386 libstdc++6:i386 libncurses5:i386 zlib1g:i386

Install Linaro gcc compiler for ARM.

wget -c https://launchpad.net/linaro-toolchain-binaries/trunk/2013.10/+download/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux.tar.xz
tar xJf gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux.tar.xz
export CC=`pwd`/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-
${CC}gcc --version

The last command should provide this kind of output. Otherwise there is a library install issue.

arm-linux-gnueabihf-gcc ...

Building U-Boot

Obtain u-boot sources.

git clone git://git.denx.de/u-boot.git
cd u-boot/

Patch U-Boot

wget -c https://raw.github.com/eewiki/u-boot-patches/master/v2013.10/0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch
patch -p1 < 0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch

Or get patched sources.

git clone https://github.com/adilinden/u-boot.git
cd u-boot/
git checkout v2013.10 -b tmp

Build U-Boot

make ARCH=arm CROSS_COMPILE=${CC} distclean
make ARCH=arm CROSS_COMPILE=${CC} am335x_evm_config
make ARCH=arm CROSS_COMPILE=${CC}
cd ..

Build the device tree compiler

Upgrade device tree compiler package. If this script throws an error about ‘sudo: not found’, then just manual install those packages. Still need to run the script!

wget -c https://raw.github.com/RobertCNelson/tools/master/pkgs/dtc.sh
chmod +x dtc.sh
./dtc.sh

Build the kernel

Get Kernel. (This isn’t really necessary as the next step would clone the kernel repo. But I wanted a local kernel repo for other tasks, too.)

git cone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git

Get the kernel build scripts.

git clone git://github.com/RobertCNelson/linux-dev.git
cd linux-dev/
cp system.sh.sample system.sh

Edit the script to clone out local kernel repo. Edit the following lines to read like this:

CC=~/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-
LINUX_GIT=~/linux-stable/

Build the kernel (3.8).

git checkout origin/am33x-v3.8 -b tmp-3.8
./build_kernel.sh
cd ..

Prepare the SD card

We are using a HD partition to experiment. Be careful here and be sure what disk device you are using. Very easy to nuke the local filesystem and require a rebuild of the build machine.

export DISK=/dev/sdc

Erase the disk.

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

Create partition layout.

fdisk $DISK
Command: n
Select: p
Partition: 1
First:
Last: +48M
Command: t
Hex Code: e
Command: a
Partition: 1
Command: n
Select: p
Partition: 2
First:
Last: +1024M
Command: w

This is what we want.

Device Boot      Start         End      Blocks   Id  System
/dev/sdd1   *        2048      100351       49152    e  W95 FAT16 (LBA)
/dev/sdd2          100352     7626751     3763200   83  Linux

Format partitions.

mkfs.vfat -F 16 ${DISK}1 -n boot
mkfs.ext4 ${DISK}2 -L rootfs -O ^has_journal

Make partition mount points.

mkdir -p /tmp/boot/
mkdir -p /tmp/rootfs/

Mount volumes.

mount ${DISK}1 /tmp/boot/
mount ${DISK}2 /tmp/rootfs/

Install bootloader.

cp -v ./u-boot/MLO /tmp/boot/
cp -v ./u-boot/u-boot.img /tmp/boot/

Create /tmp/boot/uEnv.txt

#u-boot eMMC specific overrides; Angstrom Distribution (BeagleBone Black) 2013-06-20
kernel_file=zImage
initrd_file=uInitrd

loadzimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${kernel_file}
loadinitrd=load mmc ${mmcdev}:${mmcpart} 0x81000000 ${initrd_file}; setenv initrd_size ${filesize}
loadfdt=load mmc ${mmcdev}:${mmcpart} ${fdtaddr} /dtbs/${fdtfile}
#

console=ttyO0,115200n8
mmcroot=/dev/mmcblk0p2 ro
mmcrootfstype=ext4 rootwait fixrtc

##To disable HDMI/eMMC...
#optargs=capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN,BB-BONE-EMMC-2G

##3.1MP Camera Cape
#optargs=capemgr.disable_partno=BB-BONE-EMMC-2G

mmcargs=setenv bootargs console=${console} root=${mmcroot} rootfstype=${mmcrootfstype} ${optargs}

#zImage:
uenvcmd=run loadzimage; run loadfdt; run mmcargs; bootz ${loadaddr} - ${fdtaddr}

#zImage + uInitrd: where uInitrd has to be generated on the running system.
#boot_fdt=run loadzimage; run loadinitrd; run loadfdt
#uenvcmd=run boot_fdt; run mmcargs; bootz ${loadaddr} 0x81000000:${initrd_size} ${fdtaddr}

Install root filesystem.

wget -c https://rcn-ee.net/deb/minfs/wheezy/debian-7.3-minimal-armhf-2013-12-18.tar.xz
tar xJvpf ./debian-7.3-minimal-armhf-2013-12-18.tar.xz
tar xpf debian-7.3-minimal-armhf-2013-12-18/armhf-rootfs-debian-wheezy.tar -C /tmp/rootfs

Copy the kernel.

cp -v ./linux-dev/deploy/*.zImage /tmp/boot/zImage
mkdir -p /tmp/boot/dtbs/
tar xfov ./linux-dev/deploy/*-dtbs.tar.gz -C /tmp/boot/dtbs/
tar xfov ./linux-dev/deploy/*-firmware.tar.gz -C /tmp/rootfs/lib/firmware/
tar xfov ./linux-dev/deploy/*-modules.tar.gz -C /tmp/rootfs/

Edit /tmp/rootfs/etc/fstab.

/dev/mmcblk0p2   /           ext4   ro,noatime                0   0
/dev/mmcblk0p1   /boot/uboot vfat   ro,user,umask=000         0   0
tmpfs            /tmp        tmpfs  nodev,nosuid,size=10m     0   0
tmpfs            /var/log    tmpfs  nodev,nosuid,size=10m     0   0
tmpfs            /var/tmp    tmpfs  nodev,nosuid,size=10m     0   0

Edit /tmp/rootfs/etc/networking/interfaces.

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

allow-hotplug usb0
iface usb0 inet dhcp

Edit /tmp/rootfs/etc/inittab.

T0:23:respawn:/sbin/getty -L ttyO0 115200 vt102

Create /tmp/rootfs/etc/init/serial.conf.

start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]
 
respawn
exec /sbin/getty 115200 ttyO0

Be done with SD card.

sync
umount /tmp/rootfs
umount /tmp/boot

After system is installed

Boot Beaglebone Black with the new SD card. Use the serial console cable to access the root prompt. The username/password are root/root.

To make permanent changes the root filesystem needs to be mounted read-write. This is easily done:

mount -o remount,rw /

Enjoy!