Linux Kernel and Boot Loader

To the extent possible, the NDI examples attempt to follow the vendor specific boot flow and methods for building a Linux kernel and U-Boot boot-loader. The following sections detail specific customizations made to enable the otherwise standard vendor boot-loader and kernel to work with the NDI FPGA examples.

Altera

The Altera U-Boot bootloader and Linux kernel are built from git repositories provided by altera-opensource on github. See RocketBoards.org for full details.

Directory Structure

The following Altera project subdirectories can be found in the fpga_reference_design/linux_kernel directory:

Directory
Target Development Board

agilex7

DK-SI-AGI027FA Agilex-7 SoC DevKit

a10-socdk

Arria-10 SoC Development Kit

SoCKit

Arrow/Terasic SoCKit

Build Requirements

Building the Linux kernel and U-Boot bootloader requires an appropriate cross compiler for the target archiecture. On Debian and similar systems, this can be accomplished by installing the appropriate packages:

sudo apt-get install cpp-aarch64-linux-gnu
sudo apt-get install gcc-arm-linux-gnueabihf

Alternately an appropriate 3rd party cross compiler can be used, or a toolchain can be built directly from source.

Building an Existing Project

The build instructions from Altera involve quite a few manual steps:

https://www.rocketboards.org/foswiki/Documentation/BuildingBootloaderCycloneVAndArria10arrow-up-right https://altera-fpga.github.io/rel-25.1/embedded-designs/agilex-7/f-series/soc/boot-examples/ug-linux-boot-agx7-soc/arrow-up-right

These steps have mostly been automated via a Makefile, with some additional changes to customize the kernel as needed for the NDI Advanced SDK (enable UIO devices and create custom device-tree nodes).

The Makefile will checkout the source directories, patch and configure as required, then build the files required to boot and create a uSD image. Warnings about watchdog and timer drivers are expected while building U-Boot from the Altera released sources and can be ignored.

The configuration snippet uio.fragment enables the required uio kernel modules.

The patch file 0001-NewTek-Altera-NDI-device-tree-entries.patch adds the required device-tree nodes for logic in the FPGA fabric. See the instructions from Altera for full details:

https://www.rocketboards.org/foswiki/Documentation/HOWTOCreateADeviceTreearrow-up-right

Note:

If you follow the RocketBoards instructions for generating the Cyclone-V boot files, the FPGA will not be programmed by default. The provided Makefile builds a u-boot.scr file which is executed by the default Altera U-Boot bootcmd. This script programs the FPGA prior to loading the Linux kernel and device-tree.

Xilinx

The following boards and NDI configurations are supported. For a full list of available targets run make help in the fpga_reference_design/linux_kernel directory.

Configuration
Contents

Arty-Z7-20-Enc

NDI encoder for the Digilent Arty Z7-20

Zybo-Z7-20-Enc

NDI encoder for the Digilent Zybo Z7-20

Zybo-Z7-20-Enc-Lite

NDI encoder for the Digilent Zybo Z7-20 with 16-bit SDRAM

Zybo-Z7-20-Dec

NDI decoder for the Digilent Zybo Z7-20

ZCU104-Enc

NDI encoder for the Xilinx ZCU104

ZCU104-Dec

NDI decoder for the Xilinx ZCU104

Xilinx offers at least two different approaches to generating the bootloaders, device tree, and Linux kernel.

Open Source Linux (OSL) Flow

The OSL flow essentially builds each component required to boot the example design independently and then packages them together in a BOOT.BIN file along with a kernel, kernel modules, kernel headers, and a device tree. It offers the highest degree of transparency and control to the user and avoids the need to deal with the vagaries of alternate methods like Yocto or PetaLinux. It requires only that the user have installed the appropriate version of Vitis, which provides the ARM cross-compilers, XSCT, bootgen, and other supporting tools.

Required Xilinx Tools

Building the Xilinx example designs requires that the user have installed the AMD Vitis Unified Software Platform version 2024.2. Xilinx has recently merged Vivado and Vitis together and they generally should be installed concurrently. Vitis provides example design source code, the SDK, bare-metal libraries, as well as the cross-compilers, XSCT, bootgen and other supporting tools.

Installation instructions, supported platforms, and other details can be found in "UG1742, Vitis Release Notes and Installation Guide". After installation, users should prepare their environment by sourcing the appropriate settings script, found at <install_dir>/Vitis/2024.2/settings64.sh before attempting to build any of the example designs.

Generating Example Designs

The steps required for building the bootloaders and kernel are described to some degree on the Xilinx wiki and forums and have generally been automated via a top-level Makefile. To build one of the example designs, run make all with the following variables set accordingly:

  • XSA_BOARD - The target board: ZCU104, Zybo-Z7-20, or Arty-Z7-20

  • XSA_BOARD_PROJ - The design to build: Enc, Dec, or Enc-lite (Zybo only)

Note that case is significant and that the combination matches the project names in ../src/fpga as well as the device tree snippets in device-tree/.

Configuration Files

Each Xilinx board has a corresponding entry in boards/ which contains configuration settings used by the make process. The appropriate file to use is determined by the value of the XSA_BOARD variable and determines the flags to use for compiling the bootloader, the kernel, and other settings. Refer to the Makefile and fragments in mk/ for more details.

Each Xilinx project has a corresponding entry in device-tree/ which contains a device tree include file that will be included in the device tree source and ultimately compiled during the build process. The appropriate file to use is determined by the value of the XSA_BOARD_PROJ variable. Refer to the Makefile and fragments in mk/ for more details.

Output Products

There are many ways to boot Xilinx devices, this discussion is limited to what is done here. The build process produces several artifacts required for booting the system:

  • BOOT.BIN - The initial binary used to boot the system prior to loading the kernel

  • system.dtb - The flattened device tree passed to the kernel by U-boot

  • Image or zImage - The Linux kernel loaded by U-boot

  • Kernel modules and headers

Bootloaders and BOOT.BIN

The BOOT.BIN file created for the example designs contains the following content:

  • First-stage bootloader (FSBL)

  • U-boot ELF

  • Minimal U-boot device tree (used by U-Boot before loading the kernel)

  • Bitstream

Ultrascale+ devices also contain:

  • ARM Trusted Firmware (ATF)

  • Platform management unit (PMU) firmware

The origins of each component of the BOOT.BIN are the following:

  • The FSBL source code is exported by XSCT using the contents of the associated Xilinx support archive. After export, the source code and linker script are cross compiled for the target platform. Build flags for the FSBL are controlled by variables set in the appropriate board specific file in the boards/ directory. The FSBL ELF is staged for later packaging.

  • The Makefile fetches the specified tag of the Xilinx U-boot fork, applies the defconfig from the file defined by XSA_BOARD and cross-compiles it for the target platform. The U-boot ELF and a minimal device tree are staged for later packaging. It is worth noting that the Xilinx platforms used for NDI Advanced SDK example designs all have some level of support by U-boot and the device tree that is created is sufficient to boot a kernel from the SD card.

  • The bitstream is extracted from the provided Xilinx support archive (XSA) file and staged for later packaging.

  • The PMU firmware (ZCU104 only) source code is exported by XSCT using the contents of the XSA file. The PMUFW is cross-compiled in the same was as the FSBL, with PMUFW specific build variables that can be useful for debugging. The user is referred to the Xilinx wiki and especially UG1137, the Zynq MPSoC Software Developers Guide, for more details regarding PMU use and configuration.

  • The Makefile fetches the specified tag of the ARM trusted firmware (ATF) and builds it for the target platform. The bl31.elf it creates is then staged for later packaging.

  • Once the FSBL and U-boot binaries, minimal U-boot device tree, bitstream, and PMUFW and ATF are staged, the appropriate .bif file is installed alongside them and bootgen is run construct the BOOT.BIN that will eventually be transferred to /boot of an SD card. An MD5 hash is computed for each component as well as the final product. See UG1283 for more information on the use of bootgen to create and dump BOOT.BIN files.

  • Once bootgen has finished assembling the BOOT.BIN file, it is copied to a project specific location in the output directory.

Flattened Device Tree

Generating the device tree source code and the flattened device tree requires several steps:

  • The Makefile fetches the indicated tag of the Xilinx device-tree source generator which is a large collection of Tcl scripts and board specific details for Xilinx IP and development boards. The DTS generator uses the XSA to infer IP settings and connections.

  • The path to that repo is used together with the project XSA file to create a directory containing all the files required to build a device tree for the specific Vivado project.

  • The files in the device tree source directory then undergo some modifications (see mk/dtb.mk for details) prior to compilation.

  • The appropriate .dtsi file in device-tree/ is included at this stage before the final device tree source is compiled into the flattened device tree.

  • The flattened device tree and the top level source code are copied into the same project-specific location in the output directory that the BOOT.BIN was.

Kernel and Modules

The Linux kernel follows a much more familiar set of steps:

  • The Makefile fetches the indicated tag of the Xilinx fork of the Linux kernel source tree. To save space and time, this is a limited clone of the tree.

  • The kernel is built using an external build directory (using the O= option), which allows the same source tree to be used to build multiple architectures.

  • Default kernel configurations are used for both ARM and ARM64 kernels.

  • The kernel, modules, and headers are installed into output/$(ARCH)/.

Rebuilding Example Designs after Modification

Rebuilding example designs after modifications to the FPGA projects is straightforward as long as a couple of caveats are followed:

  • The project naming conventions need to remain the same in order for device tree include files to be properly included

  • In principle, any new IP added that the kernel needs to be aware of will be automatically included by the device tree source generator. In practice, some manual modifications via the .dtsi file may be required.

  • Run make clean which will remove the staging area and output directories but preserve the git repos that were downloaded to extern/. Then run make all with the XSA_BOARD and XSA_BOARD_PROJ set appropriately.

Petalinux Flow

The PetaLinux design flow is an alternative to the OSL flow that the NDI Advanced SDK uses. No PetaLinux projects are provided.

Suggested Steps for PetaLinux Projects

The PetaLinux commands and recommended work flow have changed in recent revisions of the tools and the following steps should only be used as a guide. For more detailed information, including the most recent commands and arguments, refer to "UG1144 PetaLinux Tools Documentation: Reference Guide" and other documents, in particular the Xilinx wiki.

The general approach to building a PetaLinux project based on the NDI Advanced SDK would be the following:

  • Export the hardware platform from Vivado and make sure that the bitstream is included in the exported Xilinx support archive (XSA)

  • Create a PetaLinux project

    $ petalinux-create -t project <project_name>

  • Import the new hardware definition and configure the project

    $ cd <project_name> $ petalinux-config --get-hw-description <path-to-vivado-project>

  • Configure the project, kernel, U-boot, and rootfs

    $ petalinux-config -c u-boot $ petalinux-config -c kernel $ petalinux-config -c rootfs

  • Add device tree include files from device-tree/ for the target platform to the PetaLinux project. This has typically been done by copying it to a location with the project-meta directory, but this may vary by version. If the design to be built includes additional IP or other modifications that affect the device tree, these need to be made as well, typically by hand.

  • Build the project.

    $ petalinux-build

  • Package the system for deployment (note that there are likely many options that will need to be included for this command)

    $ petalinux-package <options>

Once the project has been completed, boot images are typically located in the project tree at images/linux. The kernel and kernel modules will need to be extracted from the project along with the device tree and BOOT.BIN for transfer to an SD card. Various kernel images are usually generated during the build process. Kernel modules can be extracted from the rootfs tarball that is created during the build.

Last updated

Was this helpful?