summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_local.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interface/efi/efi_local.c')
-rw-r--r--src/interface/efi/efi_local.c89
1 files changed, 82 insertions, 7 deletions
diff --git a/src/interface/efi/efi_local.c b/src/interface/efi/efi_local.c
index f54f5dae..d3ac3d54 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 )