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 check_platform_features(efi_system_table_t *sys_table_arg) 13 { 14 int block; 15 16 /* non-LPAE kernels can run anywhere */ 17 if (!IS_ENABLED(CONFIG_ARM_LPAE)) 18 return EFI_SUCCESS; 19 20 /* LPAE kernels need compatible hardware */ 21 block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0); 22 if (block < 5) { 23 pr_efi_err(sys_table_arg, "This LPAE kernel is not supported by your CPU\n"); 24 return EFI_UNSUPPORTED; 25 } 26 return EFI_SUCCESS; 27 } 28 29 static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID; 30 31 struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg) 32 { 33 struct screen_info *si; 34 efi_status_t status; 35 36 /* 37 * Unlike on arm64, where we can directly fill out the screen_info 38 * structure from the stub, we need to allocate a buffer to hold 39 * its contents while we hand over to the kernel proper from the 40 * decompressor. 41 */ 42 status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA, 43 sizeof(*si), (void **)&si); 44 45 if (status != EFI_SUCCESS) 46 return NULL; 47 48 status = efi_call_early(install_configuration_table, 49 &screen_info_guid, si); 50 if (status == EFI_SUCCESS) 51 return si; 52 53 efi_call_early(free_pool, si); 54 return NULL; 55 } 56 57 void free_screen_info(efi_system_table_t *sys_table_arg, struct screen_info *si) 58 { 59 if (!si) 60 return; 61 62 efi_call_early(install_configuration_table, &screen_info_guid, NULL); 63 efi_call_early(free_pool, si); 64 } 65 66 efi_status_t handle_kernel_image(efi_system_table_t *sys_table, 67 unsigned long *image_addr, 68 unsigned long *image_size, 69 unsigned long *reserve_addr, 70 unsigned long *reserve_size, 71 unsigned long dram_base, 72 efi_loaded_image_t *image) 73 { 74 unsigned long nr_pages; 75 efi_status_t status; 76 /* Use alloc_addr to tranlsate between types */ 77 efi_physical_addr_t alloc_addr; 78 79 /* 80 * Verify that the DRAM base address is compatible with the ARM 81 * boot protocol, which determines the base of DRAM by masking 82 * off the low 27 bits of the address at which the zImage is 83 * loaded. These assumptions are made by the decompressor, 84 * before any memory map is available. 85 */ 86 dram_base = round_up(dram_base, SZ_128M); 87 88 /* 89 * Reserve memory for the uncompressed kernel image. This is 90 * all that prevents any future allocations from conflicting 91 * with the kernel. Since we can't tell from the compressed 92 * image how much DRAM the kernel actually uses (due to BSS 93 * size uncertainty) we allocate the maximum possible size. 94 * Do this very early, as prints can cause memory allocations 95 * that may conflict with this. 96 */ 97 alloc_addr = dram_base; 98 *reserve_size = MAX_UNCOMP_KERNEL_SIZE; 99 nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; 100 status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS, 101 EFI_LOADER_DATA, 102 nr_pages, &alloc_addr); 103 if (status != EFI_SUCCESS) { 104 *reserve_size = 0; 105 pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n"); 106 return status; 107 } 108 *reserve_addr = alloc_addr; 109 110 /* 111 * Relocate the zImage, so that it appears in the lowest 128 MB 112 * memory window. 113 */ 114 *image_size = image->image_size; 115 status = efi_relocate_kernel(sys_table, image_addr, *image_size, 116 *image_size, 117 dram_base + MAX_UNCOMP_KERNEL_SIZE, 0); 118 if (status != EFI_SUCCESS) { 119 pr_efi_err(sys_table, "Failed to relocate kernel.\n"); 120 efi_free(sys_table, *reserve_size, *reserve_addr); 121 *reserve_size = 0; 122 return status; 123 } 124 125 /* 126 * Check to see if we were able to allocate memory low enough 127 * in memory. The kernel determines the base of DRAM from the 128 * address at which the zImage is loaded. 129 */ 130 if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) { 131 pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n"); 132 efi_free(sys_table, *reserve_size, *reserve_addr); 133 *reserve_size = 0; 134 efi_free(sys_table, *image_size, *image_addr); 135 *image_size = 0; 136 return EFI_LOAD_ERROR; 137 } 138 return EFI_SUCCESS; 139 } 140