Files
u-boot/boot/bootm_final.c
Simon Glass bfcb0a6dd6 bootm: Update FPDT boot times before handing off to OS
Update the FPDT boot performance record's ebs_entry and ebs_exit
fields in bootm_final() to record the time when we're about to
hand off to the operating system.

The timing is recorded just before we start the kernel, after all
device cleanup and before interrupts are disabled, which corresponds
to the ExitBootServices phase in UEFI.

If EFI is used to boot, a further update could be made, but that is
left for later.

Avoid including asm/acpi_table.h on platforms without ACPI. Ad a special
case for the QEMU RISC-V ACPI board.

Series-changes: 2
- Depend on ACPIGEN instead of GENERATE_ACPI_TABLE
- Avoid including asm/acpi_table.h on platforms without ACPI

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
2025-10-23 19:36:12 +01:00

67 lines
1.6 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Cleanup before handing off to the OS
*
* Copyright 2025 Simon Glass <sjg@chromium.org>
*/
#include <bootm.h>
#include <bootstage.h>
#include <event.h>
#include <usb.h>
#include <acpi/acpi_table.h>
#include <dm/root.h>
__weak void board_quiesce_devices(void)
{
}
void bootm_final(enum bootm_final_t flags)
{
struct event_bootm_final final;
int ret;
printf("\nStarting kernel ...%s\n\n", flags & BOOTM_FINAL_FAKE ?
"(fake run for tracing)" : "");
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
/* Update FPDT boot performance record if it exists */
if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE) &&
IS_ENABLED(CONFIG_ACPIGEN))
acpi_final_fpdt();
if (IS_ENABLED(CONFIG_BOOTSTAGE_FDT) && IS_ENABLED(CONFIG_CMD_FDT))
bootstage_fdt_add_report();
if (IS_ENABLED(CONFIG_BOOTSTAGE_REPORT))
bootstage_report();
board_quiesce_devices();
if (IS_ENABLED(CONFIG_USB_DEVICE))
udc_disconnect();
/*
* Call remove function of all devices with a removal flag set.
* This may be useful for last-stage operations, like cancelling
* of DMA operation or releasing device internal buffers.
* dm_remove_devices_active() ensures that vital devices are removed in
* a second round.
*/
dm_remove_devices_active();
final.flags = flags;
ret = event_notify(EVT_BOOTM_FINAL, &final, sizeof(final));
if (ret) {
printf("Event handler failed to finalise (err %dE\n",
ret);
return;
}
if (!(flags & BOOTM_FINAL_FAKE)) {
bootm_disable_interrupts();
if (!(flags & BOOTM_FINAL_NO_CLEANUP))
cleanup_before_linux();
}
}