diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/efi/Makefile | 1 | ||||
-rw-r--r-- | common/efi/efi-iomem.c | 175 | ||||
-rw-r--r-- | common/memory.c | 2 |
3 files changed, 177 insertions, 1 deletions
diff --git a/common/efi/Makefile b/common/efi/Makefile index ef19969f93..d746fabe21 100644 --- a/common/efi/Makefile +++ b/common/efi/Makefile @@ -1,3 +1,4 @@ obj-y += efi.o obj-y += efi-image.o bbenv-y += env-efi +obj-$(CONFIG_CMD_IOMEM) += efi-iomem.o diff --git a/common/efi/efi-iomem.c b/common/efi/efi-iomem.c new file mode 100644 index 0000000000..e223c595c4 --- /dev/null +++ b/common/efi/efi-iomem.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Ahmad Fatoum, Pengutronix + +#define pr_fmt(fmt) "efi-iomem: " fmt + +#include <common.h> +#include <init.h> +#include <efi.h> +#include <efi/efi.h> +#include <memory.h> +#include <linux/sizes.h> + +static int efi_parse_mmap(struct efi_memory_desc *desc) +{ + struct resource *res; + u32 flags; + const char *name; + char *fullname; + resource_size_t va_base, va_size; + int ret = 0; + + va_size = desc->npages * SZ_4K; + if (!va_size) + return 0; + + /* XXX At least OVMF doesn't populate ->virt_start and leaves it at zero + * for all mapping. Thus assume a 1:1 mapping and ignore virt_start + */ + va_base = desc->phys_start; + + switch (desc->type) { + case EFI_RESERVED_TYPE: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "reserved"; + flags = IORESOURCE_MEM | IORESOURCE_DISABLED; + break; + case EFI_LOADER_CODE: + return barebox_add_memory_bank("loader code", va_base, va_size); + case EFI_LOADER_DATA: + return barebox_add_memory_bank("loader data", va_base, va_size); + case EFI_BOOT_SERVICES_CODE: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "boot services code"; + flags = IORESOURCE_MEM | IORESOURCE_READONLY; + break; + case EFI_BOOT_SERVICES_DATA: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "boot services data"; + flags = IORESOURCE_MEM; + break; + case EFI_RUNTIME_SERVICES_CODE: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "runtime services code"; + flags = IORESOURCE_MEM | IORESOURCE_READONLY; + break; + case EFI_RUNTIME_SERVICES_DATA: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "runtime services data"; + flags = IORESOURCE_MEM; + break; + case EFI_CONVENTIONAL_MEMORY: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "conventional memory"; + flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_CACHEABLE; + break; + case EFI_UNUSABLE_MEMORY: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "unusable"; + flags = IORESOURCE_MEM | IORESOURCE_DISABLED; + break; + case EFI_ACPI_RECLAIM_MEMORY: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "ACPI reclaim memory"; + flags = IORESOURCE_MEM | IORESOURCE_READONLY; + break; + case EFI_ACPI_MEMORY_NVS: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "ACPI NVS memory"; + flags = IORESOURCE_MEM | IORESOURCE_READONLY; + break; + case EFI_MEMORY_MAPPED_IO: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "MMIO"; + flags = IORESOURCE_MEM; + break; + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "MMIOPORT"; + flags = IORESOURCE_IO; + break; + case EFI_PAL_CODE: + if (!IS_ENABLED(DEBUG)) + return 0; + name = "PAL code"; + flags = IORESOURCE_MEM | IORESOURCE_ROM_BIOS_COPY; + break; + default: + if (!(desc->type & (1U << 31))) { + pr_warn("illegal memory type = %u >= %u\n", + desc->type, EFI_MAX_MEMORY_TYPE); + return -EINVAL; + } + + if (!IS_ENABLED(DEBUG)) + return 0; + + name = "vendor reserved"; + flags = IORESOURCE_MEM | IORESOURCE_ROM_BIOS_COPY; + } + + fullname = xasprintf("%s@%llx", name, desc->phys_start); + + pr_debug("%s: (0x%llx+0x%llx)\n", fullname, va_base, va_size); + + res = request_iomem_region(fullname, va_base, va_base + va_size - 1); + if (IS_ERR(res)) { + ret = PTR_ERR(res); + goto out; + } + + res->flags |= flags; + +out: + free(fullname); + return ret; +} + +static int efi_barebox_populate_mmap(void) +{ + void *desc; + u8 *mmap_buf = NULL; + efi_status_t efiret; + size_t mmap_size; + size_t mapkey; + size_t descsz; + u32 descver; + int ret = 0; + + mmap_size = sizeof(struct efi_memory_desc); + + do { + mmap_buf = xrealloc(mmap_buf, mmap_size); + efiret = BS->get_memory_map(&mmap_size, mmap_buf, + &mapkey, &descsz, &descver); + } while (efiret == EFI_BUFFER_TOO_SMALL); + + if (EFI_ERROR(efiret)) { + ret = -efi_errno(efiret); + goto out; + } + + if (descver != 1) { + ret = -ENOSYS; + goto out; + } + + for (desc = mmap_buf; (u8 *)desc < &mmap_buf[mmap_size]; desc += descsz) + efi_parse_mmap(desc); + +out: + free(mmap_buf); + return ret; +} +mem_initcall(efi_barebox_populate_mmap); diff --git a/common/memory.c b/common/memory.c index a56eaf9494..392522bfc3 100644 --- a/common/memory.c +++ b/common/memory.c @@ -53,7 +53,7 @@ void mem_malloc_init(void *start, void *end) mem_malloc_initialized = 1; } -#if !defined __SANDBOX__ && !defined CONFIG_EFI_BOOTUP +#if !defined __SANDBOX__ static int mem_malloc_resource(void) { /* |