efi/arm64: ignore dtb= when UEFI SecureBoot is enabled
[deliverable/linux.git] / drivers / firmware / efi / arm-stub.c
1 /*
2 * EFI stub implementation that is shared by arm and arm64 architectures.
3 * This should be #included by the EFI stub implementation files.
4 *
5 * Copyright (C) 2013,2014 Linaro Limited
6 * Roy Franz <roy.franz@linaro.org
7 * Copyright (C) 2013 Red Hat, Inc.
8 * Mark Salter <msalter@redhat.com>
9 *
10 * This file is part of the Linux kernel, and is made available under the
11 * terms of the GNU General Public License version 2.
12 *
13 */
14
15 static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg)
16 {
17 static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID;
18 static efi_char16_t const var_name[] __initconst = {
19 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 };
20
21 efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable;
22 unsigned long size = sizeof(u8);
23 efi_status_t status;
24 u8 val;
25
26 status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)&var_guid,
27 NULL, &size, &val);
28
29 switch (status) {
30 case EFI_SUCCESS:
31 return val;
32 case EFI_NOT_FOUND:
33 return 0;
34 default:
35 return 1;
36 }
37 }
38
39 static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
40 void *__image, void **__fh)
41 {
42 efi_file_io_interface_t *io;
43 efi_loaded_image_t *image = __image;
44 efi_file_handle_t *fh;
45 efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
46 efi_status_t status;
47 void *handle = (void *)(unsigned long)image->device_handle;
48
49 status = sys_table_arg->boottime->handle_protocol(handle,
50 &fs_proto, (void **)&io);
51 if (status != EFI_SUCCESS) {
52 efi_printk(sys_table_arg, "Failed to handle fs_proto\n");
53 return status;
54 }
55
56 status = io->open_volume(io, &fh);
57 if (status != EFI_SUCCESS)
58 efi_printk(sys_table_arg, "Failed to open volume\n");
59
60 *__fh = fh;
61 return status;
62 }
63 static efi_status_t efi_file_close(void *handle)
64 {
65 efi_file_handle_t *fh = handle;
66
67 return fh->close(handle);
68 }
69
70 static efi_status_t
71 efi_file_read(void *handle, unsigned long *size, void *addr)
72 {
73 efi_file_handle_t *fh = handle;
74
75 return fh->read(handle, size, addr);
76 }
77
78
79 static efi_status_t
80 efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
81 efi_char16_t *filename_16, void **handle, u64 *file_sz)
82 {
83 efi_file_handle_t *h, *fh = __fh;
84 efi_file_info_t *info;
85 efi_status_t status;
86 efi_guid_t info_guid = EFI_FILE_INFO_ID;
87 unsigned long info_sz;
88
89 status = fh->open(fh, &h, filename_16, EFI_FILE_MODE_READ, (u64)0);
90 if (status != EFI_SUCCESS) {
91 efi_printk(sys_table_arg, "Failed to open file: ");
92 efi_char16_printk(sys_table_arg, filename_16);
93 efi_printk(sys_table_arg, "\n");
94 return status;
95 }
96
97 *handle = h;
98
99 info_sz = 0;
100 status = h->get_info(h, &info_guid, &info_sz, NULL);
101 if (status != EFI_BUFFER_TOO_SMALL) {
102 efi_printk(sys_table_arg, "Failed to get file info size\n");
103 return status;
104 }
105
106 grow:
107 status = sys_table_arg->boottime->allocate_pool(EFI_LOADER_DATA,
108 info_sz, (void **)&info);
109 if (status != EFI_SUCCESS) {
110 efi_printk(sys_table_arg, "Failed to alloc mem for file info\n");
111 return status;
112 }
113
114 status = h->get_info(h, &info_guid, &info_sz,
115 info);
116 if (status == EFI_BUFFER_TOO_SMALL) {
117 sys_table_arg->boottime->free_pool(info);
118 goto grow;
119 }
120
121 *file_sz = info->file_size;
122 sys_table_arg->boottime->free_pool(info);
123
124 if (status != EFI_SUCCESS)
125 efi_printk(sys_table_arg, "Failed to get initrd info\n");
126
127 return status;
128 }
129
130
131
132 static void efi_char16_printk(efi_system_table_t *sys_table_arg,
133 efi_char16_t *str)
134 {
135 struct efi_simple_text_output_protocol *out;
136
137 out = (struct efi_simple_text_output_protocol *)sys_table_arg->con_out;
138 out->output_string(out, str);
139 }
140
141
142 /*
143 * This function handles the architcture specific differences between arm and
144 * arm64 regarding where the kernel image must be loaded and any memory that
145 * must be reserved. On failure it is required to free all
146 * all allocations it has made.
147 */
148 static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
149 unsigned long *image_addr,
150 unsigned long *image_size,
151 unsigned long *reserve_addr,
152 unsigned long *reserve_size,
153 unsigned long dram_base,
154 efi_loaded_image_t *image);
155 /*
156 * EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint
157 * that is described in the PE/COFF header. Most of the code is the same
158 * for both archictectures, with the arch-specific code provided in the
159 * handle_kernel_image() function.
160 */
161 unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
162 unsigned long *image_addr)
163 {
164 efi_loaded_image_t *image;
165 efi_status_t status;
166 unsigned long image_size = 0;
167 unsigned long dram_base;
168 /* addr/point and size pairs for memory management*/
169 unsigned long initrd_addr;
170 u64 initrd_size = 0;
171 unsigned long fdt_addr = 0; /* Original DTB */
172 u64 fdt_size = 0; /* We don't get size from configuration table */
173 char *cmdline_ptr = NULL;
174 int cmdline_size = 0;
175 unsigned long new_fdt_addr;
176 efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
177 unsigned long reserve_addr = 0;
178 unsigned long reserve_size = 0;
179
180 /* Check if we were booted by the EFI firmware */
181 if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
182 goto fail;
183
184 pr_efi(sys_table, "Booting Linux Kernel...\n");
185
186 /*
187 * Get a handle to the loaded image protocol. This is used to get
188 * information about the running image, such as size and the command
189 * line.
190 */
191 status = sys_table->boottime->handle_protocol(handle,
192 &loaded_image_proto, (void *)&image);
193 if (status != EFI_SUCCESS) {
194 pr_efi_err(sys_table, "Failed to get loaded image protocol\n");
195 goto fail;
196 }
197
198 dram_base = get_dram_base(sys_table);
199 if (dram_base == EFI_ERROR) {
200 pr_efi_err(sys_table, "Failed to find DRAM base\n");
201 goto fail;
202 }
203 status = handle_kernel_image(sys_table, image_addr, &image_size,
204 &reserve_addr,
205 &reserve_size,
206 dram_base, image);
207 if (status != EFI_SUCCESS) {
208 pr_efi_err(sys_table, "Failed to relocate kernel\n");
209 goto fail;
210 }
211
212 /*
213 * Get the command line from EFI, using the LOADED_IMAGE
214 * protocol. We are going to copy the command line into the
215 * device tree, so this can be allocated anywhere.
216 */
217 cmdline_ptr = efi_convert_cmdline(sys_table, image, &cmdline_size);
218 if (!cmdline_ptr) {
219 pr_efi_err(sys_table, "getting command line via LOADED_IMAGE_PROTOCOL\n");
220 goto fail_free_image;
221 }
222
223 /*
224 * Unauthenticated device tree data is a security hazard, so
225 * ignore 'dtb=' unless UEFI Secure Boot is disabled.
226 */
227 if (efi_secureboot_enabled(sys_table)) {
228 pr_efi(sys_table, "UEFI Secure Boot is enabled.\n");
229 } else {
230 status = handle_cmdline_files(sys_table, image, cmdline_ptr,
231 "dtb=",
232 ~0UL, (unsigned long *)&fdt_addr,
233 (unsigned long *)&fdt_size);
234
235 if (status != EFI_SUCCESS) {
236 pr_efi_err(sys_table, "Failed to load device tree!\n");
237 goto fail_free_cmdline;
238 }
239 }
240 if (!fdt_addr)
241 /* Look for a device tree configuration table entry. */
242 fdt_addr = (uintptr_t)get_fdt(sys_table);
243
244 status = handle_cmdline_files(sys_table, image, cmdline_ptr,
245 "initrd=", dram_base + SZ_512M,
246 (unsigned long *)&initrd_addr,
247 (unsigned long *)&initrd_size);
248 if (status != EFI_SUCCESS)
249 pr_efi_err(sys_table, "Failed initrd from command line!\n");
250
251 new_fdt_addr = fdt_addr;
252 status = allocate_new_fdt_and_exit_boot(sys_table, handle,
253 &new_fdt_addr, dram_base + MAX_FDT_OFFSET,
254 initrd_addr, initrd_size, cmdline_ptr,
255 fdt_addr, fdt_size);
256
257 /*
258 * If all went well, we need to return the FDT address to the
259 * calling function so it can be passed to kernel as part of
260 * the kernel boot protocol.
261 */
262 if (status == EFI_SUCCESS)
263 return new_fdt_addr;
264
265 pr_efi_err(sys_table, "Failed to update FDT and exit boot services\n");
266
267 efi_free(sys_table, initrd_size, initrd_addr);
268 efi_free(sys_table, fdt_size, fdt_addr);
269
270 fail_free_cmdline:
271 efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
272
273 fail_free_image:
274 efi_free(sys_table, image_size, *image_addr);
275 efi_free(sys_table, reserve_size, reserve_addr);
276 fail:
277 return EFI_ERROR;
278 }
This page took 0.047504 seconds and 5 git commands to generate.