ZCU104 SD card image

The easiest way is to use the prebuilt SD card image, as described in ZCU104 board instructions. However, it is possible to build the image from source, if needed.

The SD card image consists of boot partition and rootfs. Currently, only rootfs is built using buildroot. The boot partition contents has to be built manually.

In the future, the buildroot configuration should be revised to build all the required software. Initial configuration has been included but it is still a work i progress and does not boot.

Bootloaders & kernel

Currently, we are using Xilinx FSBL, but it should be possible to use U-Boot SPL (link1, link2).

FSBL and PMU firmware can be built with following the steps:

Create a project from the Vivado example project “Base Zynq UltraScale+ MPSoC” for ZCU104 eval board. Open the PS IP configurator and add the following: * PS-PL Interfaces -> AXI HPM0 FPD (32-bit), AXI HPM1 FPD (32-bit) * disable Carrier Detect in Memory Interfaces -> SD -> SD 0

The following script can be used to generate FSBL, PMU firmware and Device Tree:


set hwdsgn  [open_hw_design PATH/TO/Base_Zynq_MPSoC_wrapper.hdf]

generate_app -hw $hwdsgn -os standalone -proc psu_cortexa53_0 -app zynqmp_fsbl -compile -sw fsbl -dir ./fsbl/
generate_app -hw $hwdsgn -os standalone -proc psu_pmu_0 -app zynqmp_pmufw -compile -sw pmufw -dir ./pmufw

set_repo_path PATH/TO/device-tree-xlnx
create_sw_design device-tree -os device_tree -proc psu_cortexa53_0
generate_target -dir dts

close_hw_design [current_hw_design]

The Device Tree generated by Vivado is missing ethernet-phy node. Modify `pcw.dtsi` as follows:

&gem3 {
    phy-mode = "rgmii-id";
    status = "okay";
    xlnx,ptp-enet-clock = <0x0>;
    phy0: phy@c {
        reg = <0xc>;
        ti,rx-internal-delay = <0x8>;
        ti,tx-internal-delay = <0xa>;
        ti,fifo-depth = <0x1>;

Then generate the Device Tree Blob in the dts directory:

gcc -I include -I . -E -nostdinc -undef -D__DTS__ -x assembler-with-cpp -o system.dts system-top.dts
dtc -I dts -O dtb -o system.dtb system.dts

Build the rest of the required components:

NOTE: It may be necessary to apply the patches from firmware/zcu104/buildroot/board/zynqmp/patches when building U-Boot/Linux.

When building U-Boot make sure to update its configuration (u-boot-xlnx/.config) with the following options:

CONFIG_BOOTARGS="earlycon clk_ignore_unused console=ttyPS0,115200 root=/dev/mmcblk0p2 rootwait rw earlyprintk rootfstype=ext4"
CONFIG_BOOTCOMMAND="load mmc 0:1 0x2000000 zcu104.bit; fpga load 0 0x2000000 $filesize; load mmc 0:1 0x2000000 system.dtb; load mmc 0:1 0x3000000 Image; booti 0x3000000 - 0x2000000"

These configure U-Boot to load the bitstream from SD card and then start the system. Unfolding CONFIG_BOOTCOMMAND we can see:

load mmc 0:1 0x2000000 zcu104.bit
fpga load 0 0x2000000 $filesize
load mmc 0:1 0x2000000 system.dtb
load mmc 0:1 0x3000000 Image
booti 0x3000000 - 0x2000000

Example of building ARM Trusted firmware:

make distclean
make -j`nproc` PLAT=zynqmp RESET_TO_BL31=1

Example of building U-Boot:

make -j`nproc` distclean
make xilinx_zynqmp_zcu104_revC_defconfig
# now modify .config directly or using `make menuconfig` as described earlier
make -j`nproc`

Example of building Linux:

make -j`nproc` ARCH=arm64 distclean
make ARCH=arm64 xilinx_zynqmp_defconfig
# optional `make menuconfig`
make -j`nproc` ARCH=arm64 dtbs
make -j`nproc` ARCH=arm64

Then download zynq-mkbootimage and prepare the following boot.bif file:

    [fsbl_config] a53_x64
    [bootloader] fsbl.elf
    [pmufw_image] pmufw.elf
    [, destination_cpu=a53-0, exception_level=el-2] bl31.elf
    [, destination_cpu=a53-0, exception_level=el-2] u-boot.elf

Open a terminal and make sure that the filepaths specified in boot.bif are correct. Then use``mkbootimage –zynqmp boot.bif boot.bin`` to create the boot.bin file.

Root filesystem

Download buildroot

git clone git://git.buildroot.net/buildroot
git checkout 2020.08.2


As of time of writing git checkout f45925a951318e9e53bead80b363e004301adc6f was required to avoid fakeroot errors when building.

Then prepare configuration using external sources and build everything:

make BR2_EXTERNAL=/PATH/TO/REPO/litex-rowhammer-tester/firmware/zcu104/buildroot zynqmp_zcu104_defconfig
make -j`nproc`

Flashing SD card

One can use fdisk to directly partition the SD card /dev/xxx or use the provided genimage configuration to create an SD card image than can be then directly copied to the SD card. The second method is usually more convenient.

Formatting SD card manually

Use fdisk or other tool to partition the SD card. The recommended partitioning scheme is as follows:

  • Partition 1, FAT32, 128M

  • Partition 2, ext4, 128M

Then create the filesystems:

sudo mkfs.fat -F 32 -n BOOT /dev/OUR_SD_CARD_PARTITION_1
sudo mkfs.ext4 -L rootfs /dev/OUR_SD_CARD_PARTITION_2

Write the rootfs:

sudo dd status=progress oflag=sync bs=4M if=/PATH/TO/BUILDROOT/output/images/rootfs.ext4 of=/dev/OUR_SD_CARD_PARTITION_2

Mount the boot partition and copy the boot files and kernel image created earlier and the ZCU104 bitstream:

cp boot.bin /MOUNT/POINT/BOOT/
cp /PATH/TO/litex-rowhammer-tester/build/zcu104/gateware/zcu104.bit /MOUNT/POINT/BOOT/
cp /PATH/TO/linux-xlnx/arch/arm64/boot/Image /MOUNT/POINT/BOOT/
cp /PATH/TO/linux-xlnx/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dtb /MOUNT/POINT/BOOT/system.dtb

Note: make sure to name the device tree blob system.dtb for the U-Boot to be able to find it (as shown in above commands).

Using genimage

By default ZCU104 buildroot configuration will also build the genimage tool for host system. Image configuration is described in the firmware/zcu104/image.cfg file. There is also a script firmware/zcu104/genimage.sh for convenience. Run it without arguments to get help. Then run it providing correct paths to all the required files to generate the zcu104.img file.

The image can be then copied to SD card device (not partition! so e.g. /dev/sdb, not /dev/sdb1) using dd:

sudo dd status=progress oflag=sync bs=4M if=/PATH/TO/zcu104.img of=/dev/OUR_SD_CARD