aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/efi/efi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/efi/efi.c')
-rw-r--r--drivers/firmware/efi/efi.c67
1 files changed, 36 insertions, 31 deletions
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 7dd2e2d37231..1ac199cd75e7 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -27,6 +27,7 @@
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/acpi.h> 28#include <linux/acpi.h>
29#include <linux/ucs2_string.h> 29#include <linux/ucs2_string.h>
30#include <linux/memblock.h>
30 31
31#include <asm/early_ioremap.h> 32#include <asm/early_ioremap.h>
32 33
@@ -347,56 +348,31 @@ subsys_initcall(efisubsys_init);
347 348
348/* 349/*
349 * Find the efi memory descriptor for a given physical address. Given a 350 * Find the efi memory descriptor for a given physical address. Given a
350 * physicall address, determine if it exists within an EFI Memory Map entry, 351 * physical address, determine if it exists within an EFI Memory Map entry,
351 * and if so, populate the supplied memory descriptor with the appropriate 352 * and if so, populate the supplied memory descriptor with the appropriate
352 * data. 353 * data.
353 */ 354 */
354int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) 355int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
355{ 356{
356 struct efi_memory_map *map = &efi.memmap; 357 efi_memory_desc_t *md;
357 phys_addr_t p, e;
358 358
359 if (!efi_enabled(EFI_MEMMAP)) { 359 if (!efi_enabled(EFI_MEMMAP)) {
360 pr_err_once("EFI_MEMMAP is not enabled.\n"); 360 pr_err_once("EFI_MEMMAP is not enabled.\n");
361 return -EINVAL; 361 return -EINVAL;
362 } 362 }
363 363
364 if (!map) {
365 pr_err_once("efi.memmap is not set.\n");
366 return -EINVAL;
367 }
368 if (!out_md) { 364 if (!out_md) {
369 pr_err_once("out_md is null.\n"); 365 pr_err_once("out_md is null.\n");
370 return -EINVAL; 366 return -EINVAL;
371 } 367 }
372 if (WARN_ON_ONCE(!map->phys_map))
373 return -EINVAL;
374 if (WARN_ON_ONCE(map->nr_map == 0) || WARN_ON_ONCE(map->desc_size == 0))
375 return -EINVAL;
376 368
377 e = map->phys_map + map->nr_map * map->desc_size; 369 for_each_efi_memory_desc(md) {
378 for (p = map->phys_map; p < e; p += map->desc_size) {
379 efi_memory_desc_t *md;
380 u64 size; 370 u64 size;
381 u64 end; 371 u64 end;
382 372
383 /*
384 * If a driver calls this after efi_free_boot_services,
385 * ->map will be NULL, and the target may also not be mapped.
386 * So just always get our own virtual map on the CPU.
387 *
388 */
389 md = early_memremap(p, sizeof (*md));
390 if (!md) {
391 pr_err_once("early_memremap(%pa, %zu) failed.\n",
392 &p, sizeof (*md));
393 return -ENOMEM;
394 }
395
396 if (!(md->attribute & EFI_MEMORY_RUNTIME) && 373 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
397 md->type != EFI_BOOT_SERVICES_DATA && 374 md->type != EFI_BOOT_SERVICES_DATA &&
398 md->type != EFI_RUNTIME_SERVICES_DATA) { 375 md->type != EFI_RUNTIME_SERVICES_DATA) {
399 early_memunmap(md, sizeof (*md));
400 continue; 376 continue;
401 } 377 }
402 378
@@ -404,11 +380,8 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
404 end = md->phys_addr + size; 380 end = md->phys_addr + size;
405 if (phys_addr >= md->phys_addr && phys_addr < end) { 381 if (phys_addr >= md->phys_addr && phys_addr < end) {
406 memcpy(out_md, md, sizeof(*out_md)); 382 memcpy(out_md, md, sizeof(*out_md));
407 early_memunmap(md, sizeof (*md));
408 return 0; 383 return 0;
409 } 384 }
410
411 early_memunmap(md, sizeof (*md));
412 } 385 }
413 pr_err_once("requested map not found.\n"); 386 pr_err_once("requested map not found.\n");
414 return -ENOENT; 387 return -ENOENT;
@@ -424,6 +397,35 @@ u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
424 return end; 397 return end;
425} 398}
426 399
400void __init __weak efi_arch_mem_reserve(phys_addr_t addr, u64 size) {}
401
402/**
403 * efi_mem_reserve - Reserve an EFI memory region
404 * @addr: Physical address to reserve
405 * @size: Size of reservation
406 *
407 * Mark a region as reserved from general kernel allocation and
408 * prevent it being released by efi_free_boot_services().
409 *
410 * This function should be called drivers once they've parsed EFI
411 * configuration tables to figure out where their data lives, e.g.
412 * efi_esrt_init().
413 */
414void __init efi_mem_reserve(phys_addr_t addr, u64 size)
415{
416 if (!memblock_is_region_reserved(addr, size))
417 memblock_reserve(addr, size);
418
419 /*
420 * Some architectures (x86) reserve all boot services ranges
421 * until efi_free_boot_services() because of buggy firmware
422 * implementations. This means the above memblock_reserve() is
423 * superfluous on x86 and instead what it needs to do is
424 * ensure the @start, @size is not freed.
425 */
426 efi_arch_mem_reserve(addr, size);
427}
428
427static __initdata efi_config_table_type_t common_tables[] = { 429static __initdata efi_config_table_type_t common_tables[] = {
428 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20}, 430 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
429 {ACPI_TABLE_GUID, "ACPI", &efi.acpi}, 431 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
@@ -811,6 +813,9 @@ int efi_status_to_err(efi_status_t status)
811 case EFI_NOT_FOUND: 813 case EFI_NOT_FOUND:
812 err = -ENOENT; 814 err = -ENOENT;
813 break; 815 break;
816 case EFI_ABORTED:
817 err = -EINTR;
818 break;
814 default: 819 default:
815 err = -EINVAL; 820 err = -EINVAL;
816 } 821 }