[PATCH] x86: fix EFI memory map parsing
authorMatt Tolentino <metolent@snoqualmie.dp.intel.com>
Sat, 3 Sep 2005 22:56:27 +0000 (15:56 -0700)
committerLinus Torvalds <torvalds@evo.osdl.org>
Mon, 5 Sep 2005 07:06:09 +0000 (00:06 -0700)
The memory descriptors that comprise the EFI memory map are not fixed in
stone such that the size could change in the future.  This uses the memory
descriptor size obtained from EFI to iterate over the memory map entries
during boot.  This enables the removal of an x86 specific pad (and ifdef)
in the EFI header.  I also couldn't stomach the broken up nature of the
function to put EFI runtime calls into virtual mode any longer so I fixed
that up a bit as well.

For reference, this patch only impacts x86.

Signed-off-by: Matt Tolentino <matthew.e.tolentino@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/kernel/efi.c
arch/i386/kernel/setup.c
arch/i386/mm/init.c
include/asm-i386/setup.h
include/linux/efi.h

index 385883ea8c199d1008d0db050e1c71ec32ce64ec..850648ae8305c17249307985790af915157f94e2 100644 (file)
@@ -233,22 +233,23 @@ void __init efi_map_memmap(void)
 {
        memmap.map = NULL;
 
-       memmap.map = (efi_memory_desc_t *)
-               bt_ioremap((unsigned long) memmap.phys_map,
-                       (memmap.nr_map * sizeof(efi_memory_desc_t)));
-
+       memmap.map = bt_ioremap((unsigned long) memmap.phys_map,
+                       (memmap.nr_map * memmap.desc_size));
        if (memmap.map == NULL)
                printk(KERN_ERR PFX "Could not remap the EFI memmap!\n");
+
+       memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);
 }
 
 #if EFI_DEBUG
 static void __init print_efi_memmap(void)
 {
        efi_memory_desc_t *md;
+       void *p;
        int i;
 
-       for (i = 0; i < memmap.nr_map; i++) {
-               md = &memmap.map[i];
+       for (p = memmap.map, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) {
+               md = p;
                printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, "
                        "range=[0x%016llx-0x%016llx) (%lluMB)\n",
                        i, md->type, md->attribute, md->phys_addr,
@@ -271,10 +272,10 @@ void efi_memmap_walk(efi_freemem_callback_t callback, void *arg)
        } prev, curr;
        efi_memory_desc_t *md;
        unsigned long start, end;
-       int i;
+       void *p;
 
-       for (i = 0; i < memmap.nr_map; i++) {
-               md = &memmap.map[i];
+       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+               md = p;
 
                if ((md->num_pages == 0) || (!is_available_memory(md)))
                        continue;
@@ -325,6 +326,7 @@ void __init efi_init(void)
        memmap.phys_map = EFI_MEMMAP;
        memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE;
        memmap.desc_version = EFI_MEMDESC_VERSION;
+       memmap.desc_size = EFI_MEMDESC_SIZE;
 
        efi.systab = (efi_system_table_t *)
                boot_ioremap((unsigned long) efi_phys.systab,
@@ -428,22 +430,30 @@ void __init efi_init(void)
                printk(KERN_ERR PFX "Could not map the runtime service table!\n");
 
        /* Map the EFI memory map for use until paging_init() */
-
-       memmap.map = (efi_memory_desc_t *)
-               boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
-
+       memmap.map = boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
        if (memmap.map == NULL)
                printk(KERN_ERR PFX "Could not map the EFI memory map!\n");
 
-       if (EFI_MEMDESC_SIZE != sizeof(efi_memory_desc_t)) {
-               printk(KERN_WARNING PFX "Warning! Kernel-defined memdesc doesn't "
-                          "match the one from EFI!\n");
-       }
+       memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);
+
 #if EFI_DEBUG
        print_efi_memmap();
 #endif
 }
 
+static inline void __init check_range_for_systab(efi_memory_desc_t *md)
+{
+       if (((unsigned long)md->phys_addr <= (unsigned long)efi_phys.systab) &&
+               ((unsigned long)efi_phys.systab < md->phys_addr +
+               ((unsigned long)md->num_pages << EFI_PAGE_SHIFT))) {
+               unsigned long addr;
+
+               addr = md->virt_addr - md->phys_addr +
+                       (unsigned long)efi_phys.systab;
+               efi.systab = (efi_system_table_t *)addr;
+       }
+}
+
 /*
  * This function will switch the EFI runtime services to virtual mode.
  * Essentially, look through the EFI memmap and map every region that
@@ -457,43 +467,32 @@ void __init efi_enter_virtual_mode(void)
 {
        efi_memory_desc_t *md;
        efi_status_t status;
-       int i;
+       void *p;
 
        efi.systab = NULL;
 
-       for (i = 0; i < memmap.nr_map; i++) {
-               md = &memmap.map[i];
+       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+               md = p;
 
-               if (md->attribute & EFI_MEMORY_RUNTIME) {
-                       md->virt_addr =
-                               (unsigned long)ioremap(md->phys_addr,
-                                       md->num_pages << EFI_PAGE_SHIFT);
-                       if (!(unsigned long)md->virt_addr) {
-                               printk(KERN_ERR PFX "ioremap of 0x%lX failed\n",
-                                       (unsigned long)md->phys_addr);
-                       }
+               if (!(md->attribute & EFI_MEMORY_RUNTIME))
+                       continue;
 
-                       if (((unsigned long)md->phys_addr <=
-                                       (unsigned long)efi_phys.systab) &&
-                               ((unsigned long)efi_phys.systab <
-                                       md->phys_addr +
-                                       ((unsigned long)md->num_pages <<
-                                               EFI_PAGE_SHIFT))) {
-                               unsigned long addr;
-
-                               addr = md->virt_addr - md->phys_addr +
-                                               (unsigned long)efi_phys.systab;
-                               efi.systab = (efi_system_table_t *)addr;
-                       }
+               md->virt_addr = (unsigned long)ioremap(md->phys_addr,
+                       md->num_pages << EFI_PAGE_SHIFT);
+               if (!(unsigned long)md->virt_addr) {
+                       printk(KERN_ERR PFX "ioremap of 0x%lX failed\n",
+                               (unsigned long)md->phys_addr);
                }
+               /* update the virtual address of the EFI system table */
+               check_range_for_systab(md);
        }
 
        if (!efi.systab)
                BUG();
 
        status = phys_efi_set_virtual_address_map(
-                       sizeof(efi_memory_desc_t) * memmap.nr_map,
-                       sizeof(efi_memory_desc_t),
+                       memmap.desc_size * memmap.nr_map,
+                       memmap.desc_size,
                        memmap.desc_version,
                        memmap.phys_map);
 
@@ -533,10 +532,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
 {
        struct resource *res;
        efi_memory_desc_t *md;
-       int i;
+       void *p;
 
-       for (i = 0; i < memmap.nr_map; i++) {
-               md = &memmap.map[i];
+       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+               md = p;
 
                if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
                    0x100000000ULL)
@@ -613,10 +612,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
 u32 efi_mem_type(unsigned long phys_addr)
 {
        efi_memory_desc_t *md;
-       int i;
+       void *p;
 
-       for (i = 0; i < memmap.nr_map; i++) {
-               md = &memmap.map[i];
+       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+               md = p;
                if ((md->phys_addr <= phys_addr) && (phys_addr <
                        (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
                        return md->type;
@@ -627,10 +626,10 @@ u32 efi_mem_type(unsigned long phys_addr)
 u64 efi_mem_attributes(unsigned long phys_addr)
 {
        efi_memory_desc_t *md;
-       int i;
+       void *p;
 
-       for (i = 0; i < memmap.nr_map; i++) {
-               md = &memmap.map[i];
+       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+               md = p;
                if ((md->phys_addr <= phys_addr) && (phys_addr <
                        (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
                        return md->attribute;
index af4de58cab543362bb19d8e31c85006cd7c17e9d..9adbf710ec8deb648ee72314c514296e25fc6566 100644 (file)
@@ -370,12 +370,16 @@ static void __init limit_regions(unsigned long long size)
        int i;
 
        if (efi_enabled) {
-               for (i = 0; i < memmap.nr_map; i++) {
-                       current_addr = memmap.map[i].phys_addr +
-                                      (memmap.map[i].num_pages << 12);
-                       if (memmap.map[i].type == EFI_CONVENTIONAL_MEMORY) {
+               efi_memory_desc_t *md;
+               void *p;
+
+               for (p = memmap.map, i = 0; p < memmap.map_end;
+                       p += memmap.desc_size, i++) {
+                       md = p;
+                       current_addr = md->phys_addr + (md->num_pages << 12);
+                       if (md->type == EFI_CONVENTIONAL_MEMORY) {
                                if (current_addr >= size) {
-                                       memmap.map[i].num_pages -=
+                                       md->num_pages -=
                                                (((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT);
                                        memmap.nr_map = i + 1;
                                        return;
index 12216b52e28bf9b50060c509060fea3057fb298e..d8b23ab76533744510e49a848cdfa7249b0666bd 100644 (file)
@@ -198,9 +198,10 @@ int page_is_ram(unsigned long pagenr)
 
        if (efi_enabled) {
                efi_memory_desc_t *md;
+               void *p;
 
-               for (i = 0; i < memmap.nr_map; i++) {
-                       md = &memmap.map[i];
+               for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+                       md = p;
                        if (!is_available_memory(md))
                                continue;
                        addr = (md->phys_addr+PAGE_SIZE-1) >> PAGE_SHIFT;
index 7a32184d54bf414522d10976d9a7a7a0b4d47a1b..826a8ca50ac801dd6960e2396d9a55e02e1ba2a4 100644 (file)
@@ -44,7 +44,7 @@ extern unsigned char boot_params[PARAM_SIZE];
 #define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4)))
 #define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8)))
 #define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc)))
-#define EFI_MEMMAP ((efi_memory_desc_t *) *((unsigned long *)(PARAM+0x1d0)))
+#define EFI_MEMMAP ((void *) *((unsigned long *)(PARAM+0x1d0)))
 #define EFI_MEMMAP_SIZE (*((unsigned long *) (PARAM+0x1d4)))
 #define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
 #define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
index 73781ec165b40a96e92f98c6701daa27393ea3f3..c7c5dd3161820caca202022ca92acdf2b397cd9c 100644 (file)
@@ -91,11 +91,6 @@ typedef      struct {
 
 #define EFI_PAGE_SHIFT         12
 
-/*
- * For current x86 implementations of EFI, there is
- * additional padding in the mem descriptors.  This is not
- * the case in ia64.  Need to have this fixed in the f/w.
- */
 typedef struct {
        u32 type;
        u32 pad;
@@ -103,9 +98,6 @@ typedef struct {
        u64 virt_addr;
        u64 num_pages;
        u64 attribute;
-#if defined (__i386__)
-       u64 pad1;
-#endif
 } efi_memory_desc_t;
 
 typedef int (*efi_freemem_callback_t) (unsigned long start, unsigned long end, void *arg);
@@ -240,10 +232,12 @@ typedef struct {
 } efi_system_table_t;
 
 struct efi_memory_map {
-       efi_memory_desc_t *phys_map;
-       efi_memory_desc_t *map;
+       void *phys_map;
+       void *map;
+       void *map_end;
        int nr_map;
        unsigned long desc_version;
+       unsigned long desc_size;
 };
 
 /*