eboot.c 23.9 KB
Newer Older
M
Matt Fleming 已提交
1 2 3 4 5 6 7 8 9 10
/* -----------------------------------------------------------------------
 *
 *   Copyright 2011 Intel Corporation; author Matt Fleming
 *
 *   This file is part of the Linux kernel, and is made available under
 *   the terms of the GNU General Public License version 2.
 *
 * ----------------------------------------------------------------------- */

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

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

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

static efi_system_table_t *sys_table;

23 24
static struct efi_config *efi_early;

A
Ard Biesheuvel 已提交
25 26 27 28
__pure const struct efi_config *__efi_early(void)
{
	return efi_early;
}
29

30 31 32 33 34 35 36
#define BOOT_SERVICES(bits)						\
static void setup_boot_services##bits(struct efi_config *c)		\
{									\
	efi_system_table_##bits##_t *table;				\
									\
	table = (typeof(table))sys_table;				\
									\
I
Ingo Molnar 已提交
37 38 39
	c->runtime_services	= table->runtime;			\
	c->boot_services	= table->boottime;			\
	c->text_output		= table->con_out;			\
40 41 42
}
BOOT_SERVICES(32);
BOOT_SERVICES(64);
M
Matt Fleming 已提交
43

44 45 46 47 48 49 50 51 52 53
static inline efi_status_t __open_volume32(void *__image, void **__fh)
{
	efi_file_io_interface_t *io;
	efi_loaded_image_32_t *image = __image;
	efi_file_handle_32_t *fh;
	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
	efi_status_t status;
	void *handle = (void *)(unsigned long)image->device_handle;
	unsigned long func;

54 55
	status = efi_call_early(handle_protocol, handle,
				&fs_proto, (void **)&io);
56 57 58 59 60 61 62 63 64
	if (status != EFI_SUCCESS) {
		efi_printk(sys_table, "Failed to handle fs_proto\n");
		return status;
	}

	func = (unsigned long)io->open_volume;
	status = efi_early->call(func, io, &fh);
	if (status != EFI_SUCCESS)
		efi_printk(sys_table, "Failed to open volume\n");
M
Matt Fleming 已提交
65

66
	*__fh = fh;
I
Ingo Molnar 已提交
67

68
	return status;
69 70
}

71
static inline efi_status_t __open_volume64(void *__image, void **__fh)
72 73
{
	efi_file_io_interface_t *io;
74 75
	efi_loaded_image_64_t *image = __image;
	efi_file_handle_64_t *fh;
76 77 78
	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
	efi_status_t status;
	void *handle = (void *)(unsigned long)image->device_handle;
79
	unsigned long func;
80

81 82
	status = efi_call_early(handle_protocol, handle,
				&fs_proto, (void **)&io);
83 84 85 86
	if (status != EFI_SUCCESS) {
		efi_printk(sys_table, "Failed to handle fs_proto\n");
		return status;
	}
M
Matt Fleming 已提交
87

88 89 90 91 92 93
	func = (unsigned long)io->open_volume;
	status = efi_early->call(func, io, &fh);
	if (status != EFI_SUCCESS)
		efi_printk(sys_table, "Failed to open volume\n");

	*__fh = fh;
I
Ingo Molnar 已提交
94

95 96 97
	return status;
}

98
efi_status_t
99 100 101 102 103 104 105 106
efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
{
	if (efi_early->is64)
		return __open_volume64(__image, __fh);

	return __open_volume32(__image, __fh);
}

107
void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
108
{
109 110
	efi_call_proto(efi_simple_text_output_protocol, output_string,
		       efi_early->text_output, str);
111 112
}

113
static efi_status_t
114
preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
115
{
116
	struct pci_setup_rom *rom = NULL;
117
	efi_status_t status;
118
	unsigned long size;
119
	uint64_t romsize;
120
	void *romimage;
121

122
	/*
123 124
	 * Some firmware images contain EFI function pointers at the place where
	 * the romimage and romsize fields are supposed to be. Typically the EFI
125 126 127 128
	 * 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.
	 */
129 130 131
	romimage = (void *)(unsigned long)efi_table_attr(efi_pci_io_protocol,
							 romimage, pci);
	romsize = efi_table_attr(efi_pci_io_protocol, romsize, pci);
132
	if (!romimage || !romsize || romsize > SZ_16M)
133
		return EFI_INVALID_PARAMETER;
134

135
	size = romsize + sizeof(*rom);
136

137
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
138
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
139
		efi_printk(sys_table, "Failed to allocate memory for 'rom'\n");
140
		return status;
141
	}
142

143 144
	memset(rom, 0, sizeof(*rom));

I
Ingo Molnar 已提交
145 146 147 148
	rom->data.type	= SETUP_PCI;
	rom->data.len	= size - sizeof(struct setup_data);
	rom->data.next	= 0;
	rom->pcilen	= pci->romsize;
149 150
	*__rom = rom;

151 152 153
	status = efi_call_proto(efi_pci_io_protocol, pci.read, pci,
				EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
				&rom->vendor);
154

155 156
	if (status != EFI_SUCCESS) {
		efi_printk(sys_table, "Failed to read rom->vendor\n");
157
		goto free_struct;
158
	}
159

160 161 162
	status = efi_call_proto(efi_pci_io_protocol, pci.read, pci,
				EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
				&rom->devid);
163

164 165
	if (status != EFI_SUCCESS) {
		efi_printk(sys_table, "Failed to read rom->devid\n");
166
		goto free_struct;
167
	}
168

169 170 171
	status = efi_call_proto(efi_pci_io_protocol, get_location, pci,
				&rom->segment, &rom->bus, &rom->device,
				&rom->function);
172 173 174 175

	if (status != EFI_SUCCESS)
		goto free_struct;

176
	memcpy(rom->romdata, romimage, romsize);
177 178 179
	return status;

free_struct:
180
	efi_call_early(free_pool, rom);
181 182 183
	return status;
}

184 185 186 187 188 189 190 191 192 193
/*
 * 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 已提交
194 195
{
	efi_status_t status;
196 197 198
	void **pci_handle = NULL;
	efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
	unsigned long size = 0;
199 200 201
	unsigned long nr_pci;
	struct setup_data *data;
	int i;
M
Matt Fleming 已提交
202

203 204 205
	status = efi_call_early(locate_handle,
				EFI_LOCATE_BY_PROTOCOL,
				&pci_proto, NULL, &size, pci_handle);
M
Matt Fleming 已提交
206

207
	if (status == EFI_BUFFER_TOO_SMALL) {
208 209 210
		status = efi_call_early(allocate_pool,
					EFI_LOADER_DATA,
					size, (void **)&pci_handle);
M
Matt Fleming 已提交
211

212
		if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
213
			efi_printk(sys_table, "Failed to allocate memory for 'pci_handle'\n");
214
			return;
215
		}
M
Matt Fleming 已提交
216

217 218 219
		status = efi_call_early(locate_handle,
					EFI_LOCATE_BY_PROTOCOL, &pci_proto,
					NULL, &size, pci_handle);
M
Matt Fleming 已提交
220 221
	}

222
	if (status != EFI_SUCCESS)
M
Matt Fleming 已提交
223 224
		goto free_handle;

225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
	data = (struct setup_data *)(unsigned long)params->hdr.setup_data;

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

	nr_pci = size / (efi_is_64bit() ? sizeof(u64) : sizeof(u32));
	for (i = 0; i < nr_pci; i++) {
		efi_pci_io_protocol_t *pci = NULL;
		struct pci_setup_rom *rom;

		status = efi_call_early(handle_protocol,
					efi_is_64bit() ? ((u64 *)pci_handle)[i]
						       : ((u32 *)pci_handle)[i],
					&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 已提交
253

254
free_handle:
255
	efi_call_early(free_pool, pci_handle);
256
}
M
Matt Fleming 已提交
257

258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
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;
	void *p;

	status = efi_call_early(locate_protocol, &guid, NULL, &p);
	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,
					size + sizeof(struct setup_data), &new);
		if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
283
			efi_printk(sys_table, "Failed to allocate memory for 'properties'\n");
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
			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 已提交
299
	if (!data) {
300
		boot_params->hdr.setup_data = (unsigned long)new;
I
Ingo Molnar 已提交
301
	} else {
302 303 304 305 306 307
		while (data->next)
			data = (struct setup_data *)(unsigned long)data->next;
		data->next = (unsigned long)new;
	}
}

308 309
static const efi_char16_t apple[] = L"Apple";

310 311 312 313 314 315 316 317 318 319 320
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);
	}
}

321 322 323
/*
 * See if we have Universal Graphics Adapter (UGA) protocol
 */
324
static efi_status_t
325
setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
326
{
327 328 329
	efi_status_t status;
	u32 width, height;
	void **uga_handle = NULL;
330
	efi_uga_draw_protocol_t *uga = NULL, *first_uga;
331 332 333
	unsigned long nr_ugas;
	int i;

334 335 336 337
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
				size, (void **)&uga_handle);
	if (status != EFI_SUCCESS)
		return status;
338

339 340 341 342 343
	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 已提交
344

345 346
	height = 0;
	width = 0;
347 348

	first_uga = NULL;
349
	nr_ugas = size / (efi_is_64bit() ? sizeof(u64) : sizeof(u32));
M
Matt Fleming 已提交
350 351 352 353
	for (i = 0; i < nr_ugas; i++) {
		efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
		u32 w, h, depth, refresh;
		void *pciio;
354 355
		unsigned long handle = efi_is_64bit() ? ((u64 *)uga_handle)[i]
						      : ((u32 *)uga_handle)[i];
M
Matt Fleming 已提交
356

357
		status = efi_call_early(handle_protocol, handle,
358
					uga_proto, (void **)&uga);
M
Matt Fleming 已提交
359 360 361
		if (status != EFI_SUCCESS)
			continue;

362
		efi_call_early(handle_protocol, handle, &pciio_proto, &pciio);
M
Matt Fleming 已提交
363

364 365
		status = efi_call_proto(efi_uga_draw_protocol, get_mode, uga,
					&w, &h, &depth, &refresh);
M
Matt Fleming 已提交
366
		if (status == EFI_SUCCESS && (!first_uga || pciio)) {
367 368
			width = w;
			height = h;
M
Matt Fleming 已提交
369 370 371 372 373 374 375 376 377 378 379 380

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

			first_uga = uga;
		}
	}

381
	if (!width && !height)
M
Matt Fleming 已提交
382 383 384
		goto free_handle;

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

I
Ingo Molnar 已提交
387 388 389
	si->lfb_depth		= 32;
	si->lfb_width		= width;
	si->lfb_height		= height;
M
Matt Fleming 已提交
390

I
Ingo Molnar 已提交
391 392 393 394 395 396 397 398
	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 已提交
399 400

free_handle:
401
	efi_call_early(free_pool, uga_handle);
I
Ingo Molnar 已提交
402

M
Matt Fleming 已提交
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
	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;
420 421 422
	status = efi_call_early(locate_handle,
				EFI_LOCATE_BY_PROTOCOL,
				&graphics_proto, NULL, &size, gop_handle);
M
Matt Fleming 已提交
423
	if (status == EFI_BUFFER_TOO_SMALL)
424
		status = efi_setup_gop(NULL, si, &graphics_proto, size);
M
Matt Fleming 已提交
425 426 427

	if (status != EFI_SUCCESS) {
		size = 0;
428 429 430
		status = efi_call_early(locate_handle,
					EFI_LOCATE_BY_PROTOCOL,
					&uga_proto, NULL, &size, uga_handle);
M
Matt Fleming 已提交
431 432 433 434 435 436 437 438 439
		if (status == EFI_BUFFER_TOO_SMALL)
			setup_uga(si, &uga_proto, size);
	}
}

/*
 * 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).
440 441 442
 *
 * The caller is responsible for filling out ->code32_start in the
 * returned boot_params.
M
Matt Fleming 已提交
443
 */
444
struct boot_params *make_boot_params(struct efi_config *c)
M
Matt Fleming 已提交
445
{
M
Matt Fleming 已提交
446 447 448 449
	struct boot_params *boot_params;
	struct apm_bios_info *bi;
	struct setup_header *hdr;
	efi_loaded_image_t *image;
450
	void *options, *handle;
M
Matt Fleming 已提交
451
	efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
M
Matt Fleming 已提交
452 453
	int options_size = 0;
	efi_status_t status;
454
	char *cmdline_ptr;
M
Matt Fleming 已提交
455 456 457
	u16 *s2;
	u8 *s1;
	int i;
458 459
	unsigned long ramdisk_addr;
	unsigned long ramdisk_size;
M
Matt Fleming 已提交
460

461 462 463
	efi_early = c;
	sys_table = (efi_system_table_t *)(unsigned long)efi_early->table;
	handle = (void *)(unsigned long)efi_early->image_handle;
M
Matt Fleming 已提交
464 465 466 467 468

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

469 470 471 472 473
	if (efi_early->is64)
		setup_boot_services64(efi_early);
	else
		setup_boot_services32(efi_early);

474 475
	status = efi_call_early(handle_protocol, handle,
				&proto, (void *)&image);
M
Matt Fleming 已提交
476
	if (status != EFI_SUCCESS) {
477
		efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
M
Matt Fleming 已提交
478 479 480
		return NULL;
	}

481 482
	status = efi_low_alloc(sys_table, 0x4000, 1,
			       (unsigned long *)&boot_params);
M
Matt Fleming 已提交
483
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
484
		efi_printk(sys_table, "Failed to allocate lowmem for boot params\n");
M
Matt Fleming 已提交
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
		return NULL;
	}

	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 已提交
500 501 502
	hdr->root_flags	= 1;
	hdr->vid_mode	= 0xffff;
	hdr->boot_flag	= 0xAA55;
M
Matt Fleming 已提交
503

M
Matt Fleming 已提交
504 505 506
	hdr->type_of_loader = 0x21;

	/* Convert unicode cmdline to ascii */
507
	cmdline_ptr = efi_convert_cmdline(sys_table, image, &options_size);
508 509
	if (!cmdline_ptr)
		goto fail;
I
Ingo Molnar 已提交
510

511
	hdr->cmd_line_ptr = (unsigned long)cmdline_ptr;
512 513
	/* 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 已提交
514 515 516 517 518 519 520

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

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

521 522 523 524
	status = efi_parse_options(cmdline_ptr);
	if (status != EFI_SUCCESS)
		goto fail2;

525 526
	status = handle_cmdline_files(sys_table, image,
				      (char *)(unsigned long)hdr->cmd_line_ptr,
527
				      "initrd=", hdr->initrd_addr_max,
528
				      &ramdisk_addr, &ramdisk_size);
529 530 531 532 533 534 535 536 537 538

	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 已提交
539 540
	if (status != EFI_SUCCESS)
		goto fail2;
541 542 543 544
	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 已提交
545 546

	return boot_params;
I
Ingo Molnar 已提交
547

M
Matt Fleming 已提交
548
fail2:
549
	efi_free(sys_table, options_size, hdr->cmd_line_ptr);
M
Matt Fleming 已提交
550
fail:
551
	efi_free(sys_table, 0x4000, (unsigned long)boot_params);
I
Ingo Molnar 已提交
552

M
Matt Fleming 已提交
553 554 555
	return NULL;
}

556 557
static void add_e820ext(struct boot_params *params,
			struct setup_data *e820ext, u32 nr_entries)
M
Matt Fleming 已提交
558
{
559
	struct setup_data *data;
M
Matt Fleming 已提交
560
	efi_status_t status;
561
	unsigned long size;
M
Matt Fleming 已提交
562

563
	e820ext->type = SETUP_E820_EXT;
I
Ingo Molnar 已提交
564
	e820ext->len  = nr_entries * sizeof(struct boot_e820_entry);
565
	e820ext->next = 0;
M
Matt Fleming 已提交
566

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

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

572 573 574 575 576
	if (data)
		data->next = (unsigned long)e820ext;
	else
		params->hdr.setup_data = (unsigned long)e820ext;
}
M
Matt Fleming 已提交
577

I
Ingo Molnar 已提交
578 579
static efi_status_t
setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_size)
580
{
581
	struct boot_e820_entry *entry = params->e820_table;
582
	struct efi_info *efi = &params->efi_info;
583
	struct boot_e820_entry *prev = NULL;
584 585 586
	u32 nr_entries;
	u32 nr_desc;
	int i;
M
Matt Fleming 已提交
587 588

	nr_entries = 0;
589 590 591
	nr_desc = efi->efi_memmap_size / efi->efi_memdesc_size;

	for (i = 0; i < nr_desc; i++) {
M
Matt Fleming 已提交
592 593
		efi_memory_desc_t *d;
		unsigned int e820_type = 0;
594
		unsigned long m = efi->efi_memmap;
M
Matt Fleming 已提交
595

596 597 598 599
#ifdef CONFIG_X86_64
		m |= (u64)efi->efi_memmap_hi << 32;
#endif

600
		d = efi_early_memdesc_ptr(m, efi->efi_memdesc_size, i);
M
Matt Fleming 已提交
601 602 603 604 605 606 607
		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:
608
			e820_type = E820_TYPE_RESERVED;
M
Matt Fleming 已提交
609 610 611
			break;

		case EFI_UNUSABLE_MEMORY:
612
			e820_type = E820_TYPE_UNUSABLE;
M
Matt Fleming 已提交
613 614 615
			break;

		case EFI_ACPI_RECLAIM_MEMORY:
616
			e820_type = E820_TYPE_ACPI;
M
Matt Fleming 已提交
617 618 619 620 621 622 623
			break;

		case EFI_LOADER_CODE:
		case EFI_LOADER_DATA:
		case EFI_BOOT_SERVICES_CODE:
		case EFI_BOOT_SERVICES_DATA:
		case EFI_CONVENTIONAL_MEMORY:
624
			e820_type = E820_TYPE_RAM;
M
Matt Fleming 已提交
625 626 627
			break;

		case EFI_ACPI_MEMORY_NVS:
628
			e820_type = E820_TYPE_NVS;
M
Matt Fleming 已提交
629 630
			break;

631
		case EFI_PERSISTENT_MEMORY:
632
			e820_type = E820_TYPE_PMEM;
633 634
			break;

M
Matt Fleming 已提交
635 636 637 638 639 640
		default:
			continue;
		}

		/* Merge adjacent mappings */
		if (prev && prev->type == e820_type &&
641
		    (prev->addr + prev->size) == d->phys_addr) {
M
Matt Fleming 已提交
642
			prev->size += d->num_pages << 12;
643
			continue;
M
Matt Fleming 已提交
644
		}
645

646
		if (nr_entries == ARRAY_SIZE(params->e820_table)) {
647
			u32 need = (nr_desc - i) * sizeof(struct e820_entry) +
648 649 650 651 652 653
				   sizeof(struct setup_data);

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

			/* boot_params map full, switch to e820 extended */
654
			entry = (struct boot_e820_entry *)e820ext->data;
655 656
		}

657 658 659 660
		entry->addr = d->phys_addr;
		entry->size = d->num_pages << PAGE_SHIFT;
		entry->type = e820_type;
		prev = entry++;
661
		nr_entries++;
M
Matt Fleming 已提交
662 663
	}

664 665
	if (nr_entries > ARRAY_SIZE(params->e820_table)) {
		u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_table);
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682

		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) +
683
		sizeof(struct e820_entry) * nr_desc;
684 685

	if (*e820ext) {
686
		efi_call_early(free_pool, *e820ext);
687 688 689 690
		*e820ext = NULL;
		*e820ext_size = 0;
	}

691 692
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
				size, (void **)e820ext);
693 694 695 696 697 698
	if (status == EFI_SUCCESS)
		*e820ext_size = size;

	return status;
}

699
struct exit_boot_struct {
I
Ingo Molnar 已提交
700 701 702 703 704
	struct boot_params	*boot_params;
	struct efi_info		*efi;
	struct setup_data	*e820ext;
	__u32			e820ext_size;
	bool			is64;
705 706 707 708 709 710 711 712 713 714 715 716 717 718
};

static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
				   struct efi_boot_memmap *map,
				   void *priv)
{
	static bool first = true;
	const char *signature;
	__u32 nr_desc;
	efi_status_t status;
	struct exit_boot_struct *p = priv;

	if (first) {
		nr_desc = *map->buff_size / *map->desc_size;
719
		if (nr_desc > ARRAY_SIZE(p->boot_params->e820_table)) {
720
			u32 nr_e820ext = nr_desc -
721
					ARRAY_SIZE(p->boot_params->e820_table);
722 723 724 725 726 727 728 729 730 731 732 733

			status = alloc_e820ext(nr_e820ext, &p->e820ext,
					       &p->e820ext_size);
			if (status != EFI_SUCCESS)
				return status;
		}
		first = false;
	}

	signature = p->is64 ? EFI64_LOADER_SIGNATURE : EFI32_LOADER_SIGNATURE;
	memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));

I
Ingo Molnar 已提交
734 735 736 737 738
	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;
739 740

#ifdef CONFIG_X86_64
I
Ingo Molnar 已提交
741 742
	p->efi->efi_systab_hi		= (unsigned long)sys_table_arg >> 32;
	p->efi->efi_memmap_hi		= (unsigned long)*map->map >> 32;
743 744 745 746 747
#endif

	return EFI_SUCCESS;
}

748
static efi_status_t exit_boot(struct boot_params *boot_params,
749
			      void *handle, bool is64)
750
{
751
	unsigned long map_sz, key, desc_size, buff_size;
752 753 754 755 756
	efi_memory_desc_t *mem_map;
	struct setup_data *e820ext;
	__u32 e820ext_size;
	efi_status_t status;
	__u32 desc_version;
757
	struct efi_boot_memmap map;
758 759
	struct exit_boot_struct priv;

I
Ingo Molnar 已提交
760 761 762 763 764 765 766 767 768 769 770
	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;
	priv.e820ext		= NULL;
	priv.e820ext_size	= 0;
	priv.is64		= is64;
771

772 773 774
	/* Might as well exit boot services now */
	status = efi_exit_boot_services(sys_table, handle, &map, &priv,
					exit_boot_func);
775 776 777
	if (status != EFI_SUCCESS)
		return status;

I
Ingo Molnar 已提交
778 779 780
	e820ext			= priv.e820ext;
	e820ext_size		= priv.e820ext_size;

781
	/* Historic? */
I
Ingo Molnar 已提交
782
	boot_params->alt_mem_k	= 32 * 1024;
783 784 785 786

	status = setup_e820(boot_params, e820ext, e820ext_size);
	if (status != EFI_SUCCESS)
		return status;
M
Matt Fleming 已提交
787 788 789 790

	return EFI_SUCCESS;
}

M
Matt Fleming 已提交
791 792 793 794
/*
 * On success we return a pointer to a boot_params structure, and NULL
 * on failure.
 */
I
Ingo Molnar 已提交
795 796
struct boot_params *
efi_main(struct efi_config *c, struct boot_params *boot_params)
M
Matt Fleming 已提交
797
{
798
	struct desc_ptr *gdt = NULL;
M
Matt Fleming 已提交
799 800 801 802
	efi_loaded_image_t *image;
	struct setup_header *hdr = &boot_params->hdr;
	efi_status_t status;
	struct desc_struct *desc;
803 804 805 806 807 808 809 810 811
	void *handle;
	efi_system_table_t *_table;
	bool is64;

	efi_early = c;

	_table = (efi_system_table_t *)(unsigned long)efi_early->table;
	handle = (void *)(unsigned long)efi_early->image_handle;
	is64 = efi_early->is64;
M
Matt Fleming 已提交
812 813 814 815 816 817 818

	sys_table = _table;

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

819 820 821 822 823
	if (is64)
		setup_boot_services64(efi_early);
	else
		setup_boot_services32(efi_early);

824 825 826 827 828 829
	/*
	 * 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);
830 831 832

	/* Ask the firmware to clear memory on unclean shutdown */
	efi_enable_reset_attack_mitigation(sys_table);
833
	efi_retrieve_tpm2_eventlog(sys_table);
834

M
Matt Fleming 已提交
835
	setup_graphics(boot_params);
M
Matt Fleming 已提交
836

837
	setup_efi_pci(boot_params);
838

839 840
	setup_quirks(boot_params);

841 842
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
				sizeof(*gdt), (void **)&gdt);
843
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
844
		efi_printk(sys_table, "Failed to allocate memory for 'gdt' structure\n");
M
Matt Fleming 已提交
845
		goto fail;
846
	}
M
Matt Fleming 已提交
847 848

	gdt->size = 0x800;
849
	status = efi_low_alloc(sys_table, gdt->size, 8,
850
			   (unsigned long *)&gdt->address);
851
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
852
		efi_printk(sys_table, "Failed to allocate memory for 'gdt'\n");
M
Matt Fleming 已提交
853
		goto fail;
854
	}
M
Matt Fleming 已提交
855

M
Matt Fleming 已提交
856 857 858 859 860
	/*
	 * If the kernel isn't already loaded at the preferred load
	 * address, relocate it.
	 */
	if (hdr->pref_address != hdr->code32_start) {
861 862 863 864 865
		unsigned long bzimage_addr = hdr->code32_start;
		status = efi_relocate_kernel(sys_table, &bzimage_addr,
					     hdr->init_size, hdr->init_size,
					     hdr->pref_address,
					     hdr->kernel_alignment);
866 867
		if (status != EFI_SUCCESS) {
			efi_printk(sys_table, "efi_relocate_kernel() failed!\n");
M
Matt Fleming 已提交
868
			goto fail;
869
		}
870 871 872

		hdr->pref_address = hdr->code32_start;
		hdr->code32_start = bzimage_addr;
M
Matt Fleming 已提交
873 874
	}

875
	status = exit_boot(boot_params, handle, is64);
876 877
	if (status != EFI_SUCCESS) {
		efi_printk(sys_table, "exit_boot() failed!\n");
M
Matt Fleming 已提交
878
		goto fail;
879
	}
M
Matt Fleming 已提交
880 881 882 883

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

884 885 886 887 888
	/* The first GDT is a dummy. */
	desc++;

	if (IS_ENABLED(CONFIG_X86_64)) {
		/* __KERNEL32_CS */
I
Ingo Molnar 已提交
889 890 891 892 893 894 895 896 897 898 899 900 901 902
		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;

903 904 905 906 907
		desc++;
	} else {
		/* Second entry is unused on 32-bit */
		desc++;
	}
M
Matt Fleming 已提交
908

909
	/* __KERNEL_CS */
I
Ingo Molnar 已提交
910 911 912 913 914 915 916 917 918 919
	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;

920 921 922 923 924 925 926
	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 已提交
927 928
	desc->g		= SEG_GRANULARITY_4KB;
	desc->base2	= 0x00;
M
Matt Fleming 已提交
929
	desc++;
930 931

	/* __KERNEL_DS */
I
Ingo Molnar 已提交
932 933 934 935 936 937 938 939 940 941 942 943 944
	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 已提交
945
	desc++;
946 947 948

	if (IS_ENABLED(CONFIG_X86_64)) {
		/* Task segment value */
I
Ingo Molnar 已提交
949 950 951 952 953 954 955 956 957 958 959 960 961
		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;
962 963
		desc++;
	}
M
Matt Fleming 已提交
964 965

	asm volatile("cli");
966
	asm volatile ("lgdt %0" : : "m" (*gdt));
M
Matt Fleming 已提交
967 968 969

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

M
Matt Fleming 已提交
972 973
	return NULL;
}