Building FreeBSD for Kirkwood

Prepare a drive

I’m using a slow, generic 8GB flash drive, but anything with at least a GiB or so of space should do.

Delete any existing partitions.

[root@Emi#/root]gpart delete -i 1 da0
da0s1 deleted
[root@Emi#/root]gpart destroy da0
da0 destroyed

Then create a 32MiB FAT partition and fill the rest of the drive with a FreeBSD slice.

[root@Emi#/root]gpart create -s MBR da0
da0 created
[root@Emi#/root]gpart add -s 32M -t freebsd da0
da0s1 added
[root@Emi#/root]gpart add -t freebsd da0
da0s2 added

Format the FAT partition.

[root@Emi#/root]newfs_msdos /dev/da0s1
/dev/da0s1: 65416 sectors in 8177 FAT16 clusters (4096 bytes/cluster)
BytesPerSec=512 SecPerClust=8 ResSectors=1 FATs=2 RootDirEnts=512 Sectors=65520 Media=0xf0 FATsecs=32 SecPerTrack=63 Heads=255 HiddenSecs=0

And the UFS slice.

[root@Emi#/root]bsdlabel -w /dev/da0s2
[root@Emi#/root]newfs -n da0s2a
/dev/da0s2a: 7680.0MB (15728564 sectors) block size 16384, fragment size 2048
	using 42 cylinder groups of 183.72MB, 11758 blks, 23552 inodes.
super-block backups (for fsck -b #) at:
 160, 376416, 752672, 1128928, 1505184, 1881440, 2257696, 2633952, 3010208,
 3386464, 3762720, 4138976, 4515232, 4891488, 5267744, 5644000, 6020256,
 6396512, 6772768, 7149024, 7525280, 7901536, 8277792, 8654048, 9030304,
 9406560, 9782816, 10159072, 10535328, 10911584, 11287840, 11664096, 12040352,
 12416608, 12792864, 13169120, 13545376, 13921632, 14297888, 14674144,
 15050400, 15426656

The DockStar’s crippled bootloader can’t read FAT or use USB drives, but creating a FAT partition gives us an alternate storage location for the kernel and the ability to use fatload on boards with a fully-capable U-boot.

Obtain the source

Use csup to grab the source for FreeBSD if you don’t already have it. I used FreeBSD 8.1 (RELENG_8_1), but there may be something newer.

*default host=cvsup8.freebsd.org
*default base=/var/db
*default prefix=/usr
*default release=cvs tag=RELENG_8_1
*default delete use-rel-suffix
*default compress
src-all

Patching

This patch is only required until usb/138798 is fixed. Until then, we need to insert a delay before mounting the root filesystem, since our USB drive might not be enumerated.

--- /usr/src/sys/kern/vfs_mount.c.orig	2010-07-04 22:50:00.613726077 -0400
+++ /usr/src/sys/kern/vfs_mount.c	2010-07-05 12:11:09.986561693 -0400
@@ -1651,6 +1651,9 @@
 	int error, i, asked = 0;

 	options = NULL;
+
+	/* NASTY HACK: wait for USB sticks to appear */
+	pause("usbhack", hz * 10);

 	root_mount_prepare();

This patch, shamelessly stolen from the mailing list, will give us the option to force fsck on the root filesystem. Otherwise, an unclean shutdown would lock us out of FreeBSD unless we had serial console access.

--- /usr/src/etc/rc.d/fsck.orig	2010-07-07 13:02:41.765255856 -0400
+++ /usr/src/etc/rc.d/fsck	2010-07-07 13:02:46.286575144 -0400
@@ -27,7 +27,16 @@
 		if checkyesno background_fsck; then
 			fsck -F -p
 		else
-			fsck -p
+			if checkyesno force_fsck; then
+				echo "Force fsck enabled"
+				for filesystem in ${force_fsck_list}
+				do
+					echo "Force check $filesystem"
+					fsck -y $filesystem
+				done
+			else
+				fsck -p
+			fi
 		fi

 		case $? in

Patch master.passwd to give root a default password of “root”. There’s probably a better way to do this.

--- /usr/src/etc/master.passwd	2010-06-13 22:09:06.000000000 -0400
+++ /home/nicole/master.passwd	2010-07-08 02:27:52.148993197 -0400
@@ -1,6 +1,6 @@
 # $FreeBSD: src/etc/master.passwd,v 1.40.22.1.4.1 2010/06/14 02:09:06 kensmith Exp $
 #
-root::0:0::0:0:Charlie &:/root:/bin/csh
+root:$1$jr4u13xy$GivPnOZ5kslfsJL4LmLK41:0:0::0:0:Charlie &:/root:/bin/csh
 toor:*:0:0::0:0:Bourne-again Superuser:/root:
 daemon:*:1:1::0:0:Owner of many system processes:/root:/usr/sbin/nologin
 operator:*:2:5::0:0:System &:/:/usr/sbin/nologin

Patch atomic.h to make BIND in the base system not segfault. (Stolen from this mailing list thread.)

--- /usr/src/contrib/bind9/lib/isc/arm/include/isc/atomic.h.orig	2010-08-04 02:02:01.194401084 -0400
+++ /usr/src/contrib/bind9/lib/isc/arm/include/isc/atomic.h	2010-08-04 02:04:53.462379414 -0400
@@ -49,26 +49,22 @@
 static inline isc_int32_t
 isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val)
 {
-	register int done, ras_start;
+	register int done, ras_start  = 0xffff1004;

 	__asm __volatile("1:\n"
 	    "adr	%1, 1b\n"
-	    "mov	%0, #0xe0000004\n"
 	    "str	%1, [%0]\n"
-	    "mov	%0, #0xe0000008\n"
 	    "adr	%1, 2f\n"
-	    "str	%1, [%0]\n"
+	    "str	%1, [%0, #4]\n"
 	    "ldr	%1, [%2]\n"
 	    "cmp	%1, %3\n"
 	    "streq	%4, [%2]\n"
 	    "2:\n"
 	    "mov	%3, #0\n"
-	    "mov	%0, #0xe0000004\n"
 	    "str	%3, [%0]\n"
 	    "mov	%3, #0xffffffff\n"
-	    "mov	%0, #0xe0000008\n"
-	    "str	%3, [%0]\n"
-	    : "=r" (ras_start), "=r" (done)
+	    "str	%3, [%0, #4]\n"
+	    : "+r" (ras_start), "=r" (done)
 	    ,"+r" (p), "+r" (cmpval), "+r" (val) : : "memory");
 	return (done);

Build world

Build world for ARM, but don’t install anything.

[root@Emi#/usr/src]make -j 8 buildworld TARGET_ARCH=arm

Build the Kernel

My kernel configuration file is much more fully-featured than the stock SHEEVAPLUG config file. It includes support for GEOM, filesystems, USB ethernet controllers, USB audio hardware, and pf/ALTQ.

#
# Custom kernel for DockStar devices.
# http://cooltrainer.org 20100705
#
# $FreeBSD: src/sys/arm/conf/DOCKSTAR,v 1.1.2.3.2.1 2010/06/14 02:09:06 kensmith Exp $
#

ident		DOCKSTAR
include		"../mv/kirkwood/std.sheevaplug"

options 	SOC_MV_KIRKWOOD
makeoptions	MODULES_OVERRIDE=""

#DockStar has 128MiB of memory, not 512 like the reference design
#(512 is defined in std.sheevaplug and should be commented out)
options		PHYSMEM_SIZE=0x8000000

#makeoptions	DEBUG=-g		#Build kernel with gdb(1) debug symbols
makeoptions	WERROR="-Werror"

options 	SCHED_4BSD		#4BSD scheduler
options 	INET			#InterNETworking
options 	INET6			#IPv6 communications protocols
options 	FFS			#Berkeley Fast Filesystem
options 	NFSCLIENT		#Network Filesystem Client
options 	NFSLOCKD		#Network Lock Manager
options 	NFS_ROOT		#NFS usable as /, requires NFSCLIENT
#options 	BOOTP
#options 	BOOTP_NFSROOT
#options 	BOOTP_NFSV3
#options 	BOOTP_WIRED_TO=mge0

options 	GEOM_PART_BSD
options 	GEOM_PART_GPT
options 	GEOM_PART_MBR
options 	GEOM_LABEL	# Provides labelization

options 	SOFTUPDATES		# Enable FFS soft updates support
options 	MSDOSFS			# MSDOS Filesystem
options 	PROCFS		# Process filesystem (/proc)
options 	PSEUDOFS		# Pseudo-filesystem framework

# Root fs on USB device
options 	ROOTDEVNAME=\"ufs:/dev/da0s2a\"

options 	SYSVSHM			#SYSV-style shared memory
options 	SYSVMSG			#SYSV-style message queues
options 	SYSVSEM			#SYSV-style semaphores
options 	_KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
options 	MUTEX_NOINLINE
options 	RWLOCK_NOINLINE
options 	NO_FFS_SNAPSHOT
options 	NO_SWAPPING

# Debugging
#options 	ALT_BREAK_TO_DEBUGGER
#options 	DDB
#options 	KDB

# Pseudo devices
device		random
device		pty
device		loop

# Serial ports
device		uart

# Networking
device		ether
device		mge			# Marvell Gigabit Ethernet controller
device		mii
device		e1000phy
device		bpf
options		HZ=1000
options		DEVICE_POLLING
device		vlan

# USB
#options 	USB_DEBUG	# enable debug msgs
device		usb
device		ehci
device		umass
device		scbus
device		pass
device		da

#USB Ethernet
device		miibus
device		aue			# ADMtek USB Ethernet
device		axe			# ASIX Electronics USB Ethernet
device		cdce		# Generic USB over Ethernet
device		cue			# CATC USB Ethernet
device		kue			# Kawasaki LSI USB Ethernet
device		rue			# RealTek RTL8150 USB Ethernet
device		udav		# Davicom DM9601E USB

#OpenBSD Packet Filter
device		pf
device		pflog
device		pfsync

#ALTQ (QoS)
options		ALTQ
options		ALTQ_CBQ	# Class Bases Queuing (CBQ)
options		ALTQ_RED	# Random Early Detection (RED)
options		ALTQ_RIO	# RED In/Out
options		ALTQ_HFSC	# Hierarchical Packet Scheduler (HFSC)
options		ALTQ_PRIQ	# Priority Queuing (PRIQ)
#options	ALTQ_NOPCC	# Required for SMP build

#Swap space (Yes, just in case)
device		md			# Memory "disks"

#USB audio
device		sound
device		snd_uaudio

Comment out PHYSMEM_SIZE in /usr/src/sys/arm/mv/kirkwood/std.sheevaplug, or your kernel might only boot as far as the copyright declaration on the DockStar.

Then build the kernel.

[root@Emi#/usr/src]make buildkernel TARGET_ARCH=arm KERNCONF=DOCKSTAR


Padding the kernel


Copy the built kernel from /usr/obj/arm/usr/src/sys/DOCKSTAR/kernel.bin to your working directory, then run this shell script. It will pad the file out to a multiple of 4096 bytes to match the pages of NAND flash and will report the size of your padded kernel in hex for use later on.

nandwrite does have a pad option ( -p ), but it just gave me trouble.

#!/bin/sh
# Cooltrainer.org kernel padder - 20100704

if [ ! -r kernel.bin ];
then
	echo "kernel.bin not found."
	exit
fi

if ! type perl >/dev/null 2>&1; then
    echo "Perl was not found."
    exit
fi

cp kernel.bin kernel.bin.page

bytes=$(ls -lrt kernel.bin | awk '{print $5}')
fillbytes=$((4096 - ($bytes % 4096)))
echo "Padding kernel.bin to 4096 byte pages as kernel.bin.page"

while [ $fillbytes -gt 0 ]; do
	#printf "\xff" >> only seemed to work in ZSH
	echo "\xff" | perl -ne 's/([0-9a-f]{2})/print chr hex $1/gie' >> kernel.bin.page
	fillbytes=$(($fillbytes - 1))
done

hexcvt ()
{
	if [ -z "$1" ]
	then
		echo 0
		return
	fi

	echo ""$1" "16" o p" | dc
	return
}

paddedbytes=$(ls -lrt kernel.bin.page | awk '{print $5}')

echo -n "Padded kernel size: 0x" && hexcvt $paddedbytes
[root@Emi#/root]sh pad.sh
Padding kernel.bin to 4096 byte pages as kernel.bin.page
Padded kernel size: 30E000

Write down the size of your padded kernel. You’ll need it when configuring the bootloader.

Install world

[root@Emi#/root]mount /dev/da0s2a /root/usb
[root@Emi#/usr/src]export DESTDIR=/root/usb
[root@Emi#/usr/src]make installworld distrib-dirs distribution TARGET_ARCH=arm

Configure some niceties

Set the hostname, turn on DHCP, and enable SSHd.

[root@Emi#/root]echo 'hostname="pochan"' > $DESTDIR/etc/rc.conf
[root@Emi#/root]echo 'ifconfig_mge0="DHCP"' >> $DESTDIR/etc/rc.conf
[root@Emi#/root]echo 'sshd_enable="YES"' >> $DESTDIR/etc/rc.conf

Enable automatic fsck, so we can get back into the OS in the event of power loss or an unclean shutdown.

[root@Emi#/root]echo 'fsck_y_enable="YES"' >> $DESTDIR/etc/rc.conf
[root@Emi#/root]echo 'background_fsck="NO"' >> $DESTDIR/etc/rc.conf
[root@Emi#/root]echo 'force_fsck="YES"' >> $DESTDIR/etc/rc.conf
[root@Emi#/root]echo 'force_fsck_list="/"' >> $DESTDIR/etc/rc.conf

Turn on NTPd. The DockStar has no real time clock, so this is required to set the time and date on boot. The -g flag makes NTPd ignore the first huge jump in time.

[root@Emi#/root]echo 'ntpd_enable="YES"' >> $DESTDIR/etc/rc.conf
[root@Emi#/root]echo 'ntpd_flags="-g"' >> $DESTDIR/etc/rc.conf

Set a better motd ( :3 ) and tell Ports not to build X11.

[root@Emi#/root]echo 'Heya cutie <3' > $DESTDIR/etc/motd
[root@Emi#/root]echo 'WITHOUT_X11=yes' >> $DESTDIR/etc/make.conf

Set some mount options for our root filesystem. Disabling clustered reads and writes is Reccommended on ARM

[root@Emi#/root]echo '# Device	Mountpoint	FStype	Options					Dump	Pass#' > $DESTDIR/etc/fstab
[root@Emi#/root]echo '/dev/da0s2a	/			ufs		rw,noclusterr,noclusterw	0		0' >> $DESTDIR/etc/fstab

Add your device’s hostname to /etc/hosts. This example uses “pochan”.

pochan# ee $DESTDIR/etc/hosts
::1                     localhost localhost.my.domain pochan
127.0.0.1               localhost localhost.my.domain pochan

Finally, edit $DESTDIR/etc/ssh/sshd_config and change PermitRootLogin to yes, since there will be no user accounts on first boot.

Installation on the Device ยป