diff options
-rw-r--r-- | arch/arm64/kernel/efi.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 56c3327bbf79..e72f3100958f 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c | |||
@@ -414,13 +414,24 @@ static int __init arm64_enter_virtual_mode(void) | |||
414 | for_each_efi_memory_desc(&memmap, md) { | 414 | for_each_efi_memory_desc(&memmap, md) { |
415 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) | 415 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) |
416 | continue; | 416 | continue; |
417 | if (remap_region(md, &virt_md)) | 417 | if (!remap_region(md, &virt_md)) |
418 | ++count; | 418 | goto err_unmap; |
419 | ++count; | ||
419 | } | 420 | } |
420 | 421 | ||
421 | efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table); | 422 | efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table); |
422 | if (efi.systab) | 423 | if (!efi.systab) { |
423 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); | 424 | /* |
425 | * If we have no virtual mapping for the System Table at this | ||
426 | * point, the memory map doesn't cover the physical offset where | ||
427 | * it resides. This means the System Table will be inaccessible | ||
428 | * to Runtime Services themselves once the virtual mapping is | ||
429 | * installed. | ||
430 | */ | ||
431 | pr_err("Failed to remap EFI System Table -- buggy firmware?\n"); | ||
432 | goto err_unmap; | ||
433 | } | ||
434 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); | ||
424 | 435 | ||
425 | local_irq_save(flags); | 436 | local_irq_save(flags); |
426 | cpu_switch_mm(idmap_pg_dir, &init_mm); | 437 | cpu_switch_mm(idmap_pg_dir, &init_mm); |
@@ -453,5 +464,14 @@ static int __init arm64_enter_virtual_mode(void) | |||
453 | set_bit(EFI_RUNTIME_SERVICES, &efi.flags); | 464 | set_bit(EFI_RUNTIME_SERVICES, &efi.flags); |
454 | 465 | ||
455 | return 0; | 466 | return 0; |
467 | |||
468 | err_unmap: | ||
469 | /* unmap all mappings that succeeded: there are 'count' of those */ | ||
470 | for (virt_md = virtmap; count--; virt_md += memmap.desc_size) { | ||
471 | md = virt_md; | ||
472 | iounmap((__force void __iomem *)md->virt_addr); | ||
473 | } | ||
474 | kfree(virtmap); | ||
475 | return -1; | ||
456 | } | 476 | } |
457 | early_initcall(arm64_enter_virtual_mode); | 477 | early_initcall(arm64_enter_virtual_mode); |