diff options
Diffstat (limited to 'drivers/firmware/efi/arm-init.c')
| -rw-r--r-- | drivers/firmware/efi/arm-init.c | 94 | 
1 files changed, 79 insertions, 15 deletions
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index aa1f743152a2..a850cbc48d8d 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -11,17 +11,19 @@   *   */ +#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/platform_device.h> +#include <linux/screen_info.h>  #include <asm/efi.h> -struct efi_memory_map memmap; -  u64 efi_system_table;  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)  {  	efi_memory_desc_t *md; -	for_each_efi_memory_desc(&memmap, md) { +	for_each_efi_memory_desc(md) {  		if (!(md->attribute & EFI_MEMORY_RUNTIME))  			continue;  		if (md->virt_addr == 0) @@ -53,6 +55,36 @@ 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; +	} + +	if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI && +	    memblock_is_map_memory(screen_info.lfb_base)) +		memblock_mark_nomap(screen_info.lfb_base, screen_info.lfb_size); +} +  static int __init uefi_init(void)  {  	efi_char16_t *c16; @@ -85,6 +117,8 @@ static int __init uefi_init(void)  			efi.systab->hdr.revision >> 16,  			efi.systab->hdr.revision & 0xffff); +	efi.runtime_version = efi.systab->hdr.revision; +  	/* Show what we know for posterity */  	c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor),  				sizeof(vendor) * sizeof(efi_char16_t)); @@ -108,7 +142,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: @@ -143,7 +178,15 @@ static __init void reserve_regions(void)  	if (efi_enabled(EFI_DBG))  		pr_info("Processing EFI memory map:\n"); -	for_each_efi_memory_desc(&memmap, md) { +	/* +	 * Discard memblocks discovered so far: if there are any at this +	 * point, they originate from memory nodes in the DT, and UEFI +	 * uses its own memory map instead. +	 */ +	memblock_dump_all(); +	memblock_remove(0, (phys_addr_t)ULLONG_MAX); + +	for_each_efi_memory_desc(md) {  		paddr = md->phys_addr;  		npages = md->num_pages; @@ -184,9 +227,9 @@ void __init efi_init(void)  	efi_system_table = params.system_table; -	memmap.phys_map = params.mmap; -	memmap.map = early_memremap_ro(params.mmap, params.mmap_size); -	if (memmap.map == NULL) { +	efi.memmap.phys_map = params.mmap; +	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size); +	if (efi.memmap.map == NULL) {  		/*  		* If we are booting via UEFI, the UEFI memory map is the only  		* description of memory we have, so there is little point in @@ -194,16 +237,37 @@ void __init efi_init(void)  		*/  		panic("Unable to map EFI memory map.\n");  	} -	memmap.map_end = memmap.map + params.mmap_size; -	memmap.desc_size = params.desc_size; -	memmap.desc_version = params.desc_ver; +	efi.memmap.map_end = efi.memmap.map + params.mmap_size; +	efi.memmap.desc_size = params.desc_size; +	efi.memmap.desc_version = params.desc_ver; + +	WARN(efi.memmap.desc_version != 1, +	     "Unexpected EFI_MEMORY_DESCRIPTOR version %ld", +	      efi.memmap.desc_version);  	if (uefi_init() < 0)  		return;  	reserve_regions(); -	early_memunmap(memmap.map, params.mmap_size); -	memblock_mark_nomap(params.mmap & PAGE_MASK, -			    PAGE_ALIGN(params.mmap_size + -				       (params.mmap & ~PAGE_MASK))); +	efi_memattr_init(); +	early_memunmap(efi.memmap.map, params.mmap_size); + +	memblock_reserve(params.mmap & PAGE_MASK, +			 PAGE_ALIGN(params.mmap_size + +				    (params.mmap & ~PAGE_MASK))); + +	init_screen_info(); +} + +static int __init register_gop_device(void) +{ +	void *pd; + +	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) +		return 0; + +	pd = platform_device_register_data(NULL, "efi-framebuffer", 0, +					   &screen_info, sizeof(screen_info)); +	return PTR_ERR_OR_ZERO(pd);  } +subsys_initcall(register_gop_device);  |