0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/efi.h>
0011 #include <asm/efi.h>
0012 #include <asm/memory.h>
0013 #include <asm/sections.h>
0014 #include <asm/sysreg.h>
0015
0016 #include "efistub.h"
0017
0018 efi_status_t check_platform_features(void)
0019 {
0020 u64 tg;
0021
0022
0023 if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
0024 return EFI_SUCCESS;
0025
0026 tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf;
0027 if (tg < ID_AA64MMFR0_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_TGRAN_SUPPORTED_MAX) {
0028 if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
0029 efi_err("This 64 KB granular kernel is not supported by your CPU\n");
0030 else
0031 efi_err("This 16 KB granular kernel is not supported by your CPU\n");
0032 return EFI_UNSUPPORTED;
0033 }
0034 return EFI_SUCCESS;
0035 }
0036
0037
0038
0039
0040
0041
0042
0043 static bool check_image_region(u64 base, u64 size)
0044 {
0045 unsigned long map_size, desc_size, buff_size;
0046 efi_memory_desc_t *memory_map;
0047 struct efi_boot_memmap map;
0048 efi_status_t status;
0049 bool ret = false;
0050 int map_offset;
0051
0052 map.map = &memory_map;
0053 map.map_size = &map_size;
0054 map.desc_size = &desc_size;
0055 map.desc_ver = NULL;
0056 map.key_ptr = NULL;
0057 map.buff_size = &buff_size;
0058
0059 status = efi_get_memory_map(&map);
0060 if (status != EFI_SUCCESS)
0061 return false;
0062
0063 for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
0064 efi_memory_desc_t *md = (void *)memory_map + map_offset;
0065 u64 end = md->phys_addr + md->num_pages * EFI_PAGE_SIZE;
0066
0067
0068
0069
0070
0071 if (base >= md->phys_addr && base < end) {
0072 ret = (base + size) <= end;
0073 break;
0074 }
0075 }
0076
0077 efi_bs_call(free_pool, memory_map);
0078
0079 return ret;
0080 }
0081
0082 efi_status_t handle_kernel_image(unsigned long *image_addr,
0083 unsigned long *image_size,
0084 unsigned long *reserve_addr,
0085 unsigned long *reserve_size,
0086 efi_loaded_image_t *image,
0087 efi_handle_t image_handle)
0088 {
0089 efi_status_t status;
0090 unsigned long kernel_size, kernel_memsize = 0;
0091 u32 phys_seed = 0;
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 u64 min_kimg_align = efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
0102
0103 if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
0104 efi_guid_t li_fixed_proto = LINUX_EFI_LOADED_IMAGE_FIXED_GUID;
0105 void *p;
0106
0107 if (efi_nokaslr) {
0108 efi_info("KASLR disabled on kernel command line\n");
0109 } else if (efi_bs_call(handle_protocol, image_handle,
0110 &li_fixed_proto, &p) == EFI_SUCCESS) {
0111 efi_info("Image placement fixed by loader\n");
0112 } else {
0113 status = efi_get_random_bytes(sizeof(phys_seed),
0114 (u8 *)&phys_seed);
0115 if (status == EFI_NOT_FOUND) {
0116 efi_info("EFI_RNG_PROTOCOL unavailable\n");
0117 efi_nokaslr = true;
0118 } else if (status != EFI_SUCCESS) {
0119 efi_err("efi_get_random_bytes() failed (0x%lx)\n",
0120 status);
0121 efi_nokaslr = true;
0122 }
0123 }
0124 }
0125
0126 if (image->image_base != _text)
0127 efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
0128
0129 if (!IS_ALIGNED((u64)_text, SEGMENT_ALIGN))
0130 efi_err("FIRMWARE BUG: kernel image not aligned on %dk boundary\n",
0131 SEGMENT_ALIGN >> 10);
0132
0133 kernel_size = _edata - _text;
0134 kernel_memsize = kernel_size + (_end - _edata);
0135 *reserve_size = kernel_memsize;
0136
0137 if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) {
0138
0139
0140
0141
0142 status = efi_random_alloc(*reserve_size, min_kimg_align,
0143 reserve_addr, phys_seed);
0144 if (status != EFI_SUCCESS)
0145 efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
0146 } else {
0147 status = EFI_OUT_OF_RESOURCES;
0148 }
0149
0150 if (status != EFI_SUCCESS) {
0151 if (!check_image_region((u64)_text, kernel_memsize)) {
0152 efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");
0153 } else if (IS_ALIGNED((u64)_text, min_kimg_align)) {
0154
0155
0156
0157
0158 *image_addr = (u64)_text;
0159 *reserve_size = 0;
0160 return EFI_SUCCESS;
0161 }
0162
0163 status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
0164 ULONG_MAX, min_kimg_align);
0165
0166 if (status != EFI_SUCCESS) {
0167 efi_err("Failed to relocate kernel\n");
0168 *reserve_size = 0;
0169 return status;
0170 }
0171 }
0172
0173 *image_addr = *reserve_addr;
0174 memcpy((void *)*image_addr, _text, kernel_size);
0175
0176 return EFI_SUCCESS;
0177 }