From 2dd1e77aef18cdc286ae5e366fdb410a9f02b230 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 5 Oct 2021 13:58:03 +0200 Subject: [efi] local: Allow loading from any volume by using file://*/... --- src/interface/efi/efi_local.c | 89 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 7 deletions(-) (limited to 'src/interface') diff --git a/src/interface/efi/efi_local.c b/src/interface/efi/efi_local.c index 4ebca5726..64e0addd0 100644 --- a/src/interface/efi/efi_local.c +++ b/src/interface/efi/efi_local.c @@ -294,6 +294,62 @@ static int efi_local_open_root ( struct efi_local *local, EFI_HANDLE device, return rc; } +/** + * Open root filesystem of specified volume by index + * + * @v local Local file + * @v index Volume index + * @ret rc Return status code + */ +static int efi_local_open_volume_index ( struct efi_local *local, + UINTN index ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + EFI_GUID *protocol = &efi_simple_file_system_protocol_guid; + EFI_FILE_PROTOCOL *root; + EFI_HANDLE *handles; + EFI_HANDLE device; + UINTN num_handles; + EFI_STATUS efirc; + int rc; + + /* Locate all filesystem handles */ + if ( ( efirc = bs->LocateHandleBuffer ( ByProtocol, protocol, + NULL, &num_handles, + &handles ) ) != 0 ) { + rc = -EEFI ( efirc ); + DBGC ( local, "LOCAL %p could not enumerate handles: " + "%s\n", local, strerror ( rc ) ); + return rc; + } + + /* Find matching handle */ + if ( index >= num_handles ) { + rc = -ENOENT; + } else { + /* Get this device handle */ + device = handles[index]; + + /* Open root directory */ + if ( ( rc = efi_local_open_root ( local, device, &root ) ) == 0 && root ) { + local->root = root; + rc = 0; + } else { + rc = -EACCES; + } + } + + /* Free handles, if applicable */ + bs->FreePool ( handles ); + + /* Fail if we found no matching handle */ + if ( ! local->root ) { + DBGC ( local, "LOCAL %p found no matching device with index %u\n", + local, (unsigned int)index ); + } + + return rc; +} + /** * Open root filesystem of specified volume * @@ -534,7 +590,7 @@ static int efi_local_open ( struct interface *xfer, struct uri *uri ) { struct efi_local *local; const char *volume; const char *path; - int rc; + int rc, vol; /* Parse URI */ volume = ( ( uri->host && uri->host[0] ) ? uri->host : NULL ); @@ -551,13 +607,32 @@ static int efi_local_open ( struct interface *xfer, struct uri *uri ) { process_init_stopped ( &local->process, &efi_local_process_desc, &local->refcnt ); - /* Open specified volume */ - if ( ( rc = efi_local_open_volume ( local, volume ) ) != 0 ) - goto err_open_root; + if ( volume && strcmp ( volume, "*" ) == 0 ) { + /* Open on any volume */ + vol = 0; + while ( ( rc = efi_local_open_volume_index ( local, vol++ ) ) != -ENOENT ) { + if ( rc != 0 ) + continue; + /* Open specified path */ + if ( ( rc = efi_local_open_path ( local, path ) ) != 0 ) { + local->root->Close ( local->root ); + local->root = NULL; + continue; + } + /* Success */ + break; + } + if ( rc != 0 ) + goto err_open_root; + } else { + /* Open specified volume */ + if ( ( rc = efi_local_open_volume ( local, volume ) ) != 0 ) + goto err_open_root; - /* Open specified path */ - if ( ( rc = efi_local_open_path ( local, path ) ) != 0 ) - goto err_open_file; + /* Open specified path */ + if ( ( rc = efi_local_open_path ( local, path ) ) != 0 ) + goto err_open_file; + } /* Get length of file */ if ( ( rc = efi_local_len ( local ) ) != 0 ) -- cgit v1.2.3-55-g7522