FreeBSD on Zynq-7000 / Zybo / Zedboard / Ultra96


This page describes running FreeBSD on the Zedboard and other Xilinx Zynq-7000 platforms. The Zynq-7000 is an interesting platform combing a Xilinx 7-series FPGA fabric with a dual-core ARM Cortex-A9 based Application Processor Unit (System-on-a-Chip).

The Zedboard is an evaluation board for the Zynq-7000. It is manufactured by Digilent. More information on the Zedboard can be found at www.zedboard.org.

The information on this page is migrating to the FreeBSD wiki at http://wiki.freebsd.org/FreeBSD/arm/Zedboard.

Ultra96:

A Display Port driver works on the Ultra96 board. It only supports 1920 x 1080 @ 60 hz.

FreeBSD can boot on the Zynq UltraScale+ based Ultra96 board from Avnet.

An arm64 GENERIC kernel boots on the Ultra96 but has limited functionality due to lack of drivers. Starting with a FreeBSD aarch64 snapshot, all that is needed is to add a fairly generic BOOT.BIN file and a custom device tree blob.

Building a bootable FreeBSD SD image for Ultra96:

Here is a recipe for creating a bootable SD card image from a Raspberry Pi 3 snapshot:

DTS files for FreeBSD on Ultra96

Although I have a modified FreeBSD kernel running on the Ultra96 using the upstream DTS files, the drivers in the GENERIC kernel do not yet handle all the driver FDT compatible strings and properties. My custom DTS files for using the GENERIC kernel are on github here.

To create the dtb, use dtc, the device tree compiler:

  dtc -I dts -O dtb avnet-ultra96-rev1.dts > ultra96-rev1.dtb

About BOOT.BIN:

BOOT.BIN is a binary that the Zynq UltraScale+ uses to boot. The following is the .bif file used to create BOOT.BIN using bootgen, a tool included in the Xilinx Vivado software suite:
	image :
	{
		[bootloader, destination_cpu=a53-0] fsbl.elf
		[destination_device=pl] design_1_wrapper.bit // optional
		[pmufw_image] pmufw.elf
		[destination_cpu=a53-0, exception_level=el-3, trustzone] bl31.elf
		[destination_cpu=a53-0, exception_level=el-2] u-boot.elf
	}
This is the bootgen command to create BOOT.BIN:
  bootgen -arch zynqmp -image boot.bif -o BOOT.BIN
The following are vague descriptions of how I built each of the software componentsin BOOT.BIN. I have put these individual binaries in this directory.

Zedboard: Pre-built SD card image

An SD card image for the Zedboard based upon FreeBSD 12.1-RELEASE is available here: FreeBSD-12.1-ZEDBOARD-354239.img.xz.

SHA256 (FreeBSD-12.1-ZEDBOARD-354239.img) = 0c42d842c3e697b175aa13bb9033e0c9f32bfa78916e0756c4eb501a468c6c77
SHA256 (FreeBSD-12.1-ZEDBOARD-354239.img.xz) = b49f69c3eaa389a5e17d916efede0297ebb22ed8808e509e2c4b7c83a415cf03

If you would like to test-drive FreeBSD on a Zedboard, download the xz compressed SD card image. Uncompress and copy the image to the SD card.

On my machine, the SD card shows up as /dev/da0. Be sure that is the same on your machine before cut and pasting this.

xz --decompress FreeBSD-12.1-ZEDBOARD-354239.img.xz
dd if=FreeBSD-12.1-ZEDBOARD-354239.img of=/dev/da0 bs=1m

Boot It

Power down the Zedboard. Insert the SD card in the SD slot and be sure the Zedboard's configuration mode jumpers are set for booting from the SD card before powering up. (If you've already been booting the Linux image from the SD card shipped with the Zedboard, you shouldn't need to change anything.)

The USB-UART connected to connector J14 acts as the FreeBSD console (device uart1). This is the same console as the stock Linux image. The Zedboard should automatically boot U-boot and then the FreeBSD kernel.

The FreeBSD kernel has drivers for the UARTs, SDHCI, Gig Ethernet, and a USB host driver for the USB OTG connected at J13. There is also a GPIO driver which allows reading of switches and buttons and controlling the LEDs.

Note: Booting this pre-built image will not display "FreeBSD" on the OLED display as shown in the picture. It was a separate C program I wrote a while ago and now I can't find it!

Please send any feedback to me via E-mail


Zybo:

FreeBSD also runs on the Zybo. The Zybo from Digilent Inc. is a lower cost board than the Zedboard.

Here is a pre-built SD card image for Zybo based upon FreeBSD 12.1-RELEASE: FreeBSD-12.1-ZYBO-354239.img.xz.

SHA256 (FreeBSD-12.1-ZYBO-354239.img) = 5d3c1eed42dd4b8ff19b576bb1726953020f82a2aae5f1fd2fbcef54244abe27
SHA256 (FreeBSD-12.1-ZYBO-354239.img.xz) = 4c9aedd1b79a843ec5af52f50f964d4e7be8bac36b8133e234ab441ba848fd06
Follow the instructions above in the Zedboard section to uncompress and copy the image to an SD card. To boot the image on Zybo, don't forget to set the mode jumper (JP5) to boot from SD.

Note: This image is for the original Zybo which has been retired and replaced by the Zybo Z7 board. This image will not work on the Zybo Z7.


Building an SD Image

Build world and kernel

First, we need to build world for armv7 and a kernel for Zedboard:

From the source directory /usr/src:

make TARGET_ARCH=armv7 KERNCONF=ZEDBOARD buildworld buildkernel

Create an SD card image

The following creates SD card image with an msdos boot partition.
dd if=/dev/zero of=SDCARD.img bs=1m count=2500
mdconfig -f SDCARD.img -u 0

gpart create -s MBR md0
gpart add -s64m -t \!14 md0
gpart set -a active -i 1 md0
newfs_msdos -F 16 /dev/md0s1

gpart add -t freebsd md0
gpart create -s BSD md0s2
gpart add -t freebsd-ufs md0s2
newfs /dev/md0s2a

Mount SD card partitions

mkdir /mnt/boot /mnt/armroot
mount -t msdosfs /dev/md0s1 /mnt/boot
mount /dev/md0s2a /mnt/armroot

Copy boot files

The Zynq chip needs several files in an msdos boot partition to boot FreeBSD:
boot.bin
u-boot.img
EFI/BOOT/bootarm.efi
dtb/zynq-zynq.dtb
The boot.bin and u-boot.img come from the u-boot-zedboard port in /usr/ports/sysutils/u-boot-zedboard.
cp /usr/local/share/u-boot/u-boot-zedboard/{boot.bin,u-boot.img} /mnt/boot
The efi boot loader is built by buildworld (see above). The binary is found in /usr/obj/usr/src/arm.armv7/stand/efi/loader_lua/loader_lua.efi. Copy it over:
mkdir -p /mnt/boot/EFI/BOOT
cp /usr/obj/usr/src/arm.armv7/stand/efi/loader_lua/loader_lua.efi /mnt/boot/EFI/BOOT/bootarm.efi
Last, we need the dtb file. U-boot defaults to using "zynq-zynq.dtb" as the dtb:
mkdir /mnt/boot/dtb
dtc -I dts -O dtb /usr/src/sys/dts/arm/zedboard.dts > /mnt/boot/dtb/zynq-zynq.dtb

Populate root and boot partitions

From within the source directory:
make TARGET_ARCH=armv7 KERNCONF=ZEDBOARD DESTDIR=/mnt/armroot installworld distribution installkernel

Final tweaks

Copy a couple more files:
cp fstab rc.conf /mnt/armroot/etc

Create a mount point for the boot partition:

mkdir /mnt/armroot/boot/msdos

Touch /firstboot:

touch /mnt/armroot/firstboot

Unmount file systems

umount /mnt/boot
umount /mnt/armroot
mdconfig -d -u 0

Copy to an SD card

dd if=SDCARD.img of=/dev/da0 bs=1m

Updated: June 2020


Thomas Skibo

E-mail Me