Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This article will discuss the steps needed to download and compile a Bootable (SD) Linux Image for the ZCU102 using the OSL flow.

...

The recommended flow for building a Linux system is to use the Petalinux tools. However, this article offers an alternative for users that want full visibility into the Image.

This assumes that the users has downloaded Vitis 2020.1 (used to by the devcetree generator). I have structured this wiki in a way that users can copy this into their Makefile for ease of use. However, users will need to be careful of the makefile syntax while copy and pasting.
Some steps are duplicated. For example, the cross_compile steps. This is intentional to allow the users to build each image in isolation.
However, users must use the same tag, as there are dependencies between pmufw and atf for example.The rootFS is downloaded from the released images from here

Build FSBL

  • git clone https://github.com/Xilinx/embeddedsw
  • cd embeddedsw
  • git checkout xilinx-v2020.1
  • cd embeddedsw/lib/sw_apps/zynqmp_fsbl/src
  • make "BOARD=zcu102-es2" "PROC=a53" "CFLAGS+=-DFSBL_DEBUG_INFO"

Build PMU Firmware

  • cd embeddedsw/lib/sw_apps/zynqmp_pmufw/src
  • make

Build ATF

Note: If users want to debug (ie use the symbols) the ATF in Vitis, then set the DEBUG=1. This will place the ATF in DDR at 0x1000

Build u-boot

...

NOTE: If building on an Ubuntu (or derivative machine), ensure that the default shell has been changed from Dash to Bash.  Compiling in Dash may result in syntax errors within the Makefile that will prevent the code from compiling.

Makefile params:


Code Block
languagec#
titleparams
SHELL := /bin/bash
TOOLS ?= /proj/gsd/vivado/Vitis
VERSION ?= 2020.2
BOARD ?= ZCU102

Note: Make sure that the tools patch point to your relevant install on your machine

Getting Sources:


Code Block
languagec#
titleget_sources
get_sources:
	if [ ! -d "./bootgen" ];then \
		git clone https://github.com/Xilinx/

...

Note: If users want to debug (ie use the symbols) the u-boot in Vitis, then use the u-boot (renamed u-boot.elf) in the boot image.

Build Linux Image:

Build device-tree

...

bootgen; \
		$(MAKE) -C bootgen; \
	fi
	if [ ! -d "./linux-xlnx" ];then \
		git clone https://github.com/Xilinx/linux-xlnx; \
		cd linux-xlnx && git checkout xilinx-v$(VERSION); \
	fi
	if [ ! -d "./repo" ];then \
		mkdir -p repo/my_dtg; \
		cd repo/my_dtg && git clone https://github.com/Xilinx/device-tree-xlnx; \
		cd device-tree-xlnx && git checkout xilinx-v$(VERSION); \
	fi
	if [ ! -d "./u-boot-xlnx" ];then \
		git clone https://github.com/Xilinx/

...

u-

...

boot-xlnx

...

Code Block
themeMidnight
proc gen_dtb {hdf} {
   open_hw_design $hdf
   set_repo_path ./repo
   create_sw_design device-tree -os device_tree -proc psu_cortexa53_0
   generate_target -dir my_dts
}
  • Launch HSI, and execute the following commands:
  • source <your_filename>.tcl
  • gen_dtb <HDF_FILE>.xsa
  • Exit HSI

...

Code Block
themeMidnight
&gem3 {
             status = "okay";
             local-mac-address = [00 0a 35 00 02 90];
             phy-mode = "rgmii-id";
             phy-handle = <&phy0>;
             phy0: phy@c {
                         reg = <0xc>;
                         ti,rx-internal-delay = <0x8>;
                         ti,tx-internal-delay = <0xa>;
                         ti,fifo-depth = <0x1>;
             };
};

Users can also add the dtsi here to my_dts directory, and include this into the DT structure. For a quick guide on Devicetree debugging, see the wiki here

Compile the devicetree (DTB)

  • dtc -I dts -O dtb -o my_dts/system-top.dtb my_dts/system-top.dts

Note: For the 2018.3 release version onward, the 'include' syntax in device-tree files changed from /include/ to the 'C' style #include. Depending on which version of the device-tree-compiler (dtc) is being used, this may cause parsing errors when the .dts file is read. To fix this, all instances of #include need to be replaced with /include/.

...

  • dtc -I dtb -O dts -o my_dts/system-dump.dts my_dts/system-top.dtb

Create SD image

Build The bootgen binary

...

Code Block
themeMidnight
the_ROM_image:
{
[fsbl_config] a53_x64
[bootloader, destination_cpu=a53-0] embedded/lib/sw_apps/zynqmp_fsbl/src/fsbl.elf
[pmufw_image] embeddedsw/lib/sw_apps/zynqmp_pmufw/src/executable.elf
[destination_device=pl] design_1_wrapper.bit
[destination_cpu=a53-0, load=0x00100000] my_dts/system-top.dtb
[destination_cpu=a53-0,exception_level=el-3,trustzone] arm-trusted-firmware/build/zynqmp/release/bl31/bl31.elf
[destination_cpu=a53-0,exception_level=el-2] u-boot-xlnx/u-boot.elf
}

...

; \
		cd u-boot-xlnx && git checkout xilinx-v$(VERSION); \
	fi
	if [ ! -d "./arm-trusted-firmware" ];then \
		git clone https://github.com/Xilinx/arm-trusted-firmware; \
		cd arm-trusted-firmware && git checkout xilinx-v$(VERSION); \
	fi
	if [ ! -d "./dtc" ];then \
		git clone https://git.kernel.org/pub/scm/utils/dtc/dtc.git; \
		$(MAKE) -C dtc; \
	fi


Build FSBL

Create, or append the proc below to your xsct_script.tcl

Code Block
languagec#
titlefsbl
proc fsbl {args} {
	set board 0
	for {set i 0} {$i < [llength $args]} {incr i} {
		if {[lindex $args $i] == "-board"} {
			set board [string toupper [lindex $args [expr {$i + 1}]]] 
		}
	}
	set xsa [glob -nocomplain -directory [pwd] -type f *.xsa *.hdf]
	hsi::open_hw_design $xsa
	set fsbl_design [hsi::create_sw_design fsbl_1 -proc psu_cortexa53_0 -app zynqmp_fsbl]
	if {$board != 0} {
		common::set_property -name APP_COMPILER_FLAGS -value "-DXPS_BOARD_${board}" -objects $fsbl_design
	}
	hsi::generate_app -dir zynqmp_fsbl -compile
	hsi::close_hw_design [hsi::current_hw_design]
}

Note: if you have a development board such as the ZCU102, then you can pass this as a symbol to the compiler

Then call this from your Makefile:

Code Block
languagec#
titlebuild_fsbl
fsbl:
	$(RM) -r zynqmp_fsbl
	$(TOOLS)/$(VERSION)/bin/xsct -eval "source xsct_script.tcl; fsbl -board $(BOARD)"

Build PMU Firmware

Create, or append the proc below to your xsct_script.tcl

Code Block
languagec#
titlepmufw
proc pmufw {} {
	set xsa [glob -nocomplain -directory [pwd] -type f *.xsa *.hdf]
	hsi::open_hw_design $xsa
	hsi::generate_app -app zynqmp_pmufw -proc psu_pmu_0 -dir zynqmp_pmufw -compile
	hsi::close_hw_design [hsi::current_hw_design]
}

Then call this from your Makefile:

Code Block
languagec#
titlebuild_pmufw
pmufw:
	$(RM) -r zynqmp_pmufw
	$(TOOLS)/$(VERSION)/bin/xsct -eval "source xsct_script.tcl; pmufw"

Build ATF


Code Block
languagec#
titleatf
atf:
	$(MAKE) -C arm-trusted-firmware clean
	source $(TOOLS)/$(VERSION)/settings64.sh; \
	export CROSS_COMPILE=aarch64-none-elf-; \
	cd arm-trusted-firmware; \
	$(MAKE) -f Makefile DEBUG=0 RESET_TO_BL31=1 PLAT=zynqmp bl31

Note: If users want to debug (ie use the symbols) the ATF in Vitis, then set the DEBUG=1. This will place the ATF in DDR at 0x1000

Build u-boot


Code Block
languagec#
titleu-boot
uboot:
	$(MAKE) -C u-boot-xlnx clean
	source $(TOOLS)/$(VERSION)/settings64.sh; \
	export CROSS_COMPILE=aarch64-linux-gnu-; \
	export ARCH=aarch64; \
	export CC=aarch64-linux-gnu-gcc; \
	export PATH=$$PATH:$(shell pwd)/dtc; \
	cd u-boot-xlnx; \
	$(MAKE) -f  Makefile xilinx_zynqmp_virt_defconfig; \
	$(MAKE) -f  Makefile all -j 32

Note: If users want to debug (ie use the symbols) the u-boot in Vitis, then use the u-boot (renamed u-boot.elf) in the boot image.

Build Linux Image:


Code Block
languagec#
titlekernel
kernel:
	$(MAKE) -C linux-xlnx clean
	source $(TOOLS)/$(VERSION)/settings64.sh; \
	export CROSS_COMPILE=aarch64-linux-gnu-; \
	export ARCH=arm64; \
	export CC=aarch64-linux-gnu-gcc; \
	cd linux-xlnx; \
	$(MAKE) -f Makefile xilinx_zynqmp_defconfig; \
	$(MAKE) -f Makefile all -j 32; \
	$(MAKE) -f Makefile modules_install INSTALL_MOD_PATH=.


Build device-tree

  • Create a xsct_script.tcl file with the following contents:
Code Block
themeMidnight
proc build_dts {args} {
	set board 0
	set version 2020.2
	for {set i 0} {$i < [llength $args]} {incr i} {
		if {[lindex $args $i] == "-board"} {
			set board [string tolower [lindex $args [expr {$i + 1}]]] 
		}
		if {[lindex $args $i] == "-version"} {
			set version [string toupper [lindex $args [expr {$i + 1}]]] 
		}
	}
    	set xsa [glob -nocomplain -directory [pwd] -type f *.xsa]
    	hsi::open_hw_design $xsa
    	hsi::set_repo_path ./repo
    	hsi::create_sw_design device-tree -os device_tree -proc psu_cortexa53_0
    	hsi::generate_target -dir my_dts
    	hsi::close_hw_design [hsi::current_hw_design]
    	if {$board != 0} {
		foreach lib [glob -nocomplain -directory repo/my_dtg/device-tree-xlnx/device_tree/data/kernel_dtsi/${version}/include/dt-bindings -type d *] {
			if {![file exists my_dts/include/dt-bindings/[file tail $lib]]} {
				file copy -force $lib my_dts/include/dt-bindings
			}
		}
		set dtsi_files [glob -nocomplain -directory repo/my_dtg/device-tree-xlnx/device_tree/data/kernel_dtsi/${version}/BOARD -type f *${board}*]
		if {[llength $dtsi_files] != 0} {
			file copy -force [lindex $dtsi_files end] my_dts
			set fileId [open my_dts/system-user.dtsi "w"]
			puts $fileId "/include/ \"[file tail [lindex $dtsi_files end]]\""
			puts $fileId "/ {"
			puts $fileId "};"
			close $fileId
		}
	}
}

If there is a valid board found, then it will added to dtsi files. Then we can call this from our Makefile:

Code Block
languagec#
titledts
build_dts:
	$(RM) -r my_dts
	$(TOOLS)/$(VERSION)/bin/xsct -eval "source xsct_script.tcl; build_dts -version $(VERSION) -board $(BOARD)"

Compile the devicetree (DTB)


Code Block
languagec#
titledtb
build_dtb:
	$(RM) -r system.dtb
	export PATH=$$PATH:$(shell pwd)/dtc; \
	gcc -I my_dts -E -nostdinc -undef -D__DTS__ -x assembler-with-cpp -o my_dts/system-top.dts.tmp my_dts/system-top.dts; \
	dtc -I dts -O dtb -o system.dtb my_dts/system-top.dts.tmp

Create SD image


Create the BIF file with the contents below:
Code Block
themeMidnight
the_ROM_image:
{
	[fsbl_config] a53_x64
	[bootloader, destination_cpu=a53-0] zynqmp_fsbl/executable.elf
	[pmufw_image] zynqmp_pmufw/executable.elf
	[destination_device=pl] design_1_wrapper.bit
	[destination_cpu=a53-0, load=0x00100000] system.dtb
	[destination_cpu=a53-0,exception_level=el-3,trustzone] arm-trusted-firmware/build/zynqmp/release/bl31/bl31.elf
	[destination_cpu=a53-0,exception_level=el-2] u-boot-xlnx/u-boot.elf
}


Then in bootgen command from your Makefile


Code Block
languagec#
titlebootgen
bootimage:
	export PATH=$$PATH:$(shell pwd)/bootgen; \
	bootgen -arch zynqMP -image bootgen.bif -w -o BOOT.BIN


Downloading the RootFS:

There are released images for all Xilinx development boards. I will extract the rootfs from the image.ub here using dumpimage utility:

Code Block
languagec#
titleextract_rootfs
extract_rootfs:
	tar xvf $(VERSION)-$(BOARD)-release.tar.xz
	./u-boot-xlnx/tools/dumpimage -T flat_dt -p 2 $(VERSION)-$(BOARD)-release/image.ub -o petalinux-image-minimal-zynqmp-generic.cpio.gz

Creating the FIT image:


Code Block
themeMidnight
/dts-v1/;
/ {
          description = "U-Boot fitImage for plnx_aarch64 kernel";
          #address-cells = <1>;
          images {
                       kernel@0 {
                                   description = "Linux Kernel";
                                   data = /incbin/("./linux-xlnx/arch/arm64/boot/Image");
                                   type = "kernel";
                                   arch = "arm64";
                                   os = "linux";
                                   compression = "none";
                                   load = <0x80000>;
                                   entry = <0x80000>;
                                   hash@1 {
                                          algo = "sha1";
                                    };
                       };
                       fdt@0 {
                                  description = "Flattened Device Tree blob";
                                  data = /incbin/("./my_dts/system.dtb");
                                  type = "flat_dt";
                                  arch = "arm64";
                                  compression = "none";
                                  hash@1 {
                                         algo = "sha1";
                                  };
                      };
                      ramdisk@0 {
                                   description = "ramdisk";
                                   data = /incbin/("./petalinux-user-image-plnx_aarch64.cpio.gz");
                                   type = "ramdisk";
                                   arch = "arm64";
                                   os = "linux";
                                   compression = "none";
                                   hash@1 {
                                          algo = "sha1";
                                   };
                      };
};
      configurations {
             default = "conf@1";
             conf@1 {
                          description = "Boot Linux kernel with FDT blob + ramdisk";
                          kernel = "kernel@0";
                          fdt = "fdt@0";
                          ramdisk = "ramdisk@0";
                          hash@1 {
                                algo = "sha1";
                          };
               };
               conf@2 {
                           description = "Boot Linux kernel with FDT blob";
                           kernel = "kernel@0";
                           fdt = "fdt@0";
                           hash@1 {
                                 algo = "sha1";;
                           };
       };        };
       };
};


Use the command below to created the .ub file:


Code Block
languagec#
titlefit
fit_image:
	export PATH=$$PATH:$(shell pwd)/dtc; \
	./u-boot-xlnx/tools/mkimage  };
};
Use the command below to created the ITB file:
-f fitimage.its image.ub

  • u-boot-xlnx/tools/mkimage -f fitimage.its fitimageimage.itbub

Load the BOOT.BIN and the fitImage.itb image.ub and boot.scr on the SD card and boot. Stop at uboot, and
  • fatload mmc 0 0x10000000 fitimage
  • bootm 0x10000000
Users, can also update add the boot.scr to the SD Card from here:2020.1 Release