|
|
4210fa |
From dfd6c73a212f8cf6b32ce74807de9a08a87f0b79 Mon Sep 17 00:00:00 2001
|
|
|
4210fa |
From: Peter Jones <pjones@redhat.com>
|
|
|
4210fa |
Date: Fri, 31 Jan 2014 10:30:24 -0500
|
|
|
4210fa |
Subject: [PATCH 18/74] [fallback] For HD() device paths, use just the media
|
|
|
4210fa |
node and later.
|
|
|
4210fa |
|
|
|
4210fa |
UEFI 2.x section 3.1.2 provides for "short-form device path", where the
|
|
|
4210fa |
first element specified is a "hard drive media device path", so that you
|
|
|
4210fa |
can move a disk around on different buses without invalidating your
|
|
|
4210fa |
device path. Fallback has not been using this option, though in most
|
|
|
4210fa |
cases efibootmgr has.
|
|
|
4210fa |
|
|
|
4210fa |
Note that we still keep the full device path, because LoadImage()
|
|
|
4210fa |
isn't necessarily the layer where HD() works - one some systems BDS is
|
|
|
4210fa |
responsible for resolving the full path and passes that to LoadImage()
|
|
|
4210fa |
instead. So we have to do LoadImage() with the full path.
|
|
|
4210fa |
---
|
|
|
4210fa |
fallback.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++---------------
|
|
|
4210fa |
1 file changed, 78 insertions(+), 25 deletions(-)
|
|
|
4210fa |
|
|
|
4210fa |
diff --git a/fallback.c b/fallback.c
|
|
|
4210fa |
index ba864ee..a12bb74 100644
|
|
|
4210fa |
--- a/fallback.c
|
|
|
4210fa |
+++ b/fallback.c
|
|
|
4210fa |
@@ -15,6 +15,27 @@
|
|
|
4210fa |
EFI_LOADED_IMAGE *this_image = NULL;
|
|
|
4210fa |
|
|
|
4210fa |
static EFI_STATUS
|
|
|
4210fa |
+FindSubDevicePath(EFI_DEVICE_PATH *In, UINT8 Type, UINT8 SubType,
|
|
|
4210fa |
+ EFI_DEVICE_PATH **Out)
|
|
|
4210fa |
+{
|
|
|
4210fa |
+ EFI_DEVICE_PATH *dp = In;
|
|
|
4210fa |
+ if (!In || !Out)
|
|
|
4210fa |
+ return EFI_INVALID_PARAMETER;
|
|
|
4210fa |
+
|
|
|
4210fa |
+ for (dp = In; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) {
|
|
|
4210fa |
+ if (DevicePathType(dp) == Type &&
|
|
|
4210fa |
+ DevicePathSubType(dp) == SubType) {
|
|
|
4210fa |
+ *Out = DuplicateDevicePath(dp);
|
|
|
4210fa |
+ if (!*Out)
|
|
|
4210fa |
+ return EFI_OUT_OF_RESOURCES;
|
|
|
4210fa |
+ return EFI_SUCCESS;
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+ *Out = NULL;
|
|
|
4210fa |
+ return EFI_NOT_FOUND;
|
|
|
4210fa |
+}
|
|
|
4210fa |
+
|
|
|
4210fa |
+static EFI_STATUS
|
|
|
4210fa |
get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize)
|
|
|
4210fa |
{
|
|
|
4210fa |
EFI_STATUS rc;
|
|
|
4210fa |
@@ -93,7 +114,9 @@ make_full_path(CHAR16 *dirname, CHAR16 *filename, CHAR16 **out, UINT64 *outlen)
|
|
|
4210fa |
{
|
|
|
4210fa |
UINT64 len;
|
|
|
4210fa |
|
|
|
4210fa |
- len = StrLen(dirname) + StrLen(filename) + StrLen(L"\\EFI\\\\") + 2;
|
|
|
4210fa |
+ len = StrLen(L"\\EFI\\") + StrLen(dirname)
|
|
|
4210fa |
+ + StrLen(L"\\") + StrLen(filename)
|
|
|
4210fa |
+ + 2;
|
|
|
4210fa |
|
|
|
4210fa |
CHAR16 *fullpath = AllocateZeroPool(len*sizeof(CHAR16));
|
|
|
4210fa |
if (!fullpath) {
|
|
|
4210fa |
@@ -119,7 +142,8 @@ VOID *first_new_option_args = NULL;
|
|
|
4210fa |
UINTN first_new_option_size = 0;
|
|
|
4210fa |
|
|
|
4210fa |
EFI_STATUS
|
|
|
4210fa |
-add_boot_option(EFI_DEVICE_PATH *dp, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
|
|
|
4210fa |
+add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
|
|
|
4210fa |
+ CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
|
|
|
4210fa |
{
|
|
|
4210fa |
static int i = 0;
|
|
|
4210fa |
CHAR16 varname[] = L"Boot0000";
|
|
|
4210fa |
@@ -136,24 +160,31 @@ add_boot_option(EFI_DEVICE_PATH *dp, CHAR16 *filename, CHAR16 *label, CHAR16 *ar
|
|
|
4210fa |
void *var = LibGetVariable(varname, &global);
|
|
|
4210fa |
if (!var) {
|
|
|
4210fa |
int size = sizeof(UINT32) + sizeof (UINT16) +
|
|
|
4210fa |
- StrLen(label)*2 + 2 + DevicePathSize(dp) +
|
|
|
4210fa |
- StrLen(arguments) * 2 + 2;
|
|
|
4210fa |
+ StrLen(label)*2 + 2 + DevicePathSize(hddp) +
|
|
|
4210fa |
+ StrLen(arguments) * 2;
|
|
|
4210fa |
|
|
|
4210fa |
CHAR8 *data = AllocateZeroPool(size);
|
|
|
4210fa |
CHAR8 *cursor = data;
|
|
|
4210fa |
*(UINT32 *)cursor = LOAD_OPTION_ACTIVE;
|
|
|
4210fa |
cursor += sizeof (UINT32);
|
|
|
4210fa |
- *(UINT16 *)cursor = DevicePathSize(dp);
|
|
|
4210fa |
+ *(UINT16 *)cursor = DevicePathSize(hddp);
|
|
|
4210fa |
cursor += sizeof (UINT16);
|
|
|
4210fa |
StrCpy((CHAR16 *)cursor, label);
|
|
|
4210fa |
cursor += StrLen(label)*2 + 2;
|
|
|
4210fa |
- CopyMem(cursor, dp, DevicePathSize(dp));
|
|
|
4210fa |
- cursor += DevicePathSize(dp);
|
|
|
4210fa |
+ CopyMem(cursor, hddp, DevicePathSize(hddp));
|
|
|
4210fa |
+ cursor += DevicePathSize(hddp);
|
|
|
4210fa |
StrCpy((CHAR16 *)cursor, arguments);
|
|
|
4210fa |
|
|
|
4210fa |
Print(L"Creating boot entry \"%s\" with label \"%s\" "
|
|
|
4210fa |
L"for file \"%s\"\n",
|
|
|
4210fa |
varname, label, filename);
|
|
|
4210fa |
+
|
|
|
4210fa |
+ if (!first_new_option) {
|
|
|
4210fa |
+ first_new_option = DuplicateDevicePath(fulldp);
|
|
|
4210fa |
+ first_new_option_args = arguments;
|
|
|
4210fa |
+ first_new_option_size = StrLen(arguments) * sizeof (CHAR16);
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+
|
|
|
4210fa |
rc = uefi_call_wrapper(RT->SetVariable, 5, varname,
|
|
|
4210fa |
&global, EFI_VARIABLE_NON_VOLATILE |
|
|
|
4210fa |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
|
|
4210fa |
@@ -254,7 +285,10 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *
|
|
|
4210fa |
if (EFI_ERROR(rc))
|
|
|
4210fa |
return rc;
|
|
|
4210fa |
|
|
|
4210fa |
- EFI_DEVICE_PATH *dph = NULL, *dpf = NULL, *dp = NULL;
|
|
|
4210fa |
+ EFI_DEVICE_PATH *dph = NULL;
|
|
|
4210fa |
+ EFI_DEVICE_PATH *file = NULL;
|
|
|
4210fa |
+ EFI_DEVICE_PATH *full_device_path = NULL;
|
|
|
4210fa |
+ EFI_DEVICE_PATH *dp = NULL;
|
|
|
4210fa |
|
|
|
4210fa |
dph = DevicePathFromHandle(this_image->DeviceHandle);
|
|
|
4210fa |
if (!dph) {
|
|
|
4210fa |
@@ -262,19 +296,31 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *
|
|
|
4210fa |
goto err;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
- dpf = FileDevicePath(fh, fullpath);
|
|
|
4210fa |
- if (!dpf) {
|
|
|
4210fa |
+ file = FileDevicePath(fh, fullpath);
|
|
|
4210fa |
+ if (!file) {
|
|
|
4210fa |
rc = EFI_OUT_OF_RESOURCES;
|
|
|
4210fa |
goto err;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
- dp = AppendDevicePath(dph, dpf);
|
|
|
4210fa |
- if (!dp) {
|
|
|
4210fa |
+ full_device_path = AppendDevicePath(dph, file);
|
|
|
4210fa |
+ if (!full_device_path) {
|
|
|
4210fa |
rc = EFI_OUT_OF_RESOURCES;
|
|
|
4210fa |
goto err;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
+ rc = FindSubDevicePath(full_device_path,
|
|
|
4210fa |
+ MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, &dp;;
|
|
|
4210fa |
+ if (EFI_ERROR(rc)) {
|
|
|
4210fa |
+ if (rc == EFI_NOT_FOUND) {
|
|
|
4210fa |
+ dp = full_device_path;
|
|
|
4210fa |
+ } else {
|
|
|
4210fa |
+ rc = EFI_OUT_OF_RESOURCES;
|
|
|
4210fa |
+ goto err;
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+
|
|
|
4210fa |
#ifdef DEBUG_FALLBACK
|
|
|
4210fa |
+ {
|
|
|
4210fa |
UINTN s = DevicePathSize(dp);
|
|
|
4210fa |
int i;
|
|
|
4210fa |
UINT8 *dpv = (void *)dp;
|
|
|
4210fa |
@@ -287,20 +333,16 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *
|
|
|
4210fa |
|
|
|
4210fa |
CHAR16 *dps = DevicePathToStr(dp);
|
|
|
4210fa |
Print(L"device path: \"%s\"\n", dps);
|
|
|
4210fa |
-#endif
|
|
|
4210fa |
- if (!first_new_option) {
|
|
|
4210fa |
- CHAR16 *dps = DevicePathToStr(dp);
|
|
|
4210fa |
- Print(L"device path: \"%s\"\n", dps);
|
|
|
4210fa |
- first_new_option = DuplicateDevicePath(dp);
|
|
|
4210fa |
- first_new_option_args = arguments;
|
|
|
4210fa |
- first_new_option_size = StrLen(arguments) * sizeof (CHAR16);
|
|
|
4210fa |
}
|
|
|
4210fa |
+#endif
|
|
|
4210fa |
|
|
|
4210fa |
- add_boot_option(dp, fullpath, label, arguments);
|
|
|
4210fa |
+ add_boot_option(dp, full_device_path, fullpath, label, arguments);
|
|
|
4210fa |
|
|
|
4210fa |
err:
|
|
|
4210fa |
- if (dpf)
|
|
|
4210fa |
- FreePool(dpf);
|
|
|
4210fa |
+ if (file)
|
|
|
4210fa |
+ FreePool(file);
|
|
|
4210fa |
+ if (full_device_path)
|
|
|
4210fa |
+ FreePool(full_device_path);
|
|
|
4210fa |
if (dp)
|
|
|
4210fa |
FreePool(dp);
|
|
|
4210fa |
if (fullpath)
|
|
|
4210fa |
@@ -629,8 +671,19 @@ try_start_first_option(EFI_HANDLE parent_image_handle)
|
|
|
4210fa |
first_new_option, NULL, 0,
|
|
|
4210fa |
&image_handle);
|
|
|
4210fa |
if (EFI_ERROR(rc)) {
|
|
|
4210fa |
- Print(L"LoadImage failed: %d\n", rc);
|
|
|
4210fa |
- uefi_call_wrapper(BS->Stall, 1, 2000000);
|
|
|
4210fa |
+ CHAR16 *dps = DevicePathToStr(first_new_option);
|
|
|
4210fa |
+ UINTN s = DevicePathSize(first_new_option);
|
|
|
4210fa |
+ int i;
|
|
|
4210fa |
+ UINT8 *dpv = (void *)first_new_option;
|
|
|
4210fa |
+ Print(L"LoadImage failed: %d\nDevice path: \"%s\"\n", rc, dps);
|
|
|
4210fa |
+ for (i = 0; i < s; i++) {
|
|
|
4210fa |
+ if (i > 0 && i % 16 == 0)
|
|
|
4210fa |
+ Print(L"\n");
|
|
|
4210fa |
+ Print(L"%02x ", dpv[i]);
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+ Print(L"\n");
|
|
|
4210fa |
+
|
|
|
4210fa |
+ uefi_call_wrapper(BS->Stall, 1, 500000000);
|
|
|
4210fa |
return rc;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
@@ -644,7 +697,7 @@ try_start_first_option(EFI_HANDLE parent_image_handle)
|
|
|
4210fa |
rc = uefi_call_wrapper(BS->StartImage, 3, image_handle, NULL, NULL);
|
|
|
4210fa |
if (EFI_ERROR(rc)) {
|
|
|
4210fa |
Print(L"StartImage failed: %d\n", rc);
|
|
|
4210fa |
- uefi_call_wrapper(BS->Stall, 1, 2000000);
|
|
|
4210fa |
+ uefi_call_wrapper(BS->Stall, 1, 500000000);
|
|
|
4210fa |
}
|
|
|
4210fa |
return rc;
|
|
|
4210fa |
}
|
|
|
4210fa |
--
|
|
|
4210fa |
1.9.3
|
|
|
4210fa |
|