When efi.quickboot is enabled on VMWare (which is the default for
hardware release 16 and later), it may happen that not all EFI devices
are connected. Due to this, browsing the devices in make_devices() just
fails to find devices, in particular partitions for a given disk.
This typically happens when network booting, then trying to
chainload to
local disk (this is used in deployment tools such as Red Hat
Satellite).
This patch makes sure all controllers are connected before enumerating
the disks. It blindly calls the EFI ConnectController function with
recursive option and just ignores the result, which is 0 (EFI_SUCCESS)
or 14 (EFI_NOT_FOUND) when the handle is not a controller.
Signed-off-by: Renaud Métrich <rmetr...@redhat.com>
---
grub-core/disk/efi/efidisk.c | 10 ++++++++++
grub-core/kern/efi/efi.c | 13 +++++++++++++
include/grub/efi/efi.h | 5 +++++
3 files changed, 28 insertions(+)
diff --git a/grub-core/disk/efi/efidisk.c
b/grub-core/disk/efi/efidisk.c
index f077b5f55..0b16c3868 100644
--- a/grub-core/disk/efi/efidisk.c
+++ b/grub-core/disk/efi/efidisk.c
@@ -387,6 +387,16 @@ static void
enumerate_disks (void)
{
struct grub_efidisk_data *devices;
+ unsigned i;
+ grub_efi_handle_t *handles;
+ grub_efi_uintn_t num_handles;
+
+ /* Prior to enumerating, make sure all EFI devices are connected */
+
+ handles = grub_efi_locate_handle (GRUB_EFI_ALL_HANDLES,
+ NULL, NULL, &num_handles);
+ for (i = 0; i < num_handles; i++)
+ (void) grub_efi_connect_controller(handles[i], NULL, NULL, 1);
devices = make_devices ();
if (! devices)
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 18858c327..bdfff3dd0 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -95,6 +95,19 @@ grub_efi_locate_handle
(grub_efi_locate_search_type_t search_type,
return buffer;
}
+grub_efi_status_t
+grub_efi_connect_controller (grub_efi_handle_t controller_handle,
+ grub_efi_handle_t *driver_image_handle,
+ grub_efi_device_path_protocol_t
*remaining_device_path,
+ grub_efi_boolean_t recursive)
+{
+ grub_efi_boot_services_t *b;
+
+ b = grub_efi_system_table->boot_services;
+ return efi_call_4 (b->connect_controller, controller_handle,
+ driver_image_handle, remaining_device_path, recursive);
+}
+
void *
grub_efi_open_protocol (grub_efi_handle_t handle,
grub_efi_guid_t *protocol,
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index fc723962d..62dbd9788 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -32,6 +32,11 @@ EXPORT_FUNC(grub_efi_locate_handle)
(grub_efi_locate_search_type_t search_type,
grub_efi_guid_t *protocol,
void *search_key,
grub_efi_uintn_t *num_handles);
+grub_efi_status_t
+EXPORT_FUNC(grub_efi_connect_controller) (grub_efi_handle_t
controller_handle,
+ grub_efi_handle_t *driver_image_handle,
+ grub_efi_device_path_protocol_t
*remaining_device_path,
+ grub_efi_boolean_t recursive);
void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle,
grub_efi_guid_t *protocol,
grub_efi_uint32_t attributes);