summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2024-03-07 14:31:29 +0100
committerMichael Brown2024-03-07 14:31:29 +0100
commit62b6d363351fb5d8890cdcd36c949d6d8563b4e9 (patch)
tree52289625111e210c73a132470f3d31fe25eae125
parent[block] Allow SAN boot device to be identified by UUID (diff)
downloadipxe-62b6d363351fb5d8890cdcd36c949d6d8563b4e9.tar.gz
ipxe-62b6d363351fb5d8890cdcd36c949d6d8563b4e9.tar.xz
ipxe-62b6d363351fb5d8890cdcd36c949d6d8563b4e9.zip
[block] Allow SAN boot device to be identified by an extra filename
Add an "--extra" option that can be used to specify an extra (non-boot) filename that must exist within the booted filesystem. Note that only files within the FAT-formatted bootable partition will be visible to this filter. Files within the operating system's root disk (e.g. "/etc/redhat-release") are not generally accessible to the firmware and so cannot be used as the existence check filter filename. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/hci/commands/sanboot_cmd.c9
-rw-r--r--src/include/ipxe/sanboot.h2
-rw-r--r--src/interface/efi/efi_block.c85
3 files changed, 68 insertions, 28 deletions
diff --git a/src/hci/commands/sanboot_cmd.c b/src/hci/commands/sanboot_cmd.c
index b3d9ccad..add0756d 100644
--- a/src/hci/commands/sanboot_cmd.c
+++ b/src/hci/commands/sanboot_cmd.c
@@ -47,8 +47,10 @@ struct sanboot_options {
int no_describe;
/** Keep SAN device */
int keep;
- /** Filename */
+ /** Boot filename */
char *filename;
+ /** Required extra filename */
+ char *extra;
/** UUID */
struct uuid_option uuid;
};
@@ -56,7 +58,7 @@ struct sanboot_options {
/** "sanboot" option list */
static union {
/* "sanboot" takes all options */
- struct option_descriptor sanboot[5];
+ struct option_descriptor sanboot[6];
/* "sanhook" takes only --drive and --no-describe */
struct option_descriptor sanhook[2];
/* "sanunhook" takes only --drive */
@@ -71,6 +73,8 @@ static union {
struct sanboot_options, keep, parse_flag ),
OPTION_DESC ( "filename", 'f', required_argument,
struct sanboot_options, filename, parse_string ),
+ OPTION_DESC ( "extra", 'e', required_argument,
+ struct sanboot_options, extra, parse_string ),
OPTION_DESC ( "uuid", 'u', required_argument,
struct sanboot_options, uuid, parse_uuid ),
},
@@ -130,6 +134,7 @@ static int sanboot_core_exec ( int argc, char **argv,
/* Construct configuration parameters */
config.filename = opts.filename;
+ config.extra = opts.extra;
config.uuid = opts.uuid.value;
/* Construct flags */
diff --git a/src/include/ipxe/sanboot.h b/src/include/ipxe/sanboot.h
index 9841edda..91c848b0 100644
--- a/src/include/ipxe/sanboot.h
+++ b/src/include/ipxe/sanboot.h
@@ -110,6 +110,8 @@ enum san_device_flags {
struct san_boot_config {
/** Boot filename (or NULL to use default) */
const char *filename;
+ /** Required extra filename (or NULL to ignore) */
+ const char *extra;
/** UUID (or NULL to ignore UUID) */
union uuid *uuid;
};
diff --git a/src/interface/efi/efi_block.c b/src/interface/efi/efi_block.c
index f5b913f1..269b9abd 100644
--- a/src/interface/efi/efi_block.c
+++ b/src/interface/efi/efi_block.c
@@ -506,55 +506,77 @@ static int efi_block_describe ( void ) {
}
/**
- * Check for existence of a file within a filesystem
+ * Open root directory within a filesystem
*
* @v drive Drive number
* @v handle Filesystem handle
- * @v filename Filename (or NULL to use default)
+ * @v root Root directory file to fill in
* @ret rc Return status code
*/
-static int efi_block_filename ( unsigned int drive, EFI_HANDLE handle,
- const char *filename ) {
+static int efi_block_root ( unsigned int drive, EFI_HANDLE handle,
+ EFI_FILE_PROTOCOL **root ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_GUID *protocol = &efi_simple_file_system_protocol_guid;
- CHAR16 tmp[ filename ? ( strlen ( filename ) + 1 /* wNUL */ ) : 0 ];
union {
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs;
void *interface;
} u;
- CHAR16 *wname;
- EFI_FILE_PROTOCOL *root;
- EFI_FILE_PROTOCOL *file;
EFI_STATUS efirc;
int rc;
- /* Construct filename */
- if ( filename ) {
- efi_snprintf ( tmp, sizeof ( tmp ), "%s", filename );
- wname = tmp;
- } else {
- wname = efi_block_boot_filename;
- }
-
- /* Open file system protocol */
+ /* Open filesystem protocol */
if ( ( efirc = bs->OpenProtocol ( handle, protocol, &u.interface,
efi_image_handle, handle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
rc = -EEFI ( efirc );
- DBGC ( drive, "EFIBLK %#02x could not open %s device path: "
- "%s\n", drive, efi_handle_name ( handle ),
- strerror ( rc ) );
+ DBGC ( drive, "EFIBLK %#02x could not open %s filesystem: %s\n",
+ drive, efi_handle_name ( handle ), strerror ( rc ) );
goto err_open;
}
/* Open root volume */
- if ( ( efirc = u.fs->OpenVolume ( u.fs, &root ) ) != 0 ) {
+ if ( ( efirc = u.fs->OpenVolume ( u.fs, root ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( drive, "EFIBLK %#02x could not open %s root: %s\n",
drive, efi_handle_name ( handle ), strerror ( rc ) );
goto err_volume;
}
+ /* Success */
+ rc = 0;
+
+ err_volume:
+ bs->CloseProtocol ( handle, protocol, efi_image_handle, handle );
+ err_open:
+ return rc;
+}
+
+/**
+ * Check for existence of a file within a filesystem
+ *
+ * @v drive Drive number
+ * @v handle Filesystem handle
+ * @v root Root directory
+ * @v filename Filename (or NULL to use default)
+ * @ret rc Return status code
+ */
+static int efi_block_filename ( unsigned int drive, EFI_HANDLE handle,
+ EFI_FILE_PROTOCOL *root,
+ const char *filename ) {
+ CHAR16 tmp[ filename ? ( strlen ( filename ) + 1 /* wNUL */ ) : 0 ];
+ CHAR16 *wname;
+ EFI_FILE_PROTOCOL *file;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Construct filename */
+ if ( filename ) {
+ efi_snprintf ( tmp, sizeof ( tmp ), "%s", filename );
+ wname = tmp;
+ } else {
+ wname = efi_block_boot_filename;
+ }
+
/* Try opening file */
if ( ( efirc = root->Open ( root, &file, wname,
EFI_FILE_MODE_READ, 0 ) ) != 0 ) {
@@ -570,10 +592,6 @@ static int efi_block_filename ( unsigned int drive, EFI_HANDLE handle,
file->Close ( file );
err_file:
- root->Close ( root );
- err_volume:
- bs->CloseProtocol ( handle, protocol, efi_image_handle, handle );
- err_open:
return rc;
}
@@ -597,6 +615,7 @@ static int efi_block_match ( unsigned int drive, EFI_HANDLE handle,
EFI_DEVICE_PATH_PROTOCOL *path;
void *interface;
} u;
+ EFI_FILE *root;
union uuid guid;
EFI_STATUS efirc;
int rc;
@@ -639,16 +658,30 @@ static int efi_block_match ( unsigned int drive, EFI_HANDLE handle,
}
}
+ /* Open root directory */
+ if ( ( rc = efi_block_root ( drive, handle, &root ) ) != 0 )
+ goto err_root;
+
/* Check if filesystem contains boot filename */
- if ( ( rc = efi_block_filename ( drive, handle,
+ if ( ( rc = efi_block_filename ( drive, handle, root,
config->filename ) ) != 0 ) {
goto err_filename;
}
+ /* Check if filesystem contains additional filename, if applicable */
+ if ( config->extra &&
+ ( ( rc = efi_block_filename ( drive, handle, root,
+ config->extra ) ) != 0 ) ) {
+ goto err_extra;
+ }
+
/* Success */
rc = 0;
+ err_extra:
err_filename:
+ root->Close ( root );
+ err_root:
err_wrong_guid:
err_no_guid:
err_not_child: