blob: 50e1cef1f373862d58d3a1fef333751c8c4ad2b3 [file] [edit]
/*
* Copyright (c) 2026 The Fuchsia Authors
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common.h>
#include <efi_loader.h>
#include <gbl_efi_boot_control_protocol.h>
// Slot management functions return EFI_UNSUPPORTED as GBL's Fuchsia flow
// does not rely on this protocol for slot work.
static efi_status_t EFIAPI
get_slot_count(struct GblEfiBootControlProtocol *self, uint8_t *slot_count)
{
EFI_ENTRY("%p, %p", self, slot_count);
return EFI_EXIT(EFI_UNSUPPORTED);
}
static efi_status_t EFIAPI get_slot_info(struct GblEfiBootControlProtocol *self,
uint8_t index, GblEfiSlotInfo *info)
{
EFI_ENTRY("%p, %d, %p", self, index, info);
return EFI_EXIT(EFI_UNSUPPORTED);
}
static efi_status_t EFIAPI
get_current_slot(struct GblEfiBootControlProtocol *self, GblEfiSlotInfo *info)
{
EFI_ENTRY("%p, %p", self, info);
return EFI_EXIT(EFI_UNSUPPORTED);
}
static efi_status_t EFIAPI
set_active_slot(struct GblEfiBootControlProtocol *self, uint8_t index)
{
EFI_ENTRY("%p, %d", self, index);
return EFI_EXIT(EFI_UNSUPPORTED);
}
static efi_status_t EFIAPI get_one_shot_boot_mode(
struct GblEfiBootControlProtocol *self, GblEfiOneShotBootMode *mode)
{
EFI_ENTRY("%p, %p", self, mode);
if (!mode)
return EFI_EXIT(EFI_INVALID_PARAMETER);
char *boot_mode = getenv("gbl_one_shot_boot_mode");
if (boot_mode && (strcmp(boot_mode, "bootloader") == 0 ||
strcmp(boot_mode, "fastboot") == 0)) {
printf("GBL: One-shot boot mode set via env: %s\n", boot_mode);
*mode = GBL_EFI_ONE_SHOT_BOOT_MODE_BOOTLOADER;
return EFI_EXIT(EFI_SUCCESS);
}
printf("\nPress 'f' to enter fastboot mode...\n");
ulong start = get_timer(0);
bool enter_fastboot = false;
while (get_timer(start) < 2000) {
if (tstc()) {
int c = getc();
if (c == 'f') {
enter_fastboot = true;
break;
}
}
udelay(1000);
}
if (enter_fastboot) {
printf("Entering fastboot mode...\n");
*mode = GBL_EFI_ONE_SHOT_BOOT_MODE_BOOTLOADER;
} else {
*mode = GBL_EFI_ONE_SHOT_BOOT_MODE_NONE;
}
return EFI_EXIT(EFI_SUCCESS);
}
static efi_status_t EFIAPI handle_loaded_os(
struct GblEfiBootControlProtocol *self, const GblEfiLoadedOs *os)
{
EFI_ENTRY("%p, %p", self, os);
if (!os)
return EFI_EXIT(EFI_INVALID_PARAMETER);
printf("GBL: Loaded OS: kernel size %zu at 0x%llx, ramdisk size %zu at 0x%llx\n",
os->kernel_size, os->kernel, os->ramdisk_size, os->ramdisk);
return EFI_EXIT(EFI_SUCCESS);
}
static const efi_guid_t guid = EFI_GUID(0xd382db1b, 0x9ac2, 0x11f0, 0x84, 0xc7,
0x04, 0x7b, 0xcb, 0xa9, 0x60, 0x19);
static GblEfiBootControlProtocol protocol = {
.revision = GBL_EFI_BOOT_CONTROL_PROTOCOL_REVISION,
.get_slot_count = get_slot_count,
.get_slot_info = get_slot_info,
.get_current_slot = get_current_slot,
.set_active_slot = set_active_slot,
.get_one_shot_boot_mode = get_one_shot_boot_mode,
.handle_loaded_os = handle_loaded_os,
};
efi_status_t efi_gbl_boot_control_register(void)
{
efi_status_t ret = efi_add_protocol(efi_root, &guid, (void *)&protocol);
if (ret != EFI_SUCCESS)
printf("Cannot install GBL_EFI_BOOT_CONTROL_PROTOCOL\n");
return ret;
}