Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 801820be authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Ingo Molnar
Browse files

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: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarMatt 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: default avatarIngo Molnar <mingo@kernel.org>
parent 57fdb89a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -64,6 +64,9 @@ void efi_virtmap_unload(void);
#define __efi_call_early(f, ...)	f(__VA_ARGS__)
#define efi_is_64bit()			(false)

struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg);
void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si);

/*
 * A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
 * so we will reserve that amount of memory. We have no easy way to tell what
+2 −1
Original line number Diff line number Diff line
@@ -883,7 +883,8 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
		request_resource(&ioport_resource, &lp2);
}

#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) || \
    defined(CONFIG_EFI)
struct screen_info screen_info = {
 .orig_video_lines	= 30,
 .orig_video_cols	= 80,
+33 −1
Original line number Diff line number Diff line
@@ -11,12 +11,15 @@
 *
 */

#define pr_fmt(fmt)	"efi: " fmt

#include <linux/efi.h>
#include <linux/init.h>
#include <linux/memblock.h>
#include <linux/mm_types.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/screen_info.h>

#include <asm/efi.h>

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

static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;

static __initdata efi_config_table_type_t arch_tables[] = {
	{LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, NULL, &screen_info_table},
	{NULL_GUID, NULL, NULL}
};

static void __init init_screen_info(void)
{
	struct screen_info *si;

	if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
		si = early_memremap_ro(screen_info_table, sizeof(*si));
		if (!si) {
			pr_err("Could not map screen_info config table\n");
			return;
		}
		screen_info = *si;
		early_memunmap(si, sizeof(*si));

		/* dummycon on ARM needs non-zero values for columns/lines */
		screen_info.orig_video_cols = 80;
		screen_info.orig_video_lines = 25;
	}
}

static int __init uefi_init(void)
{
	efi_char16_t *c16;
@@ -108,7 +137,8 @@ static int __init uefi_init(void)
		goto out;
	}
	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
					 sizeof(efi_config_table_t), NULL);
					 sizeof(efi_config_table_t),
					 arch_tables);

	early_memunmap(config_tables, table_size);
out:
@@ -223,4 +253,6 @@ void __init efi_init(void)
				 PAGE_ALIGN(params.mmap_size +
					    (params.mmap & ~PAGE_MASK)));
	}

	init_screen_info();
}
+3 −2
Original line number Diff line number Diff line
@@ -353,6 +353,7 @@ static __init int match_config_table(efi_guid_t *guid,
		for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
			if (!efi_guidcmp(*guid, table_types[i].guid)) {
				*(table_types[i].ptr) = table;
				if (table_types[i].name)
					pr_cont(" %s=0x%lx ",
						table_types[i].name, table);
				return 1;
+37 −0
Original line number Diff line number Diff line
@@ -26,6 +26,43 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
	return EFI_SUCCESS;
}

static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;

struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg)
{
	struct screen_info *si;
	efi_status_t status;

	/*
	 * Unlike on arm64, where we can directly fill out the screen_info
	 * structure from the stub, we need to allocate a buffer to hold
	 * its contents while we hand over to the kernel proper from the
	 * decompressor.
	 */
	status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
				sizeof(*si), (void **)&si);

	if (status != EFI_SUCCESS)
		return NULL;

	status = efi_call_early(install_configuration_table,
				&screen_info_guid, si);
	if (status == EFI_SUCCESS)
		return si;

	efi_call_early(free_pool, si);
	return NULL;
}

void free_screen_info(efi_system_table_t *sys_table_arg, struct screen_info *si)
{
	if (!si)
		return;

	efi_call_early(install_configuration_table, &screen_info_guid, NULL);
	efi_call_early(free_pool, si);
}

efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
				 unsigned long *image_addr,
				 unsigned long *image_size,
Loading