eboot.c 22.2 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2

M
Matt Fleming 已提交
3 4 5 6 7 8 9
/* -----------------------------------------------------------------------
 *
 *   Copyright 2011 Intel Corporation; author Matt Fleming
 *
 * ----------------------------------------------------------------------- */

#include <linux/efi.h>
10
#include <linux/pci.h>
11

M
Matt Fleming 已提交
12
#include <asm/efi.h>
13
#include <asm/e820/types.h>
M
Matt Fleming 已提交
14 15
#include <asm/setup.h>
#include <asm/desc.h>
16
#include <asm/boot.h>
M
Matt Fleming 已提交
17

18
#include "../string.h"
M
Matt Fleming 已提交
19 20 21
#include "eboot.h"

static efi_system_table_t *sys_table;
22
static bool efi_is64 = IS_ENABLED(CONFIG_X86_64);
23

24 25 26 27 28
__pure efi_system_table_t *efi_system_table(void)
{
	return sys_table;
}

29 30 31
__pure bool efi_is_64bit(void)
{
	return efi_is64;
32
}
M
Matt Fleming 已提交
33

34
static efi_status_t
35
preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
36
{
37
	struct pci_setup_rom *rom = NULL;
38
	efi_status_t status;
39
	unsigned long size;
40
	uint64_t romsize;
41
	void *romimage;
42

43
	/*
44 45
	 * Some firmware images contain EFI function pointers at the place where
	 * the romimage and romsize fields are supposed to be. Typically the EFI
46 47 48 49
	 * code is mapped at high addresses, translating to an unrealistically
	 * large romsize. The UEFI spec limits the size of option ROMs to 16
	 * MiB so we reject any ROMs over 16 MiB in size to catch this.
	 */
50
	romimage = efi_table_attr(efi_pci_io_protocol, romimage, pci);
51
	romsize = efi_table_attr(efi_pci_io_protocol, romsize, pci);
52
	if (!romimage || !romsize || romsize > SZ_16M)
53
		return EFI_INVALID_PARAMETER;
54

55
	size = romsize + sizeof(*rom);
56

57 58
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size,
				(void **)&rom);
59
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
60
		efi_printk(sys_table, "Failed to allocate memory for 'rom'\n");
61
		return status;
62
	}
63

64 65
	memset(rom, 0, sizeof(*rom));

I
Ingo Molnar 已提交
66 67 68 69
	rom->data.type	= SETUP_PCI;
	rom->data.len	= size - sizeof(struct setup_data);
	rom->data.next	= 0;
	rom->pcilen	= pci->romsize;
70 71
	*__rom = rom;

72 73 74
	status = efi_call_proto(efi_pci_io_protocol, pci.read, pci,
				EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
				&rom->vendor);
75

76 77
	if (status != EFI_SUCCESS) {
		efi_printk(sys_table, "Failed to read rom->vendor\n");
78
		goto free_struct;
79
	}
80

81 82 83
	status = efi_call_proto(efi_pci_io_protocol, pci.read, pci,
				EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
				&rom->devid);
84

85 86
	if (status != EFI_SUCCESS) {
		efi_printk(sys_table, "Failed to read rom->devid\n");
87
		goto free_struct;
88
	}
89

90 91 92
	status = efi_call_proto(efi_pci_io_protocol, get_location, pci,
				&rom->segment, &rom->bus, &rom->device,
				&rom->function);
93 94 95 96

	if (status != EFI_SUCCESS)
		goto free_struct;

97
	memcpy(rom->romdata, romimage, romsize);
98 99 100
	return status;

free_struct:
101
	efi_call_early(free_pool, rom);
102 103 104
	return status;
}

105 106 107 108 109 110 111 112 113 114
/*
 * There's no way to return an informative status from this function,
 * because any analysis (and printing of error messages) needs to be
 * done directly at the EFI function call-site.
 *
 * For example, EFI_INVALID_PARAMETER could indicate a bug or maybe we
 * just didn't find any PCI devices, but there's no way to tell outside
 * the context of the call.
 */
static void setup_efi_pci(struct boot_params *params)
M
Matt Fleming 已提交
115 116
{
	efi_status_t status;
117 118 119
	void **pci_handle = NULL;
	efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
	unsigned long size = 0;
120 121
	unsigned long nr_pci;
	struct setup_data *data;
122
	efi_handle_t h;
123
	int i;
M
Matt Fleming 已提交
124

125 126 127
	status = efi_call_early(locate_handle,
				EFI_LOCATE_BY_PROTOCOL,
				&pci_proto, NULL, &size, pci_handle);
M
Matt Fleming 已提交
128

129
	if (status == EFI_BUFFER_TOO_SMALL) {
130 131 132
		status = efi_call_early(allocate_pool,
					EFI_LOADER_DATA,
					size, (void **)&pci_handle);
M
Matt Fleming 已提交
133

134
		if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
135
			efi_printk(sys_table, "Failed to allocate memory for 'pci_handle'\n");
136
			return;
137
		}
M
Matt Fleming 已提交
138

139 140 141
		status = efi_call_early(locate_handle,
					EFI_LOCATE_BY_PROTOCOL, &pci_proto,
					NULL, &size, pci_handle);
M
Matt Fleming 已提交
142 143
	}

144
	if (status != EFI_SUCCESS)
M
Matt Fleming 已提交
145 146
		goto free_handle;

147 148 149 150 151
	data = (struct setup_data *)(unsigned long)params->hdr.setup_data;

	while (data && data->next)
		data = (struct setup_data *)(unsigned long)data->next;

152
	for_each_efi_handle(h, pci_handle, size, i) {
153 154 155
		efi_pci_io_protocol_t *pci = NULL;
		struct pci_setup_rom *rom;

156
		status = efi_call_early(handle_protocol, h,
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
					&pci_proto, (void **)&pci);
		if (status != EFI_SUCCESS || !pci)
			continue;

		status = preserve_pci_rom_image(pci, &rom);
		if (status != EFI_SUCCESS)
			continue;

		if (data)
			data->next = (unsigned long)rom;
		else
			params->hdr.setup_data = (unsigned long)rom;

		data = (struct setup_data *)rom;
	}
M
Matt Fleming 已提交
172

173
free_handle:
174
	efi_call_early(free_pool, pci_handle);
175
}
M
Matt Fleming 已提交
176

177 178 179 180 181 182
static void retrieve_apple_device_properties(struct boot_params *boot_params)
{
	efi_guid_t guid = APPLE_PROPERTIES_PROTOCOL_GUID;
	struct setup_data *data, *new;
	efi_status_t status;
	u32 size = 0;
183
	apple_properties_protocol_t *p;
184

185
	status = efi_call_early(locate_protocol, &guid, NULL, (void **)&p);
186 187 188 189 190 191 192 193 194 195 196 197 198 199
	if (status != EFI_SUCCESS)
		return;

	if (efi_table_attr(apple_properties_protocol, version, p) != 0x10000) {
		efi_printk(sys_table, "Unsupported properties proto version\n");
		return;
	}

	efi_call_proto(apple_properties_protocol, get_all, p, NULL, &size);
	if (!size)
		return;

	do {
		status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
200 201
					size + sizeof(struct setup_data),
					(void **)&new);
202
		if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
203
			efi_printk(sys_table, "Failed to allocate memory for 'properties'\n");
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
			return;
		}

		status = efi_call_proto(apple_properties_protocol, get_all, p,
					new->data, &size);

		if (status == EFI_BUFFER_TOO_SMALL)
			efi_call_early(free_pool, new);
	} while (status == EFI_BUFFER_TOO_SMALL);

	new->type = SETUP_APPLE_PROPERTIES;
	new->len  = size;
	new->next = 0;

	data = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data;
I
Ingo Molnar 已提交
219
	if (!data) {
220
		boot_params->hdr.setup_data = (unsigned long)new;
I
Ingo Molnar 已提交
221
	} else {
222 223 224 225 226 227
		while (data->next)
			data = (struct setup_data *)(unsigned long)data->next;
		data->next = (unsigned long)new;
	}
}

228 229
static const efi_char16_t apple[] = L"Apple";

230 231 232 233 234 235 236 237 238 239 240
static void setup_quirks(struct boot_params *boot_params)
{
	efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
		efi_table_attr(efi_system_table, fw_vendor, sys_table);

	if (!memcmp(fw_vendor, apple, sizeof(apple))) {
		if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
			retrieve_apple_device_properties(boot_params);
	}
}

241 242 243
/*
 * See if we have Universal Graphics Adapter (UGA) protocol
 */
244
static efi_status_t
245
setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
246
{
247 248 249
	efi_status_t status;
	u32 width, height;
	void **uga_handle = NULL;
250
	efi_uga_draw_protocol_t *uga = NULL, *first_uga;
251
	unsigned long nr_ugas;
252
	efi_handle_t handle;
253 254
	int i;

255 256 257 258
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
				size, (void **)&uga_handle);
	if (status != EFI_SUCCESS)
		return status;
259

260 261 262 263 264
	status = efi_call_early(locate_handle,
				EFI_LOCATE_BY_PROTOCOL,
				uga_proto, NULL, &size, uga_handle);
	if (status != EFI_SUCCESS)
		goto free_handle;
M
Matt Fleming 已提交
265

266 267
	height = 0;
	width = 0;
268 269

	first_uga = NULL;
270
	for_each_efi_handle(handle, uga_handle, size, i) {
M
Matt Fleming 已提交
271 272 273 274
		efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
		u32 w, h, depth, refresh;
		void *pciio;

275
		status = efi_call_early(handle_protocol, handle,
276
					uga_proto, (void **)&uga);
M
Matt Fleming 已提交
277 278 279
		if (status != EFI_SUCCESS)
			continue;

280
		pciio = NULL;
281
		efi_call_early(handle_protocol, handle, &pciio_proto, &pciio);
M
Matt Fleming 已提交
282

283 284
		status = efi_call_proto(efi_uga_draw_protocol, get_mode, uga,
					&w, &h, &depth, &refresh);
M
Matt Fleming 已提交
285
		if (status == EFI_SUCCESS && (!first_uga || pciio)) {
286 287
			width = w;
			height = h;
M
Matt Fleming 已提交
288 289 290 291 292 293 294 295 296 297 298 299

			/*
			 * Once we've found a UGA supporting PCIIO,
			 * don't bother looking any further.
			 */
			if (pciio)
				break;

			first_uga = uga;
		}
	}

300
	if (!width && !height)
M
Matt Fleming 已提交
301 302 303
		goto free_handle;

	/* EFI framebuffer */
I
Ingo Molnar 已提交
304
	si->orig_video_isVGA	= VIDEO_TYPE_EFI;
M
Matt Fleming 已提交
305

I
Ingo Molnar 已提交
306 307 308
	si->lfb_depth		= 32;
	si->lfb_width		= width;
	si->lfb_height		= height;
M
Matt Fleming 已提交
309

I
Ingo Molnar 已提交
310 311 312 313 314 315 316 317
	si->red_size		= 8;
	si->red_pos		= 16;
	si->green_size		= 8;
	si->green_pos		= 8;
	si->blue_size		= 8;
	si->blue_pos		= 0;
	si->rsvd_size		= 8;
	si->rsvd_pos		= 24;
M
Matt Fleming 已提交
318 319

free_handle:
320
	efi_call_early(free_pool, uga_handle);
I
Ingo Molnar 已提交
321

M
Matt Fleming 已提交
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
	return status;
}

void setup_graphics(struct boot_params *boot_params)
{
	efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
	struct screen_info *si;
	efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
	efi_status_t status;
	unsigned long size;
	void **gop_handle = NULL;
	void **uga_handle = NULL;

	si = &boot_params->screen_info;
	memset(si, 0, sizeof(*si));

	size = 0;
339 340 341
	status = efi_call_early(locate_handle,
				EFI_LOCATE_BY_PROTOCOL,
				&graphics_proto, NULL, &size, gop_handle);
M
Matt Fleming 已提交
342
	if (status == EFI_BUFFER_TOO_SMALL)
343
		status = efi_setup_gop(NULL, si, &graphics_proto, size);
M
Matt Fleming 已提交
344 345 346

	if (status != EFI_SUCCESS) {
		size = 0;
347 348 349
		status = efi_call_early(locate_handle,
					EFI_LOCATE_BY_PROTOCOL,
					&uga_proto, NULL, &size, uga_handle);
M
Matt Fleming 已提交
350 351 352 353 354
		if (status == EFI_BUFFER_TOO_SMALL)
			setup_uga(si, &uga_proto, size);
	}
}

355 356 357 358 359 360
void startup_32(struct boot_params *boot_params);

void __noreturn efi_stub_entry(efi_handle_t handle,
			       efi_system_table_t *sys_table_arg,
			       struct boot_params *boot_params);

M
Matt Fleming 已提交
361 362 363 364 365
/*
 * Because the x86 boot code expects to be passed a boot_params we
 * need to create one ourselves (usually the bootloader would create
 * one for us).
 */
366 367
efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
				   efi_system_table_t *sys_table_arg)
M
Matt Fleming 已提交
368
{
M
Matt Fleming 已提交
369 370 371 372 373
	struct boot_params *boot_params;
	struct apm_bios_info *bi;
	struct setup_header *hdr;
	efi_loaded_image_t *image;
	efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
M
Matt Fleming 已提交
374 375
	int options_size = 0;
	efi_status_t status;
376
	char *cmdline_ptr;
377 378
	unsigned long ramdisk_addr;
	unsigned long ramdisk_size;
M
Matt Fleming 已提交
379

380
	sys_table = sys_table_arg;
M
Matt Fleming 已提交
381 382 383

	/* Check if we were booted by the EFI firmware */
	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
384
		return EFI_INVALID_PARAMETER;
385

386 387
	status = efi_call_early(handle_protocol, handle,
				&proto, (void *)&image);
M
Matt Fleming 已提交
388
	if (status != EFI_SUCCESS) {
389
		efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
390
		return status;
M
Matt Fleming 已提交
391 392
	}

393 394
	status = efi_low_alloc(sys_table, 0x4000, 1,
			       (unsigned long *)&boot_params);
M
Matt Fleming 已提交
395
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
396
		efi_printk(sys_table, "Failed to allocate lowmem for boot params\n");
397
		return status;
M
Matt Fleming 已提交
398 399 400 401 402 403 404 405 406 407 408 409 410 411
	}

	memset(boot_params, 0x0, 0x4000);

	hdr = &boot_params->hdr;
	bi = &boot_params->apm_bios_info;

	/* Copy the second sector to boot_params */
	memcpy(&hdr->jump, image->image_base + 512, 512);

	/*
	 * Fill out some of the header fields ourselves because the
	 * EFI firmware loader doesn't load the first sector.
	 */
I
Ingo Molnar 已提交
412 413 414
	hdr->root_flags	= 1;
	hdr->vid_mode	= 0xffff;
	hdr->boot_flag	= 0xAA55;
M
Matt Fleming 已提交
415

M
Matt Fleming 已提交
416 417 418
	hdr->type_of_loader = 0x21;

	/* Convert unicode cmdline to ascii */
419
	cmdline_ptr = efi_convert_cmdline(sys_table, image, &options_size);
420 421
	if (!cmdline_ptr)
		goto fail;
I
Ingo Molnar 已提交
422

423
	hdr->cmd_line_ptr = (unsigned long)cmdline_ptr;
424 425
	/* Fill in upper bits of command line address, NOP on 32 bit  */
	boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32;
M
Matt Fleming 已提交
426 427 428 429 430 431 432

	hdr->ramdisk_image = 0;
	hdr->ramdisk_size = 0;

	/* Clear APM BIOS info */
	memset(bi, 0, sizeof(*bi));

433 434 435 436
	status = efi_parse_options(cmdline_ptr);
	if (status != EFI_SUCCESS)
		goto fail2;

437 438
	status = handle_cmdline_files(sys_table, image,
				      (char *)(unsigned long)hdr->cmd_line_ptr,
439
				      "initrd=", hdr->initrd_addr_max,
440
				      &ramdisk_addr, &ramdisk_size);
441 442 443 444 445 446 447 448 449 450

	if (status != EFI_SUCCESS &&
	    hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G) {
		efi_printk(sys_table, "Trying to load files to higher address\n");
		status = handle_cmdline_files(sys_table, image,
				      (char *)(unsigned long)hdr->cmd_line_ptr,
				      "initrd=", -1UL,
				      &ramdisk_addr, &ramdisk_size);
	}

M
Matt Fleming 已提交
451 452
	if (status != EFI_SUCCESS)
		goto fail2;
453 454 455 456
	hdr->ramdisk_image = ramdisk_addr & 0xffffffff;
	hdr->ramdisk_size  = ramdisk_size & 0xffffffff;
	boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32;
	boot_params->ext_ramdisk_size  = (u64)ramdisk_size >> 32;
M
Matt Fleming 已提交
457

458 459 460 461
	hdr->code32_start = (u32)(unsigned long)startup_32;

	efi_stub_entry(handle, sys_table, boot_params);
	/* not reached */
I
Ingo Molnar 已提交
462

M
Matt Fleming 已提交
463
fail2:
464
	efi_free(sys_table, options_size, hdr->cmd_line_ptr);
M
Matt Fleming 已提交
465
fail:
466
	efi_free(sys_table, 0x4000, (unsigned long)boot_params);
I
Ingo Molnar 已提交
467

468
	return status;
M
Matt Fleming 已提交
469 470
}

471 472
static void add_e820ext(struct boot_params *params,
			struct setup_data *e820ext, u32 nr_entries)
M
Matt Fleming 已提交
473
{
474
	struct setup_data *data;
M
Matt Fleming 已提交
475

476
	e820ext->type = SETUP_E820_EXT;
I
Ingo Molnar 已提交
477
	e820ext->len  = nr_entries * sizeof(struct boot_e820_entry);
478
	e820ext->next = 0;
M
Matt Fleming 已提交
479

480
	data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
M
Matt Fleming 已提交
481

482 483
	while (data && data->next)
		data = (struct setup_data *)(unsigned long)data->next;
484

485 486 487 488 489
	if (data)
		data->next = (unsigned long)e820ext;
	else
		params->hdr.setup_data = (unsigned long)e820ext;
}
M
Matt Fleming 已提交
490

I
Ingo Molnar 已提交
491 492
static efi_status_t
setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_size)
493
{
494
	struct boot_e820_entry *entry = params->e820_table;
495
	struct efi_info *efi = &params->efi_info;
496
	struct boot_e820_entry *prev = NULL;
497 498 499
	u32 nr_entries;
	u32 nr_desc;
	int i;
M
Matt Fleming 已提交
500 501

	nr_entries = 0;
502 503 504
	nr_desc = efi->efi_memmap_size / efi->efi_memdesc_size;

	for (i = 0; i < nr_desc; i++) {
M
Matt Fleming 已提交
505 506
		efi_memory_desc_t *d;
		unsigned int e820_type = 0;
507
		unsigned long m = efi->efi_memmap;
M
Matt Fleming 已提交
508

509 510 511 512
#ifdef CONFIG_X86_64
		m |= (u64)efi->efi_memmap_hi << 32;
#endif

513
		d = efi_early_memdesc_ptr(m, efi->efi_memdesc_size, i);
M
Matt Fleming 已提交
514 515 516 517 518 519 520
		switch (d->type) {
		case EFI_RESERVED_TYPE:
		case EFI_RUNTIME_SERVICES_CODE:
		case EFI_RUNTIME_SERVICES_DATA:
		case EFI_MEMORY_MAPPED_IO:
		case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
		case EFI_PAL_CODE:
521
			e820_type = E820_TYPE_RESERVED;
M
Matt Fleming 已提交
522 523 524
			break;

		case EFI_UNUSABLE_MEMORY:
525
			e820_type = E820_TYPE_UNUSABLE;
M
Matt Fleming 已提交
526 527 528
			break;

		case EFI_ACPI_RECLAIM_MEMORY:
529
			e820_type = E820_TYPE_ACPI;
M
Matt Fleming 已提交
530 531 532 533 534 535 536
			break;

		case EFI_LOADER_CODE:
		case EFI_LOADER_DATA:
		case EFI_BOOT_SERVICES_CODE:
		case EFI_BOOT_SERVICES_DATA:
		case EFI_CONVENTIONAL_MEMORY:
537 538 539 540 541
			if (efi_soft_reserve_enabled() &&
			    (d->attribute & EFI_MEMORY_SP))
				e820_type = E820_TYPE_SOFT_RESERVED;
			else
				e820_type = E820_TYPE_RAM;
M
Matt Fleming 已提交
542 543 544
			break;

		case EFI_ACPI_MEMORY_NVS:
545
			e820_type = E820_TYPE_NVS;
M
Matt Fleming 已提交
546 547
			break;

548
		case EFI_PERSISTENT_MEMORY:
549
			e820_type = E820_TYPE_PMEM;
550 551
			break;

M
Matt Fleming 已提交
552 553 554 555 556 557
		default:
			continue;
		}

		/* Merge adjacent mappings */
		if (prev && prev->type == e820_type &&
558
		    (prev->addr + prev->size) == d->phys_addr) {
M
Matt Fleming 已提交
559
			prev->size += d->num_pages << 12;
560
			continue;
M
Matt Fleming 已提交
561
		}
562

563
		if (nr_entries == ARRAY_SIZE(params->e820_table)) {
564
			u32 need = (nr_desc - i) * sizeof(struct e820_entry) +
565 566 567 568 569 570
				   sizeof(struct setup_data);

			if (!e820ext || e820ext_size < need)
				return EFI_BUFFER_TOO_SMALL;

			/* boot_params map full, switch to e820 extended */
571
			entry = (struct boot_e820_entry *)e820ext->data;
572 573
		}

574 575 576 577
		entry->addr = d->phys_addr;
		entry->size = d->num_pages << PAGE_SHIFT;
		entry->type = e820_type;
		prev = entry++;
578
		nr_entries++;
M
Matt Fleming 已提交
579 580
	}

581 582
	if (nr_entries > ARRAY_SIZE(params->e820_table)) {
		u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_table);
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599

		add_e820ext(params, e820ext, nr_e820ext);
		nr_entries -= nr_e820ext;
	}

	params->e820_entries = (u8)nr_entries;

	return EFI_SUCCESS;
}

static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
				  u32 *e820ext_size)
{
	efi_status_t status;
	unsigned long size;

	size = sizeof(struct setup_data) +
600
		sizeof(struct e820_entry) * nr_desc;
601 602

	if (*e820ext) {
603
		efi_call_early(free_pool, *e820ext);
604 605 606 607
		*e820ext = NULL;
		*e820ext_size = 0;
	}

608 609
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
				size, (void **)e820ext);
610 611 612 613 614 615
	if (status == EFI_SUCCESS)
		*e820ext_size = size;

	return status;
}

616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
static efi_status_t allocate_e820(struct boot_params *params,
				  struct setup_data **e820ext,
				  u32 *e820ext_size)
{
	unsigned long map_size, desc_size, buff_size;
	struct efi_boot_memmap boot_map;
	efi_memory_desc_t *map;
	efi_status_t status;
	__u32 nr_desc;

	boot_map.map		= &map;
	boot_map.map_size	= &map_size;
	boot_map.desc_size	= &desc_size;
	boot_map.desc_ver	= NULL;
	boot_map.key_ptr	= NULL;
	boot_map.buff_size	= &buff_size;

	status = efi_get_memory_map(sys_table, &boot_map);
	if (status != EFI_SUCCESS)
		return status;

	nr_desc = buff_size / desc_size;

	if (nr_desc > ARRAY_SIZE(params->e820_table)) {
		u32 nr_e820ext = nr_desc - ARRAY_SIZE(params->e820_table);

		status = alloc_e820ext(nr_e820ext, e820ext, e820ext_size);
		if (status != EFI_SUCCESS)
			return status;
	}

	return EFI_SUCCESS;
}

650
struct exit_boot_struct {
I
Ingo Molnar 已提交
651 652
	struct boot_params	*boot_params;
	struct efi_info		*efi;
653 654 655 656 657 658 659 660 661
};

static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
				   struct efi_boot_memmap *map,
				   void *priv)
{
	const char *signature;
	struct exit_boot_struct *p = priv;

662 663
	signature = efi_is_64bit() ? EFI64_LOADER_SIGNATURE
				   : EFI32_LOADER_SIGNATURE;
664 665
	memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));

I
Ingo Molnar 已提交
666 667 668 669 670
	p->efi->efi_systab		= (unsigned long)sys_table_arg;
	p->efi->efi_memdesc_size	= *map->desc_size;
	p->efi->efi_memdesc_version	= *map->desc_ver;
	p->efi->efi_memmap		= (unsigned long)*map->map;
	p->efi->efi_memmap_size		= *map->map_size;
671 672

#ifdef CONFIG_X86_64
I
Ingo Molnar 已提交
673 674
	p->efi->efi_systab_hi		= (unsigned long)sys_table_arg >> 32;
	p->efi->efi_memmap_hi		= (unsigned long)*map->map >> 32;
675 676 677 678 679
#endif

	return EFI_SUCCESS;
}

680
static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
681
{
682
	unsigned long map_sz, key, desc_size, buff_size;
683
	efi_memory_desc_t *mem_map;
684 685
	struct setup_data *e820ext = NULL;
	__u32 e820ext_size = 0;
686 687
	efi_status_t status;
	__u32 desc_version;
688
	struct efi_boot_memmap map;
689 690
	struct exit_boot_struct priv;

I
Ingo Molnar 已提交
691 692 693 694 695 696 697 698
	map.map			= &mem_map;
	map.map_size		= &map_sz;
	map.desc_size		= &desc_size;
	map.desc_ver		= &desc_version;
	map.key_ptr		= &key;
	map.buff_size		= &buff_size;
	priv.boot_params	= boot_params;
	priv.efi		= &boot_params->efi_info;
699 700 701 702

	status = allocate_e820(boot_params, &e820ext, &e820ext_size);
	if (status != EFI_SUCCESS)
		return status;
703

704 705 706
	/* Might as well exit boot services now */
	status = efi_exit_boot_services(sys_table, handle, &map, &priv,
					exit_boot_func);
707 708 709 710
	if (status != EFI_SUCCESS)
		return status;

	/* Historic? */
I
Ingo Molnar 已提交
711
	boot_params->alt_mem_k	= 32 * 1024;
712 713 714 715

	status = setup_e820(boot_params, e820ext, e820ext_size);
	if (status != EFI_SUCCESS)
		return status;
M
Matt Fleming 已提交
716 717 718 719

	return EFI_SUCCESS;
}

M
Matt Fleming 已提交
720 721 722 723
/*
 * On success we return a pointer to a boot_params structure, and NULL
 * on failure.
 */
724 725 726 727
struct boot_params *efi_main(efi_handle_t handle,
			     efi_system_table_t *sys_table_arg,
			     struct boot_params *boot_params,
			     bool is64)
M
Matt Fleming 已提交
728
{
729
	struct desc_ptr *gdt = NULL;
M
Matt Fleming 已提交
730 731 732
	struct setup_header *hdr = &boot_params->hdr;
	efi_status_t status;
	struct desc_struct *desc;
733
	unsigned long cmdline_paddr;
734

735
	sys_table = sys_table_arg;
M
Matt Fleming 已提交
736

737 738
	if (IS_ENABLED(CONFIG_EFI_MIXED))
		efi_is64 = is64;
M
Matt Fleming 已提交
739 740 741 742 743

	/* Check if we were booted by the EFI firmware */
	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
		goto fail;

744 745 746 747 748 749 750 751 752
	/*
	 * make_boot_params() may have been called before efi_main(), in which
	 * case this is the second time we parse the cmdline. This is ok,
	 * parsing the cmdline multiple times does not have side-effects.
	 */
	cmdline_paddr = ((u64)hdr->cmd_line_ptr |
			 ((u64)boot_params->ext_cmd_line_ptr << 32));
	efi_parse_options((char *)cmdline_paddr);

753 754 755 756 757 758
	/*
	 * If the boot loader gave us a value for secure_boot then we use that,
	 * otherwise we ask the BIOS.
	 */
	if (boot_params->secure_boot == efi_secureboot_mode_unset)
		boot_params->secure_boot = efi_get_secureboot(sys_table);
759 760 761

	/* Ask the firmware to clear memory on unclean shutdown */
	efi_enable_reset_attack_mitigation(sys_table);
762 763 764

	efi_random_get_seed(sys_table);

765
	efi_retrieve_tpm2_eventlog(sys_table);
766

M
Matt Fleming 已提交
767
	setup_graphics(boot_params);
M
Matt Fleming 已提交
768

769
	setup_efi_pci(boot_params);
770

771 772
	setup_quirks(boot_params);

773 774
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
				sizeof(*gdt), (void **)&gdt);
775
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
776
		efi_printk(sys_table, "Failed to allocate memory for 'gdt' structure\n");
M
Matt Fleming 已提交
777
		goto fail;
778
	}
M
Matt Fleming 已提交
779 780

	gdt->size = 0x800;
781
	status = efi_low_alloc(sys_table, gdt->size, 8,
782
			   (unsigned long *)&gdt->address);
783
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
784
		efi_printk(sys_table, "Failed to allocate memory for 'gdt'\n");
M
Matt Fleming 已提交
785
		goto fail;
786
	}
M
Matt Fleming 已提交
787

M
Matt Fleming 已提交
788 789 790 791 792
	/*
	 * If the kernel isn't already loaded at the preferred load
	 * address, relocate it.
	 */
	if (hdr->pref_address != hdr->code32_start) {
793 794 795 796
		unsigned long bzimage_addr = hdr->code32_start;
		status = efi_relocate_kernel(sys_table, &bzimage_addr,
					     hdr->init_size, hdr->init_size,
					     hdr->pref_address,
797 798
					     hdr->kernel_alignment,
					     LOAD_PHYSICAL_ADDR);
799 800
		if (status != EFI_SUCCESS) {
			efi_printk(sys_table, "efi_relocate_kernel() failed!\n");
M
Matt Fleming 已提交
801
			goto fail;
802
		}
803 804 805

		hdr->pref_address = hdr->code32_start;
		hdr->code32_start = bzimage_addr;
M
Matt Fleming 已提交
806 807
	}

808
	status = exit_boot(boot_params, handle);
809 810
	if (status != EFI_SUCCESS) {
		efi_printk(sys_table, "exit_boot() failed!\n");
M
Matt Fleming 已提交
811
		goto fail;
812
	}
M
Matt Fleming 已提交
813 814 815 816

	memset((char *)gdt->address, 0x0, gdt->size);
	desc = (struct desc_struct *)gdt->address;

817 818 819 820 821
	/* The first GDT is a dummy. */
	desc++;

	if (IS_ENABLED(CONFIG_X86_64)) {
		/* __KERNEL32_CS */
I
Ingo Molnar 已提交
822 823 824 825 826 827 828 829 830 831 832 833 834 835
		desc->limit0	= 0xffff;
		desc->base0	= 0x0000;
		desc->base1	= 0x0000;
		desc->type	= SEG_TYPE_CODE | SEG_TYPE_EXEC_READ;
		desc->s		= DESC_TYPE_CODE_DATA;
		desc->dpl	= 0;
		desc->p		= 1;
		desc->limit1	= 0xf;
		desc->avl	= 0;
		desc->l		= 0;
		desc->d		= SEG_OP_SIZE_32BIT;
		desc->g		= SEG_GRANULARITY_4KB;
		desc->base2	= 0x00;

836 837 838 839 840
		desc++;
	} else {
		/* Second entry is unused on 32-bit */
		desc++;
	}
M
Matt Fleming 已提交
841

842
	/* __KERNEL_CS */
I
Ingo Molnar 已提交
843 844 845 846 847 848 849 850 851 852
	desc->limit0	= 0xffff;
	desc->base0	= 0x0000;
	desc->base1	= 0x0000;
	desc->type	= SEG_TYPE_CODE | SEG_TYPE_EXEC_READ;
	desc->s		= DESC_TYPE_CODE_DATA;
	desc->dpl	= 0;
	desc->p		= 1;
	desc->limit1	= 0xf;
	desc->avl	= 0;

853 854 855 856 857 858 859
	if (IS_ENABLED(CONFIG_X86_64)) {
		desc->l = 1;
		desc->d = 0;
	} else {
		desc->l = 0;
		desc->d = SEG_OP_SIZE_32BIT;
	}
I
Ingo Molnar 已提交
860 861
	desc->g		= SEG_GRANULARITY_4KB;
	desc->base2	= 0x00;
M
Matt Fleming 已提交
862
	desc++;
863 864

	/* __KERNEL_DS */
I
Ingo Molnar 已提交
865 866 867 868 869 870 871 872 873 874 875 876 877
	desc->limit0	= 0xffff;
	desc->base0	= 0x0000;
	desc->base1	= 0x0000;
	desc->type	= SEG_TYPE_DATA | SEG_TYPE_READ_WRITE;
	desc->s		= DESC_TYPE_CODE_DATA;
	desc->dpl	= 0;
	desc->p		= 1;
	desc->limit1	= 0xf;
	desc->avl	= 0;
	desc->l		= 0;
	desc->d		= SEG_OP_SIZE_32BIT;
	desc->g		= SEG_GRANULARITY_4KB;
	desc->base2	= 0x00;
M
Matt Fleming 已提交
878
	desc++;
879 880 881

	if (IS_ENABLED(CONFIG_X86_64)) {
		/* Task segment value */
I
Ingo Molnar 已提交
882 883 884 885 886 887 888 889 890 891 892 893 894
		desc->limit0	= 0x0000;
		desc->base0	= 0x0000;
		desc->base1	= 0x0000;
		desc->type	= SEG_TYPE_TSS;
		desc->s		= 0;
		desc->dpl	= 0;
		desc->p		= 1;
		desc->limit1	= 0x0;
		desc->avl	= 0;
		desc->l		= 0;
		desc->d		= 0;
		desc->g		= SEG_GRANULARITY_4KB;
		desc->base2	= 0x00;
895 896
		desc++;
	}
M
Matt Fleming 已提交
897 898

	asm volatile("cli");
899
	asm volatile ("lgdt %0" : : "m" (*gdt));
M
Matt Fleming 已提交
900 901 902

	return boot_params;
fail:
903
	efi_printk(sys_table, "efi_main() failed!\n");
I
Ingo Molnar 已提交
904

905 906
	for (;;)
		asm("hlt");
M
Matt Fleming 已提交
907
}