blob: 69a942f0640bdcf5b43e4142975a59802718e55e [file] [log] [blame]
Thomas Gleixner97873a32019-06-04 10:11:30 +02001// SPDX-License-Identifier: GPL-2.0-only
Eric Snowbergb84a64f2018-11-29 18:12:20 +01002
Matt Fleming291f3632011-12-12 21:27:52 +00003/* -----------------------------------------------------------------------
4 *
5 * Copyright 2011 Intel Corporation; author Matt Fleming
6 *
Matt Fleming291f3632011-12-12 21:27:52 +00007 * ----------------------------------------------------------------------- */
8
9#include <linux/efi.h>
Matthew Garrettdd5fc852012-12-05 14:33:26 -070010#include <linux/pci.h>
Ingo Molnar5520b7e2017-01-27 11:59:46 +010011
Matt Fleming291f3632011-12-12 21:27:52 +000012#include <asm/efi.h>
Ingo Molnar5520b7e2017-01-27 11:59:46 +010013#include <asm/e820/types.h>
Matt Fleming291f3632011-12-12 21:27:52 +000014#include <asm/setup.h>
15#include <asm/desc.h>
Kairui Song220dd762019-10-29 18:37:54 +010016#include <asm/boot.h>
Matt Fleming291f3632011-12-12 21:27:52 +000017
Ard Biesheuvelc2d0b472020-02-10 17:02:36 +010018#include "efistub.h"
Matt Fleming291f3632011-12-12 21:27:52 +000019
20static efi_system_table_t *sys_table;
Ard Biesheuvel796eb8d2020-01-13 18:22:33 +010021extern const bool efi_is64;
Matt Fleming204b0a12014-03-22 10:09:01 +000022
Ard Biesheuvel2fcdad22019-12-24 16:10:15 +010023__pure efi_system_table_t *efi_system_table(void)
24{
25 return sys_table;
26}
27
Ard Biesheuvel796eb8d2020-01-13 18:22:33 +010028__attribute_const__ bool efi_is_64bit(void)
Ard Biesheuvelc3710de2019-12-24 16:10:17 +010029{
Ard Biesheuvel796eb8d2020-01-13 18:22:33 +010030 if (IS_ENABLED(CONFIG_EFI_MIXED))
31 return efi_is64;
Qian Caicada0b62020-01-22 14:14:30 -050032 return IS_ENABLED(CONFIG_X86_64);
Matt Fleming54b52d82014-01-10 15:27:14 +000033}
Matt Fleming54b52d82014-01-10 15:27:14 +000034
Matt Flemingc116e8d2014-01-16 11:35:43 +000035static efi_status_t
Ard Biesheuvel75c5a712018-07-20 10:47:19 +090036preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
Matthew Garrettdd5fc852012-12-05 14:33:26 -070037{
Matt Flemingc116e8d2014-01-16 11:35:43 +000038 struct pci_setup_rom *rom = NULL;
Matthew Garrettdd5fc852012-12-05 14:33:26 -070039 efi_status_t status;
Matt Flemingc116e8d2014-01-16 11:35:43 +000040 unsigned long size;
Ard Biesheuvele2967012018-07-11 11:02:35 +020041 uint64_t romsize;
Ard Biesheuvel2c3625c2018-05-04 08:00:00 +020042 void *romimage;
Matt Flemingc116e8d2014-01-16 11:35:43 +000043
Hans de Goede1de3a1b2018-05-04 08:00:01 +020044 /*
Ard Biesheuvele2967012018-07-11 11:02:35 +020045 * Some firmware images contain EFI function pointers at the place where
46 * the romimage and romsize fields are supposed to be. Typically the EFI
Hans de Goede1de3a1b2018-05-04 08:00:01 +020047 * code is mapped at high addresses, translating to an unrealistically
48 * large romsize. The UEFI spec limits the size of option ROMs to 16
49 * MiB so we reject any ROMs over 16 MiB in size to catch this.
50 */
Ard Biesheuvel99ea8b12019-12-24 16:10:22 +010051 romimage = efi_table_attr(pci, romimage);
52 romsize = efi_table_attr(pci, romsize);
Hans de Goede1de3a1b2018-05-04 08:00:01 +020053 if (!romimage || !romsize || romsize > SZ_16M)
Matt Flemingc116e8d2014-01-16 11:35:43 +000054 return EFI_INVALID_PARAMETER;
55
Ard Biesheuvel2c3625c2018-05-04 08:00:00 +020056 size = romsize + sizeof(*rom);
Matt Flemingc116e8d2014-01-16 11:35:43 +000057
Ard Biesheuvel966291f2019-12-24 16:10:23 +010058 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
59 (void **)&rom);
Andre Müller77e21e82014-09-10 01:00:22 +020060 if (status != EFI_SUCCESS) {
Ard Biesheuvel8173ec72019-12-24 16:10:18 +010061 efi_printk("Failed to allocate memory for 'rom'\n");
Matt Flemingc116e8d2014-01-16 11:35:43 +000062 return status;
Andre Müller77e21e82014-09-10 01:00:22 +020063 }
Matt Flemingc116e8d2014-01-16 11:35:43 +000064
65 memset(rom, 0, sizeof(*rom));
66
Ingo Molnar90a21862018-07-11 11:40:33 +020067 rom->data.type = SETUP_PCI;
68 rom->data.len = size - sizeof(struct setup_data);
69 rom->data.next = 0;
70 rom->pcilen = pci->romsize;
Matt Flemingc116e8d2014-01-16 11:35:43 +000071 *__rom = rom;
72
Ard Biesheuvel47c0fd32019-12-24 16:10:21 +010073 status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
74 PCI_VENDOR_ID, 1, &rom->vendor);
Matt Flemingc116e8d2014-01-16 11:35:43 +000075
Andre Müller77e21e82014-09-10 01:00:22 +020076 if (status != EFI_SUCCESS) {
Ard Biesheuvel8173ec72019-12-24 16:10:18 +010077 efi_printk("Failed to read rom->vendor\n");
Matt Flemingc116e8d2014-01-16 11:35:43 +000078 goto free_struct;
Andre Müller77e21e82014-09-10 01:00:22 +020079 }
Matt Flemingc116e8d2014-01-16 11:35:43 +000080
Ard Biesheuvel47c0fd32019-12-24 16:10:21 +010081 status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
82 PCI_DEVICE_ID, 1, &rom->devid);
Matt Flemingc116e8d2014-01-16 11:35:43 +000083
Andre Müller77e21e82014-09-10 01:00:22 +020084 if (status != EFI_SUCCESS) {
Ard Biesheuvel8173ec72019-12-24 16:10:18 +010085 efi_printk("Failed to read rom->devid\n");
Matt Flemingc116e8d2014-01-16 11:35:43 +000086 goto free_struct;
Andre Müller77e21e82014-09-10 01:00:22 +020087 }
Matt Flemingc116e8d2014-01-16 11:35:43 +000088
Ard Biesheuvel47c0fd32019-12-24 16:10:21 +010089 status = efi_call_proto(pci, get_location, &rom->segment, &rom->bus,
90 &rom->device, &rom->function);
Matt Flemingc116e8d2014-01-16 11:35:43 +000091
92 if (status != EFI_SUCCESS)
93 goto free_struct;
94
Ard Biesheuvel2c3625c2018-05-04 08:00:00 +020095 memcpy(rom->romdata, romimage, romsize);
Matt Flemingc116e8d2014-01-16 11:35:43 +000096 return status;
97
98free_struct:
Ard Biesheuvel966291f2019-12-24 16:10:23 +010099 efi_bs_call(free_pool, rom);
Matt Flemingc116e8d2014-01-16 11:35:43 +0000100 return status;
101}
102
Matt Fleming56394ab2014-09-11 09:04:25 +0100103/*
104 * There's no way to return an informative status from this function,
105 * because any analysis (and printing of error messages) needs to be
106 * done directly at the EFI function call-site.
107 *
108 * For example, EFI_INVALID_PARAMETER could indicate a bug or maybe we
109 * just didn't find any PCI devices, but there's no way to tell outside
110 * the context of the call.
111 */
112static void setup_efi_pci(struct boot_params *params)
Matt Flemingc116e8d2014-01-16 11:35:43 +0000113{
114 efi_status_t status;
115 void **pci_handle = NULL;
116 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
117 unsigned long size = 0;
Ard Biesheuvel75c5a712018-07-20 10:47:19 +0900118 struct setup_data *data;
Ard Biesheuvel2732ea02019-12-24 16:10:07 +0100119 efi_handle_t h;
Ard Biesheuvel75c5a712018-07-20 10:47:19 +0900120 int i;
Matt Flemingc116e8d2014-01-16 11:35:43 +0000121
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100122 status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
123 &pci_proto, NULL, &size, pci_handle);
Matthew Garrettdd5fc852012-12-05 14:33:26 -0700124
125 if (status == EFI_BUFFER_TOO_SMALL) {
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100126 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
127 (void **)&pci_handle);
Matthew Garrettdd5fc852012-12-05 14:33:26 -0700128
Andre Müller77e21e82014-09-10 01:00:22 +0200129 if (status != EFI_SUCCESS) {
Ard Biesheuvel8173ec72019-12-24 16:10:18 +0100130 efi_printk("Failed to allocate memory for 'pci_handle'\n");
Matt Fleming56394ab2014-09-11 09:04:25 +0100131 return;
Andre Müller77e21e82014-09-10 01:00:22 +0200132 }
Matthew Garrettdd5fc852012-12-05 14:33:26 -0700133
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100134 status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
135 &pci_proto, NULL, &size, pci_handle);
Matthew Garrettdd5fc852012-12-05 14:33:26 -0700136 }
137
138 if (status != EFI_SUCCESS)
139 goto free_handle;
140
Ard Biesheuvel75c5a712018-07-20 10:47:19 +0900141 data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
142
143 while (data && data->next)
144 data = (struct setup_data *)(unsigned long)data->next;
145
Ard Biesheuvel2732ea02019-12-24 16:10:07 +0100146 for_each_efi_handle(h, pci_handle, size, i) {
Ard Biesheuvel75c5a712018-07-20 10:47:19 +0900147 efi_pci_io_protocol_t *pci = NULL;
148 struct pci_setup_rom *rom;
149
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100150 status = efi_bs_call(handle_protocol, h, &pci_proto,
151 (void **)&pci);
Ard Biesheuvel75c5a712018-07-20 10:47:19 +0900152 if (status != EFI_SUCCESS || !pci)
153 continue;
154
155 status = preserve_pci_rom_image(pci, &rom);
156 if (status != EFI_SUCCESS)
157 continue;
158
159 if (data)
160 data->next = (unsigned long)rom;
161 else
162 params->hdr.setup_data = (unsigned long)rom;
163
164 data = (struct setup_data *)rom;
165 }
Matthew Garrettdd5fc852012-12-05 14:33:26 -0700166
167free_handle:
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100168 efi_bs_call(free_pool, pci_handle);
Matthew Garrettdd5fc852012-12-05 14:33:26 -0700169}
170
Lukas Wunner58c54752016-11-12 21:32:36 +0000171static void retrieve_apple_device_properties(struct boot_params *boot_params)
172{
173 efi_guid_t guid = APPLE_PROPERTIES_PROTOCOL_GUID;
174 struct setup_data *data, *new;
175 efi_status_t status;
176 u32 size = 0;
Ard Biesheuvel960a8d02019-12-24 16:10:11 +0100177 apple_properties_protocol_t *p;
Lukas Wunner58c54752016-11-12 21:32:36 +0000178
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100179 status = efi_bs_call(locate_protocol, &guid, NULL, (void **)&p);
Lukas Wunner58c54752016-11-12 21:32:36 +0000180 if (status != EFI_SUCCESS)
181 return;
182
Ard Biesheuvel99ea8b12019-12-24 16:10:22 +0100183 if (efi_table_attr(p, version) != 0x10000) {
Ard Biesheuvel8173ec72019-12-24 16:10:18 +0100184 efi_printk("Unsupported properties proto version\n");
Lukas Wunner58c54752016-11-12 21:32:36 +0000185 return;
186 }
187
Ard Biesheuvel47c0fd32019-12-24 16:10:21 +0100188 efi_call_proto(p, get_all, NULL, &size);
Lukas Wunner58c54752016-11-12 21:32:36 +0000189 if (!size)
190 return;
191
192 do {
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100193 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
194 size + sizeof(struct setup_data),
195 (void **)&new);
Lukas Wunner58c54752016-11-12 21:32:36 +0000196 if (status != EFI_SUCCESS) {
Ard Biesheuvel8173ec72019-12-24 16:10:18 +0100197 efi_printk("Failed to allocate memory for 'properties'\n");
Lukas Wunner58c54752016-11-12 21:32:36 +0000198 return;
199 }
200
Ard Biesheuvel47c0fd32019-12-24 16:10:21 +0100201 status = efi_call_proto(p, get_all, new->data, &size);
Lukas Wunner58c54752016-11-12 21:32:36 +0000202
203 if (status == EFI_BUFFER_TOO_SMALL)
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100204 efi_bs_call(free_pool, new);
Lukas Wunner58c54752016-11-12 21:32:36 +0000205 } while (status == EFI_BUFFER_TOO_SMALL);
206
207 new->type = SETUP_APPLE_PROPERTIES;
208 new->len = size;
209 new->next = 0;
210
211 data = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data;
Ingo Molnar90a21862018-07-11 11:40:33 +0200212 if (!data) {
Lukas Wunner58c54752016-11-12 21:32:36 +0000213 boot_params->hdr.setup_data = (unsigned long)new;
Ingo Molnar90a21862018-07-11 11:40:33 +0200214 } else {
Lukas Wunner58c54752016-11-12 21:32:36 +0000215 while (data->next)
216 data = (struct setup_data *)(unsigned long)data->next;
217 data->next = (unsigned long)new;
218 }
219}
220
Ard Biesheuvel36b64972018-03-12 08:45:00 +0000221static const efi_char16_t apple[] = L"Apple";
222
Lukas Wunner58c54752016-11-12 21:32:36 +0000223static void setup_quirks(struct boot_params *boot_params)
224{
Lukas Wunner58c54752016-11-12 21:32:36 +0000225 efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
Ard Biesheuvel99ea8b12019-12-24 16:10:22 +0100226 efi_table_attr(efi_system_table(), fw_vendor);
Lukas Wunner58c54752016-11-12 21:32:36 +0000227
228 if (!memcmp(fw_vendor, apple, sizeof(apple))) {
229 if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
230 retrieve_apple_device_properties(boot_params);
231 }
232}
233
Matt Flemingc116e8d2014-01-16 11:35:43 +0000234/*
235 * See if we have Universal Graphics Adapter (UGA) protocol
236 */
Ingo Molnar90a21862018-07-11 11:40:33 +0200237static efi_status_t
238setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
Matt Flemingc116e8d2014-01-16 11:35:43 +0000239{
240 efi_status_t status;
241 u32 width, height;
242 void **uga_handle = NULL;
Ard Biesheuvel290084c2018-07-20 10:47:21 +0900243 efi_uga_draw_protocol_t *uga = NULL, *first_uga;
Ard Biesheuvel2732ea02019-12-24 16:10:07 +0100244 efi_handle_t handle;
Ard Biesheuvel290084c2018-07-20 10:47:21 +0900245 int i;
Matt Flemingc116e8d2014-01-16 11:35:43 +0000246
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100247 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
248 (void **)&uga_handle);
Matt Flemingc116e8d2014-01-16 11:35:43 +0000249 if (status != EFI_SUCCESS)
250 return status;
251
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100252 status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
253 uga_proto, NULL, &size, uga_handle);
Matt Flemingc116e8d2014-01-16 11:35:43 +0000254 if (status != EFI_SUCCESS)
255 goto free_handle;
256
257 height = 0;
258 width = 0;
259
Ard Biesheuvel290084c2018-07-20 10:47:21 +0900260 first_uga = NULL;
Ard Biesheuvel2732ea02019-12-24 16:10:07 +0100261 for_each_efi_handle(handle, uga_handle, size, i) {
Ard Biesheuvel290084c2018-07-20 10:47:21 +0900262 efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
263 u32 w, h, depth, refresh;
264 void *pciio;
Ard Biesheuvel290084c2018-07-20 10:47:21 +0900265
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100266 status = efi_bs_call(handle_protocol, handle, uga_proto,
267 (void **)&uga);
Ard Biesheuvel290084c2018-07-20 10:47:21 +0900268 if (status != EFI_SUCCESS)
269 continue;
270
Ard Biesheuvel093174f2018-07-20 10:47:22 +0900271 pciio = NULL;
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100272 efi_bs_call(handle_protocol, handle, &pciio_proto, &pciio);
Ard Biesheuvel290084c2018-07-20 10:47:21 +0900273
Ard Biesheuvel47c0fd32019-12-24 16:10:21 +0100274 status = efi_call_proto(uga, get_mode, &w, &h, &depth, &refresh);
Ard Biesheuvel290084c2018-07-20 10:47:21 +0900275 if (status == EFI_SUCCESS && (!first_uga || pciio)) {
276 width = w;
277 height = h;
278
279 /*
280 * Once we've found a UGA supporting PCIIO,
281 * don't bother looking any further.
282 */
283 if (pciio)
284 break;
285
286 first_uga = uga;
287 }
288 }
Matt Flemingc116e8d2014-01-16 11:35:43 +0000289
290 if (!width && !height)
Matt Fleming291f3632011-12-12 21:27:52 +0000291 goto free_handle;
292
293 /* EFI framebuffer */
Ingo Molnar90a21862018-07-11 11:40:33 +0200294 si->orig_video_isVGA = VIDEO_TYPE_EFI;
Matt Fleming291f3632011-12-12 21:27:52 +0000295
Ingo Molnar90a21862018-07-11 11:40:33 +0200296 si->lfb_depth = 32;
297 si->lfb_width = width;
298 si->lfb_height = height;
Matt Fleming291f3632011-12-12 21:27:52 +0000299
Ingo Molnar90a21862018-07-11 11:40:33 +0200300 si->red_size = 8;
301 si->red_pos = 16;
302 si->green_size = 8;
303 si->green_pos = 8;
304 si->blue_size = 8;
305 si->blue_pos = 0;
306 si->rsvd_size = 8;
307 si->rsvd_pos = 24;
Matt Fleming291f3632011-12-12 21:27:52 +0000308
Matt Fleming291f3632011-12-12 21:27:52 +0000309free_handle:
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100310 efi_bs_call(free_pool, uga_handle);
Ingo Molnar90a21862018-07-11 11:40:33 +0200311
Matt Fleming291f3632011-12-12 21:27:52 +0000312 return status;
313}
314
Arvind Sankarf32ea1c2020-01-30 17:20:04 -0500315static void setup_graphics(struct boot_params *boot_params)
Matt Fleming291f3632011-12-12 21:27:52 +0000316{
317 efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
318 struct screen_info *si;
319 efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
320 efi_status_t status;
321 unsigned long size;
322 void **gop_handle = NULL;
323 void **uga_handle = NULL;
324
325 si = &boot_params->screen_info;
326 memset(si, 0, sizeof(*si));
327
328 size = 0;
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100329 status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
330 &graphics_proto, NULL, &size, gop_handle);
Matt Fleming291f3632011-12-12 21:27:52 +0000331 if (status == EFI_BUFFER_TOO_SMALL)
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100332 status = efi_setup_gop(si, &graphics_proto, size);
Matt Fleming291f3632011-12-12 21:27:52 +0000333
334 if (status != EFI_SUCCESS) {
335 size = 0;
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100336 status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
337 &uga_proto, NULL, &size, uga_handle);
Matt Fleming291f3632011-12-12 21:27:52 +0000338 if (status == EFI_BUFFER_TOO_SMALL)
339 setup_uga(si, &uga_proto, size);
340 }
341}
342
Ard Biesheuvel3b8f44f2020-02-16 00:03:25 +0100343
344static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status)
345{
346 efi_bs_call(exit, handle, status, 0, NULL);
Ard Biesheuvelf3fa0ef2020-03-08 09:08:45 +0100347 for(;;)
348 asm("hlt");
Ard Biesheuvel3b8f44f2020-02-16 00:03:25 +0100349}
350
Ard Biesheuvelc3710de2019-12-24 16:10:17 +0100351void startup_32(struct boot_params *boot_params);
352
353void __noreturn efi_stub_entry(efi_handle_t handle,
354 efi_system_table_t *sys_table_arg,
355 struct boot_params *boot_params);
356
Matt Fleming291f3632011-12-12 21:27:52 +0000357/*
358 * Because the x86 boot code expects to be passed a boot_params we
359 * need to create one ourselves (usually the bootloader would create
360 * one for us).
361 */
Ard Biesheuvelc3710de2019-12-24 16:10:17 +0100362efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
363 efi_system_table_t *sys_table_arg)
Matt Fleming291f3632011-12-12 21:27:52 +0000364{
Matt Fleming9ca8f722012-07-19 10:23:48 +0100365 struct boot_params *boot_params;
Matt Fleming9ca8f722012-07-19 10:23:48 +0100366 struct setup_header *hdr;
Matt Fleming9ca8f722012-07-19 10:23:48 +0100367 efi_loaded_image_t *image;
Matt Fleming9ca8f722012-07-19 10:23:48 +0100368 efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
Matt Fleming291f3632011-12-12 21:27:52 +0000369 int options_size = 0;
370 efi_status_t status;
Roy Franz5fef3872013-09-22 15:45:33 -0700371 char *cmdline_ptr;
Roy Franz46f45822013-09-22 15:45:39 -0700372 unsigned long ramdisk_addr;
373 unsigned long ramdisk_size;
Ard Biesheuvel6a4db9b2020-02-10 17:02:39 +0100374 bool above4g;
Matt Fleming291f3632011-12-12 21:27:52 +0000375
Ard Biesheuvelc3710de2019-12-24 16:10:17 +0100376 sys_table = sys_table_arg;
Matt Fleming9ca8f722012-07-19 10:23:48 +0100377
378 /* Check if we were booted by the EFI firmware */
379 if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
Ard Biesheuvel3b8f44f2020-02-16 00:03:25 +0100380 efi_exit(handle, EFI_INVALID_PARAMETER);
Matt Fleming54b52d82014-01-10 15:27:14 +0000381
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100382 status = efi_bs_call(handle_protocol, handle, &proto, (void *)&image);
Matt Fleming9ca8f722012-07-19 10:23:48 +0100383 if (status != EFI_SUCCESS) {
Ard Biesheuvel8173ec72019-12-24 16:10:18 +0100384 efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
Ard Biesheuvel3b8f44f2020-02-16 00:03:25 +0100385 efi_exit(handle, status);
Matt Fleming9ca8f722012-07-19 10:23:48 +0100386 }
387
Ard Biesheuvelf7b85b32020-02-14 14:29:21 +0100388 hdr = &((struct boot_params *)efi_table_attr(image, image_base))->hdr;
Ard Biesheuvel6a4db9b2020-02-10 17:02:39 +0100389 above4g = hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G;
390
391 status = efi_allocate_pages(0x4000, (unsigned long *)&boot_params,
392 above4g ? ULONG_MAX : UINT_MAX);
Matt Fleming9ca8f722012-07-19 10:23:48 +0100393 if (status != EFI_SUCCESS) {
Ard Biesheuvel8173ec72019-12-24 16:10:18 +0100394 efi_printk("Failed to allocate lowmem for boot params\n");
Ard Biesheuvel3b8f44f2020-02-16 00:03:25 +0100395 efi_exit(handle, status);
Matt Fleming9ca8f722012-07-19 10:23:48 +0100396 }
397
398 memset(boot_params, 0x0, 0x4000);
399
400 hdr = &boot_params->hdr;
Matt Fleming9ca8f722012-07-19 10:23:48 +0100401
402 /* Copy the second sector to boot_params */
Ard Biesheuvelf7b85b32020-02-14 14:29:21 +0100403 memcpy(&hdr->jump, efi_table_attr(image, image_base) + 512, 512);
Matt Fleming9ca8f722012-07-19 10:23:48 +0100404
405 /*
406 * Fill out some of the header fields ourselves because the
407 * EFI firmware loader doesn't load the first sector.
408 */
Ingo Molnar90a21862018-07-11 11:40:33 +0200409 hdr->root_flags = 1;
410 hdr->vid_mode = 0xffff;
411 hdr->boot_flag = 0xAA55;
Matt Fleming9ca8f722012-07-19 10:23:48 +0100412
Matt Fleming291f3632011-12-12 21:27:52 +0000413 hdr->type_of_loader = 0x21;
414
415 /* Convert unicode cmdline to ascii */
Ard Biesheuvel1e45bf72020-02-10 17:02:40 +0100416 cmdline_ptr = efi_convert_cmdline(image, &options_size,
417 above4g ? ULONG_MAX : UINT_MAX);
Roy Franz5fef3872013-09-22 15:45:33 -0700418 if (!cmdline_ptr)
419 goto fail;
Ingo Molnar90a21862018-07-11 11:40:33 +0200420
Roy Franz5fef3872013-09-22 15:45:33 -0700421 hdr->cmd_line_ptr = (unsigned long)cmdline_ptr;
Roy Franz98b228f2015-04-15 16:32:24 -0700422 /* Fill in upper bits of command line address, NOP on 32 bit */
423 boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32;
Matt Fleming291f3632011-12-12 21:27:52 +0000424
425 hdr->ramdisk_image = 0;
426 hdr->ramdisk_size = 0;
427
Ard Biesheuvel17054f42020-02-12 23:20:54 +0100428 if (efi_is_native()) {
429 status = efi_parse_options(cmdline_ptr);
Ard Biesheuvel79d32192020-02-04 22:01:22 +0000430 if (status != EFI_SUCCESS)
431 goto fail2;
Ard Biesheuvel17054f42020-02-12 23:20:54 +0100432
433 if (!noinitrd()) {
434 status = efi_load_initrd(image, &ramdisk_addr,
435 &ramdisk_size,
436 hdr->initrd_addr_max,
437 above4g ? ULONG_MAX
438 : hdr->initrd_addr_max);
439 if (status != EFI_SUCCESS)
440 goto fail2;
441 hdr->ramdisk_image = ramdisk_addr & 0xffffffff;
442 hdr->ramdisk_size = ramdisk_size & 0xffffffff;
443 boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32;
444 boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32;
445 }
Ard Biesheuvel79d32192020-02-04 22:01:22 +0000446 }
Matt Fleming9ca8f722012-07-19 10:23:48 +0100447
Ard Biesheuvelc3710de2019-12-24 16:10:17 +0100448 efi_stub_entry(handle, sys_table, boot_params);
449 /* not reached */
Ingo Molnar90a21862018-07-11 11:40:33 +0200450
Matt Fleming9ca8f722012-07-19 10:23:48 +0100451fail2:
Ard Biesheuvel1e45bf72020-02-10 17:02:40 +0100452 efi_free(options_size, (unsigned long)cmdline_ptr);
Matt Fleming9ca8f722012-07-19 10:23:48 +0100453fail:
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100454 efi_free(0x4000, (unsigned long)boot_params);
Ingo Molnar90a21862018-07-11 11:40:33 +0200455
Ard Biesheuvel3b8f44f2020-02-16 00:03:25 +0100456 efi_exit(handle, status);
Matt Fleming9ca8f722012-07-19 10:23:48 +0100457}
458
Linn Crosettod2078d52013-09-22 19:59:08 -0600459static void add_e820ext(struct boot_params *params,
460 struct setup_data *e820ext, u32 nr_entries)
Matt Fleming9ca8f722012-07-19 10:23:48 +0100461{
Linn Crosettod2078d52013-09-22 19:59:08 -0600462 struct setup_data *data;
Linn Crosettod2078d52013-09-22 19:59:08 -0600463
464 e820ext->type = SETUP_E820_EXT;
Ingo Molnar90a21862018-07-11 11:40:33 +0200465 e820ext->len = nr_entries * sizeof(struct boot_e820_entry);
Linn Crosettod2078d52013-09-22 19:59:08 -0600466 e820ext->next = 0;
467
468 data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
469
470 while (data && data->next)
471 data = (struct setup_data *)(unsigned long)data->next;
472
473 if (data)
474 data->next = (unsigned long)e820ext;
475 else
476 params->hdr.setup_data = (unsigned long)e820ext;
477}
478
Ingo Molnar90a21862018-07-11 11:40:33 +0200479static efi_status_t
480setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_size)
Linn Crosettod2078d52013-09-22 19:59:08 -0600481{
Ingo Molnar7410aa12017-01-29 12:56:13 +0100482 struct boot_e820_entry *entry = params->e820_table;
Linn Crosettod2078d52013-09-22 19:59:08 -0600483 struct efi_info *efi = &params->efi_info;
Ingo Molnar7410aa12017-01-29 12:56:13 +0100484 struct boot_e820_entry *prev = NULL;
Linn Crosettod2078d52013-09-22 19:59:08 -0600485 u32 nr_entries;
486 u32 nr_desc;
Matt Fleming9ca8f722012-07-19 10:23:48 +0100487 int i;
Matt Fleming291f3632011-12-12 21:27:52 +0000488
Matt Fleming291f3632011-12-12 21:27:52 +0000489 nr_entries = 0;
Linn Crosettod2078d52013-09-22 19:59:08 -0600490 nr_desc = efi->efi_memmap_size / efi->efi_memdesc_size;
491
492 for (i = 0; i < nr_desc; i++) {
Matt Fleming291f3632011-12-12 21:27:52 +0000493 efi_memory_desc_t *d;
494 unsigned int e820_type = 0;
Linn Crosettod2078d52013-09-22 19:59:08 -0600495 unsigned long m = efi->efi_memmap;
Matt Fleming291f3632011-12-12 21:27:52 +0000496
Dmitry Skorodumov7cc03e42015-07-28 18:38:32 +0400497#ifdef CONFIG_X86_64
498 m |= (u64)efi->efi_memmap_hi << 32;
499#endif
500
Baoquan He02e43c22017-08-16 21:46:51 +0800501 d = efi_early_memdesc_ptr(m, efi->efi_memdesc_size, i);
Matt Fleming291f3632011-12-12 21:27:52 +0000502 switch (d->type) {
503 case EFI_RESERVED_TYPE:
504 case EFI_RUNTIME_SERVICES_CODE:
505 case EFI_RUNTIME_SERVICES_DATA:
506 case EFI_MEMORY_MAPPED_IO:
507 case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
508 case EFI_PAL_CODE:
Ingo Molnar09821ff2017-01-28 17:09:33 +0100509 e820_type = E820_TYPE_RESERVED;
Matt Fleming291f3632011-12-12 21:27:52 +0000510 break;
511
512 case EFI_UNUSABLE_MEMORY:
Ingo Molnar09821ff2017-01-28 17:09:33 +0100513 e820_type = E820_TYPE_UNUSABLE;
Matt Fleming291f3632011-12-12 21:27:52 +0000514 break;
515
516 case EFI_ACPI_RECLAIM_MEMORY:
Ingo Molnar09821ff2017-01-28 17:09:33 +0100517 e820_type = E820_TYPE_ACPI;
Matt Fleming291f3632011-12-12 21:27:52 +0000518 break;
519
520 case EFI_LOADER_CODE:
521 case EFI_LOADER_DATA:
522 case EFI_BOOT_SERVICES_CODE:
523 case EFI_BOOT_SERVICES_DATA:
524 case EFI_CONVENTIONAL_MEMORY:
Dan Williams262b45a2019-11-06 17:43:16 -0800525 if (efi_soft_reserve_enabled() &&
526 (d->attribute & EFI_MEMORY_SP))
527 e820_type = E820_TYPE_SOFT_RESERVED;
528 else
529 e820_type = E820_TYPE_RAM;
Matt Fleming291f3632011-12-12 21:27:52 +0000530 break;
531
532 case EFI_ACPI_MEMORY_NVS:
Ingo Molnar09821ff2017-01-28 17:09:33 +0100533 e820_type = E820_TYPE_NVS;
Matt Fleming291f3632011-12-12 21:27:52 +0000534 break;
535
Dan Williamsad5fb872015-04-03 12:05:28 -0400536 case EFI_PERSISTENT_MEMORY:
Ingo Molnar09821ff2017-01-28 17:09:33 +0100537 e820_type = E820_TYPE_PMEM;
Dan Williamsad5fb872015-04-03 12:05:28 -0400538 break;
539
Matt Fleming291f3632011-12-12 21:27:52 +0000540 default:
541 continue;
542 }
543
544 /* Merge adjacent mappings */
545 if (prev && prev->type == e820_type &&
Linn Crosettod2078d52013-09-22 19:59:08 -0600546 (prev->addr + prev->size) == d->phys_addr) {
Matt Fleming291f3632011-12-12 21:27:52 +0000547 prev->size += d->num_pages << 12;
Linn Crosettod2078d52013-09-22 19:59:08 -0600548 continue;
Matt Fleming291f3632011-12-12 21:27:52 +0000549 }
Linn Crosettod2078d52013-09-22 19:59:08 -0600550
Ingo Molnar61a50102017-01-27 13:54:38 +0100551 if (nr_entries == ARRAY_SIZE(params->e820_table)) {
Ingo Molnar8ec67d92017-01-27 12:54:38 +0100552 u32 need = (nr_desc - i) * sizeof(struct e820_entry) +
Linn Crosettod2078d52013-09-22 19:59:08 -0600553 sizeof(struct setup_data);
554
555 if (!e820ext || e820ext_size < need)
556 return EFI_BUFFER_TOO_SMALL;
557
558 /* boot_params map full, switch to e820 extended */
Ingo Molnar7410aa12017-01-29 12:56:13 +0100559 entry = (struct boot_e820_entry *)e820ext->data;
Linn Crosettod2078d52013-09-22 19:59:08 -0600560 }
561
Ingo Molnar7410aa12017-01-29 12:56:13 +0100562 entry->addr = d->phys_addr;
563 entry->size = d->num_pages << PAGE_SHIFT;
564 entry->type = e820_type;
565 prev = entry++;
Linn Crosettod2078d52013-09-22 19:59:08 -0600566 nr_entries++;
Matt Fleming291f3632011-12-12 21:27:52 +0000567 }
568
Ingo Molnar61a50102017-01-27 13:54:38 +0100569 if (nr_entries > ARRAY_SIZE(params->e820_table)) {
570 u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_table);
Linn Crosettod2078d52013-09-22 19:59:08 -0600571
572 add_e820ext(params, e820ext, nr_e820ext);
573 nr_entries -= nr_e820ext;
574 }
575
576 params->e820_entries = (u8)nr_entries;
577
578 return EFI_SUCCESS;
579}
580
581static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
582 u32 *e820ext_size)
583{
584 efi_status_t status;
585 unsigned long size;
586
587 size = sizeof(struct setup_data) +
Ingo Molnar8ec67d92017-01-27 12:54:38 +0100588 sizeof(struct e820_entry) * nr_desc;
Linn Crosettod2078d52013-09-22 19:59:08 -0600589
590 if (*e820ext) {
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100591 efi_bs_call(free_pool, *e820ext);
Linn Crosettod2078d52013-09-22 19:59:08 -0600592 *e820ext = NULL;
593 *e820ext_size = 0;
594 }
595
Ard Biesheuvel966291f2019-12-24 16:10:23 +0100596 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
597 (void **)e820ext);
Linn Crosettod2078d52013-09-22 19:59:08 -0600598 if (status == EFI_SUCCESS)
599 *e820ext_size = size;
600
601 return status;
602}
603
Eric Snowbergb84a64f2018-11-29 18:12:20 +0100604static efi_status_t allocate_e820(struct boot_params *params,
605 struct setup_data **e820ext,
606 u32 *e820ext_size)
607{
608 unsigned long map_size, desc_size, buff_size;
609 struct efi_boot_memmap boot_map;
610 efi_memory_desc_t *map;
611 efi_status_t status;
612 __u32 nr_desc;
613
614 boot_map.map = &map;
615 boot_map.map_size = &map_size;
616 boot_map.desc_size = &desc_size;
617 boot_map.desc_ver = NULL;
618 boot_map.key_ptr = NULL;
619 boot_map.buff_size = &buff_size;
620
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100621 status = efi_get_memory_map(&boot_map);
Eric Snowbergb84a64f2018-11-29 18:12:20 +0100622 if (status != EFI_SUCCESS)
623 return status;
624
625 nr_desc = buff_size / desc_size;
626
627 if (nr_desc > ARRAY_SIZE(params->e820_table)) {
628 u32 nr_e820ext = nr_desc - ARRAY_SIZE(params->e820_table);
629
630 status = alloc_e820ext(nr_e820ext, e820ext, e820ext_size);
631 if (status != EFI_SUCCESS)
632 return status;
633 }
634
635 return EFI_SUCCESS;
636}
637
Jeffrey Hugod6493402016-08-29 14:38:54 -0600638struct exit_boot_struct {
Ingo Molnar90a21862018-07-11 11:40:33 +0200639 struct boot_params *boot_params;
640 struct efi_info *efi;
Jeffrey Hugod6493402016-08-29 14:38:54 -0600641};
642
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100643static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
Jeffrey Hugod6493402016-08-29 14:38:54 -0600644 void *priv)
645{
Jeffrey Hugod6493402016-08-29 14:38:54 -0600646 const char *signature;
Jeffrey Hugod6493402016-08-29 14:38:54 -0600647 struct exit_boot_struct *p = priv;
648
Ard Biesheuvelaab95932018-07-20 10:47:24 +0900649 signature = efi_is_64bit() ? EFI64_LOADER_SIGNATURE
650 : EFI32_LOADER_SIGNATURE;
Jeffrey Hugod6493402016-08-29 14:38:54 -0600651 memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));
652
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100653 p->efi->efi_systab = (unsigned long)efi_system_table();
Ingo Molnar90a21862018-07-11 11:40:33 +0200654 p->efi->efi_memdesc_size = *map->desc_size;
655 p->efi->efi_memdesc_version = *map->desc_ver;
656 p->efi->efi_memmap = (unsigned long)*map->map;
657 p->efi->efi_memmap_size = *map->map_size;
Jeffrey Hugod6493402016-08-29 14:38:54 -0600658
659#ifdef CONFIG_X86_64
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100660 p->efi->efi_systab_hi = (unsigned long)efi_system_table() >> 32;
Ingo Molnar90a21862018-07-11 11:40:33 +0200661 p->efi->efi_memmap_hi = (unsigned long)*map->map >> 32;
Jeffrey Hugod6493402016-08-29 14:38:54 -0600662#endif
663
664 return EFI_SUCCESS;
665}
666
Ard Biesheuvelaab95932018-07-20 10:47:24 +0900667static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
Linn Crosettod2078d52013-09-22 19:59:08 -0600668{
Jeffrey Hugodadb57a2016-08-29 14:38:51 -0600669 unsigned long map_sz, key, desc_size, buff_size;
Linn Crosettod2078d52013-09-22 19:59:08 -0600670 efi_memory_desc_t *mem_map;
Eric Snowbergb84a64f2018-11-29 18:12:20 +0100671 struct setup_data *e820ext = NULL;
672 __u32 e820ext_size = 0;
Linn Crosettod2078d52013-09-22 19:59:08 -0600673 efi_status_t status;
674 __u32 desc_version;
Jeffrey Hugodadb57a2016-08-29 14:38:51 -0600675 struct efi_boot_memmap map;
Jeffrey Hugod6493402016-08-29 14:38:54 -0600676 struct exit_boot_struct priv;
Linn Crosettod2078d52013-09-22 19:59:08 -0600677
Ingo Molnar90a21862018-07-11 11:40:33 +0200678 map.map = &mem_map;
679 map.map_size = &map_sz;
680 map.desc_size = &desc_size;
681 map.desc_ver = &desc_version;
682 map.key_ptr = &key;
683 map.buff_size = &buff_size;
684 priv.boot_params = boot_params;
685 priv.efi = &boot_params->efi_info;
Eric Snowbergb84a64f2018-11-29 18:12:20 +0100686
687 status = allocate_e820(boot_params, &e820ext, &e820ext_size);
688 if (status != EFI_SUCCESS)
689 return status;
Linn Crosettod2078d52013-09-22 19:59:08 -0600690
Jeffrey Hugod6493402016-08-29 14:38:54 -0600691 /* Might as well exit boot services now */
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100692 status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func);
Linn Crosettod2078d52013-09-22 19:59:08 -0600693 if (status != EFI_SUCCESS)
694 return status;
695
Linn Crosettod2078d52013-09-22 19:59:08 -0600696 /* Historic? */
Ingo Molnar90a21862018-07-11 11:40:33 +0200697 boot_params->alt_mem_k = 32 * 1024;
Linn Crosettod2078d52013-09-22 19:59:08 -0600698
699 status = setup_e820(boot_params, e820ext, e820ext_size);
700 if (status != EFI_SUCCESS)
701 return status;
Matt Fleming291f3632011-12-12 21:27:52 +0000702
703 return EFI_SUCCESS;
Matt Fleming291f3632011-12-12 21:27:52 +0000704}
705
Matt Fleming9ca8f722012-07-19 10:23:48 +0100706/*
Arvind Sankar8acf63e2020-03-08 09:08:43 +0100707 * On success, we return the address of startup_32, which has potentially been
708 * relocated by efi_relocate_kernel.
709 * On failure, we exit to the firmware via efi_exit instead of returning.
Matt Fleming9ca8f722012-07-19 10:23:48 +0100710 */
Arvind Sankar8acf63e2020-03-08 09:08:43 +0100711unsigned long efi_main(efi_handle_t handle,
Ard Biesheuvelc3710de2019-12-24 16:10:17 +0100712 efi_system_table_t *sys_table_arg,
Ard Biesheuvel796eb8d2020-01-13 18:22:33 +0100713 struct boot_params *boot_params)
Matt Fleming9ca8f722012-07-19 10:23:48 +0100714{
Ard Biesheuvel04a7d0e2020-02-10 17:02:31 +0100715 unsigned long bzimage_addr = (unsigned long)startup_32;
Matt Fleming9ca8f722012-07-19 10:23:48 +0100716 struct setup_header *hdr = &boot_params->hdr;
717 efi_status_t status;
Hans de Goedec33ce982018-09-12 20:32:05 +0200718 unsigned long cmdline_paddr;
Matt Fleming54b52d82014-01-10 15:27:14 +0000719
Ard Biesheuvelc3710de2019-12-24 16:10:17 +0100720 sys_table = sys_table_arg;
Matt Fleming54b52d82014-01-10 15:27:14 +0000721
Matt Fleming9ca8f722012-07-19 10:23:48 +0100722 /* Check if we were booted by the EFI firmware */
723 if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
Ard Biesheuvel3b8f44f2020-02-16 00:03:25 +0100724 efi_exit(handle, EFI_INVALID_PARAMETER);
Matt Fleming9ca8f722012-07-19 10:23:48 +0100725
David Howellsde8cb452017-02-06 11:22:43 +0000726 /*
Ard Biesheuvel04a7d0e2020-02-10 17:02:31 +0100727 * If the kernel isn't already loaded at the preferred load
728 * address, relocate it.
729 */
730 if (bzimage_addr != hdr->pref_address) {
731 status = efi_relocate_kernel(&bzimage_addr,
732 hdr->init_size, hdr->init_size,
733 hdr->pref_address,
734 hdr->kernel_alignment,
735 LOAD_PHYSICAL_ADDR);
736 if (status != EFI_SUCCESS) {
737 efi_printk("efi_relocate_kernel() failed!\n");
738 goto fail;
739 }
740 }
Ard Biesheuvel04a7d0e2020-02-10 17:02:31 +0100741
742 /*
Ard Biesheuvel91d150c2020-02-10 17:02:46 +0100743 * efi_pe_entry() may have been called before efi_main(), in which
Hans de Goedec33ce982018-09-12 20:32:05 +0200744 * case this is the second time we parse the cmdline. This is ok,
745 * parsing the cmdline multiple times does not have side-effects.
746 */
747 cmdline_paddr = ((u64)hdr->cmd_line_ptr |
748 ((u64)boot_params->ext_cmd_line_ptr << 32));
749 efi_parse_options((char *)cmdline_paddr);
750
751 /*
Ard Biesheuvelec93fc32020-02-03 23:45:14 +0000752 * At this point, an initrd may already have been loaded, either by
753 * the bootloader and passed via bootparams, or loaded from a initrd=
754 * command line option by efi_pe_entry() above. In either case, we
755 * permit an initrd loaded from the LINUX_EFI_INITRD_MEDIA_GUID device
756 * path to supersede it.
757 */
Ard Biesheuvel79d32192020-02-04 22:01:22 +0000758 if (!noinitrd()) {
759 unsigned long addr, size;
760 unsigned long max_addr = hdr->initrd_addr_max;
761
762 if (hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G)
763 max_addr = ULONG_MAX;
764
765 status = efi_load_initrd_dev_path(&addr, &size, max_addr);
766 if (status == EFI_SUCCESS) {
767 hdr->ramdisk_image = (u32)addr;
768 hdr->ramdisk_size = (u32)size;
769 boot_params->ext_ramdisk_image = (u64)addr >> 32;
770 boot_params->ext_ramdisk_size = (u64)size >> 32;
771 } else if (status != EFI_NOT_FOUND) {
772 efi_printk("efi_load_initrd_dev_path() failed!\n");
773 goto fail;
774 }
Ard Biesheuvelec93fc32020-02-03 23:45:14 +0000775 }
776
777 /*
David Howellsde8cb452017-02-06 11:22:43 +0000778 * If the boot loader gave us a value for secure_boot then we use that,
779 * otherwise we ask the BIOS.
780 */
781 if (boot_params->secure_boot == efi_secureboot_mode_unset)
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100782 boot_params->secure_boot = efi_get_secureboot();
David Howellsde8cb452017-02-06 11:22:43 +0000783
Matthew Garrettccc829b2017-08-25 16:50:15 +0100784 /* Ask the firmware to clear memory on unclean shutdown */
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100785 efi_enable_reset_attack_mitigation();
Dominik Brodowski0d959812019-11-06 08:06:13 +0100786
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100787 efi_random_get_seed();
Dominik Brodowski0d959812019-11-06 08:06:13 +0100788
Ard Biesheuvelcd33a5c2019-12-24 16:10:19 +0100789 efi_retrieve_tpm2_eventlog();
Matthew Garrettccc829b2017-08-25 16:50:15 +0100790
Matt Fleming9ca8f722012-07-19 10:23:48 +0100791 setup_graphics(boot_params);
Matt Fleming291f3632011-12-12 21:27:52 +0000792
Matt Fleming56394ab2014-09-11 09:04:25 +0100793 setup_efi_pci(boot_params);
Matthew Garrettdd5fc852012-12-05 14:33:26 -0700794
Lukas Wunner58c54752016-11-12 21:32:36 +0000795 setup_quirks(boot_params);
796
Ard Biesheuvelaab95932018-07-20 10:47:24 +0900797 status = exit_boot(boot_params, handle);
Ulf Winkelvosfb86b242014-07-10 02:12:41 +0200798 if (status != EFI_SUCCESS) {
Ard Biesheuvel8173ec72019-12-24 16:10:18 +0100799 efi_printk("exit_boot() failed!\n");
Matt Fleming291f3632011-12-12 21:27:52 +0000800 goto fail;
Ulf Winkelvosfb86b242014-07-10 02:12:41 +0200801 }
Matt Fleming291f3632011-12-12 21:27:52 +0000802
Arvind Sankar8acf63e2020-03-08 09:08:43 +0100803 return bzimage_addr;
Matt Fleming291f3632011-12-12 21:27:52 +0000804fail:
Ard Biesheuvel8173ec72019-12-24 16:10:18 +0100805 efi_printk("efi_main() failed!\n");
Ingo Molnar90a21862018-07-11 11:40:33 +0200806
Ard Biesheuvel3b8f44f2020-02-16 00:03:25 +0100807 efi_exit(handle, status);
Matt Fleming291f3632011-12-12 21:27:52 +0000808}