diff options
author | Simon Rettberg | 2021-10-05 13:58:03 +0200 |
---|---|---|
committer | Simon Rettberg | 2021-10-05 13:58:03 +0200 |
commit | 2dd1e77aef18cdc286ae5e366fdb410a9f02b230 (patch) | |
tree | 1c0cae93ed23a2cbdfc5bbc0d88a57a257bb913f | |
parent | Merge branch 'master' into openslx (diff) | |
download | ipxe-2dd1e77aef18cdc286ae5e366fdb410a9f02b230.tar.gz ipxe-2dd1e77aef18cdc286ae5e366fdb410a9f02b230.tar.xz ipxe-2dd1e77aef18cdc286ae5e366fdb410a9f02b230.zip |
[efi] local: Allow loading from any volume by using file://*/...
-rw-r--r-- | src/interface/efi/efi_local.c | 89 |
1 files changed, 82 insertions, 7 deletions
diff --git a/src/interface/efi/efi_local.c b/src/interface/efi/efi_local.c index 4ebca572..64e0addd 100644 --- a/src/interface/efi/efi_local.c +++ b/src/interface/efi/efi_local.c @@ -295,6 +295,62 @@ static int efi_local_open_root ( struct efi_local *local, EFI_HANDLE device, } /** + * 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 * * @v local Local file @@ -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 ) |