Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64...
[cascardo/linux.git] / drivers / firmware / efi / arm-init.c
index ca708fb..a850cbc 100644 (file)
  *
  */
 
+#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:
@@ -151,7 +186,7 @@ static __init void reserve_regions(void)
        memblock_dump_all();
        memblock_remove(0, (phys_addr_t)ULLONG_MAX);
 
-       for_each_efi_memory_desc(&memmap, md) {
+       for_each_efi_memory_desc(md) {
                paddr = md->phys_addr;
                npages = md->num_pages;
 
@@ -192,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
@@ -202,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);