@@ -127,8 +127,8 @@ extern bool efi_disable_ibt_for_runtime;
extern int __init efi_memblock_x86_reserve_range(void);
extern void __init efi_print_memmap(void);
-extern void __init efi_map_region(efi_memory_desc_t *md);
-extern void __init efi_map_region_fixed(efi_memory_desc_t *md);
+extern int __init efi_map_region(efi_memory_desc_t *md);
+extern int __init efi_map_region_fixed(efi_memory_desc_t *md);
extern void efi_sync_low_kernel_mappings(void);
extern int __init efi_alloc_page_tables(void);
extern int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages);
@@ -690,7 +690,8 @@ static void * __init efi_map_regions(int *count, int *pg_shift)
if (!should_map_region(md))
continue;
- efi_map_region(md);
+ if (efi_map_region(md))
+ return NULL;
if (left < desc_size) {
new_memmap = realloc_pages(new_memmap, *pg_shift);
@@ -736,9 +737,10 @@ static void __init kexec_enter_virtual_mode(void)
* Map efi regions which were passed via setup_data. The virt_addr is a
* fixed addr which was used in first kernel of a kexec boot.
*/
- for_each_efi_memory_desc(md)
- efi_map_region_fixed(md); /* FIXME: add error handling */
-
+ for_each_efi_memory_desc(md) {
+ if (efi_map_region_fixed(md))
+ return;
+ }
/*
* Unregister the early EFI memmap from efi_init() and install
* the new EFI memory map.
@@ -33,7 +33,7 @@
#include <asm/tlbflush.h>
#include <asm/efi.h>
-void __init efi_map_region(efi_memory_desc_t *md)
+int __init efi_map_region(efi_memory_desc_t *md)
{
u64 start_pfn, end_pfn, end;
unsigned long size;
@@ -54,8 +54,11 @@ void __init efi_map_region(efi_memory_desc_t *md)
}
md->virt_addr = (unsigned long)va;
- if (!va)
+ if (!va) {
pr_err("ioremap of 0x%llX failed!\n", md->phys_addr);
+ return -EINVAL;
+ }
+ return 0;
}
/*
@@ -268,12 +268,12 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
return 0;
}
-static void __init __map_region(efi_memory_desc_t *md, u64 va)
+static int __init __map_region(efi_memory_desc_t *md, u64 va)
{
unsigned long flags = _PAGE_RW;
unsigned long pfn;
pgd_t *pgd = efi_mm.pgd;
-
+ int retval;
/*
* EFI_RUNTIME_SERVICES_CODE regions typically cover PE/COFF
* executable images in memory that consist of both R-X and
@@ -298,22 +298,25 @@ static void __init __map_region(efi_memory_desc_t *md, u64 va)
flags |= _PAGE_ENC;
pfn = md->phys_addr >> PAGE_SHIFT;
- if (kernel_map_pages_in_pgd(pgd, pfn, va, md->num_pages, flags))
+ retval = kernel_map_pages_in_pgd(pgd, pfn, va, md->num_pages, flags);
+ if (retval)
pr_warn("Error mapping PA 0x%llx -> VA 0x%llx!\n",
md->phys_addr, va);
+ return retval;
}
-void __init efi_map_region(efi_memory_desc_t *md)
+int __init efi_map_region(efi_memory_desc_t *md)
{
unsigned long size = md->num_pages << PAGE_SHIFT;
u64 pa = md->phys_addr;
+ int retval = 0;
/*
* Make sure the 1:1 mappings are present as a catch-all for b0rked
* firmware which doesn't update all internal pointers after switching
* to virtual mode and would otherwise crap on us.
*/
- __map_region(md, md->phys_addr);
+ retval = __map_region(md, md->phys_addr);
/*
* Enforce the 1:1 mapping as the default virtual address when
@@ -322,7 +325,7 @@ void __init efi_map_region(efi_memory_desc_t *md)
*/
if (efi_is_mixed()) {
md->virt_addr = md->phys_addr;
- return;
+ return retval;
}
efi_va -= size;
@@ -343,12 +346,13 @@ void __init efi_map_region(efi_memory_desc_t *md)
if (efi_va < EFI_VA_END) {
pr_warn(FW_WARN "VA address range overflow!\n");
- return;
+ return retval;
}
/* Do the VA map */
- __map_region(md, efi_va);
+ retval = __map_region(md, efi_va);
md->virt_addr = efi_va;
+ return retval;
}
/*
@@ -356,10 +360,16 @@ void __init efi_map_region(efi_memory_desc_t *md)
* md->virt_addr is the original virtual address which had been mapped in kexec
* 1st kernel.
*/
-void __init efi_map_region_fixed(efi_memory_desc_t *md)
-{
- __map_region(md, md->phys_addr);
- __map_region(md, md->virt_addr);
+int __init efi_map_region_fixed(efi_memory_desc_t *md)
+{
+ int retval;
+ retval = __map_region(md, md->phys_addr);
+ if (retval)
+ return retval;
+ retval = __map_region(md, md->virt_addr);
+ if (retval)
+ return retval;
+ return 0;
}
void __init parse_efi_setup(u64 phys_addr, u32 data_len)