Merge changes I0396b597,I326f920f,I0437eec8,Ieadf01fc,I4e1d8c24, ... into integration

* changes:
  feat(fvp): set defaults for build commandline
  docs(arm): enable Linux boot from fip as BL33
  feat(arm): enable Linux boot from fip as BL33
  docs(fvp): update fvp build time options
  docs(arm): add initrd props to dtb at build time
  feat(arm): add initrd props to dtb at build time
This commit is contained in:
Manish Pandey 2025-03-04 17:13:46 +01:00 committed by TrustedFirmware Code Review
commit 183f2ea2fe
6 changed files with 138 additions and 66 deletions

View file

@ -1638,6 +1638,21 @@ endif #(NEED_BL2U)
# Expand build macros for the different images
ifeq (${NEED_FDT},yes)
$(eval $(call MAKE_DTBS,$(BUILD_PLAT)/fdts,$(FDT_SOURCES)))
ifneq (${INITRD_SIZE}${INITRD_PATH},)
ifndef INITRD_BASE
$(error INITRD_BASE must be set when inserting initrd properties to the DTB.)
endif
INITRD_SIZE ?= $(shell printf "0x%x\n" $$(stat -Lc %s $(INITRD_PATH)))
initrd_end = $(shell printf "0x%x\n" $$(expr $$(($(INITRD_BASE) + $(INITRD_SIZE)))))
define $(HW_CONFIG)-after +=
$(s)echo " INITRD $(HW_CONFIG)"
$(q)fdtput -t x $@ /chosen linux,initrd-start $(INITRD_BASE)
$(q)fdtput -t x $@ /chosen linux,initrd-end $(initrd_end)
endef
endif
endif #(NEED_FDT)
# Add Secure Partition packages

View file

@ -46,6 +46,16 @@ Arm FVP Platform Specific Build Options
is ``0``, which means the redistributor pages of all CPU cores are marked
as read and write.
- ``INITRD_SIZE`` : Enable the insertion of initrd properties to the device
tree blob at build time. Takes an initrd size value in hex format
- ``INITRD_PATH`` : Enable the insertion of initrd properties to the device tree
blob at build time. Takes a path to an initrd file. Can be used as an
alternative to ``INITRD_SIZE``. ``INITRD_SIZE`` takes precedence over
``INITRD_PATH`` if both values are provided.
- ``INITRD_BASE`` : Provide the preloaded initrd base address in memory (hex format).
--------------
*Copyright (c) 2019-2024, Arm Limited. All rights reserved.*
*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*

View file

@ -73,85 +73,122 @@ used:
The address provided to the FVP must match the ``EL3_PAYLOAD_BASE`` address
used when building TF-A.
Booting a preloaded kernel image (Base FVP)
-------------------------------------------
Booting a kernel image in BL33
------------------------------
The following example uses a simplified boot flow by directly jumping from the
TF-A to the Linux kernel, which will use a ramdisk as filesystem. This can be
useful if both the kernel and the device tree blob (DTB) are already present in
memory (like in FVP).
TF-A can boot a Linux kernel, which uses a ramdisk as a filesystem. The
required initrd properties are injected in to the device tree blob (DTB) at
build time.
For example, if the kernel is loaded at ``0x80080000`` and the DTB is loaded at
address ``0x82000000``, the firmware can be built like this:
Kernel image packaged in fip as a BL33 image
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A Linux kernel image can be packaged in the fip as a BL33 image and then
booted in TF-A.
For example, the firmware can be built as:
.. code:: shell
CROSS_COMPILE=aarch64-none-elf- \
make PLAT=fvp DEBUG=1 \
RESET_TO_BL31=1 \
ARM_LINUX_KERNEL_AS_BL33=1 \
PRELOADED_BL33_BASE=0x80080000 \
ARM_PRELOADED_DTB_BASE=0x82000000 \
ARM_LINUX_KERNEL_AS_BL33 \
BL33=<path-to-kernel-binary> \
INITRD_SIZE=0x8000000 \
all fip
Now, it is needed to modify the DTB so that the kernel knows the address of the
ramdisk. The following script generates a patched DTB from the provided one,
assuming that the ramdisk is loaded at address ``0x84000000``. Note that this
script assumes that the user is using a ramdisk image prepared for U-Boot, like
the ones provided by Linaro. If using a ramdisk without this header,the ``0x40``
offset in ``INITRD_START`` has to be removed.
The options ``INITRD_SIZE`` or ``INITRD_PATH`` triggers the insertion of initrd
properties in to the DTB. ``INITRD_BASE`` is also required but a default value
is set by the FVP platform.
.. code:: bash
The options available here are:
#!/bin/bash
::
# Path to the input DTB
KERNEL_DTB=<path-to>/<fdt>
# Path to the output DTB
PATCHED_KERNEL_DTB=<path-to>/<patched-fdt>
# Base address of the ramdisk
INITRD_BASE=0x84000000
# Path to the ramdisk
INITRD=<path-to>/<ramdisk.img>
INITRD_BASE: Set the initrd base address in memory. Defaults to 0x90000000 in FVP.
INITRD_SIZE: Set the initrd size in dec or hex format. Hex format must precede with '0x'.
INITRD_PATH: Provide an initrd path for the build time to determine its exact size.
# Skip uboot header (64 bytes)
INITRD_START=$(printf "0x%x" $((${INITRD_BASE} + 0x40)) )
INITRD_SIZE=$(stat -Lc %s ${INITRD})
INITRD_END=$(printf "0x%x" $((${INITRD_BASE} + ${INITRD_SIZE})) )
Users can provide either ``INITRD_SIZE`` or ``INITRD_PATH`` to set the initrd
size value. ``INITRD_SIZE`` takes prioty over ``INITRD_PATH``.
CHOSEN_NODE=$(echo \
"/ { \
chosen { \
linux,initrd-start = <${INITRD_START}>; \
linux,initrd-end = <${INITRD_END}>; \
}; \
};")
echo $(dtc -O dts -I dtb ${KERNEL_DTB}) ${CHOSEN_NODE} | \
dtc -O dtb -o ${PATCHED_KERNEL_DTB} -
And the FVP binary can be run with the following command:
Now the fvp binary can be run as:
.. code:: shell
<path-to>/FVP_Base_AEMv8A-AEMv8A \
-C pctl.startup=0.0.0.0 \
-C bp.secure_memory=1 \
-C cluster0.NUM_CORES=4 \
-C cluster1.NUM_CORES=4 \
-C cache_state_modelled=1 \
-C cluster0.cpu0.RVBAR=0x04001000 \
-C cluster0.cpu1.RVBAR=0x04001000 \
-C cluster0.cpu2.RVBAR=0x04001000 \
-C cluster0.cpu3.RVBAR=0x04001000 \
-C cluster1.cpu0.RVBAR=0x04001000 \
-C cluster1.cpu1.RVBAR=0x04001000 \
-C cluster1.cpu2.RVBAR=0x04001000 \
-C cluster1.cpu3.RVBAR=0x04001000 \
--data cluster0.cpu0="<path-to>/bl31.bin"@0x04001000 \
--data cluster0.cpu0="<path-to>/<patched-fdt>"@0x82000000 \
-C bp.secureflashloader.fname=<path-to>/bl1.bin \
-C bp.flashloader0.fname=<path-to>/fip.bin \
--data cluster0.cpu0="<path-to>/<initrd.bin>"@0x90000000
.. note::
Providing a higher value for an initrd size than the actual size of the file
is supported but it will trigger a non-breaking "Initramfs unpacking failed"
error by the kernel at runtime. This error can be ignored because initrd's
can be stacked one after another, when the kernel unpacks the first initrd it
looks for another in the extra space which it won't find, hence the error.
Preloaded kernel image - Normal flow
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following example uses a simplified boot flow to boot a Linux kernel
using TF-A. This can be useful if the kernel is already present in memory
(like in FVP).
For example, if the kernel is loaded at ``0x80080000`` the firmware can be
built like this:
.. code:: shell
make PLAT=fvp DEBUG=1 \
ARM_LINUX_KERNEL_AS_BL33=1 \
PRELOADED_BL33_BASE=0x80080000 \
INITRD_SIZE=0x8000000 \
all fip
Now the FVP binary can be run with the following command:
.. code:: shell
<path-to>/FVP_Base_AEMv8A-AEMv8A \
-C bp.secureflashloader.fname=<path-to>/bl1.bin \
-C bp.flashloader0.fname=<path-to>/fip.bin \
--data cluster0.cpu0="<path-to>/<kernel-binary>"@0x80080000 \
--data cluster0.cpu0="<path-to>/<ramdisk.img>"@0x84000000
--data cluster0.cpu0="<path-to>/<initrd.bin>"@0x90000000
Preloaded kernel image - Reset to BL31
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We can also boot a Linux kernel by jumping directly to BL31 ``RESET_TO_BL31=1``.
This requires preloading a DTB into memory. We can inject the initrd start and
end properties into the DTB (HW_CONFIG) at build time which is then stored by
TF-A in ``build/fvp/<build-type>/fdts/`` directory.
For example, we can build the firmware as:
.. code:: shell
make PLAT=fvp DEBUG=1 \
RESET_TO_BL31=1 \
ARM_LINUX_KERNEL_AS_BL33=1 \
PRELOADED_BL33_BASE=0x80080000 \
ARM_PRELOADED_DTB_BASE=0x87F00000 \
INITRD_BASE=0x88000000 \
INITRD_PATH=<path-to>/initrd.bin
Now we can run the binary as:
.. code:: shell
<path-to>/FVP_Base_AEMv8A-AEMv8A \
-C cluster0.NUM_CORES=4 \
-C cluster0.cpu0.RVBAR=0x04001000 \
-C cluster0.cpu1.RVBAR=0x04001000 \
-C cluster0.cpu2.RVBAR=0x04001000 \
-C cluster0.cpu3.RVBAR=0x04001000 \
--data cluster0.cpu0="<path-to>/bl31.bin"@0x04001000 \
--data cluster0.cpu0="<path-to>/<kernel-binary>"@0x80080000 \
--data cluster0.cpu0="<path-to>/<initrd.bin>"@0x88000000 \
--data cluster0.cpu0="<path-to>/fdts/fvp-base-gicv3-psci.dtb"@87F00000
Obtaining the Flattened Device Trees
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -604,6 +604,7 @@ $(DPRE): $(2) | $$$$(@D)/
$(DOBJ): $(DPRE) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " DTC $$<"
$$(q)$($(ARCH)-dtc) $$(DTC_FLAGS) -d $(DTBDEP) -o $$@ $$<
$$($$@-after)
-include $(DTBDEP)
-include $(DTSDEP)

View file

@ -367,6 +367,19 @@ FVP_HW_CONFIG_DTS := fdts/${FVP_DT_PREFIX}.dts
FDT_SOURCES += ${FVP_HW_CONFIG_DTS}
$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(FVP_HW_CONFIG_DTS)))
HW_CONFIG := ${FVP_HW_CONFIG}
# Set default initrd base 128MiB offset of the default kernel address in FVP
INITRD_BASE ?= 0x90000000
# Kernel base address supports Linux kernels before v5.7
# DTB base 1MiB before normal base kernel address in FVP (0x88000000)
ifeq (${ARM_LINUX_KERNEL_AS_BL33},1)
PRELOADED_BL33_BASE ?= 0x80080000
ifeq (${RESET_TO_BL31},1)
ARM_PRELOADED_DTB_BASE ?= 0x87F00000
endif
endif
ifeq (${TRANSFER_LIST}, 0)
FDT_SOURCES += $(addprefix plat/arm/board/fvp/fdts/, \
@ -419,7 +432,6 @@ ifeq (${TRANSFER_LIST}, 1)
include lib/transfer_list/transfer_list.mk
ifeq ($(RESET_TO_BL31), 1)
HW_CONFIG := ${FVP_HW_CONFIG}
FW_HANDOFF_SIZE := 20000
TRANSFER_LIST_DTB_OFFSET := 0x20

View file

@ -108,9 +108,6 @@ ifeq (${ARM_LINUX_KERNEL_AS_BL33},1)
$(error ARM_LINUX_KERNEL_AS_BL33 is only available if RESET_TO_SP_MIN=1.)
endif
endif
ifndef PRELOADED_BL33_BASE
$(error PRELOADED_BL33_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.)
endif
ifeq (${RESET_TO_BL31},1)
ifndef ARM_PRELOADED_DTB_BASE
$(error ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used with RESET_TO_BL31.)