aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/efi.h2
-rw-r--r--arch/x86/kernel/setup.c10
-rw-r--r--arch/x86/platform/efi/efi.c164
3 files changed, 151 insertions, 25 deletions
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 844f735fd63a..c9dcc181d4d1 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -95,7 +95,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
95 95
96extern int add_efi_memmap; 96extern int add_efi_memmap;
97extern void efi_set_executable(efi_memory_desc_t *md, bool executable); 97extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
98extern void efi_memblock_x86_reserve_range(void); 98extern int efi_memblock_x86_reserve_range(void);
99extern void efi_call_phys_prelog(void); 99extern void efi_call_phys_prelog(void);
100extern void efi_call_phys_epilog(void); 100extern void efi_call_phys_epilog(void);
101 101
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index d7d5099fe874..88638883176a 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -749,10 +749,16 @@ void __init setup_arch(char **cmdline_p)
749#endif 749#endif
750#ifdef CONFIG_EFI 750#ifdef CONFIG_EFI
751 if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, 751 if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
752 EFI_LOADER_SIGNATURE, 4)) { 752 "EL32", 4)) {
753 efi_enabled = 1; 753 efi_enabled = 1;
754 efi_memblock_x86_reserve_range(); 754 efi_64bit = false;
755 } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
756 "EL64", 4)) {
757 efi_enabled = 1;
758 efi_64bit = true;
755 } 759 }
760 if (efi_enabled && efi_memblock_x86_reserve_range())
761 efi_enabled = 0;
756#endif 762#endif
757 763
758 x86_init.oem.arch_setup(); 764 x86_init.oem.arch_setup();
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 5a053e7737b7..92660edaa1e7 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -68,6 +68,9 @@ EXPORT_SYMBOL(efi);
68 68
69struct efi_memory_map memmap; 69struct efi_memory_map memmap;
70 70
71bool efi_64bit;
72static bool efi_native;
73
71static struct efi efi_phys __initdata; 74static struct efi efi_phys __initdata;
72static efi_system_table_t efi_systab __initdata; 75static efi_system_table_t efi_systab __initdata;
73 76
@@ -339,11 +342,16 @@ static void __init do_add_efi_memmap(void)
339 sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); 342 sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
340} 343}
341 344
342void __init efi_memblock_x86_reserve_range(void) 345int __init efi_memblock_x86_reserve_range(void)
343{ 346{
344 unsigned long pmap; 347 unsigned long pmap;
345 348
346#ifdef CONFIG_X86_32 349#ifdef CONFIG_X86_32
350 /* Can't handle data above 4GB at this time */
351 if (boot_params.efi_info.efi_memmap_hi) {
352 pr_err("Memory map is above 4GB, disabling EFI.\n");
353 return -EINVAL;
354 }
347 pmap = boot_params.efi_info.efi_memmap; 355 pmap = boot_params.efi_info.efi_memmap;
348#else 356#else
349 pmap = (boot_params.efi_info.efi_memmap | 357 pmap = (boot_params.efi_info.efi_memmap |
@@ -355,6 +363,8 @@ void __init efi_memblock_x86_reserve_range(void)
355 memmap.desc_version = boot_params.efi_info.efi_memdesc_version; 363 memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
356 memmap.desc_size = boot_params.efi_info.efi_memdesc_size; 364 memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
357 memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); 365 memblock_reserve(pmap, memmap.nr_map * memmap.desc_size);
366
367 return 0;
358} 368}
359 369
360#if EFI_DEBUG 370#if EFI_DEBUG
@@ -432,14 +442,75 @@ static void __init efi_free_boot_services(void)
432 442
433static int __init efi_systab_init(void *phys) 443static int __init efi_systab_init(void *phys)
434{ 444{
435 efi.systab = early_ioremap((unsigned long)efi_phys.systab, 445 if (efi_64bit) {
436 sizeof(efi_system_table_t)); 446 efi_system_table_64_t *systab64;
437 if (efi.systab == NULL) { 447 u64 tmp = 0;
438 pr_err("Couldn't map the system table!\n"); 448
439 return -ENOMEM; 449 systab64 = early_ioremap((unsigned long)phys,
450 sizeof(*systab64));
451 if (systab64 == NULL) {
452 pr_err("Couldn't map the system table!\n");
453 return -ENOMEM;
454 }
455
456 efi_systab.hdr = systab64->hdr;
457 efi_systab.fw_vendor = systab64->fw_vendor;
458 tmp |= systab64->fw_vendor;
459 efi_systab.fw_revision = systab64->fw_revision;
460 efi_systab.con_in_handle = systab64->con_in_handle;
461 tmp |= systab64->con_in_handle;
462 efi_systab.con_in = systab64->con_in;
463 tmp |= systab64->con_in;
464 efi_systab.con_out_handle = systab64->con_out_handle;
465 tmp |= systab64->con_out_handle;
466 efi_systab.con_out = systab64->con_out;
467 tmp |= systab64->con_out;
468 efi_systab.stderr_handle = systab64->stderr_handle;
469 tmp |= systab64->stderr_handle;
470 efi_systab.stderr = systab64->stderr;
471 tmp |= systab64->stderr;
472 efi_systab.runtime = (void *)(unsigned long)systab64->runtime;
473 tmp |= systab64->runtime;
474 efi_systab.boottime = (void *)(unsigned long)systab64->boottime;
475 tmp |= systab64->boottime;
476 efi_systab.nr_tables = systab64->nr_tables;
477 efi_systab.tables = systab64->tables;
478 tmp |= systab64->tables;
479
480 early_iounmap(systab64, sizeof(*systab64));
481#ifdef CONFIG_X86_32
482 if (tmp >> 32) {
483 pr_err("EFI data located above 4GB, disabling EFI.\n");
484 return -EINVAL;
485 }
486#endif
487 } else {
488 efi_system_table_32_t *systab32;
489
490 systab32 = early_ioremap((unsigned long)phys,
491 sizeof(*systab32));
492 if (systab32 == NULL) {
493 pr_err("Couldn't map the system table!\n");
494 return -ENOMEM;
495 }
496
497 efi_systab.hdr = systab32->hdr;
498 efi_systab.fw_vendor = systab32->fw_vendor;
499 efi_systab.fw_revision = systab32->fw_revision;
500 efi_systab.con_in_handle = systab32->con_in_handle;
501 efi_systab.con_in = systab32->con_in;
502 efi_systab.con_out_handle = systab32->con_out_handle;
503 efi_systab.con_out = systab32->con_out;
504 efi_systab.stderr_handle = systab32->stderr_handle;
505 efi_systab.stderr = systab32->stderr;
506 efi_systab.runtime = (void *)(unsigned long)systab32->runtime;
507 efi_systab.boottime = (void *)(unsigned long)systab32->boottime;
508 efi_systab.nr_tables = systab32->nr_tables;
509 efi_systab.tables = systab32->tables;
510
511 early_iounmap(systab32, sizeof(*systab32));
440 } 512 }
441 memcpy(&efi_systab, efi.systab, sizeof(efi_system_table_t)); 513
442 early_iounmap(efi.systab, sizeof(efi_system_table_t));
443 efi.systab = &efi_systab; 514 efi.systab = &efi_systab;
444 515
445 /* 516 /*
@@ -460,24 +531,47 @@ static int __init efi_systab_init(void *phys)
460 531
461static int __init efi_config_init(u64 tables, int nr_tables) 532static int __init efi_config_init(u64 tables, int nr_tables)
462{ 533{
463 efi_config_table_t *config_tables; 534 void *config_tables, *tablep;
464 int i, sz = sizeof(efi_config_table_t); 535 int i, sz;
536
537 if (efi_64bit)
538 sz = sizeof(efi_config_table_64_t);
539 else
540 sz = sizeof(efi_config_table_32_t);
465 541
466 /* 542 /*
467 * Let's see what config tables the firmware passed to us. 543 * Let's see what config tables the firmware passed to us.
468 */ 544 */
469 config_tables = early_ioremap(efi.systab->tables, 545 config_tables = early_ioremap(tables, nr_tables * sz);
470 efi.systab->nr_tables * sz);
471 if (config_tables == NULL) { 546 if (config_tables == NULL) {
472 pr_err("Could not map Configuration table!\n"); 547 pr_err("Could not map Configuration table!\n");
473 return -ENOMEM; 548 return -ENOMEM;
474 } 549 }
475 550
551 tablep = config_tables;
476 pr_info(""); 552 pr_info("");
477 for (i = 0; i < efi.systab->nr_tables; i++) { 553 for (i = 0; i < efi.systab->nr_tables; i++) {
478 efi_guid_t guid = config_tables[i].guid; 554 efi_guid_t guid;
479 unsigned long table = config_tables[i].table; 555 unsigned long table;
480 556
557 if (efi_64bit) {
558 u64 table64;
559 guid = ((efi_config_table_64_t *)tablep)->guid;
560 table64 = ((efi_config_table_64_t *)tablep)->table;
561 table = table64;
562#ifdef CONFIG_X86_32
563 if (table64 >> 32) {
564 pr_cont("\n");
565 pr_err("Table located above 4GB, disabling EFI.\n");
566 early_iounmap(config_tables,
567 efi.systab->nr_tables * sz);
568 return -EINVAL;
569 }
570#endif
571 } else {
572 guid = ((efi_config_table_32_t *)tablep)->guid;
573 table = ((efi_config_table_32_t *)tablep)->table;
574 }
481 if (!efi_guidcmp(guid, MPS_TABLE_GUID)) { 575 if (!efi_guidcmp(guid, MPS_TABLE_GUID)) {
482 efi.mps = table; 576 efi.mps = table;
483 pr_cont(" MPS=0x%lx ", table); 577 pr_cont(" MPS=0x%lx ", table);
@@ -502,10 +596,10 @@ static int __init efi_config_init(u64 tables, int nr_tables)
502 efi.uga = table; 596 efi.uga = table;
503 pr_cont(" UGA=0x%lx ", table); 597 pr_cont(" UGA=0x%lx ", table);
504 } 598 }
599 tablep += sz;
505 } 600 }
506 pr_cont("\n"); 601 pr_cont("\n");
507 early_iounmap(config_tables, efi.systab->nr_tables * sz); 602 early_iounmap(config_tables, efi.systab->nr_tables * sz);
508
509 return 0; 603 return 0;
510} 604}
511 605
@@ -569,11 +663,19 @@ void __init efi_init(void)
569 void *tmp; 663 void *tmp;
570 664
571#ifdef CONFIG_X86_32 665#ifdef CONFIG_X86_32
666 if (boot_params.efi_info.efi_systab_hi ||
667 boot_params.efi_info.efi_memmap_hi) {
668 pr_info("Table located above 4GB, disabling EFI.\n");
669 efi_enabled = 0;
670 return;
671 }
572 efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; 672 efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
673 efi_native = !efi_64bit;
573#else 674#else
574 efi_phys.systab = (efi_system_table_t *) 675 efi_phys.systab = (efi_system_table_t *)
575 (boot_params.efi_info.efi_systab | 676 (boot_params.efi_info.efi_systab |
576 ((__u64)boot_params.efi_info.efi_systab_hi<<32)); 677 ((__u64)boot_params.efi_info.efi_systab_hi<<32));
678 efi_native = efi_64bit;
577#endif 679#endif
578 680
579 if (efi_systab_init(efi_phys.systab)) { 681 if (efi_systab_init(efi_phys.systab)) {
@@ -602,7 +704,14 @@ void __init efi_init(void)
602 return; 704 return;
603 } 705 }
604 706
605 if (efi_runtime_init()) { 707 /*
708 * Note: We currently don't support runtime services on an EFI
709 * that doesn't match the kernel 32/64-bit mode.
710 */
711
712 if (!efi_native)
713 pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
714 else if (efi_runtime_init()) {
606 efi_enabled = 0; 715 efi_enabled = 0;
607 return; 716 return;
608 } 717 }
@@ -611,10 +720,11 @@ void __init efi_init(void)
611 efi_enabled = 0; 720 efi_enabled = 0;
612 return; 721 return;
613 } 722 }
614
615#ifdef CONFIG_X86_32 723#ifdef CONFIG_X86_32
616 x86_platform.get_wallclock = efi_get_time; 724 if (efi_native) {
617 x86_platform.set_wallclock = efi_set_rtc_mmss; 725 x86_platform.get_wallclock = efi_get_time;
726 x86_platform.set_wallclock = efi_set_rtc_mmss;
727 }
618#endif 728#endif
619 729
620#if EFI_DEBUG 730#if EFI_DEBUG
@@ -672,6 +782,14 @@ void __init efi_enter_virtual_mode(void)
672 782
673 efi.systab = NULL; 783 efi.systab = NULL;
674 784
785 /*
786 * We don't do virtual mode, since we don't do runtime services, on
787 * non-native EFI
788 */
789
790 if (!efi_native)
791 goto out;
792
675 /* Merge contiguous regions of the same type and attribute */ 793 /* Merge contiguous regions of the same type and attribute */
676 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { 794 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
677 u64 prev_size; 795 u64 prev_size;
@@ -787,6 +905,8 @@ void __init efi_enter_virtual_mode(void)
787 efi.query_capsule_caps = virt_efi_query_capsule_caps; 905 efi.query_capsule_caps = virt_efi_query_capsule_caps;
788 if (__supported_pte_mask & _PAGE_NX) 906 if (__supported_pte_mask & _PAGE_NX)
789 runtime_code_page_mkexec(); 907 runtime_code_page_mkexec();
908
909out:
790 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); 910 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
791 memmap.map = NULL; 911 memmap.map = NULL;
792 kfree(new_memmap); 912 kfree(new_memmap);