Skip to content

Commit 498b149

Browse files
committed
fallback: don't add new boot order entries backwards
In issues #554 and elsewhere, it's been noted that when fallback is creating multiple entries, it will create them in one order and add them to BootOrder in the opposite order. This is weird. This patch changes fallback to keep a list of "new" entries, and then prepend that entire list to BootOrder when it's done, rather than prepending one at a time, that avoiding the inversion. Resolves issue #554. Signed-off-by: Peter Jones <pjones@redhat.com>
1 parent 81d40e3 commit 498b149

File tree

1 file changed

+74
-50
lines changed

1 file changed

+74
-50
lines changed

fallback.c

Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,17 @@ make_full_path(CHAR16 *dirname, CHAR16 *filename, CHAR16 **out, UINT64 *outlen)
119119
return EFI_SUCCESS;
120120
}
121121

122-
CHAR16 *bootorder = NULL;
123-
int nbootorder = 0;
122+
UINT16 *bootorder = NULL;
123+
UINTN nbootorder = 0;
124124

125125
EFI_DEVICE_PATH *first_new_option = NULL;
126126
VOID *first_new_option_args = NULL;
127127
UINTN first_new_option_size = 0;
128128

129129
EFI_STATUS
130130
add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
131-
CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
131+
CHAR16 *filename, CHAR16 *label, CHAR16 *arguments,
132+
UINT16 **newbootentries, UINTN *nnewbootentries)
132133
{
133134
static int i = 0;
134135
CHAR16 varname[] = L"Boot0000";
@@ -188,24 +189,21 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
188189
return efi_status;
189190
}
190191

191-
CHAR16 *newbootorder = AllocateZeroPool(sizeof (CHAR16)
192-
* (nbootorder + 1));
192+
UINT16 *newbootorder = AllocateZeroPool(sizeof (UINT16) * (*nnewbootentries + 1));
193193
if (!newbootorder)
194194
return EFI_OUT_OF_RESOURCES;
195195

196-
int j = 0;
197-
newbootorder[0] = i & 0xffff;
198-
if (nbootorder) {
199-
for (j = 0; j < nbootorder; j++)
200-
newbootorder[j+1] = bootorder[j];
201-
FreePool(bootorder);
202-
}
203-
bootorder = newbootorder;
204-
nbootorder += 1;
205-
VerbosePrint(L"nbootorder: %d\nBootOrder: ",
206-
nbootorder);
207-
for (j = 0 ; j < nbootorder ; j++)
208-
VerbosePrintUnprefixed(L"%04x ", bootorder[j]);
196+
UINTN j = 0;
197+
CopyMem(newbootorder, *newbootentries, sizeof (UINT16) * (*nnewbootentries));
198+
newbootorder[*nnewbootentries] = i & 0xffff;
199+
if (*newbootentries)
200+
FreePool(*newbootentries);
201+
*newbootentries = newbootorder;
202+
*nnewbootentries += 1;
203+
VerbosePrint(L"nnewbootentries: %d\nnewbootentries: ",
204+
*nnewbootentries);
205+
for (j = 0 ; j < *nnewbootentries ; j++)
206+
VerbosePrintUnprefixed(L"%04x ", (*newbootentries)[j]);
209207
VerbosePrintUnprefixed(L"\n");
210208

211209
return EFI_SUCCESS;
@@ -424,13 +422,13 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp,
424422
EFI_STATUS
425423
set_boot_order(void)
426424
{
427-
CHAR16 *oldbootorder;
425+
UINT16 *oldbootorder;
428426
UINTN size;
429427

430428
oldbootorder = LibGetVariableAndSize(L"BootOrder", &GV_GUID, &size);
431429
if (oldbootorder) {
432-
int i;
433-
nbootorder = size / sizeof (CHAR16);
430+
UINTN i;
431+
nbootorder = size / sizeof (UINT16);
434432
bootorder = oldbootorder;
435433

436434
VerbosePrint(L"Original nbootorder: %d\nOriginal BootOrder: ",
@@ -444,23 +442,41 @@ set_boot_order(void)
444442
}
445443

446444
EFI_STATUS
447-
update_boot_order(void)
445+
update_boot_order(UINT16 *newbootentries, UINTN nnewbootentries)
448446
{
449447
UINTN size;
450448
UINTN len = 0;
451-
CHAR16 *newbootorder = NULL;
449+
UINT16 *newbootorder = NULL;
452450
EFI_STATUS efi_status;
451+
UINTN i;
452+
453+
VerbosePrint(L"old boot order: ");
454+
for (i = 0; i < nbootorder; i++)
455+
VerbosePrintUnprefixed(L"%04x ", bootorder[i]);
456+
VerbosePrintUnprefixed(L"\n");
457+
VerbosePrint(L"new boot entries: ");
458+
for (i = 0; i < nnewbootentries; i++)
459+
VerbosePrintUnprefixed(L"%04x ", newbootentries[i]);
460+
VerbosePrintUnprefixed(L"\n");
453461

454-
size = nbootorder * sizeof(CHAR16);
462+
size = nbootorder * sizeof(UINT16) + nnewbootentries * sizeof(UINT16);
455463
newbootorder = AllocateZeroPool(size);
456464
if (!newbootorder)
457465
return EFI_OUT_OF_RESOURCES;
458-
CopyMem(newbootorder, bootorder, size);
466+
for (i = 0 ; i < nnewbootentries; i++) {
467+
newbootorder[i] = newbootentries[i];
468+
}
469+
CopyMem(&newbootorder[i], bootorder, nbootorder * sizeof(UINT16));
459470

460-
VerbosePrint(L"nbootorder: %d\nBootOrder: ", size / sizeof (CHAR16));
461-
UINTN j;
462-
for (j = 0 ; j < size / sizeof (CHAR16); j++)
463-
VerbosePrintUnprefixed(L"%04x ", newbootorder[j]);
471+
if (bootorder)
472+
FreePool(bootorder);
473+
nbootorder = nnewbootentries + nbootorder;
474+
bootorder = newbootorder;
475+
476+
VerbosePrint(L"updated nbootorder: %d\n", nbootorder);
477+
VerbosePrint(L"updated bootoder: ");
478+
for (i = 0; i < nbootorder; i++)
479+
VerbosePrintUnprefixed(L"%04x ", bootorder[i]);
464480
VerbosePrintUnprefixed(L"\n");
465481
efi_status = RT->GetVariable(L"BootOrder", &GV_GUID, NULL, &len, NULL);
466482
if (efi_status == EFI_BUFFER_TOO_SMALL)
@@ -470,13 +486,13 @@ update_boot_order(void)
470486
EFI_VARIABLE_NON_VOLATILE |
471487
EFI_VARIABLE_BOOTSERVICE_ACCESS |
472488
EFI_VARIABLE_RUNTIME_ACCESS,
473-
size, newbootorder);
474-
FreePool(newbootorder);
489+
size, bootorder);
475490
return efi_status;
476491
}
477492

478493
EFI_STATUS
479-
add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
494+
add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments,
495+
UINT16 **newbootentries, UINTN *nnewbootentries)
480496
{
481497
CHAR16 *fullpath = NULL;
482498
UINT64 pathlen = 0;
@@ -535,50 +551,50 @@ add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *argum
535551
arguments, &option);
536552
if (EFI_ERROR(efi_status)) {
537553
add_boot_option(dp, full_device_path, fullpath, label,
538-
arguments);
554+
arguments, newbootentries, nnewbootentries);
539555
goto done;
540556
}
541557

542558
UINT16 bootnum;
543-
CHAR16 *newbootorder;
559+
UINT16 *newbootorder;
544560
/* Search for the option in the current bootorder */
545561
for (bootnum = 0; bootnum < nbootorder; bootnum++)
546562
if (bootorder[bootnum] == option)
547563
break;
548564
if (bootnum == nbootorder) {
549565
/* Option not found, prepend option and copy the rest */
550-
newbootorder = AllocateZeroPool(sizeof(CHAR16)
566+
newbootorder = AllocateZeroPool(sizeof(UINT16)
551567
* (nbootorder + 1));
552568
if (!newbootorder) {
553569
efi_status = EFI_OUT_OF_RESOURCES;
554570
goto done;
555571
}
556572
newbootorder[0] = option;
557573
CopyMem(newbootorder + 1, bootorder,
558-
sizeof(CHAR16) * nbootorder);
574+
sizeof(UINT16) * nbootorder);
559575
FreePool(bootorder);
560576
bootorder = newbootorder;
561577
nbootorder += 1;
562578
} else {
563579
/* Option found, put first and slice the rest */
564580
newbootorder = AllocateZeroPool(
565-
sizeof(CHAR16) * nbootorder);
581+
sizeof(UINT16) * nbootorder);
566582
if (!newbootorder) {
567583
efi_status = EFI_OUT_OF_RESOURCES;
568584
goto done;
569585
}
570586
newbootorder[0] = option;
571587
CopyMem(newbootorder + 1, bootorder,
572-
sizeof(CHAR16) * bootnum);
588+
sizeof(UINT16) * bootnum);
573589
CopyMem(newbootorder + 1 + bootnum,
574590
bootorder + bootnum + 1,
575-
sizeof(CHAR16) * (nbootorder - bootnum - 1));
591+
sizeof(UINT16) * (nbootorder - bootnum - 1));
576592
FreePool(bootorder);
577593
bootorder = newbootorder;
578594
}
579595
VerbosePrint(L"New nbootorder: %d\nBootOrder: ",
580596
nbootorder);
581-
for (int i = 0 ; i < nbootorder ; i++)
597+
for (UINTN i = 0 ; i < nbootorder ; i++)
582598
VerbosePrintUnprefixed(L"%04x ", bootorder[i]);
583599
VerbosePrintUnprefixed(L"\n");
584600

@@ -593,7 +609,8 @@ add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *argum
593609
}
594610

595611
EFI_STATUS
596-
populate_stanza(CHAR16 *dirname, CHAR16 *filename UNUSED, CHAR16 *csv)
612+
populate_stanza(CHAR16 *dirname, CHAR16 *filename UNUSED, CHAR16 *csv,
613+
UINT16 **newbootentries, UINTN *nnewbootentries)
597614
{
598615
CHAR16 *file = csv;
599616
VerbosePrint(L"CSV data: \"%s\"\n", csv);
@@ -617,13 +634,14 @@ populate_stanza(CHAR16 *dirname, CHAR16 *filename UNUSED, CHAR16 *csv)
617634
/* This one is optional, so don't check if comma2 is 0 */
618635
VerbosePrint(L"arguments: \"%s\"\n", arguments);
619636

620-
add_to_boot_list(dirname, file, label, arguments);
637+
add_to_boot_list(dirname, file, label, arguments, newbootentries, nnewbootentries);
621638

622639
return EFI_SUCCESS;
623640
}
624641

625642
EFI_STATUS
626-
try_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename)
643+
try_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename,
644+
UINT16 **newbootentries, UINTN *nnewbootentries)
627645
{
628646
CHAR16 *fullpath = NULL;
629647
UINT64 pathlen = 0;
@@ -672,7 +690,7 @@ try_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename)
672690
CHAR16 c = start[l];
673691
start[l] = L'\0';
674692

675-
populate_stanza(dirname, filename, start);
693+
populate_stanza(dirname, filename, start, newbootentries, nnewbootentries);
676694

677695
start[l] = c;
678696
start += l;
@@ -683,7 +701,8 @@ try_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename)
683701
}
684702

685703
EFI_STATUS
686-
find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname)
704+
find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname,
705+
UINT16 **newbootentries, UINTN *nnewbootentries)
687706
{
688707
EFI_STATUS efi_status;
689708
void *buffer = NULL;
@@ -782,7 +801,8 @@ find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname)
782801
console_print(L"Couldn't open \\EFI\\%s\\%s: %r\n",
783802
dirname, bootarchcsv, efi_status);
784803
} else {
785-
efi_status = try_boot_csv(fh2, dirname, bootarchcsv);
804+
efi_status = try_boot_csv(fh2, dirname, bootarchcsv,
805+
newbootentries, nnewbootentries);
786806
fh2->Close(fh2);
787807
if (EFI_ERROR(efi_status))
788808
console_print(L"Could not process \\EFI\\%s\\%s: %r\n",
@@ -797,7 +817,8 @@ find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname)
797817
console_print(L"Couldn't open \\EFI\\%s\\%s: %r\n",
798818
dirname, bootcsv, efi_status);
799819
} else {
800-
efi_status = try_boot_csv(fh2, dirname, bootcsv);
820+
efi_status = try_boot_csv(fh2, dirname, bootcsv,
821+
newbootentries, nnewbootentries);
801822
fh2->Close(fh2);
802823
if (EFI_ERROR(efi_status))
803824
console_print(L"Could not process \\EFI\\%s\\%s: %r\n",
@@ -812,6 +833,8 @@ find_boot_options(EFI_HANDLE device)
812833
{
813834
EFI_STATUS efi_status;
814835
EFI_FILE_IO_INTERFACE *fio = NULL;
836+
UINT16 *newbootentries = NULL;
837+
UINTN nnewbootentries = 0;
815838

816839
efi_status = BS->HandleProtocol(device, &FileSystemProtocol,
817840
(void **) &fio);
@@ -903,7 +926,8 @@ find_boot_options(EFI_HANDLE device)
903926
continue;
904927
}
905928

906-
efi_status = find_boot_csv(fh3, fi->FileName);
929+
efi_status = find_boot_csv(fh3, fi->FileName,
930+
&newbootentries, &nnewbootentries);
907931
fh3->Close(fh3);
908932
FreePool(buffer);
909933
buffer = NULL;
@@ -912,8 +936,8 @@ find_boot_options(EFI_HANDLE device)
912936

913937
} while (1);
914938

915-
if (!EFI_ERROR(efi_status) && nbootorder > 0)
916-
efi_status = update_boot_order();
939+
if (!EFI_ERROR(efi_status) && (nbootorder > 0 || nnewbootentries > 0))
940+
efi_status = update_boot_order(newbootentries, nnewbootentries);
917941

918942
fh2->Close(fh2);
919943
fh->Close(fh);

0 commit comments

Comments
 (0)