Skip to content

Commit

Permalink
elfloader: use helper struct for DTB loading
Browse files Browse the repository at this point in the history
Signed-off-by: Axel Heider <axel.heider@hensoldt.net>
  • Loading branch information
Axel Heider committed Feb 26, 2024
1 parent 24a7eca commit 60909da
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 52 deletions.
13 changes: 10 additions & 3 deletions elfloader-tool/include/elfloader_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ typedef uintptr_t vaddr_t;
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
#define NULL ((void *)0)


/*
* Information about a DTB we are loading.
*/
typedef struct {
paddr_t phys_base;
size_t size;
} dtb_info_t;

/*
* Information about an image we are loading.
*/
Expand Down Expand Up @@ -93,9 +102,7 @@ int load_images(
struct image_info *user_info,
unsigned int max_user_images,
unsigned int *num_images,
void const *bootloader_dtb,
void const **chosen_dtb,
size_t *chosen_dtb_size);
dtb_info_t *dtb_info);

/* Platform functions */
void platform_init(void);
Expand Down
10 changes: 7 additions & 3 deletions elfloader-tool/src/arch-arm/smp_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ static volatile int non_boot_lock = 0;

void arm_disable_dcaches(void);

extern void const *dtb;
extern uint32_t dtb_size;
extern dtb_info_t dtb_info;

/* Entry point for all CPUs other than the initial. */
void non_boot_main(void)
Expand Down Expand Up @@ -58,10 +57,15 @@ void non_boot_main(void)
arm_enable_mmu();
}

/* Usually DTBs are much less than 4 GiB, so this cast should be fine. */
uint32_t dtb_size_u32 = (uint32_t)dtb_info.size;

/* Jump to the kernel. */
((init_arm_kernel_t)kernel_info.virt_entry)(user_info.phys_region_start,
user_info.phys_region_end, user_info.phys_virt_offset,
user_info.virt_entry, (paddr_t)dtb, dtb_size);
user_info.virt_entry,
(word_t)dtb_info.phys_base,
(word_t)dtb_size_u32);

printf("AP Kernel returned back to the elf-loader.\n");
abort();
Expand Down
37 changes: 25 additions & 12 deletions elfloader-tool/src/arch-arm/sys_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ char core_stack_alloc[CONFIG_MAX_NUM_NODES][BIT(PAGE_BITS)];

struct image_info kernel_info;
struct image_info user_info;
void const *dtb;
size_t dtb_size;
dtb_info_t dtb_info;

extern void finish_relocation(int offset, void *_dynamic, unsigned int total_offset);
void continue_boot(int was_relocated);
Expand Down Expand Up @@ -101,8 +100,6 @@ void relocate_below_kernel(void)
*/
void main(UNUSED void *arg)
{
void *bootloader_dtb = NULL;

/* initialize platform to a state where we can print to a UART */
if (initialise_devices()) {
printf("ERROR: Did not successfully return from initialise_devices()\n");
Expand All @@ -116,13 +113,22 @@ void main(UNUSED void *arg)
print_cpuid();
printf(" paddr=[%p..%p]\n", _text, _end - 1);

/* Assume by default, that no DTB is provided from a previous
* bootloader stage. Since 0 is a valid physical address, the size
* field is used to indicate if the address is valid. The value -1
* is to be used if the actual size is not known.
*/
dtb_info.phys_base = 0;
dtb_info.size = 0;

#if defined(CONFIG_IMAGE_UIMAGE)

/* U-Boot passes a DTB. Ancient bootloaders may pass atags. When booting via
* bootelf argc is NULL.
*/
if (arg && (DTB_MAGIC == *(uint32_t *)arg)) {
bootloader_dtb = arg;
dtb_info.phys_base = (paddr_t)arg;
dtb_info.size = (size_t)(-1);
}

#elif defined(CONFIG_IMAGE_EFI)
Expand All @@ -132,20 +138,24 @@ void main(UNUSED void *arg)
abort();
}

bootloader_dtb = efi_get_fdt();
/* For EFI, the DTB address is not supposed to be 0. */
void *efi_dtb = efi_get_fdt();
if (efi_dtb) {
dtb_info.phys_base = (paddr_t)efi_dtb;
dtb_info.size = (size_t)(-1);
}

#endif

if (bootloader_dtb) {
printf(" dtb=%p\n", bootloader_dtb);
if (0 != dtb_info.size) {
printf(" dtb=%p\n", dtb_info.phys_base);
} else {
printf("No DTB passed in from boot loader.\n");
}

/* Unpack ELF images into memory. */
unsigned int num_apps = 0;
int ret = load_images(&kernel_info, &user_info, 1, &num_apps,
bootloader_dtb, &dtb, &dtb_size);
int ret = load_images(&kernel_info, &user_info, 1, &num_apps, &dtb_info);
if (0 != ret) {
printf("ERROR: image loading failed\n");
abort();
Expand Down Expand Up @@ -221,12 +231,15 @@ void continue_boot(int was_relocated)
printf("Jumping to kernel-image entry point...\n\n");
}

/* Usually DTBs are much less than 4 GiB, so this cast should be fine. */
uint32_t dtb_size_u32 = (uint32_t)dtb_info.size;

((init_arm_kernel_t)kernel_info.virt_entry)(user_info.phys_region_start,
user_info.phys_region_end,
user_info.phys_virt_offset,
user_info.virt_entry,
(word_t)dtb,
dtb_size);
(word_t)dtb_info.phys_base,
(word_t)dtb_size_u32);

/* We should never get here. */
printf("ERROR: Kernel returned back to the ELF Loader\n");
Expand Down
22 changes: 14 additions & 8 deletions elfloader-tool/src/arch-riscv/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ unsigned long l2pt_elf[PTES_PER_PT] __attribute__((aligned(4096)));
char elfloader_stack_alloc[BIT(CONFIG_KERNEL_STACK_BITS)];

/* first HART will initialise these */
void const *dtb = NULL;
size_t dtb_size = 0;
dtb_info_t dtb_info;

/*
* overwrite the default implementation for abort()
Expand Down Expand Up @@ -194,10 +193,12 @@ static int run_elfloader(UNUSED int hart_id, void *bootloader_dtb)
{
int ret;

dtb_info.phys_base = (paddr_t)bootloader_dtb;
dtb_info.size = (size_t)(-1);

/* Unpack ELF images into memory. */
unsigned int num_apps = 0;
ret = load_images(&kernel_info, &user_info, 1, &num_apps,
bootloader_dtb, &dtb, &dtb_size);
ret = load_images(&kernel_info, &user_info, 1, &num_apps, &dtb_info);
if (0 != ret) {
printf("ERROR: image loading failed, code %d\n", ret);
return -1;
Expand Down Expand Up @@ -238,13 +239,16 @@ static int run_elfloader(UNUSED int hart_id, void *bootloader_dtb)
printf("Enabling MMU and paging\n");
enable_virtual_memory();

/* Usually DTBs are much less than 4 GiB, so this cast should be fine. */
uint32_t dtb_size_u32 = (uint32_t)dtb_info.size;

printf("Jumping to kernel-image entry point...\n\n");
((init_riscv_kernel_t)kernel_info.virt_entry)(user_info.phys_region_start,
user_info.phys_region_end,
user_info.phys_virt_offset,
user_info.virt_entry,
(word_t)dtb,
dtb_size
(word_t)dtb_info.phys_base,
(word_t)dtb_size_u32
#if CONFIG_MAX_NUM_NODES > 1
,
hart_id,
Expand All @@ -271,15 +275,17 @@ void secondary_entry(int hart_id, int core_id)

enable_virtual_memory();

/* Usually DTBs are much less than 4 GiB, so this cast should be fine. */
uint32_t dtb_size_u32 = (uint32_t)dtb_info.size;

/* If adding or modifying these parameters you will need to update
the registers in head.S */
((init_riscv_kernel_t)kernel_info.virt_entry)(user_info.phys_region_start,
user_info.phys_region_end,
user_info.phys_virt_offset,
user_info.virt_entry,
(word_t)dtb,
dtb_size,
(word_t)dtb_info.phys_base,
(word_t)dtb_size_u32,
hart_id,
core_id
);
Expand Down
53 changes: 27 additions & 26 deletions elfloader-tool/src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,9 +384,7 @@ int load_images(
struct image_info *user_info,
unsigned int max_user_images,
unsigned int *num_images,
void const *bootloader_dtb,
void const **chosen_dtb,
size_t *chosen_dtb_size)
dtb_info_t *dtb_info)
{
int ret;
uint64_t kernel_phys_start, kernel_phys_end;
Expand Down Expand Up @@ -434,31 +432,32 @@ int load_images(

#ifdef CONFIG_ELFLOADER_INCLUDE_DTB

if (chosen_dtb) {
printf("Looking for DTB in CPIO archive...");
/*
* Note the lack of newline in the above printf(). Normally one would
* have an fflush(stdout) here to ensure that the message shows up on a
* line-buffered stream (which is the POSIX default on terminal
* devices). But we are freestanding (on the "bare metal"), and using
* our own unbuffered printf() implementation.
*/
dtb = cpio_get_file(cpio, cpio_len, "kernel.dtb", NULL);
if (dtb == NULL) {
printf("not found.\n");
} else {
has_dtb_cpio = 1;
printf("found at %p.\n", dtb);
}
printf("Looking for DTB in CPIO archive...");
/*
* Note the lack of newline in the above printf(). Normally one would
* have an fflush(stdout) here to ensure that the message shows up on a
* line-buffered stream (which is the POSIX default on terminal
* devices). But we are freestanding (on the "bare metal"), and using
* our own unbuffered printf() implementation.
*/
dtb = cpio_get_file(cpio, cpio_len, "kernel.dtb", NULL);
if (dtb == NULL) {
printf("not found.\n");
} else {
has_dtb_cpio = 1;
printf("found at %p.\n", dtb);
}

#endif /* CONFIG_ELFLOADER_INCLUDE_DTB */

if (chosen_dtb && !dtb && bootloader_dtb) {
/* Use the bootloader's DTB if we are not using the DTB in the CPIO
* archive.
*/
dtb = bootloader_dtb;
/* If we don't have a DTB here, use the one a bootloader might have
* provided. Since 0 is a valid physical address, the size field is used to
* determin if the address is valid. A size of -1 indicates, that the actual
* size is not known - which is usually the case, because a bootloader often
* just passes an address.
*/
if (!dtb && (dtb_info->size > 0)) {
dtb = (void const *)dtb_info->phys_base;
}

/*
Expand Down Expand Up @@ -489,9 +488,11 @@ int load_images(

printf("Loaded DTB from %p.\n", dtb);
printf(" paddr=[%p..%p]\n", dtb_phys_start, dtb_phys_end - 1);
*chosen_dtb = (void *)dtb_phys_start;
*chosen_dtb_size = dtb_size;
dtb_info->phys_base = dtb_phys_start;
dtb_info->size = dtb_size;
} else {
dtb_info->phys_base = 0;
dtb_info->size = 0;
next_phys_addr = ROUND_UP(kernel_phys_end, PAGE_BITS);
}

Expand Down

0 comments on commit 60909da

Please sign in to comment.