Skip to content

Commit 801820b

Browse files
Ard BiesheuvelIngo Molnar
authored andcommitted
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>
1 parent 57fdb89 commit 801820b

File tree

6 files changed

+88
-5
lines changed

6 files changed

+88
-5
lines changed

arch/arm/include/asm/efi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ void efi_virtmap_unload(void);
6464
#define __efi_call_early(f, ...) f(__VA_ARGS__)
6565
#define efi_is_64bit() (false)
6666

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+
6770
/*
6871
* A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
6972
* so we will reserve that amount of memory. We have no easy way to tell what

arch/arm/kernel/setup.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,8 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
883883
request_resource(&ioport_resource, &lp2);
884884
}
885885

886-
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
886+
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) || \
887+
defined(CONFIG_EFI)
887888
struct screen_info screen_info = {
888889
.orig_video_lines = 30,
889890
.orig_video_cols = 80,

drivers/firmware/efi/arm-init.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@
1111
*
1212
*/
1313

14+
#define pr_fmt(fmt) "efi: " fmt
15+
1416
#include <linux/efi.h>
1517
#include <linux/init.h>
1618
#include <linux/memblock.h>
1719
#include <linux/mm_types.h>
1820
#include <linux/of.h>
1921
#include <linux/of_fdt.h>
22+
#include <linux/screen_info.h>
2023

2124
#include <asm/efi.h>
2225

@@ -51,6 +54,32 @@ static phys_addr_t efi_to_phys(unsigned long addr)
5154
return addr;
5255
}
5356

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+
5483
static int __init uefi_init(void)
5584
{
5685
efi_char16_t *c16;
@@ -108,7 +137,8 @@ static int __init uefi_init(void)
108137
goto out;
109138
}
110139
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);
112142

113143
early_memunmap(config_tables, table_size);
114144
out:
@@ -223,4 +253,6 @@ void __init efi_init(void)
223253
PAGE_ALIGN(params.mmap_size +
224254
(params.mmap & ~PAGE_MASK)));
225255
}
256+
257+
init_screen_info();
226258
}

drivers/firmware/efi/efi.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,9 @@ static __init int match_config_table(efi_guid_t *guid,
353353
for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
354354
if (!efi_guidcmp(*guid, table_types[i].guid)) {
355355
*(table_types[i].ptr) = table;
356-
pr_cont(" %s=0x%lx ",
357-
table_types[i].name, table);
356+
if (table_types[i].name)
357+
pr_cont(" %s=0x%lx ",
358+
table_types[i].name, table);
358359
return 1;
359360
}
360361
}

drivers/firmware/efi/libstub/arm32-stub.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,43 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
2626
return EFI_SUCCESS;
2727
}
2828

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+
2966
efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
3067
unsigned long *image_addr,
3168
unsigned long *image_size,

include/linux/efi.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ typedef struct {
286286
efi_status_t (*locate_handle)(int, efi_guid_t *, void *,
287287
unsigned long *, efi_handle_t *);
288288
void *locate_device_path;
289-
void *install_configuration_table;
289+
efi_status_t (*install_configuration_table)(efi_guid_t *, void *);
290290
void *load_image;
291291
void *start_image;
292292
void *exit;
@@ -633,6 +633,15 @@ void efi_native_runtime_setup(void);
633633
EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, \
634634
0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
635635

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+
636645
typedef struct {
637646
efi_guid_t guid;
638647
u64 table;

0 commit comments

Comments
 (0)