Browse Source

[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 <vish.ishaya@oracle.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
84d406ccf4

+ 2
- 1
src/arch/x86/interface/pcbios/int13.c View File

@@ -1507,6 +1507,7 @@ static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
1507 1507
  * Attempt to boot from an INT 13 drive
1508 1508
  *
1509 1509
  * @v drive		Drive number
1510
+ * @v filename		Filename (or NULL to use default)
1510 1511
  * @ret rc		Return status code
1511 1512
  *
1512 1513
  * This boots from the specified INT 13 drive by loading the Master
@@ -1516,7 +1517,7 @@ static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
1516 1517
  *
1517 1518
  * Note that this function can never return success, by definition.
1518 1519
  */
1519
-static int int13_boot ( unsigned int drive ) {
1520
+static int int13_boot ( unsigned int drive, const char *filename __unused ) {
1520 1521
 	struct memory_map memmap;
1521 1522
 	struct segoff address;
1522 1523
 	int rc;

+ 4
- 1
src/core/dummy_sanboot.c View File

@@ -95,8 +95,11 @@ static void dummy_san_unhook ( unsigned int drive ) {
95 95
  * Boot from dummy SAN device
96 96
  *
97 97
  * @v drive		Drive number
98
+ * @v filename		Filename (or NULL to use default)
99
+ * @ret rc		Return status code
98 100
  */
99
-static int dummy_san_boot ( unsigned int drive __unused ) {
101
+static int dummy_san_boot ( unsigned int drive __unused,
102
+			    const char *filename __unused ) {
100 103
 
101 104
 	return -EOPNOTSUPP;
102 105
 }

+ 2
- 1
src/core/null_sanboot.c View File

@@ -37,7 +37,8 @@ static void null_san_unhook ( unsigned int drive __unused ) {
37 37
 	/* Do nothing */
38 38
 }
39 39
 
40
-static int null_san_boot ( unsigned int drive __unused ) {
40
+static int null_san_boot ( unsigned int drive __unused,
41
+			   const char *filename __unused ) {
41 42
 	return -EOPNOTSUPP;
42 43
 }
43 44
 

+ 9
- 0
src/core/settings.c View File

@@ -2396,6 +2396,15 @@ const struct setting root_path_setting __setting ( SETTING_SANBOOT, root-path)={
2396 2396
 	.type = &setting_type_string,
2397 2397
 };
2398 2398
 
2399
+/** SAN filename setting */
2400
+const struct setting san_filename_setting __setting ( SETTING_SANBOOT,
2401
+						      san-filename ) = {
2402
+	.name = "san-filename",
2403
+	.description = "SAN filename",
2404
+	.tag = DHCP_EB_SAN_FILENAME,
2405
+	.type = &setting_type_string,
2406
+};
2407
+
2399 2408
 /** Username setting */
2400 2409
 const struct setting username_setting __setting ( SETTING_AUTH, username ) = {
2401 2410
 	.name = "username",

+ 8
- 3
src/hci/commands/sanboot_cmd.c View File

@@ -47,12 +47,14 @@ struct sanboot_options {
47 47
 	int no_describe;
48 48
 	/** Keep SAN device */
49 49
 	int keep;
50
+	/** Filename */
51
+	char *filename;
50 52
 };
51 53
 
52 54
 /** "sanboot" option list */
53 55
 static union {
54
-	/* "sanboot" takes all three options */
55
-	struct option_descriptor sanboot[3];
56
+	/* "sanboot" takes all four options */
57
+	struct option_descriptor sanboot[4];
56 58
 	/* "sanhook" takes only --drive and --no-describe */
57 59
 	struct option_descriptor sanhook[2];
58 60
 	/* "sanunhook" takes only --drive */
@@ -65,6 +67,8 @@ static union {
65 67
 			      struct sanboot_options, no_describe, parse_flag ),
66 68
 		OPTION_DESC ( "keep", 'k', no_argument,
67 69
 			      struct sanboot_options, keep, parse_flag ),
70
+		OPTION_DESC ( "filename", 'f', required_argument,
71
+			      struct sanboot_options, filename, parse_string ),
68 72
 	},
69 73
 };
70 74
 
@@ -130,7 +134,8 @@ static int sanboot_core_exec ( int argc, char **argv,
130 134
 		flags |= no_root_path_flags;
131 135
 
132 136
 	/* Boot from root path */
133
-	if ( ( rc = uriboot ( NULL, uris, count, opts.drive, flags ) ) != 0 )
137
+	if ( ( rc = uriboot ( NULL, uris, count, opts.drive, opts.filename,
138
+			      flags ) ) != 0 )
134 139
 		goto err_uriboot;
135 140
 
136 141
  err_uriboot:

+ 6
- 0
src/include/ipxe/dhcp.h View File

@@ -440,6 +440,12 @@ struct dhcp_netdev_desc {
440 440
  */
441 441
 #define DHCP_EB_SAN_RETRY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbb )
442 442
 
443
+/** SAN filename
444
+ *
445
+ * This is the path of the bootloader within the SAN device.
446
+ */
447
+#define DHCP_EB_SAN_FILENAME DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbc )
448
+
443 449
 /** SAN drive number
444 450
  *
445 451
  * This is the drive number for a SAN-hooked drive.  For BIOS, 0x80 is

+ 2
- 1
src/include/ipxe/sanboot.h View File

@@ -155,9 +155,10 @@ void san_unhook ( unsigned int drive );
155 155
  * Attempt to boot from a SAN device
156 156
  *
157 157
  * @v drive		Drive number
158
+ * @v filename		Filename (or NULL to use default)
158 159
  * @ret rc		Return status code
159 160
  */
160
-int san_boot ( unsigned int drive );
161
+int san_boot ( unsigned int drive, const char *filename );
161 162
 
162 163
 /**
163 164
  * Describe SAN devices for SAN-booted operating system

+ 2
- 0
src/include/ipxe/settings.h View File

@@ -452,6 +452,8 @@ filename_setting __setting ( SETTING_BOOT, filename );
452 452
 extern const struct setting
453 453
 root_path_setting __setting ( SETTING_SANBOOT, root-path );
454 454
 extern const struct setting
455
+san_filename_setting __setting ( SETTING_SANBOOT, san-filename );
456
+extern const struct setting
455 457
 username_setting __setting ( SETTING_AUTH, username );
456 458
 extern const struct setting
457 459
 password_setting __setting ( SETTING_AUTH, password );

+ 1
- 1
src/include/usr/autoboot.h View File

@@ -32,7 +32,7 @@ extern void set_autoboot_ll_addr ( const void *ll_addr, size_t len );
32 32
 
33 33
 extern int uriboot ( struct uri *filename, struct uri **root_paths,
34 34
 		     unsigned int root_path_count, int drive,
35
-		     unsigned int flags );
35
+		     const char *san_filename, unsigned int flags );
36 36
 extern struct uri *
37 37
 fetch_next_server_and_filename ( struct settings *settings );
38 38
 extern int netboot ( struct net_device *netdev );

+ 16
- 6
src/interface/efi/efi_block.c View File

@@ -518,10 +518,12 @@ static int efi_block_describe ( void ) {
518 518
  *
519 519
  * @v sandev		SAN device
520 520
  * @v handle		EFI handle
521
+ * @v filename		Filename (or NULL to use default)
522
+ * @v image		Image handle to fill in
521 523
  * @ret rc		Return status code
522 524
  */
523 525
 static int efi_block_boot_image ( struct san_device *sandev, EFI_HANDLE handle,
524
-				  EFI_HANDLE *image ) {
526
+				  const char *filename, EFI_HANDLE *image ) {
525 527
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
526 528
 	struct efi_block_data *block = sandev->priv;
527 529
 	union {
@@ -563,7 +565,10 @@ static int efi_block_boot_image ( struct san_device *sandev, EFI_HANDLE handle,
563 565
 	end = efi_devpath_end ( path.path );
564 566
 	prefix_len = ( ( ( void * ) end ) - ( ( void * ) path.path ) );
565 567
 	filepath_len = ( SIZE_OF_FILEPATH_DEVICE_PATH +
566
-			 sizeof ( efi_block_boot_filename ) );
568
+			 ( filename ?
569
+			   ( ( strlen ( filename ) + 1 /* NUL */ ) *
570
+			     sizeof ( filepath->PathName[0] ) ) :
571
+			   sizeof ( efi_block_boot_filename ) ) );
567 572
 	boot_path_len = ( prefix_len + filepath_len + sizeof ( *end ) );
568 573
 	boot_path = zalloc ( boot_path_len );
569 574
 	if ( ! boot_path ) {
@@ -576,8 +581,12 @@ static int efi_block_boot_image ( struct san_device *sandev, EFI_HANDLE handle,
576 581
 	filepath->Header.SubType = MEDIA_FILEPATH_DP;
577 582
 	filepath->Header.Length[0] = ( filepath_len & 0xff );
578 583
 	filepath->Header.Length[1] = ( filepath_len >> 8 );
579
-	memcpy ( filepath->PathName, efi_block_boot_filename,
580
-		 sizeof ( efi_block_boot_filename ) );
584
+	if ( filename ) {
585
+		efi_sprintf ( filepath->PathName, "%s", filename );
586
+	} else {
587
+		memcpy ( filepath->PathName, efi_block_boot_filename,
588
+			 sizeof ( efi_block_boot_filename ) );
589
+	}
581 590
 	end = ( ( ( void * ) filepath ) + filepath_len );
582 591
 	end->Type = END_DEVICE_PATH_TYPE;
583 592
 	end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
@@ -609,9 +618,10 @@ static int efi_block_boot_image ( struct san_device *sandev, EFI_HANDLE handle,
609 618
  * Boot from EFI block device
610 619
  *
611 620
  * @v drive		Drive number
621
+ * @v filename		Filename (or NULL to use default)
612 622
  * @ret rc		Return status code
613 623
  */
614
-static int efi_block_boot ( unsigned int drive ) {
624
+static int efi_block_boot ( unsigned int drive, const char *filename ) {
615 625
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
616 626
 	struct san_device *sandev;
617 627
 	EFI_HANDLE *handles;
@@ -649,7 +659,7 @@ static int efi_block_boot ( unsigned int drive ) {
649 659
 	 */
650 660
 	rc = -ENOENT;
651 661
 	for ( i = 0 ; i < count ; i++ ) {
652
-		if ( ( rc = efi_block_boot_image ( sandev, handles[i],
662
+		if ( ( rc = efi_block_boot_image ( sandev, handles[i], filename,
653 663
 						   &image ) ) != 0 )
654 664
 			continue;
655 665
 		DBGC ( sandev, "EFIBLK %#02x found boot image\n",

+ 44
- 6
src/usr/autoboot.c View File

@@ -112,6 +112,7 @@ const struct setting skip_san_boot_setting __setting ( SETTING_SANBOOT_EXTRA,
112 112
  * @v root_paths	Root path(s)
113 113
  * @v root_path_count	Number of root paths
114 114
  * @v drive		SAN drive (if applicable)
115
+ * @v san_filename	SAN filename (or NULL to use default)
115 116
  * @v flags		Boot action flags
116 117
  * @ret rc		Return status code
117 118
  *
@@ -122,7 +123,8 @@ const struct setting skip_san_boot_setting __setting ( SETTING_SANBOOT_EXTRA,
122 123
  * "skip-san-boot" options.
123 124
  */
124 125
 int uriboot ( struct uri *filename, struct uri **root_paths,
125
-	      unsigned int root_path_count, int drive, unsigned int flags ) {
126
+	      unsigned int root_path_count, int drive,
127
+	      const char *san_filename, unsigned int flags ) {
126 128
 	struct image *image;
127 129
 	int rc;
128 130
 
@@ -177,8 +179,10 @@ int uriboot ( struct uri *filename, struct uri **root_paths,
177 179
 	/* Attempt SAN boot if applicable */
178 180
 	if ( ! ( flags & URIBOOT_NO_SAN_BOOT ) ) {
179 181
 		if ( fetch_intz_setting ( NULL, &skip_san_boot_setting) == 0 ) {
180
-			printf ( "Booting from SAN device %#02x\n", drive );
181
-			rc = san_boot ( drive );
182
+			printf ( "Booting%s%s from SAN device %#02x\n",
183
+				 ( san_filename ? " " : "" ),
184
+				 ( san_filename ? san_filename : "" ), drive );
185
+			rc = san_boot ( drive, san_filename );
182 186
 			printf ( "Boot from SAN device %#02x failed: %s\n",
183 187
 				 drive, strerror ( rc ) );
184 188
 		} else {
@@ -300,10 +304,10 @@ static struct uri * fetch_root_path ( struct settings *settings ) {
300 304
 	root_path = expand_settings ( raw_root_path );
301 305
 	if ( ! root_path )
302 306
 		goto err_expand;
303
-
304
-	/* Parse root path */
305 307
 	if ( root_path[0] )
306 308
 		printf ( "Root path: %s\n", root_path );
309
+
310
+	/* Parse root path */
307 311
 	uri = parse_uri ( root_path );
308 312
 	if ( ! uri )
309 313
 		goto err_parse;
@@ -316,6 +320,35 @@ static struct uri * fetch_root_path ( struct settings *settings ) {
316 320
 	return uri;
317 321
 }
318 322
 
323
+/**
324
+ * Fetch san-filename setting
325
+ *
326
+ * @v settings		Settings block
327
+ * @ret san_filename	SAN filename, or NULL on failure
328
+ */
329
+static char * fetch_san_filename ( struct settings *settings ) {
330
+	char *raw_san_filename;
331
+	char *san_filename = NULL;
332
+
333
+	/* Fetch san-filename setting */
334
+	fetch_string_setting_copy ( settings, &san_filename_setting,
335
+				    &raw_san_filename );
336
+	if ( ! raw_san_filename )
337
+		goto err_fetch;
338
+
339
+	/* Expand san-filename setting */
340
+	san_filename = expand_settings ( raw_san_filename );
341
+	if ( ! san_filename )
342
+		goto err_expand;
343
+	if ( san_filename[0] )
344
+		printf ( "SAN filename: %s\n", san_filename );
345
+
346
+ err_expand:
347
+	free ( raw_san_filename );
348
+ err_fetch:
349
+	return san_filename;
350
+}
351
+
319 352
 /**
320 353
  * Check whether or not we have a usable PXE menu
321 354
  *
@@ -351,6 +384,7 @@ static int have_pxe_menu ( void ) {
351 384
 int netboot ( struct net_device *netdev ) {
352 385
 	struct uri *filename;
353 386
 	struct uri *root_path;
387
+	char *san_filename;
354 388
 	int rc;
355 389
 
356 390
 	/* Close all other network devices */
@@ -379,6 +413,9 @@ int netboot ( struct net_device *netdev ) {
379 413
 	/* Fetch root path (if any) */
380 414
 	root_path = fetch_root_path ( NULL );
381 415
 
416
+	/* Fetch SAN filename (if any) */
417
+	san_filename = fetch_san_filename ( NULL );
418
+
382 419
 	/* If we have both a filename and a root path, ignore an
383 420
 	 * unsupported or missing URI scheme in the root path, since
384 421
 	 * it may represent an NFS root.
@@ -400,12 +437,13 @@ int netboot ( struct net_device *netdev ) {
400 437
 
401 438
 	/* Boot using next server, filename and root path */
402 439
 	if ( ( rc = uriboot ( filename, &root_path, ( root_path ? 1 : 0 ),
403
-			      san_default_drive(),
440
+			      san_default_drive(), san_filename,
404 441
 			      ( root_path ? 0 : URIBOOT_NO_SAN ) ) ) != 0 )
405 442
 		goto err_uriboot;
406 443
 
407 444
  err_uriboot:
408 445
  err_no_boot:
446
+	free ( san_filename );
409 447
 	uri_put ( root_path );
410 448
 	uri_put ( filename );
411 449
  err_pxe_menu_boot:

+ 1
- 1
src/usr/pxemenu.c View File

@@ -378,7 +378,7 @@ int pxe_menu_boot ( struct net_device *netdev ) {
378 378
 		return -ENOMEM;
379 379
 
380 380
 	/* Attempt boot */
381
-	rc = uriboot ( uri, NULL, 0, 0, URIBOOT_NO_SAN );
381
+	rc = uriboot ( uri, NULL, 0, 0, NULL, URIBOOT_NO_SAN );
382 382
 	uri_put ( uri );
383 383
 	return rc;
384 384
 }

Loading…
Cancel
Save