Upgrading to Petalinux 2021

The latest Petalinux 2021.1 from Xilinx comes with a few improvements and changes that can also trip the unsuspecting user.

Introduction

In this post we will target the upgrade from Petalinux 2020.2 to 2021.1 focusing on the process and the changes that make the upgrade as seamless as can be.

Upgrading

In our experience, upgrading from version to version has rarely been a trouble free endeavor. Some of the changes involve aligning with the underlying Yocto system and often modifications in Petalinux itself. Our suggested update path is to not update from a previous project, but rather create a new 2021.1 project and configure it from scratch, using data from the old project. While this sounds tedious and slow, it will save valuable time over the alternative. The process would be summarized as follows:

  • Open the older project in a parallel window.
  • Create Petalinux project, petalinux-create -t project -n <name> –template zynqMP
  • Import hardware description .xsa, petalinux-config –get-hw-description <path-to-xsa>
  • Compare the older project menuconfig settings and apply to the new project where necessary.
  • Open the rootfs menuconfig, petalinux-config -c rootfs
  • Again compare to the old project’s rootfs.
  • Lastly, set the new configuration items.

Changes

The most substantial change in 2021.1 at first sight is the U-Boot script configuration. As you recall, in 2020.2 this was done as a hand-modifiable script under the u-boot recipe, that required changing several offsets and sizes to align with the bootable media formatting.

MAC address

The Ethernet MAC address is now defined as the invalid ff:ff:ff:ff:ff:ff address. If defined, it will be set to the device tree. If not defined, it will attempt to read it from EEPROM, and failing that, it will be set to a random address.

Bootable storage

The Advanced bootable images storage settings was removed from the Subsystem AUTO settings, replaced by…

U-Boot script

The newly added u-boot script configuration, in which it defines the offsets in the boot.scr script and other settings that used to be the above image storage settings.

Here’s the QSPI image offsets options:

(0x3F00000) QSPI/OSPI Kernel offset (NEW)
(0x1D00000) QSPI/OSPI Kernel size (NEW)
(0x5D00000) QSPI/OSPI Ramdisk offset (NEW)
(0x1D00000) QSPI/OSPI Ramdisk size (NEW)
(0x3F80000) QSPI/OSPI fit image offset (NEW)
(0x3F00000) QSPI/OSPI fit image size (NEW)

These offsets and sizes will be used to generate the U-Boot boot.scr. There’s additional options for JTAG/DDR and NAND image offsets.

U-Boot

I had to configure U-Boot (petalinux-config -c u-boot) to disable “ARM Architecture -> Reading MAC address from EEPROM” or it would attempt to read from a non-existent flash on this hardware. Also changed the “Boot Script Offset” to match QSPI partition for the boot.scr. Ended up looking like this:

# CONFIG_ZYNQ_MAC_IN_EEPROM is not set
CONFIG_BOOTDELAY=5
CONFIG_BOOT_SCRIPT_OFFSET=0x2580000
CONFIG_ENV_OFFSET=0x2600000

Adding U-Boot environment commands to Petalinux

The Linux commands to access and modify the U-Boot’s environment are fw_printenv and fw_setenv. They are built as part of the U-Boot codebase and require special handling in 2021.1, due to their recipe being missing in Yocto meta layer. I had to copy the entire recipe from 2020.2 (copied in turn from 2019.2) and modify it slightly for 2021.1.

  • Create recipes-bsp/u-boot-fw-utils
  • Copy u-boot-fw-utils_2019.07.bb and u-boot-common.inc from 2020.2 components/yocto/layers/meta/recipes-bsp/u-boot to the u-boot-fw-utils directory
  • Copy u-boot-fw-utils_%.bbappend to u-boot-fw-utils
  • Modify u-boot-fw-utils_%.bbappend as below
  • Add a u-boot-fw-utils subdirectory with the fw_env.config file

The u-boot-fw-utils looks like this:

FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"

SRCREV = "0b0c6af38738f2c132cfd41a240889acaa031c8f"

SRC_URI += "git://github.com/Xilinx/u-boot-xlnx.git;protocol=https"
SRC_URI += " file://fw_env.config"

# remove patches introduced in older version
SRC_URI_remove = "file://0001-CVE-2019-13103.patch"
SRC_URI_remove = "file://0002-CVE-2019-13104.patch"
SRC_URI_remove = "file://0003-CVE-2019-13105.patch"
SRC_URI_remove = "file://0004-CVE-2019-13106.patch"
SRC_URI_remove = "file://0005-CVE-2019-14192-14193-14199.patch"
SRC_URI_remove = "file://0006-CVE-2019-14197-14200-14201-14202-14203-14204.patch"
SRC_URI_remove = "file://0007-CVE-2019-14194-14198.patch"
SRC_URI_remove = "file://0008-CVE-2019-14195.patch"
SRC_URI_remove = "file://0009-CVE-2019-14196.patch"

do_install_append() {
  install -d ${D}${sysconfdir}
  install -m 0644 ${WORKDIR}/fw_env.config ${D}${sysconfdir}/fw_env.config
}

PACKAGE_ARCH = "${MACHINE_ARCH}"

The fw_env.config looks like this:

# NOR example
# MTD device name	Device offset	Env. size	Flash sector size	Number of sectors
/dev/mtd2		0x0000		0x80000		0x4000

$ tree
├── u-boot-common.inc
├── u-boot-fw-utils
│   └── fw_env.config
├── u-boot-fw-utils_2019.07.bb
└── u-boot-fw-utils_%.bbappend

Gotchas

No ‘/dev’ on rootfs

Building the project and loading it on the hardware initially throws a “There’s no ‘/dev’ on rootfs”. This happens due to using a small RAM disk for rootfs built-in the FIT image by default, intended to be a temporary filesystem in use before loading the real filesystem in flash, i.e. in eMMC. For users that don’t need this, the workaround is to rename the INITRD image name to petalinux-image-minimal.

petalinux-config -> Image packaging configuration -> INITRAMFS/INITRD Image name

Product version

The /etc/petalinux/version and product do not take the values set in petalinux-config; instead they read 2021.1 and zynqmp-generic respectively. To fix this, this workaround (AR#76764) is needed.

In this file /project-spec/meta-user/conf/petalinuxbsp.conf set the values to apply:

PETALINUX_PRODUCT_pn-base-files-plnx = "zynqmp-test"
PETALINUX_VERSION_pn-base-files-plnx = "2021.1.15"

Clean the base-files-plnx sstate cache and rebuild the base-files-plnx recipes:

$ petalinux-build -c base-files-plnx -x cleansstate
$ petalinux-build -x cleansstate
$ petalinux-build

Initscripts output

In 2021.1 the initscripts output don’t actually produce any output to the console, even though they do run. Xilinx admits this is an issue and provided a workaround.

Create a sysvinit directory and recipe.

$ mkdir -p project-spec/meta-user/recipes-core/sysvinit
$ touch -p project-spec/meta-user/recipes-core/sysvinit/sysvinit_%.bbappend

Disable bootlog deamon in do_install bitbake task.

do_install_append () {
	install -d ${D}${sysconfdir}/default
	echo "BOOTLOGD_ENABLE=N" >> ${D}${sysconfdir}/default/bootlogd
}

Clean the sysvinit and rootfs sstate cache and rebuild it.

$ petalinux-build -c sysvinit -x cleansstate; petalinux-build -x cleansstate
$ petalinux-build

Fix USB support

USB is plainly broken in 2021.1, and this patch from @aravinds fortunately fixes it.

“Deselect the PIPE clock when operating in USB2.0 only mode. Due to USB controller getting reset, the pipe clock control register was by default selecting the Serdes as the clock source. This was causing the issue when the Serdes is disabled and only USB2.0 mode is selected.”

https://forums.xilinx.com/t5/Embedded-Linux/ZynqMP-Yocto-no-USB-with-2021-1/m-p/1269990

Conclusion

There were a few changes in Petalinux 2021.1 that caused a few headaches but are better explained in the datasheet than previous upgrades. It’s highly recommended to read the section “Migration” from ug1144 to get more insight into these changes. In this post we summarized them and provided workarounds.

QSPI boot then loading from MMC

The flexibility of U-Boot distro boot feature is exercised in this post, where we configure the target to boot from...

Previous
Temperature sensor

In this post we will look at controlling a temperature sensor IC over I2C from Linux, and pre-setting its critical...

Next