From b99bf5811850afdb2502ba37251c48348da63c82 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 27 Nov 2022 13:38:18 +0100 Subject: [PATCH 1/3] boot: Use EFI_BOOT_MANAGER_POLICY_PROTOCOL to connect console devices --- src/boot/efi/console.c | 16 ++++++++++++++++ src/boot/efi/missing_efi.h | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c index 14c0008afb..cd980fd535 100644 --- a/src/boot/efi/console.c +++ b/src/boot/efi/console.c @@ -12,6 +12,20 @@ #define VERTICAL_MAX_OK 1080 #define VIEWPORT_RATIO 10 +static EFI_STATUS console_connect(void) { + EFI_BOOT_MANAGER_POLICY_PROTOCOL *boot_policy; + EFI_STATUS err; + + /* This should make console devices appear/fully initialize on fastboot firmware. */ + + err = BS->LocateProtocol( + &(EFI_GUID) EFI_BOOT_MANAGER_POLICY_PROTOCOL_GUID, NULL, (void **) &boot_policy); + if (err != EFI_SUCCESS) + return err; + + return boot_policy->ConnectDeviceClass(boot_policy, &(EFI_GUID) EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID); +} + static inline void event_closep(EFI_EVENT *event) { if (!*event) return; @@ -47,6 +61,8 @@ EFI_STATUS console_key_read(uint64_t *key, uint64_t timeout_usec) { assert(key); if (!checked) { + console_connect(); + /* Get the *first* TextInputEx device.*/ err = BS->LocateProtocol(&SimpleTextInputExProtocol, NULL, (void **) &extraInEx); if (err != EFI_SUCCESS || BS->CheckEvent(extraInEx->WaitForKeyEx) == EFI_INVALID_PARAMETER) diff --git a/src/boot/efi/missing_efi.h b/src/boot/efi/missing_efi.h index 250c84c248..b446e0399f 100644 --- a/src/boot/efi/missing_efi.h +++ b/src/boot/efi/missing_efi.h @@ -398,3 +398,22 @@ typedef struct { void *StdErr; } EFI_SHELL_PARAMETERS_PROTOCOL; #endif + +#ifndef EFI_BOOT_MANAGER_POLICY_PROTOCOL_GUID +#define EFI_BOOT_MANAGER_POLICY_PROTOCOL_GUID \ + { 0xFEDF8E0C, 0xE147, 0x11E3, { 0x99, 0x03, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA } } +#define EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID \ + { 0xCAB0E94C, 0xE15F, 0x11E3, { 0x91, 0x8D, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA } } + +typedef struct EFI_BOOT_MANAGER_POLICY_PROTOCOL EFI_BOOT_MANAGER_POLICY_PROTOCOL; +struct EFI_BOOT_MANAGER_POLICY_PROTOCOL { + UINT64 Revision; + EFI_STATUS (EFIAPI *ConnectDevicePath)( + EFI_BOOT_MANAGER_POLICY_PROTOCOL *This, + EFI_DEVICE_PATH *DevicePath, + BOOLEAN Recursive); + EFI_STATUS (EFIAPI *ConnectDeviceClass)( + EFI_BOOT_MANAGER_POLICY_PROTOCOL *This, + EFI_GUID *Class); +}; +#endif From 7f19be808c9cb9cabcaf1e48ccff875fa8191d3a Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 27 Nov 2022 13:53:30 +0100 Subject: [PATCH 2/3] boot: Make sure all partitions drivers are connected --- src/boot/efi/part-discovery.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/boot/efi/part-discovery.c b/src/boot/efi/part-discovery.c index de6d6112a1..14479c06ea 100644 --- a/src/boot/efi/part-discovery.c +++ b/src/boot/efi/part-discovery.c @@ -202,6 +202,10 @@ static EFI_STATUS find_device(const EFI_GUID *type, EFI_HANDLE *device, EFI_DEVI if (err != EFI_SUCCESS) return err; + /* The drivers for other partitions on this drive may not be initialized on fastboot firmware, so we + * have to ask the firmware to do just that. */ + (void) BS->ConnectController(disk_handle, NULL, NULL, true); + err = BS->HandleProtocol(disk_handle, &BlockIoProtocol, (void **)&block_io); if (err != EFI_SUCCESS) return err; From f6d59e2ebfc1bf50683a2e640aad501c372a50e4 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 27 Nov 2022 13:56:18 +0100 Subject: [PATCH 3/3] boot: Only do full driver initialization in VMs Doing the reconnect dance on some real firmware creates huge delays on boot. This should not be needed anymore as we now ask the firmware to make console devices and xbootldr partitions available explicitly in a more targeted fashion. Fixes: #25510 --- src/boot/efi/boot.c | 6 ------ src/boot/efi/vmm.c | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 9123c9a84c..9a562dcf22 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -2638,12 +2638,6 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { /* Uncomment the next line if you need to wait for debugger. */ // debug_break(); - /* The firmware may skip initializing some devices for the sake of a faster boot. This is especially - * true for fastboot enabled firmwares. But this means that things we use like input devices or the - * xbootldr partition may not be available yet. Reconnect all drivers should hopefully make the - * firmware initialize everything we need. */ - (void) reconnect_all_drivers(); - err = BS->OpenProtocol(image, &LoadedImageProtocol, (void **)&loaded_image, diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c index b1bfd778fc..2260b217b7 100644 --- a/src/boot/efi/vmm.c +++ b/src/boot/efi/vmm.c @@ -83,6 +83,10 @@ EFI_STATUS vmm_open(EFI_HANDLE *ret_vmm_dev, EFI_FILE **ret_vmm_dir) { assert(ret_vmm_dev); assert(ret_vmm_dir); + /* Make sure all file systems have been initialized. Only do this in VMs as this is slow + * on some real firmwares. */ + (void) reconnect_all_drivers(); + /* find all file system handles */ err = BS->LocateHandleBuffer(ByProtocol, &FileSystemProtocol, NULL, &n_handles, &handles); if (err != EFI_SUCCESS)