blob: adc88ca1d01b540a2af48bd33f8059ad317ad687 [file]
/*
* Copyright (c) 2026 The Fuchsia Authors
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common.h>
#include <efi_loader.h>
#include <gbl_efi_boot_memory_protocol.h>
static ulong reserved_kaddr;
static ulong reserved_ksize;
static ulong reserved_fdt_addr;
static ulong reserved_fdt_size;
static efi_status_t EFIAPI get_partition_buffer(
struct GblEfiBootMemoryProtocol *self, const char *base_name,
size_t *size, void **addr, GblEfiPartitionBufferFlag *flag)
{
EFI_ENTRY("%p, %s, %p, %p, %p", self, base_name, size, addr, flag);
// We don't have any preloaded partitions in memory.
return EFI_EXIT(EFI_NOT_FOUND);
}
static efi_status_t EFIAPI sync_partition_buffer(
struct GblEfiBootMemoryProtocol *self, bool sync_preloaded)
{
EFI_ENTRY("%p, %d", self, sync_preloaded);
return EFI_EXIT(EFI_SUCCESS);
}
static efi_status_t EFIAPI get_boot_buffer(struct GblEfiBootMemoryProtocol *self,
GblEfiBootBufferType buf_type,
size_t *size, void **addr)
{
EFI_ENTRY("%p, %d, %p, %p", self, buf_type, size, addr);
if (!size || !addr) {
return EFI_EXIT(EFI_INVALID_PARAMETER);
}
*addr = NULL;
switch (buf_type) {
case GBL_EFI_BOOT_BUFFER_TYPE_KERNEL: {
ulong kaddr = getenv_hex("loadaddr", 0x0);
ulong ksize = getenv_hex("loadsize", 0x4000000);
if (kaddr != reserved_kaddr || ksize != reserved_ksize) {
printf("GBL Boot Memory WARNING: 'loadaddr' or 'loadsize' changed after registration! (Registered: 0x%lx/0x%lx, Current: 0x%lx/0x%lx)\n",
reserved_kaddr, reserved_ksize, kaddr, ksize);
}
if (reserved_kaddr != 0) {
*addr = (void *)(uintptr_t)reserved_kaddr;
*size = (size_t)reserved_ksize;
}
break;
}
case GBL_EFI_BOOT_BUFFER_TYPE_FDT: {
ulong fdt_addr = getenv_hex("fdtaddr", 0x0);
if (fdt_addr != reserved_fdt_addr) {
printf("GBL Boot Memory WARNING: 'fdtaddr' changed after registration! (Registered: 0x%lx, Current: 0x%lx)\n",
reserved_fdt_addr, fdt_addr);
}
if (reserved_fdt_addr != 0) {
*addr = (void *)(uintptr_t)reserved_fdt_addr;
*size = (size_t)reserved_fdt_size;
}
break;
}
default:
break;
}
if (*addr) {
return EFI_EXIT(EFI_SUCCESS);
}
// Fallback to let GBL allocate its own buffer for the rest buffer types.
return EFI_EXIT(EFI_NOT_FOUND);
}
static const efi_guid_t guid = EFI_GUID(0x309f2874, 0xad59, 0x4fd2, 0xaf, 0x5e,
0xce, 0x0f, 0x4a, 0xb4, 0x01, 0xa6);
static GblEfiBootMemoryProtocol protocol = {
.revision = GBL_EFI_BOOT_MEMORY_PROTOCOL_REVISION,
.get_partition_buffer = get_partition_buffer,
.sync_partition_buffer = sync_partition_buffer,
.get_boot_buffer = get_boot_buffer,
};
efi_status_t efi_gbl_boot_memory_register(void)
{
efi_status_t ret = efi_add_protocol(efi_root, &guid, (void *)&protocol);
if (ret != EFI_SUCCESS) {
printf("Cannot install GBL_EFI_BOOT_MEMORY_PROTOCOL\n");
return ret;
}
reserved_kaddr = getenv_hex("loadaddr", 0x0);
reserved_ksize = getenv_hex("loadsize", 0x4000000);
if (reserved_kaddr != 0) {
efi_add_memory_map(reserved_kaddr, reserved_ksize,
EFI_BOOT_SERVICES_DATA);
}
reserved_fdt_addr = getenv_hex("fdtaddr", 0x0);
reserved_fdt_size = 0x200000;
if (reserved_fdt_addr != 0) {
efi_add_memory_map(reserved_fdt_addr, reserved_fdt_size,
EFI_BOOT_SERVICES_DATA);
}
return EFI_SUCCESS;
}