fallback.c 25.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * Copyright 2012-2013 Red Hat, Inc.
 * All rights reserved.
 *
 * See "COPYING" for license terms.
 *
 * Author(s): Peter Jones <pjones@redhat.com>
 */

#include <efi.h>
#include <efilib.h>

#include "ucs2.h"
14
#include "variables.h"
15
#include "tpm.h"
16 17 18

EFI_LOADED_IMAGE *this_image = NULL;

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };

int
get_fallback_verbose(void)
{
	EFI_GUID guid = SHIM_LOCK_GUID;
	UINT8 *data = NULL;
	UINTN dataSize = 0;
	EFI_STATUS efi_status;
	unsigned int i;
	static int state = -1;

	if (state != -1)
		return state;

	efi_status = get_variable(L"FALLBACK_VERBOSE",
				  &data, &dataSize, guid);
	if (EFI_ERROR(efi_status)) {
		state = 0;
		return state;
	}

	for (i = 0; i < dataSize; i++) {
		if (data[i]) {
			state = 1;
			return state;
		}
	}

	state = 0;
	return state;
}

#define VerbosePrintUnprefixed(fmt, ...)				\
	({								\
		UINTN ret_ = 0;						\
		if (get_fallback_verbose())				\
			ret_ = Print((fmt), ##__VA_ARGS__);		\
		ret_;							\
	})

#define VerbosePrint(fmt, ...)						\
	({	UINTN line_ = __LINE__;					\
		UINTN ret_ = 0;						\
		if (get_fallback_verbose()) {				\
			Print(L"%a:%d: ", __func__, line_);		\
			ret_ = Print((fmt), ##__VA_ARGS__);		\
		}							\
		ret_;							\
	})

70 71 72 73 74 75 76 77
static EFI_STATUS
FindSubDevicePath(EFI_DEVICE_PATH *In, UINT8 Type, UINT8 SubType,
		  EFI_DEVICE_PATH **Out)
{
	EFI_DEVICE_PATH *dp = In;
	if (!In || !Out)
		return EFI_INVALID_PARAMETER;

78 79 80 81
	CHAR16 *dps = DevicePathToStr(In);
	VerbosePrint(L"input device path: \"%s\"\n", dps);
	FreePool(dps);

82 83 84
	for (dp = In; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) {
		if (DevicePathType(dp) == Type &&
				DevicePathSubType(dp) == SubType) {
85 86 87 88 89
			dps = DevicePathToStr(dp);
			VerbosePrint(L"sub-path (%hhd,%hhd): \"%s\"\n",
				     Type, SubType, dps);
			FreePool(dps);

90 91 92 93 94 95 96 97 98 99
			*Out = DuplicateDevicePath(dp);
			if (!*Out)
				return EFI_OUT_OF_RESOURCES;
			return EFI_SUCCESS;
		}
	}
	*Out = NULL;
	return EFI_NOT_FOUND;
}

100
static EFI_STATUS
101
get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize)
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
{
	EFI_STATUS rc;
	void *buffer = NULL;
	UINTN bs = 0;
	EFI_GUID finfo = EFI_FILE_INFO_ID;

	/* The API here is "Call it once with bs=0, it fills in bs,
	 * then allocate a buffer and ask again to get it filled. */
	rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo, &bs, NULL);
	if (rc == EFI_BUFFER_TOO_SMALL) {
		buffer = AllocateZeroPool(bs);
		if (!buffer) {
			Print(L"Could not allocate memory\n");
			return EFI_OUT_OF_RESOURCES;
		}
		rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo,
					&bs, buffer);
	}
	/* This checks *either* the error from the first GetInfo, if it isn't
	 * the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo call
	 * in *any* case. */
	if (EFI_ERROR(rc)) {
		Print(L"Could not get file info: %d\n", rc);
		if (buffer)
			FreePool(buffer);
		return rc;
	}
	EFI_FILE_INFO *fi = buffer;
	*retsize = fi->FileSize;
	FreePool(buffer);
	return EFI_SUCCESS;
}

EFI_STATUS
read_file(EFI_FILE_HANDLE fh, CHAR16 *fullpath, CHAR16 **buffer, UINT64 *bs)
{
	EFI_FILE_HANDLE fh2;
	EFI_STATUS rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2, fullpath,
				EFI_FILE_READ_ONLY, 0);
	if (EFI_ERROR(rc)) {
		Print(L"Couldn't open \"%s\": %d\n", fullpath, rc);
		return rc;
	}

146
	UINTN len = 0;
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
	CHAR16 *b = NULL;
	rc = get_file_size(fh2, &len);
	if (EFI_ERROR(rc)) {
		uefi_call_wrapper(fh2->Close, 1, fh2);
		return rc;
	}

	b = AllocateZeroPool(len + 2);
	if (!buffer) {
		Print(L"Could not allocate memory\n");
		uefi_call_wrapper(fh2->Close, 1, fh2);
		return EFI_OUT_OF_RESOURCES;
	}

	rc = uefi_call_wrapper(fh->Read, 3, fh, &len, b);
	if (EFI_ERROR(rc)) {
		FreePool(buffer);
		uefi_call_wrapper(fh2->Close, 1, fh2);
		Print(L"Could not read file: %d\n", rc);
		return rc;
	}
	*buffer = b;
	*bs = len;
	uefi_call_wrapper(fh2->Close, 1, fh2);
	return EFI_SUCCESS;
}

EFI_STATUS
make_full_path(CHAR16 *dirname, CHAR16 *filename, CHAR16 **out, UINT64 *outlen)
{
	UINT64 len;
178

179 180 181
	len = StrLen(L"\\EFI\\") + StrLen(dirname)
	    + StrLen(L"\\") + StrLen(filename)
	    + 2;
182

183
	CHAR16 *fullpath = AllocateZeroPool(len*sizeof(CHAR16));
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
	if (!fullpath) {
		Print(L"Could not allocate memory\n");
		return EFI_OUT_OF_RESOURCES;
	}

	StrCat(fullpath, L"\\EFI\\");
	StrCat(fullpath, dirname);
	StrCat(fullpath, L"\\");
	StrCat(fullpath, filename);

	*out = fullpath;
	*outlen = len;
	return EFI_SUCCESS;
}

CHAR16 *bootorder = NULL;
int nbootorder = 0;

202 203 204 205
EFI_DEVICE_PATH *first_new_option = NULL;
VOID *first_new_option_args = NULL;
UINTN first_new_option_size = 0;

206
EFI_STATUS
207 208
add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
		CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
{
	static int i = 0;
	CHAR16 varname[] = L"Boot0000";
	CHAR16 hexmap[] = L"0123456789ABCDEF";
	EFI_GUID global = EFI_GLOBAL_VARIABLE;
	EFI_STATUS rc;

	for(; i <= 0xffff; i++) {
		varname[4] = hexmap[(i & 0xf000) >> 12];
		varname[5] = hexmap[(i & 0x0f00) >> 8];
		varname[6] = hexmap[(i & 0x00f0) >> 4];
		varname[7] = hexmap[(i & 0x000f) >> 0];

		void *var = LibGetVariable(varname, &global);
		if (!var) {
			int size = sizeof(UINT32) + sizeof (UINT16) +
225 226
				StrLen(label)*2 + 2 + DevicePathSize(hddp) +
				StrLen(arguments) * 2;
227

228
			CHAR8 *data = AllocateZeroPool(size + 2);
229 230 231
			CHAR8 *cursor = data;
			*(UINT32 *)cursor = LOAD_OPTION_ACTIVE;
			cursor += sizeof (UINT32);
232
			*(UINT16 *)cursor = DevicePathSize(hddp);
233 234 235
			cursor += sizeof (UINT16);
			StrCpy((CHAR16 *)cursor, label);
			cursor += StrLen(label)*2 + 2;
236 237
			CopyMem(cursor, hddp, DevicePathSize(hddp));
			cursor += DevicePathSize(hddp);
238 239 240 241 242
			StrCpy((CHAR16 *)cursor, arguments);

			Print(L"Creating boot entry \"%s\" with label \"%s\" "
					L"for file \"%s\"\n",
				varname, label, filename);
243 244 245 246 247 248 249

			if (!first_new_option) {
				first_new_option = DuplicateDevicePath(fulldp);
				first_new_option_args = arguments;
				first_new_option_size = StrLen(arguments) * sizeof (CHAR16);
			}

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
			rc = uefi_call_wrapper(RT->SetVariable, 5, varname,
				&global, EFI_VARIABLE_NON_VOLATILE |
					 EFI_VARIABLE_BOOTSERVICE_ACCESS |
					 EFI_VARIABLE_RUNTIME_ACCESS,
				size, data);

			FreePool(data);

			if (EFI_ERROR(rc)) {
				Print(L"Could not create variable: %d\n", rc);
				return rc;
			}

			CHAR16 *newbootorder = AllocateZeroPool(sizeof (CHAR16)
							* (nbootorder + 1));
			if (!newbootorder)
				return EFI_OUT_OF_RESOURCES;

			int j = 0;
269
			newbootorder[0] = i & 0xffff;
270 271
			if (nbootorder) {
				for (j = 0; j < nbootorder; j++)
272
					newbootorder[j+1] = bootorder[j];
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
				FreePool(bootorder);
			}
			bootorder = newbootorder;
			nbootorder += 1;
#ifdef DEBUG_FALLBACK
			Print(L"nbootorder: %d\nBootOrder: ", nbootorder);
			for (j = 0 ; j < nbootorder ; j++)
				Print(L"%04x ", bootorder[j]);
			Print(L"\n");
#endif

			return EFI_SUCCESS;
		}
	}
	return EFI_OUT_OF_RESOURCES;
}

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
/*
 * AMI BIOS (e.g, Intel NUC5i3MYHE) may automatically hide and patch BootXXXX
 * variables with ami_masked_device_path_guid. We can get the valid device path
 * if just skipping it and its next end path.
 */

static EFI_GUID ami_masked_device_path_guid = {
	0x99e275e7, 0x75a0, 0x4b37,
	{ 0xa2, 0xe6, 0xc5, 0x38, 0x5e, 0x6c, 0x0, 0xcb }
};

static unsigned int
calc_masked_boot_option_size(unsigned int size)
{
	return size + sizeof(EFI_DEVICE_PATH) +
	       sizeof(ami_masked_device_path_guid) + sizeof(EFI_DEVICE_PATH);
}

static int
check_masked_boot_option(CHAR8 *candidate, unsigned int candidate_size,
			 CHAR8 *data, unsigned int data_size)
{
	/*
	 * The patched BootXXXX variables contain a hardware device path and
	 * an end path, preceding the real device path.
	 */
	if (calc_masked_boot_option_size(data_size) != candidate_size)
		return 1;

	CHAR8 *cursor = candidate;

	/* Check whether the BootXXXX is patched */
	cursor += sizeof(UINT32) + sizeof(UINT16);
	cursor += StrSize((CHAR16 *)cursor);

	unsigned int min_valid_size = cursor - candidate + sizeof(EFI_DEVICE_PATH);

	if (candidate_size <= min_valid_size)
		return 1;

	EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *)cursor;
	unsigned int node_size = DevicePathNodeLength(dp) - sizeof(EFI_DEVICE_PATH);

	min_valid_size += node_size;
	if (candidate_size <= min_valid_size ||
	    DevicePathType(dp) != HARDWARE_DEVICE_PATH ||
	    DevicePathSubType(dp) != HW_VENDOR_DP ||
	    node_size != sizeof(ami_masked_device_path_guid) ||
	    CompareGuid((EFI_GUID *)(cursor + sizeof(EFI_DEVICE_PATH)),
		        &ami_masked_device_path_guid))
		return 1;

	/* Check whether the patched guid is followed by an end path */
	min_valid_size += sizeof(EFI_DEVICE_PATH);
	if (candidate_size <= min_valid_size)
		return 1;

	dp = NextDevicePathNode(dp);
	if (!IsDevicePathEnd(dp))
		return 1;

	/*
	 * OK. We may really get a masked BootXXXX variable. The next
	 * step is to test whether it is hidden.
	 */
	UINT32 attrs = *(UINT32 *)candidate;
#ifndef LOAD_OPTION_HIDDEN
#  define LOAD_OPTION_HIDDEN	0x00000008
#endif
        if (!(attrs & LOAD_OPTION_HIDDEN))
		return 1;

	attrs &= ~LOAD_OPTION_HIDDEN;

	/* Compare the field Attributes */
	if (attrs != *(UINT32 *)data)
		return 1;

	/* Compare the field FilePathListLength */
	data += sizeof(UINT32);
	candidate += sizeof(UINT32);
	if (calc_masked_boot_option_size(*(UINT16 *)data) !=
					 *(UINT16 *)candidate)
		return 1;

	/* Compare the field Description */
	data += sizeof(UINT16);
	candidate += sizeof(UINT16);
	if (CompareMem(candidate, data, cursor - candidate))
		return 1;

	/* Compare the filed FilePathList */
	cursor = (CHAR8 *)NextDevicePathNode(dp);
	data += sizeof(UINT16);
	data += StrSize((CHAR16 *)data);

	return CompareMem(cursor, data, candidate_size - min_valid_size);
}

389
EFI_STATUS
390 391 392
find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp,
                 CHAR16 *filename, CHAR16 *label, CHAR16 *arguments,
                 UINT16 *optnum)
393
{
394
	unsigned int size = sizeof(UINT32) + sizeof (UINT16) +
395
		StrLen(label)*2 + 2 + DevicePathSize(dp) +
396
		StrLen(arguments) * 2;
397

398
	CHAR8 *data = AllocateZeroPool(size + 2);
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
	if (!data)
		return EFI_OUT_OF_RESOURCES;
	CHAR8 *cursor = data;
	*(UINT32 *)cursor = LOAD_OPTION_ACTIVE;
	cursor += sizeof (UINT32);
	*(UINT16 *)cursor = DevicePathSize(dp);
	cursor += sizeof (UINT16);
	StrCpy((CHAR16 *)cursor, label);
	cursor += StrLen(label)*2 + 2;
	CopyMem(cursor, dp, DevicePathSize(dp));
	cursor += DevicePathSize(dp);
	StrCpy((CHAR16 *)cursor, arguments);

	int i = 0;
	CHAR16 varname[] = L"Boot0000";
	CHAR16 hexmap[] = L"0123456789ABCDEF";
	EFI_GUID global = EFI_GLOBAL_VARIABLE;
	EFI_STATUS rc;

418 419
	UINTN max_candidate_size = calc_masked_boot_option_size(size);
	CHAR8 *candidate = AllocateZeroPool(max_candidate_size);
420 421 422 423 424 425 426 427 428 429 430
	if (!candidate) {
		FreePool(data);
		return EFI_OUT_OF_RESOURCES;
	}

	for(i = 0; i < nbootorder && i < 0x10000; i++) {
		varname[4] = hexmap[(bootorder[i] & 0xf000) >> 12];
		varname[5] = hexmap[(bootorder[i] & 0x0f00) >> 8];
		varname[6] = hexmap[(bootorder[i] & 0x00f0) >> 4];
		varname[7] = hexmap[(bootorder[i] & 0x000f) >> 0];

431
		UINTN candidate_size = max_candidate_size;
432 433 434 435 436
		rc = uefi_call_wrapper(RT->GetVariable, 5, varname, &global,
					NULL, &candidate_size, candidate);
		if (EFI_ERROR(rc))
			continue;

437 438 439 440 441
		if (candidate_size != size) {
			if (check_masked_boot_option(candidate, candidate_size,
						     data, size))
				continue;
		} else if (CompareMem(candidate, data, size))
442 443
			continue;

444 445
		VerbosePrint(L"Found boot entry \"%s\" with label \"%s\" "
			     L"for file \"%s\"\n", varname, label, filename);
446 447

		/* at this point, we have duplicate data. */
448 449 450 451 452 453
		if (!first_new_option) {
			first_new_option = DuplicateDevicePath(fulldp);
			first_new_option_args = arguments;
			first_new_option_size = StrLen(arguments) * sizeof (CHAR16);
		}

454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
		*optnum = i;
		FreePool(candidate);
		FreePool(data);
		return EFI_SUCCESS;
	}
	FreePool(candidate);
	FreePool(data);
	return EFI_NOT_FOUND;
}

EFI_STATUS
set_boot_order(void)
{
	CHAR16 *oldbootorder;
	UINTN size;
	EFI_GUID global = EFI_GLOBAL_VARIABLE;

	oldbootorder = LibGetVariableAndSize(L"BootOrder", &global, &size);
	if (oldbootorder) {
		nbootorder = size / sizeof (CHAR16);
		bootorder = oldbootorder;
	}
	return EFI_SUCCESS;

}

480 481 482 483
EFI_STATUS
update_boot_order(void)
{
	UINTN size;
484
	UINTN len = 0;
485 486
	EFI_GUID global = EFI_GLOBAL_VARIABLE;
	CHAR16 *newbootorder = NULL;
487
	EFI_STATUS rc;
488

489 490 491 492 493
	size = nbootorder * sizeof(CHAR16);
	newbootorder = AllocateZeroPool(size);
	if (!newbootorder)
		return EFI_OUT_OF_RESOURCES;
	CopyMem(newbootorder, bootorder, size);
494

495
	VerbosePrint(L"nbootorder: %d\nBootOrder: ", size / sizeof (CHAR16));
496
	UINTN j;
497
	for (j = 0 ; j < size / sizeof (CHAR16); j++)
498
		VerbosePrintUnprefixed(L"%04x ", newbootorder[j]);
499
	Print(L"\n");
500 501 502
	rc = uefi_call_wrapper(RT->GetVariable, 5, L"BootOrder", &global,
			       NULL, &len, NULL);
	if (rc == EFI_BUFFER_TOO_SMALL)
503 504 505 506 507 508 509 510 511 512 513 514
		LibDeleteVariable(L"BootOrder", &global);

	rc = uefi_call_wrapper(RT->SetVariable, 5, L"BootOrder", &global,
					EFI_VARIABLE_NON_VOLATILE |
					 EFI_VARIABLE_BOOTSERVICE_ACCESS |
					 EFI_VARIABLE_RUNTIME_ACCESS,
					size, newbootorder);
	FreePool(newbootorder);
	return rc;
}

EFI_STATUS
515
add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
516 517 518 519 520 521 522 523
{
	CHAR16 *fullpath = NULL;
	UINT64 pathlen = 0;
	EFI_STATUS rc = EFI_SUCCESS;

	rc = make_full_path(dirname, filename, &fullpath, &pathlen);
	if (EFI_ERROR(rc))
		return rc;
524

525 526
	EFI_DEVICE_PATH *full_device_path = NULL;
	EFI_DEVICE_PATH *dp = NULL;
527
	CHAR16 *dps;
528

529
	full_device_path = FileDevicePath(this_image->DeviceHandle, fullpath);
530
	if (!full_device_path) {
531 532 533
		rc = EFI_OUT_OF_RESOURCES;
		goto err;
	}
534 535 536
	dps = DevicePathToStr(full_device_path);
	VerbosePrint(L"file DP: %s\n", dps);
	FreePool(dps);
537

538 539 540 541 542 543 544 545 546 547 548 549
	rc = FindSubDevicePath(full_device_path,
				MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, &dp);
	if (EFI_ERROR(rc)) {
		if (rc == EFI_NOT_FOUND) {
			dp = full_device_path;
		} else {
			rc = EFI_OUT_OF_RESOURCES;
			goto err;
		}
	}

	{
550 551 552 553 554 555 556 557 558 559 560 561
		UINTN s = DevicePathSize(dp);
		UINTN i;
		UINT8 *dpv = (void *)dp;
		for (i = 0; i < s; i++) {
			if (i % 16 == 0) {
				if (i > 0)
					VerbosePrintUnprefixed(L"\n");
				VerbosePrint(L"");
			}
			VerbosePrintUnprefixed(L"%02x ", dpv[i]);
		}
		VerbosePrintUnprefixed(L"\n");
562

563 564 565
		CHAR16 *dps = DevicePathToStr(dp);
		VerbosePrint(L"device path: \"%s\"\n", dps);
		FreePool(dps);
566
	}
567

568
	UINT16 option;
569
	rc = find_boot_option(dp, full_device_path, fullpath, label, arguments, &option);
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
	if (EFI_ERROR(rc)) {
		add_boot_option(dp, full_device_path, fullpath, label, arguments);
	} else if (option != 0) {
		CHAR16 *newbootorder;
		newbootorder = AllocateZeroPool(sizeof (CHAR16) * nbootorder);
		if (!newbootorder)
			return EFI_OUT_OF_RESOURCES;

		newbootorder[0] = bootorder[option];
		CopyMem(newbootorder + 1, bootorder, sizeof (CHAR16) * option);
		CopyMem(newbootorder + option + 1, bootorder + option + 1,
			sizeof (CHAR16) * (nbootorder - option - 1));
		FreePool(bootorder);
		bootorder = newbootorder;
	}
585 586

err:
587 588
	if (full_device_path)
		FreePool(full_device_path);
589
	if (dp && dp != full_device_path)
590 591 592 593 594 595 596
		FreePool(dp);
	if (fullpath)
		FreePool(fullpath);
	return rc;
}

EFI_STATUS
597
populate_stanza(CHAR16 *dirname, CHAR16 *filename, CHAR16 *csv)
598 599
{
	CHAR16 *file = csv;
600
	VerbosePrint(L"CSV data: \"%s\"\n", csv);
601 602 603 604 605

	UINTN comma0 = StrCSpn(csv, L",");
	if (comma0 == 0)
		return EFI_INVALID_PARAMETER;
	file[comma0] = L'\0';
606
	VerbosePrint(L"filename: \"%s\"\n", file);
607 608 609 610 611 612

	CHAR16 *label = csv + comma0 + 1;
	UINTN comma1 = StrCSpn(label, L",");
	if (comma1 == 0)
		return EFI_INVALID_PARAMETER;
	label[comma1] = L'\0';
613
	VerbosePrint(L"label: \"%s\"\n", label);
614 615 616 617 618

	CHAR16 *arguments = csv + comma0 +1 + comma1 +1;
	UINTN comma2 = StrCSpn(arguments, L",");
	arguments[comma2] = L'\0';
	/* This one is optional, so don't check if comma2 is 0 */
619
	VerbosePrint(L"arguments: \"%s\"\n", arguments);
620

621
	add_to_boot_list(dirname, file, label, arguments);
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636

	return EFI_SUCCESS;
}

EFI_STATUS
try_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename)
{
	CHAR16 *fullpath = NULL;
	UINT64 pathlen = 0;
	EFI_STATUS rc;

	rc = make_full_path(dirname, filename, &fullpath, &pathlen);
	if (EFI_ERROR(rc))
		return rc;

637
	VerbosePrint(L"Found file \"%s\"\n", fullpath);
638 639 640 641 642 643 644 645 646 647 648

	CHAR16 *buffer;
	UINT64 bs;
	rc = read_file(fh, fullpath, &buffer, &bs);
	if (EFI_ERROR(rc)) {
		Print(L"Could not read file \"%s\": %d\n", fullpath, rc);
		FreePool(fullpath);
		return rc;
	}
	FreePool(fullpath);

649
	VerbosePrint(L"File looks like:\n%s\n", buffer);
650 651

	CHAR16 *start = buffer;
652 653 654 655 656 657 658
	/* The file may or may not start with the Unicode byte order marker.
	 * Sadness ensues.  Since UEFI is defined as LE, I'm going to decree
	 * that these files must also be LE.
	 *
	 * IT IS THUS SO.
	 *
	 * But if we find the LE byte order marker, just skip it.
659 660 661 662
	 */
	if (*start == 0xfeff)
		start++;
	while (*start) {
663
		while (*start == L'\r' || *start == L'\n')
664 665 666 667 668 669 670 671 672 673 674
			start++;
		UINTN l = StrCSpn(start, L"\r\n");
		if (l == 0) {
			if (start[l] == L'\0')
				break;
			start++;
			continue;
		}
		CHAR16 c = start[l];
		start[l] = L'\0';

675
		populate_stanza(dirname, filename, start);
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720

		start[l] = c;
		start += l;
	}

	FreePool(buffer);
	return EFI_SUCCESS;
}

EFI_STATUS
find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname)
{
	EFI_STATUS rc;
	void *buffer = NULL;
	UINTN bs = 0;
	EFI_GUID finfo = EFI_FILE_INFO_ID;

	/* The API here is "Call it once with bs=0, it fills in bs,
	 * then allocate a buffer and ask again to get it filled. */
	rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo, &bs, NULL);
	if (rc == EFI_BUFFER_TOO_SMALL) {
		buffer = AllocateZeroPool(bs);
		if (!buffer) {
			Print(L"Could not allocate memory\n");
			return EFI_OUT_OF_RESOURCES;
		}
		rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo,
					&bs, buffer);
	}
	/* This checks *either* the error from the first GetInfo, if it isn't
	 * the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo call
	 * in *any* case. */
	if (EFI_ERROR(rc)) {
		Print(L"Could not get info for \"%s\": %d\n", dirname, rc);
		if (buffer)
			FreePool(buffer);
		return rc;
	}

	EFI_FILE_INFO *fi = buffer;
	if (!(fi->Attribute & EFI_FILE_DIRECTORY)) {
		FreePool(buffer);
		return EFI_SUCCESS;
	}
	FreePool(buffer);
721
	buffer = NULL;
722

723 724
	CHAR16 *bootcsv=NULL, *bootarchcsv=NULL;

725 726 727 728
	bs = 0;
	do {
		bs = 0;
		rc = uefi_call_wrapper(fh->Read, 3, fh, &bs, NULL);
729 730 731 732 733 734
		if (EFI_ERROR(rc) && rc != EFI_BUFFER_TOO_SMALL) {
			Print(L"Could not read \\EFI\\%s\\: %d\n", dirname, rc);
			if (buffer)
				FreePool(buffer);
			return rc;
		}
735 736 737 738
		/* If there's no data to read, don't try to allocate 0 bytes
		 * and read the data... */
		if (bs == 0)
			break;
739

740 741 742 743
		buffer = AllocateZeroPool(bs);
		if (!buffer) {
			Print(L"Could not allocate memory\n");
			return EFI_OUT_OF_RESOURCES;
744
		}
745 746

		rc = uefi_call_wrapper(fh->Read, 3, fh, &bs, buffer);
747 748 749 750 751
		if (EFI_ERROR(rc)) {
			Print(L"Could not read \\EFI\\%s\\: %d\n", dirname, rc);
			FreePool(buffer);
			return rc;
		}
752

753 754 755 756 757
		if (bs == 0)
			break;

		fi = buffer;

758 759 760 761 762 763
		if (!bootcsv && !StrCaseCmp(fi->FileName, L"boot.csv"))
			bootcsv = StrDuplicate(fi->FileName);

		if (!bootarchcsv &&
		    !StrCaseCmp(fi->FileName, L"boot" EFI_ARCH L".csv"))
			bootarchcsv = StrDuplicate(fi->FileName);
764 765 766 767 768

		FreePool(buffer);
		buffer = NULL;
	} while (bs != 0);

769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
	rc = EFI_SUCCESS;
	if (bootarchcsv) {
		EFI_FILE_HANDLE fh2;
		rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2,
				       bootarchcsv, EFI_FILE_READ_ONLY, 0);
		if (EFI_ERROR(rc) || fh2 == NULL) {
			Print(L"Couldn't open \\EFI\\%s\\%s: %d\n",
			      dirname, bootarchcsv, rc);
		} else {
			rc = try_boot_csv(fh2, dirname, bootarchcsv);
			uefi_call_wrapper(fh2->Close, 1, fh2);
		}
	}
	if ((EFI_ERROR(rc) || !bootarchcsv) && bootcsv) {
		EFI_FILE_HANDLE fh2;
		rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2,
				       bootcsv, EFI_FILE_READ_ONLY, 0);
		if (EFI_ERROR(rc) || fh2 == NULL) {
			Print(L"Couldn't open \\EFI\\%s\\%s: %d\n",
			      dirname, bootcsv, rc);
		} else {
			rc = try_boot_csv(fh2, dirname, bootcsv);
			uefi_call_wrapper(fh2->Close, 1, fh2);
		}
	}
794 795 796 797 798 799 800 801 802 803 804 805
	rc = EFI_SUCCESS;

	return rc;
}

EFI_STATUS
find_boot_options(EFI_HANDLE device)
{
	EFI_STATUS rc = EFI_SUCCESS;

	EFI_FILE_IO_INTERFACE *fio = NULL;
	rc = uefi_call_wrapper(BS->HandleProtocol, 3, device,
806
				&FileSystemProtocol, (void **)&fio);
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
	if (EFI_ERROR(rc)) {
		Print(L"Couldn't find file system: %d\n", rc);
		return rc;
	}

	/* EFI_FILE_HANDLE is a pointer to an EFI_FILE, and I have
	 * *no idea* what frees the memory allocated here. Hopefully
	 * Close() does. */
	EFI_FILE_HANDLE fh = NULL;
	rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &fh);
	if (EFI_ERROR(rc) || fh == NULL) {
		Print(L"Couldn't open file system: %d\n", rc);
		return rc;
	}

	EFI_FILE_HANDLE fh2 = NULL;
	rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2, L"EFI",
						EFI_FILE_READ_ONLY, 0);
	if (EFI_ERROR(rc) || fh2 == NULL) {
		Print(L"Couldn't open EFI: %d\n", rc);
		uefi_call_wrapper(fh->Close, 1, fh);
		return rc;
	}
	rc = uefi_call_wrapper(fh2->SetPosition, 2, fh2, 0);
	if (EFI_ERROR(rc)) {
		Print(L"Couldn't set file position: %d\n", rc);
		uefi_call_wrapper(fh2->Close, 1, fh2);
		uefi_call_wrapper(fh->Close, 1, fh);
		return rc;
	}

	void *buffer;
	UINTN bs;
	do {
		bs = 0;
		rc = uefi_call_wrapper(fh2->Read, 3, fh2, &bs, NULL);
		if (rc == EFI_BUFFER_TOO_SMALL ||
				(rc == EFI_SUCCESS && bs != 0)) {
			buffer = AllocateZeroPool(bs);
			if (!buffer) {
				Print(L"Could not allocate memory\n");
				/* sure, this might work, why not? */
				uefi_call_wrapper(fh2->Close, 1, fh2);
				uefi_call_wrapper(fh->Close, 1, fh);
				return EFI_OUT_OF_RESOURCES;
			}

			rc = uefi_call_wrapper(fh2->Read, 3, fh2, &bs, buffer);
		}
		if (bs == 0)
			break;

		if (EFI_ERROR(rc)) {
			Print(L"Could not read \\EFI\\: %d\n", rc);
			if (buffer) {
				FreePool(buffer);
				buffer = NULL;
			}
			uefi_call_wrapper(fh2->Close, 1, fh2);
			uefi_call_wrapper(fh->Close, 1, fh);
			return rc;
		}
		EFI_FILE_INFO *fi = buffer;

		if (!(fi->Attribute & EFI_FILE_DIRECTORY)) {
			FreePool(buffer);
			buffer = NULL;
			continue;
		}
		if (!StrCmp(fi->FileName, L".") ||
				!StrCmp(fi->FileName, L"..") ||
				!StrCaseCmp(fi->FileName, L"BOOT")) {
			FreePool(buffer);
			buffer = NULL;
			continue;
		}
883
		VerbosePrint(L"Found directory named \"%s\"\n", fi->FileName);
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902

		EFI_FILE_HANDLE fh3;
		rc = uefi_call_wrapper(fh->Open, 5, fh2, &fh3, fi->FileName,
						EFI_FILE_READ_ONLY, 0);
		if (EFI_ERROR(rc)) {
			Print(L"%d Couldn't open %s: %d\n", __LINE__, fi->FileName, rc);
			FreePool(buffer);
			buffer = NULL;
			continue;
		}

		rc = find_boot_csv(fh3, fi->FileName);
		FreePool(buffer);
		buffer = NULL;
		if (rc == EFI_OUT_OF_RESOURCES)
			break;

	} while (1);

903 904 905
	if (rc == EFI_SUCCESS && nbootorder > 0)
		rc = update_boot_order();

906 907
	uefi_call_wrapper(fh2->Close, 1, fh2);
	uefi_call_wrapper(fh->Close, 1, fh);
908
	return rc;
909
}
910 911 912 913 914 915 916 917 918 919 920 921 922 923 924

static EFI_STATUS
try_start_first_option(EFI_HANDLE parent_image_handle)
{
	EFI_STATUS rc;
	EFI_HANDLE image_handle;

	if (!first_new_option) {
		return EFI_SUCCESS;
	}

	rc = uefi_call_wrapper(BS->LoadImage, 6, 0, parent_image_handle,
			       first_new_option, NULL, 0,
			       &image_handle);
	if (EFI_ERROR(rc)) {
925 926
		CHAR16 *dps = DevicePathToStr(first_new_option);
		UINTN s = DevicePathSize(first_new_option);
927
		unsigned int i;
928 929 930 931 932 933 934 935 936 937
		UINT8 *dpv = (void *)first_new_option;
		Print(L"LoadImage failed: %d\nDevice path: \"%s\"\n", rc, dps);
		for (i = 0; i < s; i++) {
			if (i > 0 && i % 16 == 0)
				Print(L"\n");
			Print(L"%02x ", dpv[i]);
		}
		Print(L"\n");

		uefi_call_wrapper(BS->Stall, 1, 500000000);
938 939
		return rc;
	}
940 941 942 943 944 945 946 947

	EFI_LOADED_IMAGE *image;
	rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, &LoadedImageProtocol, (void *)&image);
	if (!EFI_ERROR(rc)) {
		image->LoadOptions = first_new_option_args;
		image->LoadOptionsSize = first_new_option_size;
	}

948 949 950
	rc = uefi_call_wrapper(BS->StartImage, 3, image_handle, NULL, NULL);
	if (EFI_ERROR(rc)) {
		Print(L"StartImage failed: %d\n", rc);
951
		uefi_call_wrapper(BS->Stall, 1, 500000000);
952 953 954 955
	}
	return rc;
}

956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
extern EFI_STATUS
efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab);

static void
__attribute__((__optimize__("0")))
debug_hook(void)
{
	EFI_GUID guid = SHIM_LOCK_GUID;
	UINT8 *data = NULL;
	UINTN dataSize = 0;
	EFI_STATUS efi_status;
	volatile register int x = 0;
	extern char _etext, _edata;

	efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize, guid);
	if (EFI_ERROR(efi_status)) {
		return;
	}

	if (x)
		return;

	x = 1;
	Print(L"add-symbol-file "DEBUGDIR
980
	      L"fb" EFI_ARCH L".efi.debug %p -s .data %p\n", &_etext,
981 982 983
	      &_edata);
}

984 985 986 987 988 989 990
EFI_STATUS
efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
	EFI_STATUS rc;

	InitializeLib(image, systab);

991 992 993 994 995
	/*
	 * if SHIM_DEBUG is set, wait for a debugger to attach.
	 */
	debug_hook();

996 997 998 999 1000 1001 1002 1003
	rc = uefi_call_wrapper(BS->HandleProtocol, 3, image, &LoadedImageProtocol, (void *)&this_image);
	if (EFI_ERROR(rc)) {
		Print(L"Error: could not find loaded image: %d\n", rc);
		return rc;
	}

	Print(L"System BootOrder not found.  Initializing defaults.\n");

1004 1005
	set_boot_order();

1006 1007 1008 1009 1010 1011
	rc = find_boot_options(this_image->DeviceHandle);
	if (EFI_ERROR(rc)) {
		Print(L"Error: could not find boot options: %d\n", rc);
		return rc;
	}

1012 1013 1014 1015 1016 1017 1018
	rc = fallback_should_prefer_reset();
	if (EFI_ERROR(rc)) {
		VerbosePrint(L"tpm not present, starting the first image\n");
		try_start_first_option(image);
	} else {
		VerbosePrint(L"tpm present, resetting system\n");
	}
1019

1020
	Print(L"Reset System\n");
1021 1022 1023 1024 1025 1026

	if (get_fallback_verbose()) {
		Print(L"Verbose enabled, sleeping for half a second\n");
		uefi_call_wrapper(BS->Stall, 1, 500000);
	}

1027
	uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold,
1028 1029
			  EFI_SUCCESS, 0, NULL);

1030 1031
	return EFI_SUCCESS;
}