mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-06-10 02:30:56 +00:00

If shim is invoked as \EFI\BOOT\BOOT*.EFI and a file exists named \EFI\BOOT\FALLBACK.EFI, try it instead of our second stage. So don't put fallback.efi on your install media in \EFI\BOOT, because that won't do whatever it is you're hoping for, unless you're hoping not to start the installer. So here's the process for using this: in /EFI/fedora/ (or whichever directory you happen to own), you put: shim.efi grub.efi boot.csv - format is: shim.efi,Nice Label,cmdline arguments,comments - filenames refer only to files in this directory, with no leading characters such as L"./" or L"/EFI/fedora/" - note that while this is CSV, the character encoding is UCS-2 and if /EFI/BOOT/BOOTX64.EFI doesn't already exist, then in /EFI/BOOT: shim.efi as BOOTX64.EFI fallback.efi Signed-off-by: Peter Jones <pjones@redhat.com>
620 lines
14 KiB
C
620 lines
14 KiB
C
/*
|
|
* 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"
|
|
|
|
EFI_LOADED_IMAGE *this_image = NULL;
|
|
|
|
static EFI_STATUS
|
|
get_file_size(EFI_FILE_HANDLE fh, UINT64 *retsize)
|
|
{
|
|
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;
|
|
}
|
|
|
|
UINT64 len = 0;
|
|
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;
|
|
|
|
len = StrLen(dirname) + StrLen(filename) + StrLen(L"\\EFI\\\\") + 2;
|
|
|
|
CHAR16 *fullpath = AllocateZeroPool(len);
|
|
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;
|
|
|
|
EFI_STATUS
|
|
add_boot_option(EFI_DEVICE_PATH *dp, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
|
|
{
|
|
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) +
|
|
StrLen(label)*2 + 2 + DevicePathSize(dp) +
|
|
StrLen(arguments) * 2 + 2;
|
|
|
|
CHAR8 *data = AllocateZeroPool(size);
|
|
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);
|
|
|
|
Print(L"Creating boot entry \"%s\" with label \"%s\" "
|
|
L"for file \"%s\"\n",
|
|
varname, label, filename);
|
|
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;
|
|
if (nbootorder) {
|
|
for (j = 0; j < nbootorder; j++)
|
|
newbootorder[j] = bootorder[j];
|
|
FreePool(bootorder);
|
|
}
|
|
newbootorder[j] = i & 0xffff;
|
|
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;
|
|
}
|
|
|
|
EFI_STATUS
|
|
update_boot_order(void)
|
|
{
|
|
CHAR16 *oldbootorder;
|
|
UINTN size;
|
|
EFI_GUID global = EFI_GLOBAL_VARIABLE;
|
|
CHAR16 *newbootorder = NULL;
|
|
|
|
oldbootorder = LibGetVariableAndSize(L"BootOrder", &global, &size);
|
|
if (oldbootorder) {
|
|
int n = size / sizeof (CHAR16) + nbootorder;
|
|
|
|
newbootorder = AllocateZeroPool(n * sizeof (CHAR16));
|
|
CopyMem(newbootorder, bootorder, nbootorder * sizeof (CHAR16));
|
|
CopyMem(newbootorder + nbootorder, oldbootorder, size);
|
|
size = n * sizeof (CHAR16);
|
|
} else {
|
|
size = nbootorder * sizeof(CHAR16);
|
|
newbootorder = AllocateZeroPool(size);
|
|
CopyMem(newbootorder, bootorder, size);
|
|
}
|
|
if (!newbootorder)
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
#ifdef DEBUG_FALLBACK
|
|
Print(L"nbootorder: %d\nBootOrder: ", size / sizeof (CHAR16));
|
|
int j;
|
|
for (j = 0 ; j < size / sizeof (CHAR16); j++)
|
|
Print(L"%04x ", newbootorder[j]);
|
|
Print(L"\n");
|
|
#endif
|
|
|
|
if (oldbootorder) {
|
|
LibDeleteVariable(L"BootOrder", &global);
|
|
FreePool(oldbootorder);
|
|
}
|
|
|
|
EFI_STATUS rc;
|
|
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
|
|
add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
|
|
{
|
|
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;
|
|
|
|
EFI_DEVICE_PATH *dph = NULL, *dpf = NULL, *dp = NULL;
|
|
|
|
dph = DevicePathFromHandle(this_image->DeviceHandle);
|
|
if (!dph) {
|
|
rc = EFI_OUT_OF_RESOURCES;
|
|
goto err;
|
|
}
|
|
|
|
dpf = FileDevicePath(fh, fullpath);
|
|
if (!dpf) {
|
|
rc = EFI_OUT_OF_RESOURCES;
|
|
goto err;
|
|
}
|
|
|
|
dp = AppendDevicePath(dph, dpf);
|
|
if (!dp) {
|
|
rc = EFI_OUT_OF_RESOURCES;
|
|
goto err;
|
|
}
|
|
|
|
#ifdef DEBUG_FALLBACK
|
|
UINTN s = DevicePathSize(dp);
|
|
int i;
|
|
UINT8 *dpv = (void *)dp;
|
|
for (i = 0; i < s; i++) {
|
|
if (i > 0 && i % 16 == 0)
|
|
Print(L"\n");
|
|
Print(L"%02x ", dpv[i]);
|
|
}
|
|
Print(L"\n");
|
|
|
|
CHAR16 *dps = DevicePathToStr(dp);
|
|
Print(L"device path: \"%s\"\n", dps);
|
|
#endif
|
|
|
|
add_boot_option(dp, fullpath, label, arguments);
|
|
FreePool(fullpath);
|
|
|
|
err:
|
|
if (dph)
|
|
FreePool(dph);
|
|
if (dpf)
|
|
FreePool(dpf);
|
|
if (dp)
|
|
FreePool(dp);
|
|
if (fullpath)
|
|
FreePool(fullpath);
|
|
return rc;
|
|
}
|
|
|
|
EFI_STATUS
|
|
populate_stanza(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *csv)
|
|
{
|
|
#ifdef DEBUG_FALLBACK
|
|
Print(L"CSV data: \"%s\"\n", csv);
|
|
#endif
|
|
CHAR16 *file = csv;
|
|
|
|
UINTN comma0 = StrCSpn(csv, L",");
|
|
if (comma0 == 0)
|
|
return EFI_INVALID_PARAMETER;
|
|
file[comma0] = L'\0';
|
|
#ifdef DEBUG_FALLBACK
|
|
Print(L"filename: \"%s\"\n", file);
|
|
#endif
|
|
|
|
CHAR16 *label = csv + comma0 + 1;
|
|
UINTN comma1 = StrCSpn(label, L",");
|
|
if (comma1 == 0)
|
|
return EFI_INVALID_PARAMETER;
|
|
label[comma1] = L'\0';
|
|
#ifdef DEBUG_FALLBACK
|
|
Print(L"label: \"%s\"\n", label);
|
|
#endif
|
|
|
|
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 */
|
|
#ifdef DEBUG_FALLBACK
|
|
Print(L"arguments: \"%s\"\n", arguments);
|
|
#endif
|
|
|
|
add_to_boot_list(fh, dirname, file, label, arguments);
|
|
|
|
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;
|
|
|
|
#ifdef DEBUG_FALLBACK
|
|
Print(L"Found file \"%s\"\n", fullpath);
|
|
#endif
|
|
|
|
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);
|
|
|
|
#ifdef DEBUG_FALLBACK
|
|
Print(L"File looks like:\n%s\n", buffer);
|
|
#endif
|
|
|
|
CHAR16 *start = buffer;
|
|
/* If I create boot.csv with the efi shell's "edit" command,
|
|
* it starts with 0xfeff. I assume there's some reason for this,
|
|
* but it doesn't matter much to me...
|
|
*/
|
|
if (*start == 0xfeff)
|
|
start++;
|
|
while (*start) {
|
|
while (*start == L'\r' || *start == L'\n') {
|
|
start++;
|
|
continue;
|
|
}
|
|
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';
|
|
|
|
populate_stanza(fh, dirname, filename, start);
|
|
|
|
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);
|
|
|
|
bs = 0;
|
|
do {
|
|
bs = 0;
|
|
rc = uefi_call_wrapper(fh->Read, 3, fh, &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->Read, 3, fh, &bs, buffer);
|
|
}
|
|
if (EFI_ERROR(rc)) {
|
|
Print(L"Could not read \\EFI\\%s\\: %d\n", dirname, rc);
|
|
FreePool(buffer);
|
|
return rc;
|
|
}
|
|
if (bs == 0)
|
|
break;
|
|
|
|
fi = buffer;
|
|
|
|
if (!StrCaseCmp(fi->FileName, L"boot.csv")) {
|
|
EFI_FILE_HANDLE fh2;
|
|
rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2,
|
|
fi->FileName,
|
|
EFI_FILE_READ_ONLY, 0);
|
|
if (EFI_ERROR(rc) || fh2 == NULL) {
|
|
Print(L"Couldn't open \\EFI\\%s\\%s: %d\n",
|
|
dirname, fi->FileName, rc);
|
|
FreePool(buffer);
|
|
buffer = NULL;
|
|
continue;
|
|
}
|
|
rc = try_boot_csv(fh2, dirname, fi->FileName);
|
|
uefi_call_wrapper(fh2->Close, 1, fh2);
|
|
}
|
|
|
|
FreePool(buffer);
|
|
buffer = NULL;
|
|
} while (bs != 0);
|
|
|
|
rc = EFI_SUCCESS;
|
|
if (nbootorder > 0)
|
|
rc = update_boot_order();
|
|
|
|
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,
|
|
&FileSystemProtocol, &fio);
|
|
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;
|
|
}
|
|
#ifdef DEBUG_FALLBACK
|
|
Print(L"Found directory named \"%s\"\n", fi->FileName);
|
|
#endif
|
|
|
|
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);
|
|
|
|
uefi_call_wrapper(fh2->Close, 1, fh2);
|
|
uefi_call_wrapper(fh->Close, 1, fh);
|
|
return EFI_SUCCESS;
|
|
}
|
|
EFI_STATUS
|
|
efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
|
{
|
|
EFI_STATUS rc;
|
|
|
|
InitializeLib(image, systab);
|
|
|
|
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");
|
|
|
|
rc = find_boot_options(this_image->DeviceHandle);
|
|
if (EFI_ERROR(rc)) {
|
|
Print(L"Error: could not find boot options: %d\n", rc);
|
|
return rc;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|