1 // SPDX-License-Identifier: GPL-2.0
3 * Helper functions used by the EFI stub on multiple
4 * architectures. This should be #included by the EFI stub
5 * implementation files.
7 * Copyright 2011 Intel Corporation; author Matt Fleming
10 #include <linux/efi.h>
16 * Some firmware implementations have problems reading files in one go.
17 * A read chunk size of 1MB seems to work for most platforms.
19 * Unfortunately, reading files in chunks triggers *other* bugs on some
20 * platforms, so we provide a way to disable this workaround, which can
21 * be done by passing "efi=nochunk" on the EFI boot stub command line.
23 * If you experience issues with initrd images being corrupt it's worth
24 * trying efi=nochunk, but chunking is enabled by default on x86 because
25 * there are far more machines that require the workaround than those that
26 * break with it enabled.
28 #define EFI_READ_CHUNK_SIZE SZ_1M
31 efi_file_protocol_t *handle;
35 static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16,
36 void **handle, u64 *file_sz)
38 efi_file_protocol_t *h, *fh = __fh;
39 efi_file_info_t *info;
41 efi_guid_t info_guid = EFI_FILE_INFO_ID;
42 unsigned long info_sz;
44 status = fh->open(fh, &h, filename_16, EFI_FILE_MODE_READ, 0);
45 if (status != EFI_SUCCESS) {
46 efi_printk("Failed to open file: ");
47 efi_char16_printk(filename_16);
55 status = h->get_info(h, &info_guid, &info_sz, NULL);
56 if (status != EFI_BUFFER_TOO_SMALL) {
57 efi_printk("Failed to get file info size\n");
62 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, info_sz,
64 if (status != EFI_SUCCESS) {
65 efi_printk("Failed to alloc mem for file info\n");
69 status = h->get_info(h, &info_guid, &info_sz, info);
70 if (status == EFI_BUFFER_TOO_SMALL) {
71 efi_bs_call(free_pool, info);
75 *file_sz = info->file_size;
76 efi_bs_call(free_pool, info);
78 if (status != EFI_SUCCESS)
79 efi_printk("Failed to get initrd info\n");
84 static efi_status_t efi_file_read(efi_file_protocol_t *handle,
85 unsigned long *size, void *addr)
87 return handle->read(handle, size, addr);
90 static efi_status_t efi_file_close(efi_file_protocol_t *handle)
92 return handle->close(handle);
95 static efi_status_t efi_open_volume(efi_loaded_image_t *image,
96 efi_file_protocol_t **__fh)
98 efi_simple_file_system_protocol_t *io;
99 efi_file_protocol_t *fh;
100 efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
102 efi_handle_t handle = image->device_handle;
104 status = efi_bs_call(handle_protocol, handle, &fs_proto, (void **)&io);
105 if (status != EFI_SUCCESS) {
106 efi_printk("Failed to handle fs_proto\n");
110 status = io->open_volume(io, &fh);
111 if (status != EFI_SUCCESS)
112 efi_printk("Failed to open volume\n");
120 * Check the cmdline for a LILO-style file= arguments.
122 * We only support loading a file from the same filesystem as
125 efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
126 char *cmd_line, char *option_string,
127 unsigned long max_addr,
128 unsigned long *load_addr,
129 unsigned long *load_size)
131 unsigned long efi_chunk_size = ULONG_MAX;
132 struct file_info *files;
133 unsigned long file_addr;
135 efi_file_protocol_t *fh = NULL;
141 if (IS_ENABLED(CONFIG_X86) && !nochunk())
142 efi_chunk_size = EFI_READ_CHUNK_SIZE;
149 j = 0; /* See close_handles */
151 if (!load_addr || !load_size)
152 return EFI_INVALID_PARAMETER;
160 for (nr_files = 0; *str; nr_files++) {
161 str = strstr(str, option_string);
165 str += strlen(option_string);
167 /* Skip any leading slashes */
168 while (*str == '/' || *str == '\\')
171 while (*str && *str != ' ' && *str != '\n')
178 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
179 nr_files * sizeof(*files), (void **)&files);
180 if (status != EFI_SUCCESS) {
181 pr_efi_err("Failed to alloc mem for file handle list\n");
186 for (i = 0; i < nr_files; i++) {
187 struct file_info *file;
188 efi_char16_t filename_16[256];
191 str = strstr(str, option_string);
195 str += strlen(option_string);
200 /* Skip any leading slashes */
201 while (*str == '/' || *str == '\\')
204 while (*str && *str != ' ' && *str != '\n') {
205 if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16))
218 /* Only open the volume once. */
220 status = efi_open_volume(image, &fh);
221 if (status != EFI_SUCCESS)
225 status = efi_file_size(fh, filename_16, (void **)&file->handle,
227 if (status != EFI_SUCCESS)
230 file_size_total += file->size;
233 if (file_size_total) {
237 * Multiple files need to be at consecutive addresses in memory,
238 * so allocate enough memory for all the files. This is used
239 * for loading multiple files.
241 status = efi_allocate_pages(file_size_total, &file_addr, max_addr);
242 if (status != EFI_SUCCESS) {
243 pr_efi_err("Failed to alloc highmem for files\n");
247 /* We've run out of free low memory. */
248 if (file_addr > max_addr) {
249 pr_efi_err("We've run out of free low memory\n");
250 status = EFI_INVALID_PARAMETER;
251 goto free_file_total;
255 for (j = 0; j < nr_files; j++) {
258 size = files[j].size;
260 unsigned long chunksize;
262 if (size > efi_chunk_size)
263 chunksize = efi_chunk_size;
267 status = efi_file_read(files[j].handle,
270 if (status != EFI_SUCCESS) {
271 pr_efi_err("Failed to read file\n");
272 goto free_file_total;
278 efi_file_close(files[j].handle);
283 efi_bs_call(free_pool, files);
285 *load_addr = file_addr;
286 *load_size = file_size_total;
291 efi_free(file_size_total, file_addr);
294 for (k = j; k < i; k++)
295 efi_file_close(files[k].handle);
297 efi_bs_call(free_pool, files);