Minimalist Linux distribution

Goal

In this tutorial you will:
  • create Linux distribution using Yocto (along with support firmware) based on Vivado project created earlier

  • boot Linux on Leopard DPU through EGSE Host

A bit of background

Running Linux on device like Leopard DPU requires set of artifacts

  • Boot firmware (in particular first stage bootloader and U-Boot)

  • Linux kernel

  • Device tree

  • Root filesystem

Yocto can build these items automatically. Developers construct project using Yocto from layers coming from Yocto project itself, hardware manufactures and their own. Each layer contributes series of recipes that are describing how to build particular components of Linux distribution. BitBake tool manages all dependencies between recipes and hides build complexity.

After building all required artifacts you can use Leopard DPU boot capabilities to load boot firmware into persistent memory and load Linux kernel and root filesystem from network.

Prerequisites

Provided outputs

Following files (Tutorial files) are associated with this tutorial:

  • Leopard/Zero-to-hero/02 Minimalist Linux distribution/boot-common.bin - Boot firmware for Leopard

  • Leopard/Zero-to-hero/02 Minimalist Linux distribution/nominal-image-leopard-dpu.rootfs.cpio.gz.u-boot - Root filesystem for Leopard

  • Leopard/Zero-to-hero/02 Minimalist Linux distribution/Image - Linux kernel

  • Leopard/Zero-to-hero/02 Minimalist Linux distribution/system.dtb - Device tree

Use these files if you want to skip building Yocto distribution by yourself.

Create project Yocto

  1. Create new directory for Yocto project and navigate to it.

    machine:~$ mkdir ~/leopard-linux-1
    machine:~$ cd ~/leopard-linux-1
    machine:~/leopard-linux-1$
    
  2. Clone Poky layer from Yocto project

    machine:~/leopard-linux-1$ git clone -b nanbield https://git.yoctoproject.org/poky sources/poky
    
  3. Create new build configuration

    machine:~/leopard-linux-1$ source sources/poky/oe-init-build-env ./build
    You had no conf/local.conf file. This configuration file has therefore been
    created for you from ~/leopard-linux-1/sources/poky/meta-poky/conf/templates/default/local.conf.sample
    You may wish to edit it to, for example, select a different MACHINE (target
    hardware).
    
    You had no conf/bblayers.conf file. This configuration file has therefore been
    created for you from ~/leopard-linux-1/sources/poky/meta-poky/conf/templates/default/bblayers.conf.sample
    To add additional metadata layers into your configuration please add entries
    to conf/bblayers.conf.
    
    The Yocto Project has extensive documentation about OE including a reference
    manual which can be found at:
        https://docs.yoctoproject.org
    
    For more information about OpenEmbedded see the website:
        https://www.openembedded.org/
    
    
    ### Shell environment set up for builds. ###
    
    You can now run 'bitbake <target>'
    
    Common targets are:
        core-image-minimal
        core-image-full-cmdline
        core-image-sato
        core-image-weston
        meta-toolchain
        meta-ide-support
    
    You can also run generated qemu images with a command like 'runqemu qemux86-64'.
    
    Other commonly useful commands are:
    - 'devtool' and 'recipetool' handle common recipe tasks
    - 'bitbake-layers' handles common layer tasks
    - 'oe-pkgdata-util' handles common target package tasks
    machine:~/leopard-linux-1/build$
    

Add layers Yocto

  1. Clone Xilinx layers:

    machine:~/leopard-linux-1/build$ git clone -b nanbield https://github.com/Xilinx/meta-xilinx.git ../sources/meta-xilinx
    machine:~/leopard-linux-1/build$ git clone -b nanbield https://github.com/Xilinx/meta-xilinx-tools.git ../sources/meta-xilinx-tools
    machine:~/leopard-linux-1/build$ git clone -b nanbield https://git.openembedded.org/meta-openembedded/ ../sources/meta-openembedded
    
  2. Add set of required layers from Xilinx repositories:

    machine:~/leopard-linux-1/build$ bitbake-layers add-layer ../sources/meta-xilinx/meta-xilinx-core
    machine:~/leopard-linux-1/build$ bitbake-layers add-layer ../sources/meta-xilinx/meta-xilinx-bsp
    machine:~/leopard-linux-1/build$ bitbake-layers add-layer ../sources/meta-xilinx/meta-xilinx-standalone
    machine:~/leopard-linux-1/build$ bitbake-layers add-layer ../sources/meta-xilinx-tools
    machine:~/leopard-linux-1/build$ bitbake-layers add-layer ../sources/meta-openembedded/meta-oe/
    machine:~/leopard-linux-1/build$ bitbake-layers add-layer ../sources/meta-openembedded/meta-networking/
    

    Note

    After adding Xilinx layers, BitBake might report warning

    The ZynqMP pmu-rom is not enabled (…) To enable this you must add ‘xilinx’ to the LICENSE_FLAGS_ACCEPTED to indicate you accept the software license.

    This is for informational purposes only and you can ignore it.

  3. Clone KP Labs layers

    machine:~/leopard-linux-1/build$ git clone -b nanbield https://github.com/kplabs-pl/meta-kp-classes.git ../sources/meta-kp-classes
    machine:~/leopard-linux-1/build$ git clone -b nanbield https://github.com/kplabs-pl/meta-kp-leopard.git ../sources/meta-kp-leopard
    
  4. Add set of required layers from KP Labs repositories:

    machine:~/leopard-linux-1/build$ bitbake-layers add-layer ../sources/meta-kp-classes/
    machine:~/leopard-linux-1/build$ bitbake-layers add-layer ../sources/meta-kp-leopard
    

Create layer for customizations Yocto

  1. Create empty layer

    machine:~/leopard-linux-1/build$ bitbake-layers create-layer ../sources/meta-local
    
  2. Add newly created layer to project

    machine:~/leopard-linux-1/build$ bitbake-layers add-layer ../sources/meta-local
    
  3. Verify set of layers enabled in project by opening ~/leopard-linux-1/build/conf/bblayers.conf and checking its contents:

    # POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
    # changes incompatibly
    POKY_BBLAYERS_CONF_VERSION = "2"
    
    BBPATH = "${TOPDIR}"
    BBFILES ?= ""
    
    BBLAYERS ?= " \
    ~/leopard-linux-1/sources/poky/meta \
    ~/leopard-linux-1/sources/poky/meta-poky \
    ~/leopard-linux-1/sources/poky/meta-yocto-bsp \
    ~/leopard-linux-1/sources/meta-xilinx/meta-xilinx-core \
    ~/leopard-linux-1/sources/meta-xilinx/meta-xilinx-bsp \
    ~/leopard-linux-1/sources/meta-xilinx/meta-xilinx-standalone \
    ~/leopard-linux-1/sources/meta-xilinx-tools \
    ~/leopard-linux-1/sources/meta-openembedded/meta-oe \
    ~/leopard-linux-1/sources/meta-openembedded/meta-networking \
    ~/leopard-linux-1/sources/meta-kp-classes \
    ~/leopard-linux-1/sources/meta-kp-leopard \
    ~/leopard-linux-1/sources/meta-local \
    "
    

Configure project Yocto

  1. Edit ~/leopard-linux-1/build/conf/local.conf and add following lines at the beginning:

    MACHINE = "leopard-dpu"
    DISTRO = "kplabs-dpu"
    INHERIT += "rm_work"
    PROJECT_NAME = "leopard-dpu-minimal-linux"
    
  2. Create recipe append to set XSA file

    machine:~/leopard-linux-1/build$ recipetool newappend --wildcard-version ../sources/meta-local/ external-hdf
    
  3. Create directory ~/leopard-linux-1/sources/meta-local/recipes-bsp/hdf/external-hdf and copy minimal-leopard.xsa to it.

  4. Edit recipe append ~/leopard-linux-1/sources/meta-local/recipes-bsp/hdf/external-hdf_%.bbappend and set path XSA file

    FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
    
    HDF_BASE = "file://"
    HDF_PATH = "leopard-minimal.xsa"
    

Build project Yocto

  1. Build project artifacts:

    machine:~/leopard-linux-1/build$ bitbake leopard-all
    

    Warning

    First build might take a long time to complete. Be patient.

  2. Prepare build artifacts for transfer to EGSE Host

    machine:~/leopard-linux-1/build$ mkdir -p ../egse-host-transfer/
    machine:~/leopard-linux-1/build$ cp tmp/deploy/images/leopard-dpu/bootbins/boot-common.bin ../egse-host-transfer/
    machine:~/leopard-linux-1/build$ cp tmp/deploy/images/leopard-dpu/system.dtb ../egse-host-transfer/
    machine:~/leopard-linux-1/build$ cp tmp/deploy/images/leopard-dpu/nominal-image-leopard-dpu.rootfs.cpio.gz.u-boot ../egse-host-transfer/
    machine:~/leopard-linux-1/build$ cp tmp/deploy/images/leopard-dpu/Image ../egse-host-transfer/
    
  3. Transfer content of ~/leopard-linux-1/egse-host-transfer directory to EGSE Host and place it in /var/tftp/tutorial directory

Booting Linux on DPU EGSE Host

  1. Verify that all necessary artifacts are present on EGSE Host:

    customer@egse-host:~$ ls -lh /var/tftp/tutorial
    total 48M
    -rw-rw-r-- 1 customer customer  21M Jul 16 07:15 Image
    -rw-rw-r-- 1 customer customer 1.6M Jul 16 07:15 boot-common.bin
    -rw-rw-r-- 1 customer customer  41M Jul 16 07:15 nominal-image-leopard-dpu.rootfs.cpio.gz.u-boot
    -rw-rw-r-- 1 customer customer  39K Jul 16 07:15 system.dtb
    

    Note

    Exact file size might differ a bit but they should be in the same range (for example nominal-image-leopard-dpu.rootfs.cpio.gz.u-boot shall be about ~40MB)

  2. Ensure that Leopard is powered off

    customer@egse-host:~$ sml power off
    Powering off...Success
    
  3. Prepare U-Boot script for booting from network by writing following content to /var/tftp/leopard-boot.cmd

    dhcp
    
    tftpboot ${kernel_addr_r} /tutorial/Image
    tftpboot ${fdt_addr_r} /tutorial/system.dtb
    tftpboot ${ramdisk_addr_r} /tutorial/nominal-image-leopard-dpu.rootfs.cpio.gz.u-boot
    
    booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}
    
  4. Compile U-Boot script

    customer@egse-host:~$ mkimage -A arm64 -O U-Boot -T script -C none -d /var/tftp/leopard-boot.cmd /var/tftp/leopard-boot.scr
    Image Name:
    Created:      Wed Jan 22 08:31:23 2025
    Image Type:   AArch64 U-Boot Script (uncompressed)
    Data Size:    240 Bytes = 0.23 KiB = 0.00 MiB
    Load Address: 00000000
    Entry Point:  00000000
    Contents:
       Image 0: 232 Bytes = 0.23 KiB = 0.00 MiB
    
  5. Power on Leopard

    customer@egse-host:~$ sml power on
    Powering on...Success
    
  6. Write boot firmware to DPU boot flash

    customer@egse-host:~$ sml boot-flash write --nor-memory nor1 0 /var/tftp/tutorial/boot-common.bin
    Uploading   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00 48.6 MB/s
    Erasing     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00 553.3 kB/s
    Programming ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00 13.5 kB/s
    
  7. Write U-Boot boot script to DPU boot flash

    customer@egse-host:~$ sml boot-flash write --nor-memory nor1 0x380000 /var/tftp/leopard-boot.scr
    Uploading   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00 ?
    Erasing     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00 ?
    Programming ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00 30.7 MB/s
    
  8. Open second SSH connection to EGSE Host and start minicom to observe boot process

    customer@egse-host:~$ minicom -D /dev/sml/leopard-pn1-uart
    

    Leave this terminal open and get back to SSH connection used in previous steps.

  9. Power on Processing Node 1

    customer@egse-host:~$ sml pn1 power on --nor-memory nor1
    Powering on processing node Node1...Success
    
  10. DPU boot process should be visible in minicom terminal

    Note

    It might take ~20 seconds to get first line of output

    Zynq MP First Stage Boot Loader
    Release 2023.2   Oct 12 2023  -  15:51:06
    [SI5338] I2C initialized
    [SI5338] Clock generator configured successfully
    [SI5338] done!
    PMU Firmware 2023.2     Oct 12 2023   15:51:06
    PMU_ROM Version: xpbr-v8.1.0-0
    NOTICE:  BL31: Non secure code at 0x8000000
    NOTICE:  BL31: v2.8(release):xlnx_rebase_v2.8_2023.2_ksb_sep
    NOTICE:  BL31: Built : 12:21:43, Aug 31 2023
    
    
    U-Boot 2023.01-build-6a53a3e6bd5cc95fdcb5508b7f15bf76e709a9b2 (Sep 21 2023 - 11:02:37 +0000)
    
    CPU:   ZynqMP
    Silicon: v3
    Chip:  zu9eg
    Board: Xilinx ZynqMP
    DRAM:  2 GiB (effective 16 GiB)
    PMUFW:  v1.1
    PMUFW:  No permission to change config object
    EL Level:       EL2
    Secure Boot:    not authenticated, not encrypted
    Core:  46 devices, 27 uclasses, devicetree: board
    NAND:  4096 MiB
    MMC:   mmc@ff170000: 0
    Loading Environment from SPIFlash... SF: Detected s25fl512s with page size 256 Bytes, erase size 256 KiB, total 64 MiB
    *** Warning - bad CRC, using default environment
    
    In:    serial
    Out:   serial
    Err:   serial
    [Leopard] Running on PN1
    Bootmode: QSPI_MODE
    Reset reason:   EXTERNAL
    Net:
    ZYNQ GEM: ff0d0000, mdio bus ff0d0000, phyaddr 0, interface rgmii-id
    eth0: ethernet@ff0d0000
    scanning bus for devices...
    SATA link 0 timeout.
    SATA link 1 timeout.
    AHCI 0001.0301 32 slots 2 ports 6 Gbps 0x3 impl SATA mode
    flags: 64bit ncq pm clo only pmp fbss pio slum part ccc apst
    starting USB...
    No working controllers found
    Hit any key to stop autoboot:  0
    SF: Detected s25fl512s with page size 256 Bytes, erase size 256 KiB, total 64 MiB
    device 0 offset 0x380000, size 0x80000
    SF: 524288 bytes @ 0x380000 Read: OK
    QSPI: Trying to boot script at 20000000
    ## Executing script at 20000000
    BOOTP broadcast 1
    DHCP client bound to address 172.20.200.100 (43 ms)
    Using ethernet@ff0d0000 device
    TFTP from server 172.20.200.1; our IP address is 172.20.200.100
    Filename '/tutorial/Image'.
    Load address: 0x18000000
    Loading: #################################################################
            9.2 MiB/s
    done
    Bytes transferred = 21377536 (1463200 hex)
    Using ethernet@ff0d0000 device
    TFTP from server 172.20.200.1; our IP address is 172.20.200.100
    Filename '/tutorial/system.dtb'.
    Load address: 0x40000000
    Loading: ###
            7.5 MiB/s
    done
    Bytes transferred = 39069 (989d hex)
    Using ethernet@ff0d0000 device
    TFTP from server 172.20.200.1; our IP address is 172.20.200.100
    Filename '/tutorial/nominal-image-leopard-dpu.rootfs.cpio.gz.u-boot'.
    Load address: 0x2100000
    Loading: #################################################################
             9.4 MiB/s
    done
    Bytes transferred = 42320355 (285c1e3 hex)
    ## Loading init Ramdisk from Legacy Image at 02100000 ...
    Image Name:   nominal-image-leopard-dpu.rootfs
    Created:      2011-04-05  23:00:00 UTC
    Image Type:   AArch64 Linux RAMDisk Image (uncompressed)
    Data Size:    42320291 Bytes = 40.4 MiB
    Load Address: 00000000
    Entry Point:  00000000
    Verifying Checksum ... OK
    ## Flattened Device Tree blob at 40000000
    Booting using the fdt blob at 0x40000000
    Working FDT set to 40000000
    Loading Ramdisk to 7935f000, end 7bbbb1a3 ... OK
    Loading Device Tree to 0000000079352000, end 000000007935e89c ... OK
    Working FDT set to 79352000
    
    Starting kernel ...
    
    [    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
    [    0.000000] Linux version 6.1.30-xilinx-v2023.2 (oe-user@oe-host) (aarch64-oe-linux-gcc (GCC) 13.2.0, GNU ld (GNU Binutils) 2.41.0.20231213) #1 SMP Fri Sep 22 10:41:01 UTC 2023
    ...
    [    2.945728] of_cfs_init
    [    2.948207] of_cfs_init: OK
    [    2.952210] ALSA device list:
    [    2.955177]   No soundcards found.
    [    2.974513] mmc0: SDHCI controller on ff170000.mmc [ff170000.mmc] using ADMA 64-bit
    [    2.982998] Freeing unused kernel memory: 2176K
    [    2.987664] Run /init as init process
    [    3.004971] systemd[1]: System time is further ahead than 15y after build time, resetting clock to build time.
    [    3.020050] systemd[1]: systemd 254.4^ running in system mode (-PAM -AUDIT -SELINUX -APPARMOR +IMA -SMACK +SECCOMP -GCRYPT -GNUTLS -OPENSSL +ACL +BLKID -CURL -ELFUTILS -FIDO2 -IDN2 -IDN -IPTC +KMOD -LIBCRYPTSETUP +LIBFDISK -PCRE2 -PWQUALITY -P11KIT -QRENCODE -TPM2 -BZIP2 -LZ4)
    [    3.052059] systemd[1]: Detected architecture arm64.
    
    Welcome to KP Labs DPU build-6a53a3e (KP Labs DPU)!
    
    [    3.068419] systemd[1]: Hostname set to <leopard-dpu>.
    [    3.073672] systemd[1]: Initializing machine ID from random generator.
    [    3.362495] systemd[1]: Queued start job for default target Multi-User System.
    ...
    
    KP Labs DPU build-6a53a3e leopard-dpu ttyPS0
    
    leopard-dpu login:
    
  11. Log in to DPU using root user

    leopard-dpu login: root
    root@leopard-dpu:~#
    

Summary

In this tutorial you’ve built minimal Linux distribution for Leopard DPU using Yocto and XSA file prepared with platform configuration. After copying build artifacts to EGSE Host you’ve written necessary boot firmware to DPU boot flash. You’ve also prepared U-Boot script for booting from network and observed boot process in minicom terminal. Finally you’ve logged in to DPU and verified that Linux is running.