arch/arm: Enable FIT payloads
Implements fit_payload_arch for the arm (aarch32) architecture, so that FIT images can be used. The implementation is very similar to the existing implementations for arm64 and riscv, and has mostly been lifted from these other ports. TEST: Booted Beaglebone Black (in progress port, to be submitted soon!) with a FIT image containing a 5.4 kernel, dtb and initramfs. Change-Id: I6b50c6f06b83c00a5b3622b5bbafe67130b6d233 Signed-off-by: Sam Lewis <sam.vr.lewis@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/44377 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
parent
3b9041a563
commit
cb287987a1
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
## Supported architectures
|
## Supported architectures
|
||||||
|
|
||||||
|
* aarch32
|
||||||
* aarch64
|
* aarch64
|
||||||
* riscv
|
* riscv
|
||||||
|
|
||||||
|
@ -26,6 +27,13 @@ The section must be named in order to be found by the FIT parser:
|
||||||
|
|
||||||
The FIT parser needs architecure support.
|
The FIT parser needs architecure support.
|
||||||
|
|
||||||
|
### aarch32
|
||||||
|
The source code can be found in `src/arch/arm/fit_payload.c`.
|
||||||
|
|
||||||
|
On aarch32 the kernel (a section named 'kernel') must be in **Image**
|
||||||
|
format and it needs a devicetree (a section named 'fdt') to boot.
|
||||||
|
The kernel will be placed close to "*DRAMSTART*".
|
||||||
|
|
||||||
### aarch64
|
### aarch64
|
||||||
The source code can be found in `src/arch/arm64/fit_payload.c`.
|
The source code can be found in `src/arch/arm64/fit_payload.c`.
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ config PAYLOAD_ELF
|
||||||
|
|
||||||
config PAYLOAD_FIT
|
config PAYLOAD_FIT
|
||||||
bool "A FIT payload"
|
bool "A FIT payload"
|
||||||
depends on ARCH_ARM64 || ARCH_RISCV
|
depends on ARCH_ARM64 || ARCH_RISCV || ARCH_ARM
|
||||||
select PAYLOAD_FIT_SUPPORT
|
select PAYLOAD_FIT_SUPPORT
|
||||||
help
|
help
|
||||||
Select this option if you have a payload image (a FIT file) which
|
Select this option if you have a payload image (a FIT file) which
|
||||||
|
@ -97,7 +97,7 @@ config PAYLOAD_FIT_SUPPORT
|
||||||
bool "FIT support"
|
bool "FIT support"
|
||||||
default n
|
default n
|
||||||
default y if PAYLOAD_LINUX && (ARCH_ARM || ARCH_ARM64 || ARCH_RISCV)
|
default y if PAYLOAD_LINUX && (ARCH_ARM || ARCH_ARM64 || ARCH_RISCV)
|
||||||
depends on ARCH_ARM64 || ARCH_RISCV
|
depends on ARCH_ARM64 || ARCH_RISCV || ARCH_ARM
|
||||||
select FLATTENED_DEVICE_TREE
|
select FLATTENED_DEVICE_TREE
|
||||||
help
|
help
|
||||||
Select this option if your payload is of type FIT.
|
Select this option if your payload is of type FIT.
|
||||||
|
|
|
@ -119,6 +119,7 @@ ramstage-y += memset.S
|
||||||
ramstage-y += memcpy.S
|
ramstage-y += memcpy.S
|
||||||
ramstage-y += memmove.S
|
ramstage-y += memmove.S
|
||||||
ramstage-y += clock.c
|
ramstage-y += clock.c
|
||||||
|
ramstage-$(CONFIG_PAYLOAD_FIT_SUPPORT) += fit_payload.c
|
||||||
|
|
||||||
rmodules_arm-y += memset.S
|
rmodules_arm-y += memset.S
|
||||||
rmodules_arm-y += memcpy.S
|
rmodules_arm-y += memcpy.S
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <bootmem.h>
|
||||||
|
#include <program_loading.h>
|
||||||
|
#include <fit.h>
|
||||||
|
#include <symbols.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place the region in free memory range.
|
||||||
|
*/
|
||||||
|
static bool fit_place_mem(const struct range_entry *r, void *arg)
|
||||||
|
{
|
||||||
|
struct region *region = arg;
|
||||||
|
resource_t start;
|
||||||
|
|
||||||
|
if (range_entry_tag(r) != BM_MEM_RAM)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Linux 4.15 doesn't like 4KiB alignment. Align to 1 MiB for now. */
|
||||||
|
start = ALIGN_UP(MAX(region->offset, range_entry_base(r)), 1 * MiB);
|
||||||
|
|
||||||
|
if (start + region->size < range_entry_end(r)) {
|
||||||
|
region->offset = (size_t)start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool fit_payload_arch(struct prog *payload, struct fit_config_node *config,
|
||||||
|
struct region *kernel,
|
||||||
|
struct region *fdt,
|
||||||
|
struct region *initrd)
|
||||||
|
{
|
||||||
|
void *arg = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The kernel ARM documentation recommends loading the kernel above 32MiB
|
||||||
|
* in order to avoid the need to need to relocate prior to decompression.
|
||||||
|
*/
|
||||||
|
kernel->offset = (uintptr_t)_dram + 32 * MiB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The code assumes that bootmem_walk provides a sorted list of memory
|
||||||
|
* regions, starting from the lowest address.
|
||||||
|
* The order of the calls here doesn't matter, as the placement is
|
||||||
|
* enforced in the called functions.
|
||||||
|
* For details check code on top.
|
||||||
|
*/
|
||||||
|
if (!bootmem_walk(fit_place_mem, kernel))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Mark as reserved for future allocations. */
|
||||||
|
bootmem_add_range(kernel->offset, kernel->size, BM_MEM_PAYLOAD);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To ensure the fdt is not overwritten by the kernel decompressor, place
|
||||||
|
* the fdt above the 128 MB from the start of RAM, as recommended by the
|
||||||
|
* kernel documentation.
|
||||||
|
*/
|
||||||
|
fdt->offset = (uintptr_t)_dram + 128 * MiB;
|
||||||
|
|
||||||
|
if (!bootmem_walk(fit_place_mem, fdt))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Mark as reserved for future allocations. */
|
||||||
|
bootmem_add_range(fdt->offset, fdt->size, BM_MEM_PAYLOAD);
|
||||||
|
|
||||||
|
/* Place INITRD */
|
||||||
|
if (config->ramdisk) {
|
||||||
|
initrd->offset = fdt->offset + fdt->size;
|
||||||
|
|
||||||
|
if (!bootmem_walk(fit_place_mem, initrd))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Mark as reserved for future allocations. */
|
||||||
|
bootmem_add_range(initrd->offset, initrd->size, BM_MEM_PAYLOAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Kernel expects FDT as argument */
|
||||||
|
arg = (void *)fdt->offset;
|
||||||
|
|
||||||
|
prog_set_entry(payload, (void *)kernel->offset, arg);
|
||||||
|
|
||||||
|
bootmem_dump_ranges();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
Loading…
Reference in New Issue