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 <salman.nabi@arm.com>
diff --git a/docs/plat/arm/fvp/fvp-specific-configs.rst b/docs/plat/arm/fvp/fvp-specific-configs.rst
index 63b3c31..a7fac91 100644
--- a/docs/plat/arm/fvp/fvp-specific-configs.rst
+++ b/docs/plat/arm/fvp/fvp-specific-configs.rst
@@ -73,85 +73,96 @@
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>/<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>
+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
<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>/<kernel-binary>"@0x80080000 \
- --data cluster0.cpu0="<path-to>/<ramdisk.img>"@0x84000000
+ --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.
+
+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/<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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^