Commit f06fc0c0de0b4f01dbad8ec5552e78192c7abbb8
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge branch 'x86-eficross-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/eficross (booting 32/64-bit kernel from 64/32-bit EFI) from Ingo Molnar * 'x86-eficross-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, efi: Allow basic init with mixed 32/64-bit efi/kernel x86, efi: Add basic error handling x86, efi: Cleanup config table walking x86, efi: Convert printk to pr_*() x86, efi: Refactor efi_init() a bit
Showing 4 changed files Side-by-side Diff
arch/x86/include/asm/efi.h
... | ... | @@ -95,7 +95,7 @@ |
95 | 95 | |
96 | 96 | extern int add_efi_memmap; |
97 | 97 | extern void efi_set_executable(efi_memory_desc_t *md, bool executable); |
98 | -extern void efi_memblock_x86_reserve_range(void); | |
98 | +extern int efi_memblock_x86_reserve_range(void); | |
99 | 99 | extern void efi_call_phys_prelog(void); |
100 | 100 | extern void efi_call_phys_epilog(void); |
101 | 101 |
arch/x86/kernel/setup.c
... | ... | @@ -749,10 +749,16 @@ |
749 | 749 | #endif |
750 | 750 | #ifdef CONFIG_EFI |
751 | 751 | if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, |
752 | - EFI_LOADER_SIGNATURE, 4)) { | |
752 | + "EL32", 4)) { | |
753 | 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 | 762 | #endif |
757 | 763 | |
758 | 764 | x86_init.oem.arch_setup(); |
arch/x86/platform/efi/efi.c
... | ... | @@ -26,6 +26,8 @@ |
26 | 26 | * Skip non-WB memory and ignore empty memory ranges. |
27 | 27 | */ |
28 | 28 | |
29 | +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
30 | + | |
29 | 31 | #include <linux/kernel.h> |
30 | 32 | #include <linux/init.h> |
31 | 33 | #include <linux/efi.h> |
... | ... | @@ -47,7 +49,6 @@ |
47 | 49 | #include <asm/x86_init.h> |
48 | 50 | |
49 | 51 | #define EFI_DEBUG 1 |
50 | -#define PFX "EFI: " | |
51 | 52 | |
52 | 53 | int efi_enabled; |
53 | 54 | EXPORT_SYMBOL(efi_enabled); |
... | ... | @@ -67,6 +68,9 @@ |
67 | 68 | |
68 | 69 | struct efi_memory_map memmap; |
69 | 70 | |
71 | +bool efi_64bit; | |
72 | +static bool efi_native; | |
73 | + | |
70 | 74 | static struct efi efi_phys __initdata; |
71 | 75 | static efi_system_table_t efi_systab __initdata; |
72 | 76 | |
... | ... | @@ -254,7 +258,7 @@ |
254 | 258 | |
255 | 259 | status = efi.get_time(&eft, &cap); |
256 | 260 | if (status != EFI_SUCCESS) { |
257 | - printk(KERN_ERR "Oops: efitime: can't read time!\n"); | |
261 | + pr_err("Oops: efitime: can't read time!\n"); | |
258 | 262 | return -1; |
259 | 263 | } |
260 | 264 | |
... | ... | @@ -268,7 +272,7 @@ |
268 | 272 | |
269 | 273 | status = efi.set_time(&eft); |
270 | 274 | if (status != EFI_SUCCESS) { |
271 | - printk(KERN_ERR "Oops: efitime: can't write time!\n"); | |
275 | + pr_err("Oops: efitime: can't write time!\n"); | |
272 | 276 | return -1; |
273 | 277 | } |
274 | 278 | return 0; |
... | ... | @@ -282,7 +286,7 @@ |
282 | 286 | |
283 | 287 | status = efi.get_time(&eft, &cap); |
284 | 288 | if (status != EFI_SUCCESS) |
285 | - printk(KERN_ERR "Oops: efitime: can't read time!\n"); | |
289 | + pr_err("Oops: efitime: can't read time!\n"); | |
286 | 290 | |
287 | 291 | return mktime(eft.year, eft.month, eft.day, eft.hour, |
288 | 292 | eft.minute, eft.second); |
289 | 293 | |
... | ... | @@ -338,11 +342,16 @@ |
338 | 342 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); |
339 | 343 | } |
340 | 344 | |
341 | -void __init efi_memblock_x86_reserve_range(void) | |
345 | +int __init efi_memblock_x86_reserve_range(void) | |
342 | 346 | { |
343 | 347 | unsigned long pmap; |
344 | 348 | |
345 | 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 | + } | |
346 | 355 | pmap = boot_params.efi_info.efi_memmap; |
347 | 356 | #else |
348 | 357 | pmap = (boot_params.efi_info.efi_memmap | |
... | ... | @@ -354,6 +363,8 @@ |
354 | 363 | memmap.desc_version = boot_params.efi_info.efi_memdesc_version; |
355 | 364 | memmap.desc_size = boot_params.efi_info.efi_memdesc_size; |
356 | 365 | memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); |
366 | + | |
367 | + return 0; | |
357 | 368 | } |
358 | 369 | |
359 | 370 | #if EFI_DEBUG |
... | ... | @@ -367,7 +378,7 @@ |
367 | 378 | p < memmap.map_end; |
368 | 379 | p += memmap.desc_size, i++) { |
369 | 380 | md = p; |
370 | - printk(KERN_INFO PFX "mem%02u: type=%u, attr=0x%llx, " | |
381 | + pr_info("mem%02u: type=%u, attr=0x%llx, " | |
371 | 382 | "range=[0x%016llx-0x%016llx) (%lluMB)\n", |
372 | 383 | i, md->type, md->attribute, md->phys_addr, |
373 | 384 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), |
... | ... | @@ -400,7 +411,7 @@ |
400 | 411 | memblock_is_region_reserved(start, size)) { |
401 | 412 | /* Could not reserve, skip it */ |
402 | 413 | md->num_pages = 0; |
403 | - memblock_dbg(PFX "Could not reserve boot range " | |
414 | + memblock_dbg("Could not reserve boot range " | |
404 | 415 | "[0x%010llx-0x%010llx]\n", |
405 | 416 | start, start+size-1); |
406 | 417 | } else |
407 | 418 | |
408 | 419 | |
409 | 420 | |
410 | 421 | |
411 | 422 | |
412 | 423 | |
413 | 424 | |
414 | 425 | |
415 | 426 | |
416 | 427 | |
417 | 428 | |
418 | 429 | |
419 | 430 | |
420 | 431 | |
421 | 432 | |
422 | 433 | |
423 | 434 | |
424 | 435 | |
... | ... | @@ -429,104 +440,173 @@ |
429 | 440 | } |
430 | 441 | } |
431 | 442 | |
432 | -void __init efi_init(void) | |
443 | +static int __init efi_systab_init(void *phys) | |
433 | 444 | { |
434 | - efi_config_table_t *config_tables; | |
435 | - efi_runtime_services_t *runtime; | |
436 | - efi_char16_t *c16; | |
437 | - char vendor[100] = "unknown"; | |
438 | - int i = 0; | |
439 | - void *tmp; | |
445 | + if (efi_64bit) { | |
446 | + efi_system_table_64_t *systab64; | |
447 | + u64 tmp = 0; | |
440 | 448 | |
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)); | |
441 | 481 | #ifdef CONFIG_X86_32 |
442 | - efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; | |
443 | -#else | |
444 | - efi_phys.systab = (efi_system_table_t *) | |
445 | - (boot_params.efi_info.efi_systab | | |
446 | - ((__u64)boot_params.efi_info.efi_systab_hi<<32)); | |
482 | + if (tmp >> 32) { | |
483 | + pr_err("EFI data located above 4GB, disabling EFI.\n"); | |
484 | + return -EINVAL; | |
485 | + } | |
447 | 486 | #endif |
487 | + } else { | |
488 | + efi_system_table_32_t *systab32; | |
448 | 489 | |
449 | - efi.systab = early_ioremap((unsigned long)efi_phys.systab, | |
450 | - sizeof(efi_system_table_t)); | |
451 | - if (efi.systab == NULL) | |
452 | - printk(KERN_ERR "Couldn't map the EFI system table!\n"); | |
453 | - memcpy(&efi_systab, efi.systab, sizeof(efi_system_table_t)); | |
454 | - early_iounmap(efi.systab, sizeof(efi_system_table_t)); | |
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)); | |
512 | + } | |
513 | + | |
455 | 514 | efi.systab = &efi_systab; |
456 | 515 | |
457 | 516 | /* |
458 | 517 | * Verify the EFI Table |
459 | 518 | */ |
460 | - if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | |
461 | - printk(KERN_ERR "EFI system table signature incorrect!\n"); | |
519 | + if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) { | |
520 | + pr_err("System table signature incorrect!\n"); | |
521 | + return -EINVAL; | |
522 | + } | |
462 | 523 | if ((efi.systab->hdr.revision >> 16) == 0) |
463 | - printk(KERN_ERR "Warning: EFI system table version " | |
524 | + pr_err("Warning: System table version " | |
464 | 525 | "%d.%02d, expected 1.00 or greater!\n", |
465 | 526 | efi.systab->hdr.revision >> 16, |
466 | 527 | efi.systab->hdr.revision & 0xffff); |
467 | 528 | |
468 | - /* | |
469 | - * Show what we know for posterity | |
470 | - */ | |
471 | - c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2); | |
472 | - if (c16) { | |
473 | - for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i) | |
474 | - vendor[i] = *c16++; | |
475 | - vendor[i] = '\0'; | |
476 | - } else | |
477 | - printk(KERN_ERR PFX "Could not map the firmware vendor!\n"); | |
478 | - early_iounmap(tmp, 2); | |
529 | + return 0; | |
530 | +} | |
479 | 531 | |
480 | - printk(KERN_INFO "EFI v%u.%.02u by %s\n", | |
481 | - efi.systab->hdr.revision >> 16, | |
482 | - efi.systab->hdr.revision & 0xffff, vendor); | |
532 | +static int __init efi_config_init(u64 tables, int nr_tables) | |
533 | +{ | |
534 | + void *config_tables, *tablep; | |
535 | + int i, sz; | |
483 | 536 | |
537 | + if (efi_64bit) | |
538 | + sz = sizeof(efi_config_table_64_t); | |
539 | + else | |
540 | + sz = sizeof(efi_config_table_32_t); | |
541 | + | |
484 | 542 | /* |
485 | 543 | * Let's see what config tables the firmware passed to us. |
486 | 544 | */ |
487 | - config_tables = early_ioremap( | |
488 | - efi.systab->tables, | |
489 | - efi.systab->nr_tables * sizeof(efi_config_table_t)); | |
490 | - if (config_tables == NULL) | |
491 | - printk(KERN_ERR "Could not map EFI Configuration Table!\n"); | |
545 | + config_tables = early_ioremap(tables, nr_tables * sz); | |
546 | + if (config_tables == NULL) { | |
547 | + pr_err("Could not map Configuration table!\n"); | |
548 | + return -ENOMEM; | |
549 | + } | |
492 | 550 | |
493 | - printk(KERN_INFO); | |
551 | + tablep = config_tables; | |
552 | + pr_info(""); | |
494 | 553 | for (i = 0; i < efi.systab->nr_tables; i++) { |
495 | - if (!efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID)) { | |
496 | - efi.mps = config_tables[i].table; | |
497 | - printk(" MPS=0x%lx ", config_tables[i].table); | |
498 | - } else if (!efi_guidcmp(config_tables[i].guid, | |
499 | - ACPI_20_TABLE_GUID)) { | |
500 | - efi.acpi20 = config_tables[i].table; | |
501 | - printk(" ACPI 2.0=0x%lx ", config_tables[i].table); | |
502 | - } else if (!efi_guidcmp(config_tables[i].guid, | |
503 | - ACPI_TABLE_GUID)) { | |
504 | - efi.acpi = config_tables[i].table; | |
505 | - printk(" ACPI=0x%lx ", config_tables[i].table); | |
506 | - } else if (!efi_guidcmp(config_tables[i].guid, | |
507 | - SMBIOS_TABLE_GUID)) { | |
508 | - efi.smbios = config_tables[i].table; | |
509 | - printk(" SMBIOS=0x%lx ", config_tables[i].table); | |
554 | + efi_guid_t guid; | |
555 | + unsigned long table; | |
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 | + } | |
575 | + if (!efi_guidcmp(guid, MPS_TABLE_GUID)) { | |
576 | + efi.mps = table; | |
577 | + pr_cont(" MPS=0x%lx ", table); | |
578 | + } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) { | |
579 | + efi.acpi20 = table; | |
580 | + pr_cont(" ACPI 2.0=0x%lx ", table); | |
581 | + } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) { | |
582 | + efi.acpi = table; | |
583 | + pr_cont(" ACPI=0x%lx ", table); | |
584 | + } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) { | |
585 | + efi.smbios = table; | |
586 | + pr_cont(" SMBIOS=0x%lx ", table); | |
510 | 587 | #ifdef CONFIG_X86_UV |
511 | - } else if (!efi_guidcmp(config_tables[i].guid, | |
512 | - UV_SYSTEM_TABLE_GUID)) { | |
513 | - efi.uv_systab = config_tables[i].table; | |
514 | - printk(" UVsystab=0x%lx ", config_tables[i].table); | |
588 | + } else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) { | |
589 | + efi.uv_systab = table; | |
590 | + pr_cont(" UVsystab=0x%lx ", table); | |
515 | 591 | #endif |
516 | - } else if (!efi_guidcmp(config_tables[i].guid, | |
517 | - HCDP_TABLE_GUID)) { | |
518 | - efi.hcdp = config_tables[i].table; | |
519 | - printk(" HCDP=0x%lx ", config_tables[i].table); | |
520 | - } else if (!efi_guidcmp(config_tables[i].guid, | |
521 | - UGA_IO_PROTOCOL_GUID)) { | |
522 | - efi.uga = config_tables[i].table; | |
523 | - printk(" UGA=0x%lx ", config_tables[i].table); | |
592 | + } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) { | |
593 | + efi.hcdp = table; | |
594 | + pr_cont(" HCDP=0x%lx ", table); | |
595 | + } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) { | |
596 | + efi.uga = table; | |
597 | + pr_cont(" UGA=0x%lx ", table); | |
524 | 598 | } |
599 | + tablep += sz; | |
525 | 600 | } |
526 | - printk("\n"); | |
527 | - early_iounmap(config_tables, | |
528 | - efi.systab->nr_tables * sizeof(efi_config_table_t)); | |
601 | + pr_cont("\n"); | |
602 | + early_iounmap(config_tables, efi.systab->nr_tables * sz); | |
603 | + return 0; | |
604 | +} | |
529 | 605 | |
606 | +static int __init efi_runtime_init(void) | |
607 | +{ | |
608 | + efi_runtime_services_t *runtime; | |
609 | + | |
530 | 610 | /* |
531 | 611 | * Check out the runtime services table. We need to map |
532 | 612 | * the runtime services table so that we can grab the physical |
533 | 613 | |
534 | 614 | |
535 | 615 | |
536 | 616 | |
537 | 617 | |
538 | 618 | |
... | ... | @@ -535,45 +615,118 @@ |
535 | 615 | */ |
536 | 616 | runtime = early_ioremap((unsigned long)efi.systab->runtime, |
537 | 617 | sizeof(efi_runtime_services_t)); |
538 | - if (runtime != NULL) { | |
539 | - /* | |
540 | - * We will only need *early* access to the following | |
541 | - * two EFI runtime services before set_virtual_address_map | |
542 | - * is invoked. | |
543 | - */ | |
544 | - efi_phys.get_time = (efi_get_time_t *)runtime->get_time; | |
545 | - efi_phys.set_virtual_address_map = | |
546 | - (efi_set_virtual_address_map_t *) | |
547 | - runtime->set_virtual_address_map; | |
548 | - /* | |
549 | - * Make efi_get_time can be called before entering | |
550 | - * virtual mode. | |
551 | - */ | |
552 | - efi.get_time = phys_efi_get_time; | |
553 | - } else | |
554 | - printk(KERN_ERR "Could not map the EFI runtime service " | |
555 | - "table!\n"); | |
618 | + if (!runtime) { | |
619 | + pr_err("Could not map the runtime service table!\n"); | |
620 | + return -ENOMEM; | |
621 | + } | |
622 | + /* | |
623 | + * We will only need *early* access to the following | |
624 | + * two EFI runtime services before set_virtual_address_map | |
625 | + * is invoked. | |
626 | + */ | |
627 | + efi_phys.get_time = (efi_get_time_t *)runtime->get_time; | |
628 | + efi_phys.set_virtual_address_map = | |
629 | + (efi_set_virtual_address_map_t *) | |
630 | + runtime->set_virtual_address_map; | |
631 | + /* | |
632 | + * Make efi_get_time can be called before entering | |
633 | + * virtual mode. | |
634 | + */ | |
635 | + efi.get_time = phys_efi_get_time; | |
556 | 636 | early_iounmap(runtime, sizeof(efi_runtime_services_t)); |
557 | 637 | |
638 | + return 0; | |
639 | +} | |
640 | + | |
641 | +static int __init efi_memmap_init(void) | |
642 | +{ | |
558 | 643 | /* Map the EFI memory map */ |
559 | 644 | memmap.map = early_ioremap((unsigned long)memmap.phys_map, |
560 | 645 | memmap.nr_map * memmap.desc_size); |
561 | - if (memmap.map == NULL) | |
562 | - printk(KERN_ERR "Could not map the EFI memory map!\n"); | |
646 | + if (memmap.map == NULL) { | |
647 | + pr_err("Could not map the memory map!\n"); | |
648 | + return -ENOMEM; | |
649 | + } | |
563 | 650 | memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); |
564 | 651 | |
565 | - if (memmap.desc_size != sizeof(efi_memory_desc_t)) | |
566 | - printk(KERN_WARNING | |
567 | - "Kernel-defined memdesc doesn't match the one from EFI!\n"); | |
568 | - | |
569 | 652 | if (add_efi_memmap) |
570 | 653 | do_add_efi_memmap(); |
571 | 654 | |
655 | + return 0; | |
656 | +} | |
657 | + | |
658 | +void __init efi_init(void) | |
659 | +{ | |
660 | + efi_char16_t *c16; | |
661 | + char vendor[100] = "unknown"; | |
662 | + int i = 0; | |
663 | + void *tmp; | |
664 | + | |
572 | 665 | #ifdef CONFIG_X86_32 |
573 | - x86_platform.get_wallclock = efi_get_time; | |
574 | - x86_platform.set_wallclock = efi_set_rtc_mmss; | |
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 | + } | |
672 | + efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; | |
673 | + efi_native = !efi_64bit; | |
674 | +#else | |
675 | + efi_phys.systab = (efi_system_table_t *) | |
676 | + (boot_params.efi_info.efi_systab | | |
677 | + ((__u64)boot_params.efi_info.efi_systab_hi<<32)); | |
678 | + efi_native = efi_64bit; | |
575 | 679 | #endif |
576 | 680 | |
681 | + if (efi_systab_init(efi_phys.systab)) { | |
682 | + efi_enabled = 0; | |
683 | + return; | |
684 | + } | |
685 | + | |
686 | + /* | |
687 | + * Show what we know for posterity | |
688 | + */ | |
689 | + c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2); | |
690 | + if (c16) { | |
691 | + for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i) | |
692 | + vendor[i] = *c16++; | |
693 | + vendor[i] = '\0'; | |
694 | + } else | |
695 | + pr_err("Could not map the firmware vendor!\n"); | |
696 | + early_iounmap(tmp, 2); | |
697 | + | |
698 | + pr_info("EFI v%u.%.02u by %s\n", | |
699 | + efi.systab->hdr.revision >> 16, | |
700 | + efi.systab->hdr.revision & 0xffff, vendor); | |
701 | + | |
702 | + if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) { | |
703 | + efi_enabled = 0; | |
704 | + return; | |
705 | + } | |
706 | + | |
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()) { | |
715 | + efi_enabled = 0; | |
716 | + return; | |
717 | + } | |
718 | + | |
719 | + if (efi_memmap_init()) { | |
720 | + efi_enabled = 0; | |
721 | + return; | |
722 | + } | |
723 | +#ifdef CONFIG_X86_32 | |
724 | + if (efi_native) { | |
725 | + x86_platform.get_wallclock = efi_get_time; | |
726 | + x86_platform.set_wallclock = efi_set_rtc_mmss; | |
727 | + } | |
728 | +#endif | |
729 | + | |
577 | 730 | #if EFI_DEBUG |
578 | 731 | print_efi_memmap(); |
579 | 732 | #endif |
... | ... | @@ -629,6 +782,14 @@ |
629 | 782 | |
630 | 783 | efi.systab = NULL; |
631 | 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 | + | |
632 | 793 | /* Merge contiguous regions of the same type and attribute */ |
633 | 794 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
634 | 795 | u64 prev_size; |
... | ... | @@ -677,7 +838,7 @@ |
677 | 838 | md->virt_addr = (u64) (unsigned long) va; |
678 | 839 | |
679 | 840 | if (!va) { |
680 | - printk(KERN_ERR PFX "ioremap of 0x%llX failed!\n", | |
841 | + pr_err("ioremap of 0x%llX failed!\n", | |
681 | 842 | (unsigned long long)md->phys_addr); |
682 | 843 | continue; |
683 | 844 | } |
... | ... | @@ -711,8 +872,8 @@ |
711 | 872 | (efi_memory_desc_t *)__pa(new_memmap)); |
712 | 873 | |
713 | 874 | if (status != EFI_SUCCESS) { |
714 | - printk(KERN_ALERT "Unable to switch EFI into virtual mode " | |
715 | - "(status=%lx)!\n", status); | |
875 | + pr_alert("Unable to switch EFI into virtual mode " | |
876 | + "(status=%lx)!\n", status); | |
716 | 877 | panic("EFI call to SetVirtualAddressMap() failed!"); |
717 | 878 | } |
718 | 879 | |
... | ... | @@ -744,6 +905,8 @@ |
744 | 905 | efi.query_capsule_caps = virt_efi_query_capsule_caps; |
745 | 906 | if (__supported_pte_mask & _PAGE_NX) |
746 | 907 | runtime_code_page_mkexec(); |
908 | + | |
909 | +out: | |
747 | 910 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); |
748 | 911 | memmap.map = NULL; |
749 | 912 | kfree(new_memmap); |
include/linux/efi.h
... | ... | @@ -315,6 +315,16 @@ |
315 | 315 | |
316 | 316 | typedef struct { |
317 | 317 | efi_guid_t guid; |
318 | + u64 table; | |
319 | +} efi_config_table_64_t; | |
320 | + | |
321 | +typedef struct { | |
322 | + efi_guid_t guid; | |
323 | + u32 table; | |
324 | +} efi_config_table_32_t; | |
325 | + | |
326 | +typedef struct { | |
327 | + efi_guid_t guid; | |
318 | 328 | unsigned long table; |
319 | 329 | } efi_config_table_t; |
320 | 330 | |
... | ... | @@ -329,6 +339,40 @@ |
329 | 339 | |
330 | 340 | typedef struct { |
331 | 341 | efi_table_hdr_t hdr; |
342 | + u64 fw_vendor; /* physical addr of CHAR16 vendor string */ | |
343 | + u32 fw_revision; | |
344 | + u32 __pad1; | |
345 | + u64 con_in_handle; | |
346 | + u64 con_in; | |
347 | + u64 con_out_handle; | |
348 | + u64 con_out; | |
349 | + u64 stderr_handle; | |
350 | + u64 stderr; | |
351 | + u64 runtime; | |
352 | + u64 boottime; | |
353 | + u32 nr_tables; | |
354 | + u32 __pad2; | |
355 | + u64 tables; | |
356 | +} efi_system_table_64_t; | |
357 | + | |
358 | +typedef struct { | |
359 | + efi_table_hdr_t hdr; | |
360 | + u32 fw_vendor; /* physical addr of CHAR16 vendor string */ | |
361 | + u32 fw_revision; | |
362 | + u32 con_in_handle; | |
363 | + u32 con_in; | |
364 | + u32 con_out_handle; | |
365 | + u32 con_out; | |
366 | + u32 stderr_handle; | |
367 | + u32 stderr; | |
368 | + u32 runtime; | |
369 | + u32 boottime; | |
370 | + u32 nr_tables; | |
371 | + u32 tables; | |
372 | +} efi_system_table_32_t; | |
373 | + | |
374 | +typedef struct { | |
375 | + efi_table_hdr_t hdr; | |
332 | 376 | unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */ |
333 | 377 | u32 fw_revision; |
334 | 378 | unsigned long con_in_handle; |
... | ... | @@ -497,6 +541,7 @@ |
497 | 541 | #ifdef CONFIG_EFI |
498 | 542 | # ifdef CONFIG_X86 |
499 | 543 | extern int efi_enabled; |
544 | + extern bool efi_64bit; | |
500 | 545 | # else |
501 | 546 | # define efi_enabled 1 |
502 | 547 | # endif |