1 /* 2 * Copyright (C) 2013 Linaro Ltd; <roy.franz@linaro.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 */ 9 #include <linux/efi.h> 10 #include <asm/efi.h> 11 12 efi_status_t handle_kernel_image(efi_system_table_t *sys_table, 13 unsigned long *image_addr, 14 unsigned long *image_size, 15 unsigned long *reserve_addr, 16 unsigned long *reserve_size, 17 unsigned long dram_base, 18 efi_loaded_image_t *image) 19 { 20 unsigned long nr_pages; 21 efi_status_t status; 22 /* Use alloc_addr to tranlsate between types */ 23 efi_physical_addr_t alloc_addr; 24 25 /* 26 * Verify that the DRAM base address is compatible with the ARM 27 * boot protocol, which determines the base of DRAM by masking 28 * off the low 27 bits of the address at which the zImage is 29 * loaded. These assumptions are made by the decompressor, 30 * before any memory map is available. 31 */ 32 dram_base = round_up(dram_base, SZ_128M); 33 34 /* 35 * Reserve memory for the uncompressed kernel image. This is 36 * all that prevents any future allocations from conflicting 37 * with the kernel. Since we can't tell from the compressed 38 * image how much DRAM the kernel actually uses (due to BSS 39 * size uncertainty) we allocate the maximum possible size. 40 * Do this very early, as prints can cause memory allocations 41 * that may conflict with this. 42 */ 43 alloc_addr = dram_base; 44 *reserve_size = MAX_UNCOMP_KERNEL_SIZE; 45 nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; 46 status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS, 47 EFI_LOADER_DATA, 48 nr_pages, &alloc_addr); 49 if (status != EFI_SUCCESS) { 50 *reserve_size = 0; 51 pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n"); 52 return status; 53 } 54 *reserve_addr = alloc_addr; 55 56 /* 57 * Relocate the zImage, so that it appears in the lowest 128 MB 58 * memory window. 59 */ 60 *image_size = image->image_size; 61 status = efi_relocate_kernel(sys_table, image_addr, *image_size, 62 *image_size, 63 dram_base + MAX_UNCOMP_KERNEL_SIZE, 0); 64 if (status != EFI_SUCCESS) { 65 pr_efi_err(sys_table, "Failed to relocate kernel.\n"); 66 efi_free(sys_table, *reserve_size, *reserve_addr); 67 *reserve_size = 0; 68 return status; 69 } 70 71 /* 72 * Check to see if we were able to allocate memory low enough 73 * in memory. The kernel determines the base of DRAM from the 74 * address at which the zImage is loaded. 75 */ 76 if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) { 77 pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n"); 78 efi_free(sys_table, *reserve_size, *reserve_addr); 79 *reserve_size = 0; 80 efi_free(sys_table, *image_size, *image_addr); 81 *image_size = 0; 82 return EFI_LOAD_ERROR; 83 } 84 return EFI_SUCCESS; 85 } 86