Cool new FreeBSD 11/12 kernel developer trick

One of the cool new features in FreeBSD 11 is that we can use the system compiler as a cross compiler, eliminating the need to rebuild clang. While this allows buildworld to go much faster, there's another benefit that might not be immediately obvious.

For kernel development, this almost means we can forget about the usually required 'make kernel-toolchain' even when we're cross building. The system linker can't (yet) handle it, so the kernel fails to link if you've not done it. The good news is that you don't need to build gcc or clang for the kernel toolchain target, so you can build it quickly (in under a minute on my fast build machine, under 5 on my laptop VM). The trick is one command:
make kernel-toolchain TARGET=arm WITHOUT_{GCC,CLANG}{,_BOOTSTRAP}=t
If you are developing for amv6/v7, change TARGET=arm to TARGET_ARCH=armv6. I've not tried others, but suspect they will work as well as clang supports the target in question. This allows me to start building test kernels w/o the usual delay of building a kernel toolchain, especially on my laptop VM where  I'm chronically short on disk and always deleting the old obj tree.

This works on both 11.0 and 12.0-current. It likely will fail on 10.x since the system compiler as the cross compiler work hasn't been MFC'd there yet.


Quick hack: creating a pcDuino3 bootable image from FreeBSD 11.0's BANANA PI image.

Here's a tip about FreeBSD pre-configured armv6 images. For a given SoC, they are all (almost) the same. There's two difference for the Allwinner case (at least for the MP boards): u-boot and the hostname. Recently, I created a u-boot port for pcDuino3 as a slave port. Since I didn't care about the hostname, I thought I'd swap out the u-boot on the BANANA PI image. I snagged it from FreeBSD's download page and installed the u-boot-pcduino3 port. Allwinnner stores u-boot and a small initialization program in the first part of the SD after the MBR partition table. Other SoCs have different boot processes. Currently, you have to check the readme for each one. In the future, there will be a way to insert u-boot into any image.

So, to put the image on the SD card that showed up on my system as /dev/da2:
xz -d < FreeBSD-11.0-RC3-arm-armv6-BANANAPI.img.xz | dd of=/dev/da2 bs=1m
dd if=/usr/local/share/u-boot/u-boot-pcduino/u-boot-sunxi-with-spl.bin of=/dev/da2 bs=1k seek=8 conv=notrunc,sync
This puts the u-boot image (a SPL header which sets up the system to run u-boot coupled with u-boot) onto the disk. You can also uncompress the image you download and insert it there before pushing it out to the SD card. Since I also have a Banana PI I wanted to create an SD card for, I just changed it after it was on the image.

Unfortunately, every board needs a slightly different u-boot image. I have a number of changes I'm testing to help unify the u-boot ports. One of them adds metadata to each u-boot port that a generic imaging tool can use to make things better in the future.

Chain booting u-boot with u-boot

Recently, I needed to test u-boot before I flashed a new u-boot image into NAND. In the past, when I've googled it, I find a lot of screeds about how u-boot can't chain boot u-boot in the general case. Recently, I found a page for blackfin Linux that talks about doing just this. So, I got to thinking about trying again. I have a AT91SAM9G20. Atmel's boot process is split in two. at91bootstrap sets up the board enough to run u-boot. u-boot on Atmel boards can actually chain-boot.

So, how do I find out how to do it? I built u-boot for my board. 'objdump -f u-boot' after I built it showed:
u-boot:     file format elf32-littlearm
architecture: armv5te, flags 0x00000112:
start address 0x21f00000
Generally, u-boot is loaded at the same address it executes at. So, I confirmed with objdump -x, the full output is too long to quote here, but this is relevant:
 Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0002f5e4  21f00000  21f00000  00010000  2**5
which confirms the address. So, I booted up the old u-boot I wanted to replace and loaded u-boot.bin at 0x21f00000 and jumped to it:
Start AT91Bootstrap...

U-Boot 1.3.4 (Jul 24 2009 - 17:50:12)

NAND: 256 MiB
In: serial
Out: serial
Err: serial
Net: macb0
macb0: Starting autonegotiation...
macb0: Autonegotiation complete
macb0: link up, 100Mbps full-duplex (lpa: 0x45e1)
Hit any key to stop autoboot: 0
U-Boot> tftp 0x21f00000 u-boot.bin
macb0: link up, 100Mbps full-duplex (lpa: 0x45e1)
Using macb0 device
TFTP from server; our IP address is
Filename 'u-boot.bin'.
Load address: 0x21f00000
Loading: ####################
Bytes transferred = 288984 (468d8 hex)
U-Boot> go 0x21f00000
## Starting application at 0x21F00000 ...

U-Boot 2016.05-00018-g2f0dd66 (Sep 18 2016 - 21:38:36 -0600)

Crystal frequency: 18.432 MHz
CPU clock : 396.288 MHz
Master clock : 132.096 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
NAND: 256 MiB
*** Warning - bad CRC, using default environment

In: serial
Out: serial
Err: serial
Net: macb0
Error: macb0 address not set.

Hit any key to stop autoboot: 0
And we're in...