Attempt to start image using LoadImage/StartImage first

This commit is contained in:
Matthew Garrett 2012-06-18 17:31:42 -04:00
parent 5bc80cec92
commit db54b0a4c6
2 changed files with 99 additions and 53 deletions

1
TODO
View File

@ -1,3 +1,2 @@
Check against blacklist Check against blacklist
Attempt to just LoadImage and StartImage?
Support for netbooting Support for netbooting

151
shim.c
View File

@ -218,6 +218,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
/* FIXME - more paranoia here? */ /* FIXME - more paranoia here? */
if (status != EFI_SUCCESS || sb != 1) { if (status != EFI_SUCCESS || sb != 1) {
Print(L"Secure boot not enabled\n");
status = EFI_SUCCESS; status = EFI_SUCCESS;
goto done; 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); status = get_variable(L"SetupMode", global_var, &charsize, (void *)&setupmode);
if (status == EFI_SUCCESS && setupmode == 1) { if (status == EFI_SUCCESS && setupmode == 1) {
Print(L"Platform is in setup mode\n");
goto done; goto done;
} }
@ -518,33 +520,14 @@ static EFI_STATUS handle_grub (void *data, int datasize)
return EFI_SUCCESS; return EFI_SUCCESS;
} }
/* static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **grubpath, CHAR16 **PathName)
* Locate the second stage bootloader and read it into a buffer
*/
static EFI_STATUS load_grub (EFI_HANDLE image_handle, void **data,
int *datasize)
{ {
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_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; EFI_HANDLE device;
unsigned int buffersize = sizeof(EFI_FILE_INFO); FILEPATH_DEVICE_PATH *FilePath;
unsigned int pathlen = 0;
int len; int len;
unsigned int pathlen = 0;
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, EFI_STATUS efi_status = EFI_SUCCESS;
&loaded_image_protocol, &li);
if (efi_status != EFI_SUCCESS)
return efi_status;
device = li->DeviceHandle; device = li->DeviceHandle;
devpath = li->FilePath; devpath = li->FilePath;
@ -572,10 +555,10 @@ static EFI_STATUS load_grub (EFI_HANDLE image_handle, void **data,
devpath = NextDevicePathNode(devpath); devpath = NextDevicePathNode(devpath);
} }
PathName = AllocatePool(pathlen + StrLen(SECOND_STAGE)); *PathName = AllocatePool(pathlen + StrLen(SECOND_STAGE));
PathName[0] = '\0'; *PathName[0] = '\0';
if (!PathName) { if (!*PathName) {
Print(L"Failed to allocate path buffer\n"); Print(L"Failed to allocate path buffer\n");
efi_status = EFI_OUT_OF_RESOURCES; efi_status = EFI_OUT_OF_RESOURCES;
goto error; 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 no leading \, need to add one */
if (tmpbuffer[0] != '\\') if (tmpbuffer[0] != '\\')
StrCat(PathName, L"\\"); StrCat(*PathName, L"\\");
/* If trailing \, need to strip it */ /* If trailing \, need to strip it */
if (tmpbuffer[len-1] == '\\') if (tmpbuffer[len-1] == '\\')
tmpbuffer[len=1] = '\0'; tmpbuffer[len=1] = '\0';
StrCat(PathName, tmpbuffer); StrCat(*PathName, tmpbuffer);
FreePool(tmpbuffer); FreePool(tmpbuffer);
devpath = NextDevicePathNode(devpath); 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, efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
&simple_file_system_protocol, &drive); &simple_file_system_protocol, &drive);
if (efi_status != EFI_SUCCESS) { if (efi_status != EFI_SUCCESS) {
Print(L"Failed to find fs\n"); Print(L"Failed to find fs\n");
@ -708,7 +714,7 @@ error:
return efi_status; return efi_status;
} }
EFI_STATUS shim_verify (void *buffer, int size) EFI_STATUS shim_verify (void *buffer, UINT32 size)
{ {
EFI_STATUS status; EFI_STATUS status;
PE_COFF_LOADER_IMAGE_CONTEXT context; PE_COFF_LOADER_IMAGE_CONTEXT context;
@ -723,12 +729,68 @@ EFI_STATUS shim_verify (void *buffer, int size)
return status; 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_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; void *data = NULL;
int datasize; int datasize;
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
&loaded_image_protocol, &li);
if (efi_status != EFI_SUCCESS) {
Print(L"Unable to init protocol\n");
return efi_status;
}
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->LoadImage, 6, FALSE, image_handle,
grubpath, NULL, 0, &grub_handle);
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");
goto done;
}
efi_status = handle_grub(data, datasize);
if (efi_status != EFI_SUCCESS) {
Print(L"Failed to load grub\n");
goto done;
}
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; static SHIM_LOCK shim_lock_interface;
EFI_HANDLE handle = NULL; EFI_HANDLE handle = NULL;
@ -738,24 +800,9 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
InitializeLib(image_handle, systab); InitializeLib(image_handle, systab);
efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, uefi_call_wrapper(BS->InstallProtocolInterface, 4, &handle,
&handle, &shim_lock_guid, &shim_lock_guid, EFI_NATIVE_INTERFACE,
EFI_NATIVE_INTERFACE, &shim_lock_interface);
&shim_lock_interface);
efi_status = load_grub(image_handle, &data, &datasize); return init_grub(image_handle);
if (efi_status != EFI_SUCCESS) {
Print(L"Failed to load grub\n");
return efi_status;
}
efi_status = handle_grub(data, datasize);
if (efi_status != EFI_SUCCESS) {
Print(L"Failed to load grub\n");
return efi_status;
}
return uefi_call_wrapper(entry_point, 3, image_handle, passed_systab);
} }