*/
 static bool check_image_region(u64 base, u64 size)
 {
-       unsigned long map_size, desc_size, buff_size;
-       efi_memory_desc_t *memory_map;
-       struct efi_boot_memmap map;
+       struct efi_boot_memmap *map;
        efi_status_t status;
        bool ret = false;
        int map_offset;
 
-       map.map =       &memory_map;
-       map.map_size =  &map_size;
-       map.desc_size = &desc_size;
-       map.desc_ver =  NULL;
-       map.key_ptr =   NULL;
-       map.buff_size = &buff_size;
-
        status = efi_get_memory_map(&map);
        if (status != EFI_SUCCESS)
                return false;
 
-       for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
-               efi_memory_desc_t *md = (void *)memory_map + map_offset;
+       for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) {
+               efi_memory_desc_t *md = (void *)map->map + map_offset;
                u64 end = md->phys_addr + md->num_pages * EFI_PAGE_SIZE;
 
                /*
                }
        }
 
-       efi_bs_call(free_pool, memory_map);
+       efi_bs_call(free_pool, map);
 
        return ret;
 }
 
 /**
  * efi_exit_boot_services() - Exit boot services
  * @handle:    handle of the exiting image
- * @map:       pointer to receive the memory map
  * @priv:      argument to be passed to @priv_func
  * @priv_func: function to process the memory map before exiting boot services
  *
  *
  * Return:     status code
  */
-efi_status_t efi_exit_boot_services(void *handle,
-                                   struct efi_boot_memmap *map,
-                                   void *priv,
+efi_status_t efi_exit_boot_services(void *handle, void *priv,
                                    efi_exit_boot_map_processing priv_func)
 {
+       struct efi_boot_memmap *map;
        efi_status_t status;
 
-       status = efi_get_memory_map(map);
+       status = efi_get_memory_map(&map);
 
        if (status != EFI_SUCCESS)
                goto fail;
        if (efi_disable_pci_dma)
                efi_pci_disable_bridge_busmaster();
 
-       status = efi_bs_call(exit_boot_services, handle, *map->key_ptr);
+       status = efi_bs_call(exit_boot_services, handle, map->map_key);
 
        if (status == EFI_INVALID_PARAMETER) {
                /*
                 * buffer should account for any changes in the map so the call
                 * to get_memory_map() is expected to succeed here.
                 */
-               *map->map_size = *map->buff_size;
+               map->map_size = map->buff_size;
                status = efi_bs_call(get_memory_map,
-                                    map->map_size,
-                                    *map->map,
-                                    map->key_ptr,
-                                    map->desc_size,
-                                    map->desc_ver);
+                                    &map->map_size,
+                                    &map->map,
+                                    &map->map_key,
+                                    &map->desc_size,
+                                    &map->desc_ver);
 
                /* exit_boot_services() was called, thus cannot free */
                if (status != EFI_SUCCESS)
                if (status != EFI_SUCCESS)
                        goto fail;
 
-               status = efi_bs_call(exit_boot_services, handle, *map->key_ptr);
+               status = efi_bs_call(exit_boot_services, handle, map->map_key);
        }
 
        /* exit_boot_services() was called, thus cannot free */
        return EFI_SUCCESS;
 
 free_map:
-       efi_bs_call(free_pool, *map->map);
+       efi_bs_call(free_pool, map);
 fail:
        return status;
 }
 
  */
 #define EFI_MMAP_NR_SLACK_SLOTS        8
 
-struct efi_boot_memmap {
-       efi_memory_desc_t       **map;
-       unsigned long           *map_size;
-       unsigned long           *desc_size;
-       u32                     *desc_ver;
-       unsigned long           *key_ptr;
-       unsigned long           *buff_size;
-};
-
 typedef struct efi_generic_dev_path efi_device_path_protocol_t;
 
 typedef void *efi_event_t;
        struct efi_boot_memmap *map,
        void *priv);
 
-efi_status_t efi_exit_boot_services(void *handle,
-                                   struct efi_boot_memmap *map,
-                                   void *priv,
+efi_status_t efi_exit_boot_services(void *handle, void *priv,
                                    efi_exit_boot_map_processing priv_func);
 
 efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
 
 char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len);
 
-efi_status_t efi_get_memory_map(struct efi_boot_memmap *map);
+efi_status_t efi_get_memory_map(struct efi_boot_memmap **map);
 
 efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
                                unsigned long max);
 
        if (node < 0)
                return EFI_LOAD_ERROR;
 
-       fdt_val64 = cpu_to_fdt64((unsigned long)*map->map);
+       fdt_val64 = cpu_to_fdt64((unsigned long)map->map);
 
        err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-start", fdt_val64);
        if (err)
                return EFI_LOAD_ERROR;
 
-       fdt_val32 = cpu_to_fdt32(*map->map_size);
+       fdt_val32 = cpu_to_fdt32(map->map_size);
 
        err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-size", fdt_val32);
        if (err)
                return EFI_LOAD_ERROR;
 
-       fdt_val32 = cpu_to_fdt32(*map->desc_size);
+       fdt_val32 = cpu_to_fdt32(map->desc_size);
 
        err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-size", fdt_val32);
        if (err)
                return EFI_LOAD_ERROR;
 
-       fdt_val32 = cpu_to_fdt32(*map->desc_ver);
+       fdt_val32 = cpu_to_fdt32(map->desc_ver);
 
        err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-ver", fdt_val32);
        if (err)
 }
 
 struct exit_boot_struct {
+       struct efi_boot_memmap  *boot_memmap;
        efi_memory_desc_t       *runtime_map;
        int                     runtime_entry_count;
        void                    *new_fdt_addr;
 };
 
-static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
-                                  void *priv)
+static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
 {
        struct exit_boot_struct *p = priv;
+
+       p->boot_memmap = map;
+
        /*
         * Update the memory map with virtual addresses. The function will also
         * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
         * entries so that we can pass it straight to SetVirtualAddressMap()
         */
-       efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
+       efi_get_virtmap(map->map, map->map_size, map->desc_size,
                        p->runtime_map, &p->runtime_entry_count);
 
        return update_fdt_memmap(p->new_fdt_addr, map);
                                            unsigned long fdt_addr,
                                            unsigned long fdt_size)
 {
-       unsigned long map_size, desc_size, buff_size;
+       unsigned long desc_size;
        u32 desc_ver;
-       unsigned long mmap_key;
-       efi_memory_desc_t *memory_map;
        efi_status_t status;
-       struct efi_boot_memmap map;
        struct exit_boot_struct priv;
 
-       map.map_size    = &map_size;
-       map.desc_size   = &desc_size;
-       map.desc_ver    = &desc_ver;
-       map.key_ptr     = &mmap_key;
-       map.buff_size   = &buff_size;
-
        if (!efi_novamap) {
                status = efi_alloc_virtmap(&priv.runtime_map, &desc_size,
                                           &desc_ver);
 
        efi_info("Exiting boot services...\n");
 
-       map.map = &memory_map;
        status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX);
        if (status != EFI_SUCCESS) {
                efi_err("Unable to allocate memory for new device tree.\n");
 
        priv.new_fdt_addr = (void *)*new_fdt_addr;
 
-       status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func);
+       status = efi_exit_boot_services(handle, &priv, exit_boot_func);
 
        if (status == EFI_SUCCESS) {
                efi_set_virtual_address_map_t *svam;
                 * incoming kernel but proceed normally otherwise.
                 */
                if (status != EFI_SUCCESS) {
+                       efi_memory_desc_t *p;
                        int l;
 
                        /*
                         * the incoming kernel that no virtual translation has
                         * been installed.
                         */
-                       for (l = 0; l < map_size; l += desc_size) {
-                               efi_memory_desc_t *p = (void *)memory_map + l;
+                       for (l = 0; l < priv.boot_memmap->map_size;
+                            l += priv.boot_memmap->desc_size) {
+                               p = (void *)priv.boot_memmap->map + l;
 
                                if (p->attribute & EFI_MEMORY_RUNTIME)
                                        p->virt_addr = 0;
 
 
 #include "efistub.h"
 
-static inline bool mmap_has_headroom(unsigned long buff_size,
-                                    unsigned long map_size,
-                                    unsigned long desc_size)
-{
-       unsigned long slack = buff_size - map_size;
-
-       return slack / desc_size >= EFI_MMAP_NR_SLACK_SLOTS;
-}
-
 /**
  * efi_get_memory_map() - get memory map
- * @map:       on return pointer to memory map
+ * @map:               pointer to memory map pointer to which to assign the
+ *                     newly allocated memory map
  *
  * Retrieve the UEFI memory map. The allocated memory leaves room for
  * up to EFI_MMAP_NR_SLACK_SLOTS additional memory map entries.
  *
  * Return:     status code
  */
-efi_status_t efi_get_memory_map(struct efi_boot_memmap *map)
+efi_status_t efi_get_memory_map(struct efi_boot_memmap **map)
 {
-       efi_memory_desc_t *m = NULL;
+       struct efi_boot_memmap *m, tmp;
        efi_status_t status;
-       unsigned long key;
-       u32 desc_version;
+       unsigned long size;
 
-       *map->desc_size =       sizeof(*m);
-       *map->map_size =        *map->desc_size * 32;
-       *map->buff_size =       *map->map_size;
-again:
-       status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
-                            *map->map_size, (void **)&m);
+       tmp.map_size = 0;
+       status = efi_bs_call(get_memory_map, &tmp.map_size, NULL, &tmp.map_key,
+                            &tmp.desc_size, &tmp.desc_ver);
+       if (status != EFI_BUFFER_TOO_SMALL)
+               return EFI_LOAD_ERROR;
+
+       size = tmp.map_size + tmp.desc_size * EFI_MMAP_NR_SLACK_SLOTS;
+       status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(*m) + size,
+                            (void **)&m);
        if (status != EFI_SUCCESS)
-               goto fail;
+               return status;
 
-       *map->desc_size = 0;
-       key = 0;
-       status = efi_bs_call(get_memory_map, map->map_size, m,
-                            &key, map->desc_size, &desc_version);
-       if (status == EFI_BUFFER_TOO_SMALL ||
-           !mmap_has_headroom(*map->buff_size, *map->map_size,
-                              *map->desc_size)) {
-               efi_bs_call(free_pool, m);
-               /*
-                * Make sure there is some entries of headroom so that the
-                * buffer can be reused for a new map after allocations are
-                * no longer permitted.  Its unlikely that the map will grow to
-                * exceed this headroom once we are ready to trigger
-                * ExitBootServices()
-                */
-               *map->map_size += *map->desc_size * EFI_MMAP_NR_SLACK_SLOTS;
-               *map->buff_size = *map->map_size;
-               goto again;
-       }
+       m->buff_size = m->map_size = size;
+       status = efi_bs_call(get_memory_map, &m->map_size, m->map, &m->map_key,
+                            &m->desc_size, &m->desc_ver);
+       if (status != EFI_SUCCESS)
+               goto free_map;
 
-       if (status == EFI_SUCCESS) {
-               if (map->key_ptr)
-                       *map->key_ptr = key;
-               if (map->desc_ver)
-                       *map->desc_ver = desc_version;
-       } else {
-               efi_bs_call(free_pool, m);
-       }
+       *map = m;
+       return EFI_SUCCESS;
 
-fail:
-       *map->map = m;
+free_map:
+       efi_bs_call(free_pool, m);
        return status;
 }
 
 
                              unsigned long *addr,
                              unsigned long random_seed)
 {
-       unsigned long map_size, desc_size, total_slots = 0, target_slot;
+       unsigned long total_slots = 0, target_slot;
        unsigned long total_mirrored_slots = 0;
-       unsigned long buff_size;
+       struct efi_boot_memmap *map;
        efi_status_t status;
-       efi_memory_desc_t *memory_map;
        int map_offset;
-       struct efi_boot_memmap map;
-
-       map.map =       &memory_map;
-       map.map_size =  &map_size;
-       map.desc_size = &desc_size;
-       map.desc_ver =  NULL;
-       map.key_ptr =   NULL;
-       map.buff_size = &buff_size;
 
        status = efi_get_memory_map(&map);
        if (status != EFI_SUCCESS)
        size = round_up(size, EFI_ALLOC_ALIGN);
 
        /* count the suitable slots in each memory map entry */
-       for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
-               efi_memory_desc_t *md = (void *)memory_map + map_offset;
+       for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) {
+               efi_memory_desc_t *md = (void *)map->map + map_offset;
                unsigned long slots;
 
                slots = get_entry_num_slots(md, size, ilog2(align));
         * to calculate the randomly chosen address, and allocate it directly
         * using EFI_ALLOCATE_ADDRESS.
         */
-       for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
-               efi_memory_desc_t *md = (void *)memory_map + map_offset;
+       for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) {
+               efi_memory_desc_t *md = (void *)map->map + map_offset;
                efi_physical_addr_t target;
                unsigned long pages;
 
                break;
        }
 
-       efi_bs_call(free_pool, memory_map);
+       efi_bs_call(free_pool, map);
 
        return status;
 }
 
 efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
                                 unsigned long *addr, unsigned long min)
 {
-       unsigned long map_size, desc_size, buff_size;
-       efi_memory_desc_t *map;
+       struct efi_boot_memmap *map;
        efi_status_t status;
        unsigned long nr_pages;
        int i;
-       struct efi_boot_memmap boot_map;
 
-       boot_map.map            = ↦
-       boot_map.map_size       = &map_size;
-       boot_map.desc_size      = &desc_size;
-       boot_map.desc_ver       = NULL;
-       boot_map.key_ptr        = NULL;
-       boot_map.buff_size      = &buff_size;
-
-       status = efi_get_memory_map(&boot_map);
+       status = efi_get_memory_map(&map);
        if (status != EFI_SUCCESS)
                goto fail;
 
 
        size = round_up(size, EFI_ALLOC_ALIGN);
        nr_pages = size / EFI_PAGE_SIZE;
-       for (i = 0; i < map_size / desc_size; i++) {
+       for (i = 0; i < map->map_size / map->desc_size; i++) {
                efi_memory_desc_t *desc;
-               unsigned long m = (unsigned long)map;
+               unsigned long m = (unsigned long)map->map;
                u64 start, end;
 
-               desc = efi_early_memdesc_ptr(m, desc_size, i);
+               desc = efi_early_memdesc_ptr(m, map->desc_size, i);
 
                if (desc->type != EFI_CONVENTIONAL_MEMORY)
                        continue;
                }
        }
 
-       if (i == map_size / desc_size)
+       if (i == map->map_size / map->desc_size)
                status = EFI_NOT_FOUND;
 
        efi_bs_call(free_pool, map);
 
 
        efi_set_u64_split((unsigned long)efi_system_table,
                          &p->efi->efi_systab, &p->efi->efi_systab_hi);
-       p->efi->efi_memdesc_size        = *map->desc_size;
-       p->efi->efi_memdesc_version     = *map->desc_ver;
-       efi_set_u64_split((unsigned long)*map->map,
+       p->efi->efi_memdesc_size        = map->desc_size;
+       p->efi->efi_memdesc_version     = map->desc_ver;
+       efi_set_u64_split((unsigned long)map->map,
                          &p->efi->efi_memmap, &p->efi->efi_memmap_hi);
-       p->efi->efi_memmap_size         = *map->map_size;
+       p->efi->efi_memmap_size         = map->map_size;
 
        return EFI_SUCCESS;
 }
 
 static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
 {
-       unsigned long map_sz, key, desc_size, buff_size;
-       efi_memory_desc_t *mem_map;
        struct setup_data *e820ext = NULL;
        __u32 e820ext_size = 0;
        efi_status_t status;
-       __u32 desc_version;
-       struct efi_boot_memmap map;
        struct exit_boot_struct priv;
 
-       map.map                 = &mem_map;
-       map.map_size            = &map_sz;
-       map.desc_size           = &desc_size;
-       map.desc_ver            = &desc_version;
-       map.key_ptr             = &key;
-       map.buff_size           = &buff_size;
        priv.boot_params        = boot_params;
        priv.efi                = &boot_params->efi_info;
 
                return status;
 
        /* Might as well exit boot services now */
-       status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func);
+       status = efi_exit_boot_services(handle, &priv, exit_boot_func);
        if (status != EFI_SUCCESS)
                return status;
 
 
        efi_system_table_32_t mixed_mode;
 } efi_system_table_t;
 
+struct efi_boot_memmap {
+       unsigned long           map_size;
+       unsigned long           desc_size;
+       u32                     desc_ver;
+       unsigned long           map_key;
+       unsigned long           buff_size;
+       efi_memory_desc_t       map[];
+};
+
 /*
  * Architecture independent structure for describing a memory map for the
  * benefit of efi_memmap_init_early(), and for passing context between