Merge tag 'signed-efi-next' of git://github.com/agraf/u-boot
[platform/kernel/u-boot.git] / lib / efi_loader / efi_image_loader.c
index 574b204..d4c62e6 100644 (file)
@@ -26,7 +26,7 @@ efi_status_t EFIAPI efi_return_handle(void *handle, efi_guid_t *protocol,
        return EFI_SUCCESS;
 }
 
-static void efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
+static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
                        unsigned long rel_size, void *efi_reloc)
 {
        const IMAGE_BASE_RELOCATION *end;
@@ -37,7 +37,7 @@ static void efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
                const uint16_t *relocs = (const uint16_t *)(rel + 1);
                i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t);
                while (i--) {
-                       uint16_t offset = (*relocs & 0xfff) +
+                       uint32_t offset = (uint32_t)(*relocs & 0xfff) +
                                          rel->VirtualAddress;
                        int type = *relocs >> EFI_PAGE_SHIFT;
                        unsigned long delta = (unsigned long)efi_reloc;
@@ -63,11 +63,13 @@ static void efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
                        default:
                                printf("Unknown Relocation off %x type %x\n",
                                       offset, type);
+                               return EFI_LOAD_ERROR;
                        }
                        relocs++;
                }
                rel = (const IMAGE_BASE_RELOCATION *)relocs;
        }
+       return EFI_SUCCESS;
 }
 
 void __weak invalidate_icache_all(void)
@@ -171,10 +173,15 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
        }
 
        /* Run through relocations */
-       efi_loader_relocate(rel, rel_size, efi_reloc);
+       if (efi_loader_relocate(rel, rel_size, efi_reloc) != EFI_SUCCESS) {
+               efi_free_pages((uintptr_t) efi_reloc,
+                              (virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT);
+               return NULL;
+       }
 
        /* Flush cache */
-       flush_cache((ulong)efi_reloc, virt_size);
+       flush_cache((ulong)efi_reloc,
+                   ALIGN(virt_size, CONFIG_SYS_CACHELINE_SIZE));
        invalidate_icache_all();
 
        /* Populate the loaded image interface bits */