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>
67 lines
1.6 KiB
C
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();
|
|
}
|
|
}
|