Skip to content

Commit

Permalink
elfloader: Exit UEFI boot services very early
Browse files Browse the repository at this point in the history
UEFI is an operating system that hides as a bootloader. UEFI is in
control of the machine as long as we didn't call exit_boot_services.

For instance, UEFI may set up timers to interrupt us while we're
fiddling with hardware and UEFI is fiddling with hardware itself and
UEFI may be fiddling with the exact same hardware that we are
fiddling with, while we're being preempted. That is not good.

The previous state of ELFloader is that before exiting UEFI boot
services, we already called platform_init() in main(), which may
fiddle around with all kinds of hardware. Thus, we should have
already exited UEFI boot services when main() is called.

Note that exit_boot_services now still executes on the UEFI stack
(since we switch the stack in _start()). But so did e.g. the
clear_bss() function. I don't see a problem here.

It's more a question the other way around: Previously, we called
into UEFI with exit_boot_services on our own, potentially too small,
stack. Do we have enough space for UEFI to execute? How are we
supposed to know that? The UEFI implementation can change, so we
can never be sure. But it would be unreasonable for UEFI to start
us with a stack that is too small to call any UEFI API, including
exit_boot_services. So we can safely assume that there is enough
space when using the UEFI stack (since our use of stack to this
point is minimal).

Also, mask all exceptions until we are about to enter the kernel.
We do not want to run with whatever state the bootloader set us up
before, do we? We only re-enable the asyncs and debugs; interrupts
and FIQs are still masked when entering the kernel. What would we
gain from that? We don't expect any. Asyncs (SErrors), however,
can indicate that we e.g. touched memory that we shouldn't have
touched (secure memory).

Signed-off-by: Matthias Rosenfelder <[email protected]>
  • Loading branch information
mro-github-12345 authored and Andy Bui committed Feb 25, 2024
1 parent 4996de7 commit 5ebb1fc
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
3 changes: 3 additions & 0 deletions elfloader-tool/src/arch-arm/sys_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ void continue_boot(int was_relocated)
printf("Jumping to kernel-image entry point...\n\n");
}

/* Clear D&A in DAIF */
asm volatile("msr daifclr, #0xC\n\t");

/* Jump to the kernel. Note: Our DTB is smaller than 4 GiB. */
((init_arm_kernel_t)kernel_info.virt_entry)(user_info.phys_region_start,
user_info.phys_region_end,
Expand Down
18 changes: 17 additions & 1 deletion elfloader-tool/src/binaries/efi/efi_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,28 @@
* SPDX-License-Identifier: GPL-2.0-only
*/

#include <autoconf.h>
#include <binaries/efi/efi.h>
#include <elfloader_common.h>

void *__application_handle = NULL; // current efi application handler
efi_system_table_t *__efi_system_table = NULL; // current efi system table

static unsigned long efi_exit_bs_result = EFI_SUCCESS;
static unsigned long exit_boot_services(void);

unsigned long efi_exit_boot_services(void)
{
return efi_exit_bs_result;
}

extern void _start(void);
unsigned int efi_main(uintptr_t application_handle, uintptr_t efi_system_table)
{
clear_bss();
__application_handle = (void *)application_handle;
__efi_system_table = (efi_system_table_t *)efi_system_table;
efi_exit_bs_result = exit_boot_services();
_start();
return 0;
}
Expand All @@ -41,7 +51,7 @@ void *efi_get_fdt(void)
* This means boot time services are not available anymore. We should store
* system information e.g. current memory map and pass them to kernel.
*/
unsigned long efi_exit_boot_services(void)
static unsigned long exit_boot_services(void)
{
unsigned long status;
efi_memory_desc_t *memory_map;
Expand Down Expand Up @@ -78,5 +88,11 @@ unsigned long efi_exit_boot_services(void)
}

status = bts->exit_boot_services(__application_handle, key);

#if defined(CONFIG_ARCH_AARCH64)
/* Now that we're free, mask all exceptions until we enter the kernel */
asm volatile("msr daifset, #0xF\n\t");
#endif

return status;
}

0 comments on commit 5ebb1fc

Please sign in to comment.