aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2016-04-25 16:06:53 -0400
committerIngo Molnar <mingo@kernel.org>2016-04-28 05:33:59 -0400
commit801820bee9bccb7c156af2b95c7208f428a06ae7 (patch)
treee2d486dc835f643ffa966d7b499f2ef17d3f1d7b
parent57fdb89aeb7b0e3aab19847ab7399e5d76f11e6f (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.h3
-rw-r--r--arch/arm/kernel/setup.c3
-rw-r--r--drivers/firmware/efi/arm-init.c34
-rw-r--r--drivers/firmware/efi/efi.c5
-rw-r--r--drivers/firmware/efi/libstub/arm32-stub.c37
-rw-r--r--include/linux/efi.h11
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
67struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg);
68void 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)
887struct screen_info screen_info = { 888struct 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
57static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
58
59static __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
64static 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
54static int __init uefi_init(void) 83static 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);
114out: 144out:
@@ -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
29static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;
30
31struct 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
57void 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
29efi_status_t handle_kernel_image(efi_system_table_t *sys_table, 66efi_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
636typedef struct { 645typedef struct {
637 efi_guid_t guid; 646 efi_guid_t guid;
638 u64 table; 647 u64 table;