Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add configuration option to boot an alternative 2nd stage #608

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ CFLAGS += -DENABLE_SHIM_CERT
else
TARGETS += $(MMNAME) $(FBNAME)
endif
OBJS = shim.o globals.o mok.o netboot.o cert.o dp.o replacements.o tpm.o version.o errlog.o sbat.o sbat_data.o sbat_var.o pe.o pe-relocate.o httpboot.o csv.o load-options.o
OBJS = shim.o globals.o mok.o netboot.o cert.o dp.o replacements.o tpm.o version.o errlog.o sbat.o sbat_data.o sbat_var.o pe.o pe-relocate.o httpboot.o csv.o load-options.o utils.o
KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key shim.cer
ORIG_SOURCES = shim.c globals.c mok.c netboot.c dp.c replacements.c tpm.c errlog.c sbat.c pe.c pe-relocate.c httpboot.c shim.h version.h $(wildcard include/*.h) cert.S sbat_var.S
MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o errlog.o sbat_data.o globals.o dp.o
ORIG_MOK_SOURCES = MokManager.c PasswordCrypt.c crypt_blowfish.c shim.h $(wildcard include/*.h)
FALLBACK_OBJS = fallback.o tpm.o errlog.o sbat_data.o globals.o
FALLBACK_OBJS = fallback.o tpm.o errlog.o sbat_data.o globals.o utils.o
ORIG_FALLBACK_SRCS = fallback.c
SBATPATH = $(TOPDIR)/data/sbat.csv

Expand Down
83 changes: 0 additions & 83 deletions fallback.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,89 +94,6 @@ FindSubDevicePath(EFI_DEVICE_PATH *In, UINT8 Type, UINT8 SubType,
return EFI_NOT_FOUND;
}

static EFI_STATUS
get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize)
{
EFI_STATUS efi_status;
void *buffer = NULL;
UINTN bs = 0;

/* 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. */
efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, NULL);
if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL)
return efi_status;
if (bs == 0)
return EFI_SUCCESS;

buffer = AllocateZeroPool(bs);
if (!buffer) {
console_print(L"Could not allocate memory\n");
return EFI_OUT_OF_RESOURCES;
}
efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &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(efi_status)) {
console_print(L"Could not get file info: %r\n", efi_status);
if (buffer)
FreePool(buffer);
return efi_status;
}
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 efi_status;

efi_status = fh->Open(fh, &fh2, fullpath, EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(efi_status)) {
console_print(L"Couldn't open \"%s\": %r\n", fullpath, efi_status);
return efi_status;
}

UINTN len = 0;
CHAR16 *b = NULL;
efi_status = get_file_size(fh2, &len);
if (EFI_ERROR(efi_status)) {
console_print(L"Could not get file size for \"%s\": %r\n",
fullpath, efi_status);
fh2->Close(fh2);
return efi_status;
}

if (len > 1024 * PAGE_SIZE) {
fh2->Close(fh2);
return EFI_BAD_BUFFER_SIZE;
}

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

efi_status = fh->Read(fh, &len, b);
if (EFI_ERROR(efi_status)) {
FreePool(b);
fh2->Close(fh2);
console_print(L"Could not read file: %r\n", efi_status);
return efi_status;
}
*buffer = b;
*bs = len;
fh2->Close(fh2);
return EFI_SUCCESS;
}

EFI_STATUS
make_full_path(CHAR16 *dirname, CHAR16 *filename, CHAR16 **out, UINT64 *outlen)
{
Expand Down
1 change: 1 addition & 0 deletions include/load-options.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ EFI_STATUS generate_path_from_image_path(EFI_LOADED_IMAGE *li,
EFI_STATUS parse_load_options(EFI_LOADED_IMAGE *li);

extern CHAR16 *second_stage;
extern CHAR16 *optional_second_stage;
extern void *load_options;
extern UINT32 load_options_size;

Expand Down
9 changes: 9 additions & 0 deletions include/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: BSD-2-Clause-Patent
#ifndef UTILS_H_
#define UTILS_H_

EFI_STATUS get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize);
EFI_STATUS
read_file(EFI_FILE_HANDLE fh, CHAR16 *fullpath, CHAR16 **buffer, UINT64 *bs);

#endif /* UTILS_H_ */
1 change: 1 addition & 0 deletions load-options.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "shim.h"

CHAR16 *second_stage;
CHAR16 *optional_second_stage = NULL;
void *load_options;
UINT32 load_options_size;

Expand Down
83 changes: 82 additions & 1 deletion shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,7 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
EFI_STATUS efi_status;
EFI_LOADED_IMAGE *li = NULL;

second_stage = DEFAULT_LOADER;
second_stage = (optional_second_stage) ? optional_second_stage : DEFAULT_LOADER;
load_options = NULL;
load_options_size = 0;

Expand Down Expand Up @@ -1668,6 +1668,85 @@ load_unbundled_trust(EFI_HANDLE image_handle)
return efi_status;
}

/* Read optional options file */
EFI_STATUS
load_shim_options(EFI_HANDLE image_handle)
{
EFI_STATUS efi_status;
EFI_HANDLE device;
EFI_LOADED_IMAGE *li = NULL;
EFI_FILE_IO_INTERFACE *drive;
EFI_FILE *root;
EFI_FILE_HANDLE ofile;
CHAR16 *PathName = NULL;
CHAR16 *buffer;
UINTN comma0;
UINT64 bs;

efi_status = gBS->HandleProtocol(image_handle, &EFI_LOADED_IMAGE_GUID,
(void **)&li);
if (EFI_ERROR(efi_status)) {
perror(L"Unable to init protocol\n");
return efi_status;
}

efi_status = generate_path_from_image_path(li, L"options.csv", &PathName);
if (EFI_ERROR(efi_status))
goto done;

device = li->DeviceHandle;

efi_status = BS->HandleProtocol(device, &EFI_SIMPLE_FILE_SYSTEM_GUID,
(void **) &drive);
if (EFI_ERROR(efi_status))
goto done;

efi_status = drive->OpenVolume(drive, &root);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to open fs: %r\n", efi_status);
goto done;
}

efi_status = root->Open(root, &ofile, PathName, EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(efi_status)) {
esnowberg marked this conversation as resolved.
Show resolved Hide resolved
if (efi_status != EFI_NOT_FOUND)
perror(L"Failed to open %s - %r\n", PathName, efi_status);
goto done;
}

efi_status = read_file(ofile, PathName, &buffer, &bs);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to read file\n");
goto done;
}

/*
* This file may or may not start with the Unicode byte order marker.
* Since UEFI is defined as LE, this file must also be LE.
* If we find the LE byte order marker, just skip its.
*/
if (*buffer == 0xfeff)
buffer++;

comma0 = StrCSpn(buffer, L",");
if (comma0 == 0) {
perror(L"Invalid csv file\n");
goto done;
}

/*
* Currently the options.csv file allows one entry for the optional
* secondary boot stage, anything afterwards is skipped.
*/
buffer[comma0] = L'\0';
console_print(L"Optional 2nd stage: %s\n", buffer);
optional_second_stage=buffer;

done:
FreePool(PathName);
return EFI_SUCCESS;
}

EFI_STATUS
shim_init(void)
{
Expand Down Expand Up @@ -1952,6 +2031,8 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
*/
(void) del_variable(SHIM_RETAIN_PROTOCOL_VAR_NAME, SHIM_LOCK_GUID);

load_shim_options(image_handle);

efi_status = shim_init();
if (EFI_ERROR(efi_status)) {
msg = SHIM_INIT;
Expand Down
1 change: 1 addition & 0 deletions shim.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
#include "include/simple_file.h"
#include "include/str.h"
#include "include/tpm.h"
#include "include/utils.h"
esnowberg marked this conversation as resolved.
Show resolved Hide resolved
#include "include/cc.h"
#include "include/ucs2.h"
#include "include/variables.h"
Expand Down
86 changes: 86 additions & 0 deletions utils.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: BSD-2-Clause-Patent

#include "shim.h"

EFI_STATUS
get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize)
{
EFI_STATUS efi_status;
void *buffer = NULL;
UINTN bs = 0;

/* 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. */
efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, NULL);
if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL)
return efi_status;
if (bs == 0)
return EFI_SUCCESS;

buffer = AllocateZeroPool(bs);
if (!buffer) {
console_print(L"Could not allocate memory\n");
return EFI_OUT_OF_RESOURCES;
}
efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &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(efi_status)) {
console_print(L"Could not get file info: %r\n", efi_status);
if (buffer)
FreePool(buffer);
return efi_status;
}
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 efi_status;

efi_status = fh->Open(fh, &fh2, fullpath, EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(efi_status)) {
console_print(L"Couldn't open \"%s\": %r\n", fullpath, efi_status);
return efi_status;
}

UINTN len = 0;
CHAR16 *b = NULL;
efi_status = get_file_size(fh2, &len);
if (EFI_ERROR(efi_status)) {
console_print(L"Could not get file size for \"%s\": %r\n",
fullpath, efi_status);
fh2->Close(fh2);
return efi_status;
}

if (len > 1024 * PAGE_SIZE) {
fh2->Close(fh2);
return EFI_BAD_BUFFER_SIZE;
}

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

efi_status = fh->Read(fh, &len, b);
if (EFI_ERROR(efi_status)) {
FreePool(b);
fh2->Close(fh2);
console_print(L"Could not read file: %r\n", efi_status);
return efi_status;
}
*buffer = b;
*bs = len;
fh2->Close(fh2);
return EFI_SUCCESS;
}