mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-07 21:33:54 +00:00
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>
This commit is contained in:
parent
1c08ff3277
commit
1a21980518
1 changed files with 71 additions and 60 deletions
|
@ -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>/<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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
Loading…
Add table
Reference in a new issue