1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Helper functions used by the EFI stub on multiple 4 * architectures. This should be #included by the EFI stub 5 * implementation files. 6 * 7 * Copyright 2011 Intel Corporation; author Matt Fleming 8 */ 9 10 #include <linux/efi.h> 11 #include <asm/efi.h> 12 13 #include "efistub.h" 14 15 #define MAX_FILENAME_SIZE 256 16 17 /* 18 * Some firmware implementations have problems reading files in one go. 19 * A read chunk size of 1MB seems to work for most platforms. 20 * 21 * Unfortunately, reading files in chunks triggers *other* bugs on some 22 * platforms, so we provide a way to disable this workaround, which can 23 * be done by passing "efi=nochunk" on the EFI boot stub command line. 24 * 25 * If you experience issues with initrd images being corrupt it's worth 26 * trying efi=nochunk, but chunking is enabled by default on x86 because 27 * there are far more machines that require the workaround than those that 28 * break with it enabled. 29 */ 30 #define EFI_READ_CHUNK_SIZE SZ_1M 31 32 struct finfo { 33 efi_file_info_t info; 34 efi_char16_t filename[MAX_FILENAME_SIZE]; 35 }; 36 37 static efi_status_t efi_open_file(efi_file_protocol_t *volume, 38 struct finfo *fi, 39 efi_file_protocol_t **handle, 40 unsigned long *file_size) 41 { 42 efi_guid_t info_guid = EFI_FILE_INFO_ID; 43 efi_file_protocol_t *fh; 44 unsigned long info_sz; 45 efi_status_t status; 46 47 status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0); 48 if (status != EFI_SUCCESS) { 49 pr_efi_err("Failed to open file: "); 50 efi_char16_printk(fi->filename); 51 efi_printk("\n"); 52 return status; 53 } 54 55 info_sz = sizeof(struct finfo); 56 status = fh->get_info(fh, &info_guid, &info_sz, fi); 57 if (status != EFI_SUCCESS) { 58 pr_efi_err("Failed to get file info\n"); 59 fh->close(fh); 60 return status; 61 } 62 63 *handle = fh; 64 *file_size = fi->info.file_size; 65 return EFI_SUCCESS; 66 } 67 68 static efi_status_t efi_open_volume(efi_loaded_image_t *image, 69 efi_file_protocol_t **fh) 70 { 71 efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; 72 efi_simple_file_system_protocol_t *io; 73 efi_status_t status; 74 75 status = efi_bs_call(handle_protocol, image->device_handle, &fs_proto, 76 (void **)&io); 77 if (status != EFI_SUCCESS) { 78 pr_efi_err("Failed to handle fs_proto\n"); 79 return status; 80 } 81 82 status = io->open_volume(io, fh); 83 if (status != EFI_SUCCESS) 84 pr_efi_err("Failed to open volume\n"); 85 86 return status; 87 } 88 89 static int find_file_option(const efi_char16_t *cmdline, int cmdline_len, 90 const efi_char16_t *prefix, int prefix_size, 91 efi_char16_t *result, int result_len) 92 { 93 int prefix_len = prefix_size / 2; 94 bool found = false; 95 int i; 96 97 for (i = prefix_len; i < cmdline_len; i++) { 98 if (!memcmp(&cmdline[i - prefix_len], prefix, prefix_size)) { 99 found = true; 100 break; 101 } 102 } 103 104 if (!found) 105 return 0; 106 107 while (--result_len > 0 && i < cmdline_len) { 108 if (cmdline[i] == L'\0' || 109 cmdline[i] == L'\n' || 110 cmdline[i] == L' ') 111 break; 112 *result++ = cmdline[i++]; 113 } 114 *result = L'\0'; 115 return i; 116 } 117 118 /* 119 * Check the cmdline for a LILO-style file= arguments. 120 * 121 * We only support loading a file from the same filesystem as 122 * the kernel image. 123 */ 124 static efi_status_t handle_cmdline_files(efi_loaded_image_t *image, 125 const efi_char16_t *optstr, 126 int optstr_size, 127 unsigned long soft_limit, 128 unsigned long hard_limit, 129 unsigned long *load_addr, 130 unsigned long *load_size) 131 { 132 const efi_char16_t *cmdline = image->load_options; 133 int cmdline_len = image->load_options_size / 2; 134 unsigned long efi_chunk_size = ULONG_MAX; 135 efi_file_protocol_t *volume = NULL; 136 efi_file_protocol_t *file; 137 unsigned long alloc_addr; 138 unsigned long alloc_size; 139 efi_status_t status; 140 int offset; 141 142 if (!load_addr || !load_size) 143 return EFI_INVALID_PARAMETER; 144 145 if (IS_ENABLED(CONFIG_X86) && !nochunk()) 146 efi_chunk_size = EFI_READ_CHUNK_SIZE; 147 148 alloc_addr = alloc_size = 0; 149 do { 150 struct finfo fi; 151 unsigned long size; 152 void *addr; 153 154 offset = find_file_option(cmdline, cmdline_len, 155 optstr, optstr_size, 156 fi.filename, ARRAY_SIZE(fi.filename)); 157 158 if (!offset) 159 break; 160 161 cmdline += offset; 162 cmdline_len -= offset; 163 164 if (!volume) { 165 status = efi_open_volume(image, &volume); 166 if (status != EFI_SUCCESS) 167 return status; 168 } 169 170 status = efi_open_file(volume, &fi, &file, &size); 171 if (status != EFI_SUCCESS) 172 goto err_close_volume; 173 174 /* 175 * Check whether the existing allocation can contain the next 176 * file. This condition will also trigger naturally during the 177 * first (and typically only) iteration of the loop, given that 178 * alloc_size == 0 in that case. 179 */ 180 if (round_up(alloc_size + size, EFI_ALLOC_ALIGN) > 181 round_up(alloc_size, EFI_ALLOC_ALIGN)) { 182 unsigned long old_addr = alloc_addr; 183 184 status = EFI_OUT_OF_RESOURCES; 185 if (soft_limit < hard_limit) 186 status = efi_allocate_pages(alloc_size + size, 187 &alloc_addr, 188 soft_limit); 189 if (status == EFI_OUT_OF_RESOURCES) 190 status = efi_allocate_pages(alloc_size + size, 191 &alloc_addr, 192 hard_limit); 193 if (status != EFI_SUCCESS) { 194 pr_efi_err("Failed to allocate memory for files\n"); 195 goto err_close_file; 196 } 197 198 if (old_addr != 0) { 199 /* 200 * This is not the first time we've gone 201 * around this loop, and so we are loading 202 * multiple files that need to be concatenated 203 * and returned in a single buffer. 204 */ 205 memcpy((void *)alloc_addr, (void *)old_addr, alloc_size); 206 efi_free(alloc_size, old_addr); 207 } 208 } 209 210 addr = (void *)alloc_addr + alloc_size; 211 alloc_size += size; 212 213 while (size) { 214 unsigned long chunksize = min(size, efi_chunk_size); 215 216 status = file->read(file, &chunksize, addr); 217 if (status != EFI_SUCCESS) { 218 pr_efi_err("Failed to read file\n"); 219 goto err_close_file; 220 } 221 addr += chunksize; 222 size -= chunksize; 223 } 224 file->close(file); 225 } while (offset > 0); 226 227 *load_addr = alloc_addr; 228 *load_size = alloc_size; 229 230 if (volume) 231 volume->close(volume); 232 return EFI_SUCCESS; 233 234 err_close_file: 235 file->close(file); 236 237 err_close_volume: 238 volume->close(volume); 239 efi_free(alloc_size, alloc_addr); 240 return status; 241 } 242 243 efi_status_t efi_load_dtb(efi_loaded_image_t *image, 244 unsigned long *load_addr, 245 unsigned long *load_size) 246 { 247 return handle_cmdline_files(image, L"dtb=", sizeof(L"dtb=") - 2, 248 ULONG_MAX, ULONG_MAX, load_addr, load_size); 249 } 250 251 efi_status_t efi_load_initrd(efi_loaded_image_t *image, 252 unsigned long *load_addr, 253 unsigned long *load_size, 254 unsigned long soft_limit, 255 unsigned long hard_limit) 256 { 257 return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2, 258 soft_limit, hard_limit, load_addr, load_size); 259 } 260