Merge remote-tracking branch 'lsk/v3.10/topic/gator' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / arch / x86 / boot / compressed / eboot.c
index 851fd4249603328b97acc2ed048dc6f1f894d4b0..17177e80d466779db6418be524c4c61e9b30d214 100644 (file)
@@ -865,6 +865,9 @@ fail:
  * Because the x86 boot code expects to be passed a boot_params we
  * need to create one ourselves (usually the bootloader would create
  * one for us).
+ *
+ * The caller is responsible for filling out ->code32_start in the
+ * returned boot_params.
  */
 struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
 {
@@ -923,8 +926,6 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
        hdr->vid_mode = 0xffff;
        hdr->boot_flag = 0xAA55;
 
-       hdr->code32_start = (__u64)(unsigned long)image->image_base;
-
        hdr->type_of_loader = 0x21;
 
        /* Convert unicode cmdline to ascii */
@@ -968,18 +969,20 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
        efi_memory_desc_t *mem_map;
        efi_status_t status;
        __u32 desc_version;
+       bool called_exit = false;
        u8 nr_entries;
        int i;
 
        size = sizeof(*mem_map) * 32;
 
 again:
-       size += sizeof(*mem_map);
+       size += sizeof(*mem_map) * 2;
        _size = size;
        status = efi_low_alloc(sys_table, size, 1, (unsigned long *)&mem_map);
        if (status != EFI_SUCCESS)
                return status;
 
+get_map:
        status = efi_call_phys5(sys_table->boottime->get_memory_map, &size,
                                mem_map, &key, &desc_size, &desc_version);
        if (status == EFI_BUFFER_TOO_SMALL) {
@@ -1005,8 +1008,20 @@ again:
        /* Might as well exit boot services now */
        status = efi_call_phys2(sys_table->boottime->exit_boot_services,
                                handle, key);
-       if (status != EFI_SUCCESS)
-               goto free_mem_map;
+       if (status != EFI_SUCCESS) {
+               /*
+                * ExitBootServices() will fail if any of the event
+                * handlers change the memory map. In which case, we
+                * must be prepared to retry, but only once so that
+                * we're guaranteed to exit on repeated failures instead
+                * of spinning forever.
+                */
+               if (called_exit)
+                       goto free_mem_map;
+
+               called_exit = true;
+               goto get_map;
+       }
 
        /* Historic? */
        boot_params->alt_mem_k = 32 * 1024;