From 84d406ccf48c8808b0bb30d526b758e4b58cacc8 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 12 Apr 2017 15:03:25 +0100 Subject: [block] Allow use of a non-default EFI SAN boot filename Some older operating systems (e.g. RHEL6) use a non-default filename on the root disk and rely on setting an EFI variable to point to the bootloader. This does not work when performing a SAN boot on a machine where the EFI variable is not present. Fix by allowing a non-default filename to be specified via the "sanboot --filename" option or the "san-filename" setting. For example: sanboot --filename \efi\redhat\grub.efi \ iscsi:192.168.0.1::::iqn.2010-04.org.ipxe.demo:rhel6 or option ipxe.san-filename code 188 = string; option ipxe.san-filename "\\efi\\redhat\\grub.efi"; option root-path "iscsi:192.168.0.1::::iqn.2010-04.org.ipxe.demo:rhel6"; Originally-implemented-by: Vishvananda Ishaya Abrams Signed-off-by: Michael Brown --- src/usr/autoboot.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------ src/usr/pxemenu.c | 2 +- 2 files changed, 45 insertions(+), 7 deletions(-) (limited to 'src/usr') diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index 10ccdc1d..106e0f87 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -112,6 +112,7 @@ const struct setting skip_san_boot_setting __setting ( SETTING_SANBOOT_EXTRA, * @v root_paths Root path(s) * @v root_path_count Number of root paths * @v drive SAN drive (if applicable) + * @v san_filename SAN filename (or NULL to use default) * @v flags Boot action flags * @ret rc Return status code * @@ -122,7 +123,8 @@ const struct setting skip_san_boot_setting __setting ( SETTING_SANBOOT_EXTRA, * "skip-san-boot" options. */ int uriboot ( struct uri *filename, struct uri **root_paths, - unsigned int root_path_count, int drive, unsigned int flags ) { + unsigned int root_path_count, int drive, + const char *san_filename, unsigned int flags ) { struct image *image; int rc; @@ -177,8 +179,10 @@ int uriboot ( struct uri *filename, struct uri **root_paths, /* Attempt SAN boot if applicable */ if ( ! ( flags & URIBOOT_NO_SAN_BOOT ) ) { if ( fetch_intz_setting ( NULL, &skip_san_boot_setting) == 0 ) { - printf ( "Booting from SAN device %#02x\n", drive ); - rc = san_boot ( drive ); + printf ( "Booting%s%s from SAN device %#02x\n", + ( san_filename ? " " : "" ), + ( san_filename ? san_filename : "" ), drive ); + rc = san_boot ( drive, san_filename ); printf ( "Boot from SAN device %#02x failed: %s\n", drive, strerror ( rc ) ); } else { @@ -300,10 +304,10 @@ static struct uri * fetch_root_path ( struct settings *settings ) { root_path = expand_settings ( raw_root_path ); if ( ! root_path ) goto err_expand; - - /* Parse root path */ if ( root_path[0] ) printf ( "Root path: %s\n", root_path ); + + /* Parse root path */ uri = parse_uri ( root_path ); if ( ! uri ) goto err_parse; @@ -316,6 +320,35 @@ static struct uri * fetch_root_path ( struct settings *settings ) { return uri; } +/** + * Fetch san-filename setting + * + * @v settings Settings block + * @ret san_filename SAN filename, or NULL on failure + */ +static char * fetch_san_filename ( struct settings *settings ) { + char *raw_san_filename; + char *san_filename = NULL; + + /* Fetch san-filename setting */ + fetch_string_setting_copy ( settings, &san_filename_setting, + &raw_san_filename ); + if ( ! raw_san_filename ) + goto err_fetch; + + /* Expand san-filename setting */ + san_filename = expand_settings ( raw_san_filename ); + if ( ! san_filename ) + goto err_expand; + if ( san_filename[0] ) + printf ( "SAN filename: %s\n", san_filename ); + + err_expand: + free ( raw_san_filename ); + err_fetch: + return san_filename; +} + /** * Check whether or not we have a usable PXE menu * @@ -351,6 +384,7 @@ static int have_pxe_menu ( void ) { int netboot ( struct net_device *netdev ) { struct uri *filename; struct uri *root_path; + char *san_filename; int rc; /* Close all other network devices */ @@ -379,6 +413,9 @@ int netboot ( struct net_device *netdev ) { /* Fetch root path (if any) */ root_path = fetch_root_path ( NULL ); + /* Fetch SAN filename (if any) */ + san_filename = fetch_san_filename ( NULL ); + /* If we have both a filename and a root path, ignore an * unsupported or missing URI scheme in the root path, since * it may represent an NFS root. @@ -400,12 +437,13 @@ int netboot ( struct net_device *netdev ) { /* Boot using next server, filename and root path */ if ( ( rc = uriboot ( filename, &root_path, ( root_path ? 1 : 0 ), - san_default_drive(), + san_default_drive(), san_filename, ( root_path ? 0 : URIBOOT_NO_SAN ) ) ) != 0 ) goto err_uriboot; err_uriboot: err_no_boot: + free ( san_filename ); uri_put ( root_path ); uri_put ( filename ); err_pxe_menu_boot: diff --git a/src/usr/pxemenu.c b/src/usr/pxemenu.c index 391d698a..5e497f99 100644 --- a/src/usr/pxemenu.c +++ b/src/usr/pxemenu.c @@ -378,7 +378,7 @@ int pxe_menu_boot ( struct net_device *netdev ) { return -ENOMEM; /* Attempt boot */ - rc = uriboot ( uri, NULL, 0, 0, URIBOOT_NO_SAN ); + rc = uriboot ( uri, NULL, 0, 0, NULL, URIBOOT_NO_SAN ); uri_put ( uri ); return rc; } -- cgit v1.2.3-55-g7522