diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-16 16:06:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-16 16:06:27 -0400 |
commit | 49817c33433a3cd6f320b13699e6746cc39b453b (patch) | |
tree | 1eb8c4a4d585e648b0783741c02ab611149971d9 | |
parent | 230e51f21101e49c8d73018d414adbd0d57459a1 (diff) | |
parent | 6c5450ef66816216e574885cf8d3ddb31ef77428 (diff) |
Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI updates from Ingo Molnar:
"The main changes in this cycle were:
- Drop the unused EFI_SYSTEM_TABLES efi.flags bit and ensure the
ARM/arm64 EFI System Table mapping is read-only (Ard Biesheuvel)
- Add a comment to explain that one of the code paths in the x86/pat
code is only executed for EFI boot (Matt Fleming)
- Improve Secure Boot status checks on arm64 and handle unexpected
errors (Linn Crosetto)
- Remove the global EFI memory map variable 'memmap' as the same
information is already available in efi::memmap (Matt Fleming)
- Add EFI Memory Attribute table support for ARM/arm64 (Ard
Biesheuvel)
- Add EFI GOP framebuffer support for ARM/arm64 (Ard Biesheuvel)
- Add EFI Bootloader Control driver for storing reboot(2) data in EFI
variables for consumption by bootloaders (Jeremy Compostella)
- Add Core EFI capsule support (Matt Fleming)
- Add EFI capsule char driver (Kweh, Hock Leong)
- Unify EFI memory map code for ARM and arm64 (Ard Biesheuvel)
- Add generic EFI support for detecting when firmware corrupts CPU
status register bits (like IRQ flags) when performing EFI runtime
service calls (Mark Rutland)
... and other misc cleanups"
* 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (46 commits)
efivarfs: Make efivarfs_file_ioctl() static
efi: Merge boolean flag arguments
efi/capsule: Move 'capsule' to the stack in efi_capsule_supported()
efibc: Fix excessive stack footprint warning
efi/capsule: Make efi_capsule_pending() lockless
efi: Remove unnecessary (and buggy) .memmap initialization from the Xen EFI driver
efi/runtime-wrappers: Remove ARCH_EFI_IRQ_FLAGS_MASK #ifdef
x86/efi: Enable runtime call flag checking
arm/efi: Enable runtime call flag checking
arm64/efi: Enable runtime call flag checking
efi/runtime-wrappers: Detect firmware IRQ flag corruption
efi/runtime-wrappers: Remove redundant #ifdefs
x86/efi: Move to generic {__,}efi_call_virt()
arm/efi: Move to generic {__,}efi_call_virt()
arm64/efi: Move to generic {__,}efi_call_virt()
efi/runtime-wrappers: Add {__,}efi_call_virt() templates
efi/arm-init: Reserve rather than unmap the memory map for ARM as well
efi: Add misc char driver interface to update EFI firmware
x86/efi: Force EFI reboot to process pending capsules
efi: Add 'capsule' update support
...
41 files changed, 2097 insertions, 713 deletions
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index e0eea72deb87..a708fa1f0905 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h | |||
@@ -17,34 +17,28 @@ | |||
17 | #include <asm/mach/map.h> | 17 | #include <asm/mach/map.h> |
18 | #include <asm/mmu_context.h> | 18 | #include <asm/mmu_context.h> |
19 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
20 | #include <asm/ptrace.h> | ||
20 | 21 | ||
21 | #ifdef CONFIG_EFI | 22 | #ifdef CONFIG_EFI |
22 | void efi_init(void); | 23 | void efi_init(void); |
23 | 24 | ||
24 | int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); | 25 | int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); |
26 | int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); | ||
25 | 27 | ||
26 | #define efi_call_virt(f, ...) \ | 28 | #define arch_efi_call_virt_setup() efi_virtmap_load() |
27 | ({ \ | 29 | #define arch_efi_call_virt_teardown() efi_virtmap_unload() |
28 | efi_##f##_t *__f; \ | ||
29 | efi_status_t __s; \ | ||
30 | \ | ||
31 | efi_virtmap_load(); \ | ||
32 | __f = efi.systab->runtime->f; \ | ||
33 | __s = __f(__VA_ARGS__); \ | ||
34 | efi_virtmap_unload(); \ | ||
35 | __s; \ | ||
36 | }) | ||
37 | 30 | ||
38 | #define __efi_call_virt(f, ...) \ | 31 | #define arch_efi_call_virt(f, args...) \ |
39 | ({ \ | 32 | ({ \ |
40 | efi_##f##_t *__f; \ | 33 | efi_##f##_t *__f; \ |
41 | \ | ||
42 | efi_virtmap_load(); \ | ||
43 | __f = efi.systab->runtime->f; \ | 34 | __f = efi.systab->runtime->f; \ |
44 | __f(__VA_ARGS__); \ | 35 | __f(args); \ |
45 | efi_virtmap_unload(); \ | ||
46 | }) | 36 | }) |
47 | 37 | ||
38 | #define ARCH_EFI_IRQ_FLAGS_MASK \ | ||
39 | (PSR_J_BIT | PSR_E_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | \ | ||
40 | PSR_T_BIT | MODE_MASK) | ||
41 | |||
48 | static inline void efi_set_pgd(struct mm_struct *mm) | 42 | static inline void efi_set_pgd(struct mm_struct *mm) |
49 | { | 43 | { |
50 | check_and_switch_context(mm, NULL); | 44 | check_and_switch_context(mm, NULL); |
@@ -59,7 +53,16 @@ void efi_virtmap_unload(void); | |||
59 | 53 | ||
60 | /* arch specific definitions used by the stub code */ | 54 | /* arch specific definitions used by the stub code */ |
61 | 55 | ||
62 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) | 56 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) |
57 | #define __efi_call_early(f, ...) f(__VA_ARGS__) | ||
58 | #define efi_is_64bit() (false) | ||
59 | |||
60 | struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg); | ||
61 | void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si); | ||
62 | |||
63 | static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) | ||
64 | { | ||
65 | } | ||
63 | 66 | ||
64 | /* | 67 | /* |
65 | * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, | 68 | * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, |
diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c index ff8a9d8acfac..9f43ba012d10 100644 --- a/arch/arm/kernel/efi.c +++ b/arch/arm/kernel/efi.c | |||
@@ -11,6 +11,41 @@ | |||
11 | #include <asm/mach/map.h> | 11 | #include <asm/mach/map.h> |
12 | #include <asm/mmu_context.h> | 12 | #include <asm/mmu_context.h> |
13 | 13 | ||
14 | static int __init set_permissions(pte_t *ptep, pgtable_t token, | ||
15 | unsigned long addr, void *data) | ||
16 | { | ||
17 | efi_memory_desc_t *md = data; | ||
18 | pte_t pte = *ptep; | ||
19 | |||
20 | if (md->attribute & EFI_MEMORY_RO) | ||
21 | pte = set_pte_bit(pte, __pgprot(L_PTE_RDONLY)); | ||
22 | if (md->attribute & EFI_MEMORY_XP) | ||
23 | pte = set_pte_bit(pte, __pgprot(L_PTE_XN)); | ||
24 | set_pte_ext(ptep, pte, PTE_EXT_NG); | ||
25 | return 0; | ||
26 | } | ||
27 | |||
28 | int __init efi_set_mapping_permissions(struct mm_struct *mm, | ||
29 | efi_memory_desc_t *md) | ||
30 | { | ||
31 | unsigned long base, size; | ||
32 | |||
33 | base = md->virt_addr; | ||
34 | size = md->num_pages << EFI_PAGE_SHIFT; | ||
35 | |||
36 | /* | ||
37 | * We can only use apply_to_page_range() if we can guarantee that the | ||
38 | * entire region was mapped using pages. This should be the case if the | ||
39 | * region does not cover any naturally aligned SECTION_SIZE sized | ||
40 | * blocks. | ||
41 | */ | ||
42 | if (round_down(base + size, SECTION_SIZE) < | ||
43 | round_up(base, SECTION_SIZE) + SECTION_SIZE) | ||
44 | return apply_to_page_range(mm, base, size, set_permissions, md); | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
14 | int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) | 49 | int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) |
15 | { | 50 | { |
16 | struct map_desc desc = { | 51 | struct map_desc desc = { |
@@ -34,5 +69,11 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) | |||
34 | desc.type = MT_DEVICE; | 69 | desc.type = MT_DEVICE; |
35 | 70 | ||
36 | create_mapping_late(mm, &desc, true); | 71 | create_mapping_late(mm, &desc, true); |
72 | |||
73 | /* | ||
74 | * If stricter permissions were specified, apply them now. | ||
75 | */ | ||
76 | if (md->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP)) | ||
77 | return efi_set_mapping_permissions(mm, md); | ||
37 | return 0; | 78 | return 0; |
38 | } | 79 | } |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 2c4bea39cf22..7d4e2850910c 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -883,7 +883,8 @@ static void __init request_standard_resources(const struct machine_desc *mdesc) | |||
883 | request_resource(&ioport_resource, &lp2); | 883 | request_resource(&ioport_resource, &lp2); |
884 | } | 884 | } |
885 | 885 | ||
886 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) | 886 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) || \ |
887 | defined(CONFIG_EFI) | ||
887 | struct screen_info screen_info = { | 888 | struct screen_info screen_info = { |
888 | .orig_video_lines = 30, | 889 | .orig_video_lines = 30, |
889 | .orig_video_cols = 80, | 890 | .orig_video_cols = 80, |
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 8e88a696c9cb..622db3c6474e 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <asm/io.h> | 4 | #include <asm/io.h> |
5 | #include <asm/mmu_context.h> | 5 | #include <asm/mmu_context.h> |
6 | #include <asm/neon.h> | 6 | #include <asm/neon.h> |
7 | #include <asm/ptrace.h> | ||
7 | #include <asm/tlbflush.h> | 8 | #include <asm/tlbflush.h> |
8 | 9 | ||
9 | #ifdef CONFIG_EFI | 10 | #ifdef CONFIG_EFI |
@@ -14,32 +15,29 @@ extern void efi_init(void); | |||
14 | 15 | ||
15 | int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); | 16 | int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); |
16 | 17 | ||
17 | #define efi_call_virt(f, ...) \ | 18 | #define efi_set_mapping_permissions efi_create_mapping |
19 | |||
20 | #define arch_efi_call_virt_setup() \ | ||
18 | ({ \ | 21 | ({ \ |
19 | efi_##f##_t *__f; \ | ||
20 | efi_status_t __s; \ | ||
21 | \ | ||
22 | kernel_neon_begin(); \ | 22 | kernel_neon_begin(); \ |
23 | efi_virtmap_load(); \ | 23 | efi_virtmap_load(); \ |
24 | __f = efi.systab->runtime->f; \ | ||
25 | __s = __f(__VA_ARGS__); \ | ||
26 | efi_virtmap_unload(); \ | ||
27 | kernel_neon_end(); \ | ||
28 | __s; \ | ||
29 | }) | 24 | }) |
30 | 25 | ||
31 | #define __efi_call_virt(f, ...) \ | 26 | #define arch_efi_call_virt(f, args...) \ |
32 | ({ \ | 27 | ({ \ |
33 | efi_##f##_t *__f; \ | 28 | efi_##f##_t *__f; \ |
34 | \ | ||
35 | kernel_neon_begin(); \ | ||
36 | efi_virtmap_load(); \ | ||
37 | __f = efi.systab->runtime->f; \ | 29 | __f = efi.systab->runtime->f; \ |
38 | __f(__VA_ARGS__); \ | 30 | __f(args); \ |
31 | }) | ||
32 | |||
33 | #define arch_efi_call_virt_teardown() \ | ||
34 | ({ \ | ||
39 | efi_virtmap_unload(); \ | 35 | efi_virtmap_unload(); \ |
40 | kernel_neon_end(); \ | 36 | kernel_neon_end(); \ |
41 | }) | 37 | }) |
42 | 38 | ||
39 | #define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT) | ||
40 | |||
43 | /* arch specific definitions used by the stub code */ | 41 | /* arch specific definitions used by the stub code */ |
44 | 42 | ||
45 | /* | 43 | /* |
@@ -50,7 +48,16 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); | |||
50 | #define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */ | 48 | #define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */ |
51 | #define MAX_FDT_OFFSET SZ_512M | 49 | #define MAX_FDT_OFFSET SZ_512M |
52 | 50 | ||
53 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) | 51 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) |
52 | #define __efi_call_early(f, ...) f(__VA_ARGS__) | ||
53 | #define efi_is_64bit() (true) | ||
54 | |||
55 | #define alloc_screen_info(x...) &screen_info | ||
56 | #define free_screen_info(x...) | ||
57 | |||
58 | static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) | ||
59 | { | ||
60 | } | ||
54 | 61 | ||
55 | #define EFI_ALLOC_ALIGN SZ_64K | 62 | #define EFI_ALLOC_ALIGN SZ_64K |
56 | 63 | ||
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index b6abc852f2a1..78f52488f9ff 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c | |||
@@ -17,22 +17,51 @@ | |||
17 | 17 | ||
18 | #include <asm/efi.h> | 18 | #include <asm/efi.h> |
19 | 19 | ||
20 | int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) | 20 | /* |
21 | * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be | ||
22 | * executable, everything else can be mapped with the XN bits | ||
23 | * set. Also take the new (optional) RO/XP bits into account. | ||
24 | */ | ||
25 | static __init pteval_t create_mapping_protection(efi_memory_desc_t *md) | ||
21 | { | 26 | { |
22 | pteval_t prot_val; | 27 | u64 attr = md->attribute; |
28 | u32 type = md->type; | ||
23 | 29 | ||
24 | /* | 30 | if (type == EFI_MEMORY_MAPPED_IO) |
25 | * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be | 31 | return PROT_DEVICE_nGnRE; |
26 | * executable, everything else can be mapped with the XN bits | 32 | |
27 | * set. | 33 | if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr), |
28 | */ | 34 | "UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?")) |
29 | if ((md->attribute & EFI_MEMORY_WB) == 0) | 35 | /* |
30 | prot_val = PROT_DEVICE_nGnRE; | 36 | * If the region is not aligned to the page size of the OS, we |
31 | else if (md->type == EFI_RUNTIME_SERVICES_CODE || | 37 | * can not use strict permissions, since that would also affect |
32 | !PAGE_ALIGNED(md->phys_addr)) | 38 | * the mapping attributes of the adjacent regions. |
33 | prot_val = pgprot_val(PAGE_KERNEL_EXEC); | 39 | */ |
34 | else | 40 | return pgprot_val(PAGE_KERNEL_EXEC); |
35 | prot_val = pgprot_val(PAGE_KERNEL); | 41 | |
42 | /* R-- */ | ||
43 | if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) == | ||
44 | (EFI_MEMORY_XP | EFI_MEMORY_RO)) | ||
45 | return pgprot_val(PAGE_KERNEL_RO); | ||
46 | |||
47 | /* R-X */ | ||
48 | if (attr & EFI_MEMORY_RO) | ||
49 | return pgprot_val(PAGE_KERNEL_ROX); | ||
50 | |||
51 | /* RW- */ | ||
52 | if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE) | ||
53 | return pgprot_val(PAGE_KERNEL); | ||
54 | |||
55 | /* RWX */ | ||
56 | return pgprot_val(PAGE_KERNEL_EXEC); | ||
57 | } | ||
58 | |||
59 | /* we will fill this structure from the stub, so don't put it in .bss */ | ||
60 | struct screen_info screen_info __section(.data); | ||
61 | |||
62 | int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) | ||
63 | { | ||
64 | pteval_t prot_val = create_mapping_protection(md); | ||
36 | 65 | ||
37 | create_pgd_mapping(mm, md->phys_addr, md->virt_addr, | 66 | create_pgd_mapping(mm, md->phys_addr, md->virt_addr, |
38 | md->num_pages << EFI_PAGE_SHIFT, | 67 | md->num_pages << EFI_PAGE_SHIFT, |
diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h index 5e360ce88f10..1428849aece8 100644 --- a/arch/arm64/kernel/image.h +++ b/arch/arm64/kernel/image.h | |||
@@ -112,6 +112,7 @@ __efistub___memset = KALLSYMS_HIDE(__pi_memset); | |||
112 | __efistub__text = KALLSYMS_HIDE(_text); | 112 | __efistub__text = KALLSYMS_HIDE(_text); |
113 | __efistub__end = KALLSYMS_HIDE(_end); | 113 | __efistub__end = KALLSYMS_HIDE(_end); |
114 | __efistub__edata = KALLSYMS_HIDE(_edata); | 114 | __efistub__edata = KALLSYMS_HIDE(_edata); |
115 | __efistub_screen_info = KALLSYMS_HIDE(screen_info); | ||
115 | 116 | ||
116 | #endif | 117 | #endif |
117 | 118 | ||
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 300dac3702f1..bf0865cd438a 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
@@ -531,8 +531,6 @@ efi_init (void) | |||
531 | efi.systab->hdr.revision >> 16, | 531 | efi.systab->hdr.revision >> 16, |
532 | efi.systab->hdr.revision & 0xffff, vendor); | 532 | efi.systab->hdr.revision & 0xffff, vendor); |
533 | 533 | ||
534 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); | ||
535 | |||
536 | palo_phys = EFI_INVALID_TABLE_ADDR; | 534 | palo_phys = EFI_INVALID_TABLE_ADDR; |
537 | 535 | ||
538 | if (efi_config_init(arch_tables) != 0) | 536 | if (efi_config_init(arch_tables) != 0) |
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 583d539a4197..52fef606bc54 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -571,312 +571,6 @@ free_handle: | |||
571 | efi_call_early(free_pool, pci_handle); | 571 | efi_call_early(free_pool, pci_handle); |
572 | } | 572 | } |
573 | 573 | ||
574 | static void | ||
575 | setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line, | ||
576 | struct efi_pixel_bitmask pixel_info, int pixel_format) | ||
577 | { | ||
578 | if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { | ||
579 | si->lfb_depth = 32; | ||
580 | si->lfb_linelength = pixels_per_scan_line * 4; | ||
581 | si->red_size = 8; | ||
582 | si->red_pos = 0; | ||
583 | si->green_size = 8; | ||
584 | si->green_pos = 8; | ||
585 | si->blue_size = 8; | ||
586 | si->blue_pos = 16; | ||
587 | si->rsvd_size = 8; | ||
588 | si->rsvd_pos = 24; | ||
589 | } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) { | ||
590 | si->lfb_depth = 32; | ||
591 | si->lfb_linelength = pixels_per_scan_line * 4; | ||
592 | si->red_size = 8; | ||
593 | si->red_pos = 16; | ||
594 | si->green_size = 8; | ||
595 | si->green_pos = 8; | ||
596 | si->blue_size = 8; | ||
597 | si->blue_pos = 0; | ||
598 | si->rsvd_size = 8; | ||
599 | si->rsvd_pos = 24; | ||
600 | } else if (pixel_format == PIXEL_BIT_MASK) { | ||
601 | find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size); | ||
602 | find_bits(pixel_info.green_mask, &si->green_pos, | ||
603 | &si->green_size); | ||
604 | find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size); | ||
605 | find_bits(pixel_info.reserved_mask, &si->rsvd_pos, | ||
606 | &si->rsvd_size); | ||
607 | si->lfb_depth = si->red_size + si->green_size + | ||
608 | si->blue_size + si->rsvd_size; | ||
609 | si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; | ||
610 | } else { | ||
611 | si->lfb_depth = 4; | ||
612 | si->lfb_linelength = si->lfb_width / 2; | ||
613 | si->red_size = 0; | ||
614 | si->red_pos = 0; | ||
615 | si->green_size = 0; | ||
616 | si->green_pos = 0; | ||
617 | si->blue_size = 0; | ||
618 | si->blue_pos = 0; | ||
619 | si->rsvd_size = 0; | ||
620 | si->rsvd_pos = 0; | ||
621 | } | ||
622 | } | ||
623 | |||
624 | static efi_status_t | ||
625 | __gop_query32(struct efi_graphics_output_protocol_32 *gop32, | ||
626 | struct efi_graphics_output_mode_info **info, | ||
627 | unsigned long *size, u64 *fb_base) | ||
628 | { | ||
629 | struct efi_graphics_output_protocol_mode_32 *mode; | ||
630 | efi_status_t status; | ||
631 | unsigned long m; | ||
632 | |||
633 | m = gop32->mode; | ||
634 | mode = (struct efi_graphics_output_protocol_mode_32 *)m; | ||
635 | |||
636 | status = efi_early->call(gop32->query_mode, gop32, | ||
637 | mode->mode, size, info); | ||
638 | if (status != EFI_SUCCESS) | ||
639 | return status; | ||
640 | |||
641 | *fb_base = mode->frame_buffer_base; | ||
642 | return status; | ||
643 | } | ||
644 | |||
645 | static efi_status_t | ||
646 | setup_gop32(struct screen_info *si, efi_guid_t *proto, | ||
647 | unsigned long size, void **gop_handle) | ||
648 | { | ||
649 | struct efi_graphics_output_protocol_32 *gop32, *first_gop; | ||
650 | unsigned long nr_gops; | ||
651 | u16 width, height; | ||
652 | u32 pixels_per_scan_line; | ||
653 | u32 ext_lfb_base; | ||
654 | u64 fb_base; | ||
655 | struct efi_pixel_bitmask pixel_info; | ||
656 | int pixel_format; | ||
657 | efi_status_t status; | ||
658 | u32 *handles = (u32 *)(unsigned long)gop_handle; | ||
659 | int i; | ||
660 | |||
661 | first_gop = NULL; | ||
662 | gop32 = NULL; | ||
663 | |||
664 | nr_gops = size / sizeof(u32); | ||
665 | for (i = 0; i < nr_gops; i++) { | ||
666 | struct efi_graphics_output_mode_info *info = NULL; | ||
667 | efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; | ||
668 | bool conout_found = false; | ||
669 | void *dummy = NULL; | ||
670 | u32 h = handles[i]; | ||
671 | u64 current_fb_base; | ||
672 | |||
673 | status = efi_call_early(handle_protocol, h, | ||
674 | proto, (void **)&gop32); | ||
675 | if (status != EFI_SUCCESS) | ||
676 | continue; | ||
677 | |||
678 | status = efi_call_early(handle_protocol, h, | ||
679 | &conout_proto, &dummy); | ||
680 | if (status == EFI_SUCCESS) | ||
681 | conout_found = true; | ||
682 | |||
683 | status = __gop_query32(gop32, &info, &size, ¤t_fb_base); | ||
684 | if (status == EFI_SUCCESS && (!first_gop || conout_found)) { | ||
685 | /* | ||
686 | * Systems that use the UEFI Console Splitter may | ||
687 | * provide multiple GOP devices, not all of which are | ||
688 | * backed by real hardware. The workaround is to search | ||
689 | * for a GOP implementing the ConOut protocol, and if | ||
690 | * one isn't found, to just fall back to the first GOP. | ||
691 | */ | ||
692 | width = info->horizontal_resolution; | ||
693 | height = info->vertical_resolution; | ||
694 | pixel_format = info->pixel_format; | ||
695 | pixel_info = info->pixel_information; | ||
696 | pixels_per_scan_line = info->pixels_per_scan_line; | ||
697 | fb_base = current_fb_base; | ||
698 | |||
699 | /* | ||
700 | * Once we've found a GOP supporting ConOut, | ||
701 | * don't bother looking any further. | ||
702 | */ | ||
703 | first_gop = gop32; | ||
704 | if (conout_found) | ||
705 | break; | ||
706 | } | ||
707 | } | ||
708 | |||
709 | /* Did we find any GOPs? */ | ||
710 | if (!first_gop) | ||
711 | goto out; | ||
712 | |||
713 | /* EFI framebuffer */ | ||
714 | si->orig_video_isVGA = VIDEO_TYPE_EFI; | ||
715 | |||
716 | si->lfb_width = width; | ||
717 | si->lfb_height = height; | ||
718 | si->lfb_base = fb_base; | ||
719 | |||
720 | ext_lfb_base = (u64)(unsigned long)fb_base >> 32; | ||
721 | if (ext_lfb_base) { | ||
722 | si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; | ||
723 | si->ext_lfb_base = ext_lfb_base; | ||
724 | } | ||
725 | |||
726 | si->pages = 1; | ||
727 | |||
728 | setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); | ||
729 | |||
730 | si->lfb_size = si->lfb_linelength * si->lfb_height; | ||
731 | |||
732 | si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; | ||
733 | out: | ||
734 | return status; | ||
735 | } | ||
736 | |||
737 | static efi_status_t | ||
738 | __gop_query64(struct efi_graphics_output_protocol_64 *gop64, | ||
739 | struct efi_graphics_output_mode_info **info, | ||
740 | unsigned long *size, u64 *fb_base) | ||
741 | { | ||
742 | struct efi_graphics_output_protocol_mode_64 *mode; | ||
743 | efi_status_t status; | ||
744 | unsigned long m; | ||
745 | |||
746 | m = gop64->mode; | ||
747 | mode = (struct efi_graphics_output_protocol_mode_64 *)m; | ||
748 | |||
749 | status = efi_early->call(gop64->query_mode, gop64, | ||
750 | mode->mode, size, info); | ||
751 | if (status != EFI_SUCCESS) | ||
752 | return status; | ||
753 | |||
754 | *fb_base = mode->frame_buffer_base; | ||
755 | return status; | ||
756 | } | ||
757 | |||
758 | static efi_status_t | ||
759 | setup_gop64(struct screen_info *si, efi_guid_t *proto, | ||
760 | unsigned long size, void **gop_handle) | ||
761 | { | ||
762 | struct efi_graphics_output_protocol_64 *gop64, *first_gop; | ||
763 | unsigned long nr_gops; | ||
764 | u16 width, height; | ||
765 | u32 pixels_per_scan_line; | ||
766 | u32 ext_lfb_base; | ||
767 | u64 fb_base; | ||
768 | struct efi_pixel_bitmask pixel_info; | ||
769 | int pixel_format; | ||
770 | efi_status_t status; | ||
771 | u64 *handles = (u64 *)(unsigned long)gop_handle; | ||
772 | int i; | ||
773 | |||
774 | first_gop = NULL; | ||
775 | gop64 = NULL; | ||
776 | |||
777 | nr_gops = size / sizeof(u64); | ||
778 | for (i = 0; i < nr_gops; i++) { | ||
779 | struct efi_graphics_output_mode_info *info = NULL; | ||
780 | efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; | ||
781 | bool conout_found = false; | ||
782 | void *dummy = NULL; | ||
783 | u64 h = handles[i]; | ||
784 | u64 current_fb_base; | ||
785 | |||
786 | status = efi_call_early(handle_protocol, h, | ||
787 | proto, (void **)&gop64); | ||
788 | if (status != EFI_SUCCESS) | ||
789 | continue; | ||
790 | |||
791 | status = efi_call_early(handle_protocol, h, | ||
792 | &conout_proto, &dummy); | ||
793 | if (status == EFI_SUCCESS) | ||
794 | conout_found = true; | ||
795 | |||
796 | status = __gop_query64(gop64, &info, &size, ¤t_fb_base); | ||
797 | if (status == EFI_SUCCESS && (!first_gop || conout_found)) { | ||
798 | /* | ||
799 | * Systems that use the UEFI Console Splitter may | ||
800 | * provide multiple GOP devices, not all of which are | ||
801 | * backed by real hardware. The workaround is to search | ||
802 | * for a GOP implementing the ConOut protocol, and if | ||
803 | * one isn't found, to just fall back to the first GOP. | ||
804 | */ | ||
805 | width = info->horizontal_resolution; | ||
806 | height = info->vertical_resolution; | ||
807 | pixel_format = info->pixel_format; | ||
808 | pixel_info = info->pixel_information; | ||
809 | pixels_per_scan_line = info->pixels_per_scan_line; | ||
810 | fb_base = current_fb_base; | ||
811 | |||
812 | /* | ||
813 | * Once we've found a GOP supporting ConOut, | ||
814 | * don't bother looking any further. | ||
815 | */ | ||
816 | first_gop = gop64; | ||
817 | if (conout_found) | ||
818 | break; | ||
819 | } | ||
820 | } | ||
821 | |||
822 | /* Did we find any GOPs? */ | ||
823 | if (!first_gop) | ||
824 | goto out; | ||
825 | |||
826 | /* EFI framebuffer */ | ||
827 | si->orig_video_isVGA = VIDEO_TYPE_EFI; | ||
828 | |||
829 | si->lfb_width = width; | ||
830 | si->lfb_height = height; | ||
831 | si->lfb_base = fb_base; | ||
832 | |||
833 | ext_lfb_base = (u64)(unsigned long)fb_base >> 32; | ||
834 | if (ext_lfb_base) { | ||
835 | si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; | ||
836 | si->ext_lfb_base = ext_lfb_base; | ||
837 | } | ||
838 | |||
839 | si->pages = 1; | ||
840 | |||
841 | setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); | ||
842 | |||
843 | si->lfb_size = si->lfb_linelength * si->lfb_height; | ||
844 | |||
845 | si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; | ||
846 | out: | ||
847 | return status; | ||
848 | } | ||
849 | |||
850 | /* | ||
851 | * See if we have Graphics Output Protocol | ||
852 | */ | ||
853 | static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, | ||
854 | unsigned long size) | ||
855 | { | ||
856 | efi_status_t status; | ||
857 | void **gop_handle = NULL; | ||
858 | |||
859 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | ||
860 | size, (void **)&gop_handle); | ||
861 | if (status != EFI_SUCCESS) | ||
862 | return status; | ||
863 | |||
864 | status = efi_call_early(locate_handle, | ||
865 | EFI_LOCATE_BY_PROTOCOL, | ||
866 | proto, NULL, &size, gop_handle); | ||
867 | if (status != EFI_SUCCESS) | ||
868 | goto free_handle; | ||
869 | |||
870 | if (efi_early->is64) | ||
871 | status = setup_gop64(si, proto, size, gop_handle); | ||
872 | else | ||
873 | status = setup_gop32(si, proto, size, gop_handle); | ||
874 | |||
875 | free_handle: | ||
876 | efi_call_early(free_pool, gop_handle); | ||
877 | return status; | ||
878 | } | ||
879 | |||
880 | static efi_status_t | 574 | static efi_status_t |
881 | setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height) | 575 | setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height) |
882 | { | 576 | { |
@@ -1038,7 +732,7 @@ void setup_graphics(struct boot_params *boot_params) | |||
1038 | EFI_LOCATE_BY_PROTOCOL, | 732 | EFI_LOCATE_BY_PROTOCOL, |
1039 | &graphics_proto, NULL, &size, gop_handle); | 733 | &graphics_proto, NULL, &size, gop_handle); |
1040 | if (status == EFI_BUFFER_TOO_SMALL) | 734 | if (status == EFI_BUFFER_TOO_SMALL) |
1041 | status = setup_gop(si, &graphics_proto, size); | 735 | status = efi_setup_gop(NULL, si, &graphics_proto, size); |
1042 | 736 | ||
1043 | if (status != EFI_SUCCESS) { | 737 | if (status != EFI_SUCCESS) { |
1044 | size = 0; | 738 | size = 0; |
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index d487e727f1ec..c0223f1a89d7 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h | |||
@@ -11,80 +11,6 @@ | |||
11 | 11 | ||
12 | #define DESC_TYPE_CODE_DATA (1 << 0) | 12 | #define DESC_TYPE_CODE_DATA (1 << 0) |
13 | 13 | ||
14 | #define EFI_CONSOLE_OUT_DEVICE_GUID \ | ||
15 | EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \ | ||
16 | 0x3f, 0xc1, 0x4d) | ||
17 | |||
18 | #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 | ||
19 | #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 | ||
20 | #define PIXEL_BIT_MASK 2 | ||
21 | #define PIXEL_BLT_ONLY 3 | ||
22 | #define PIXEL_FORMAT_MAX 4 | ||
23 | |||
24 | struct efi_pixel_bitmask { | ||
25 | u32 red_mask; | ||
26 | u32 green_mask; | ||
27 | u32 blue_mask; | ||
28 | u32 reserved_mask; | ||
29 | }; | ||
30 | |||
31 | struct efi_graphics_output_mode_info { | ||
32 | u32 version; | ||
33 | u32 horizontal_resolution; | ||
34 | u32 vertical_resolution; | ||
35 | int pixel_format; | ||
36 | struct efi_pixel_bitmask pixel_information; | ||
37 | u32 pixels_per_scan_line; | ||
38 | } __packed; | ||
39 | |||
40 | struct efi_graphics_output_protocol_mode_32 { | ||
41 | u32 max_mode; | ||
42 | u32 mode; | ||
43 | u32 info; | ||
44 | u32 size_of_info; | ||
45 | u64 frame_buffer_base; | ||
46 | u32 frame_buffer_size; | ||
47 | } __packed; | ||
48 | |||
49 | struct efi_graphics_output_protocol_mode_64 { | ||
50 | u32 max_mode; | ||
51 | u32 mode; | ||
52 | u64 info; | ||
53 | u64 size_of_info; | ||
54 | u64 frame_buffer_base; | ||
55 | u64 frame_buffer_size; | ||
56 | } __packed; | ||
57 | |||
58 | struct efi_graphics_output_protocol_mode { | ||
59 | u32 max_mode; | ||
60 | u32 mode; | ||
61 | unsigned long info; | ||
62 | unsigned long size_of_info; | ||
63 | u64 frame_buffer_base; | ||
64 | unsigned long frame_buffer_size; | ||
65 | } __packed; | ||
66 | |||
67 | struct efi_graphics_output_protocol_32 { | ||
68 | u32 query_mode; | ||
69 | u32 set_mode; | ||
70 | u32 blt; | ||
71 | u32 mode; | ||
72 | }; | ||
73 | |||
74 | struct efi_graphics_output_protocol_64 { | ||
75 | u64 query_mode; | ||
76 | u64 set_mode; | ||
77 | u64 blt; | ||
78 | u64 mode; | ||
79 | }; | ||
80 | |||
81 | struct efi_graphics_output_protocol { | ||
82 | void *query_mode; | ||
83 | unsigned long set_mode; | ||
84 | unsigned long blt; | ||
85 | struct efi_graphics_output_protocol_mode *mode; | ||
86 | }; | ||
87 | |||
88 | struct efi_uga_draw_protocol_32 { | 14 | struct efi_uga_draw_protocol_32 { |
89 | u32 get_mode; | 15 | u32 get_mode; |
90 | u32 set_mode; | 16 | u32 set_mode; |
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 53748c45e488..78d1e7467eae 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <asm/fpu/api.h> | 4 | #include <asm/fpu/api.h> |
5 | #include <asm/pgtable.h> | 5 | #include <asm/pgtable.h> |
6 | #include <asm/processor-flags.h> | ||
6 | #include <asm/tlb.h> | 7 | #include <asm/tlb.h> |
7 | 8 | ||
8 | /* | 9 | /* |
@@ -28,33 +29,22 @@ | |||
28 | 29 | ||
29 | #define MAX_CMDLINE_ADDRESS UINT_MAX | 30 | #define MAX_CMDLINE_ADDRESS UINT_MAX |
30 | 31 | ||
31 | #ifdef CONFIG_X86_32 | 32 | #define ARCH_EFI_IRQ_FLAGS_MASK X86_EFLAGS_IF |
32 | 33 | ||
34 | #ifdef CONFIG_X86_32 | ||
33 | 35 | ||
34 | extern unsigned long asmlinkage efi_call_phys(void *, ...); | 36 | extern unsigned long asmlinkage efi_call_phys(void *, ...); |
35 | 37 | ||
38 | #define arch_efi_call_virt_setup() kernel_fpu_begin() | ||
39 | #define arch_efi_call_virt_teardown() kernel_fpu_end() | ||
40 | |||
36 | /* | 41 | /* |
37 | * Wrap all the virtual calls in a way that forces the parameters on the stack. | 42 | * Wrap all the virtual calls in a way that forces the parameters on the stack. |
38 | */ | 43 | */ |
39 | 44 | #define arch_efi_call_virt(f, args...) \ | |
40 | /* Use this macro if your virtual returns a non-void value */ | ||
41 | #define efi_call_virt(f, args...) \ | ||
42 | ({ \ | 45 | ({ \ |
43 | efi_status_t __s; \ | ||
44 | kernel_fpu_begin(); \ | ||
45 | __s = ((efi_##f##_t __attribute__((regparm(0)))*) \ | ||
46 | efi.systab->runtime->f)(args); \ | ||
47 | kernel_fpu_end(); \ | ||
48 | __s; \ | ||
49 | }) | ||
50 | |||
51 | /* Use this macro if your virtual call does not return any value */ | ||
52 | #define __efi_call_virt(f, args...) \ | ||
53 | ({ \ | ||
54 | kernel_fpu_begin(); \ | ||
55 | ((efi_##f##_t __attribute__((regparm(0)))*) \ | 46 | ((efi_##f##_t __attribute__((regparm(0)))*) \ |
56 | efi.systab->runtime->f)(args); \ | 47 | efi.systab->runtime->f)(args); \ |
57 | kernel_fpu_end(); \ | ||
58 | }) | 48 | }) |
59 | 49 | ||
60 | #define efi_ioremap(addr, size, type, attr) ioremap_cache(addr, size) | 50 | #define efi_ioremap(addr, size, type, attr) ioremap_cache(addr, size) |
@@ -78,10 +68,8 @@ struct efi_scratch { | |||
78 | u64 phys_stack; | 68 | u64 phys_stack; |
79 | } __packed; | 69 | } __packed; |
80 | 70 | ||
81 | #define efi_call_virt(f, ...) \ | 71 | #define arch_efi_call_virt_setup() \ |
82 | ({ \ | 72 | ({ \ |
83 | efi_status_t __s; \ | ||
84 | \ | ||
85 | efi_sync_low_kernel_mappings(); \ | 73 | efi_sync_low_kernel_mappings(); \ |
86 | preempt_disable(); \ | 74 | preempt_disable(); \ |
87 | __kernel_fpu_begin(); \ | 75 | __kernel_fpu_begin(); \ |
@@ -91,9 +79,13 @@ struct efi_scratch { | |||
91 | write_cr3((unsigned long)efi_scratch.efi_pgt); \ | 79 | write_cr3((unsigned long)efi_scratch.efi_pgt); \ |
92 | __flush_tlb_all(); \ | 80 | __flush_tlb_all(); \ |
93 | } \ | 81 | } \ |
94 | \ | 82 | }) |
95 | __s = efi_call((void *)efi.systab->runtime->f, __VA_ARGS__); \ | 83 | |
96 | \ | 84 | #define arch_efi_call_virt(f, args...) \ |
85 | efi_call((void *)efi.systab->runtime->f, args) \ | ||
86 | |||
87 | #define arch_efi_call_virt_teardown() \ | ||
88 | ({ \ | ||
97 | if (efi_scratch.use_pgd) { \ | 89 | if (efi_scratch.use_pgd) { \ |
98 | write_cr3(efi_scratch.prev_cr3); \ | 90 | write_cr3(efi_scratch.prev_cr3); \ |
99 | __flush_tlb_all(); \ | 91 | __flush_tlb_all(); \ |
@@ -101,15 +93,8 @@ struct efi_scratch { | |||
101 | \ | 93 | \ |
102 | __kernel_fpu_end(); \ | 94 | __kernel_fpu_end(); \ |
103 | preempt_enable(); \ | 95 | preempt_enable(); \ |
104 | __s; \ | ||
105 | }) | 96 | }) |
106 | 97 | ||
107 | /* | ||
108 | * All X86_64 virt calls return non-void values. Thus, use non-void call for | ||
109 | * virt calls that would be void on X86_32. | ||
110 | */ | ||
111 | #define __efi_call_virt(f, args...) efi_call_virt(f, args) | ||
112 | |||
113 | extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size, | 98 | extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size, |
114 | u32 type, u64 attribute); | 99 | u32 type, u64 attribute); |
115 | 100 | ||
@@ -180,6 +165,8 @@ static inline bool efi_runtime_supported(void) | |||
180 | extern struct console early_efi_console; | 165 | extern struct console early_efi_console; |
181 | extern void parse_efi_setup(u64 phys_addr, u32 data_len); | 166 | extern void parse_efi_setup(u64 phys_addr, u32 data_len); |
182 | 167 | ||
168 | extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); | ||
169 | |||
183 | #ifdef CONFIG_EFI_MIXED | 170 | #ifdef CONFIG_EFI_MIXED |
184 | extern void efi_thunk_runtime_setup(void); | 171 | extern void efi_thunk_runtime_setup(void); |
185 | extern efi_status_t efi_thunk_set_virtual_address_map( | 172 | extern efi_status_t efi_thunk_set_virtual_address_map( |
@@ -225,6 +212,11 @@ __pure const struct efi_config *__efi_early(void); | |||
225 | #define efi_call_early(f, ...) \ | 212 | #define efi_call_early(f, ...) \ |
226 | __efi_early()->call(__efi_early()->f, __VA_ARGS__); | 213 | __efi_early()->call(__efi_early()->f, __VA_ARGS__); |
227 | 214 | ||
215 | #define __efi_call_early(f, ...) \ | ||
216 | __efi_early()->call((unsigned long)f, __VA_ARGS__); | ||
217 | |||
218 | #define efi_is_64bit() __efi_early()->is64 | ||
219 | |||
228 | extern bool efi_reboot_required(void); | 220 | extern bool efi_reboot_required(void); |
229 | 221 | ||
230 | #else | 222 | #else |
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index ab0adc0fa5db..a9b31eb815f2 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
@@ -535,6 +535,15 @@ static void native_machine_emergency_restart(void) | |||
535 | mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0; | 535 | mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0; |
536 | *((unsigned short *)__va(0x472)) = mode; | 536 | *((unsigned short *)__va(0x472)) = mode; |
537 | 537 | ||
538 | /* | ||
539 | * If an EFI capsule has been registered with the firmware then | ||
540 | * override the reboot= parameter. | ||
541 | */ | ||
542 | if (efi_capsule_pending(NULL)) { | ||
543 | pr_info("EFI capsule is pending, forcing EFI reboot.\n"); | ||
544 | reboot_type = BOOT_EFI; | ||
545 | } | ||
546 | |||
538 | for (;;) { | 547 | for (;;) { |
539 | /* Could also try the reset bit in the Hammer NB */ | 548 | /* Could also try the reset bit in the Hammer NB */ |
540 | switch (reboot_type) { | 549 | switch (reboot_type) { |
diff --git a/arch/x86/kernel/sysfb_efi.c b/arch/x86/kernel/sysfb_efi.c index 5da924bbf0a0..623965e86b65 100644 --- a/arch/x86/kernel/sysfb_efi.c +++ b/arch/x86/kernel/sysfb_efi.c | |||
@@ -68,6 +68,21 @@ struct efifb_dmi_info efifb_dmi_list[] = { | |||
68 | [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE } | 68 | [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE } |
69 | }; | 69 | }; |
70 | 70 | ||
71 | void efifb_setup_from_dmi(struct screen_info *si, const char *opt) | ||
72 | { | ||
73 | int i; | ||
74 | |||
75 | for (i = 0; i < M_UNKNOWN; i++) { | ||
76 | if (efifb_dmi_list[i].base != 0 && | ||
77 | !strcmp(opt, efifb_dmi_list[i].optname)) { | ||
78 | si->lfb_base = efifb_dmi_list[i].base; | ||
79 | si->lfb_linelength = efifb_dmi_list[i].stride; | ||
80 | si->lfb_width = efifb_dmi_list[i].width; | ||
81 | si->lfb_height = efifb_dmi_list[i].height; | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | |||
71 | #define choose_value(dmivalue, fwvalue, field, flags) ({ \ | 86 | #define choose_value(dmivalue, fwvalue, field, flags) ({ \ |
72 | typeof(fwvalue) _ret_ = fwvalue; \ | 87 | typeof(fwvalue) _ret_ = fwvalue; \ |
73 | if ((flags) & (field)) \ | 88 | if ((flags) & (field)) \ |
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 01be9ec3bf79..a1f0e1d0ddc2 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -1125,8 +1125,14 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr) | |||
1125 | static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr, | 1125 | static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr, |
1126 | int primary) | 1126 | int primary) |
1127 | { | 1127 | { |
1128 | if (cpa->pgd) | 1128 | if (cpa->pgd) { |
1129 | /* | ||
1130 | * Right now, we only execute this code path when mapping | ||
1131 | * the EFI virtual memory map regions, no other users | ||
1132 | * provide a ->pgd value. This may change in the future. | ||
1133 | */ | ||
1129 | return populate_pgd(cpa, vaddr); | 1134 | return populate_pgd(cpa, vaddr); |
1135 | } | ||
1130 | 1136 | ||
1131 | /* | 1137 | /* |
1132 | * Ignore all non primary paths. | 1138 | * Ignore all non primary paths. |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 994a7df84a7b..f93545e7dc54 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -54,10 +54,6 @@ | |||
54 | #include <asm/rtc.h> | 54 | #include <asm/rtc.h> |
55 | #include <asm/uv/uv.h> | 55 | #include <asm/uv/uv.h> |
56 | 56 | ||
57 | #define EFI_DEBUG | ||
58 | |||
59 | struct efi_memory_map memmap; | ||
60 | |||
61 | static struct efi efi_phys __initdata; | 57 | static struct efi efi_phys __initdata; |
62 | static efi_system_table_t efi_systab __initdata; | 58 | static efi_system_table_t efi_systab __initdata; |
63 | 59 | ||
@@ -119,11 +115,10 @@ void efi_get_time(struct timespec *now) | |||
119 | 115 | ||
120 | void __init efi_find_mirror(void) | 116 | void __init efi_find_mirror(void) |
121 | { | 117 | { |
122 | void *p; | 118 | efi_memory_desc_t *md; |
123 | u64 mirror_size = 0, total_size = 0; | 119 | u64 mirror_size = 0, total_size = 0; |
124 | 120 | ||
125 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 121 | for_each_efi_memory_desc(md) { |
126 | efi_memory_desc_t *md = p; | ||
127 | unsigned long long start = md->phys_addr; | 122 | unsigned long long start = md->phys_addr; |
128 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | 123 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; |
129 | 124 | ||
@@ -146,10 +141,9 @@ void __init efi_find_mirror(void) | |||
146 | 141 | ||
147 | static void __init do_add_efi_memmap(void) | 142 | static void __init do_add_efi_memmap(void) |
148 | { | 143 | { |
149 | void *p; | 144 | efi_memory_desc_t *md; |
150 | 145 | ||
151 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 146 | for_each_efi_memory_desc(md) { |
152 | efi_memory_desc_t *md = p; | ||
153 | unsigned long long start = md->phys_addr; | 147 | unsigned long long start = md->phys_addr; |
154 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | 148 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; |
155 | int e820_type; | 149 | int e820_type; |
@@ -209,47 +203,47 @@ int __init efi_memblock_x86_reserve_range(void) | |||
209 | #else | 203 | #else |
210 | pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32)); | 204 | pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32)); |
211 | #endif | 205 | #endif |
212 | memmap.phys_map = pmap; | 206 | efi.memmap.phys_map = pmap; |
213 | memmap.nr_map = e->efi_memmap_size / | 207 | efi.memmap.nr_map = e->efi_memmap_size / |
214 | e->efi_memdesc_size; | 208 | e->efi_memdesc_size; |
215 | memmap.desc_size = e->efi_memdesc_size; | 209 | efi.memmap.desc_size = e->efi_memdesc_size; |
216 | memmap.desc_version = e->efi_memdesc_version; | 210 | efi.memmap.desc_version = e->efi_memdesc_version; |
217 | 211 | ||
218 | memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); | 212 | WARN(efi.memmap.desc_version != 1, |
213 | "Unexpected EFI_MEMORY_DESCRIPTOR version %ld", | ||
214 | efi.memmap.desc_version); | ||
219 | 215 | ||
220 | efi.memmap = &memmap; | 216 | memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size); |
221 | 217 | ||
222 | return 0; | 218 | return 0; |
223 | } | 219 | } |
224 | 220 | ||
225 | void __init efi_print_memmap(void) | 221 | void __init efi_print_memmap(void) |
226 | { | 222 | { |
227 | #ifdef EFI_DEBUG | ||
228 | efi_memory_desc_t *md; | 223 | efi_memory_desc_t *md; |
229 | void *p; | 224 | int i = 0; |
230 | int i; | ||
231 | 225 | ||
232 | for (p = memmap.map, i = 0; | 226 | for_each_efi_memory_desc(md) { |
233 | p < memmap.map_end; | ||
234 | p += memmap.desc_size, i++) { | ||
235 | char buf[64]; | 227 | char buf[64]; |
236 | 228 | ||
237 | md = p; | ||
238 | pr_info("mem%02u: %s range=[0x%016llx-0x%016llx] (%lluMB)\n", | 229 | pr_info("mem%02u: %s range=[0x%016llx-0x%016llx] (%lluMB)\n", |
239 | i, efi_md_typeattr_format(buf, sizeof(buf), md), | 230 | i++, efi_md_typeattr_format(buf, sizeof(buf), md), |
240 | md->phys_addr, | 231 | md->phys_addr, |
241 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1, | 232 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1, |
242 | (md->num_pages >> (20 - EFI_PAGE_SHIFT))); | 233 | (md->num_pages >> (20 - EFI_PAGE_SHIFT))); |
243 | } | 234 | } |
244 | #endif /* EFI_DEBUG */ | ||
245 | } | 235 | } |
246 | 236 | ||
247 | void __init efi_unmap_memmap(void) | 237 | void __init efi_unmap_memmap(void) |
248 | { | 238 | { |
239 | unsigned long size; | ||
240 | |||
249 | clear_bit(EFI_MEMMAP, &efi.flags); | 241 | clear_bit(EFI_MEMMAP, &efi.flags); |
250 | if (memmap.map) { | 242 | |
251 | early_memunmap(memmap.map, memmap.nr_map * memmap.desc_size); | 243 | size = efi.memmap.nr_map * efi.memmap.desc_size; |
252 | memmap.map = NULL; | 244 | if (efi.memmap.map) { |
245 | early_memunmap(efi.memmap.map, size); | ||
246 | efi.memmap.map = NULL; | ||
253 | } | 247 | } |
254 | } | 248 | } |
255 | 249 | ||
@@ -352,8 +346,6 @@ static int __init efi_systab_init(void *phys) | |||
352 | efi.systab->hdr.revision >> 16, | 346 | efi.systab->hdr.revision >> 16, |
353 | efi.systab->hdr.revision & 0xffff); | 347 | efi.systab->hdr.revision & 0xffff); |
354 | 348 | ||
355 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); | ||
356 | |||
357 | return 0; | 349 | return 0; |
358 | } | 350 | } |
359 | 351 | ||
@@ -440,17 +432,22 @@ static int __init efi_runtime_init(void) | |||
440 | 432 | ||
441 | static int __init efi_memmap_init(void) | 433 | static int __init efi_memmap_init(void) |
442 | { | 434 | { |
435 | unsigned long addr, size; | ||
436 | |||
443 | if (efi_enabled(EFI_PARAVIRT)) | 437 | if (efi_enabled(EFI_PARAVIRT)) |
444 | return 0; | 438 | return 0; |
445 | 439 | ||
446 | /* Map the EFI memory map */ | 440 | /* Map the EFI memory map */ |
447 | memmap.map = early_memremap((unsigned long)memmap.phys_map, | 441 | size = efi.memmap.nr_map * efi.memmap.desc_size; |
448 | memmap.nr_map * memmap.desc_size); | 442 | addr = (unsigned long)efi.memmap.phys_map; |
449 | if (memmap.map == NULL) { | 443 | |
444 | efi.memmap.map = early_memremap(addr, size); | ||
445 | if (efi.memmap.map == NULL) { | ||
450 | pr_err("Could not map the memory map!\n"); | 446 | pr_err("Could not map the memory map!\n"); |
451 | return -ENOMEM; | 447 | return -ENOMEM; |
452 | } | 448 | } |
453 | memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); | 449 | |
450 | efi.memmap.map_end = efi.memmap.map + size; | ||
454 | 451 | ||
455 | if (add_efi_memmap) | 452 | if (add_efi_memmap) |
456 | do_add_efi_memmap(); | 453 | do_add_efi_memmap(); |
@@ -552,12 +549,9 @@ void __init efi_set_executable(efi_memory_desc_t *md, bool executable) | |||
552 | void __init runtime_code_page_mkexec(void) | 549 | void __init runtime_code_page_mkexec(void) |
553 | { | 550 | { |
554 | efi_memory_desc_t *md; | 551 | efi_memory_desc_t *md; |
555 | void *p; | ||
556 | 552 | ||
557 | /* Make EFI runtime service code area executable */ | 553 | /* Make EFI runtime service code area executable */ |
558 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 554 | for_each_efi_memory_desc(md) { |
559 | md = p; | ||
560 | |||
561 | if (md->type != EFI_RUNTIME_SERVICES_CODE) | 555 | if (md->type != EFI_RUNTIME_SERVICES_CODE) |
562 | continue; | 556 | continue; |
563 | 557 | ||
@@ -604,12 +598,10 @@ void __init old_map_region(efi_memory_desc_t *md) | |||
604 | /* Merge contiguous regions of the same type and attribute */ | 598 | /* Merge contiguous regions of the same type and attribute */ |
605 | static void __init efi_merge_regions(void) | 599 | static void __init efi_merge_regions(void) |
606 | { | 600 | { |
607 | void *p; | ||
608 | efi_memory_desc_t *md, *prev_md = NULL; | 601 | efi_memory_desc_t *md, *prev_md = NULL; |
609 | 602 | ||
610 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 603 | for_each_efi_memory_desc(md) { |
611 | u64 prev_size; | 604 | u64 prev_size; |
612 | md = p; | ||
613 | 605 | ||
614 | if (!prev_md) { | 606 | if (!prev_md) { |
615 | prev_md = md; | 607 | prev_md = md; |
@@ -651,30 +643,31 @@ static void __init get_systab_virt_addr(efi_memory_desc_t *md) | |||
651 | static void __init save_runtime_map(void) | 643 | static void __init save_runtime_map(void) |
652 | { | 644 | { |
653 | #ifdef CONFIG_KEXEC_CORE | 645 | #ifdef CONFIG_KEXEC_CORE |
646 | unsigned long desc_size; | ||
654 | efi_memory_desc_t *md; | 647 | efi_memory_desc_t *md; |
655 | void *tmp, *p, *q = NULL; | 648 | void *tmp, *q = NULL; |
656 | int count = 0; | 649 | int count = 0; |
657 | 650 | ||
658 | if (efi_enabled(EFI_OLD_MEMMAP)) | 651 | if (efi_enabled(EFI_OLD_MEMMAP)) |
659 | return; | 652 | return; |
660 | 653 | ||
661 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 654 | desc_size = efi.memmap.desc_size; |
662 | md = p; | ||
663 | 655 | ||
656 | for_each_efi_memory_desc(md) { | ||
664 | if (!(md->attribute & EFI_MEMORY_RUNTIME) || | 657 | if (!(md->attribute & EFI_MEMORY_RUNTIME) || |
665 | (md->type == EFI_BOOT_SERVICES_CODE) || | 658 | (md->type == EFI_BOOT_SERVICES_CODE) || |
666 | (md->type == EFI_BOOT_SERVICES_DATA)) | 659 | (md->type == EFI_BOOT_SERVICES_DATA)) |
667 | continue; | 660 | continue; |
668 | tmp = krealloc(q, (count + 1) * memmap.desc_size, GFP_KERNEL); | 661 | tmp = krealloc(q, (count + 1) * desc_size, GFP_KERNEL); |
669 | if (!tmp) | 662 | if (!tmp) |
670 | goto out; | 663 | goto out; |
671 | q = tmp; | 664 | q = tmp; |
672 | 665 | ||
673 | memcpy(q + count * memmap.desc_size, md, memmap.desc_size); | 666 | memcpy(q + count * desc_size, md, desc_size); |
674 | count++; | 667 | count++; |
675 | } | 668 | } |
676 | 669 | ||
677 | efi_runtime_map_setup(q, count, memmap.desc_size); | 670 | efi_runtime_map_setup(q, count, desc_size); |
678 | return; | 671 | return; |
679 | 672 | ||
680 | out: | 673 | out: |
@@ -714,10 +707,10 @@ static inline void *efi_map_next_entry_reverse(void *entry) | |||
714 | { | 707 | { |
715 | /* Initial call */ | 708 | /* Initial call */ |
716 | if (!entry) | 709 | if (!entry) |
717 | return memmap.map_end - memmap.desc_size; | 710 | return efi.memmap.map_end - efi.memmap.desc_size; |
718 | 711 | ||
719 | entry -= memmap.desc_size; | 712 | entry -= efi.memmap.desc_size; |
720 | if (entry < memmap.map) | 713 | if (entry < efi.memmap.map) |
721 | return NULL; | 714 | return NULL; |
722 | 715 | ||
723 | return entry; | 716 | return entry; |
@@ -759,10 +752,10 @@ static void *efi_map_next_entry(void *entry) | |||
759 | 752 | ||
760 | /* Initial call */ | 753 | /* Initial call */ |
761 | if (!entry) | 754 | if (!entry) |
762 | return memmap.map; | 755 | return efi.memmap.map; |
763 | 756 | ||
764 | entry += memmap.desc_size; | 757 | entry += efi.memmap.desc_size; |
765 | if (entry >= memmap.map_end) | 758 | if (entry >= efi.memmap.map_end) |
766 | return NULL; | 759 | return NULL; |
767 | 760 | ||
768 | return entry; | 761 | return entry; |
@@ -776,8 +769,11 @@ static void * __init efi_map_regions(int *count, int *pg_shift) | |||
776 | { | 769 | { |
777 | void *p, *new_memmap = NULL; | 770 | void *p, *new_memmap = NULL; |
778 | unsigned long left = 0; | 771 | unsigned long left = 0; |
772 | unsigned long desc_size; | ||
779 | efi_memory_desc_t *md; | 773 | efi_memory_desc_t *md; |
780 | 774 | ||
775 | desc_size = efi.memmap.desc_size; | ||
776 | |||
781 | p = NULL; | 777 | p = NULL; |
782 | while ((p = efi_map_next_entry(p))) { | 778 | while ((p = efi_map_next_entry(p))) { |
783 | md = p; | 779 | md = p; |
@@ -792,7 +788,7 @@ static void * __init efi_map_regions(int *count, int *pg_shift) | |||
792 | efi_map_region(md); | 788 | efi_map_region(md); |
793 | get_systab_virt_addr(md); | 789 | get_systab_virt_addr(md); |
794 | 790 | ||
795 | if (left < memmap.desc_size) { | 791 | if (left < desc_size) { |
796 | new_memmap = realloc_pages(new_memmap, *pg_shift); | 792 | new_memmap = realloc_pages(new_memmap, *pg_shift); |
797 | if (!new_memmap) | 793 | if (!new_memmap) |
798 | return NULL; | 794 | return NULL; |
@@ -801,10 +797,9 @@ static void * __init efi_map_regions(int *count, int *pg_shift) | |||
801 | (*pg_shift)++; | 797 | (*pg_shift)++; |
802 | } | 798 | } |
803 | 799 | ||
804 | memcpy(new_memmap + (*count * memmap.desc_size), md, | 800 | memcpy(new_memmap + (*count * desc_size), md, desc_size); |
805 | memmap.desc_size); | ||
806 | 801 | ||
807 | left -= memmap.desc_size; | 802 | left -= desc_size; |
808 | (*count)++; | 803 | (*count)++; |
809 | } | 804 | } |
810 | 805 | ||
@@ -816,7 +811,6 @@ static void __init kexec_enter_virtual_mode(void) | |||
816 | #ifdef CONFIG_KEXEC_CORE | 811 | #ifdef CONFIG_KEXEC_CORE |
817 | efi_memory_desc_t *md; | 812 | efi_memory_desc_t *md; |
818 | unsigned int num_pages; | 813 | unsigned int num_pages; |
819 | void *p; | ||
820 | 814 | ||
821 | efi.systab = NULL; | 815 | efi.systab = NULL; |
822 | 816 | ||
@@ -840,8 +834,7 @@ static void __init kexec_enter_virtual_mode(void) | |||
840 | * Map efi regions which were passed via setup_data. The virt_addr is a | 834 | * Map efi regions which were passed via setup_data. The virt_addr is a |
841 | * fixed addr which was used in first kernel of a kexec boot. | 835 | * fixed addr which was used in first kernel of a kexec boot. |
842 | */ | 836 | */ |
843 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 837 | for_each_efi_memory_desc(md) { |
844 | md = p; | ||
845 | efi_map_region_fixed(md); /* FIXME: add error handling */ | 838 | efi_map_region_fixed(md); /* FIXME: add error handling */ |
846 | get_systab_virt_addr(md); | 839 | get_systab_virt_addr(md); |
847 | } | 840 | } |
@@ -850,10 +843,10 @@ static void __init kexec_enter_virtual_mode(void) | |||
850 | 843 | ||
851 | BUG_ON(!efi.systab); | 844 | BUG_ON(!efi.systab); |
852 | 845 | ||
853 | num_pages = ALIGN(memmap.nr_map * memmap.desc_size, PAGE_SIZE); | 846 | num_pages = ALIGN(efi.memmap.nr_map * efi.memmap.desc_size, PAGE_SIZE); |
854 | num_pages >>= PAGE_SHIFT; | 847 | num_pages >>= PAGE_SHIFT; |
855 | 848 | ||
856 | if (efi_setup_page_tables(memmap.phys_map, num_pages)) { | 849 | if (efi_setup_page_tables(efi.memmap.phys_map, num_pages)) { |
857 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); | 850 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); |
858 | return; | 851 | return; |
859 | } | 852 | } |
@@ -937,16 +930,16 @@ static void __init __efi_enter_virtual_mode(void) | |||
937 | 930 | ||
938 | if (efi_is_native()) { | 931 | if (efi_is_native()) { |
939 | status = phys_efi_set_virtual_address_map( | 932 | status = phys_efi_set_virtual_address_map( |
940 | memmap.desc_size * count, | 933 | efi.memmap.desc_size * count, |
941 | memmap.desc_size, | 934 | efi.memmap.desc_size, |
942 | memmap.desc_version, | 935 | efi.memmap.desc_version, |
943 | (efi_memory_desc_t *)__pa(new_memmap)); | 936 | (efi_memory_desc_t *)__pa(new_memmap)); |
944 | } else { | 937 | } else { |
945 | status = efi_thunk_set_virtual_address_map( | 938 | status = efi_thunk_set_virtual_address_map( |
946 | efi_phys.set_virtual_address_map, | 939 | efi_phys.set_virtual_address_map, |
947 | memmap.desc_size * count, | 940 | efi.memmap.desc_size * count, |
948 | memmap.desc_size, | 941 | efi.memmap.desc_size, |
949 | memmap.desc_version, | 942 | efi.memmap.desc_version, |
950 | (efi_memory_desc_t *)__pa(new_memmap)); | 943 | (efi_memory_desc_t *)__pa(new_memmap)); |
951 | } | 944 | } |
952 | 945 | ||
@@ -1011,13 +1004,11 @@ void __init efi_enter_virtual_mode(void) | |||
1011 | u32 efi_mem_type(unsigned long phys_addr) | 1004 | u32 efi_mem_type(unsigned long phys_addr) |
1012 | { | 1005 | { |
1013 | efi_memory_desc_t *md; | 1006 | efi_memory_desc_t *md; |
1014 | void *p; | ||
1015 | 1007 | ||
1016 | if (!efi_enabled(EFI_MEMMAP)) | 1008 | if (!efi_enabled(EFI_MEMMAP)) |
1017 | return 0; | 1009 | return 0; |
1018 | 1010 | ||
1019 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 1011 | for_each_efi_memory_desc(md) { |
1020 | md = p; | ||
1021 | if ((md->phys_addr <= phys_addr) && | 1012 | if ((md->phys_addr <= phys_addr) && |
1022 | (phys_addr < (md->phys_addr + | 1013 | (phys_addr < (md->phys_addr + |
1023 | (md->num_pages << EFI_PAGE_SHIFT)))) | 1014 | (md->num_pages << EFI_PAGE_SHIFT)))) |
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 49e4dd4a1f58..6e7242be1c87 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
@@ -55,14 +55,12 @@ struct efi_scratch efi_scratch; | |||
55 | static void __init early_code_mapping_set_exec(int executable) | 55 | static void __init early_code_mapping_set_exec(int executable) |
56 | { | 56 | { |
57 | efi_memory_desc_t *md; | 57 | efi_memory_desc_t *md; |
58 | void *p; | ||
59 | 58 | ||
60 | if (!(__supported_pte_mask & _PAGE_NX)) | 59 | if (!(__supported_pte_mask & _PAGE_NX)) |
61 | return; | 60 | return; |
62 | 61 | ||
63 | /* Make EFI service code area executable */ | 62 | /* Make EFI service code area executable */ |
64 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 63 | for_each_efi_memory_desc(md) { |
65 | md = p; | ||
66 | if (md->type == EFI_RUNTIME_SERVICES_CODE || | 64 | if (md->type == EFI_RUNTIME_SERVICES_CODE || |
67 | md->type == EFI_BOOT_SERVICES_CODE) | 65 | md->type == EFI_BOOT_SERVICES_CODE) |
68 | efi_set_executable(md, executable); | 66 | efi_set_executable(md, executable); |
@@ -253,7 +251,7 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) | |||
253 | * Map all of RAM so that we can access arguments in the 1:1 | 251 | * Map all of RAM so that we can access arguments in the 1:1 |
254 | * mapping when making EFI runtime calls. | 252 | * mapping when making EFI runtime calls. |
255 | */ | 253 | */ |
256 | for_each_efi_memory_desc(&memmap, md) { | 254 | for_each_efi_memory_desc(md) { |
257 | if (md->type != EFI_CONVENTIONAL_MEMORY && | 255 | if (md->type != EFI_CONVENTIONAL_MEMORY && |
258 | md->type != EFI_LOADER_DATA && | 256 | md->type != EFI_LOADER_DATA && |
259 | md->type != EFI_LOADER_CODE) | 257 | md->type != EFI_LOADER_CODE) |
@@ -398,7 +396,6 @@ void __init efi_runtime_update_mappings(void) | |||
398 | unsigned long pfn; | 396 | unsigned long pfn; |
399 | pgd_t *pgd = efi_pgd; | 397 | pgd_t *pgd = efi_pgd; |
400 | efi_memory_desc_t *md; | 398 | efi_memory_desc_t *md; |
401 | void *p; | ||
402 | 399 | ||
403 | if (efi_enabled(EFI_OLD_MEMMAP)) { | 400 | if (efi_enabled(EFI_OLD_MEMMAP)) { |
404 | if (__supported_pte_mask & _PAGE_NX) | 401 | if (__supported_pte_mask & _PAGE_NX) |
@@ -409,9 +406,8 @@ void __init efi_runtime_update_mappings(void) | |||
409 | if (!efi_enabled(EFI_NX_PE_DATA)) | 406 | if (!efi_enabled(EFI_NX_PE_DATA)) |
410 | return; | 407 | return; |
411 | 408 | ||
412 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 409 | for_each_efi_memory_desc(md) { |
413 | unsigned long pf = 0; | 410 | unsigned long pf = 0; |
414 | md = p; | ||
415 | 411 | ||
416 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) | 412 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) |
417 | continue; | 413 | continue; |
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index ab50ada1d56e..097cb09d917b 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c | |||
@@ -195,10 +195,9 @@ static bool can_free_region(u64 start, u64 size) | |||
195 | */ | 195 | */ |
196 | void __init efi_reserve_boot_services(void) | 196 | void __init efi_reserve_boot_services(void) |
197 | { | 197 | { |
198 | void *p; | 198 | efi_memory_desc_t *md; |
199 | 199 | ||
200 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 200 | for_each_efi_memory_desc(md) { |
201 | efi_memory_desc_t *md = p; | ||
202 | u64 start = md->phys_addr; | 201 | u64 start = md->phys_addr; |
203 | u64 size = md->num_pages << EFI_PAGE_SHIFT; | 202 | u64 size = md->num_pages << EFI_PAGE_SHIFT; |
204 | bool already_reserved; | 203 | bool already_reserved; |
@@ -250,10 +249,9 @@ void __init efi_reserve_boot_services(void) | |||
250 | 249 | ||
251 | void __init efi_free_boot_services(void) | 250 | void __init efi_free_boot_services(void) |
252 | { | 251 | { |
253 | void *p; | 252 | efi_memory_desc_t *md; |
254 | 253 | ||
255 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 254 | for_each_efi_memory_desc(md) { |
256 | efi_memory_desc_t *md = p; | ||
257 | unsigned long long start = md->phys_addr; | 255 | unsigned long long start = md->phys_addr; |
258 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | 256 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; |
259 | 257 | ||
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index e1670d533f97..6394152f648f 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig | |||
@@ -87,6 +87,31 @@ config EFI_RUNTIME_WRAPPERS | |||
87 | config EFI_ARMSTUB | 87 | config EFI_ARMSTUB |
88 | bool | 88 | bool |
89 | 89 | ||
90 | config EFI_BOOTLOADER_CONTROL | ||
91 | tristate "EFI Bootloader Control" | ||
92 | depends on EFI_VARS | ||
93 | default n | ||
94 | ---help--- | ||
95 | This module installs a reboot hook, such that if reboot() is | ||
96 | invoked with a string argument NNN, "NNN" is copied to the | ||
97 | "LoaderEntryOneShot" EFI variable, to be read by the | ||
98 | bootloader. If the string matches one of the boot labels | ||
99 | defined in its configuration, the bootloader will boot once | ||
100 | to that label. The "LoaderEntryRebootReason" EFI variable is | ||
101 | set with the reboot reason: "reboot" or "shutdown". The | ||
102 | bootloader reads this reboot reason and takes particular | ||
103 | action according to its policy. | ||
104 | |||
105 | config EFI_CAPSULE_LOADER | ||
106 | tristate "EFI capsule loader" | ||
107 | depends on EFI | ||
108 | help | ||
109 | This option exposes a loader interface "/dev/efi_capsule_loader" for | ||
110 | users to load EFI capsules. This driver requires working runtime | ||
111 | capsule support in the firmware, which many OEMs do not provide. | ||
112 | |||
113 | Most users should say N. | ||
114 | |||
90 | endmenu | 115 | endmenu |
91 | 116 | ||
92 | config UEFI_CPER | 117 | config UEFI_CPER |
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 62e654f255f4..a219640f881f 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile | |||
@@ -9,7 +9,8 @@ | |||
9 | # | 9 | # |
10 | KASAN_SANITIZE_runtime-wrappers.o := n | 10 | KASAN_SANITIZE_runtime-wrappers.o := n |
11 | 11 | ||
12 | obj-$(CONFIG_EFI) += efi.o vars.o reboot.o | 12 | obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o |
13 | obj-$(CONFIG_EFI) += capsule.o | ||
13 | obj-$(CONFIG_EFI_VARS) += efivars.o | 14 | obj-$(CONFIG_EFI_VARS) += efivars.o |
14 | obj-$(CONFIG_EFI_ESRT) += esrt.o | 15 | obj-$(CONFIG_EFI_ESRT) += esrt.o |
15 | obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o | 16 | obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o |
@@ -18,7 +19,9 @@ obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o | |||
18 | obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o | 19 | obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o |
19 | obj-$(CONFIG_EFI_STUB) += libstub/ | 20 | obj-$(CONFIG_EFI_STUB) += libstub/ |
20 | obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o | 21 | obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o |
22 | obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o | ||
21 | 23 | ||
22 | arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o | 24 | arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o |
23 | obj-$(CONFIG_ARM) += $(arm-obj-y) | 25 | obj-$(CONFIG_ARM) += $(arm-obj-y) |
24 | obj-$(CONFIG_ARM64) += $(arm-obj-y) | 26 | obj-$(CONFIG_ARM64) += $(arm-obj-y) |
27 | obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o | ||
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 8714f8c271ba..ef90f0c4b70a 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c | |||
@@ -11,17 +11,19 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define pr_fmt(fmt) "efi: " fmt | ||
15 | |||
14 | #include <linux/efi.h> | 16 | #include <linux/efi.h> |
15 | #include <linux/init.h> | 17 | #include <linux/init.h> |
16 | #include <linux/memblock.h> | 18 | #include <linux/memblock.h> |
17 | #include <linux/mm_types.h> | 19 | #include <linux/mm_types.h> |
18 | #include <linux/of.h> | 20 | #include <linux/of.h> |
19 | #include <linux/of_fdt.h> | 21 | #include <linux/of_fdt.h> |
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/screen_info.h> | ||
20 | 24 | ||
21 | #include <asm/efi.h> | 25 | #include <asm/efi.h> |
22 | 26 | ||
23 | struct efi_memory_map memmap; | ||
24 | |||
25 | u64 efi_system_table; | 27 | u64 efi_system_table; |
26 | 28 | ||
27 | static int __init is_normal_ram(efi_memory_desc_t *md) | 29 | static int __init is_normal_ram(efi_memory_desc_t *md) |
@@ -40,7 +42,7 @@ static phys_addr_t efi_to_phys(unsigned long addr) | |||
40 | { | 42 | { |
41 | efi_memory_desc_t *md; | 43 | efi_memory_desc_t *md; |
42 | 44 | ||
43 | for_each_efi_memory_desc(&memmap, md) { | 45 | for_each_efi_memory_desc(md) { |
44 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) | 46 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) |
45 | continue; | 47 | continue; |
46 | if (md->virt_addr == 0) | 48 | if (md->virt_addr == 0) |
@@ -53,6 +55,36 @@ static phys_addr_t efi_to_phys(unsigned long addr) | |||
53 | return addr; | 55 | return addr; |
54 | } | 56 | } |
55 | 57 | ||
58 | static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR; | ||
59 | |||
60 | static __initdata efi_config_table_type_t arch_tables[] = { | ||
61 | {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, NULL, &screen_info_table}, | ||
62 | {NULL_GUID, NULL, NULL} | ||
63 | }; | ||
64 | |||
65 | static void __init init_screen_info(void) | ||
66 | { | ||
67 | struct screen_info *si; | ||
68 | |||
69 | if (screen_info_table != EFI_INVALID_TABLE_ADDR) { | ||
70 | si = early_memremap_ro(screen_info_table, sizeof(*si)); | ||
71 | if (!si) { | ||
72 | pr_err("Could not map screen_info config table\n"); | ||
73 | return; | ||
74 | } | ||
75 | screen_info = *si; | ||
76 | early_memunmap(si, sizeof(*si)); | ||
77 | |||
78 | /* dummycon on ARM needs non-zero values for columns/lines */ | ||
79 | screen_info.orig_video_cols = 80; | ||
80 | screen_info.orig_video_lines = 25; | ||
81 | } | ||
82 | |||
83 | if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI && | ||
84 | memblock_is_map_memory(screen_info.lfb_base)) | ||
85 | memblock_mark_nomap(screen_info.lfb_base, screen_info.lfb_size); | ||
86 | } | ||
87 | |||
56 | static int __init uefi_init(void) | 88 | static int __init uefi_init(void) |
57 | { | 89 | { |
58 | efi_char16_t *c16; | 90 | efi_char16_t *c16; |
@@ -85,6 +117,8 @@ static int __init uefi_init(void) | |||
85 | efi.systab->hdr.revision >> 16, | 117 | efi.systab->hdr.revision >> 16, |
86 | efi.systab->hdr.revision & 0xffff); | 118 | efi.systab->hdr.revision & 0xffff); |
87 | 119 | ||
120 | efi.runtime_version = efi.systab->hdr.revision; | ||
121 | |||
88 | /* Show what we know for posterity */ | 122 | /* Show what we know for posterity */ |
89 | c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor), | 123 | c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor), |
90 | sizeof(vendor) * sizeof(efi_char16_t)); | 124 | sizeof(vendor) * sizeof(efi_char16_t)); |
@@ -108,7 +142,8 @@ static int __init uefi_init(void) | |||
108 | goto out; | 142 | goto out; |
109 | } | 143 | } |
110 | retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, | 144 | retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, |
111 | sizeof(efi_config_table_t), NULL); | 145 | sizeof(efi_config_table_t), |
146 | arch_tables); | ||
112 | 147 | ||
113 | early_memunmap(config_tables, table_size); | 148 | early_memunmap(config_tables, table_size); |
114 | out: | 149 | out: |
@@ -143,7 +178,7 @@ static __init void reserve_regions(void) | |||
143 | if (efi_enabled(EFI_DBG)) | 178 | if (efi_enabled(EFI_DBG)) |
144 | pr_info("Processing EFI memory map:\n"); | 179 | pr_info("Processing EFI memory map:\n"); |
145 | 180 | ||
146 | for_each_efi_memory_desc(&memmap, md) { | 181 | for_each_efi_memory_desc(md) { |
147 | paddr = md->phys_addr; | 182 | paddr = md->phys_addr; |
148 | npages = md->num_pages; | 183 | npages = md->num_pages; |
149 | 184 | ||
@@ -184,9 +219,9 @@ void __init efi_init(void) | |||
184 | 219 | ||
185 | efi_system_table = params.system_table; | 220 | efi_system_table = params.system_table; |
186 | 221 | ||
187 | memmap.phys_map = params.mmap; | 222 | efi.memmap.phys_map = params.mmap; |
188 | memmap.map = early_memremap_ro(params.mmap, params.mmap_size); | 223 | efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size); |
189 | if (memmap.map == NULL) { | 224 | if (efi.memmap.map == NULL) { |
190 | /* | 225 | /* |
191 | * If we are booting via UEFI, the UEFI memory map is the only | 226 | * If we are booting via UEFI, the UEFI memory map is the only |
192 | * description of memory we have, so there is little point in | 227 | * description of memory we have, so there is little point in |
@@ -194,28 +229,37 @@ void __init efi_init(void) | |||
194 | */ | 229 | */ |
195 | panic("Unable to map EFI memory map.\n"); | 230 | panic("Unable to map EFI memory map.\n"); |
196 | } | 231 | } |
197 | memmap.map_end = memmap.map + params.mmap_size; | 232 | efi.memmap.map_end = efi.memmap.map + params.mmap_size; |
198 | memmap.desc_size = params.desc_size; | 233 | efi.memmap.desc_size = params.desc_size; |
199 | memmap.desc_version = params.desc_ver; | 234 | efi.memmap.desc_version = params.desc_ver; |
235 | |||
236 | WARN(efi.memmap.desc_version != 1, | ||
237 | "Unexpected EFI_MEMORY_DESCRIPTOR version %ld", | ||
238 | efi.memmap.desc_version); | ||
200 | 239 | ||
201 | if (uefi_init() < 0) | 240 | if (uefi_init() < 0) |
202 | return; | 241 | return; |
203 | 242 | ||
204 | reserve_regions(); | 243 | reserve_regions(); |
205 | early_memunmap(memmap.map, params.mmap_size); | 244 | efi_memattr_init(); |
245 | early_memunmap(efi.memmap.map, params.mmap_size); | ||
206 | 246 | ||
207 | if (IS_ENABLED(CONFIG_ARM)) { | 247 | memblock_reserve(params.mmap & PAGE_MASK, |
208 | /* | 248 | PAGE_ALIGN(params.mmap_size + |
209 | * ARM currently does not allow ioremap_cache() to be called on | 249 | (params.mmap & ~PAGE_MASK))); |
210 | * memory regions that are covered by struct page. So remove the | 250 | |
211 | * UEFI memory map from the linear mapping. | 251 | init_screen_info(); |
212 | */ | 252 | } |
213 | memblock_mark_nomap(params.mmap & PAGE_MASK, | 253 | |
214 | PAGE_ALIGN(params.mmap_size + | 254 | static int __init register_gop_device(void) |
215 | (params.mmap & ~PAGE_MASK))); | 255 | { |
216 | } else { | 256 | void *pd; |
217 | memblock_reserve(params.mmap & PAGE_MASK, | 257 | |
218 | PAGE_ALIGN(params.mmap_size + | 258 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) |
219 | (params.mmap & ~PAGE_MASK))); | 259 | return 0; |
220 | } | 260 | |
261 | pd = platform_device_register_data(NULL, "efi-framebuffer", 0, | ||
262 | &screen_info, sizeof(screen_info)); | ||
263 | return PTR_ERR_OR_ZERO(pd); | ||
221 | } | 264 | } |
265 | subsys_initcall(register_gop_device); | ||
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 6ae21e41a429..17ccf0a8787a 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c | |||
@@ -42,11 +42,13 @@ static struct mm_struct efi_mm = { | |||
42 | static bool __init efi_virtmap_init(void) | 42 | static bool __init efi_virtmap_init(void) |
43 | { | 43 | { |
44 | efi_memory_desc_t *md; | 44 | efi_memory_desc_t *md; |
45 | bool systab_found; | ||
45 | 46 | ||
46 | efi_mm.pgd = pgd_alloc(&efi_mm); | 47 | efi_mm.pgd = pgd_alloc(&efi_mm); |
47 | init_new_context(NULL, &efi_mm); | 48 | init_new_context(NULL, &efi_mm); |
48 | 49 | ||
49 | for_each_efi_memory_desc(&memmap, md) { | 50 | systab_found = false; |
51 | for_each_efi_memory_desc(md) { | ||
50 | phys_addr_t phys = md->phys_addr; | 52 | phys_addr_t phys = md->phys_addr; |
51 | int ret; | 53 | int ret; |
52 | 54 | ||
@@ -64,7 +66,25 @@ static bool __init efi_virtmap_init(void) | |||
64 | &phys, ret); | 66 | &phys, ret); |
65 | return false; | 67 | return false; |
66 | } | 68 | } |
69 | /* | ||
70 | * If this entry covers the address of the UEFI system table, | ||
71 | * calculate and record its virtual address. | ||
72 | */ | ||
73 | if (efi_system_table >= phys && | ||
74 | efi_system_table < phys + (md->num_pages * EFI_PAGE_SIZE)) { | ||
75 | efi.systab = (void *)(unsigned long)(efi_system_table - | ||
76 | phys + md->virt_addr); | ||
77 | systab_found = true; | ||
78 | } | ||
79 | } | ||
80 | if (!systab_found) { | ||
81 | pr_err("No virtual mapping found for the UEFI System Table\n"); | ||
82 | return false; | ||
67 | } | 83 | } |
84 | |||
85 | if (efi_memattr_apply_permissions(&efi_mm, efi_set_mapping_permissions)) | ||
86 | return false; | ||
87 | |||
68 | return true; | 88 | return true; |
69 | } | 89 | } |
70 | 90 | ||
@@ -89,26 +109,17 @@ static int __init arm_enable_runtime_services(void) | |||
89 | 109 | ||
90 | pr_info("Remapping and enabling EFI services.\n"); | 110 | pr_info("Remapping and enabling EFI services.\n"); |
91 | 111 | ||
92 | mapsize = memmap.map_end - memmap.map; | 112 | mapsize = efi.memmap.map_end - efi.memmap.map; |
93 | memmap.map = (__force void *)ioremap_cache(memmap.phys_map, | ||
94 | mapsize); | ||
95 | if (!memmap.map) { | ||
96 | pr_err("Failed to remap EFI memory map\n"); | ||
97 | return -ENOMEM; | ||
98 | } | ||
99 | memmap.map_end = memmap.map + mapsize; | ||
100 | efi.memmap = &memmap; | ||
101 | 113 | ||
102 | efi.systab = (__force void *)ioremap_cache(efi_system_table, | 114 | efi.memmap.map = memremap(efi.memmap.phys_map, mapsize, MEMREMAP_WB); |
103 | sizeof(efi_system_table_t)); | 115 | if (!efi.memmap.map) { |
104 | if (!efi.systab) { | 116 | pr_err("Failed to remap EFI memory map\n"); |
105 | pr_err("Failed to remap EFI System Table\n"); | ||
106 | return -ENOMEM; | 117 | return -ENOMEM; |
107 | } | 118 | } |
108 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); | 119 | efi.memmap.map_end = efi.memmap.map + mapsize; |
109 | 120 | ||
110 | if (!efi_virtmap_init()) { | 121 | if (!efi_virtmap_init()) { |
111 | pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); | 122 | pr_err("UEFI virtual mapping missing or invalid -- runtime services will not be available\n"); |
112 | return -ENOMEM; | 123 | return -ENOMEM; |
113 | } | 124 | } |
114 | 125 | ||
@@ -116,8 +127,6 @@ static int __init arm_enable_runtime_services(void) | |||
116 | efi_native_runtime_setup(); | 127 | efi_native_runtime_setup(); |
117 | set_bit(EFI_RUNTIME_SERVICES, &efi.flags); | 128 | set_bit(EFI_RUNTIME_SERVICES, &efi.flags); |
118 | 129 | ||
119 | efi.runtime_version = efi.systab->hdr.revision; | ||
120 | |||
121 | return 0; | 130 | return 0; |
122 | } | 131 | } |
123 | early_initcall(arm_enable_runtime_services); | 132 | early_initcall(arm_enable_runtime_services); |
diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c new file mode 100644 index 000000000000..c99c24bc79b0 --- /dev/null +++ b/drivers/firmware/efi/capsule-loader.c | |||
@@ -0,0 +1,343 @@ | |||
1 | /* | ||
2 | * EFI capsule loader driver. | ||
3 | * | ||
4 | * Copyright 2015 Intel Corporation | ||
5 | * | ||
6 | * This file is part of the Linux kernel, and is made available under | ||
7 | * the terms of the GNU General Public License version 2. | ||
8 | */ | ||
9 | |||
10 | #define pr_fmt(fmt) "efi: " fmt | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/miscdevice.h> | ||
15 | #include <linux/highmem.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/mutex.h> | ||
18 | #include <linux/efi.h> | ||
19 | |||
20 | #define NO_FURTHER_WRITE_ACTION -1 | ||
21 | |||
22 | struct capsule_info { | ||
23 | bool header_obtained; | ||
24 | int reset_type; | ||
25 | long index; | ||
26 | size_t count; | ||
27 | size_t total_size; | ||
28 | struct page **pages; | ||
29 | size_t page_bytes_remain; | ||
30 | }; | ||
31 | |||
32 | /** | ||
33 | * efi_free_all_buff_pages - free all previous allocated buffer pages | ||
34 | * @cap_info: pointer to current instance of capsule_info structure | ||
35 | * | ||
36 | * In addition to freeing buffer pages, it flags NO_FURTHER_WRITE_ACTION | ||
37 | * to cease processing data in subsequent write(2) calls until close(2) | ||
38 | * is called. | ||
39 | **/ | ||
40 | static void efi_free_all_buff_pages(struct capsule_info *cap_info) | ||
41 | { | ||
42 | while (cap_info->index > 0) | ||
43 | __free_page(cap_info->pages[--cap_info->index]); | ||
44 | |||
45 | cap_info->index = NO_FURTHER_WRITE_ACTION; | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * efi_capsule_setup_info - obtain the efi capsule header in the binary and | ||
50 | * setup capsule_info structure | ||
51 | * @cap_info: pointer to current instance of capsule_info structure | ||
52 | * @kbuff: a mapped first page buffer pointer | ||
53 | * @hdr_bytes: the total received number of bytes for efi header | ||
54 | **/ | ||
55 | static ssize_t efi_capsule_setup_info(struct capsule_info *cap_info, | ||
56 | void *kbuff, size_t hdr_bytes) | ||
57 | { | ||
58 | efi_capsule_header_t *cap_hdr; | ||
59 | size_t pages_needed; | ||
60 | int ret; | ||
61 | void *temp_page; | ||
62 | |||
63 | /* Only process data block that is larger than efi header size */ | ||
64 | if (hdr_bytes < sizeof(efi_capsule_header_t)) | ||
65 | return 0; | ||
66 | |||
67 | /* Reset back to the correct offset of header */ | ||
68 | cap_hdr = kbuff - cap_info->count; | ||
69 | pages_needed = ALIGN(cap_hdr->imagesize, PAGE_SIZE) >> PAGE_SHIFT; | ||
70 | |||
71 | if (pages_needed == 0) { | ||
72 | pr_err("%s: pages count invalid\n", __func__); | ||
73 | return -EINVAL; | ||
74 | } | ||
75 | |||
76 | /* Check if the capsule binary supported */ | ||
77 | ret = efi_capsule_supported(cap_hdr->guid, cap_hdr->flags, | ||
78 | cap_hdr->imagesize, | ||
79 | &cap_info->reset_type); | ||
80 | if (ret) { | ||
81 | pr_err("%s: efi_capsule_supported() failed\n", | ||
82 | __func__); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | cap_info->total_size = cap_hdr->imagesize; | ||
87 | temp_page = krealloc(cap_info->pages, | ||
88 | pages_needed * sizeof(void *), | ||
89 | GFP_KERNEL | __GFP_ZERO); | ||
90 | if (!temp_page) { | ||
91 | pr_debug("%s: krealloc() failed\n", __func__); | ||
92 | return -ENOMEM; | ||
93 | } | ||
94 | |||
95 | cap_info->pages = temp_page; | ||
96 | cap_info->header_obtained = true; | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * efi_capsule_submit_update - invoke the efi_capsule_update API once binary | ||
103 | * upload done | ||
104 | * @cap_info: pointer to current instance of capsule_info structure | ||
105 | **/ | ||
106 | static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info) | ||
107 | { | ||
108 | int ret; | ||
109 | void *cap_hdr_temp; | ||
110 | |||
111 | cap_hdr_temp = kmap(cap_info->pages[0]); | ||
112 | if (!cap_hdr_temp) { | ||
113 | pr_debug("%s: kmap() failed\n", __func__); | ||
114 | return -EFAULT; | ||
115 | } | ||
116 | |||
117 | ret = efi_capsule_update(cap_hdr_temp, cap_info->pages); | ||
118 | kunmap(cap_info->pages[0]); | ||
119 | if (ret) { | ||
120 | pr_err("%s: efi_capsule_update() failed\n", __func__); | ||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | /* Indicate capsule binary uploading is done */ | ||
125 | cap_info->index = NO_FURTHER_WRITE_ACTION; | ||
126 | pr_info("%s: Successfully upload capsule file with reboot type '%s'\n", | ||
127 | __func__, !cap_info->reset_type ? "RESET_COLD" : | ||
128 | cap_info->reset_type == 1 ? "RESET_WARM" : | ||
129 | "RESET_SHUTDOWN"); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * efi_capsule_write - store the capsule binary and pass it to | ||
135 | * efi_capsule_update() API | ||
136 | * @file: file pointer | ||
137 | * @buff: buffer pointer | ||
138 | * @count: number of bytes in @buff | ||
139 | * @offp: not used | ||
140 | * | ||
141 | * Expectation: | ||
142 | * - A user space tool should start at the beginning of capsule binary and | ||
143 | * pass data in sequentially. | ||
144 | * - Users should close and re-open this file note in order to upload more | ||
145 | * capsules. | ||
146 | * - After an error returned, user should close the file and restart the | ||
147 | * operation for the next try otherwise -EIO will be returned until the | ||
148 | * file is closed. | ||
149 | * - An EFI capsule header must be located at the beginning of capsule | ||
150 | * binary file and passed in as first block data of write operation. | ||
151 | **/ | ||
152 | static ssize_t efi_capsule_write(struct file *file, const char __user *buff, | ||
153 | size_t count, loff_t *offp) | ||
154 | { | ||
155 | int ret = 0; | ||
156 | struct capsule_info *cap_info = file->private_data; | ||
157 | struct page *page; | ||
158 | void *kbuff = NULL; | ||
159 | size_t write_byte; | ||
160 | |||
161 | if (count == 0) | ||
162 | return 0; | ||
163 | |||
164 | /* Return error while NO_FURTHER_WRITE_ACTION is flagged */ | ||
165 | if (cap_info->index < 0) | ||
166 | return -EIO; | ||
167 | |||
168 | /* Only alloc a new page when previous page is full */ | ||
169 | if (!cap_info->page_bytes_remain) { | ||
170 | page = alloc_page(GFP_KERNEL); | ||
171 | if (!page) { | ||
172 | pr_debug("%s: alloc_page() failed\n", __func__); | ||
173 | ret = -ENOMEM; | ||
174 | goto failed; | ||
175 | } | ||
176 | |||
177 | cap_info->pages[cap_info->index++] = page; | ||
178 | cap_info->page_bytes_remain = PAGE_SIZE; | ||
179 | } | ||
180 | |||
181 | page = cap_info->pages[cap_info->index - 1]; | ||
182 | |||
183 | kbuff = kmap(page); | ||
184 | if (!kbuff) { | ||
185 | pr_debug("%s: kmap() failed\n", __func__); | ||
186 | ret = -EFAULT; | ||
187 | goto failed; | ||
188 | } | ||
189 | kbuff += PAGE_SIZE - cap_info->page_bytes_remain; | ||
190 | |||
191 | /* Copy capsule binary data from user space to kernel space buffer */ | ||
192 | write_byte = min_t(size_t, count, cap_info->page_bytes_remain); | ||
193 | if (copy_from_user(kbuff, buff, write_byte)) { | ||
194 | pr_debug("%s: copy_from_user() failed\n", __func__); | ||
195 | ret = -EFAULT; | ||
196 | goto fail_unmap; | ||
197 | } | ||
198 | cap_info->page_bytes_remain -= write_byte; | ||
199 | |||
200 | /* Setup capsule binary info structure */ | ||
201 | if (!cap_info->header_obtained) { | ||
202 | ret = efi_capsule_setup_info(cap_info, kbuff, | ||
203 | cap_info->count + write_byte); | ||
204 | if (ret) | ||
205 | goto fail_unmap; | ||
206 | } | ||
207 | |||
208 | cap_info->count += write_byte; | ||
209 | kunmap(page); | ||
210 | |||
211 | /* Submit the full binary to efi_capsule_update() API */ | ||
212 | if (cap_info->header_obtained && | ||
213 | cap_info->count >= cap_info->total_size) { | ||
214 | if (cap_info->count > cap_info->total_size) { | ||
215 | pr_err("%s: upload size exceeded header defined size\n", | ||
216 | __func__); | ||
217 | ret = -EINVAL; | ||
218 | goto failed; | ||
219 | } | ||
220 | |||
221 | ret = efi_capsule_submit_update(cap_info); | ||
222 | if (ret) | ||
223 | goto failed; | ||
224 | } | ||
225 | |||
226 | return write_byte; | ||
227 | |||
228 | fail_unmap: | ||
229 | kunmap(page); | ||
230 | failed: | ||
231 | efi_free_all_buff_pages(cap_info); | ||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * efi_capsule_flush - called by file close or file flush | ||
237 | * @file: file pointer | ||
238 | * @id: not used | ||
239 | * | ||
240 | * If a capsule is being partially uploaded then calling this function | ||
241 | * will be treated as upload termination and will free those completed | ||
242 | * buffer pages and -ECANCELED will be returned. | ||
243 | **/ | ||
244 | static int efi_capsule_flush(struct file *file, fl_owner_t id) | ||
245 | { | ||
246 | int ret = 0; | ||
247 | struct capsule_info *cap_info = file->private_data; | ||
248 | |||
249 | if (cap_info->index > 0) { | ||
250 | pr_err("%s: capsule upload not complete\n", __func__); | ||
251 | efi_free_all_buff_pages(cap_info); | ||
252 | ret = -ECANCELED; | ||
253 | } | ||
254 | |||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * efi_capsule_release - called by file close | ||
260 | * @inode: not used | ||
261 | * @file: file pointer | ||
262 | * | ||
263 | * We will not free successfully submitted pages since efi update | ||
264 | * requires data to be maintained across system reboot. | ||
265 | **/ | ||
266 | static int efi_capsule_release(struct inode *inode, struct file *file) | ||
267 | { | ||
268 | struct capsule_info *cap_info = file->private_data; | ||
269 | |||
270 | kfree(cap_info->pages); | ||
271 | kfree(file->private_data); | ||
272 | file->private_data = NULL; | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * efi_capsule_open - called by file open | ||
278 | * @inode: not used | ||
279 | * @file: file pointer | ||
280 | * | ||
281 | * Will allocate each capsule_info memory for each file open call. | ||
282 | * This provided the capability to support multiple file open feature | ||
283 | * where user is not needed to wait for others to finish in order to | ||
284 | * upload their capsule binary. | ||
285 | **/ | ||
286 | static int efi_capsule_open(struct inode *inode, struct file *file) | ||
287 | { | ||
288 | struct capsule_info *cap_info; | ||
289 | |||
290 | cap_info = kzalloc(sizeof(*cap_info), GFP_KERNEL); | ||
291 | if (!cap_info) | ||
292 | return -ENOMEM; | ||
293 | |||
294 | cap_info->pages = kzalloc(sizeof(void *), GFP_KERNEL); | ||
295 | if (!cap_info->pages) { | ||
296 | kfree(cap_info); | ||
297 | return -ENOMEM; | ||
298 | } | ||
299 | |||
300 | file->private_data = cap_info; | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static const struct file_operations efi_capsule_fops = { | ||
306 | .owner = THIS_MODULE, | ||
307 | .open = efi_capsule_open, | ||
308 | .write = efi_capsule_write, | ||
309 | .flush = efi_capsule_flush, | ||
310 | .release = efi_capsule_release, | ||
311 | .llseek = no_llseek, | ||
312 | }; | ||
313 | |||
314 | static struct miscdevice efi_capsule_misc = { | ||
315 | .minor = MISC_DYNAMIC_MINOR, | ||
316 | .name = "efi_capsule_loader", | ||
317 | .fops = &efi_capsule_fops, | ||
318 | }; | ||
319 | |||
320 | static int __init efi_capsule_loader_init(void) | ||
321 | { | ||
322 | int ret; | ||
323 | |||
324 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) | ||
325 | return -ENODEV; | ||
326 | |||
327 | ret = misc_register(&efi_capsule_misc); | ||
328 | if (ret) | ||
329 | pr_err("%s: Failed to register misc char file note\n", | ||
330 | __func__); | ||
331 | |||
332 | return ret; | ||
333 | } | ||
334 | module_init(efi_capsule_loader_init); | ||
335 | |||
336 | static void __exit efi_capsule_loader_exit(void) | ||
337 | { | ||
338 | misc_deregister(&efi_capsule_misc); | ||
339 | } | ||
340 | module_exit(efi_capsule_loader_exit); | ||
341 | |||
342 | MODULE_DESCRIPTION("EFI capsule firmware binary loader"); | ||
343 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/firmware/efi/capsule.c b/drivers/firmware/efi/capsule.c new file mode 100644 index 000000000000..53b9fd2293ee --- /dev/null +++ b/drivers/firmware/efi/capsule.c | |||
@@ -0,0 +1,308 @@ | |||
1 | /* | ||
2 | * EFI capsule support. | ||
3 | * | ||
4 | * Copyright 2013 Intel Corporation; author Matt Fleming | ||
5 | * | ||
6 | * This file is part of the Linux kernel, and is made available under | ||
7 | * the terms of the GNU General Public License version 2. | ||
8 | */ | ||
9 | |||
10 | #define pr_fmt(fmt) "efi: " fmt | ||
11 | |||
12 | #include <linux/slab.h> | ||
13 | #include <linux/mutex.h> | ||
14 | #include <linux/highmem.h> | ||
15 | #include <linux/efi.h> | ||
16 | #include <linux/vmalloc.h> | ||
17 | #include <asm/io.h> | ||
18 | |||
19 | typedef struct { | ||
20 | u64 length; | ||
21 | u64 data; | ||
22 | } efi_capsule_block_desc_t; | ||
23 | |||
24 | static bool capsule_pending; | ||
25 | static bool stop_capsules; | ||
26 | static int efi_reset_type = -1; | ||
27 | |||
28 | /* | ||
29 | * capsule_mutex serialises access to both capsule_pending and | ||
30 | * efi_reset_type and stop_capsules. | ||
31 | */ | ||
32 | static DEFINE_MUTEX(capsule_mutex); | ||
33 | |||
34 | /** | ||
35 | * efi_capsule_pending - has a capsule been passed to the firmware? | ||
36 | * @reset_type: store the type of EFI reset if capsule is pending | ||
37 | * | ||
38 | * To ensure that the registered capsule is processed correctly by the | ||
39 | * firmware we need to perform a specific type of reset. If a capsule is | ||
40 | * pending return the reset type in @reset_type. | ||
41 | * | ||
42 | * This function will race with callers of efi_capsule_update(), for | ||
43 | * example, calling this function while somebody else is in | ||
44 | * efi_capsule_update() but hasn't reached efi_capsue_update_locked() | ||
45 | * will miss the updates to capsule_pending and efi_reset_type after | ||
46 | * efi_capsule_update_locked() completes. | ||
47 | * | ||
48 | * A non-racy use is from platform reboot code because we use | ||
49 | * system_state to ensure no capsules can be sent to the firmware once | ||
50 | * we're at SYSTEM_RESTART. See efi_capsule_update_locked(). | ||
51 | */ | ||
52 | bool efi_capsule_pending(int *reset_type) | ||
53 | { | ||
54 | if (!capsule_pending) | ||
55 | return false; | ||
56 | |||
57 | if (reset_type) | ||
58 | *reset_type = efi_reset_type; | ||
59 | |||
60 | return true; | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * Whitelist of EFI capsule flags that we support. | ||
65 | * | ||
66 | * We do not handle EFI_CAPSULE_INITIATE_RESET because that would | ||
67 | * require us to prepare the kernel for reboot. Refuse to load any | ||
68 | * capsules with that flag and any other flags that we do not know how | ||
69 | * to handle. | ||
70 | */ | ||
71 | #define EFI_CAPSULE_SUPPORTED_FLAG_MASK \ | ||
72 | (EFI_CAPSULE_PERSIST_ACROSS_RESET | EFI_CAPSULE_POPULATE_SYSTEM_TABLE) | ||
73 | |||
74 | /** | ||
75 | * efi_capsule_supported - does the firmware support the capsule? | ||
76 | * @guid: vendor guid of capsule | ||
77 | * @flags: capsule flags | ||
78 | * @size: size of capsule data | ||
79 | * @reset: the reset type required for this capsule | ||
80 | * | ||
81 | * Check whether a capsule with @flags is supported by the firmware | ||
82 | * and that @size doesn't exceed the maximum size for a capsule. | ||
83 | * | ||
84 | * No attempt is made to check @reset against the reset type required | ||
85 | * by any pending capsules because of the races involved. | ||
86 | */ | ||
87 | int efi_capsule_supported(efi_guid_t guid, u32 flags, size_t size, int *reset) | ||
88 | { | ||
89 | efi_capsule_header_t capsule; | ||
90 | efi_capsule_header_t *cap_list[] = { &capsule }; | ||
91 | efi_status_t status; | ||
92 | u64 max_size; | ||
93 | |||
94 | if (flags & ~EFI_CAPSULE_SUPPORTED_FLAG_MASK) | ||
95 | return -EINVAL; | ||
96 | |||
97 | capsule.headersize = capsule.imagesize = sizeof(capsule); | ||
98 | memcpy(&capsule.guid, &guid, sizeof(efi_guid_t)); | ||
99 | capsule.flags = flags; | ||
100 | |||
101 | status = efi.query_capsule_caps(cap_list, 1, &max_size, reset); | ||
102 | if (status != EFI_SUCCESS) | ||
103 | return efi_status_to_err(status); | ||
104 | |||
105 | if (size > max_size) | ||
106 | return -ENOSPC; | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | EXPORT_SYMBOL_GPL(efi_capsule_supported); | ||
111 | |||
112 | /* | ||
113 | * Every scatter gather list (block descriptor) page must end with a | ||
114 | * continuation pointer. The last continuation pointer of the last | ||
115 | * page must be zero to mark the end of the chain. | ||
116 | */ | ||
117 | #define SGLIST_PER_PAGE ((PAGE_SIZE / sizeof(efi_capsule_block_desc_t)) - 1) | ||
118 | |||
119 | /* | ||
120 | * How many scatter gather list (block descriptor) pages do we need | ||
121 | * to map @count pages? | ||
122 | */ | ||
123 | static inline unsigned int sg_pages_num(unsigned int count) | ||
124 | { | ||
125 | return DIV_ROUND_UP(count, SGLIST_PER_PAGE); | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * efi_capsule_update_locked - pass a single capsule to the firmware | ||
130 | * @capsule: capsule to send to the firmware | ||
131 | * @sg_pages: array of scatter gather (block descriptor) pages | ||
132 | * @reset: the reset type required for @capsule | ||
133 | * | ||
134 | * Since this function must be called under capsule_mutex check | ||
135 | * whether efi_reset_type will conflict with @reset, and atomically | ||
136 | * set it and capsule_pending if a capsule was successfully sent to | ||
137 | * the firmware. | ||
138 | * | ||
139 | * We also check to see if the system is about to restart, and if so, | ||
140 | * abort. This avoids races between efi_capsule_update() and | ||
141 | * efi_capsule_pending(). | ||
142 | */ | ||
143 | static int | ||
144 | efi_capsule_update_locked(efi_capsule_header_t *capsule, | ||
145 | struct page **sg_pages, int reset) | ||
146 | { | ||
147 | efi_physical_addr_t sglist_phys; | ||
148 | efi_status_t status; | ||
149 | |||
150 | lockdep_assert_held(&capsule_mutex); | ||
151 | |||
152 | /* | ||
153 | * If someone has already registered a capsule that requires a | ||
154 | * different reset type, we're out of luck and must abort. | ||
155 | */ | ||
156 | if (efi_reset_type >= 0 && efi_reset_type != reset) { | ||
157 | pr_err("Conflicting capsule reset type %d (%d).\n", | ||
158 | reset, efi_reset_type); | ||
159 | return -EINVAL; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * If the system is getting ready to restart it may have | ||
164 | * called efi_capsule_pending() to make decisions (such as | ||
165 | * whether to force an EFI reboot), and we're racing against | ||
166 | * that call. Abort in that case. | ||
167 | */ | ||
168 | if (unlikely(stop_capsules)) { | ||
169 | pr_warn("Capsule update raced with reboot, aborting.\n"); | ||
170 | return -EINVAL; | ||
171 | } | ||
172 | |||
173 | sglist_phys = page_to_phys(sg_pages[0]); | ||
174 | |||
175 | status = efi.update_capsule(&capsule, 1, sglist_phys); | ||
176 | if (status == EFI_SUCCESS) { | ||
177 | capsule_pending = true; | ||
178 | efi_reset_type = reset; | ||
179 | } | ||
180 | |||
181 | return efi_status_to_err(status); | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * efi_capsule_update - send a capsule to the firmware | ||
186 | * @capsule: capsule to send to firmware | ||
187 | * @pages: an array of capsule data pages | ||
188 | * | ||
189 | * Build a scatter gather list with EFI capsule block descriptors to | ||
190 | * map the capsule described by @capsule with its data in @pages and | ||
191 | * send it to the firmware via the UpdateCapsule() runtime service. | ||
192 | * | ||
193 | * @capsule must be a virtual mapping of the first page in @pages | ||
194 | * (@pages[0]) in the kernel address space. That is, a | ||
195 | * capsule_header_t that describes the entire contents of the capsule | ||
196 | * must be at the start of the first data page. | ||
197 | * | ||
198 | * Even though this function will validate that the firmware supports | ||
199 | * the capsule guid, users will likely want to check that | ||
200 | * efi_capsule_supported() returns true before calling this function | ||
201 | * because it makes it easier to print helpful error messages. | ||
202 | * | ||
203 | * If the capsule is successfully submitted to the firmware, any | ||
204 | * subsequent calls to efi_capsule_pending() will return true. @pages | ||
205 | * must not be released or modified if this function returns | ||
206 | * successfully. | ||
207 | * | ||
208 | * Callers must be prepared for this function to fail, which can | ||
209 | * happen if we raced with system reboot or if there is already a | ||
210 | * pending capsule that has a reset type that conflicts with the one | ||
211 | * required by @capsule. Do NOT use efi_capsule_pending() to detect | ||
212 | * this conflict since that would be racy. Instead, submit the capsule | ||
213 | * to efi_capsule_update() and check the return value. | ||
214 | * | ||
215 | * Return 0 on success, a converted EFI status code on failure. | ||
216 | */ | ||
217 | int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages) | ||
218 | { | ||
219 | u32 imagesize = capsule->imagesize; | ||
220 | efi_guid_t guid = capsule->guid; | ||
221 | unsigned int count, sg_count; | ||
222 | u32 flags = capsule->flags; | ||
223 | struct page **sg_pages; | ||
224 | int rv, reset_type; | ||
225 | int i, j; | ||
226 | |||
227 | rv = efi_capsule_supported(guid, flags, imagesize, &reset_type); | ||
228 | if (rv) | ||
229 | return rv; | ||
230 | |||
231 | count = DIV_ROUND_UP(imagesize, PAGE_SIZE); | ||
232 | sg_count = sg_pages_num(count); | ||
233 | |||
234 | sg_pages = kzalloc(sg_count * sizeof(*sg_pages), GFP_KERNEL); | ||
235 | if (!sg_pages) | ||
236 | return -ENOMEM; | ||
237 | |||
238 | for (i = 0; i < sg_count; i++) { | ||
239 | sg_pages[i] = alloc_page(GFP_KERNEL); | ||
240 | if (!sg_pages[i]) { | ||
241 | rv = -ENOMEM; | ||
242 | goto out; | ||
243 | } | ||
244 | } | ||
245 | |||
246 | for (i = 0; i < sg_count; i++) { | ||
247 | efi_capsule_block_desc_t *sglist; | ||
248 | |||
249 | sglist = kmap(sg_pages[i]); | ||
250 | if (!sglist) { | ||
251 | rv = -ENOMEM; | ||
252 | goto out; | ||
253 | } | ||
254 | |||
255 | for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) { | ||
256 | u64 sz = min_t(u64, imagesize, PAGE_SIZE); | ||
257 | |||
258 | sglist[j].length = sz; | ||
259 | sglist[j].data = page_to_phys(*pages++); | ||
260 | |||
261 | imagesize -= sz; | ||
262 | count--; | ||
263 | } | ||
264 | |||
265 | /* Continuation pointer */ | ||
266 | sglist[j].length = 0; | ||
267 | |||
268 | if (i + 1 == sg_count) | ||
269 | sglist[j].data = 0; | ||
270 | else | ||
271 | sglist[j].data = page_to_phys(sg_pages[i + 1]); | ||
272 | |||
273 | kunmap(sg_pages[i]); | ||
274 | } | ||
275 | |||
276 | mutex_lock(&capsule_mutex); | ||
277 | rv = efi_capsule_update_locked(capsule, sg_pages, reset_type); | ||
278 | mutex_unlock(&capsule_mutex); | ||
279 | |||
280 | out: | ||
281 | for (i = 0; rv && i < sg_count; i++) { | ||
282 | if (sg_pages[i]) | ||
283 | __free_page(sg_pages[i]); | ||
284 | } | ||
285 | |||
286 | kfree(sg_pages); | ||
287 | return rv; | ||
288 | } | ||
289 | EXPORT_SYMBOL_GPL(efi_capsule_update); | ||
290 | |||
291 | static int capsule_reboot_notify(struct notifier_block *nb, unsigned long event, void *cmd) | ||
292 | { | ||
293 | mutex_lock(&capsule_mutex); | ||
294 | stop_capsules = true; | ||
295 | mutex_unlock(&capsule_mutex); | ||
296 | |||
297 | return NOTIFY_DONE; | ||
298 | } | ||
299 | |||
300 | static struct notifier_block capsule_reboot_nb = { | ||
301 | .notifier_call = capsule_reboot_notify, | ||
302 | }; | ||
303 | |||
304 | static int __init capsule_reboot_register(void) | ||
305 | { | ||
306 | return register_reboot_notifier(&capsule_reboot_nb); | ||
307 | } | ||
308 | core_initcall(capsule_reboot_register); | ||
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 3a69ed5ecfcb..05509f3aaee8 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
@@ -43,6 +43,7 @@ struct efi __read_mostly efi = { | |||
43 | .config_table = EFI_INVALID_TABLE_ADDR, | 43 | .config_table = EFI_INVALID_TABLE_ADDR, |
44 | .esrt = EFI_INVALID_TABLE_ADDR, | 44 | .esrt = EFI_INVALID_TABLE_ADDR, |
45 | .properties_table = EFI_INVALID_TABLE_ADDR, | 45 | .properties_table = EFI_INVALID_TABLE_ADDR, |
46 | .mem_attr_table = EFI_INVALID_TABLE_ADDR, | ||
46 | }; | 47 | }; |
47 | EXPORT_SYMBOL(efi); | 48 | EXPORT_SYMBOL(efi); |
48 | 49 | ||
@@ -256,7 +257,7 @@ subsys_initcall(efisubsys_init); | |||
256 | */ | 257 | */ |
257 | int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) | 258 | int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) |
258 | { | 259 | { |
259 | struct efi_memory_map *map = efi.memmap; | 260 | struct efi_memory_map *map = &efi.memmap; |
260 | phys_addr_t p, e; | 261 | phys_addr_t p, e; |
261 | 262 | ||
262 | if (!efi_enabled(EFI_MEMMAP)) { | 263 | if (!efi_enabled(EFI_MEMMAP)) { |
@@ -338,6 +339,7 @@ static __initdata efi_config_table_type_t common_tables[] = { | |||
338 | {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, | 339 | {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, |
339 | {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, | 340 | {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, |
340 | {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, | 341 | {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, |
342 | {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, | ||
341 | {NULL_GUID, NULL, NULL}, | 343 | {NULL_GUID, NULL, NULL}, |
342 | }; | 344 | }; |
343 | 345 | ||
@@ -351,8 +353,9 @@ static __init int match_config_table(efi_guid_t *guid, | |||
351 | for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) { | 353 | for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) { |
352 | if (!efi_guidcmp(*guid, table_types[i].guid)) { | 354 | if (!efi_guidcmp(*guid, table_types[i].guid)) { |
353 | *(table_types[i].ptr) = table; | 355 | *(table_types[i].ptr) = table; |
354 | pr_cont(" %s=0x%lx ", | 356 | if (table_types[i].name) |
355 | table_types[i].name, table); | 357 | pr_cont(" %s=0x%lx ", |
358 | table_types[i].name, table); | ||
356 | return 1; | 359 | return 1; |
357 | } | 360 | } |
358 | } | 361 | } |
@@ -620,16 +623,12 @@ char * __init efi_md_typeattr_format(char *buf, size_t size, | |||
620 | */ | 623 | */ |
621 | u64 __weak efi_mem_attributes(unsigned long phys_addr) | 624 | u64 __weak efi_mem_attributes(unsigned long phys_addr) |
622 | { | 625 | { |
623 | struct efi_memory_map *map; | ||
624 | efi_memory_desc_t *md; | 626 | efi_memory_desc_t *md; |
625 | void *p; | ||
626 | 627 | ||
627 | if (!efi_enabled(EFI_MEMMAP)) | 628 | if (!efi_enabled(EFI_MEMMAP)) |
628 | return 0; | 629 | return 0; |
629 | 630 | ||
630 | map = efi.memmap; | 631 | for_each_efi_memory_desc(md) { |
631 | for (p = map->map; p < map->map_end; p += map->desc_size) { | ||
632 | md = p; | ||
633 | if ((md->phys_addr <= phys_addr) && | 632 | if ((md->phys_addr <= phys_addr) && |
634 | (phys_addr < (md->phys_addr + | 633 | (phys_addr < (md->phys_addr + |
635 | (md->num_pages << EFI_PAGE_SHIFT)))) | 634 | (md->num_pages << EFI_PAGE_SHIFT)))) |
@@ -637,3 +636,36 @@ u64 __weak efi_mem_attributes(unsigned long phys_addr) | |||
637 | } | 636 | } |
638 | return 0; | 637 | return 0; |
639 | } | 638 | } |
639 | |||
640 | int efi_status_to_err(efi_status_t status) | ||
641 | { | ||
642 | int err; | ||
643 | |||
644 | switch (status) { | ||
645 | case EFI_SUCCESS: | ||
646 | err = 0; | ||
647 | break; | ||
648 | case EFI_INVALID_PARAMETER: | ||
649 | err = -EINVAL; | ||
650 | break; | ||
651 | case EFI_OUT_OF_RESOURCES: | ||
652 | err = -ENOSPC; | ||
653 | break; | ||
654 | case EFI_DEVICE_ERROR: | ||
655 | err = -EIO; | ||
656 | break; | ||
657 | case EFI_WRITE_PROTECTED: | ||
658 | err = -EROFS; | ||
659 | break; | ||
660 | case EFI_SECURITY_VIOLATION: | ||
661 | err = -EACCES; | ||
662 | break; | ||
663 | case EFI_NOT_FOUND: | ||
664 | err = -ENOENT; | ||
665 | break; | ||
666 | default: | ||
667 | err = -EINVAL; | ||
668 | } | ||
669 | |||
670 | return err; | ||
671 | } | ||
diff --git a/drivers/firmware/efi/efibc.c b/drivers/firmware/efi/efibc.c new file mode 100644 index 000000000000..8dd0c7085e59 --- /dev/null +++ b/drivers/firmware/efi/efibc.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * efibc: control EFI bootloaders which obey LoaderEntryOneShot var | ||
3 | * Copyright (c) 2013-2016, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #define pr_fmt(fmt) "efibc: " fmt | ||
16 | |||
17 | #include <linux/efi.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/reboot.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | static void efibc_str_to_str16(const char *str, efi_char16_t *str16) | ||
23 | { | ||
24 | size_t i; | ||
25 | |||
26 | for (i = 0; i < strlen(str); i++) | ||
27 | str16[i] = str[i]; | ||
28 | |||
29 | str16[i] = '\0'; | ||
30 | } | ||
31 | |||
32 | static int efibc_set_variable(const char *name, const char *value) | ||
33 | { | ||
34 | int ret; | ||
35 | efi_guid_t guid = LINUX_EFI_LOADER_ENTRY_GUID; | ||
36 | struct efivar_entry *entry; | ||
37 | size_t size = (strlen(value) + 1) * sizeof(efi_char16_t); | ||
38 | |||
39 | if (size > sizeof(entry->var.Data)) { | ||
40 | pr_err("value is too large"); | ||
41 | return -EINVAL; | ||
42 | } | ||
43 | |||
44 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
45 | if (!entry) { | ||
46 | pr_err("failed to allocate efivar entry"); | ||
47 | return -ENOMEM; | ||
48 | } | ||
49 | |||
50 | efibc_str_to_str16(name, entry->var.VariableName); | ||
51 | efibc_str_to_str16(value, (efi_char16_t *)entry->var.Data); | ||
52 | memcpy(&entry->var.VendorGuid, &guid, sizeof(guid)); | ||
53 | |||
54 | ret = efivar_entry_set(entry, | ||
55 | EFI_VARIABLE_NON_VOLATILE | ||
56 | | EFI_VARIABLE_BOOTSERVICE_ACCESS | ||
57 | | EFI_VARIABLE_RUNTIME_ACCESS, | ||
58 | size, entry->var.Data, NULL); | ||
59 | if (ret) | ||
60 | pr_err("failed to set %s EFI variable: 0x%x\n", | ||
61 | name, ret); | ||
62 | |||
63 | kfree(entry); | ||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | static int efibc_reboot_notifier_call(struct notifier_block *notifier, | ||
68 | unsigned long event, void *data) | ||
69 | { | ||
70 | const char *reason = "shutdown"; | ||
71 | int ret; | ||
72 | |||
73 | if (event == SYS_RESTART) | ||
74 | reason = "reboot"; | ||
75 | |||
76 | ret = efibc_set_variable("LoaderEntryRebootReason", reason); | ||
77 | if (ret || !data) | ||
78 | return NOTIFY_DONE; | ||
79 | |||
80 | efibc_set_variable("LoaderEntryOneShot", (char *)data); | ||
81 | |||
82 | return NOTIFY_DONE; | ||
83 | } | ||
84 | |||
85 | static struct notifier_block efibc_reboot_notifier = { | ||
86 | .notifier_call = efibc_reboot_notifier_call, | ||
87 | }; | ||
88 | |||
89 | static int __init efibc_init(void) | ||
90 | { | ||
91 | int ret; | ||
92 | |||
93 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) | ||
94 | return -ENODEV; | ||
95 | |||
96 | ret = register_reboot_notifier(&efibc_reboot_notifier); | ||
97 | if (ret) | ||
98 | pr_err("unable to register reboot notifier\n"); | ||
99 | |||
100 | return ret; | ||
101 | } | ||
102 | module_init(efibc_init); | ||
103 | |||
104 | static void __exit efibc_exit(void) | ||
105 | { | ||
106 | unregister_reboot_notifier(&efibc_reboot_notifier); | ||
107 | } | ||
108 | module_exit(efibc_exit); | ||
109 | |||
110 | MODULE_AUTHOR("Jeremy Compostella <jeremy.compostella@intel.com>"); | ||
111 | MODULE_AUTHOR("Matt Gumbel <matthew.k.gumbel@intel.com"); | ||
112 | MODULE_DESCRIPTION("EFI Bootloader Control"); | ||
113 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 096adcbcb5a9..116b244dee68 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c | |||
@@ -661,7 +661,7 @@ static void efivar_update_sysfs_entries(struct work_struct *work) | |||
661 | return; | 661 | return; |
662 | 662 | ||
663 | err = efivar_init(efivar_update_sysfs_entry, entry, | 663 | err = efivar_init(efivar_update_sysfs_entry, entry, |
664 | true, false, &efivar_sysfs_list); | 664 | false, &efivar_sysfs_list); |
665 | if (!err) | 665 | if (!err) |
666 | break; | 666 | break; |
667 | 667 | ||
@@ -730,8 +730,7 @@ int efivars_sysfs_init(void) | |||
730 | return -ENOMEM; | 730 | return -ENOMEM; |
731 | } | 731 | } |
732 | 732 | ||
733 | efivar_init(efivars_sysfs_callback, NULL, false, | 733 | efivar_init(efivars_sysfs_callback, NULL, true, &efivar_sysfs_list); |
734 | true, &efivar_sysfs_list); | ||
735 | 734 | ||
736 | error = create_efivars_bin_attributes(); | 735 | error = create_efivars_bin_attributes(); |
737 | if (error) { | 736 | if (error) { |
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c index ed3a854950cc..48430aba13c1 100644 --- a/drivers/firmware/efi/fake_mem.c +++ b/drivers/firmware/efi/fake_mem.c | |||
@@ -57,7 +57,7 @@ static int __init cmp_fake_mem(const void *x1, const void *x2) | |||
57 | void __init efi_fake_memmap(void) | 57 | void __init efi_fake_memmap(void) |
58 | { | 58 | { |
59 | u64 start, end, m_start, m_end, m_attr; | 59 | u64 start, end, m_start, m_end, m_attr; |
60 | int new_nr_map = memmap.nr_map; | 60 | int new_nr_map = efi.memmap.nr_map; |
61 | efi_memory_desc_t *md; | 61 | efi_memory_desc_t *md; |
62 | phys_addr_t new_memmap_phy; | 62 | phys_addr_t new_memmap_phy; |
63 | void *new_memmap; | 63 | void *new_memmap; |
@@ -68,8 +68,7 @@ void __init efi_fake_memmap(void) | |||
68 | return; | 68 | return; |
69 | 69 | ||
70 | /* count up the number of EFI memory descriptor */ | 70 | /* count up the number of EFI memory descriptor */ |
71 | for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) { | 71 | for_each_efi_memory_desc(md) { |
72 | md = old; | ||
73 | start = md->phys_addr; | 72 | start = md->phys_addr; |
74 | end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1; | 73 | end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1; |
75 | 74 | ||
@@ -95,25 +94,25 @@ void __init efi_fake_memmap(void) | |||
95 | } | 94 | } |
96 | 95 | ||
97 | /* allocate memory for new EFI memmap */ | 96 | /* allocate memory for new EFI memmap */ |
98 | new_memmap_phy = memblock_alloc(memmap.desc_size * new_nr_map, | 97 | new_memmap_phy = memblock_alloc(efi.memmap.desc_size * new_nr_map, |
99 | PAGE_SIZE); | 98 | PAGE_SIZE); |
100 | if (!new_memmap_phy) | 99 | if (!new_memmap_phy) |
101 | return; | 100 | return; |
102 | 101 | ||
103 | /* create new EFI memmap */ | 102 | /* create new EFI memmap */ |
104 | new_memmap = early_memremap(new_memmap_phy, | 103 | new_memmap = early_memremap(new_memmap_phy, |
105 | memmap.desc_size * new_nr_map); | 104 | efi.memmap.desc_size * new_nr_map); |
106 | if (!new_memmap) { | 105 | if (!new_memmap) { |
107 | memblock_free(new_memmap_phy, memmap.desc_size * new_nr_map); | 106 | memblock_free(new_memmap_phy, efi.memmap.desc_size * new_nr_map); |
108 | return; | 107 | return; |
109 | } | 108 | } |
110 | 109 | ||
111 | for (old = memmap.map, new = new_memmap; | 110 | for (old = efi.memmap.map, new = new_memmap; |
112 | old < memmap.map_end; | 111 | old < efi.memmap.map_end; |
113 | old += memmap.desc_size, new += memmap.desc_size) { | 112 | old += efi.memmap.desc_size, new += efi.memmap.desc_size) { |
114 | 113 | ||
115 | /* copy original EFI memory descriptor */ | 114 | /* copy original EFI memory descriptor */ |
116 | memcpy(new, old, memmap.desc_size); | 115 | memcpy(new, old, efi.memmap.desc_size); |
117 | md = new; | 116 | md = new; |
118 | start = md->phys_addr; | 117 | start = md->phys_addr; |
119 | end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; | 118 | end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; |
@@ -134,8 +133,8 @@ void __init efi_fake_memmap(void) | |||
134 | md->num_pages = (m_end - md->phys_addr + 1) >> | 133 | md->num_pages = (m_end - md->phys_addr + 1) >> |
135 | EFI_PAGE_SHIFT; | 134 | EFI_PAGE_SHIFT; |
136 | /* latter part */ | 135 | /* latter part */ |
137 | new += memmap.desc_size; | 136 | new += efi.memmap.desc_size; |
138 | memcpy(new, old, memmap.desc_size); | 137 | memcpy(new, old, efi.memmap.desc_size); |
139 | md = new; | 138 | md = new; |
140 | md->phys_addr = m_end + 1; | 139 | md->phys_addr = m_end + 1; |
141 | md->num_pages = (end - md->phys_addr + 1) >> | 140 | md->num_pages = (end - md->phys_addr + 1) >> |
@@ -147,16 +146,16 @@ void __init efi_fake_memmap(void) | |||
147 | md->num_pages = (m_start - md->phys_addr) >> | 146 | md->num_pages = (m_start - md->phys_addr) >> |
148 | EFI_PAGE_SHIFT; | 147 | EFI_PAGE_SHIFT; |
149 | /* middle part */ | 148 | /* middle part */ |
150 | new += memmap.desc_size; | 149 | new += efi.memmap.desc_size; |
151 | memcpy(new, old, memmap.desc_size); | 150 | memcpy(new, old, efi.memmap.desc_size); |
152 | md = new; | 151 | md = new; |
153 | md->attribute |= m_attr; | 152 | md->attribute |= m_attr; |
154 | md->phys_addr = m_start; | 153 | md->phys_addr = m_start; |
155 | md->num_pages = (m_end - m_start + 1) >> | 154 | md->num_pages = (m_end - m_start + 1) >> |
156 | EFI_PAGE_SHIFT; | 155 | EFI_PAGE_SHIFT; |
157 | /* last part */ | 156 | /* last part */ |
158 | new += memmap.desc_size; | 157 | new += efi.memmap.desc_size; |
159 | memcpy(new, old, memmap.desc_size); | 158 | memcpy(new, old, efi.memmap.desc_size); |
160 | md = new; | 159 | md = new; |
161 | md->phys_addr = m_end + 1; | 160 | md->phys_addr = m_end + 1; |
162 | md->num_pages = (end - m_end) >> | 161 | md->num_pages = (end - m_end) >> |
@@ -169,8 +168,8 @@ void __init efi_fake_memmap(void) | |||
169 | md->num_pages = (m_start - md->phys_addr) >> | 168 | md->num_pages = (m_start - md->phys_addr) >> |
170 | EFI_PAGE_SHIFT; | 169 | EFI_PAGE_SHIFT; |
171 | /* latter part */ | 170 | /* latter part */ |
172 | new += memmap.desc_size; | 171 | new += efi.memmap.desc_size; |
173 | memcpy(new, old, memmap.desc_size); | 172 | memcpy(new, old, efi.memmap.desc_size); |
174 | md = new; | 173 | md = new; |
175 | md->phys_addr = m_start; | 174 | md->phys_addr = m_start; |
176 | md->num_pages = (end - md->phys_addr + 1) >> | 175 | md->num_pages = (end - md->phys_addr + 1) >> |
@@ -182,10 +181,10 @@ void __init efi_fake_memmap(void) | |||
182 | 181 | ||
183 | /* swap into new EFI memmap */ | 182 | /* swap into new EFI memmap */ |
184 | efi_unmap_memmap(); | 183 | efi_unmap_memmap(); |
185 | memmap.map = new_memmap; | 184 | efi.memmap.map = new_memmap; |
186 | memmap.phys_map = new_memmap_phy; | 185 | efi.memmap.phys_map = new_memmap_phy; |
187 | memmap.nr_map = new_nr_map; | 186 | efi.memmap.nr_map = new_nr_map; |
188 | memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size; | 187 | efi.memmap.map_end = efi.memmap.map + efi.memmap.nr_map * efi.memmap.desc_size; |
189 | set_bit(EFI_MEMMAP, &efi.flags); | 188 | set_bit(EFI_MEMMAP, &efi.flags); |
190 | 189 | ||
191 | /* print new EFI memmap */ | 190 | /* print new EFI memmap */ |
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index da99bbb74aeb..c06945160a41 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile | |||
@@ -28,7 +28,7 @@ OBJECT_FILES_NON_STANDARD := y | |||
28 | # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. | 28 | # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. |
29 | KCOV_INSTRUMENT := n | 29 | KCOV_INSTRUMENT := n |
30 | 30 | ||
31 | lib-y := efi-stub-helper.o | 31 | lib-y := efi-stub-helper.o gop.o |
32 | 32 | ||
33 | # include the stub's generic dependencies from lib/ when building for ARM/arm64 | 33 | # include the stub's generic dependencies from lib/ when building for ARM/arm64 |
34 | arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c | 34 | arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c |
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 414deb85c2e5..993aa56755f6 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c | |||
@@ -20,27 +20,49 @@ | |||
20 | 20 | ||
21 | bool __nokaslr; | 21 | bool __nokaslr; |
22 | 22 | ||
23 | static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) | 23 | static int efi_get_secureboot(efi_system_table_t *sys_table_arg) |
24 | { | 24 | { |
25 | static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; | 25 | static efi_char16_t const sb_var_name[] = { |
26 | static efi_char16_t const var_name[] = { | ||
27 | 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; | 26 | 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; |
27 | static efi_char16_t const sm_var_name[] = { | ||
28 | 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; | ||
28 | 29 | ||
30 | efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; | ||
29 | efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; | 31 | efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; |
30 | unsigned long size = sizeof(u8); | ||
31 | efi_status_t status; | ||
32 | u8 val; | 32 | u8 val; |
33 | unsigned long size = sizeof(val); | ||
34 | efi_status_t status; | ||
33 | 35 | ||
34 | status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)&var_guid, | 36 | status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)&var_guid, |
35 | NULL, &size, &val); | 37 | NULL, &size, &val); |
36 | 38 | ||
39 | if (status != EFI_SUCCESS) | ||
40 | goto out_efi_err; | ||
41 | |||
42 | if (val == 0) | ||
43 | return 0; | ||
44 | |||
45 | status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)&var_guid, | ||
46 | NULL, &size, &val); | ||
47 | |||
48 | if (status != EFI_SUCCESS) | ||
49 | goto out_efi_err; | ||
50 | |||
51 | if (val == 1) | ||
52 | return 0; | ||
53 | |||
54 | return 1; | ||
55 | |||
56 | out_efi_err: | ||
37 | switch (status) { | 57 | switch (status) { |
38 | case EFI_SUCCESS: | ||
39 | return val; | ||
40 | case EFI_NOT_FOUND: | 58 | case EFI_NOT_FOUND: |
41 | return 0; | 59 | return 0; |
60 | case EFI_DEVICE_ERROR: | ||
61 | return -EIO; | ||
62 | case EFI_SECURITY_VIOLATION: | ||
63 | return -EACCES; | ||
42 | default: | 64 | default: |
43 | return 1; | 65 | return -EINVAL; |
44 | } | 66 | } |
45 | } | 67 | } |
46 | 68 | ||
@@ -147,6 +169,25 @@ void efi_char16_printk(efi_system_table_t *sys_table_arg, | |||
147 | out->output_string(out, str); | 169 | out->output_string(out, str); |
148 | } | 170 | } |
149 | 171 | ||
172 | static struct screen_info *setup_graphics(efi_system_table_t *sys_table_arg) | ||
173 | { | ||
174 | efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; | ||
175 | efi_status_t status; | ||
176 | unsigned long size; | ||
177 | void **gop_handle = NULL; | ||
178 | struct screen_info *si = NULL; | ||
179 | |||
180 | size = 0; | ||
181 | status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, | ||
182 | &gop_proto, NULL, &size, gop_handle); | ||
183 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
184 | si = alloc_screen_info(sys_table_arg); | ||
185 | if (!si) | ||
186 | return NULL; | ||
187 | efi_setup_gop(sys_table_arg, si, &gop_proto, size); | ||
188 | } | ||
189 | return si; | ||
190 | } | ||
150 | 191 | ||
151 | /* | 192 | /* |
152 | * This function handles the architcture specific differences between arm and | 193 | * This function handles the architcture specific differences between arm and |
@@ -185,6 +226,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, | |||
185 | efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; | 226 | efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; |
186 | unsigned long reserve_addr = 0; | 227 | unsigned long reserve_addr = 0; |
187 | unsigned long reserve_size = 0; | 228 | unsigned long reserve_size = 0; |
229 | int secure_boot = 0; | ||
230 | struct screen_info *si; | ||
188 | 231 | ||
189 | /* Check if we were booted by the EFI firmware */ | 232 | /* Check if we were booted by the EFI firmware */ |
190 | if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | 233 | if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) |
@@ -237,6 +280,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, | |||
237 | __nokaslr = true; | 280 | __nokaslr = true; |
238 | } | 281 | } |
239 | 282 | ||
283 | si = setup_graphics(sys_table); | ||
284 | |||
240 | status = handle_kernel_image(sys_table, image_addr, &image_size, | 285 | status = handle_kernel_image(sys_table, image_addr, &image_size, |
241 | &reserve_addr, | 286 | &reserve_addr, |
242 | &reserve_size, | 287 | &reserve_size, |
@@ -250,12 +295,21 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, | |||
250 | if (status != EFI_SUCCESS) | 295 | if (status != EFI_SUCCESS) |
251 | pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); | 296 | pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); |
252 | 297 | ||
298 | secure_boot = efi_get_secureboot(sys_table); | ||
299 | if (secure_boot > 0) | ||
300 | pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); | ||
301 | |||
302 | if (secure_boot < 0) { | ||
303 | pr_efi_err(sys_table, | ||
304 | "could not determine UEFI Secure Boot status.\n"); | ||
305 | } | ||
306 | |||
253 | /* | 307 | /* |
254 | * Unauthenticated device tree data is a security hazard, so | 308 | * Unauthenticated device tree data is a security hazard, so |
255 | * ignore 'dtb=' unless UEFI Secure Boot is disabled. | 309 | * ignore 'dtb=' unless UEFI Secure Boot is disabled. |
256 | */ | 310 | */ |
257 | if (efi_secureboot_enabled(sys_table)) { | 311 | if (secure_boot != 0 && strstr(cmdline_ptr, "dtb=")) { |
258 | pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); | 312 | pr_efi(sys_table, "Ignoring DTB from command line.\n"); |
259 | } else { | 313 | } else { |
260 | status = handle_cmdline_files(sys_table, image, cmdline_ptr, | 314 | status = handle_cmdline_files(sys_table, image, cmdline_ptr, |
261 | "dtb=", | 315 | "dtb=", |
@@ -309,6 +363,7 @@ fail_free_image: | |||
309 | efi_free(sys_table, image_size, *image_addr); | 363 | efi_free(sys_table, image_size, *image_addr); |
310 | efi_free(sys_table, reserve_size, reserve_addr); | 364 | efi_free(sys_table, reserve_size, reserve_addr); |
311 | fail_free_cmdline: | 365 | fail_free_cmdline: |
366 | free_screen_info(sys_table, si); | ||
312 | efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr); | 367 | efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr); |
313 | fail: | 368 | fail: |
314 | return EFI_ERROR; | 369 | return EFI_ERROR; |
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c index 6f42be4d0084..e1f0b28e1dcb 100644 --- a/drivers/firmware/efi/libstub/arm32-stub.c +++ b/drivers/firmware/efi/libstub/arm32-stub.c | |||
@@ -26,6 +26,43 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg) | |||
26 | return EFI_SUCCESS; | 26 | return EFI_SUCCESS; |
27 | } | 27 | } |
28 | 28 | ||
29 | static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID; | ||
30 | |||
31 | struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg) | ||
32 | { | ||
33 | struct screen_info *si; | ||
34 | efi_status_t status; | ||
35 | |||
36 | /* | ||
37 | * Unlike on arm64, where we can directly fill out the screen_info | ||
38 | * structure from the stub, we need to allocate a buffer to hold | ||
39 | * its contents while we hand over to the kernel proper from the | ||
40 | * decompressor. | ||
41 | */ | ||
42 | status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA, | ||
43 | sizeof(*si), (void **)&si); | ||
44 | |||
45 | if (status != EFI_SUCCESS) | ||
46 | return NULL; | ||
47 | |||
48 | status = efi_call_early(install_configuration_table, | ||
49 | &screen_info_guid, si); | ||
50 | if (status == EFI_SUCCESS) | ||
51 | return si; | ||
52 | |||
53 | efi_call_early(free_pool, si); | ||
54 | return NULL; | ||
55 | } | ||
56 | |||
57 | void free_screen_info(efi_system_table_t *sys_table_arg, struct screen_info *si) | ||
58 | { | ||
59 | if (!si) | ||
60 | return; | ||
61 | |||
62 | efi_call_early(install_configuration_table, &screen_info_guid, NULL); | ||
63 | efi_call_early(free_pool, si); | ||
64 | } | ||
65 | |||
29 | efi_status_t handle_kernel_image(efi_system_table_t *sys_table, | 66 | efi_status_t handle_kernel_image(efi_system_table_t *sys_table, |
30 | unsigned long *image_addr, | 67 | unsigned long *image_addr, |
31 | unsigned long *image_size, | 68 | unsigned long *image_size, |
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 29ed2f9b218c..3bd127f95315 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c | |||
@@ -125,10 +125,12 @@ unsigned long get_dram_base(efi_system_table_t *sys_table_arg) | |||
125 | 125 | ||
126 | map.map_end = map.map + map_size; | 126 | map.map_end = map.map + map_size; |
127 | 127 | ||
128 | for_each_efi_memory_desc(&map, md) | 128 | for_each_efi_memory_desc_in_map(&map, md) { |
129 | if (md->attribute & EFI_MEMORY_WB) | 129 | if (md->attribute & EFI_MEMORY_WB) { |
130 | if (membase > md->phys_addr) | 130 | if (membase > md->phys_addr) |
131 | membase = md->phys_addr; | 131 | membase = md->phys_addr; |
132 | } | ||
133 | } | ||
132 | 134 | ||
133 | efi_call_early(free_pool, map.map); | 135 | efi_call_early(free_pool, map.map); |
134 | 136 | ||
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c new file mode 100644 index 000000000000..932742e4cf23 --- /dev/null +++ b/drivers/firmware/efi/libstub/gop.c | |||
@@ -0,0 +1,354 @@ | |||
1 | /* ----------------------------------------------------------------------- | ||
2 | * | ||
3 | * Copyright 2011 Intel Corporation; author Matt Fleming | ||
4 | * | ||
5 | * This file is part of the Linux kernel, and is made available under | ||
6 | * the terms of the GNU General Public License version 2. | ||
7 | * | ||
8 | * ----------------------------------------------------------------------- */ | ||
9 | |||
10 | #include <linux/efi.h> | ||
11 | #include <linux/screen_info.h> | ||
12 | #include <asm/efi.h> | ||
13 | #include <asm/setup.h> | ||
14 | |||
15 | static void find_bits(unsigned long mask, u8 *pos, u8 *size) | ||
16 | { | ||
17 | u8 first, len; | ||
18 | |||
19 | first = 0; | ||
20 | len = 0; | ||
21 | |||
22 | if (mask) { | ||
23 | while (!(mask & 0x1)) { | ||
24 | mask = mask >> 1; | ||
25 | first++; | ||
26 | } | ||
27 | |||
28 | while (mask & 0x1) { | ||
29 | mask = mask >> 1; | ||
30 | len++; | ||
31 | } | ||
32 | } | ||
33 | |||
34 | *pos = first; | ||
35 | *size = len; | ||
36 | } | ||
37 | |||
38 | static void | ||
39 | setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line, | ||
40 | struct efi_pixel_bitmask pixel_info, int pixel_format) | ||
41 | { | ||
42 | if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { | ||
43 | si->lfb_depth = 32; | ||
44 | si->lfb_linelength = pixels_per_scan_line * 4; | ||
45 | si->red_size = 8; | ||
46 | si->red_pos = 0; | ||
47 | si->green_size = 8; | ||
48 | si->green_pos = 8; | ||
49 | si->blue_size = 8; | ||
50 | si->blue_pos = 16; | ||
51 | si->rsvd_size = 8; | ||
52 | si->rsvd_pos = 24; | ||
53 | } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) { | ||
54 | si->lfb_depth = 32; | ||
55 | si->lfb_linelength = pixels_per_scan_line * 4; | ||
56 | si->red_size = 8; | ||
57 | si->red_pos = 16; | ||
58 | si->green_size = 8; | ||
59 | si->green_pos = 8; | ||
60 | si->blue_size = 8; | ||
61 | si->blue_pos = 0; | ||
62 | si->rsvd_size = 8; | ||
63 | si->rsvd_pos = 24; | ||
64 | } else if (pixel_format == PIXEL_BIT_MASK) { | ||
65 | find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size); | ||
66 | find_bits(pixel_info.green_mask, &si->green_pos, | ||
67 | &si->green_size); | ||
68 | find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size); | ||
69 | find_bits(pixel_info.reserved_mask, &si->rsvd_pos, | ||
70 | &si->rsvd_size); | ||
71 | si->lfb_depth = si->red_size + si->green_size + | ||
72 | si->blue_size + si->rsvd_size; | ||
73 | si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; | ||
74 | } else { | ||
75 | si->lfb_depth = 4; | ||
76 | si->lfb_linelength = si->lfb_width / 2; | ||
77 | si->red_size = 0; | ||
78 | si->red_pos = 0; | ||
79 | si->green_size = 0; | ||
80 | si->green_pos = 0; | ||
81 | si->blue_size = 0; | ||
82 | si->blue_pos = 0; | ||
83 | si->rsvd_size = 0; | ||
84 | si->rsvd_pos = 0; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static efi_status_t | ||
89 | __gop_query32(efi_system_table_t *sys_table_arg, | ||
90 | struct efi_graphics_output_protocol_32 *gop32, | ||
91 | struct efi_graphics_output_mode_info **info, | ||
92 | unsigned long *size, u64 *fb_base) | ||
93 | { | ||
94 | struct efi_graphics_output_protocol_mode_32 *mode; | ||
95 | efi_graphics_output_protocol_query_mode query_mode; | ||
96 | efi_status_t status; | ||
97 | unsigned long m; | ||
98 | |||
99 | m = gop32->mode; | ||
100 | mode = (struct efi_graphics_output_protocol_mode_32 *)m; | ||
101 | query_mode = (void *)(unsigned long)gop32->query_mode; | ||
102 | |||
103 | status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size, | ||
104 | info); | ||
105 | if (status != EFI_SUCCESS) | ||
106 | return status; | ||
107 | |||
108 | *fb_base = mode->frame_buffer_base; | ||
109 | return status; | ||
110 | } | ||
111 | |||
112 | static efi_status_t | ||
113 | setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, | ||
114 | efi_guid_t *proto, unsigned long size, void **gop_handle) | ||
115 | { | ||
116 | struct efi_graphics_output_protocol_32 *gop32, *first_gop; | ||
117 | unsigned long nr_gops; | ||
118 | u16 width, height; | ||
119 | u32 pixels_per_scan_line; | ||
120 | u32 ext_lfb_base; | ||
121 | u64 fb_base; | ||
122 | struct efi_pixel_bitmask pixel_info; | ||
123 | int pixel_format; | ||
124 | efi_status_t status = EFI_NOT_FOUND; | ||
125 | u32 *handles = (u32 *)(unsigned long)gop_handle; | ||
126 | int i; | ||
127 | |||
128 | first_gop = NULL; | ||
129 | gop32 = NULL; | ||
130 | |||
131 | nr_gops = size / sizeof(u32); | ||
132 | for (i = 0; i < nr_gops; i++) { | ||
133 | struct efi_graphics_output_mode_info *info = NULL; | ||
134 | efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; | ||
135 | bool conout_found = false; | ||
136 | void *dummy = NULL; | ||
137 | efi_handle_t h = (efi_handle_t)(unsigned long)handles[i]; | ||
138 | u64 current_fb_base; | ||
139 | |||
140 | status = efi_call_early(handle_protocol, h, | ||
141 | proto, (void **)&gop32); | ||
142 | if (status != EFI_SUCCESS) | ||
143 | continue; | ||
144 | |||
145 | status = efi_call_early(handle_protocol, h, | ||
146 | &conout_proto, &dummy); | ||
147 | if (status == EFI_SUCCESS) | ||
148 | conout_found = true; | ||
149 | |||
150 | status = __gop_query32(sys_table_arg, gop32, &info, &size, | ||
151 | ¤t_fb_base); | ||
152 | if (status == EFI_SUCCESS && (!first_gop || conout_found)) { | ||
153 | /* | ||
154 | * Systems that use the UEFI Console Splitter may | ||
155 | * provide multiple GOP devices, not all of which are | ||
156 | * backed by real hardware. The workaround is to search | ||
157 | * for a GOP implementing the ConOut protocol, and if | ||
158 | * one isn't found, to just fall back to the first GOP. | ||
159 | */ | ||
160 | width = info->horizontal_resolution; | ||
161 | height = info->vertical_resolution; | ||
162 | pixel_format = info->pixel_format; | ||
163 | pixel_info = info->pixel_information; | ||
164 | pixels_per_scan_line = info->pixels_per_scan_line; | ||
165 | fb_base = current_fb_base; | ||
166 | |||
167 | /* | ||
168 | * Once we've found a GOP supporting ConOut, | ||
169 | * don't bother looking any further. | ||
170 | */ | ||
171 | first_gop = gop32; | ||
172 | if (conout_found) | ||
173 | break; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | /* Did we find any GOPs? */ | ||
178 | if (!first_gop) | ||
179 | goto out; | ||
180 | |||
181 | /* EFI framebuffer */ | ||
182 | si->orig_video_isVGA = VIDEO_TYPE_EFI; | ||
183 | |||
184 | si->lfb_width = width; | ||
185 | si->lfb_height = height; | ||
186 | si->lfb_base = fb_base; | ||
187 | |||
188 | ext_lfb_base = (u64)(unsigned long)fb_base >> 32; | ||
189 | if (ext_lfb_base) { | ||
190 | si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; | ||
191 | si->ext_lfb_base = ext_lfb_base; | ||
192 | } | ||
193 | |||
194 | si->pages = 1; | ||
195 | |||
196 | setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); | ||
197 | |||
198 | si->lfb_size = si->lfb_linelength * si->lfb_height; | ||
199 | |||
200 | si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; | ||
201 | out: | ||
202 | return status; | ||
203 | } | ||
204 | |||
205 | static efi_status_t | ||
206 | __gop_query64(efi_system_table_t *sys_table_arg, | ||
207 | struct efi_graphics_output_protocol_64 *gop64, | ||
208 | struct efi_graphics_output_mode_info **info, | ||
209 | unsigned long *size, u64 *fb_base) | ||
210 | { | ||
211 | struct efi_graphics_output_protocol_mode_64 *mode; | ||
212 | efi_graphics_output_protocol_query_mode query_mode; | ||
213 | efi_status_t status; | ||
214 | unsigned long m; | ||
215 | |||
216 | m = gop64->mode; | ||
217 | mode = (struct efi_graphics_output_protocol_mode_64 *)m; | ||
218 | query_mode = (void *)(unsigned long)gop64->query_mode; | ||
219 | |||
220 | status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size, | ||
221 | info); | ||
222 | if (status != EFI_SUCCESS) | ||
223 | return status; | ||
224 | |||
225 | *fb_base = mode->frame_buffer_base; | ||
226 | return status; | ||
227 | } | ||
228 | |||
229 | static efi_status_t | ||
230 | setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, | ||
231 | efi_guid_t *proto, unsigned long size, void **gop_handle) | ||
232 | { | ||
233 | struct efi_graphics_output_protocol_64 *gop64, *first_gop; | ||
234 | unsigned long nr_gops; | ||
235 | u16 width, height; | ||
236 | u32 pixels_per_scan_line; | ||
237 | u32 ext_lfb_base; | ||
238 | u64 fb_base; | ||
239 | struct efi_pixel_bitmask pixel_info; | ||
240 | int pixel_format; | ||
241 | efi_status_t status = EFI_NOT_FOUND; | ||
242 | u64 *handles = (u64 *)(unsigned long)gop_handle; | ||
243 | int i; | ||
244 | |||
245 | first_gop = NULL; | ||
246 | gop64 = NULL; | ||
247 | |||
248 | nr_gops = size / sizeof(u64); | ||
249 | for (i = 0; i < nr_gops; i++) { | ||
250 | struct efi_graphics_output_mode_info *info = NULL; | ||
251 | efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; | ||
252 | bool conout_found = false; | ||
253 | void *dummy = NULL; | ||
254 | efi_handle_t h = (efi_handle_t)(unsigned long)handles[i]; | ||
255 | u64 current_fb_base; | ||
256 | |||
257 | status = efi_call_early(handle_protocol, h, | ||
258 | proto, (void **)&gop64); | ||
259 | if (status != EFI_SUCCESS) | ||
260 | continue; | ||
261 | |||
262 | status = efi_call_early(handle_protocol, h, | ||
263 | &conout_proto, &dummy); | ||
264 | if (status == EFI_SUCCESS) | ||
265 | conout_found = true; | ||
266 | |||
267 | status = __gop_query64(sys_table_arg, gop64, &info, &size, | ||
268 | ¤t_fb_base); | ||
269 | if (status == EFI_SUCCESS && (!first_gop || conout_found)) { | ||
270 | /* | ||
271 | * Systems that use the UEFI Console Splitter may | ||
272 | * provide multiple GOP devices, not all of which are | ||
273 | * backed by real hardware. The workaround is to search | ||
274 | * for a GOP implementing the ConOut protocol, and if | ||
275 | * one isn't found, to just fall back to the first GOP. | ||
276 | */ | ||
277 | width = info->horizontal_resolution; | ||
278 | height = info->vertical_resolution; | ||
279 | pixel_format = info->pixel_format; | ||
280 | pixel_info = info->pixel_information; | ||
281 | pixels_per_scan_line = info->pixels_per_scan_line; | ||
282 | fb_base = current_fb_base; | ||
283 | |||
284 | /* | ||
285 | * Once we've found a GOP supporting ConOut, | ||
286 | * don't bother looking any further. | ||
287 | */ | ||
288 | first_gop = gop64; | ||
289 | if (conout_found) | ||
290 | break; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | /* Did we find any GOPs? */ | ||
295 | if (!first_gop) | ||
296 | goto out; | ||
297 | |||
298 | /* EFI framebuffer */ | ||
299 | si->orig_video_isVGA = VIDEO_TYPE_EFI; | ||
300 | |||
301 | si->lfb_width = width; | ||
302 | si->lfb_height = height; | ||
303 | si->lfb_base = fb_base; | ||
304 | |||
305 | ext_lfb_base = (u64)(unsigned long)fb_base >> 32; | ||
306 | if (ext_lfb_base) { | ||
307 | si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; | ||
308 | si->ext_lfb_base = ext_lfb_base; | ||
309 | } | ||
310 | |||
311 | si->pages = 1; | ||
312 | |||
313 | setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); | ||
314 | |||
315 | si->lfb_size = si->lfb_linelength * si->lfb_height; | ||
316 | |||
317 | si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; | ||
318 | out: | ||
319 | return status; | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * See if we have Graphics Output Protocol | ||
324 | */ | ||
325 | efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg, | ||
326 | struct screen_info *si, efi_guid_t *proto, | ||
327 | unsigned long size) | ||
328 | { | ||
329 | efi_status_t status; | ||
330 | void **gop_handle = NULL; | ||
331 | |||
332 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | ||
333 | size, (void **)&gop_handle); | ||
334 | if (status != EFI_SUCCESS) | ||
335 | return status; | ||
336 | |||
337 | status = efi_call_early(locate_handle, | ||
338 | EFI_LOCATE_BY_PROTOCOL, | ||
339 | proto, NULL, &size, gop_handle); | ||
340 | if (status != EFI_SUCCESS) | ||
341 | goto free_handle; | ||
342 | |||
343 | if (efi_is_64bit()) { | ||
344 | status = setup_gop64(sys_table_arg, si, proto, size, | ||
345 | gop_handle); | ||
346 | } else { | ||
347 | status = setup_gop32(sys_table_arg, si, proto, size, | ||
348 | gop_handle); | ||
349 | } | ||
350 | |||
351 | free_handle: | ||
352 | efi_call_early(free_pool, gop_handle); | ||
353 | return status; | ||
354 | } | ||
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c new file mode 100644 index 000000000000..236004b9a50d --- /dev/null +++ b/drivers/firmware/efi/memattr.c | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #define pr_fmt(fmt) "efi: memattr: " fmt | ||
10 | |||
11 | #include <linux/efi.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/memblock.h> | ||
15 | |||
16 | #include <asm/early_ioremap.h> | ||
17 | |||
18 | static int __initdata tbl_size; | ||
19 | |||
20 | /* | ||
21 | * Reserve the memory associated with the Memory Attributes configuration | ||
22 | * table, if it exists. | ||
23 | */ | ||
24 | int __init efi_memattr_init(void) | ||
25 | { | ||
26 | efi_memory_attributes_table_t *tbl; | ||
27 | |||
28 | if (efi.mem_attr_table == EFI_INVALID_TABLE_ADDR) | ||
29 | return 0; | ||
30 | |||
31 | tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl)); | ||
32 | if (!tbl) { | ||
33 | pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n", | ||
34 | efi.mem_attr_table); | ||
35 | return -ENOMEM; | ||
36 | } | ||
37 | |||
38 | if (tbl->version > 1) { | ||
39 | pr_warn("Unexpected EFI Memory Attributes table version %d\n", | ||
40 | tbl->version); | ||
41 | goto unmap; | ||
42 | } | ||
43 | |||
44 | tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size; | ||
45 | memblock_reserve(efi.mem_attr_table, tbl_size); | ||
46 | |||
47 | unmap: | ||
48 | early_memunmap(tbl, sizeof(*tbl)); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Returns a copy @out of the UEFI memory descriptor @in if it is covered | ||
54 | * entirely by a UEFI memory map entry with matching attributes. The virtual | ||
55 | * address of @out is set according to the matching entry that was found. | ||
56 | */ | ||
57 | static bool entry_is_valid(const efi_memory_desc_t *in, efi_memory_desc_t *out) | ||
58 | { | ||
59 | u64 in_paddr = in->phys_addr; | ||
60 | u64 in_size = in->num_pages << EFI_PAGE_SHIFT; | ||
61 | efi_memory_desc_t *md; | ||
62 | |||
63 | *out = *in; | ||
64 | |||
65 | if (in->type != EFI_RUNTIME_SERVICES_CODE && | ||
66 | in->type != EFI_RUNTIME_SERVICES_DATA) { | ||
67 | pr_warn("Entry type should be RuntimeServiceCode/Data\n"); | ||
68 | return false; | ||
69 | } | ||
70 | |||
71 | if (!(in->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))) { | ||
72 | pr_warn("Entry attributes invalid: RO and XP bits both cleared\n"); | ||
73 | return false; | ||
74 | } | ||
75 | |||
76 | if (PAGE_SIZE > EFI_PAGE_SIZE && | ||
77 | (!PAGE_ALIGNED(in->phys_addr) || | ||
78 | !PAGE_ALIGNED(in->num_pages << EFI_PAGE_SHIFT))) { | ||
79 | /* | ||
80 | * Since arm64 may execute with page sizes of up to 64 KB, the | ||
81 | * UEFI spec mandates that RuntimeServices memory regions must | ||
82 | * be 64 KB aligned. We need to validate this here since we will | ||
83 | * not be able to tighten permissions on such regions without | ||
84 | * affecting adjacent regions. | ||
85 | */ | ||
86 | pr_warn("Entry address region misaligned\n"); | ||
87 | return false; | ||
88 | } | ||
89 | |||
90 | for_each_efi_memory_desc(md) { | ||
91 | u64 md_paddr = md->phys_addr; | ||
92 | u64 md_size = md->num_pages << EFI_PAGE_SHIFT; | ||
93 | |||
94 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) | ||
95 | continue; | ||
96 | if (md->virt_addr == 0) { | ||
97 | /* no virtual mapping has been installed by the stub */ | ||
98 | break; | ||
99 | } | ||
100 | |||
101 | if (md_paddr > in_paddr || (in_paddr - md_paddr) >= md_size) | ||
102 | continue; | ||
103 | |||
104 | /* | ||
105 | * This entry covers the start of @in, check whether | ||
106 | * it covers the end as well. | ||
107 | */ | ||
108 | if (md_paddr + md_size < in_paddr + in_size) { | ||
109 | pr_warn("Entry covers multiple EFI memory map regions\n"); | ||
110 | return false; | ||
111 | } | ||
112 | |||
113 | if (md->type != in->type) { | ||
114 | pr_warn("Entry type deviates from EFI memory map region type\n"); | ||
115 | return false; | ||
116 | } | ||
117 | |||
118 | out->virt_addr = in_paddr + (md->virt_addr - md_paddr); | ||
119 | |||
120 | return true; | ||
121 | } | ||
122 | |||
123 | pr_warn("No matching entry found in the EFI memory map\n"); | ||
124 | return false; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * To be called after the EFI page tables have been populated. If a memory | ||
129 | * attributes table is available, its contents will be used to update the | ||
130 | * mappings with tightened permissions as described by the table. | ||
131 | * This requires the UEFI memory map to have already been populated with | ||
132 | * virtual addresses. | ||
133 | */ | ||
134 | int __init efi_memattr_apply_permissions(struct mm_struct *mm, | ||
135 | efi_memattr_perm_setter fn) | ||
136 | { | ||
137 | efi_memory_attributes_table_t *tbl; | ||
138 | int i, ret; | ||
139 | |||
140 | if (tbl_size <= sizeof(*tbl)) | ||
141 | return 0; | ||
142 | |||
143 | /* | ||
144 | * We need the EFI memory map to be setup so we can use it to | ||
145 | * lookup the virtual addresses of all entries in the of EFI | ||
146 | * Memory Attributes table. If it isn't available, this | ||
147 | * function should not be called. | ||
148 | */ | ||
149 | if (WARN_ON(!efi_enabled(EFI_MEMMAP))) | ||
150 | return 0; | ||
151 | |||
152 | tbl = memremap(efi.mem_attr_table, tbl_size, MEMREMAP_WB); | ||
153 | if (!tbl) { | ||
154 | pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n", | ||
155 | efi.mem_attr_table); | ||
156 | return -ENOMEM; | ||
157 | } | ||
158 | |||
159 | if (efi_enabled(EFI_DBG)) | ||
160 | pr_info("Processing EFI Memory Attributes table:\n"); | ||
161 | |||
162 | for (i = ret = 0; ret == 0 && i < tbl->num_entries; i++) { | ||
163 | efi_memory_desc_t md; | ||
164 | unsigned long size; | ||
165 | bool valid; | ||
166 | char buf[64]; | ||
167 | |||
168 | valid = entry_is_valid((void *)tbl->entry + i * tbl->desc_size, | ||
169 | &md); | ||
170 | size = md.num_pages << EFI_PAGE_SHIFT; | ||
171 | if (efi_enabled(EFI_DBG) || !valid) | ||
172 | pr_info("%s 0x%012llx-0x%012llx %s\n", | ||
173 | valid ? "" : "!", md.phys_addr, | ||
174 | md.phys_addr + size - 1, | ||
175 | efi_md_typeattr_format(buf, sizeof(buf), &md)); | ||
176 | |||
177 | if (valid) | ||
178 | ret = fn(mm, &md); | ||
179 | } | ||
180 | memunmap(tbl); | ||
181 | return ret; | ||
182 | } | ||
diff --git a/drivers/firmware/efi/reboot.c b/drivers/firmware/efi/reboot.c index 9c59d1c795d1..62ead9b9d871 100644 --- a/drivers/firmware/efi/reboot.c +++ b/drivers/firmware/efi/reboot.c | |||
@@ -9,7 +9,8 @@ int efi_reboot_quirk_mode = -1; | |||
9 | 9 | ||
10 | void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) | 10 | void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) |
11 | { | 11 | { |
12 | int efi_mode; | 12 | const char *str[] = { "cold", "warm", "shutdown", "platform" }; |
13 | int efi_mode, cap_reset_mode; | ||
13 | 14 | ||
14 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) | 15 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) |
15 | return; | 16 | return; |
@@ -30,6 +31,15 @@ void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) | |||
30 | if (efi_reboot_quirk_mode != -1) | 31 | if (efi_reboot_quirk_mode != -1) |
31 | efi_mode = efi_reboot_quirk_mode; | 32 | efi_mode = efi_reboot_quirk_mode; |
32 | 33 | ||
34 | if (efi_capsule_pending(&cap_reset_mode)) { | ||
35 | if (efi_mode != cap_reset_mode) | ||
36 | printk(KERN_CRIT "efi: %s reset requested but pending " | ||
37 | "capsule update requires %s reset... Performing " | ||
38 | "%s reset.\n", str[efi_mode], str[cap_reset_mode], | ||
39 | str[cap_reset_mode]); | ||
40 | efi_mode = cap_reset_mode; | ||
41 | } | ||
42 | |||
33 | efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL); | 43 | efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL); |
34 | } | 44 | } |
35 | 45 | ||
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index de6953039af6..23bef6bb73ee 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c | |||
@@ -16,10 +16,70 @@ | |||
16 | 16 | ||
17 | #include <linux/bug.h> | 17 | #include <linux/bug.h> |
18 | #include <linux/efi.h> | 18 | #include <linux/efi.h> |
19 | #include <linux/irqflags.h> | ||
19 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
20 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
22 | #include <linux/stringify.h> | ||
21 | #include <asm/efi.h> | 23 | #include <asm/efi.h> |
22 | 24 | ||
25 | static void efi_call_virt_check_flags(unsigned long flags, const char *call) | ||
26 | { | ||
27 | unsigned long cur_flags, mismatch; | ||
28 | |||
29 | local_save_flags(cur_flags); | ||
30 | |||
31 | mismatch = flags ^ cur_flags; | ||
32 | if (!WARN_ON_ONCE(mismatch & ARCH_EFI_IRQ_FLAGS_MASK)) | ||
33 | return; | ||
34 | |||
35 | add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_NOW_UNRELIABLE); | ||
36 | pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n", | ||
37 | flags, cur_flags, call); | ||
38 | local_irq_restore(flags); | ||
39 | } | ||
40 | |||
41 | /* | ||
42 | * Arch code can implement the following three template macros, avoiding | ||
43 | * reptition for the void/non-void return cases of {__,}efi_call_virt: | ||
44 | * | ||
45 | * * arch_efi_call_virt_setup | ||
46 | * | ||
47 | * Sets up the environment for the call (e.g. switching page tables, | ||
48 | * allowing kernel-mode use of floating point, if required). | ||
49 | * | ||
50 | * * arch_efi_call_virt | ||
51 | * | ||
52 | * Performs the call. The last expression in the macro must be the call | ||
53 | * itself, allowing the logic to be shared by the void and non-void | ||
54 | * cases. | ||
55 | * | ||
56 | * * arch_efi_call_virt_teardown | ||
57 | * | ||
58 | * Restores the usual kernel environment once the call has returned. | ||
59 | */ | ||
60 | |||
61 | #define efi_call_virt(f, args...) \ | ||
62 | ({ \ | ||
63 | efi_status_t __s; \ | ||
64 | unsigned long flags; \ | ||
65 | arch_efi_call_virt_setup(); \ | ||
66 | local_save_flags(flags); \ | ||
67 | __s = arch_efi_call_virt(f, args); \ | ||
68 | efi_call_virt_check_flags(flags, __stringify(f)); \ | ||
69 | arch_efi_call_virt_teardown(); \ | ||
70 | __s; \ | ||
71 | }) | ||
72 | |||
73 | #define __efi_call_virt(f, args...) \ | ||
74 | ({ \ | ||
75 | unsigned long flags; \ | ||
76 | arch_efi_call_virt_setup(); \ | ||
77 | local_save_flags(flags); \ | ||
78 | arch_efi_call_virt(f, args); \ | ||
79 | efi_call_virt_check_flags(flags, __stringify(f)); \ | ||
80 | arch_efi_call_virt_teardown(); \ | ||
81 | }) | ||
82 | |||
23 | /* | 83 | /* |
24 | * According to section 7.1 of the UEFI spec, Runtime Services are not fully | 84 | * According to section 7.1 of the UEFI spec, Runtime Services are not fully |
25 | * reentrant, and there are particular combinations of calls that need to be | 85 | * reentrant, and there are particular combinations of calls that need to be |
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index 34b741940494..d3b751383286 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c | |||
@@ -329,39 +329,6 @@ check_var_size_nonblocking(u32 attributes, unsigned long size) | |||
329 | return fops->query_variable_store(attributes, size, true); | 329 | return fops->query_variable_store(attributes, size, true); |
330 | } | 330 | } |
331 | 331 | ||
332 | static int efi_status_to_err(efi_status_t status) | ||
333 | { | ||
334 | int err; | ||
335 | |||
336 | switch (status) { | ||
337 | case EFI_SUCCESS: | ||
338 | err = 0; | ||
339 | break; | ||
340 | case EFI_INVALID_PARAMETER: | ||
341 | err = -EINVAL; | ||
342 | break; | ||
343 | case EFI_OUT_OF_RESOURCES: | ||
344 | err = -ENOSPC; | ||
345 | break; | ||
346 | case EFI_DEVICE_ERROR: | ||
347 | err = -EIO; | ||
348 | break; | ||
349 | case EFI_WRITE_PROTECTED: | ||
350 | err = -EROFS; | ||
351 | break; | ||
352 | case EFI_SECURITY_VIOLATION: | ||
353 | err = -EACCES; | ||
354 | break; | ||
355 | case EFI_NOT_FOUND: | ||
356 | err = -ENOENT; | ||
357 | break; | ||
358 | default: | ||
359 | err = -EINVAL; | ||
360 | } | ||
361 | |||
362 | return err; | ||
363 | } | ||
364 | |||
365 | static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor, | 332 | static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor, |
366 | struct list_head *head) | 333 | struct list_head *head) |
367 | { | 334 | { |
@@ -452,8 +419,7 @@ static void dup_variable_bug(efi_char16_t *str16, efi_guid_t *vendor_guid, | |||
452 | * Returns 0 on success, or a kernel error code on failure. | 419 | * Returns 0 on success, or a kernel error code on failure. |
453 | */ | 420 | */ |
454 | int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), | 421 | int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), |
455 | void *data, bool atomic, bool duplicates, | 422 | void *data, bool duplicates, struct list_head *head) |
456 | struct list_head *head) | ||
457 | { | 423 | { |
458 | const struct efivar_operations *ops = __efivars->ops; | 424 | const struct efivar_operations *ops = __efivars->ops; |
459 | unsigned long variable_name_size = 1024; | 425 | unsigned long variable_name_size = 1024; |
@@ -483,7 +449,7 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), | |||
483 | &vendor_guid); | 449 | &vendor_guid); |
484 | switch (status) { | 450 | switch (status) { |
485 | case EFI_SUCCESS: | 451 | case EFI_SUCCESS: |
486 | if (!atomic) | 452 | if (duplicates) |
487 | spin_unlock_irq(&__efivars->lock); | 453 | spin_unlock_irq(&__efivars->lock); |
488 | 454 | ||
489 | variable_name_size = var_name_strnsize(variable_name, | 455 | variable_name_size = var_name_strnsize(variable_name, |
@@ -498,21 +464,19 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), | |||
498 | * and may end up looping here forever. | 464 | * and may end up looping here forever. |
499 | */ | 465 | */ |
500 | if (duplicates && | 466 | if (duplicates && |
501 | variable_is_present(variable_name, &vendor_guid, head)) { | 467 | variable_is_present(variable_name, &vendor_guid, |
468 | head)) { | ||
502 | dup_variable_bug(variable_name, &vendor_guid, | 469 | dup_variable_bug(variable_name, &vendor_guid, |
503 | variable_name_size); | 470 | variable_name_size); |
504 | if (!atomic) | ||
505 | spin_lock_irq(&__efivars->lock); | ||
506 | |||
507 | status = EFI_NOT_FOUND; | 471 | status = EFI_NOT_FOUND; |
508 | break; | 472 | } else { |
473 | err = func(variable_name, vendor_guid, | ||
474 | variable_name_size, data); | ||
475 | if (err) | ||
476 | status = EFI_NOT_FOUND; | ||
509 | } | 477 | } |
510 | 478 | ||
511 | err = func(variable_name, vendor_guid, variable_name_size, data); | 479 | if (duplicates) |
512 | if (err) | ||
513 | status = EFI_NOT_FOUND; | ||
514 | |||
515 | if (!atomic) | ||
516 | spin_lock_irq(&__efivars->lock); | 480 | spin_lock_irq(&__efivars->lock); |
517 | 481 | ||
518 | break; | 482 | break; |
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 983280e8d93f..e5a391aecde1 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig | |||
@@ -761,7 +761,7 @@ config FB_VESA | |||
761 | 761 | ||
762 | config FB_EFI | 762 | config FB_EFI |
763 | bool "EFI-based Framebuffer Support" | 763 | bool "EFI-based Framebuffer Support" |
764 | depends on (FB = y) && X86 && EFI | 764 | depends on (FB = y) && !IA64 && EFI |
765 | select FB_CFB_FILLRECT | 765 | select FB_CFB_FILLRECT |
766 | select FB_CFB_COPYAREA | 766 | select FB_CFB_COPYAREA |
767 | select FB_CFB_IMAGEBLIT | 767 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c index 95d293b7445a..f4c045c0051c 100644 --- a/drivers/video/fbdev/efifb.c +++ b/drivers/video/fbdev/efifb.c | |||
@@ -6,16 +6,14 @@ | |||
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/efi.h> | ||
11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
12 | #include <linux/fb.h> | 12 | #include <linux/fb.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/screen_info.h> | 14 | #include <linux/screen_info.h> |
15 | #include <linux/dmi.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <video/vga.h> | 15 | #include <video/vga.h> |
18 | #include <asm/sysfb.h> | 16 | #include <asm/efi.h> |
19 | 17 | ||
20 | static bool request_mem_succeeded = false; | 18 | static bool request_mem_succeeded = false; |
21 | 19 | ||
@@ -85,21 +83,13 @@ static struct fb_ops efifb_ops = { | |||
85 | static int efifb_setup(char *options) | 83 | static int efifb_setup(char *options) |
86 | { | 84 | { |
87 | char *this_opt; | 85 | char *this_opt; |
88 | int i; | ||
89 | 86 | ||
90 | if (options && *options) { | 87 | if (options && *options) { |
91 | while ((this_opt = strsep(&options, ",")) != NULL) { | 88 | while ((this_opt = strsep(&options, ",")) != NULL) { |
92 | if (!*this_opt) continue; | 89 | if (!*this_opt) continue; |
93 | 90 | ||
94 | for (i = 0; i < M_UNKNOWN; i++) { | 91 | efifb_setup_from_dmi(&screen_info, this_opt); |
95 | if (efifb_dmi_list[i].base != 0 && | 92 | |
96 | !strcmp(this_opt, efifb_dmi_list[i].optname)) { | ||
97 | screen_info.lfb_base = efifb_dmi_list[i].base; | ||
98 | screen_info.lfb_linelength = efifb_dmi_list[i].stride; | ||
99 | screen_info.lfb_width = efifb_dmi_list[i].width; | ||
100 | screen_info.lfb_height = efifb_dmi_list[i].height; | ||
101 | } | ||
102 | } | ||
103 | if (!strncmp(this_opt, "base:", 5)) | 93 | if (!strncmp(this_opt, "base:", 5)) |
104 | screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0); | 94 | screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0); |
105 | else if (!strncmp(this_opt, "stride:", 7)) | 95 | else if (!strncmp(this_opt, "stride:", 7)) |
@@ -338,5 +328,4 @@ static struct platform_driver efifb_driver = { | |||
338 | .remove = efifb_remove, | 328 | .remove = efifb_remove, |
339 | }; | 329 | }; |
340 | 330 | ||
341 | module_platform_driver(efifb_driver); | 331 | builtin_platform_driver(efifb_driver); |
342 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/xen/efi.c b/drivers/xen/efi.c index be7e56a338e8..e9d2135445c1 100644 --- a/drivers/xen/efi.c +++ b/drivers/xen/efi.c | |||
@@ -316,7 +316,6 @@ static const struct efi efi_xen __initconst = { | |||
316 | .get_next_high_mono_count = xen_efi_get_next_high_mono_count, | 316 | .get_next_high_mono_count = xen_efi_get_next_high_mono_count, |
317 | .reset_system = NULL, /* Functionality provided by Xen. */ | 317 | .reset_system = NULL, /* Functionality provided by Xen. */ |
318 | .set_virtual_address_map = NULL, /* Not used under Xen. */ | 318 | .set_virtual_address_map = NULL, /* Not used under Xen. */ |
319 | .memmap = NULL, /* Not used under Xen. */ | ||
320 | .flags = 0 /* Initialized later. */ | 319 | .flags = 0 /* Initialized later. */ |
321 | }; | 320 | }; |
322 | 321 | ||
diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c index d48e0d261d78..5f22e74bbade 100644 --- a/fs/efivarfs/file.c +++ b/fs/efivarfs/file.c | |||
@@ -157,7 +157,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg) | |||
157 | return 0; | 157 | return 0; |
158 | } | 158 | } |
159 | 159 | ||
160 | long | 160 | static long |
161 | efivarfs_file_ioctl(struct file *file, unsigned int cmd, unsigned long p) | 161 | efivarfs_file_ioctl(struct file *file, unsigned int cmd, unsigned long p) |
162 | { | 162 | { |
163 | void __user *arg = (void __user *)p; | 163 | void __user *arg = (void __user *)p; |
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c index 553c5d2db4a4..9cb54a38832d 100644 --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c | |||
@@ -216,8 +216,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | |||
216 | 216 | ||
217 | INIT_LIST_HEAD(&efivarfs_list); | 217 | INIT_LIST_HEAD(&efivarfs_list); |
218 | 218 | ||
219 | err = efivar_init(efivarfs_callback, (void *)sb, false, | 219 | err = efivar_init(efivarfs_callback, (void *)sb, true, &efivarfs_list); |
220 | true, &efivarfs_list); | ||
221 | if (err) | 220 | if (err) |
222 | __efivar_entry_iter(efivarfs_destroy, &efivarfs_list, NULL, NULL); | 221 | __efivar_entry_iter(efivarfs_destroy, &efivarfs_list, NULL, NULL); |
223 | 222 | ||
diff --git a/include/linux/efi.h b/include/linux/efi.h index 1626474567ac..df7acb51f3cc 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/pfn.h> | 21 | #include <linux/pfn.h> |
22 | #include <linux/pstore.h> | 22 | #include <linux/pstore.h> |
23 | #include <linux/reboot.h> | 23 | #include <linux/reboot.h> |
24 | #include <linux/screen_info.h> | ||
24 | 25 | ||
25 | #include <asm/page.h> | 26 | #include <asm/page.h> |
26 | 27 | ||
@@ -124,6 +125,13 @@ typedef struct { | |||
124 | } efi_capsule_header_t; | 125 | } efi_capsule_header_t; |
125 | 126 | ||
126 | /* | 127 | /* |
128 | * EFI capsule flags | ||
129 | */ | ||
130 | #define EFI_CAPSULE_PERSIST_ACROSS_RESET 0x00010000 | ||
131 | #define EFI_CAPSULE_POPULATE_SYSTEM_TABLE 0x00020000 | ||
132 | #define EFI_CAPSULE_INITIATE_RESET 0x00040000 | ||
133 | |||
134 | /* | ||
127 | * Allocation types for calls to boottime->allocate_pages. | 135 | * Allocation types for calls to boottime->allocate_pages. |
128 | */ | 136 | */ |
129 | #define EFI_ALLOCATE_ANY_PAGES 0 | 137 | #define EFI_ALLOCATE_ANY_PAGES 0 |
@@ -282,9 +290,10 @@ typedef struct { | |||
282 | efi_status_t (*handle_protocol)(efi_handle_t, efi_guid_t *, void **); | 290 | efi_status_t (*handle_protocol)(efi_handle_t, efi_guid_t *, void **); |
283 | void *__reserved; | 291 | void *__reserved; |
284 | void *register_protocol_notify; | 292 | void *register_protocol_notify; |
285 | void *locate_handle; | 293 | efi_status_t (*locate_handle)(int, efi_guid_t *, void *, |
294 | unsigned long *, efi_handle_t *); | ||
286 | void *locate_device_path; | 295 | void *locate_device_path; |
287 | void *install_configuration_table; | 296 | efi_status_t (*install_configuration_table)(efi_guid_t *, void *); |
288 | void *load_image; | 297 | void *load_image; |
289 | void *start_image; | 298 | void *start_image; |
290 | void *exit; | 299 | void *exit; |
@@ -623,6 +632,27 @@ void efi_native_runtime_setup(void); | |||
623 | EFI_GUID(0x3152bca5, 0xeade, 0x433d, \ | 632 | EFI_GUID(0x3152bca5, 0xeade, 0x433d, \ |
624 | 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44) | 633 | 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44) |
625 | 634 | ||
635 | #define EFI_MEMORY_ATTRIBUTES_TABLE_GUID \ | ||
636 | EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, \ | ||
637 | 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20) | ||
638 | |||
639 | #define EFI_CONSOLE_OUT_DEVICE_GUID \ | ||
640 | EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, \ | ||
641 | 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) | ||
642 | |||
643 | /* | ||
644 | * This GUID is used to pass to the kernel proper the struct screen_info | ||
645 | * structure that was populated by the stub based on the GOP protocol instance | ||
646 | * associated with ConOut | ||
647 | */ | ||
648 | #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID \ | ||
649 | EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, \ | ||
650 | 0xb9, 0xe, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) | ||
651 | |||
652 | #define LINUX_EFI_LOADER_ENTRY_GUID \ | ||
653 | EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, \ | ||
654 | 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) | ||
655 | |||
626 | typedef struct { | 656 | typedef struct { |
627 | efi_guid_t guid; | 657 | efi_guid_t guid; |
628 | u64 table; | 658 | u64 table; |
@@ -847,6 +877,14 @@ typedef struct { | |||
847 | 877 | ||
848 | #define EFI_INVALID_TABLE_ADDR (~0UL) | 878 | #define EFI_INVALID_TABLE_ADDR (~0UL) |
849 | 879 | ||
880 | typedef struct { | ||
881 | u32 version; | ||
882 | u32 num_entries; | ||
883 | u32 desc_size; | ||
884 | u32 reserved; | ||
885 | efi_memory_desc_t entry[0]; | ||
886 | } efi_memory_attributes_table_t; | ||
887 | |||
850 | /* | 888 | /* |
851 | * All runtime access to EFI goes through this structure: | 889 | * All runtime access to EFI goes through this structure: |
852 | */ | 890 | */ |
@@ -868,6 +906,7 @@ extern struct efi { | |||
868 | unsigned long config_table; /* config tables */ | 906 | unsigned long config_table; /* config tables */ |
869 | unsigned long esrt; /* ESRT table */ | 907 | unsigned long esrt; /* ESRT table */ |
870 | unsigned long properties_table; /* properties table */ | 908 | unsigned long properties_table; /* properties table */ |
909 | unsigned long mem_attr_table; /* memory attributes table */ | ||
871 | efi_get_time_t *get_time; | 910 | efi_get_time_t *get_time; |
872 | efi_set_time_t *set_time; | 911 | efi_set_time_t *set_time; |
873 | efi_get_wakeup_time_t *get_wakeup_time; | 912 | efi_get_wakeup_time_t *get_wakeup_time; |
@@ -883,7 +922,7 @@ extern struct efi { | |||
883 | efi_get_next_high_mono_count_t *get_next_high_mono_count; | 922 | efi_get_next_high_mono_count_t *get_next_high_mono_count; |
884 | efi_reset_system_t *reset_system; | 923 | efi_reset_system_t *reset_system; |
885 | efi_set_virtual_address_map_t *set_virtual_address_map; | 924 | efi_set_virtual_address_map_t *set_virtual_address_map; |
886 | struct efi_memory_map *memmap; | 925 | struct efi_memory_map memmap; |
887 | unsigned long flags; | 926 | unsigned long flags; |
888 | } efi; | 927 | } efi; |
889 | 928 | ||
@@ -945,7 +984,6 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource, | |||
945 | extern void efi_get_time(struct timespec *now); | 984 | extern void efi_get_time(struct timespec *now); |
946 | extern void efi_reserve_boot_services(void); | 985 | extern void efi_reserve_boot_services(void); |
947 | extern int efi_get_fdt_params(struct efi_fdt_params *params); | 986 | extern int efi_get_fdt_params(struct efi_fdt_params *params); |
948 | extern struct efi_memory_map memmap; | ||
949 | extern struct kobject *efi_kobj; | 987 | extern struct kobject *efi_kobj; |
950 | 988 | ||
951 | extern int efi_reboot_quirk_mode; | 989 | extern int efi_reboot_quirk_mode; |
@@ -957,12 +995,34 @@ extern void __init efi_fake_memmap(void); | |||
957 | static inline void efi_fake_memmap(void) { } | 995 | static inline void efi_fake_memmap(void) { } |
958 | #endif | 996 | #endif |
959 | 997 | ||
998 | /* | ||
999 | * efi_memattr_perm_setter - arch specific callback function passed into | ||
1000 | * efi_memattr_apply_permissions() that updates the | ||
1001 | * mapping permissions described by the second | ||
1002 | * argument in the page tables referred to by the | ||
1003 | * first argument. | ||
1004 | */ | ||
1005 | typedef int (*efi_memattr_perm_setter)(struct mm_struct *, efi_memory_desc_t *); | ||
1006 | |||
1007 | extern int efi_memattr_init(void); | ||
1008 | extern int efi_memattr_apply_permissions(struct mm_struct *mm, | ||
1009 | efi_memattr_perm_setter fn); | ||
1010 | |||
960 | /* Iterate through an efi_memory_map */ | 1011 | /* Iterate through an efi_memory_map */ |
961 | #define for_each_efi_memory_desc(m, md) \ | 1012 | #define for_each_efi_memory_desc_in_map(m, md) \ |
962 | for ((md) = (m)->map; \ | 1013 | for ((md) = (m)->map; \ |
963 | (md) <= (efi_memory_desc_t *)((m)->map_end - (m)->desc_size); \ | 1014 | (md) <= (efi_memory_desc_t *)((m)->map_end - (m)->desc_size); \ |
964 | (md) = (void *)(md) + (m)->desc_size) | 1015 | (md) = (void *)(md) + (m)->desc_size) |
965 | 1016 | ||
1017 | /** | ||
1018 | * for_each_efi_memory_desc - iterate over descriptors in efi.memmap | ||
1019 | * @md: the efi_memory_desc_t * iterator | ||
1020 | * | ||
1021 | * Once the loop finishes @md must not be accessed. | ||
1022 | */ | ||
1023 | #define for_each_efi_memory_desc(md) \ | ||
1024 | for_each_efi_memory_desc_in_map(&efi.memmap, md) | ||
1025 | |||
966 | /* | 1026 | /* |
967 | * Format an EFI memory descriptor's type and attributes to a user-provided | 1027 | * Format an EFI memory descriptor's type and attributes to a user-provided |
968 | * character buffer, as per snprintf(), and return the buffer. | 1028 | * character buffer, as per snprintf(), and return the buffer. |
@@ -1000,7 +1060,6 @@ extern int __init efi_setup_pcdp_console(char *); | |||
1000 | * possible, remove EFI-related code altogether. | 1060 | * possible, remove EFI-related code altogether. |
1001 | */ | 1061 | */ |
1002 | #define EFI_BOOT 0 /* Were we booted from EFI? */ | 1062 | #define EFI_BOOT 0 /* Were we booted from EFI? */ |
1003 | #define EFI_SYSTEM_TABLES 1 /* Can we use EFI system tables? */ | ||
1004 | #define EFI_CONFIG_TABLES 2 /* Can we use EFI config tables? */ | 1063 | #define EFI_CONFIG_TABLES 2 /* Can we use EFI config tables? */ |
1005 | #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ | 1064 | #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ |
1006 | #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ | 1065 | #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ |
@@ -1026,8 +1085,16 @@ static inline bool efi_enabled(int feature) | |||
1026 | } | 1085 | } |
1027 | static inline void | 1086 | static inline void |
1028 | efi_reboot(enum reboot_mode reboot_mode, const char *__unused) {} | 1087 | efi_reboot(enum reboot_mode reboot_mode, const char *__unused) {} |
1088 | |||
1089 | static inline bool | ||
1090 | efi_capsule_pending(int *reset_type) | ||
1091 | { | ||
1092 | return false; | ||
1093 | } | ||
1029 | #endif | 1094 | #endif |
1030 | 1095 | ||
1096 | extern int efi_status_to_err(efi_status_t status); | ||
1097 | |||
1031 | /* | 1098 | /* |
1032 | * Variable Attributes | 1099 | * Variable Attributes |
1033 | */ | 1100 | */ |
@@ -1180,6 +1247,80 @@ struct efi_simple_text_output_protocol { | |||
1180 | void *test_string; | 1247 | void *test_string; |
1181 | }; | 1248 | }; |
1182 | 1249 | ||
1250 | #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 | ||
1251 | #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 | ||
1252 | #define PIXEL_BIT_MASK 2 | ||
1253 | #define PIXEL_BLT_ONLY 3 | ||
1254 | #define PIXEL_FORMAT_MAX 4 | ||
1255 | |||
1256 | struct efi_pixel_bitmask { | ||
1257 | u32 red_mask; | ||
1258 | u32 green_mask; | ||
1259 | u32 blue_mask; | ||
1260 | u32 reserved_mask; | ||
1261 | }; | ||
1262 | |||
1263 | struct efi_graphics_output_mode_info { | ||
1264 | u32 version; | ||
1265 | u32 horizontal_resolution; | ||
1266 | u32 vertical_resolution; | ||
1267 | int pixel_format; | ||
1268 | struct efi_pixel_bitmask pixel_information; | ||
1269 | u32 pixels_per_scan_line; | ||
1270 | } __packed; | ||
1271 | |||
1272 | struct efi_graphics_output_protocol_mode_32 { | ||
1273 | u32 max_mode; | ||
1274 | u32 mode; | ||
1275 | u32 info; | ||
1276 | u32 size_of_info; | ||
1277 | u64 frame_buffer_base; | ||
1278 | u32 frame_buffer_size; | ||
1279 | } __packed; | ||
1280 | |||
1281 | struct efi_graphics_output_protocol_mode_64 { | ||
1282 | u32 max_mode; | ||
1283 | u32 mode; | ||
1284 | u64 info; | ||
1285 | u64 size_of_info; | ||
1286 | u64 frame_buffer_base; | ||
1287 | u64 frame_buffer_size; | ||
1288 | } __packed; | ||
1289 | |||
1290 | struct efi_graphics_output_protocol_mode { | ||
1291 | u32 max_mode; | ||
1292 | u32 mode; | ||
1293 | unsigned long info; | ||
1294 | unsigned long size_of_info; | ||
1295 | u64 frame_buffer_base; | ||
1296 | unsigned long frame_buffer_size; | ||
1297 | } __packed; | ||
1298 | |||
1299 | struct efi_graphics_output_protocol_32 { | ||
1300 | u32 query_mode; | ||
1301 | u32 set_mode; | ||
1302 | u32 blt; | ||
1303 | u32 mode; | ||
1304 | }; | ||
1305 | |||
1306 | struct efi_graphics_output_protocol_64 { | ||
1307 | u64 query_mode; | ||
1308 | u64 set_mode; | ||
1309 | u64 blt; | ||
1310 | u64 mode; | ||
1311 | }; | ||
1312 | |||
1313 | struct efi_graphics_output_protocol { | ||
1314 | unsigned long query_mode; | ||
1315 | unsigned long set_mode; | ||
1316 | unsigned long blt; | ||
1317 | struct efi_graphics_output_protocol_mode *mode; | ||
1318 | }; | ||
1319 | |||
1320 | typedef efi_status_t (*efi_graphics_output_protocol_query_mode)( | ||
1321 | struct efi_graphics_output_protocol *, u32, unsigned long *, | ||
1322 | struct efi_graphics_output_mode_info **); | ||
1323 | |||
1183 | extern struct list_head efivar_sysfs_list; | 1324 | extern struct list_head efivar_sysfs_list; |
1184 | 1325 | ||
1185 | static inline void | 1326 | static inline void |
@@ -1195,8 +1336,7 @@ int efivars_unregister(struct efivars *efivars); | |||
1195 | struct kobject *efivars_kobject(void); | 1336 | struct kobject *efivars_kobject(void); |
1196 | 1337 | ||
1197 | int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), | 1338 | int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), |
1198 | void *data, bool atomic, bool duplicates, | 1339 | void *data, bool duplicates, struct list_head *head); |
1199 | struct list_head *head); | ||
1200 | 1340 | ||
1201 | void efivar_entry_add(struct efivar_entry *entry, struct list_head *head); | 1341 | void efivar_entry_add(struct efivar_entry *entry, struct list_head *head); |
1202 | void efivar_entry_remove(struct efivar_entry *entry); | 1342 | void efivar_entry_remove(struct efivar_entry *entry); |
@@ -1242,6 +1382,13 @@ int efivars_sysfs_init(void); | |||
1242 | #define EFIVARS_DATA_SIZE_MAX 1024 | 1382 | #define EFIVARS_DATA_SIZE_MAX 1024 |
1243 | 1383 | ||
1244 | #endif /* CONFIG_EFI_VARS */ | 1384 | #endif /* CONFIG_EFI_VARS */ |
1385 | extern bool efi_capsule_pending(int *reset_type); | ||
1386 | |||
1387 | extern int efi_capsule_supported(efi_guid_t guid, u32 flags, | ||
1388 | size_t size, int *reset); | ||
1389 | |||
1390 | extern int efi_capsule_update(efi_capsule_header_t *capsule, | ||
1391 | struct page **pages); | ||
1245 | 1392 | ||
1246 | #ifdef CONFIG_EFI_RUNTIME_MAP | 1393 | #ifdef CONFIG_EFI_RUNTIME_MAP |
1247 | int efi_runtime_map_init(struct kobject *); | 1394 | int efi_runtime_map_init(struct kobject *); |
@@ -1319,5 +1466,9 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, | |||
1319 | 1466 | ||
1320 | efi_status_t efi_parse_options(char *cmdline); | 1467 | efi_status_t efi_parse_options(char *cmdline); |
1321 | 1468 | ||
1469 | efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg, | ||
1470 | struct screen_info *si, efi_guid_t *proto, | ||
1471 | unsigned long size); | ||
1472 | |||
1322 | bool efi_runtime_disabled(void); | 1473 | bool efi_runtime_disabled(void); |
1323 | #endif /* _LINUX_EFI_H */ | 1474 | #endif /* _LINUX_EFI_H */ |