| /* |
| * 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; |
| } |