mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-06-13 06:00:57 +00:00
91 lines
1.8 KiB
C
91 lines
1.8 KiB
C
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
/*
|
|
* Copyright 2012 <James.Bottomley@HansenPartnership.com>
|
|
* Code Copyright 2012 Red Hat, Inc <mjg@redhat.com>
|
|
*/
|
|
|
|
#include <efi.h>
|
|
#include <efilib.h>
|
|
|
|
#include "shim.h"
|
|
|
|
EFI_STATUS
|
|
generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName)
|
|
{
|
|
unsigned int pathlen;
|
|
EFI_STATUS efi_status = EFI_SUCCESS;
|
|
CHAR16 *devpathstr = DevicePathToStr(li->FilePath),
|
|
*found = NULL;
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < StrLen(devpathstr); i++) {
|
|
if (devpathstr[i] == '/')
|
|
devpathstr[i] = '\\';
|
|
if (devpathstr[i] == '\\')
|
|
found = &devpathstr[i];
|
|
}
|
|
if (!found) {
|
|
pathlen = 0;
|
|
} else {
|
|
while (*(found - 1) == '\\')
|
|
--found;
|
|
*found = '\0';
|
|
pathlen = StrLen(devpathstr);
|
|
}
|
|
|
|
if (name[0] != '\\')
|
|
pathlen++;
|
|
|
|
*PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16));
|
|
|
|
if (!*PathName) {
|
|
console_print(L"Failed to allocate path buffer\n");
|
|
efi_status = EFI_OUT_OF_RESOURCES;
|
|
goto error;
|
|
}
|
|
|
|
StrCpy(*PathName, devpathstr);
|
|
|
|
if (name[0] != '\\')
|
|
StrCat(*PathName, L"\\");
|
|
StrCat(*PathName, name);
|
|
|
|
*path = FileDevicePath(li->DeviceHandle, *PathName);
|
|
|
|
error:
|
|
FreePool(devpathstr);
|
|
|
|
return efi_status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
execute(EFI_HANDLE image, CHAR16 *name)
|
|
{
|
|
EFI_STATUS efi_status;
|
|
EFI_HANDLE h;
|
|
EFI_LOADED_IMAGE *li;
|
|
EFI_DEVICE_PATH *devpath;
|
|
CHAR16 *PathName;
|
|
|
|
efi_status = gBS->HandleProtocol(image, &IMAGE_PROTOCOL,
|
|
(void **) &li);
|
|
if (EFI_ERROR(efi_status))
|
|
return efi_status;
|
|
|
|
efi_status = generate_path(name, li, &devpath, &PathName);
|
|
if (EFI_ERROR(efi_status))
|
|
return efi_status;
|
|
|
|
efi_status = gBS->LoadImage(FALSE, image, devpath, NULL, 0, &h);
|
|
if (EFI_ERROR(efi_status))
|
|
goto out;
|
|
|
|
efi_status = gBS->StartImage(h, NULL, NULL);
|
|
gBS->UnloadImage(h);
|
|
|
|
out:
|
|
FreePool(PathName);
|
|
FreePool(devpath);
|
|
return efi_status;
|
|
}
|