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 static efi_status_t efi_open_file(efi_file_protocol_t *volume, 33 efi_char16_t *filename_16, 34 efi_file_protocol_t **handle, 35 unsigned long *file_size) 36 { 37 struct { 38 efi_file_info_t info; 39 efi_char16_t filename[MAX_FILENAME_SIZE]; 40 } finfo; 41 efi_guid_t info_guid = EFI_FILE_INFO_ID; 42 efi_file_protocol_t *fh; 43 unsigned long info_sz; 44 efi_status_t status; 45 46 status = volume->open(volume, &fh, filename_16, EFI_FILE_MODE_READ, 0); 47 if (status != EFI_SUCCESS) { 48 pr_efi_err("Failed to open file: "); 49 efi_char16_printk(filename_16); 50 efi_printk("\n"); 51 return status; 52 } 53 54 info_sz = sizeof(finfo); 55 status = fh->get_info(fh, &info_guid, &info_sz, &finfo); 56 if (status != EFI_SUCCESS) { 57 pr_efi_err("Failed to get file info\n"); 58 fh->close(fh); 59 return status; 60 } 61 62 *handle = fh; 63 *file_size = finfo.info.file_size; 64 return EFI_SUCCESS; 65 } 66 67 static efi_status_t efi_open_volume(efi_loaded_image_t *image, 68 efi_file_protocol_t **fh) 69 { 70 efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; 71 efi_simple_file_system_protocol_t *io; 72 efi_status_t status; 73 74 status = efi_bs_call(handle_protocol, image->device_handle, &fs_proto, 75 (void **)&io); 76 if (status != EFI_SUCCESS) { 77 pr_efi_err("Failed to handle fs_proto\n"); 78 return status; 79 } 80 81 status = io->open_volume(io, fh); 82 if (status != EFI_SUCCESS) 83 pr_efi_err("Failed to open volume\n"); 84 85 return status; 86 } 87 88 static int find_file_option(const efi_char16_t *cmdline, int cmdline_len, 89 const efi_char16_t *prefix, int prefix_size, 90 efi_char16_t *result, int result_len) 91 { 92 int prefix_len = prefix_size / 2; 93 bool found = false; 94 int i; 95 96 for (i = prefix_len; i < cmdline_len; i++) { 97 if (!memcmp(&cmdline[i - prefix_len], prefix, prefix_size)) { 98 found = true; 99 break; 100 } 101 } 102 103 if (!found) 104 return 0; 105 106 while (--result_len > 0 && i < cmdline_len) { 107 if (cmdline[i] == L'\0' || 108 cmdline[i] == L'\n' || 109 cmdline[i] == L' ') 110 break; 111 *result++ = cmdline[i++]; 112 } 113 *result = L'\0'; 114 return i; 115 } 116 117 /* 118 * Check the cmdline for a LILO-style file= arguments. 119 * 120 * We only support loading a file from the same filesystem as 121 * the kernel image. 122 */ 123 static efi_status_t handle_cmdline_files(efi_loaded_image_t *image, 124 const efi_char16_t *optstr, 125 int optstr_size, 126 unsigned long soft_limit, 127 unsigned long hard_limit, 128 unsigned long *load_addr, 129 unsigned long *load_size) 130 { 131 const efi_char16_t *cmdline = image->load_options; 132 int cmdline_len = image->load_options_size / 2; 133 unsigned long efi_chunk_size = ULONG_MAX; 134 efi_file_protocol_t *volume = NULL; 135 efi_file_protocol_t *file; 136 unsigned long alloc_addr; 137 unsigned long alloc_size; 138 efi_status_t status; 139 int offset; 140 141 if (!load_addr || !load_size) 142 return EFI_INVALID_PARAMETER; 143 144 if (IS_ENABLED(CONFIG_X86) && !nochunk()) 145 efi_chunk_size = EFI_READ_CHUNK_SIZE; 146 147 alloc_addr = alloc_size = 0; 148 do { 149 efi_char16_t filename[MAX_FILENAME_SIZE]; 150 unsigned long size; 151 void *addr; 152 153 offset = find_file_option(cmdline, cmdline_len, 154 optstr, optstr_size, 155 filename, ARRAY_SIZE(filename)); 156 157 if (!offset) 158 break; 159 160 cmdline += offset; 161 cmdline_len -= offset; 162 163 if (!volume) { 164 status = efi_open_volume(image, &volume); 165 if (status != EFI_SUCCESS) 166 return status; 167 } 168 169 status = efi_open_file(volume, filename, &file, &size); 170 if (status != EFI_SUCCESS) 171 goto err_close_volume; 172 173 /* 174 * Check whether the existing allocation can contain the next 175 * file. This condition will also trigger naturally during the 176 * first (and typically only) iteration of the loop, given that 177 * alloc_size == 0 in that case. 178 */ 179 if (round_up(alloc_size + size, EFI_ALLOC_ALIGN) > 180 round_up(alloc_size, EFI_ALLOC_ALIGN)) { 181 unsigned long old_addr = alloc_addr; 182 183 status = EFI_OUT_OF_RESOURCES; 184 if (soft_limit < hard_limit) 185 status = efi_allocate_pages(alloc_size + size, 186 &alloc_addr, 187 soft_limit); 188 if (status == EFI_OUT_OF_RESOURCES) 189 status = efi_allocate_pages(alloc_size + size, 190 &alloc_addr, 191 hard_limit); 192 if (status != EFI_SUCCESS) { 193 pr_efi_err("Failed to allocate memory for files\n"); 194 goto err_close_file; 195 } 196 197 if (old_addr != 0) { 198 /* 199 * This is not the first time we've gone 200 * around this loop, and so we are loading 201 * multiple files that need to be concatenated 202 * and returned in a single buffer. 203 */ 204 memcpy((void *)alloc_addr, (void *)old_addr, alloc_size); 205 efi_free(alloc_size, old_addr); 206 } 207 } 208 209 addr = (void *)alloc_addr + alloc_size; 210 alloc_size += size; 211 212 while (size) { 213 unsigned long chunksize = min(size, efi_chunk_size); 214 215 status = file->read(file, &chunksize, addr); 216 if (status != EFI_SUCCESS) { 217 pr_efi_err("Failed to read file\n"); 218 goto err_close_file; 219 } 220 addr += chunksize; 221 size -= chunksize; 222 } 223 file->close(file); 224 } while (offset > 0); 225 226 *load_addr = alloc_addr; 227 *load_size = alloc_size; 228 229 if (volume) 230 volume->close(volume); 231 return EFI_SUCCESS; 232 233 err_close_file: 234 file->close(file); 235 236 err_close_volume: 237 volume->close(volume); 238 efi_free(alloc_size, alloc_addr); 239 return status; 240 } 241 242 efi_status_t efi_load_dtb(efi_loaded_image_t *image, 243 unsigned long *load_addr, 244 unsigned long *load_size) 245 { 246 return handle_cmdline_files(image, L"dtb=", sizeof(L"dtb=") - 2, 247 ULONG_MAX, ULONG_MAX, load_addr, load_size); 248 } 249 250 efi_status_t efi_load_initrd(efi_loaded_image_t *image, 251 unsigned long *load_addr, 252 unsigned long *load_size, 253 unsigned long soft_limit, 254 unsigned long hard_limit) 255 { 256 return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2, 257 soft_limit, hard_limit, load_addr, load_size); 258 } 259