diff --git a/Makefile b/Makefile index 120ba5b19..7fd8d0c85 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/docs/plat/arm/fvp/fvp-build-options.rst b/docs/plat/arm/fvp/fvp-build-options.rst index b0359fa91..79dc0dcf0 100644 --- a/docs/plat/arm/fvp/fvp-build-options.rst +++ b/docs/plat/arm/fvp/fvp-build-options.rst @@ -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.* diff --git a/docs/plat/arm/fvp/fvp-specific-configs.rst b/docs/plat/arm/fvp/fvp-specific-configs.rst index 63b3c31cc..0f51e4b35 100644 --- a/docs/plat/arm/fvp/fvp-specific-configs.rst +++ b/docs/plat/arm/fvp/fvp-specific-configs.rst @@ -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= \ + 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 the output DTB - PATCHED_KERNEL_DTB=/ - # Base address of the ramdisk - INITRD_BASE=0x84000000 - # Path to the ramdisk - INITRD=/ + 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 /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="/bl31.bin"@0x04001000 \ - --data cluster0.cpu0="/"@0x82000000 \ + -C bp.secureflashloader.fname=/bl1.bin \ + -C bp.flashloader0.fname=/fip.bin \ + --data cluster0.cpu0="/"@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 + + /FVP_Base_AEMv8A-AEMv8A \ + -C bp.secureflashloader.fname=/bl1.bin \ + -C bp.flashloader0.fname=/fip.bin \ --data cluster0.cpu0="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 + --data cluster0.cpu0="/"@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//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=/initrd.bin + +Now we can run the binary as: + +.. code:: shell + + /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="/bl31.bin"@0x04001000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/fdts/fvp-base-gicv3-psci.dtb"@87F00000 Obtaining the Flattened Device Trees ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk index b1b299cd9..aa1675193 100644 --- a/make_helpers/build_macros.mk +++ b/make_helpers/build_macros.mk @@ -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) diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 1dd0b4930..7bd2a1dae 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -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 diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index 580ef5fa1..6d59bae63 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -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.)