This howto is based on various snippets I found on the web and spiced with my
own experiences. I found Oleksandr Tymoshenko's build-pi-image.sh
script very helpful. You can find his blog at http://kernelnomicon.org/.
- For the sake of ease log in as user root and start a Bourne
compatible shell, e.g. /bin/sh or /usr/local/bin/bash
- If your system doesn't have an auditdistd user (if id
auditdistd returns no such user), then create it:
pw useradd auditdistd -u 78 -g 77 -c "Auditdistd unprivileged user" -d /var/empty -s /usr/sbin/nologin
- Download the boot loader:
fetch http://people.freebsd.org/~gonzo/arm/rpi/freebsd-uboot-20121129.tar.gz
- Either install subversion as binary package
pkg_add -r subversion
or as port:
make -C /usr/ports/devel/subversion install clean
- Fetch the latest FreeBSD source code:
svn co svn://svn.freebsd.org/base/head
- Change to the newly created directory:
cd head
-
Determine how much of your Raspberry's memory is available to FreeBSD,
e.g. mine has 512 MB. Its integrated graphics card takes 64 MB by default.
Thus FreeBSD gets 448 MB or 469762048 bytes of ram. Written in hexadecimal
this is 0x1C000000. You can use this shell one-liner to calculate that number:
printf "%X\n" $(((512-64)*1024*1024))
Edit sys/boot/fdt/dts/bcm2835-rpi-b.dts
sys/boot/fdt/dts/rpi.dts. Lines 503-506
38-42 contain something like this:
memory {
device_type = "memory";
reg = <0 0x08000000>; /* 128 MB, Set by VideoCore */
};
Replace that by:
memory {
device_type = "memory";
reg = <0 0x1C000000>; /* 448 MB */
};
- If you like, you can add support for IPv6 in the kernel
although IPv6 doesn't seem to work on FreeBSD/arm (-HEAD, as of
January 2013) (Update 2013-02-01: IPv6 is functional on FreeBSD/arm, see
this
commit message). Edit sys/arm/conf/RPI-B and add the following
lines:
options INET6 # IPv6 communications protocols
options TCP_OFFLOAD # TCP offload
options PROCFS # Process filesystem (requires PSEUDOFS)
device vlan # 802.1Q VLAN support
# libalias library, performing NAT
options LIBALIAS
options IPFIREWALL #firewall
options IPFIREWALL_DEFAULT_TO_ACCEPT #allow everything by default
options IPFIREWALL_NAT #ipfw kernel nat support
options IPDIVERT #divert sockets
- As of 2013-01-26, this step doesn't seem to be needed anymore
Edit Makefile.incl. Around lines 920 and 928
(below stage 2.3: build tools), comment out both lines starting with
cd ${KRNLOBJDIR}/${_kernel} and cd
${KERNSRCDIR}/modules/aic7xxx/aicasm, respectively
- Set an environmental variable which contains the target's cpu
architecture:
export TARGET_ARCH=armv6
- Build the tools (compilers and so) which are required to build FreeBSD
(this takes about half an hour depending on your cpu's speed):
make kernel-toolchain
- Build the kernel (this takes also about half an hour):
make KERNCONF=RPI-B WITH_FDT=yes buildkernel
- Compile the userland (this takes really long, up to several hours):
make MALLOC_PRODUCTION=yes buildworld
- Get the build environment variables:
buildenv=`make buildenvvars | sed 's/MACHINE_ARCH=armv6/MACHINE_ARCH=arm/'`
- Change to sys/boot:
cd sys/boot
- Build the boot loader (U-Boot, the Universal Boot Loader):
eval $buildenv make MK_NAND=no UBLDR_LOADADDR=0x2000000 clean obj all
- Change back to /root/head:
cd -
- Create the disk image which will be transferred to the sd card. FreeBSD
needs 260 MB at a bare minimum. Everything below 300 MB is insane. 512 MB are
ok:
dd if=/dev/zero of=/root/arm.img bs=1m count=512
- Attach that disk image:
mdfile=`mdconfig -a -t vnode -f /root/arm.img`
- Create a MBR partitioning scheme:
gpart create -s MBR "$mdfile"
- Add a small MSDOS partition which will contain the boot loader:
gpart add -s 32m -t '!12' "$mdfile"
- Mark that partition active:
gpart set -a active -i 1 "$mdfile"
- Create the filesystem:
newfs_msdos -L boot -F 16 /dev/"$mdfile"s1
- Mount that filesystem:
mount -t msdosfs /dev/"$mdfile"s1 /mnt
- Extract the boot loader to the boot partition:
tar -C /mnt -xvzf /root/freebsd-uboot-20121129.tar.gz
- Copy the U-Boot loader to the boot partition:
cp -iv /usr/obj/arm.armv6/root/head/sys/boot/arm/uboot/ubldr /mnt/
- Copy the device database to the boot partition:
cp -iv /usr/obj/arm.armv6/root/head/sys/RPI-B/bcm2835-rpi-b.dtb /mnt/devtree.dat
cp -iv /usr/obj/arm.armv6/root/head/sys/RPI-B/rpi.dtb /mnt/devtree.dat
- Edit /mnt/config.txt and add the following lines:
device_tree=devtree.dat
device_tree_address=0x100
disable_commandline_tags=1
You can assign more memory to the graphics card, e.g. 128 MB instead of 64 MB:
gpu_mem=128
Note that you have to recompile the kernel if you increase the graphics card's
memory (see step 7)
- Unmount the boot partition:
umount /mnt
- Add a FreeBSD partition:
gpart add -t freebsd "$mdfile"
- Create a BSD partitioning scheme inside that partition:
gpart create -s BSD "$mdfile"s2
- Add a UFS partition which becomes the root partition:
gpart add -t freebsd-ufs "$mdfile"s2
- Create the UFS filesystem:
newfs -U -j /dev/"$mdfile"s2a
- Mount the root partition:
mount /dev/"$mdfile"s2a /mnt
- Install the kernel:
make KERNCONF=RPI-B DESTDIR=/mnt installkernel
- Install everything else:
make DESTDIR=/mnt DB_FROM_SRC=1 installworld distribution
- Add the following line to /mnt/boot/loader.rc:
fdt addr 0x100
- FreeBSD has to know where its root filesystem resides. Add this to
/mnt/etc/fstab:
/dev/mmcsd0s2a / ufs rw,noatime 1 1
- Add this to /etc/fstab to mount /proc:
procfs /proc procfs rw 0 0
- /mnt/etc/rc.conf should contain something similiar to this:
hostname="raspberry.your.domain"
dumpdev="NO"
ifconfig_ue0="192.168.0.42 netmask 255.255.255.0"
defaultrouter="192.168.0.1"
sshd_enable="YES"
ntpdate_enable="YES"
ntpd_enable="YES"
Instead of ifconfig_ue0 and defaultrouter you could try dhcp:
ifconfig_ue0="DHCP"
- If you don't use dhcp, then configure at least one nameserver in
/mnt/etc/resolv.conf:
nameserver 192.168.0.23
- If your nameserver doesn't resolve the Raspberry's hostname, then add this
to /mnt/etc/hosts:
192.168.0.42 raspberry.your.domain raspberry
- Edit /mnt/etc/ssh/sshd_config, go to line 44, and change
#PermitRootLogin no
to
PermitRootLogin yes
-
Either add your public ssh key to /mnt/root/.ssh/authorized_keys:
mkdir -m 0700 /mnt/root/.ssh
cat ~/.ssh/id_rsa.pub >>/mnt/root/.ssh/authorized_keys
chmod 0600 /mnt/root/.ssh/authorized_keys
Or permit ssh access without being prompted for a password (Insecure!
Don't do this in a hostile environment!): Edit
/mnt/etc/pam.d/sshd, go to line 12, comment out
auth required pam_unix.so no_warn try_first_pass
and add
auth required pam_permit.so
- Set a proper timezone:
cp -iv /mnt/usr/share/zoneinfo/Europe/Berlin /mnt/etc/localtime
- Unmount the root partition:
umount /mnt
- Detach the disk image:
mdconfig -d -u "$mdfile"
- Shove the sd card into the card reader and connect it to your FreeBSD
system
- Use the output of dmesg to check which device node represents your
sd card, e.g. da1. That device node should not appear in the output of
mount
- Write the image to the sd card:
dd if=/root/arm.img of=/dev/da1 bs=1m
- Eject the sd card and insert it into the Raspberry
- Optionally, connect a monitor or TV to your Raspberry to watch FreeBSD
booting
- Power on the Raspberry
- Remotely log into your Raspberry, e.g.:
ssh root@192.168.0.42
- Assign a password to the root account:
passwd
- If you've edited /etc/pam.d/sshd (see step
44), undo that now.