eboot.c 25.3 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 324 325 326
static efi_status_t
setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
{
	struct efi_uga_draw_protocol *uga = NULL, *first_uga;
	efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
	unsigned long nr_ugas;
327
	u32 *handles = (u32 *)uga_handle;
328
	efi_status_t status = EFI_INVALID_PARAMETER;
329 330
	int i;

M
Matt Fleming 已提交
331
	first_uga = NULL;
332 333 334 335 336 337 338
	nr_ugas = size / sizeof(u32);
	for (i = 0; i < nr_ugas; i++) {
		efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
		u32 w, h, depth, refresh;
		void *pciio;
		u32 handle = handles[i];

339 340
		status = efi_call_early(handle_protocol, handle,
					&uga_proto, (void **)&uga);
341 342 343
		if (status != EFI_SUCCESS)
			continue;

344
		efi_call_early(handle_protocol, handle, &pciio_proto, &pciio);
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364

		status = efi_early->call((unsigned long)uga->get_mode, uga,
					 &w, &h, &depth, &refresh);
		if (status == EFI_SUCCESS && (!first_uga || pciio)) {
			*width = w;
			*height = h;

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

			first_uga = uga;
		}
	}

	return status;
}
M
Matt Fleming 已提交
365

366 367 368 369 370 371
static efi_status_t
setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height)
{
	struct efi_uga_draw_protocol *uga = NULL, *first_uga;
	efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
	unsigned long nr_ugas;
372
	u64 *handles = (u64 *)uga_handle;
373
	efi_status_t status = EFI_INVALID_PARAMETER;
374 375 376 377
	int i;

	first_uga = NULL;
	nr_ugas = size / sizeof(u64);
M
Matt Fleming 已提交
378 379 380 381
	for (i = 0; i < nr_ugas; i++) {
		efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
		u32 w, h, depth, refresh;
		void *pciio;
382
		u64 handle = handles[i];
M
Matt Fleming 已提交
383

384 385
		status = efi_call_early(handle_protocol, handle,
					&uga_proto, (void **)&uga);
M
Matt Fleming 已提交
386 387 388
		if (status != EFI_SUCCESS)
			continue;

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

391 392
		status = efi_early->call((unsigned long)uga->get_mode, uga,
					 &w, &h, &depth, &refresh);
M
Matt Fleming 已提交
393
		if (status == EFI_SUCCESS && (!first_uga || pciio)) {
394 395
			*width = w;
			*height = h;
M
Matt Fleming 已提交
396 397 398 399 400 401 402 403 404 405 406 407

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

			first_uga = uga;
		}
	}

408 409 410 411 412 413
	return status;
}

/*
 * See if we have Universal Graphics Adapter (UGA) protocol
 */
I
Ingo Molnar 已提交
414 415
static efi_status_t
setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
416 417 418 419 420
{
	efi_status_t status;
	u32 width, height;
	void **uga_handle = NULL;

421 422
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
				size, (void **)&uga_handle);
423 424 425
	if (status != EFI_SUCCESS)
		return status;

426 427 428
	status = efi_call_early(locate_handle,
				EFI_LOCATE_BY_PROTOCOL,
				uga_proto, NULL, &size, uga_handle);
429 430 431 432 433 434 435 436 437 438 439 440
	if (status != EFI_SUCCESS)
		goto free_handle;

	height = 0;
	width = 0;

	if (efi_early->is64)
		status = setup_uga64(uga_handle, size, &width, &height);
	else
		status = setup_uga32(uga_handle, size, &width, &height);

	if (!width && !height)
M
Matt Fleming 已提交
441 442 443
		goto free_handle;

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

I
Ingo Molnar 已提交
446 447 448
	si->lfb_depth		= 32;
	si->lfb_width		= width;
	si->lfb_height		= height;
M
Matt Fleming 已提交
449

I
Ingo Molnar 已提交
450 451 452 453 454 455 456 457
	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 已提交
458 459

free_handle:
460
	efi_call_early(free_pool, uga_handle);
I
Ingo Molnar 已提交
461

M
Matt Fleming 已提交
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
	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;
479 480 481
	status = efi_call_early(locate_handle,
				EFI_LOCATE_BY_PROTOCOL,
				&graphics_proto, NULL, &size, gop_handle);
M
Matt Fleming 已提交
482
	if (status == EFI_BUFFER_TOO_SMALL)
483
		status = efi_setup_gop(NULL, si, &graphics_proto, size);
M
Matt Fleming 已提交
484 485 486

	if (status != EFI_SUCCESS) {
		size = 0;
487 488 489
		status = efi_call_early(locate_handle,
					EFI_LOCATE_BY_PROTOCOL,
					&uga_proto, NULL, &size, uga_handle);
M
Matt Fleming 已提交
490 491 492 493 494 495 496 497 498
		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).
499 500 501
 *
 * The caller is responsible for filling out ->code32_start in the
 * returned boot_params.
M
Matt Fleming 已提交
502
 */
503
struct boot_params *make_boot_params(struct efi_config *c)
M
Matt Fleming 已提交
504
{
M
Matt Fleming 已提交
505 506 507 508
	struct boot_params *boot_params;
	struct apm_bios_info *bi;
	struct setup_header *hdr;
	efi_loaded_image_t *image;
509
	void *options, *handle;
M
Matt Fleming 已提交
510
	efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
M
Matt Fleming 已提交
511 512
	int options_size = 0;
	efi_status_t status;
513
	char *cmdline_ptr;
M
Matt Fleming 已提交
514 515 516
	u16 *s2;
	u8 *s1;
	int i;
517 518
	unsigned long ramdisk_addr;
	unsigned long ramdisk_size;
M
Matt Fleming 已提交
519

520 521 522
	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 已提交
523 524 525 526 527

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

528 529 530 531 532
	if (efi_early->is64)
		setup_boot_services64(efi_early);
	else
		setup_boot_services32(efi_early);

533 534
	status = efi_call_early(handle_protocol, handle,
				&proto, (void *)&image);
M
Matt Fleming 已提交
535
	if (status != EFI_SUCCESS) {
536
		efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
M
Matt Fleming 已提交
537 538 539
		return NULL;
	}

540 541
	status = efi_low_alloc(sys_table, 0x4000, 1,
			       (unsigned long *)&boot_params);
M
Matt Fleming 已提交
542
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
543
		efi_printk(sys_table, "Failed to allocate lowmem for boot params\n");
M
Matt Fleming 已提交
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
		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 已提交
559 560 561
	hdr->root_flags	= 1;
	hdr->vid_mode	= 0xffff;
	hdr->boot_flag	= 0xAA55;
M
Matt Fleming 已提交
562

M
Matt Fleming 已提交
563 564 565
	hdr->type_of_loader = 0x21;

	/* Convert unicode cmdline to ascii */
566
	cmdline_ptr = efi_convert_cmdline(sys_table, image, &options_size);
567 568
	if (!cmdline_ptr)
		goto fail;
I
Ingo Molnar 已提交
569

570
	hdr->cmd_line_ptr = (unsigned long)cmdline_ptr;
571 572
	/* 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 已提交
573 574 575 576 577 578 579

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

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

580 581 582 583
	status = efi_parse_options(cmdline_ptr);
	if (status != EFI_SUCCESS)
		goto fail2;

584 585
	status = handle_cmdline_files(sys_table, image,
				      (char *)(unsigned long)hdr->cmd_line_ptr,
586
				      "initrd=", hdr->initrd_addr_max,
587
				      &ramdisk_addr, &ramdisk_size);
588 589 590 591 592 593 594 595 596 597

	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 已提交
598 599
	if (status != EFI_SUCCESS)
		goto fail2;
600 601 602 603
	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 已提交
604 605

	return boot_params;
I
Ingo Molnar 已提交
606

M
Matt Fleming 已提交
607
fail2:
608
	efi_free(sys_table, options_size, hdr->cmd_line_ptr);
M
Matt Fleming 已提交
609
fail:
610
	efi_free(sys_table, 0x4000, (unsigned long)boot_params);
I
Ingo Molnar 已提交
611

M
Matt Fleming 已提交
612 613 614
	return NULL;
}

615 616
static void add_e820ext(struct boot_params *params,
			struct setup_data *e820ext, u32 nr_entries)
M
Matt Fleming 已提交
617
{
618
	struct setup_data *data;
M
Matt Fleming 已提交
619
	efi_status_t status;
620
	unsigned long size;
M
Matt Fleming 已提交
621

622
	e820ext->type = SETUP_E820_EXT;
I
Ingo Molnar 已提交
623
	e820ext->len  = nr_entries * sizeof(struct boot_e820_entry);
624
	e820ext->next = 0;
M
Matt Fleming 已提交
625

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

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

631 632 633 634 635
	if (data)
		data->next = (unsigned long)e820ext;
	else
		params->hdr.setup_data = (unsigned long)e820ext;
}
M
Matt Fleming 已提交
636

I
Ingo Molnar 已提交
637 638
static efi_status_t
setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_size)
639
{
640
	struct boot_e820_entry *entry = params->e820_table;
641
	struct efi_info *efi = &params->efi_info;
642
	struct boot_e820_entry *prev = NULL;
643 644 645
	u32 nr_entries;
	u32 nr_desc;
	int i;
M
Matt Fleming 已提交
646 647

	nr_entries = 0;
648 649 650
	nr_desc = efi->efi_memmap_size / efi->efi_memdesc_size;

	for (i = 0; i < nr_desc; i++) {
M
Matt Fleming 已提交
651 652
		efi_memory_desc_t *d;
		unsigned int e820_type = 0;
653
		unsigned long m = efi->efi_memmap;
M
Matt Fleming 已提交
654

655 656 657 658
#ifdef CONFIG_X86_64
		m |= (u64)efi->efi_memmap_hi << 32;
#endif

659
		d = efi_early_memdesc_ptr(m, efi->efi_memdesc_size, i);
M
Matt Fleming 已提交
660 661 662 663 664 665 666
		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:
667
			e820_type = E820_TYPE_RESERVED;
M
Matt Fleming 已提交
668 669 670
			break;

		case EFI_UNUSABLE_MEMORY:
671
			e820_type = E820_TYPE_UNUSABLE;
M
Matt Fleming 已提交
672 673 674
			break;

		case EFI_ACPI_RECLAIM_MEMORY:
675
			e820_type = E820_TYPE_ACPI;
M
Matt Fleming 已提交
676 677 678 679 680 681 682
			break;

		case EFI_LOADER_CODE:
		case EFI_LOADER_DATA:
		case EFI_BOOT_SERVICES_CODE:
		case EFI_BOOT_SERVICES_DATA:
		case EFI_CONVENTIONAL_MEMORY:
683
			e820_type = E820_TYPE_RAM;
M
Matt Fleming 已提交
684 685 686
			break;

		case EFI_ACPI_MEMORY_NVS:
687
			e820_type = E820_TYPE_NVS;
M
Matt Fleming 已提交
688 689
			break;

690
		case EFI_PERSISTENT_MEMORY:
691
			e820_type = E820_TYPE_PMEM;
692 693
			break;

M
Matt Fleming 已提交
694 695 696 697 698 699
		default:
			continue;
		}

		/* Merge adjacent mappings */
		if (prev && prev->type == e820_type &&
700
		    (prev->addr + prev->size) == d->phys_addr) {
M
Matt Fleming 已提交
701
			prev->size += d->num_pages << 12;
702
			continue;
M
Matt Fleming 已提交
703
		}
704

705
		if (nr_entries == ARRAY_SIZE(params->e820_table)) {
706
			u32 need = (nr_desc - i) * sizeof(struct e820_entry) +
707 708 709 710 711 712
				   sizeof(struct setup_data);

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

			/* boot_params map full, switch to e820 extended */
713
			entry = (struct boot_e820_entry *)e820ext->data;
714 715
		}

716 717 718 719
		entry->addr = d->phys_addr;
		entry->size = d->num_pages << PAGE_SHIFT;
		entry->type = e820_type;
		prev = entry++;
720
		nr_entries++;
M
Matt Fleming 已提交
721 722
	}

723 724
	if (nr_entries > ARRAY_SIZE(params->e820_table)) {
		u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_table);
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741

		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) +
742
		sizeof(struct e820_entry) * nr_desc;
743 744

	if (*e820ext) {
745
		efi_call_early(free_pool, *e820ext);
746 747 748 749
		*e820ext = NULL;
		*e820ext_size = 0;
	}

750 751
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
				size, (void **)e820ext);
752 753 754 755 756 757
	if (status == EFI_SUCCESS)
		*e820ext_size = size;

	return status;
}

758
struct exit_boot_struct {
I
Ingo Molnar 已提交
759 760 761 762 763
	struct boot_params	*boot_params;
	struct efi_info		*efi;
	struct setup_data	*e820ext;
	__u32			e820ext_size;
	bool			is64;
764 765 766 767 768 769 770 771 772 773 774 775 776 777
};

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;
778
		if (nr_desc > ARRAY_SIZE(p->boot_params->e820_table)) {
779
			u32 nr_e820ext = nr_desc -
780
					ARRAY_SIZE(p->boot_params->e820_table);
781 782 783 784 785 786 787 788 789 790 791 792

			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 已提交
793 794 795 796 797
	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;
798 799

#ifdef CONFIG_X86_64
I
Ingo Molnar 已提交
800 801
	p->efi->efi_systab_hi		= (unsigned long)sys_table_arg >> 32;
	p->efi->efi_memmap_hi		= (unsigned long)*map->map >> 32;
802 803 804 805 806
#endif

	return EFI_SUCCESS;
}

807
static efi_status_t exit_boot(struct boot_params *boot_params,
808
			      void *handle, bool is64)
809
{
810
	unsigned long map_sz, key, desc_size, buff_size;
811 812 813 814 815
	efi_memory_desc_t *mem_map;
	struct setup_data *e820ext;
	__u32 e820ext_size;
	efi_status_t status;
	__u32 desc_version;
816
	struct efi_boot_memmap map;
817 818
	struct exit_boot_struct priv;

I
Ingo Molnar 已提交
819 820 821 822 823 824 825 826 827 828 829
	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;
830

831 832 833
	/* Might as well exit boot services now */
	status = efi_exit_boot_services(sys_table, handle, &map, &priv,
					exit_boot_func);
834 835 836
	if (status != EFI_SUCCESS)
		return status;

I
Ingo Molnar 已提交
837 838 839
	e820ext			= priv.e820ext;
	e820ext_size		= priv.e820ext_size;

840
	/* Historic? */
I
Ingo Molnar 已提交
841
	boot_params->alt_mem_k	= 32 * 1024;
842 843 844 845

	status = setup_e820(boot_params, e820ext, e820ext_size);
	if (status != EFI_SUCCESS)
		return status;
M
Matt Fleming 已提交
846 847 848 849

	return EFI_SUCCESS;
}

M
Matt Fleming 已提交
850 851 852 853
/*
 * On success we return a pointer to a boot_params structure, and NULL
 * on failure.
 */
I
Ingo Molnar 已提交
854 855
struct boot_params *
efi_main(struct efi_config *c, struct boot_params *boot_params)
M
Matt Fleming 已提交
856
{
857
	struct desc_ptr *gdt = NULL;
M
Matt Fleming 已提交
858 859 860 861
	efi_loaded_image_t *image;
	struct setup_header *hdr = &boot_params->hdr;
	efi_status_t status;
	struct desc_struct *desc;
862 863 864 865 866 867 868 869 870
	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 已提交
871 872 873 874 875 876 877

	sys_table = _table;

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

878 879 880 881 882
	if (is64)
		setup_boot_services64(efi_early);
	else
		setup_boot_services32(efi_early);

883 884 885 886 887 888
	/*
	 * 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);
889 890 891

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

M
Matt Fleming 已提交
894
	setup_graphics(boot_params);
M
Matt Fleming 已提交
895

896
	setup_efi_pci(boot_params);
897

898 899
	setup_quirks(boot_params);

900 901
	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
				sizeof(*gdt), (void **)&gdt);
902
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
903
		efi_printk(sys_table, "Failed to allocate memory for 'gdt' structure\n");
M
Matt Fleming 已提交
904
		goto fail;
905
	}
M
Matt Fleming 已提交
906 907

	gdt->size = 0x800;
908
	status = efi_low_alloc(sys_table, gdt->size, 8,
909
			   (unsigned long *)&gdt->address);
910
	if (status != EFI_SUCCESS) {
I
Ingo Molnar 已提交
911
		efi_printk(sys_table, "Failed to allocate memory for 'gdt'\n");
M
Matt Fleming 已提交
912
		goto fail;
913
	}
M
Matt Fleming 已提交
914

M
Matt Fleming 已提交
915 916 917 918 919
	/*
	 * If the kernel isn't already loaded at the preferred load
	 * address, relocate it.
	 */
	if (hdr->pref_address != hdr->code32_start) {
920 921 922 923 924
		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);
925 926
		if (status != EFI_SUCCESS) {
			efi_printk(sys_table, "efi_relocate_kernel() failed!\n");
M
Matt Fleming 已提交
927
			goto fail;
928
		}
929 930 931

		hdr->pref_address = hdr->code32_start;
		hdr->code32_start = bzimage_addr;
M
Matt Fleming 已提交
932 933
	}

934
	status = exit_boot(boot_params, handle, is64);
935 936
	if (status != EFI_SUCCESS) {
		efi_printk(sys_table, "exit_boot() failed!\n");
M
Matt Fleming 已提交
937
		goto fail;
938
	}
M
Matt Fleming 已提交
939 940 941 942

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

943 944 945 946 947
	/* The first GDT is a dummy. */
	desc++;

	if (IS_ENABLED(CONFIG_X86_64)) {
		/* __KERNEL32_CS */
I
Ingo Molnar 已提交
948 949 950 951 952 953 954 955 956 957 958 959 960 961
		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;

962 963 964 965 966
		desc++;
	} else {
		/* Second entry is unused on 32-bit */
		desc++;
	}
M
Matt Fleming 已提交
967

968
	/* __KERNEL_CS */
I
Ingo Molnar 已提交
969 970 971 972 973 974 975 976 977 978
	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;

979 980 981 982 983 984 985
	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 已提交
986 987
	desc->g		= SEG_GRANULARITY_4KB;
	desc->base2	= 0x00;
M
Matt Fleming 已提交
988
	desc++;
989 990

	/* __KERNEL_DS */
I
Ingo Molnar 已提交
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
	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 已提交
1004
	desc++;
1005 1006 1007

	if (IS_ENABLED(CONFIG_X86_64)) {
		/* Task segment value */
I
Ingo Molnar 已提交
1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
		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;
1021 1022
		desc++;
	}
M
Matt Fleming 已提交
1023 1024

	asm volatile("cli");
1025
	asm volatile ("lgdt %0" : : "m" (*gdt));
M
Matt Fleming 已提交
1026 1027 1028

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

M
Matt Fleming 已提交
1031 1032
	return NULL;
}