1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2020, Linaro Limited
12 #include <efi_loader.h>
13 #include <efi_load_initrd.h>
15 static const efi_guid_t efi_guid_load_file2_protocol =
16 EFI_LOAD_FILE2_PROTOCOL_GUID;
18 static efi_status_t EFIAPI
19 efi_load_file2_initrd(struct efi_load_file_protocol *this,
20 struct efi_device_path *file_path, bool boot_policy,
21 efi_uintn_t *buffer_size, void *buffer);
23 static const struct efi_load_file_protocol efi_lf2_protocol = {
24 .load_file = efi_load_file2_initrd,
28 * Device path defined by Linux to identify the handle providing the
29 * EFI_LOAD_FILE2_PROTOCOL used for loading the initial ramdisk.
31 static const struct efi_initrd_dp dp = {
34 DEVICE_PATH_TYPE_MEDIA_DEVICE,
35 DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
38 EFI_INITRD_MEDIA_GUID,
42 DEVICE_PATH_SUB_TYPE_END,
48 * get_file_size() - retrieve the size of initramfs, set efi status on error
50 * @dev: device to read from. i.e "mmc"
51 * @part: device partition. i.e "0:1"
53 * @status: EFI exit code in case of failure
55 * Return: size of file
57 static loff_t get_file_size(const char *dev, const char *part, const char *file,
63 ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
65 *status = EFI_NO_MEDIA;
69 ret = fs_size(file, &sz);
72 *status = EFI_NOT_FOUND;
81 * load_file2() - get information about random number generation
83 * This function implement the LoadFile2() service in order to load an initram
84 * disk requested by the Linux kernel stub.
85 * See the UEFI spec for details.
87 * @this: loadfile2 protocol instance
88 * @file_path: relative path of the file. "" in this case
89 * @boot_policy: must be false for Loadfile2
90 * @buffer_size: size of allocated buffer
91 * @buffer: buffer to load the file
95 static efi_status_t EFIAPI
96 efi_load_file2_initrd(struct efi_load_file_protocol *this,
97 struct efi_device_path *file_path, bool boot_policy,
98 efi_uintn_t *buffer_size, void *buffer)
100 const char *filespec = CONFIG_EFI_INITRD_FILESPEC;
101 efi_status_t status = EFI_NOT_FOUND;
102 loff_t file_sz = 0, read_sz = 0;
103 char *dev, *part, *file;
107 EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy,
108 buffer_size, buffer);
110 s = strdup(filespec);
114 if (!this || this != &efi_lf2_protocol ||
116 status = EFI_INVALID_PARAMETER;
120 if (file_path->type != dp.end.type ||
121 file_path->sub_type != dp.end.sub_type) {
122 status = EFI_INVALID_PARAMETER;
127 status = EFI_UNSUPPORTED;
131 /* expect something like 'mmc 0:1 initrd.cpio.gz' */
132 dev = strsep(&s, " ");
135 part = strsep(&s, " ");
138 file = strsep(&s, " ");
142 file_sz = get_file_size(dev, part, file, &status);
146 if (!buffer || *buffer_size < file_sz) {
147 status = EFI_BUFFER_TOO_SMALL;
148 *buffer_size = file_sz;
150 ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
152 status = EFI_NO_MEDIA;
156 ret = fs_read(file, map_to_sysmem(buffer), 0, *buffer_size,
158 if (ret || read_sz != file_sz)
160 *buffer_size = read_sz;
162 status = EFI_SUCCESS;
167 return EFI_EXIT(status);
171 * efi_initrd_register() - Register a handle and loadfile2 protocol
173 * This function creates a new handle and installs a linux specific GUID
174 * to handle initram disk loading during boot.
175 * See the UEFI spec for details.
177 * Return: status code
179 efi_status_t efi_initrd_register(void)
181 efi_handle_t efi_initrd_handle = NULL;
185 * Set up the handle with the EFI_LOAD_FILE2_PROTOCOL which Linux may
186 * use to load the initial ramdisk.
188 ret = EFI_CALL(efi_install_multiple_protocol_interfaces
191 &efi_guid_device_path, &dp,
193 &efi_guid_load_file2_protocol,
194 (void *)&efi_lf2_protocol,