While having pre-configured devices is super-fun for getting started quickly, I usually want to know exactly what is installed on them. So I spent some time installing my BeagleBone from scratch.

U-Boot – the bootloader

First step is the boot-loader. The ROM bootloader loads the 2nd stage bootloader in to on-chip RAM and executes it. On-chip RAM is limited to just over 100kB, not enough for a full fledged bootloader. So U-boot is itself split in 2 stages, typically called MLO and u-boot.img.

To build these, I downloaded the git repository of U-Boot, applied Robert Nelson’s patches (you’ll recognise that name if you did some BeagleBone Googling before) and did:

patch -p1 < 0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch
make distclean
make am335x_boneblack_config

I have no idea what these patches do, but everyone seems to apply them…

You can probably cross-compile these on your x86-based workstation, but I just run the compile on the BeagleBone itself. I copied the resulting files to the SD-card: MLO and u-boot.img. Booting with S2 pressed greeted me with:

U-Boot SPL 2017Trying to boot from MMC1
reading u-boot.img
reading u-boot.img

U-Boot 2017.07-00043-g8822c8f (Jul 11 2017 - 19:34:01 +0000)

CPU  : AM335X-GP rev 2.1
I2C:   ready
DRAM:  512 MiB
No match for driver 'omap_hsmmc'
No match for driver 'omap_hsmmc'
Some drivers were not found
Reset Source: Power-on reset has occurred.
Using default environment

Board: BeagleBone Black
 not set. Validating first E-fuse MAC
Net:   eth0: MII MODE
Press SPACE to abort autoboot in 2 seconds

A minimal Debian image

I used debootstrap to generate a minimal Debian environment:

debootstrap --verbose --variant=minbase stretch /mnt http://deb.debian.org/debian/

I bootstrapped in to a loop-mounted file, but you can do that straight to an SD-card if you’re brave.

I had trouble getting this to work from the shipped Wheezy. debootstrap stopped with:

I: Extracting liblzma5...
I: Extracting zlib1g...
E: no . cannot create devices

The problem seems to be that Wheezy doesn’t use devfs. I tar’ed up /dev and export DEVICES_TARGZ=/mnt/dev.targz to get through this point, then removed the extracted files from the target.

Since minbase is really minimal, I added the following:

  • apt-get install --no-install-recommends openssh-server
  • apt-get install vim iproute2 iputils-ping kmod less ifupdown init udev
  • echo "deb http://repos.rcn-ee.com/debian/ stretch main" >> /mnt/etc/apt/sources.list; apt-get update
  • apt-get install linux-image-4.9.36-ti-r45
  • echo "/dev/mmcblk0p2 / ext4 defaults 0 1" > /mnt/etc/fstab
  • cp /etc/hosts /mnt/etc/hosts
  • configure /etc/network/interfaces or /etc/network/interfaces.d/

OK, well, to be honest, the above list was compiled from several trail-and-error attempts to get the image to boot… Who could have guessed you need a kernel to actually boot 😉 If you’re lazy, you can just extract my tarball, and try to log in on via USB with SSH as root (password admin).

Now you can either manually boot the kernel in U-Boot:

load mmc 0:2 ${loadaddr} /boot/vmlinuz-4.9.36-ti-r45
load mmc 0:2 ${fdtaddr} /boot/dtbs/4.9.36-ti-r45/am335x-boneblack.dtb
set bootargs console=tty0 console=ttyS0,115200n8 root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait fixrtc init=/lib/systemd/systemd
bootz ${loadaddr} - ${fdtaddr}

Or put the equivalent commands in uEnv.txt on the FAT partition: (I copied the kernel & Flattened Device Tree file to the FAT partition (mmc 0:1) for easier debugging).

bootargs=console=tty0 console=ttyS0,115200n8 root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait fixrtc init=/lib/systemd/systemd
uenvcmd=load mmc 0:1 ${loadaddr} kernel.img; load mmc 0:1 ${fdtaddr} fdt; bootz ${loadaddr} - ${fdtaddr}

Some notes:

  • The boot takes ~3 minutes longer than it should, because systemd waits for eth0 to come up (which it won’t because it’s not connected), only giving up after a few minutes.
  • If you have trouble getting the serial console to work because systemd can’t find dev-ttyS0.device, make sure you installed udev