From 1a219805187d0fe1194e4d0214313cbbe3783f2e Mon Sep 17 00:00:00 2001 From: Salman Nabi Date: Wed, 18 Dec 2024 11:00:17 +0000 Subject: [PATCH] docs(arm): add initrd props to dtb at build time Document the ability of the FVP platform to boot a Linux Kernel as a preloaded image. A preloaded Linux Kernel can be booted in a normal flow as well as in RESET_TO_BL31. This is made possible by updating the device tree with initrd properties at build time. Change-Id: I4e1d8c24f82510d21b2afa06b429a18da4d623bd Signed-off-by: Salman Nabi --- docs/plat/arm/fvp/fvp-specific-configs.rst | 131 +++++++++++---------- 1 file changed, 71 insertions(+), 60 deletions(-) diff --git a/docs/plat/arm/fvp/fvp-specific-configs.rst b/docs/plat/arm/fvp/fvp-specific-configs.rst index 63b3c31cc..a7fac913b 100644 --- a/docs/plat/arm/fvp/fvp-specific-configs.rst +++ b/docs/plat/arm/fvp/fvp-specific-configs.rst @@ -73,85 +73,96 @@ 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 preloaded kernel image +-------------------------------- -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: +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 - 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 \ + 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 + :: + 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. - # 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=/ +Users can provide either ``INITRD_SIZE`` or ``INITRD_PATH`` to set the initrd +size value. ``INITRD_SIZE`` takes prioty over ``INITRD_PATH``. - # 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})) ) - - 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 with the following command: .. 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="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 + --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. + +Booting a preloaded kernel image - Reset to BL31 (Base FVP) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^