grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 1/2] efi: new 'connectefi' command


From: Renaud Métrich
Subject: Re: [PATCH v2 1/2] efi: new 'connectefi' command
Date: Tue, 15 Feb 2022 14:07:29 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.0

Please ignore, deprecated by "efi: new 'connectefi' command" (v3).

Sorry for the mess.

Le 2/14/22 à 14:23, Renaud Métrich a écrit :
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 disks or 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),
which is done through using the following grub.cfg snippet:
-------- 8< ---------------- 8< ---------------- 8< --------
unset prefix
search --file --set=prefix /EFI/redhat/grubx64.efi
if [ -n "$prefix" ]; then
   chainloader ($prefix)/EFI/redhat/grubx64/efi
...
-------- 8< ---------------- 8< ---------------- 8< --------

With efi.quickboot, none of the devices are connected, causing "search"
to fail. Sometimes devices are connected but not the partition of the
disk matching $prefix, causing partition to not be found by
"chainloader".

This patch introduces a new "connectefi" command which recursively
connects all EFI devices starting from PCI root devices.
Typical grub.cfg snippet would then be:
-------- 8< ---------------- 8< ---------------- 8< --------
unset prefix
connectefi
search --file --set=prefix /EFI/redhat/grubx64.efi
if [ -n "$prefix" ]; then
   chainloader ($prefix)/EFI/redhat/grubx64/efi
...
-------- 8< ---------------- 8< ---------------- 8< --------

In the future, if really needed, the code may be enhanced to avoid the
recursion and only connect PCI devices block devices.

Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
---
  grub-core/commands/efi/lsefi.c | 52 ++++++++++++++++++++++++++++++++++
  grub-core/disk/efi/efidisk.c   | 13 +++++++++
  grub-core/kern/efi/efi.c       | 13 +++++++++
  include/grub/efi/disk.h        |  2 ++
  include/grub/efi/efi.h         |  5 ++++
  5 files changed, 85 insertions(+)

diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c
index d1ce99af4..7acba3b39 100644
--- a/grub-core/commands/efi/lsefi.c
+++ b/grub-core/commands/efi/lsefi.c
@@ -19,6 +19,7 @@
  #include <grub/mm.h>
  #include <grub/misc.h>
  #include <grub/efi/api.h>
+#include <grub/efi/disk.h>
  #include <grub/efi/edid.h>
  #include <grub/efi/pci.h>
  #include <grub/efi/efi.h>
@@ -26,6 +27,7 @@
  #include <grub/efi/graphics_output.h>
  #include <grub/efi/console_control.h>
  #include <grub/command.h>
+#include <grub/err.h>
GRUB_MOD_LICENSE ("GPLv3+"); @@ -78,6 +80,54 @@ struct known_protocol
      { GRUB_EFI_USB_IO_PROTOCOL_GUID, "USB I/O" },
    };
+static grub_err_t
+grub_cmd_connectefi (grub_command_t cmd __attribute__ ((unused)),
+               int argc __attribute__ ((unused)),
+               char **args __attribute__ ((unused)))
+{
+  grub_efi_handle_t *handles;
+  grub_efi_uintn_t num_handles;
+  unsigned i, j;
+  grub_efi_guid_t pci_root_guid = GRUB_EFI_PCI_ROOT_IO_GUID;
+
+  handles = grub_efi_locate_handle (GRUB_EFI_ALL_HANDLES,
+                                   NULL, NULL, &num_handles);
+
+  for (i = 0; i < num_handles; i++)
+    {
+      grub_efi_handle_t handle = handles[i];
+      grub_efi_status_t status;
+      grub_efi_uintn_t num_protocols;
+      grub_efi_packed_guid_t **protocols;
+
+      status = efi_call_3 
(grub_efi_system_table->boot_services->protocols_per_handle,
+                          handle, &protocols, &num_protocols);
+      if (status != GRUB_EFI_SUCCESS)
+       {
+         grub_dprintf ("efi", "handle %p: unable to retrieve protocols\n", 
handle);
+         continue;
+       }
+      for (j = 0; j < num_protocols; j++)
+       if (! grub_memcmp (protocols[j], &pci_root_guid, sizeof 
(pci_root_guid)))
+         {
+           status = grub_efi_connect_controller(handle, NULL, NULL, 1);
+           grub_dprintf ("efi", "connected handle %p (PCI root) "
+                         "recursively: result=%" PRIxGRUB_EFI_STATUS "\n",
+                         handle, status);
+           break;
+         }
+
+      if (protocols)
+       grub_efi_free_pool (protocols);
+    }
+
+  grub_free (handles);
+
+  grub_efidisk_reenumerate_disks ();
+
+  return GRUB_ERR_NONE;
+}
+
  static grub_err_t
  grub_cmd_lsefi (grub_command_t cmd __attribute__ ((unused)),
                int argc __attribute__ ((unused)),
@@ -147,6 +197,8 @@ GRUB_MOD_INIT(lsefi)
  {
    cmd = grub_register_command ("lsefi", grub_cmd_lsefi,
                               NULL, "Display EFI handles.");
+  cmd = grub_register_command ("connectefi", grub_cmd_connectefi,
+                              NULL, "Connect EFI handles.");
  }
GRUB_MOD_FINI(lsefi)
diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
index f077b5f55..eb0de5625 100644
--- a/grub-core/disk/efi/efidisk.c
+++ b/grub-core/disk/efi/efidisk.c
@@ -396,6 +396,19 @@ enumerate_disks (void)
    free_devices (devices);
  }
+void
+grub_efidisk_reenumerate_disks (void)
+{
+  free_devices (fd_devices);
+  free_devices (hd_devices);
+  free_devices (cd_devices);
+  fd_devices = 0;
+  hd_devices = 0;
+  cd_devices = 0;
+
+  enumerate_disks ();
+}
+
  static int
  grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
                      grub_disk_pull_t pull)
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/disk.h b/include/grub/efi/disk.h
index 254475c84..6845c2f1f 100644
--- a/include/grub/efi/disk.h
+++ b/include/grub/efi/disk.h
@@ -27,6 +27,8 @@ grub_efi_handle_t
  EXPORT_FUNC(grub_efidisk_get_device_handle) (grub_disk_t disk);
  char *EXPORT_FUNC(grub_efidisk_get_device_name) (grub_efi_handle_t *handle);
+void EXPORT_FUNC(grub_efidisk_reenumerate_disks) (void);
+
  void grub_efidisk_init (void);
  void grub_efidisk_fini (void);
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);

Attachment: OpenPGP_signature
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]