diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2016-04-25 16:06:53 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-04-28 05:33:59 -0400 |
commit | 801820bee9bccb7c156af2b95c7208f428a06ae7 (patch) | |
tree | e2d486dc835f643ffa966d7b499f2ef17d3f1d7b | |
parent | 57fdb89aeb7b0e3aab19847ab7399e5d76f11e6f (diff) |
efi/arm/libstub: Make screen_info accessible to the UEFI stub
In order to hand over the framebuffer described by the GOP protocol and
discovered by the UEFI stub, make struct screen_info accessible by the
stub. This involves allocating a loader data buffer and passing it to the
kernel proper via a UEFI Configuration Table, since the UEFI stub executes
in the context of the decompressor, and cannot access the kernel's copy of
struct screen_info directly.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Borislav Petkov <bp@alien8.de>
Cc: David Herrmann <dh.herrmann@gmail.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Jones <pjones@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will.deacon@arm.com>
Cc: linux-efi@vger.kernel.org
Link: http://lkml.kernel.org/r/1461614832-17633-22-git-send-email-matt@codeblueprint.co.uk
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/arm/include/asm/efi.h | 3 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 3 | ||||
-rw-r--r-- | drivers/firmware/efi/arm-init.c | 34 | ||||
-rw-r--r-- | drivers/firmware/efi/efi.c | 5 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm32-stub.c | 37 | ||||
-rw-r--r-- | include/linux/efi.h | 11 |
6 files changed, 88 insertions, 5 deletions
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index dc30d89a1ed3..25f8b1162c2e 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h | |||
@@ -64,6 +64,9 @@ void efi_virtmap_unload(void); | |||
64 | #define __efi_call_early(f, ...) f(__VA_ARGS__) | 64 | #define __efi_call_early(f, ...) f(__VA_ARGS__) |
65 | #define efi_is_64bit() (false) | 65 | #define efi_is_64bit() (false) |
66 | 66 | ||
67 | struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg); | ||
68 | void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si); | ||
69 | |||
67 | /* | 70 | /* |
68 | * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, | 71 | * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, |
69 | * so we will reserve that amount of memory. We have no easy way to tell what | 72 | * so we will reserve that amount of memory. We have no easy way to tell what |
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/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 909d974d35d9..ac95dd8b119f 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c | |||
@@ -11,12 +11,15 @@ | |||
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/screen_info.h> | ||
20 | 23 | ||
21 | #include <asm/efi.h> | 24 | #include <asm/efi.h> |
22 | 25 | ||
@@ -51,6 +54,32 @@ static phys_addr_t efi_to_phys(unsigned long addr) | |||
51 | return addr; | 54 | return addr; |
52 | } | 55 | } |
53 | 56 | ||
57 | static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR; | ||
58 | |||
59 | static __initdata efi_config_table_type_t arch_tables[] = { | ||
60 | {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, NULL, &screen_info_table}, | ||
61 | {NULL_GUID, NULL, NULL} | ||
62 | }; | ||
63 | |||
64 | static void __init init_screen_info(void) | ||
65 | { | ||
66 | struct screen_info *si; | ||
67 | |||
68 | if (screen_info_table != EFI_INVALID_TABLE_ADDR) { | ||
69 | si = early_memremap_ro(screen_info_table, sizeof(*si)); | ||
70 | if (!si) { | ||
71 | pr_err("Could not map screen_info config table\n"); | ||
72 | return; | ||
73 | } | ||
74 | screen_info = *si; | ||
75 | early_memunmap(si, sizeof(*si)); | ||
76 | |||
77 | /* dummycon on ARM needs non-zero values for columns/lines */ | ||
78 | screen_info.orig_video_cols = 80; | ||
79 | screen_info.orig_video_lines = 25; | ||
80 | } | ||
81 | } | ||
82 | |||
54 | static int __init uefi_init(void) | 83 | static int __init uefi_init(void) |
55 | { | 84 | { |
56 | efi_char16_t *c16; | 85 | efi_char16_t *c16; |
@@ -108,7 +137,8 @@ static int __init uefi_init(void) | |||
108 | goto out; | 137 | goto out; |
109 | } | 138 | } |
110 | retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, | 139 | retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, |
111 | sizeof(efi_config_table_t), NULL); | 140 | sizeof(efi_config_table_t), |
141 | arch_tables); | ||
112 | 142 | ||
113 | early_memunmap(config_tables, table_size); | 143 | early_memunmap(config_tables, table_size); |
114 | out: | 144 | out: |
@@ -223,4 +253,6 @@ void __init efi_init(void) | |||
223 | PAGE_ALIGN(params.mmap_size + | 253 | PAGE_ALIGN(params.mmap_size + |
224 | (params.mmap & ~PAGE_MASK))); | 254 | (params.mmap & ~PAGE_MASK))); |
225 | } | 255 | } |
256 | |||
257 | init_screen_info(); | ||
226 | } | 258 | } |
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 583e647912a5..4991371012b4 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
@@ -353,8 +353,9 @@ static __init int match_config_table(efi_guid_t *guid, | |||
353 | 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++) { |
354 | if (!efi_guidcmp(*guid, table_types[i].guid)) { | 354 | if (!efi_guidcmp(*guid, table_types[i].guid)) { |
355 | *(table_types[i].ptr) = table; | 355 | *(table_types[i].ptr) = table; |
356 | pr_cont(" %s=0x%lx ", | 356 | if (table_types[i].name) |
357 | table_types[i].name, table); | 357 | pr_cont(" %s=0x%lx ", |
358 | table_types[i].name, table); | ||
358 | return 1; | 359 | return 1; |
359 | } | 360 | } |
360 | } | 361 | } |
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/include/linux/efi.h b/include/linux/efi.h index 9203bbb28887..e53458842245 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -286,7 +286,7 @@ typedef struct { | |||
286 | efi_status_t (*locate_handle)(int, efi_guid_t *, void *, | 286 | efi_status_t (*locate_handle)(int, efi_guid_t *, void *, |
287 | unsigned long *, efi_handle_t *); | 287 | unsigned long *, efi_handle_t *); |
288 | void *locate_device_path; | 288 | void *locate_device_path; |
289 | void *install_configuration_table; | 289 | efi_status_t (*install_configuration_table)(efi_guid_t *, void *); |
290 | void *load_image; | 290 | void *load_image; |
291 | void *start_image; | 291 | void *start_image; |
292 | void *exit; | 292 | void *exit; |
@@ -633,6 +633,15 @@ void efi_native_runtime_setup(void); | |||
633 | EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, \ | 633 | EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, \ |
634 | 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) | 634 | 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) |
635 | 635 | ||
636 | /* | ||
637 | * This GUID is used to pass to the kernel proper the struct screen_info | ||
638 | * structure that was populated by the stub based on the GOP protocol instance | ||
639 | * associated with ConOut | ||
640 | */ | ||
641 | #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID \ | ||
642 | EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, \ | ||
643 | 0xb9, 0xe, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) | ||
644 | |||
636 | typedef struct { | 645 | typedef struct { |
637 | efi_guid_t guid; | 646 | efi_guid_t guid; |
638 | u64 table; | 647 | u64 table; |