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 max_addr, 127 unsigned long *load_addr, 128 unsigned long *load_size) 129 { 130 const efi_char16_t *cmdline = image->load_options; 131 int cmdline_len = image->load_options_size / 2; 132 unsigned long efi_chunk_size = ULONG_MAX; 133 efi_file_protocol_t *volume = NULL; 134 efi_file_protocol_t *file; 135 unsigned long alloc_addr; 136 unsigned long alloc_size; 137 efi_status_t status; 138 int offset; 139 140 if (!load_addr || !load_size) 141 return EFI_INVALID_PARAMETER; 142 143 if (IS_ENABLED(CONFIG_X86) && !nochunk()) 144 efi_chunk_size = EFI_READ_CHUNK_SIZE; 145 146 alloc_addr = alloc_size = 0; 147 do { 148 efi_char16_t filename[MAX_FILENAME_SIZE]; 149 unsigned long size; 150 void *addr; 151 152 offset = find_file_option(cmdline, cmdline_len, 153 optstr, optstr_size, 154 filename, ARRAY_SIZE(filename)); 155 156 if (!offset) 157 break; 158 159 cmdline += offset; 160 cmdline_len -= offset; 161 162 if (!volume) { 163 status = efi_open_volume(image, &volume); 164 if (status != EFI_SUCCESS) 165 return status; 166 } 167 168 status = efi_open_file(volume, filename, &file, &size); 169 if (status != EFI_SUCCESS) 170 goto err_close_volume; 171 172 /* 173 * Check whether the existing allocation can contain the next 174 * file. This condition will also trigger naturally during the 175 * first (and typically only) iteration of the loop, given that 176 * alloc_size == 0 in that case. 177 */ 178 if (round_up(alloc_size + size, EFI_ALLOC_ALIGN) > 179 round_up(alloc_size, EFI_ALLOC_ALIGN)) { 180 unsigned long old_addr = alloc_addr; 181 182 status = efi_allocate_pages(alloc_size + size, &alloc_addr, 183 max_addr); 184 if (status != EFI_SUCCESS) { 185 pr_efi_err("Failed to reallocate memory for files\n"); 186 goto err_close_file; 187 } 188 189 if (old_addr != 0) { 190 /* 191 * This is not the first time we've gone 192 * around this loop, and so we are loading 193 * multiple files that need to be concatenated 194 * and returned in a single buffer. 195 */ 196 memcpy((void *)alloc_addr, (void *)old_addr, alloc_size); 197 efi_free(alloc_size, old_addr); 198 } 199 } 200 201 addr = (void *)alloc_addr + alloc_size; 202 alloc_size += size; 203 204 while (size) { 205 unsigned long chunksize = min(size, efi_chunk_size); 206 207 status = file->read(file, &chunksize, addr); 208 if (status != EFI_SUCCESS) { 209 pr_efi_err("Failed to read file\n"); 210 goto err_close_file; 211 } 212 addr += chunksize; 213 size -= chunksize; 214 } 215 file->close(file); 216 } while (offset > 0); 217 218 *load_addr = alloc_addr; 219 *load_size = alloc_size; 220 221 if (volume) 222 volume->close(volume); 223 return EFI_SUCCESS; 224 225 err_close_file: 226 file->close(file); 227 228 err_close_volume: 229 volume->close(volume); 230 efi_free(alloc_size, alloc_addr); 231 return status; 232 } 233 234 efi_status_t efi_load_dtb(efi_loaded_image_t *image, 235 unsigned long *load_addr, 236 unsigned long *load_size) 237 { 238 return handle_cmdline_files(image, L"dtb=", sizeof(L"dtb=") - 2, 239 ULONG_MAX, load_addr, load_size); 240 } 241 242 efi_status_t efi_load_initrd(efi_loaded_image_t *image, 243 unsigned long *load_addr, 244 unsigned long *load_size, 245 unsigned long max_addr) 246 { 247 return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2, 248 max_addr, load_addr, load_size); 249 } 250