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
  * Attempt to boot from an INT 13 drive
1507
  * Attempt to boot from an INT 13 drive
1508
  *
1508
  *
1509
  * @v drive		Drive number
1509
  * @v drive		Drive number
1510
+ * @v filename		Filename (or NULL to use default)
1510
  * @ret rc		Return status code
1511
  * @ret rc		Return status code
1511
  *
1512
  *
1512
  * This boots from the specified INT 13 drive by loading the Master
1513
  * This boots from the specified INT 13 drive by loading the Master
1516
  *
1517
  *
1517
  * Note that this function can never return success, by definition.
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
 	struct memory_map memmap;
1521
 	struct memory_map memmap;
1521
 	struct segoff address;
1522
 	struct segoff address;
1522
 	int rc;
1523
 	int rc;

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

95
  * Boot from dummy SAN device
95
  * Boot from dummy SAN device
96
  *
96
  *
97
  * @v drive		Drive number
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
 	return -EOPNOTSUPP;
104
 	return -EOPNOTSUPP;
102
 }
105
 }

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

37
 	/* Do nothing */
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
 	return -EOPNOTSUPP;
42
 	return -EOPNOTSUPP;
42
 }
43
 }
43
 
44
 

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

2396
 	.type = &setting_type_string,
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
 /** Username setting */
2408
 /** Username setting */
2400
 const struct setting username_setting __setting ( SETTING_AUTH, username ) = {
2409
 const struct setting username_setting __setting ( SETTING_AUTH, username ) = {
2401
 	.name = "username",
2410
 	.name = "username",

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

47
 	int no_describe;
47
 	int no_describe;
48
 	/** Keep SAN device */
48
 	/** Keep SAN device */
49
 	int keep;
49
 	int keep;
50
+	/** Filename */
51
+	char *filename;
50
 };
52
 };
51
 
53
 
52
 /** "sanboot" option list */
54
 /** "sanboot" option list */
53
 static union {
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
 	/* "sanhook" takes only --drive and --no-describe */
58
 	/* "sanhook" takes only --drive and --no-describe */
57
 	struct option_descriptor sanhook[2];
59
 	struct option_descriptor sanhook[2];
58
 	/* "sanunhook" takes only --drive */
60
 	/* "sanunhook" takes only --drive */
65
 			      struct sanboot_options, no_describe, parse_flag ),
67
 			      struct sanboot_options, no_describe, parse_flag ),
66
 		OPTION_DESC ( "keep", 'k', no_argument,
68
 		OPTION_DESC ( "keep", 'k', no_argument,
67
 			      struct sanboot_options, keep, parse_flag ),
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
 		flags |= no_root_path_flags;
134
 		flags |= no_root_path_flags;
131
 
135
 
132
 	/* Boot from root path */
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
 		goto err_uriboot;
139
 		goto err_uriboot;
135
 
140
 
136
  err_uriboot:
141
  err_uriboot:

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

440
  */
440
  */
441
 #define DHCP_EB_SAN_RETRY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbb )
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
 /** SAN drive number
449
 /** SAN drive number
444
  *
450
  *
445
  * This is the drive number for a SAN-hooked drive.  For BIOS, 0x80 is
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
  * Attempt to boot from a SAN device
155
  * Attempt to boot from a SAN device
156
  *
156
  *
157
  * @v drive		Drive number
157
  * @v drive		Drive number
158
+ * @v filename		Filename (or NULL to use default)
158
  * @ret rc		Return status code
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
  * Describe SAN devices for SAN-booted operating system
164
  * Describe SAN devices for SAN-booted operating system

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

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

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

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

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

518
  *
518
  *
519
  * @v sandev		SAN device
519
  * @v sandev		SAN device
520
  * @v handle		EFI handle
520
  * @v handle		EFI handle
521
+ * @v filename		Filename (or NULL to use default)
522
+ * @v image		Image handle to fill in
521
  * @ret rc		Return status code
523
  * @ret rc		Return status code
522
  */
524
  */
523
 static int efi_block_boot_image ( struct san_device *sandev, EFI_HANDLE handle,
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
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
527
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
526
 	struct efi_block_data *block = sandev->priv;
528
 	struct efi_block_data *block = sandev->priv;
527
 	union {
529
 	union {
563
 	end = efi_devpath_end ( path.path );
565
 	end = efi_devpath_end ( path.path );
564
 	prefix_len = ( ( ( void * ) end ) - ( ( void * ) path.path ) );
566
 	prefix_len = ( ( ( void * ) end ) - ( ( void * ) path.path ) );
565
 	filepath_len = ( SIZE_OF_FILEPATH_DEVICE_PATH +
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
 	boot_path_len = ( prefix_len + filepath_len + sizeof ( *end ) );
572
 	boot_path_len = ( prefix_len + filepath_len + sizeof ( *end ) );
568
 	boot_path = zalloc ( boot_path_len );
573
 	boot_path = zalloc ( boot_path_len );
569
 	if ( ! boot_path ) {
574
 	if ( ! boot_path ) {
576
 	filepath->Header.SubType = MEDIA_FILEPATH_DP;
581
 	filepath->Header.SubType = MEDIA_FILEPATH_DP;
577
 	filepath->Header.Length[0] = ( filepath_len & 0xff );
582
 	filepath->Header.Length[0] = ( filepath_len & 0xff );
578
 	filepath->Header.Length[1] = ( filepath_len >> 8 );
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
 	end = ( ( ( void * ) filepath ) + filepath_len );
590
 	end = ( ( ( void * ) filepath ) + filepath_len );
582
 	end->Type = END_DEVICE_PATH_TYPE;
591
 	end->Type = END_DEVICE_PATH_TYPE;
583
 	end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
592
 	end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
609
  * Boot from EFI block device
618
  * Boot from EFI block device
610
  *
619
  *
611
  * @v drive		Drive number
620
  * @v drive		Drive number
621
+ * @v filename		Filename (or NULL to use default)
612
  * @ret rc		Return status code
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
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
625
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
616
 	struct san_device *sandev;
626
 	struct san_device *sandev;
617
 	EFI_HANDLE *handles;
627
 	EFI_HANDLE *handles;
649
 	 */
659
 	 */
650
 	rc = -ENOENT;
660
 	rc = -ENOENT;
651
 	for ( i = 0 ; i < count ; i++ ) {
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
 						   &image ) ) != 0 )
663
 						   &image ) ) != 0 )
654
 			continue;
664
 			continue;
655
 		DBGC ( sandev, "EFIBLK %#02x found boot image\n",
665
 		DBGC ( sandev, "EFIBLK %#02x found boot image\n",

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

112
  * @v root_paths	Root path(s)
112
  * @v root_paths	Root path(s)
113
  * @v root_path_count	Number of root paths
113
  * @v root_path_count	Number of root paths
114
  * @v drive		SAN drive (if applicable)
114
  * @v drive		SAN drive (if applicable)
115
+ * @v san_filename	SAN filename (or NULL to use default)
115
  * @v flags		Boot action flags
116
  * @v flags		Boot action flags
116
  * @ret rc		Return status code
117
  * @ret rc		Return status code
117
  *
118
  *
122
  * "skip-san-boot" options.
123
  * "skip-san-boot" options.
123
  */
124
  */
124
 int uriboot ( struct uri *filename, struct uri **root_paths,
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
 	struct image *image;
128
 	struct image *image;
127
 	int rc;
129
 	int rc;
128
 
130
 
177
 	/* Attempt SAN boot if applicable */
179
 	/* Attempt SAN boot if applicable */
178
 	if ( ! ( flags & URIBOOT_NO_SAN_BOOT ) ) {
180
 	if ( ! ( flags & URIBOOT_NO_SAN_BOOT ) ) {
179
 		if ( fetch_intz_setting ( NULL, &skip_san_boot_setting) == 0 ) {
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
 			printf ( "Boot from SAN device %#02x failed: %s\n",
186
 			printf ( "Boot from SAN device %#02x failed: %s\n",
183
 				 drive, strerror ( rc ) );
187
 				 drive, strerror ( rc ) );
184
 		} else {
188
 		} else {
300
 	root_path = expand_settings ( raw_root_path );
304
 	root_path = expand_settings ( raw_root_path );
301
 	if ( ! root_path )
305
 	if ( ! root_path )
302
 		goto err_expand;
306
 		goto err_expand;
303
-
304
-	/* Parse root path */
305
 	if ( root_path[0] )
307
 	if ( root_path[0] )
306
 		printf ( "Root path: %s\n", root_path );
308
 		printf ( "Root path: %s\n", root_path );
309
+
310
+	/* Parse root path */
307
 	uri = parse_uri ( root_path );
311
 	uri = parse_uri ( root_path );
308
 	if ( ! uri )
312
 	if ( ! uri )
309
 		goto err_parse;
313
 		goto err_parse;
316
 	return uri;
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
  * Check whether or not we have a usable PXE menu
353
  * Check whether or not we have a usable PXE menu
321
  *
354
  *
351
 int netboot ( struct net_device *netdev ) {
384
 int netboot ( struct net_device *netdev ) {
352
 	struct uri *filename;
385
 	struct uri *filename;
353
 	struct uri *root_path;
386
 	struct uri *root_path;
387
+	char *san_filename;
354
 	int rc;
388
 	int rc;
355
 
389
 
356
 	/* Close all other network devices */
390
 	/* Close all other network devices */
379
 	/* Fetch root path (if any) */
413
 	/* Fetch root path (if any) */
380
 	root_path = fetch_root_path ( NULL );
414
 	root_path = fetch_root_path ( NULL );
381
 
415
 
416
+	/* Fetch SAN filename (if any) */
417
+	san_filename = fetch_san_filename ( NULL );
418
+
382
 	/* If we have both a filename and a root path, ignore an
419
 	/* If we have both a filename and a root path, ignore an
383
 	 * unsupported or missing URI scheme in the root path, since
420
 	 * unsupported or missing URI scheme in the root path, since
384
 	 * it may represent an NFS root.
421
 	 * it may represent an NFS root.
400
 
437
 
401
 	/* Boot using next server, filename and root path */
438
 	/* Boot using next server, filename and root path */
402
 	if ( ( rc = uriboot ( filename, &root_path, ( root_path ? 1 : 0 ),
439
 	if ( ( rc = uriboot ( filename, &root_path, ( root_path ? 1 : 0 ),
403
-			      san_default_drive(),
440
+			      san_default_drive(), san_filename,
404
 			      ( root_path ? 0 : URIBOOT_NO_SAN ) ) ) != 0 )
441
 			      ( root_path ? 0 : URIBOOT_NO_SAN ) ) ) != 0 )
405
 		goto err_uriboot;
442
 		goto err_uriboot;
406
 
443
 
407
  err_uriboot:
444
  err_uriboot:
408
  err_no_boot:
445
  err_no_boot:
446
+	free ( san_filename );
409
 	uri_put ( root_path );
447
 	uri_put ( root_path );
410
 	uri_put ( filename );
448
 	uri_put ( filename );
411
  err_pxe_menu_boot:
449
  err_pxe_menu_boot:

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

378
 		return -ENOMEM;
378
 		return -ENOMEM;
379
 
379
 
380
 	/* Attempt boot */
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
 	uri_put ( uri );
382
 	uri_put ( uri );
383
 	return rc;
383
 	return rc;
384
 }
384
 }

Loading…
Cancel
Save