summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2012-06-13 01:51:39 -0400
committerMatthew Garrett <mjg@redhat.com>2012-06-18 17:31:42 -0400
commit03685963c5fae4ab3c0da4b1c40cdc31123d5614 (patch)
tree442ea32a110bcd90ae3a3ab1eff6def09efcf526
parentb6db0dd4db04d522632a43c3232d1099592d0ae2 (diff)
downloadefi-boot-shim-03685963c5fae4ab3c0da4b1c40cdc31123d5614.tar.gz
efi-boot-shim-03685963c5fae4ab3c0da4b1c40cdc31123d5614.zip
Attempt to start image using LoadImage/StartImage first
-rw-r--r--TODO1
-rw-r--r--shim.c139
2 files changed, 93 insertions, 47 deletions
diff --git a/TODO b/TODO
index bdf43cfe..3f31658e 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,2 @@
Check against blacklist
-Attempt to just LoadImage and StartImage?
Support for netbooting \ No newline at end of file
diff --git a/shim.c b/shim.c
index cd079452..106b8585 100644
--- a/shim.c
+++ b/shim.c
@@ -218,6 +218,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
/* FIXME - more paranoia here? */
if (status != EFI_SUCCESS || sb != 1) {
+ Print(L"Secure boot not enabled\n");
status = EFI_SUCCESS;
goto done;
}
@@ -225,6 +226,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
status = get_variable(L"SetupMode", global_var, &charsize, (void *)&setupmode);
if (status == EFI_SUCCESS && setupmode == 1) {
+ Print(L"Platform is in setup mode\n");
goto done;
}
@@ -518,33 +520,14 @@ static EFI_STATUS handle_grub (void *data, int datasize)
return EFI_SUCCESS;
}
-/*
- * Locate the second stage bootloader and read it into a buffer
- */
-static EFI_STATUS load_grub (EFI_HANDLE image_handle, void **data,
- int *datasize)
+static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **grubpath, CHAR16 **PathName)
{
- EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
- EFI_GUID simple_file_system_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
- EFI_GUID file_info_id = EFI_FILE_INFO_ID;
- EFI_STATUS efi_status;
EFI_DEVICE_PATH *devpath;
- EFI_FILE_INFO *fileinfo = NULL;
- EFI_LOADED_IMAGE *li;
- EFI_FILE_IO_INTERFACE *drive;
- EFI_FILE *root, *grub;
- FILEPATH_DEVICE_PATH *FilePath;
- CHAR16 *PathName = NULL;
EFI_HANDLE device;
- unsigned int buffersize = sizeof(EFI_FILE_INFO);
- unsigned int pathlen = 0;
+ FILEPATH_DEVICE_PATH *FilePath;
int len;
-
- efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
- &loaded_image_protocol, &li);
-
- if (efi_status != EFI_SUCCESS)
- return efi_status;
+ unsigned int pathlen = 0;
+ EFI_STATUS efi_status = EFI_SUCCESS;
device = li->DeviceHandle;
devpath = li->FilePath;
@@ -572,10 +555,10 @@ static EFI_STATUS load_grub (EFI_HANDLE image_handle, void **data,
devpath = NextDevicePathNode(devpath);
}
- PathName = AllocatePool(pathlen + StrLen(SECOND_STAGE));
- PathName[0] = '\0';
+ *PathName = AllocatePool(pathlen + StrLen(SECOND_STAGE));
+ *PathName[0] = '\0';
- if (!PathName) {
+ if (!*PathName) {
Print(L"Failed to allocate path buffer\n");
efi_status = EFI_OUT_OF_RESOURCES;
goto error;
@@ -605,21 +588,44 @@ static EFI_STATUS load_grub (EFI_HANDLE image_handle, void **data,
/* If no leading \, need to add one */
if (tmpbuffer[0] != '\\')
- StrCat(PathName, L"\\");
+ StrCat(*PathName, L"\\");
/* If trailing \, need to strip it */
if (tmpbuffer[len-1] == '\\')
tmpbuffer[len=1] = '\0';
- StrCat(PathName, tmpbuffer);
+ StrCat(*PathName, tmpbuffer);
FreePool(tmpbuffer);
devpath = NextDevicePathNode(devpath);
}
- StrCat(PathName, SECOND_STAGE);
+ StrCat(*PathName, SECOND_STAGE);
+
+ *grubpath = FileDevicePath(device, *PathName);
+
+error:
+ return efi_status;
+}
+
+/*
+ * Locate the second stage bootloader and read it into a buffer
+ */
+static EFI_STATUS load_grub (EFI_LOADED_IMAGE *li, void **data,
+ int *datasize, CHAR16 *PathName)
+{
+ EFI_GUID simple_file_system_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
+ EFI_GUID file_info_id = EFI_FILE_INFO_ID;
+ EFI_STATUS efi_status;
+ EFI_HANDLE device;
+ EFI_FILE_INFO *fileinfo = NULL;
+ EFI_FILE_IO_INTERFACE *drive;
+ EFI_FILE *root, *grub;
+ unsigned int buffersize = sizeof(EFI_FILE_INFO);
+
+ device = li->DeviceHandle;
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
- &simple_file_system_protocol, &drive);
+ &simple_file_system_protocol, &drive);
if (efi_status != EFI_SUCCESS) {
Print(L"Failed to find fs\n");
@@ -708,7 +714,7 @@ error:
return efi_status;
}
-EFI_STATUS shim_verify (void *buffer, int size)
+EFI_STATUS shim_verify (void *buffer, UINT32 size)
{
EFI_STATUS status;
PE_COFF_LOADER_IMAGE_CONTEXT context;
@@ -723,39 +729,80 @@ EFI_STATUS shim_verify (void *buffer, int size)
return status;
}
-EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
+EFI_STATUS init_grub(EFI_HANDLE image_handle)
{
EFI_STATUS efi_status;
- EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
+ EFI_HANDLE grub_handle = NULL;
+ EFI_LOADED_IMAGE *li;
+ EFI_DEVICE_PATH *grubpath;
+ CHAR16 *PathName;
+ EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
void *data = NULL;
int datasize;
- static SHIM_LOCK shim_lock_interface;
- EFI_HANDLE handle = NULL;
- shim_lock_interface.Verify = shim_verify;
+ efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
+ &loaded_image_protocol, &li);
- systab = passed_systab;
+ if (efi_status != EFI_SUCCESS) {
+ Print(L"Unable to init protocol\n");
+ return efi_status;
+ }
- InitializeLib(image_handle, systab);
+ efi_status = generate_path(li, &grubpath, &PathName);
+
+ if (efi_status != EFI_SUCCESS) {
+ Print(L"Unable to generate grub path\n");
+ goto done;
+ }
- efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4,
- &handle, &shim_lock_guid,
- EFI_NATIVE_INTERFACE,
- &shim_lock_interface);
+ efi_status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, image_handle,
+ grubpath, NULL, 0, &grub_handle);
- efi_status = load_grub(image_handle, &data, &datasize);
+
+ if (efi_status == EFI_SUCCESS) {
+ /* Image validates - start it */
+ Print(L"Starting file via StartImage\n");
+ efi_status = uefi_call_wrapper(BS->StartImage, 3, grub_handle, NULL,
+ NULL);
+ uefi_call_wrapper(BS->UnloadImage, 1, grub_handle);
+ goto done;
+ }
+
+ efi_status = load_grub(li, &data, &datasize, PathName);
if (efi_status != EFI_SUCCESS) {
Print(L"Failed to load grub\n");
- return efi_status;
+ goto done;
}
efi_status = handle_grub(data, datasize);
if (efi_status != EFI_SUCCESS) {
Print(L"Failed to load grub\n");
- return efi_status;
+ goto done;
}
- return uefi_call_wrapper(entry_point, 3, image_handle, passed_systab);
+ efi_status = uefi_call_wrapper(entry_point, 3, image_handle, systab);
+done:
+
+ return efi_status;
+}
+
+EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
+{
+ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
+ static SHIM_LOCK shim_lock_interface;
+ EFI_HANDLE handle = NULL;
+
+ shim_lock_interface.Verify = shim_verify;
+
+ systab = passed_systab;
+
+ InitializeLib(image_handle, systab);
+
+ uefi_call_wrapper(BS->InstallProtocolInterface, 4, &handle,
+ &shim_lock_guid, EFI_NATIVE_INTERFACE,
+ &shim_lock_interface);
+
+ return init_grub(image_handle);
}