Browse Source

[block] Describe all SAN devices via ACPI tables

Describe all SAN devices via ACPI tables such as the iBFT.  For tables
that can describe only a single device (i.e. the aBFT and sBFT), one
table is installed per device.  For multi-device tables (i.e. the
iBFT), all devices are described in a single table.

An underlying SAN device connection may be closed at the time that we
need to construct an ACPI table.  We therefore introduce the concept
of an "ACPI descriptor" which enables the SAN boot code to maintain an
opaque pointer to the underlying object, and an "ACPI model" which can
build tables from a list of such descriptors.  This separates the
lifecycles of ACPI descriptions from the lifecycles of the block
device interfaces, and allows for construction of the ACPI tables even
if the block device interface has been closed.

For a multipath SAN device, iPXE will wait until sufficient
information is available to describe all devices but will not wait for
all paths to connect successfully.  For example: with a multipath
iSCSI boot iPXE will wait until at least one path has become available
and name resolution has completed on all other paths.  We do this
since the iBFT has to include IP addresses rather than DNS names.  We
will commence booting without waiting for the inactive paths to either
become available or close; this avoids unnecessary boot delays.

Note that the Linux kernel will refuse to accept an iBFT with more
than two NIC or target structures.  We therefore describe only the
NICs that are actually required in order to reach the described
targets.  Any iBFT with at most two targets is therefore guaranteed to
describe at most two NICs.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
7cfdd769aa

+ 65
- 52
src/arch/x86/interface/pcbios/int13.c View File

@@ -1239,13 +1239,14 @@ static void int13_unhook_vector ( void ) {
1239 1239
  * @v drive		Drive number
1240 1240
  * @v uris		List of URIs
1241 1241
  * @v count		Number of URIs
1242
+ * @v flags		Flags
1242 1243
  * @ret drive		Drive number, or negative error
1243 1244
  *
1244 1245
  * Registers the drive with the INT 13 emulation subsystem, and hooks
1245 1246
  * the INT 13 interrupt vector (if not already hooked).
1246 1247
  */
1247 1248
 static int int13_hook ( unsigned int drive, struct uri **uris,
1248
-			unsigned int count ) {
1249
+			unsigned int count, unsigned int flags ) {
1249 1250
 	struct san_device *sandev;
1250 1251
 	struct int13_data *int13;
1251 1252
 	unsigned int natural_drive;
@@ -1267,14 +1268,13 @@ static int int13_hook ( unsigned int drive, struct uri **uris,
1267 1268
 		rc = -ENOMEM;
1268 1269
 		goto err_alloc;
1269 1270
 	}
1270
-	sandev->drive = drive;
1271 1271
 	int13 = sandev->priv;
1272 1272
 	int13->natural_drive = natural_drive;
1273 1273
 
1274 1274
 	/* Register SAN device */
1275
-	if ( ( rc = register_sandev ( sandev ) ) != 0 ) {
1275
+	if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
1276 1276
 		DBGC ( sandev, "INT13 drive %02x could not register: %s\n",
1277
-		       sandev->drive, strerror ( rc ) );
1277
+		       drive, strerror ( rc ) );
1278 1278
 		goto err_register;
1279 1279
 	}
1280 1280
 
@@ -1544,70 +1544,83 @@ static int int13_boot ( unsigned int drive ) {
1544 1544
 	return -ECANCELED; /* -EIMPOSSIBLE */
1545 1545
 }
1546 1546
 
1547
-/** A boot firmware table generated by iPXE */
1548
-union xbft_table {
1549
-	/** ACPI header */
1550
-	struct acpi_description_header acpi;
1551
-	/** Padding */
1552
-	char pad[768];
1553
-};
1547
+/** Maximum size of boot firmware table(s) */
1548
+#define XBFTAB_SIZE 768
1549
+
1550
+/** Alignment of boot firmware table entries */
1551
+#define XBFTAB_ALIGN 16
1554 1552
 
1555
-/** The boot firmware table generated by iPXE */
1556
-static union xbft_table __bss16 ( xbftab ) __attribute__ (( aligned ( 16 ) ));
1553
+/** The boot firmware table(s) generated by iPXE */
1554
+static uint8_t __bss16_array ( xbftab, [XBFTAB_SIZE] )
1555
+	__attribute__ (( aligned ( XBFTAB_ALIGN ) ));
1557 1556
 #define xbftab __use_data16 ( xbftab )
1558 1557
 
1558
+/** Total used length of boot firmware tables */
1559
+static size_t xbftab_used;
1560
+
1559 1561
 /**
1560
- * Describe SAN device for SAN-booted operating system
1562
+ * Install ACPI table
1561 1563
  *
1562
- * @v drive		Drive number
1564
+ * @v acpi		ACPI description header
1563 1565
  * @ret rc		Return status code
1564 1566
  */
1565
-static int int13_describe ( unsigned int drive ) {
1566
-	struct san_device *sandev;
1567
-	struct san_path *sanpath;
1567
+static int int13_install ( struct acpi_header *acpi ) {
1568 1568
 	struct segoff xbft_address;
1569
-	int rc;
1570
-
1571
-	/* Find drive */
1572
-	sandev = sandev_find ( drive );
1573
-	if ( ! sandev ) {
1574
-		DBG ( "INT13 cannot find drive %02x\n", drive );
1575
-		return -ENODEV;
1569
+	struct acpi_header *installed;
1570
+	size_t len;
1571
+
1572
+	/* Check length */
1573
+	len = acpi->length;
1574
+	if ( len > ( sizeof ( xbftab ) - xbftab_used ) ) {
1575
+		DBGC ( acpi, "INT13 out of space for %s table\n",
1576
+		       acpi_name ( acpi->signature ) );
1577
+		return -ENOSPC;
1576 1578
 	}
1577 1579
 
1578
-	/* Reopen block device if necessary */
1579
-	if ( sandev_needs_reopen ( sandev ) &&
1580
-	     ( ( rc = sandev_reopen ( sandev ) ) != 0 ) )
1581
-		return rc;
1582
-	sanpath = sandev->active;
1583
-	assert ( sanpath != NULL );
1580
+	/* Install table */
1581
+	installed = ( ( ( void * ) xbftab ) + xbftab_used );
1582
+	memcpy ( installed, acpi, len );
1583
+	xbft_address.segment = rm_ds;
1584
+	xbft_address.offset = __from_data16 ( installed );
1585
+
1586
+	/* Fill in common parameters */
1587
+	strncpy ( installed->oem_id, "FENSYS",
1588
+		  sizeof ( installed->oem_id ) );
1589
+	strncpy ( installed->oem_table_id, "iPXE",
1590
+		  sizeof ( installed->oem_table_id ) );
1591
+
1592
+	/* Fix checksum */
1593
+	acpi_fix_checksum ( installed );
1594
+
1595
+	/* Update used length */
1596
+	xbftab_used = ( ( xbftab_used + len + XBFTAB_ALIGN - 1 ) &
1597
+			~( XBFTAB_ALIGN - 1 ) );
1598
+
1599
+	DBGC ( acpi, "INT13 installed %s:\n",
1600
+	       acpi_name ( installed->signature ) );
1601
+	DBGC_HDA ( acpi, xbft_address, installed, len );
1602
+	return 0;
1603
+}
1584 1604
 
1585
-	/* Clear table */
1605
+/**
1606
+ * Describe SAN devices for SAN-booted operating system
1607
+ *
1608
+ * @ret rc		Return status code
1609
+ */
1610
+static int int13_describe ( void ) {
1611
+	int rc;
1612
+
1613
+	/* Clear tables */
1586 1614
 	memset ( &xbftab, 0, sizeof ( xbftab ) );
1615
+	xbftab_used = 0;
1587 1616
 
1588
-	/* Fill in common parameters */
1589
-	strncpy ( xbftab.acpi.oem_id, "FENSYS",
1590
-		  sizeof ( xbftab.acpi.oem_id ) );
1591
-	strncpy ( xbftab.acpi.oem_table_id, "iPXE",
1592
-		  sizeof ( xbftab.acpi.oem_table_id ) );
1593
-
1594
-	/* Fill in remaining parameters */
1595
-	if ( ( rc = acpi_describe ( &sanpath->block, &xbftab.acpi,
1596
-				    sizeof ( xbftab ) ) ) != 0 ) {
1597
-		DBGC ( sandev, "INT13 drive %02x could not create ACPI "
1598
-		       "description: %s\n", sandev->drive, strerror ( rc ) );
1617
+	/* Install ACPI tables */
1618
+	if ( ( rc = acpi_install ( int13_install ) ) != 0 ) {
1619
+		DBG ( "INT13 could not install ACPI tables: %s\n",
1620
+		      strerror ( rc ) );
1599 1621
 		return rc;
1600 1622
 	}
1601 1623
 
1602
-	/* Fix up ACPI checksum */
1603
-	acpi_fix_checksum ( &xbftab.acpi );
1604
-	xbft_address.segment = rm_ds;
1605
-	xbft_address.offset = __from_data16 ( &xbftab );
1606
-	DBGC ( sandev, "INT13 drive %02x described using boot firmware "
1607
-	       "table:\n", sandev->drive );
1608
-	DBGC_HDA ( sandev, xbft_address, &xbftab,
1609
-		   le32_to_cpu ( xbftab.acpi.length ) );
1610
-
1611 1624
 	return 0;
1612 1625
 }
1613 1626
 

+ 54
- 31
src/core/acpi.c View File

@@ -42,28 +42,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
42 42
  ******************************************************************************
43 43
  */
44 44
 
45
-/**
46
- * Transcribe ACPI table signature (for debugging)
47
- *
48
- * @v signature		ACPI table signature
49
- * @ret name		ACPI table signature name
50
- */
51
-static const char * acpi_name ( uint32_t signature ) {
52
-	static union {
53
-		uint32_t signature;
54
-		char name[5];
55
-	} u;
56
-
57
-	u.signature = cpu_to_le32 ( signature );
58
-	return u.name;
59
-}
60
-
61 45
 /**
62 46
  * Fix up ACPI table checksum
63 47
  *
64 48
  * @v acpi		ACPI table header
65 49
  */
66
-void acpi_fix_checksum ( struct acpi_description_header *acpi ) {
50
+void acpi_fix_checksum ( struct acpi_header *acpi ) {
67 51
 	unsigned int i = 0;
68 52
 	uint8_t sum = 0;
69 53
 
@@ -147,7 +131,7 @@ userptr_t acpi_find_rsdt ( userptr_t ebda ) {
147 131
  * @ret table		Table, or UNULL if not found
148 132
  */
149 133
 userptr_t acpi_find ( userptr_t rsdt, uint32_t signature, unsigned int index ) {
150
-	struct acpi_description_header acpi;
134
+	struct acpi_header acpi;
151 135
 	struct acpi_rsdt *rsdtab;
152 136
 	typeof ( rsdtab->entry[0] ) entry;
153 137
 	userptr_t table;
@@ -227,7 +211,7 @@ userptr_t acpi_find ( userptr_t rsdt, uint32_t signature, unsigned int index ) {
227 211
  * the ACPI specification itself.
228 212
  */
229 213
 static int acpi_sx_zsdt ( userptr_t zsdt, uint32_t signature ) {
230
-	struct acpi_description_header acpi;
214
+	struct acpi_header acpi;
231 215
 	union {
232 216
 		uint32_t dword;
233 217
 		uint8_t byte[4];
@@ -331,34 +315,73 @@ int acpi_sx ( userptr_t rsdt, uint32_t signature ) {
331 315
 
332 316
 /******************************************************************************
333 317
  *
334
- * Interface methods
318
+ * Descriptors
335 319
  *
336 320
  ******************************************************************************
337 321
  */
338 322
 
339 323
 /**
340
- * Describe object in an ACPI table
324
+ * Add ACPI descriptor
325
+ *
326
+ * @v desc		ACPI descriptor
327
+ */
328
+void acpi_add ( struct acpi_descriptor *desc ) {
329
+
330
+	/* Add to list of descriptors */
331
+	ref_get ( desc->refcnt );
332
+	list_add_tail ( &desc->list, &desc->model->descs );
333
+}
334
+
335
+/**
336
+ * Remove ACPI descriptor
337
+ *
338
+ * @v desc		ACPI descriptor
339
+ */
340
+void acpi_del ( struct acpi_descriptor *desc ) {
341
+
342
+	/* Remove from list of descriptors */
343
+	list_check_contains_entry ( desc, &desc->model->descs, list );
344
+	list_del ( &desc->list );
345
+	ref_put ( desc->refcnt );
346
+}
347
+
348
+/**
349
+ * Get object's ACPI descriptor
341 350
  *
342 351
  * @v intf		Interface
343
- * @v acpi		ACPI table
344
- * @v len		Length of ACPI table
345
- * @ret rc		Return status code
352
+ * @ret desc		ACPI descriptor, or NULL
346 353
  */
347
-int acpi_describe ( struct interface *intf,
348
-		    struct acpi_description_header *acpi, size_t len ) {
354
+struct acpi_descriptor * acpi_describe ( struct interface *intf ) {
349 355
 	struct interface *dest;
350 356
 	acpi_describe_TYPE ( void * ) *op =
351 357
 		intf_get_dest_op ( intf, acpi_describe, &dest );
352 358
 	void *object = intf_object ( dest );
353
-	int rc;
359
+	struct acpi_descriptor *desc;
354 360
 
355 361
 	if ( op ) {
356
-		rc = op ( object, acpi, len );
362
+		desc = op ( object );
357 363
 	} else {
358
-		/* Default is to fail to describe */
359
-		rc = -EOPNOTSUPP;
364
+		desc = NULL;
360 365
 	}
361 366
 
362 367
 	intf_put ( dest );
363
-	return rc;
368
+	return desc;
369
+}
370
+
371
+/**
372
+ * Install ACPI tables
373
+ *
374
+ * @v install		Table installation method
375
+ * @ret rc		Return status code
376
+ */
377
+int acpi_install ( int ( * install ) ( struct acpi_header *acpi ) ){
378
+	struct acpi_model *model;
379
+	int rc;
380
+
381
+	for_each_table_entry ( model, ACPI_MODELS ) {
382
+		if ( ( rc = model->install ( install ) ) != 0 )
383
+			return rc;
384
+	}
385
+
386
+	return 0;
364 387
 }

+ 19
- 6
src/core/dummy_sanboot.c View File

@@ -38,10 +38,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
38 38
  * @v drive		Drive number
39 39
  * @v uris		List of URIs
40 40
  * @v count		Number of URIs
41
+ * @v flags		Flags
41 42
  * @ret drive		Drive number, or negative error
42 43
  */
43 44
 static int dummy_san_hook ( unsigned int drive, struct uri **uris,
44
-			    unsigned int count ) {
45
+			    unsigned int count, unsigned int flags ) {
45 46
 	struct san_device *sandev;
46 47
 	int rc;
47 48
 
@@ -51,10 +52,9 @@ static int dummy_san_hook ( unsigned int drive, struct uri **uris,
51 52
 		rc = -ENOMEM;
52 53
 		goto err_alloc;
53 54
 	}
54
-	sandev->drive = drive;
55 55
 
56 56
 	/* Register SAN device */
57
-	if ( ( rc = register_sandev ( sandev ) ) != 0 ) {
57
+	if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
58 58
 		DBGC ( sandev, "SAN %#02x could not register: %s\n",
59 59
 		       sandev->drive, strerror ( rc ) );
60 60
 		goto err_register;
@@ -102,15 +102,28 @@ static int dummy_san_boot ( unsigned int drive __unused ) {
102 102
 }
103 103
 
104 104
 /**
105
- * Describe dummy SAN device
105
+ * Install ACPI table
106 106
  *
107
- * @v drive		Drive number
107
+ * @v acpi		ACPI description header
108
+ * @ret rc		Return status code
108 109
  */
109
-static int dummy_san_describe ( unsigned int drive __unused ) {
110
+static int dummy_install ( struct acpi_header *acpi ) {
110 111
 
112
+	DBGC ( acpi, "ACPI table %s:\n", acpi_name ( acpi->signature ) );
113
+	DBGC_HDA ( acpi, 0, acpi, le32_to_cpu ( acpi->length ) );
111 114
 	return 0;
112 115
 }
113 116
 
117
+/**
118
+ * Describe dummy SAN device
119
+ *
120
+ * @ret rc		Return status code
121
+ */
122
+static int dummy_san_describe ( void ) {
123
+
124
+	return acpi_install ( dummy_install );
125
+}
126
+
114 127
 PROVIDE_SANBOOT ( dummy, san_hook, dummy_san_hook );
115 128
 PROVIDE_SANBOOT ( dummy, san_unhook, dummy_san_unhook );
116 129
 PROVIDE_SANBOOT ( dummy, san_boot, dummy_san_boot );

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

@@ -28,7 +28,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
28 28
 
29 29
 static int null_san_hook ( unsigned int drive __unused,
30 30
 			   struct uri **uris __unused,
31
-			   unsigned int count __unused ) {
31
+			   unsigned int count __unused,
32
+			   unsigned int flags __unused ) {
32 33
 	return -EOPNOTSUPP;
33 34
 }
34 35
 
@@ -40,7 +41,7 @@ static int null_san_boot ( unsigned int drive __unused ) {
40 41
 	return -EOPNOTSUPP;
41 42
 }
42 43
 
43
-static int null_san_describe ( unsigned int drive __unused ) {
44
+static int null_san_describe ( void ) {
44 45
 	return -EOPNOTSUPP;
45 46
 }
46 47
 

+ 97
- 4
src/core/sanboot.c View File

@@ -119,8 +119,10 @@ static void sandev_free ( struct refcnt *refcnt ) {
119 119
 	assert ( ! timer_running ( &sandev->timer ) );
120 120
 	assert ( ! sandev->active );
121 121
 	assert ( list_empty ( &sandev->opened ) );
122
-	for ( i = 0 ; i < sandev->paths ; i++ )
122
+	for ( i = 0 ; i < sandev->paths ; i++ ) {
123 123
 		uri_put ( sandev->path[i].uri );
124
+		assert ( sandev->path[i].desc == NULL );
125
+	}
124 126
 	free ( sandev );
125 127
 }
126 128
 
@@ -199,6 +201,15 @@ static int sanpath_open ( struct san_path *sanpath ) {
199 201
 		return rc;
200 202
 	}
201 203
 
204
+	/* Update ACPI descriptor, if applicable */
205
+	if ( ! ( sandev->flags & SAN_NO_DESCRIBE ) ) {
206
+		if ( sanpath->desc )
207
+			acpi_del ( sanpath->desc );
208
+		sanpath->desc = acpi_describe ( &sanpath->block );
209
+		if ( sanpath->desc )
210
+			acpi_add ( sanpath->desc );
211
+	}
212
+
202 213
 	/* Start process */
203 214
 	process_add ( &sanpath->process );
204 215
 
@@ -606,6 +617,72 @@ int sandev_rw ( struct san_device *sandev, uint64_t lba,
606 617
 	return 0;
607 618
 }
608 619
 
620
+/**
621
+ * Describe SAN device
622
+ *
623
+ * @v sandev		SAN device
624
+ * @ret rc		Return status code
625
+ *
626
+ * Allow connections to progress until all existent path descriptors
627
+ * are complete.
628
+ */
629
+static int sandev_describe ( struct san_device *sandev ) {
630
+	struct san_path *sanpath;
631
+	struct acpi_descriptor *desc;
632
+	int rc;
633
+
634
+	/* Wait for all paths to be either described or closed */
635
+	while ( 1 ) {
636
+
637
+		/* Allow connections to progress */
638
+		step();
639
+
640
+		/* Fail if any closed path has an incomplete descriptor */
641
+		list_for_each_entry ( sanpath, &sandev->closed, list ) {
642
+			desc = sanpath->desc;
643
+			if ( ! desc )
644
+				continue;
645
+			if ( ( rc = desc->model->complete ( desc ) ) != 0 ) {
646
+				DBGC ( sandev, "SAN %#02x.%d could not be "
647
+				       "described: %s\n", sandev->drive,
648
+				       sanpath->index, strerror ( rc ) );
649
+				return rc;
650
+			}
651
+		}
652
+
653
+		/* Succeed if no paths have an incomplete descriptor */
654
+		rc = 0;
655
+		list_for_each_entry ( sanpath, &sandev->opened, list ) {
656
+			desc = sanpath->desc;
657
+			if ( ! desc )
658
+				continue;
659
+			if ( ( rc = desc->model->complete ( desc ) ) != 0 )
660
+				break;
661
+		}
662
+		if ( rc == 0 )
663
+			return 0;
664
+	}
665
+}
666
+
667
+/**
668
+ * Remove SAN device descriptors
669
+ *
670
+ * @v sandev		SAN device
671
+ */
672
+static void sandev_undescribe ( struct san_device *sandev ) {
673
+	struct san_path *sanpath;
674
+	unsigned int i;
675
+
676
+	/* Remove all ACPI descriptors */
677
+	for ( i = 0 ; i < sandev->paths ; i++ ) {
678
+		sanpath = &sandev->path[i];
679
+		if ( sanpath->desc ) {
680
+			acpi_del ( sanpath->desc );
681
+			sanpath->desc = NULL;
682
+		}
683
+	}
684
+}
685
+
609 686
 /**
610 687
  * Configure SAN device as a CD-ROM, if applicable
611 688
  *
@@ -729,18 +806,25 @@ struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
729 806
  * Register SAN device
730 807
  *
731 808
  * @v sandev		SAN device
809
+ * @v drive		Drive number
810
+ * @v flags		Flags
732 811
  * @ret rc		Return status code
733 812
  */
734
-int register_sandev ( struct san_device *sandev ) {
813
+int register_sandev ( struct san_device *sandev, unsigned int drive,
814
+		      unsigned int flags ) {
735 815
 	int rc;
736 816
 
737 817
 	/* Check that drive number is not in use */
738
-	if ( sandev_find ( sandev->drive ) != NULL ) {
739
-		DBGC ( sandev, "SAN %#02x is already in use\n", sandev->drive );
818
+	if ( sandev_find ( drive ) != NULL ) {
819
+		DBGC ( sandev, "SAN %#02x is already in use\n", drive );
740 820
 		rc = -EADDRINUSE;
741 821
 		goto err_in_use;
742 822
 	}
743 823
 
824
+	/* Record drive number and flags */
825
+	sandev->drive = drive;
826
+	sandev->flags = flags;
827
+
744 828
 	/* Check that device is capable of being opened (i.e. that all
745 829
 	 * URIs are well-formed and that at least one path is
746 830
 	 * working).
@@ -748,6 +832,10 @@ int register_sandev ( struct san_device *sandev ) {
748 832
 	if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
749 833
 		goto err_reopen;
750 834
 
835
+	/* Describe device */
836
+	if ( ( rc = sandev_describe ( sandev ) ) != 0 )
837
+		goto err_describe;
838
+
751 839
 	/* Read device capacity */
752 840
 	if ( ( rc = sandev_command ( sandev, sandev_command_read_capacity,
753 841
 				     NULL ) ) != 0 )
@@ -766,8 +854,10 @@ int register_sandev ( struct san_device *sandev ) {
766 854
 	list_del ( &sandev->list );
767 855
  err_iso9660:
768 856
  err_capacity:
857
+ err_describe:
769 858
  err_reopen:
770 859
 	sandev_restart ( sandev, rc );
860
+	sandev_undescribe ( sandev );
771 861
  err_in_use:
772 862
 	return rc;
773 863
 }
@@ -788,6 +878,9 @@ void unregister_sandev ( struct san_device *sandev ) {
788 878
 	/* Shut down interfaces */
789 879
 	sandev_restart ( sandev, 0 );
790 880
 
881
+	/* Remove ACPI descriptors */
882
+	sandev_undescribe ( sandev );
883
+
791 884
 	DBGC ( sandev, "SAN %#02x unregistered\n", sandev->drive );
792 885
 }
793 886
 

+ 287
- 105
src/drivers/block/ibft.c View File

@@ -28,6 +28,7 @@
28 28
 FILE_LICENCE ( BSD2 );
29 29
 
30 30
 #include <stdint.h>
31
+#include <stdlib.h>
31 32
 #include <stdio.h>
32 33
 #include <string.h>
33 34
 #include <errno.h>
@@ -38,6 +39,7 @@ FILE_LICENCE ( BSD2 );
38 39
 #include <ipxe/netdevice.h>
39 40
 #include <ipxe/ethernet.h>
40 41
 #include <ipxe/vlan.h>
42
+#include <ipxe/tcpip.h>
41 43
 #include <ipxe/dhcp.h>
42 44
 #include <ipxe/iscsi.h>
43 45
 #include <ipxe/ibft.h>
@@ -54,37 +56,31 @@ FILE_LICENCE ( BSD2 );
54 56
  */
55 57
 
56 58
 /**
57
- * An iBFT created by iPXE
58
- *
59
- */
60
-struct ipxe_ibft {
61
-	/** The fixed section */
62
-	struct ibft_table table;
63
-	/** The Initiator section */
64
-	struct ibft_initiator initiator __attribute__ (( aligned ( 16 ) ));
65
-	/** The NIC section */
66
-	struct ibft_nic nic __attribute__ (( aligned ( 16 ) ));
67
-	/** The Target section */
68
-	struct ibft_target target __attribute__ (( aligned ( 16 ) ));
69
-	/** Strings block */
70
-	char strings[0];
71
-} __attribute__ (( packed, aligned ( 16 ) ));
72
-
73
-/**
74
- * iSCSI string block descriptor
59
+ * iSCSI string buffer
75 60
  *
76 61
  * This is an internal structure that we use to keep track of the
77 62
  * allocation of string data.
78 63
  */
79 64
 struct ibft_strings {
80
-	/** The iBFT containing these strings */
81
-	struct ibft_table *table;
82
-	/** Offset of first free byte within iBFT */
83
-	size_t offset;
84
-	/** Total length of the iBFT */
65
+	/** Strings data */
66
+	char *data;
67
+	/** Starting offset of strings */
68
+	size_t start;
69
+	/** Total length */
85 70
 	size_t len;
86 71
 };
87 72
 
73
+/**
74
+ * Align structure within iBFT
75
+ *
76
+ * @v len		Unaligned length (or offset)
77
+ * @ret len		Aligned length (or offset)
78
+ */
79
+static inline size_t ibft_align ( size_t len ) {
80
+
81
+	return ( ( len + IBFT_ALIGN - 1 ) & ~( IBFT_ALIGN - 1 ) );
82
+}
83
+
88 84
 /**
89 85
  * Fill in an IP address field within iBFT
90 86
  *
@@ -141,15 +137,29 @@ static const char * ibft_ipaddr ( struct ibft_ipaddr *ipaddr ) {
141 137
  */
142 138
 static char * ibft_alloc_string ( struct ibft_strings *strings,
143 139
 				  struct ibft_string *string, size_t len ) {
140
+	size_t new_len;
141
+	char *new_data;
142
+	char *dest;
144 143
 
145
-	if ( ( strings->offset + len ) >= strings->len )
144
+	/* Extend string data buffer */
145
+	new_len = ( strings->len + len + 1 /* NUL */ );
146
+	new_data = realloc ( strings->data, new_len );
147
+	if ( ! new_data )
146 148
 		return NULL;
149
+	strings->data = new_data;
147 150
 
148
-	string->offset = cpu_to_le16 ( strings->offset );
151
+	/* Fill in string field */
152
+	string->offset = cpu_to_le16 ( strings->start + strings->len );
149 153
 	string->len = cpu_to_le16 ( len );
150
-	strings->offset += ( len + 1 );
151 154
 
152
-	return ( ( ( char * ) strings->table ) + string->offset );
155
+	/* Zero string */
156
+	dest = ( strings->data + strings->len );
157
+	memset ( dest, 0, ( len + 1 /* NUL */ ) );
158
+
159
+	/* Update allocated length */
160
+	strings->len = new_len;
161
+
162
+	return dest;
153 163
 }
154 164
 
155 165
 /**
@@ -217,8 +227,28 @@ static int ibft_set_string_setting ( struct settings *settings,
217 227
  */
218 228
 static const char * ibft_string ( struct ibft_strings *strings,
219 229
 				  struct ibft_string *string ) {
220
-	return ( string->offset ?
221
-		 ( ( ( char * ) strings->table ) + string->offset ) : NULL );
230
+	size_t offset = le16_to_cpu ( string->offset );
231
+
232
+	return ( offset ? ( strings->data + offset - strings->start ) : NULL );
233
+}
234
+
235
+/**
236
+ * Check if network device is required for the iBFT
237
+ *
238
+ * @v netdev		Network device
239
+ * @ret is_required	Network device is required
240
+ */
241
+static int ibft_netdev_is_required ( struct net_device *netdev ) {
242
+	struct iscsi_session *iscsi;
243
+	struct sockaddr_tcpip *st_target;
244
+
245
+	list_for_each_entry ( iscsi, &ibft_model.descs, desc.list ) {
246
+		st_target = ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr;
247
+		if ( tcpip_netdev ( st_target ) == netdev )
248
+			return 1;
249
+	}
250
+
251
+	return 0;
222 252
 }
223 253
 
224 254
 /**
@@ -245,29 +275,33 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
245 275
 	nic->header.length = cpu_to_le16 ( sizeof ( *nic ) );
246 276
 	nic->header.flags = ( IBFT_FL_NIC_BLOCK_VALID |
247 277
 			      IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED );
278
+	DBG ( "iBFT NIC %d is %s\n", nic->header.index, netdev->name );
248 279
 
249 280
 	/* Determine origin of IP address */
250 281
 	fetch_setting ( parent, &ip_setting, &origin, NULL, NULL, 0 );
251 282
 	nic->origin = ( ( origin == parent ) ?
252 283
 			IBFT_NIC_ORIGIN_MANUAL : IBFT_NIC_ORIGIN_DHCP );
253
-	DBG ( "iBFT NIC origin = %d\n", nic->origin );
284
+	DBG ( "iBFT NIC %d origin = %d\n", nic->header.index, nic->origin );
254 285
 
255 286
 	/* Extract values from configuration settings */
256 287
 	ibft_set_ipaddr_setting ( parent, &nic->ip_address, &ip_setting, 1 );
257
-	DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) );
288
+	DBG ( "iBFT NIC %d IP = %s\n",
289
+	      nic->header.index, ibft_ipaddr ( &nic->ip_address ) );
258 290
 	ibft_set_ipaddr_setting ( parent, &nic->gateway, &gateway_setting, 1 );
259
-	DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) );
291
+	DBG ( "iBFT NIC %d gateway = %s\n",
292
+	      nic->header.index, ibft_ipaddr ( &nic->gateway ) );
260 293
 	ibft_set_ipaddr_setting ( NULL, &nic->dns[0], &dns_setting,
261 294
 				  ( sizeof ( nic->dns ) /
262 295
 				    sizeof ( nic->dns[0] ) ) );
263 296
 	ibft_set_ipaddr_setting ( parent, &nic->dhcp, &dhcp_server_setting, 1 );
264
-	DBG ( "iBFT NIC DNS = %s", ibft_ipaddr ( &nic->dns[0] ) );
297
+	DBG ( "iBFT NIC %d DNS = %s",
298
+	      nic->header.index, ibft_ipaddr ( &nic->dns[0] ) );
265 299
 	DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) );
266 300
 	if ( ( rc = ibft_set_string_setting ( NULL, strings, &nic->hostname,
267 301
 					      &hostname_setting ) ) != 0 )
268 302
 		return rc;
269
-	DBG ( "iBFT NIC hostname = %s\n",
270
-	      ibft_string ( strings, &nic->hostname ) );
303
+	DBG ( "iBFT NIC %d hostname = %s\n",
304
+	      nic->header.index, ibft_string ( strings, &nic->hostname ) );
271 305
 
272 306
 	/* Derive subnet mask prefix from subnet mask */
273 307
 	fetch_ipv4_setting ( parent, &netmask_setting, &netmask_addr );
@@ -277,19 +311,24 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
277 311
 		netmask_addr.s_addr >>= 1;
278 312
 	}
279 313
 	nic->subnet_mask_prefix = netmask_count;
280
-	DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix );
314
+	DBG ( "iBFT NIC %d subnet = /%d\n",
315
+	      nic->header.index, nic->subnet_mask_prefix );
281 316
 
282 317
 	/* Extract values from net-device configuration */
283 318
 	nic->vlan = cpu_to_le16 ( vlan_tag ( netdev ) );
284
-	DBG ( "iBFT NIC VLAN = %02x\n", le16_to_cpu ( nic->vlan ) );
319
+	DBG ( "iBFT NIC %d VLAN = %02x\n",
320
+	      nic->header.index, le16_to_cpu ( nic->vlan ) );
285 321
 	if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr,
286 322
 					    nic->mac_address ) ) != 0 ) {
287
-		DBG ( "Could not determine iBFT MAC: %s\n", strerror ( rc ) );
323
+		DBG ( "Could not determine %s MAC: %s\n",
324
+		      netdev->name, strerror ( rc ) );
288 325
 		return rc;
289 326
 	}
290
-	DBG ( "iBFT NIC MAC = %s\n", eth_ntoa ( nic->mac_address ) );
327
+	DBG ( "iBFT NIC %d MAC = %s\n",
328
+	      nic->header.index, eth_ntoa ( nic->mac_address ) );
291 329
 	nic->pci_bus_dev_func = cpu_to_le16 ( netdev->dev->desc.location );
292
-	DBG ( "iBFT NIC PCI = %04x\n", le16_to_cpu ( nic->pci_bus_dev_func ) );
330
+	DBG ( "iBFT NIC %d PCI = %04x\n",
331
+	      nic->header.index, le16_to_cpu ( nic->pci_bus_dev_func ) );
293 332
 
294 333
 	return 0;
295 334
 }
@@ -299,12 +338,10 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
299 338
  *
300 339
  * @v initiator		Initiator portion of iBFT
301 340
  * @v strings		iBFT string block descriptor
302
- * @v iscsi		iSCSI session
303 341
  * @ret rc		Return status code
304 342
  */
305 343
 static int ibft_fill_initiator ( struct ibft_initiator *initiator,
306
-				 struct ibft_strings *strings,
307
-				 struct iscsi_session *iscsi ) {
344
+				 struct ibft_strings *strings ) {
308 345
 	int rc;
309 346
 
310 347
 	/* Fill in common header */
@@ -314,16 +351,57 @@ static int ibft_fill_initiator ( struct ibft_initiator *initiator,
314 351
 	initiator->header.flags = ( IBFT_FL_INITIATOR_BLOCK_VALID |
315 352
 				    IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED );
316 353
 
317
-	/* Fill in hostname */
318
-	if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name,
319
-				      iscsi->initiator_iqn ) ) != 0 )
354
+	/* Fill in initiator name */
355
+	if ( ( rc = ibft_set_string_setting ( NULL, strings,
356
+					      &initiator->initiator_name,
357
+					      &initiator_iqn_setting ) ) != 0 )
320 358
 		return rc;
321
-	DBG ( "iBFT initiator hostname = %s\n",
359
+	DBG ( "iBFT initiator name = %s\n",
322 360
 	      ibft_string ( strings, &initiator->initiator_name ) );
323 361
 
324 362
 	return 0;
325 363
 }
326 364
 
365
+/**
366
+ * Fill in Target NIC association
367
+ *
368
+ * @v target		Target portion of iBFT
369
+ * @v iscsi		iSCSI session
370
+ * @ret rc		Return status code
371
+ */
372
+static int ibft_fill_target_nic_association ( struct ibft_target *target,
373
+					      struct iscsi_session *iscsi ) {
374
+	struct sockaddr_tcpip *st_target =
375
+		( struct sockaddr_tcpip * ) &iscsi->target_sockaddr;
376
+	struct net_device *associated;
377
+	struct net_device *netdev;
378
+
379
+	/* Find network device used to reach target */
380
+	associated = tcpip_netdev ( st_target );
381
+	if ( ! associated ) {
382
+		DBG ( "iBFT target %d has no net device\n",
383
+		      target->header.index );
384
+		return -EHOSTUNREACH;
385
+	}
386
+
387
+	/* Calculate association */
388
+	for_each_netdev ( netdev ) {
389
+		if ( netdev == associated ) {
390
+			DBG ( "iBFT target %d uses NIC %d (%s)\n",
391
+			      target->header.index, target->nic_association,
392
+			      netdev->name );
393
+			return 0;
394
+		}
395
+		if ( ! ibft_netdev_is_required ( netdev ) )
396
+			continue;
397
+		target->nic_association++;
398
+	}
399
+
400
+	DBG ( "iBFT target %d has impossible NIC %s\n",
401
+	      target->header.index, netdev->name );
402
+	return -EINVAL;
403
+}
404
+
327 405
 /**
328 406
  * Fill in Target CHAP portion of iBFT
329 407
  *
@@ -347,12 +425,12 @@ static int ibft_fill_target_chap ( struct ibft_target *target,
347 425
 	if ( ( rc = ibft_set_string ( strings, &target->chap_name,
348 426
 				      iscsi->initiator_username ) ) != 0 )
349 427
 		return rc;
350
-	DBG ( "iBFT target username = %s\n",
428
+	DBG ( "iBFT target %d username = %s\n", target->header.index,
351 429
 	      ibft_string ( strings, &target->chap_name ) );
352 430
 	if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
353 431
 				      iscsi->initiator_password ) ) != 0 )
354 432
 		return rc;
355
-	DBG ( "iBFT target password = <redacted>\n" );
433
+	DBG ( "iBFT target %d password = <redacted>\n", target->header.index );
356 434
 
357 435
 	return 0;
358 436
 }
@@ -382,12 +460,13 @@ static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
382 460
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
383 461
 				      iscsi->target_username ) ) != 0 )
384 462
 		return rc;
385
-	DBG ( "iBFT target reverse username = %s\n",
463
+	DBG ( "iBFT target %d reverse username = %s\n", target->header.index,
386 464
 	      ibft_string ( strings, &target->chap_name ) );
387 465
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
388 466
 				      iscsi->target_password ) ) != 0 )
389 467
 		return rc;
390
-	DBG ( "iBFT target reverse password = <redacted>\n" );
468
+	DBG ( "iBFT target %d reverse password = <redacted>\n",
469
+	      target->header.index );
391 470
 
392 471
 	return 0;
393 472
 }
@@ -403,6 +482,8 @@ static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
403 482
 static int ibft_fill_target ( struct ibft_target *target,
404 483
 			      struct ibft_strings *strings,
405 484
 			      struct iscsi_session *iscsi ) {
485
+	struct sockaddr_tcpip *st_target =
486
+		( struct sockaddr_tcpip * ) &iscsi->target_sockaddr;
406 487
 	struct sockaddr_in *sin_target =
407 488
 		( struct sockaddr_in * ) &iscsi->target_sockaddr;
408 489
 	int rc;
@@ -416,17 +497,21 @@ static int ibft_fill_target ( struct ibft_target *target,
416 497
 
417 498
 	/* Fill in Target values */
418 499
 	ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
419
-	DBG ( "iBFT target IP = %s\n", ibft_ipaddr ( &target->ip_address ) );
420
-	target->socket = cpu_to_le16 ( ntohs ( sin_target->sin_port ) );
421
-	DBG ( "iBFT target port = %d\n", target->socket );
500
+	DBG ( "iBFT target %d IP = %s\n",
501
+	      target->header.index, ibft_ipaddr ( &target->ip_address ) );
502
+	target->socket = cpu_to_le16 ( ntohs ( st_target->st_port ) );
503
+	DBG ( "iBFT target %d port = %d\n",
504
+	      target->header.index, target->socket );
422 505
 	memcpy ( &target->boot_lun, &iscsi->lun, sizeof ( target->boot_lun ) );
423
-	DBG ( "iBFT target boot LUN = " SCSI_LUN_FORMAT "\n",
424
-	      SCSI_LUN_DATA ( target->boot_lun ) );
506
+	DBG ( "iBFT target %d boot LUN = " SCSI_LUN_FORMAT "\n",
507
+	      target->header.index, SCSI_LUN_DATA ( target->boot_lun ) );
425 508
 	if ( ( rc = ibft_set_string ( strings, &target->target_name,
426 509
 				      iscsi->target_iqn ) ) != 0 )
427 510
 		return rc;
428
-	DBG ( "iBFT target name = %s\n",
511
+	DBG ( "iBFT target %d name = %s\n", target->header.index,
429 512
 	      ibft_string ( strings, &target->target_name ) );
513
+	if ( ( rc = ibft_fill_target_nic_association ( target, iscsi ) ) != 0 )
514
+		return rc;
430 515
 	if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
431 516
 		return rc;
432 517
 	if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,
@@ -437,62 +522,159 @@ static int ibft_fill_target ( struct ibft_target *target,
437 522
 }
438 523
 
439 524
 /**
440
- * Fill in iBFT
525
+ * Check if iBFT descriptor is complete
441 526
  *
442
- * @v iscsi		iSCSI session
443
- * @v acpi		ACPI table
444
- * @v len		Length of ACPI table
527
+ * @v desc		ACPI descriptor
445 528
  * @ret rc		Return status code
446 529
  */
447
-int ibft_describe ( struct iscsi_session *iscsi,
448
-		    struct acpi_description_header *acpi,
449
-		    size_t len ) {
450
-	struct ipxe_ibft *ibft =
451
-		container_of ( acpi, struct ipxe_ibft, table.acpi );
452
-	struct ibft_strings strings = {
453
-		.table = &ibft->table,
454
-		.offset = offsetof ( typeof ( *ibft ), strings ),
455
-		.len = len,
456
-	};
530
+static int ibft_complete ( struct acpi_descriptor *desc ) {
531
+	struct iscsi_session *iscsi =
532
+		container_of ( desc, struct iscsi_session, desc );
533
+
534
+	/* Fail if we do not yet have the target address */
535
+	if ( ! iscsi->target_sockaddr.sa_family )
536
+		return -EAGAIN;
537
+
538
+	return 0;
539
+}
540
+
541
+/**
542
+ * Install iBFT
543
+ *
544
+ * @v install		Installation method
545
+ * @ret rc		Return status code
546
+ */
547
+static int ibft_install ( int ( * install ) ( struct acpi_header *acpi ) ) {
457 548
 	struct net_device *netdev;
549
+	struct iscsi_session *iscsi;
550
+	struct ibft_table *table;
551
+	struct ibft_initiator *initiator;
552
+	struct ibft_nic *nic;
553
+	struct ibft_target *target;
554
+	struct ibft_strings strings;
555
+	struct acpi_header *acpi;
556
+	void *data;
557
+	unsigned int targets = 0;
558
+	unsigned int pairs = 0;
559
+	size_t offset = 0;
560
+	size_t table_len;
561
+	size_t control_len;
562
+	size_t initiator_offset;
563
+	size_t nic_offset;
564
+	size_t target_offset;
565
+	size_t strings_offset;
566
+	size_t len;
567
+	unsigned int i;
458 568
 	int rc;
459 569
 
460
-	/* Ugly hack.  Now that we have a generic interface mechanism
461
-	 * that can support ioctls, we can potentially eliminate this.
462
-	 */
463
-	netdev = last_opened_netdev();
464
-	if ( ! netdev ) {
465
-		DBGC ( iscsi, "iSCSI %p cannot guess network device\n",
466
-		       iscsi );
467
-		return -ENODEV;
570
+	/* Calculate table sizes and offsets */
571
+	list_for_each_entry ( iscsi, &ibft_model.descs, desc.list )
572
+		targets++;
573
+	pairs = ( sizeof ( table->control.pair ) /
574
+		  sizeof ( table->control.pair[0] ) );
575
+	if ( pairs < targets )
576
+		pairs = targets;
577
+	offset = offsetof ( typeof ( *table ), control.pair );
578
+	offset += ( pairs * sizeof ( table->control.pair[0] ) );
579
+	table_len = offset;
580
+	control_len = ( table_len - offsetof ( typeof ( *table ), control ) );
581
+	offset = ibft_align ( offset );
582
+	initiator_offset = offset;
583
+	offset += ibft_align ( sizeof ( *initiator ) );
584
+	nic_offset = offset;
585
+	offset += ( pairs * ibft_align ( sizeof ( *nic ) ) );
586
+	target_offset = offset;
587
+	offset += ( pairs * ibft_align ( sizeof ( *target ) ) );
588
+	strings_offset = offset;
589
+	strings.data = NULL;
590
+	strings.start = strings_offset;
591
+	strings.len = 0;
592
+	len = offset;
593
+
594
+	/* Allocate table */
595
+	data = zalloc ( len );
596
+	if ( ! data ) {
597
+		rc = -ENOMEM;
598
+		goto err_alloc;
468 599
 	}
469 600
 
470
-	/* Fill in ACPI header */
471
-	ibft->table.acpi.signature = cpu_to_le32 ( IBFT_SIG );
472
-	ibft->table.acpi.length = cpu_to_le32 ( len );
473
-	ibft->table.acpi.revision = 1;
474
-
475 601
 	/* Fill in Control block */
476
-	ibft->table.control.header.structure_id = IBFT_STRUCTURE_ID_CONTROL;
477
-	ibft->table.control.header.version = 1;
478
-	ibft->table.control.header.length =
479
-		cpu_to_le16 ( sizeof ( ibft->table.control ) );
480
-	ibft->table.control.initiator =
481
-		cpu_to_le16 ( offsetof ( typeof ( *ibft ), initiator ) );
482
-	ibft->table.control.nic_0 =
483
-		cpu_to_le16 ( offsetof ( typeof ( *ibft ), nic ) );
484
-	ibft->table.control.target_0 =
485
-		cpu_to_le16 ( offsetof ( typeof ( *ibft ), target ) );
486
-
487
-	/* Fill in NIC, Initiator and Target blocks */
488
-	if ( ( rc = ibft_fill_nic ( &ibft->nic, &strings, netdev ) ) != 0 )
489
-		return rc;
490
-	if ( ( rc = ibft_fill_initiator ( &ibft->initiator, &strings,
491
-					  iscsi ) ) != 0 )
492
-		return rc;
493
-	if ( ( rc = ibft_fill_target ( &ibft->target, &strings,
494
-				       iscsi ) ) != 0 )
495
-		return rc;
602
+	table = data;
603
+	table->control.header.structure_id = IBFT_STRUCTURE_ID_CONTROL;
604
+	table->control.header.version = 1;
605
+	table->control.header.length = cpu_to_le16 ( control_len );
606
+
607
+	/* Fill in Initiator block */
608
+	initiator = ( data + initiator_offset );
609
+	table->control.initiator = cpu_to_le16 ( initiator_offset );
610
+	if ( ( rc = ibft_fill_initiator ( initiator, &strings ) ) != 0 )
611
+		goto err_initiator;
612
+
613
+	/* Fill in NIC blocks */
614
+	i = 0;
615
+	for_each_netdev ( netdev ) {
616
+		if ( ! ibft_netdev_is_required ( netdev ) )
617
+			continue;
618
+		assert ( i < pairs );
619
+		table->control.pair[i].nic = nic_offset;
620
+		nic = ( data + nic_offset );
621
+		nic->header.index = i;
622
+		if ( ( rc = ibft_fill_nic ( nic, &strings, netdev ) ) != 0 )
623
+			goto err_nic;
624
+		i++;
625
+		nic_offset += ibft_align ( sizeof ( *nic ) );
626
+	}
496 627
 
497
-	return 0;
628
+	/* Fill in Target blocks */
629
+	i = 0;
630
+	list_for_each_entry ( iscsi, &ibft_model.descs, desc.list ) {
631
+		assert ( i < pairs );
632
+		table->control.pair[i].target = target_offset;
633
+		target = ( data + target_offset );
634
+		target->header.index = i;
635
+		if ( ( rc = ibft_fill_target ( target, &strings, iscsi ) ) != 0)
636
+			goto err_target;
637
+		i++;
638
+		target_offset += ibft_align ( sizeof ( *target ) );
639
+	}
640
+
641
+	/* Reallocate table to include space for strings */
642
+	len += strings.len;
643
+	acpi = realloc ( data, len );
644
+	if ( ! acpi )
645
+		goto err_realloc;
646
+	data = NULL;
647
+
648
+	/* Fill in ACPI header */
649
+	acpi->signature = cpu_to_le32 ( IBFT_SIG );
650
+	acpi->length = cpu_to_le32 ( len );
651
+	acpi->revision = 1;
652
+
653
+	/* Append strings */
654
+	memcpy ( ( ( ( void * ) acpi ) + strings_offset ), strings.data,
655
+		 strings.len );
656
+
657
+	/* Install ACPI table */
658
+	if ( ( rc = install ( acpi ) ) != 0 ) {
659
+		DBG ( "iBFT could not install: %s\n", strerror ( rc ) );
660
+		goto err_install;
661
+	}
662
+
663
+ err_install:
664
+	free ( acpi );
665
+ err_realloc:
666
+ err_target:
667
+ err_nic:
668
+ err_initiator:
669
+	free ( data );
670
+ err_alloc:
671
+	free ( strings.data );
672
+	return rc;
498 673
 }
674
+
675
+/** iBFT model */
676
+struct acpi_model ibft_model __acpi_model = {
677
+	.descs = LIST_HEAD_INIT ( ibft_model.descs ),
678
+	.complete = ibft_complete,
679
+	.install = ibft_install,
680
+};

+ 0
- 68
src/drivers/block/srp.c View File

@@ -113,13 +113,6 @@ struct srp_device {
113 113
 	/** Login completed successfully */
114 114
 	int logged_in;
115 115
 
116
-	/** Initiator port ID (for boot firmware table) */
117
-	union srp_port_id initiator;
118
-	/** Target port ID (for boot firmware table) */
119
-	union srp_port_id target;
120
-	/** SCSI LUN (for boot firmware table) */
121
-	struct scsi_lun lun;
122
-
123 116
 	/** List of active commands */
124 117
 	struct list_head commands;
125 118
 };
@@ -684,61 +677,6 @@ static size_t srpdev_window ( struct srp_device *srpdev ) {
684 677
 	return ( srpdev->logged_in ? ~( ( size_t ) 0 ) : 0 );
685 678
 }
686 679
 
687
-/**
688
- * A (transport-independent) sBFT created by iPXE
689
- */
690
-struct ipxe_sbft {
691
-	/** The table header */
692
-	struct sbft_table table;
693
-	/** The SCSI subtable */
694
-	struct sbft_scsi_subtable scsi;
695
-	/** The SRP subtable */
696
-	struct sbft_srp_subtable srp;
697
-} __attribute__ (( packed, aligned ( 16 ) ));
698
-
699
-/**
700
- * Describe SRP device in an ACPI table
701
- *
702
- * @v srpdev		SRP device
703
- * @v acpi		ACPI table
704
- * @v len		Length of ACPI table
705
- * @ret rc		Return status code
706
- */
707
-static int srpdev_describe ( struct srp_device *srpdev,
708
-			     struct acpi_description_header *acpi,
709
-			     size_t len ) {
710
-	struct ipxe_sbft *sbft =
711
-		container_of ( acpi, struct ipxe_sbft, table.acpi );
712
-	int rc;
713
-
714
-	/* Sanity check */
715
-	if ( len < sizeof ( *sbft ) )
716
-		return -ENOBUFS;
717
-
718
-	/* Populate table */
719
-	sbft->table.acpi.signature = cpu_to_le32 ( SBFT_SIG );
720
-	sbft->table.acpi.length = cpu_to_le32 ( sizeof ( *sbft ) );
721
-	sbft->table.acpi.revision = 1;
722
-	sbft->table.scsi_offset =
723
-		cpu_to_le16 ( offsetof ( typeof ( *sbft ), scsi ) );
724
-	memcpy ( &sbft->scsi.lun, &srpdev->lun, sizeof ( sbft->scsi.lun ) );
725
-	sbft->table.srp_offset =
726
-		cpu_to_le16 ( offsetof ( typeof ( *sbft ), srp ) );
727
-	memcpy ( &sbft->srp.initiator, &srpdev->initiator,
728
-		 sizeof ( sbft->srp.initiator ) );
729
-	memcpy ( &sbft->srp.target, &srpdev->target,
730
-		 sizeof ( sbft->srp.target ) );
731
-
732
-	/* Ask transport layer to describe transport-specific portions */
733
-	if ( ( rc = acpi_describe ( &srpdev->socket, acpi, len ) ) != 0 ) {
734
-		DBGC ( srpdev, "SRP %p cannot describe transport layer: %s\n",
735
-		       srpdev, strerror ( rc ) );
736
-		return rc;
737
-	}
738
-
739
-	return 0;
740
-}
741
-
742 680
 /** SRP device socket interface operations */
743 681
 static struct interface_operation srpdev_socket_op[] = {
744 682
 	INTF_OP ( xfer_deliver, struct srp_device *, srpdev_deliver ),
@@ -755,7 +693,6 @@ static struct interface_operation srpdev_scsi_op[] = {
755 693
 	INTF_OP ( scsi_command, struct srp_device *, srpdev_scsi_command ),
756 694
 	INTF_OP ( xfer_window, struct srp_device *, srpdev_window ),
757 695
 	INTF_OP ( intf_close, struct srp_device *, srpdev_close ),
758
-	INTF_OP ( acpi_describe, struct srp_device *, srpdev_describe ),
759 696
 };
760 697
 
761 698
 /** SRP device SCSI interface descriptor */
@@ -797,11 +734,6 @@ int srp_open ( struct interface *block, struct interface *socket,
797 734
 	       ntohl ( target->dwords[0] ), ntohl ( target->dwords[1] ),
798 735
 	       ntohl ( target->dwords[2] ), ntohl ( target->dwords[3] ) );
799 736
 
800
-	/* Preserve parameters required for boot firmware table */
801
-	memcpy ( &srpdev->initiator, initiator, sizeof ( srpdev->initiator ) );
802
-	memcpy ( &srpdev->target, target, sizeof ( srpdev->target ) );
803
-	memcpy ( &srpdev->lun, lun, sizeof ( srpdev->lun ) );
804
-
805 737
 	/* Attach to socket interface and initiate login */
806 738
 	intf_plug_plug ( &srpdev->socket, socket );
807 739
 	tag = srp_new_tag ( srpdev );

+ 82
- 9
src/include/ipxe/acpi.h View File

@@ -10,8 +10,12 @@
10 10
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11 11
 
12 12
 #include <stdint.h>
13
+#include <byteswap.h>
14
+#include <ipxe/refcnt.h>
15
+#include <ipxe/list.h>
13 16
 #include <ipxe/interface.h>
14 17
 #include <ipxe/uaccess.h>
18
+#include <ipxe/tables.h>
15 19
 
16 20
 /**
17 21
  * An ACPI description header
@@ -19,7 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
19 23
  * This is the structure common to the start of all ACPI system
20 24
  * description tables.
21 25
  */
22
-struct acpi_description_header {
26
+struct acpi_header {
23 27
 	/** ACPI signature (4 ASCII characters) */
24 28
 	uint32_t signature;
25 29
 	/** Length of table, in bytes, including header */
@@ -40,6 +44,22 @@ struct acpi_description_header {
40 44
 	uint32_t asl_compiler_revision;
41 45
 } __attribute__ (( packed ));
42 46
 
47
+/**
48
+ * Transcribe ACPI table signature (for debugging)
49
+ *
50
+ * @v signature		ACPI table signature
51
+ * @ret name		ACPI table signature name
52
+ */
53
+static inline const char * acpi_name ( uint32_t signature ) {
54
+	static union {
55
+		uint32_t signature;
56
+		char name[5];
57
+	} u;
58
+
59
+	u.signature = cpu_to_le32 ( signature );
60
+	return u.name;
61
+}
62
+
43 63
 /**
44 64
  * Build ACPI signature
45 65
  *
@@ -87,7 +107,7 @@ struct acpi_rsdp {
87 107
 /** ACPI Root System Description Table (RSDT) */
88 108
 struct acpi_rsdt {
89 109
 	/** ACPI header */
90
-	struct acpi_description_header acpi;
110
+	struct acpi_header acpi;
91 111
 	/** ACPI table entries */
92 112
 	uint32_t entry[0];
93 113
 } __attribute__ (( packed ));
@@ -98,7 +118,7 @@ struct acpi_rsdt {
98 118
 /** Fixed ACPI Description Table (FADT) */
99 119
 struct acpi_fadt {
100 120
 	/** ACPI header */
101
-	struct acpi_description_header acpi;
121
+	struct acpi_header acpi;
102 122
 	/** Physical address of FACS */
103 123
 	uint32_t facs;
104 124
 	/** Physical address of DSDT */
@@ -122,17 +142,70 @@ struct acpi_fadt {
122 142
 /** Secondary System Description Table (SSDT) signature */
123 143
 #define SSDT_SIGNATURE ACPI_SIGNATURE ( 'S', 'S', 'D', 'T' )
124 144
 
125
-extern int acpi_describe ( struct interface *interface,
126
-			   struct acpi_description_header *acpi, size_t len );
145
+/** An ACPI descriptor (used to construct ACPI tables) */
146
+struct acpi_descriptor {
147
+	/** Reference count of containing object */
148
+	struct refcnt *refcnt;
149
+	/** Table model */
150
+	struct acpi_model *model;
151
+	/** List of ACPI descriptors for this model */
152
+	struct list_head list;
153
+};
154
+
155
+/**
156
+ * Initialise ACPI descriptor
157
+ *
158
+ * @v desc		ACPI descriptor
159
+ * @v model		Table model
160
+ * @v refcnt		Reference count
161
+ */
162
+static inline __attribute__ (( always_inline )) void
163
+acpi_init ( struct acpi_descriptor *desc, struct acpi_model *model,
164
+	    struct refcnt *refcnt ) {
165
+
166
+	desc->refcnt = refcnt;
167
+	desc->model = model;
168
+	INIT_LIST_HEAD ( &desc->list );
169
+}
170
+
171
+/** An ACPI table model */
172
+struct acpi_model {
173
+	/** List of descriptors */
174
+	struct list_head descs;
175
+	/**
176
+	 * Check if ACPI descriptor is complete
177
+	 *
178
+	 * @v desc		ACPI descriptor
179
+	 * @ret rc		Return status code
180
+	 */
181
+	int ( * complete ) ( struct acpi_descriptor *desc );
182
+	/**
183
+	 * Install ACPI tables
184
+	 *
185
+	 * @v install		Installation method
186
+	 * @ret rc		Return status code
187
+	 */
188
+	int ( * install ) ( int ( * install ) ( struct acpi_header *acpi ) );
189
+};
190
+
191
+/** ACPI models */
192
+#define ACPI_MODELS __table ( struct acpi_model, "acpi_models" )
193
+
194
+/** Declare an ACPI model */
195
+#define __acpi_model __table_entry ( ACPI_MODELS, 01 )
196
+
197
+extern struct acpi_descriptor *
198
+acpi_describe ( struct interface *interface );
127 199
 #define acpi_describe_TYPE( object_type )				\
128
-	typeof ( int ( object_type,					\
129
-		       struct acpi_description_header *acpi,		\
130
-		       size_t len ) )
200
+	typeof ( struct acpi_descriptor * ( object_type ) )
131 201
 
132
-extern void acpi_fix_checksum ( struct acpi_description_header *acpi );
202
+extern void acpi_fix_checksum ( struct acpi_header *acpi );
133 203
 extern userptr_t acpi_find_rsdt ( userptr_t ebda );
134 204
 extern userptr_t acpi_find ( userptr_t rsdt, uint32_t signature,
135 205
 			     unsigned int index );
136 206
 extern int acpi_sx ( userptr_t rsdt, uint32_t signature );
207
+extern void acpi_add ( struct acpi_descriptor *desc );
208
+extern void acpi_del ( struct acpi_descriptor *desc );
209
+extern int acpi_install ( int ( * install ) ( struct acpi_header *acpi ) );
137 210
 
138 211
 #endif /* _IPXE_ACPI_H */

+ 1
- 1
src/include/ipxe/aoe.h View File

@@ -117,7 +117,7 @@ struct aoehdr {
117 117
  */
118 118
 struct abft_table {
119 119
 	/** ACPI header */
120
-	struct acpi_description_header acpi;
120
+	struct acpi_header acpi;
121 121
 	/** AoE shelf */
122 122
 	uint16_t shelf;
123 123
 	/** AoE slot */

+ 21
- 15
src/include/ipxe/ibft.h View File

@@ -49,6 +49,9 @@ FILE_LICENCE ( BSD2 );
49 49
 /** iSCSI Boot Firmware Table signature */
50 50
 #define IBFT_SIG ACPI_SIGNATURE ( 'i', 'B', 'F', 'T' )
51 51
 
52
+/** Alignment of structures within iBFT */
53
+#define IBFT_ALIGN 16
54
+
52 55
 /** An offset from the start of the iBFT */
53 56
 typedef uint16_t ibft_off_t;
54 57
 
@@ -97,6 +100,20 @@ struct ibft_header {
97 100
 	uint8_t flags;
98 101
 } __attribute__ (( packed ));
99 102
 
103
+/**
104
+ * iBFT NIC and Target offset pair
105
+ *
106
+ * There is no implicit relation between the NIC and the Target, but
107
+ * using this structure simplifies the table construction code while
108
+ * matching the expected table layout.
109
+ */
110
+struct ibft_offset_pair {
111
+	/** Offset to NIC structure */
112
+	ibft_off_t nic;
113
+	/** Offset to Target structure */
114
+	ibft_off_t target;
115
+} __attribute__ (( packed ));
116
+
100 117
 /**
101 118
  * iBFT Control structure
102 119
  *
@@ -108,14 +125,8 @@ struct ibft_control {
108 125
 	uint16_t extensions;
109 126
 	/** Offset to Initiator structure */
110 127
 	ibft_off_t initiator;
111
-	/** Offset to NIC structure for NIC 0 */
112
-	ibft_off_t nic_0;
113
-	/** Offset to Target structure for target 0 */
114
-	ibft_off_t target_0;
115
-	/** Offset to NIC structure for NIC 1 */
116
-	ibft_off_t nic_1;
117
-	/** Offset to Target structure for target 1 */
118
-	ibft_off_t target_1;
128
+	/** Offsets to NIC and Target structures */
129
+	struct ibft_offset_pair pair[2];
119 130
 } __attribute__ (( packed ));
120 131
 
121 132
 /** Structure ID for Control section */
@@ -262,18 +273,13 @@ struct ibft_target {
262 273
  */
263 274
 struct ibft_table {
264 275
 	/** ACPI header */
265
-	struct acpi_description_header acpi;
276
+	struct acpi_header acpi;
266 277
 	/** Reserved */
267 278
 	uint8_t reserved[12];
268 279
 	/** Control structure */
269 280
 	struct ibft_control control;
270 281
 } __attribute__ (( packed ));
271 282
 
272
-struct iscsi_session;
273
-struct net_device;
274
-
275
-extern int ibft_describe ( struct iscsi_session *iscsi,
276
-			   struct acpi_description_header *acpi,
277
-			   size_t len );
283
+extern struct acpi_model ibft_model __acpi_model;
278 284
 
279 285
 #endif /* _IPXE_IBFT_H */

+ 7
- 0
src/include/ipxe/iscsi.h View File

@@ -16,6 +16,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
16 16
 #include <ipxe/refcnt.h>
17 17
 #include <ipxe/xfer.h>
18 18
 #include <ipxe/process.h>
19
+#include <ipxe/acpi.h>
20
+#include <ipxe/settings.h>
19 21
 
20 22
 /** Default iSCSI port */
21 23
 #define ISCSI_PORT 3260
@@ -647,6 +649,8 @@ struct iscsi_session {
647 649
 	struct sockaddr target_sockaddr;
648 650
 	/** SCSI LUN (for boot firmware table) */
649 651
 	struct scsi_lun lun;
652
+	/** ACPI descriptor */
653
+	struct acpi_descriptor desc;
650 654
 };
651 655
 
652 656
 /** iSCSI session is currently in the security negotiation phase */
@@ -697,4 +701,7 @@ struct iscsi_session {
697 701
 /** Default initiator IQN prefix */
698 702
 #define ISCSI_DEFAULT_IQN_PREFIX "iqn.2010-04.org.ipxe"
699 703
 
704
+extern const struct setting
705
+initiator_iqn_setting __setting ( SETTING_SANBOOT_EXTRA, initiator-iqn );
706
+
700 707
 #endif /* _IPXE_ISCSI_H */

+ 19
- 5
src/include/ipxe/sanboot.h View File

@@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
18 18
 #include <ipxe/retry.h>
19 19
 #include <ipxe/process.h>
20 20
 #include <ipxe/blockdev.h>
21
+#include <ipxe/acpi.h>
21 22
 #include <config/sanboot.h>
22 23
 
23 24
 /** A SAN path */
@@ -37,6 +38,9 @@ struct san_path {
37 38
 	struct process process;
38 39
 	/** Path status */
39 40
 	int path_rc;
41
+
42
+	/** ACPI descriptor (if applicable) */
43
+	struct acpi_descriptor *desc;
40 44
 };
41 45
 
42 46
 /** A SAN device */
@@ -48,6 +52,8 @@ struct san_device {
48 52
 
49 53
 	/** Drive number */
50 54
 	unsigned int drive;
55
+	/** Flags */
56
+	unsigned int flags;
51 57
 
52 58
 	/** Command interface */
53 59
 	struct interface command;
@@ -83,6 +89,12 @@ struct san_device {
83 89
 	struct san_path path[0];
84 90
 };
85 91
 
92
+/** SAN device flags */
93
+enum san_device_flags {
94
+	/** Device should not be included in description tables */
95
+	SAN_NO_DESCRIBE = 0x0001,
96
+};
97
+
86 98
 /**
87 99
  * Calculate static inline sanboot API function name
88 100
  *
@@ -126,9 +138,11 @@ struct san_device {
126 138
  * @v drive		Drive number
127 139
  * @v uris		List of URIs
128 140
  * @v count		Number of URIs
141
+ * @v flags		Flags
129 142
  * @ret drive		Drive number, or negative error
130 143
  */
131
-int san_hook ( unsigned int drive, struct uri **uris, unsigned int count );
144
+int san_hook ( unsigned int drive, struct uri **uris, unsigned int count,
145
+	       unsigned int flags );
132 146
 
133 147
 /**
134 148
  * Unhook SAN device
@@ -146,12 +160,11 @@ void san_unhook ( unsigned int drive );
146 160
 int san_boot ( unsigned int drive );
147 161
 
148 162
 /**
149
- * Describe SAN device for SAN-booted operating system
163
+ * Describe SAN devices for SAN-booted operating system
150 164
  *
151
- * @v drive		Drive number
152 165
  * @ret rc		Return status code
153 166
  */
154
-int san_describe ( unsigned int drive );
167
+int san_describe ( void );
155 168
 
156 169
 extern struct list_head san_devices;
157 170
 
@@ -230,7 +243,8 @@ extern int sandev_rw ( struct san_device *sandev, uint64_t lba,
230 243
 					    userptr_t buffer, size_t len ) );
231 244
 extern struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
232 245
 					  size_t priv_size );
233
-extern int register_sandev ( struct san_device *sandev );
246
+extern int register_sandev ( struct san_device *sandev, unsigned int drive,
247
+			     unsigned int flags );
234 248
 extern void unregister_sandev ( struct san_device *sandev );
235 249
 extern unsigned int san_default_drive ( void );
236 250
 

+ 1
- 1
src/include/ipxe/srp.h View File

@@ -790,7 +790,7 @@ typedef uint16_t sbft_off_t;
790 790
  */
791 791
 struct sbft_table {
792 792
 	/** ACPI header */
793
-	struct acpi_description_header acpi;
793
+	struct acpi_header acpi;
794 794
 	/** Offset to SCSI subtable */
795 795
 	sbft_off_t scsi_offset;
796 796
 	/** Offset to SRP subtable */

+ 84
- 64
src/interface/efi/efi_block.c View File

@@ -254,10 +254,11 @@ static void efi_block_connect ( struct san_device *sandev ) {
254 254
  * @v drive		Drive number
255 255
  * @v uris		List of URIs
256 256
  * @v count		Number of URIs
257
+ * @v flags		Flags
257 258
  * @ret drive		Drive number, or negative error
258 259
  */
259 260
 static int efi_block_hook ( unsigned int drive, struct uri **uris,
260
-			    unsigned int count ) {
261
+			    unsigned int count, unsigned int flags ) {
261 262
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
262 263
 	EFI_DEVICE_PATH_PROTOCOL *end;
263 264
 	struct efi_block_vendor_path *vendor;
@@ -301,7 +302,6 @@ static int efi_block_hook ( unsigned int drive, struct uri **uris,
301 302
 		rc = -ENOMEM;
302 303
 		goto err_alloc;
303 304
 	}
304
-	sandev->drive = drive;
305 305
 	block = sandev->priv;
306 306
 	block->sandev = sandev;
307 307
 	block->media.MediaPresent = 1;
@@ -331,12 +331,12 @@ static int efi_block_hook ( unsigned int drive, struct uri **uris,
331 331
 	end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
332 332
 	end->Length[0] = sizeof ( *end );
333 333
 	DBGC ( sandev, "EFIBLK %#02x has device path %s\n",
334
-	       sandev->drive, efi_devpath_text ( block->path ) );
334
+	       drive, efi_devpath_text ( block->path ) );
335 335
 
336 336
 	/* Register SAN device */
337
-	if ( ( rc = register_sandev ( sandev ) ) != 0 ) {
337
+	if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
338 338
 		DBGC ( sandev, "EFIBLK %#02x could not register: %s\n",
339
-		       sandev->drive, strerror ( rc ) );
339
+		       drive, strerror ( rc ) );
340 340
 		goto err_register;
341 341
 	}
342 342
 
@@ -408,85 +408,105 @@ static void efi_block_unhook ( unsigned int drive ) {
408 408
 	sandev_put ( sandev );
409 409
 }
410 410
 
411
+/** An installed ACPI table */
412
+struct efi_acpi_table {
413
+	/** List of installed tables */
414
+	struct list_head list;
415
+	/** Table key */
416
+	UINTN key;
417
+};
418
+
419
+/** List of installed ACPI tables */
420
+static LIST_HEAD ( efi_acpi_tables );
421
+
411 422
 /**
412
- * Describe EFI block device
423
+ * Install ACPI table
413 424
  *
414
- * @v drive		Drive number
425
+ * @v hdr		ACPI description header
415 426
  * @ret rc		Return status code
416 427
  */
417
-static int efi_block_describe ( unsigned int drive ) {
418
-	static union {
419
-		/** ACPI header */
420
-		struct acpi_description_header acpi;
421
-		/** Padding */
422
-		char pad[768];
423
-	} xbftab;
424
-	static UINTN key;
425
-	struct san_device *sandev;
426
-	struct san_path *sanpath;
427
-	size_t len;
428
+static int efi_block_install ( struct acpi_header *hdr ) {
429
+	size_t len = le32_to_cpu ( hdr->length );
430
+	struct efi_acpi_table *installed;
428 431
 	EFI_STATUS efirc;
429 432
 	int rc;
430 433
 
431
-	/* Find SAN device */
432
-	sandev = sandev_find ( drive );
433
-	if ( ! sandev ) {
434
-		DBG ( "EFIBLK cannot find drive %#02x\n", drive );
435
-		return -ENODEV;
434
+	/* Allocate installed table record */
435
+	installed = zalloc ( sizeof ( *installed ) );
436
+	if ( ! installed ) {
437
+		rc = -ENOMEM;
438
+		goto err_alloc;
436 439
 	}
437 440
 
441
+	/* Fill in common parameters */
442
+	strncpy ( hdr->oem_id, "FENSYS", sizeof ( hdr->oem_id ) );
443
+	strncpy ( hdr->oem_table_id, "iPXE", sizeof ( hdr->oem_table_id ) );
444
+
445
+	/* Fix up ACPI checksum */
446
+	acpi_fix_checksum ( hdr );
447
+
448
+	/* Install table */
449
+	if ( ( efirc = acpi->InstallAcpiTable ( acpi, hdr, len,
450
+						&installed->key ) ) != 0 ){
451
+		rc = -EEFI ( efirc );
452
+		DBGC ( acpi, "EFIBLK could not install %s: %s\n",
453
+		       acpi_name ( hdr->signature ), strerror ( rc ) );
454
+		DBGC_HDA ( acpi, 0, hdr, len );
455
+		goto err_install;
456
+	}
457
+
458
+	/* Add to list of installed tables */
459
+	list_add_tail ( &installed->list, &efi_acpi_tables );
460
+
461
+	DBGC ( acpi, "EFIBLK installed %s as ACPI table %#lx:\n",
462
+	       acpi_name ( hdr->signature ),
463
+	       ( ( unsigned long ) installed->key ) );
464
+	DBGC_HDA ( acpi, 0, hdr, len );
465
+	return 0;
466
+
467
+	list_del ( &installed->list );
468
+ err_install:
469
+	free ( installed );
470
+ err_alloc:
471
+	return rc;
472
+}
473
+
474
+/**
475
+ * Describe EFI block devices
476
+ *
477
+ * @ret rc		Return status code
478
+ */
479
+static int efi_block_describe ( void ) {
480
+	struct efi_acpi_table *installed;
481
+	struct efi_acpi_table *tmp;
482
+	UINTN key;
483
+	EFI_STATUS efirc;
484
+	int rc;
485
+
438 486
 	/* Sanity check */
439 487
 	if ( ! acpi ) {
440
-		DBGC ( sandev, "EFIBLK %#02x has no ACPI table protocol\n",
441
-		       sandev->drive );
488
+		DBG ( "EFIBLK has no ACPI table protocol\n" );
442 489
 		return -ENOTSUP;
443 490
 	}
444 491
 
445
-	/* Remove existing table, if any */
446
-	if ( key ) {
492
+	/* Uninstall any existing ACPI tables */
493
+	list_for_each_entry_safe ( installed, tmp, &efi_acpi_tables, list ) {
494
+		key = installed->key;
447 495
 		if ( ( efirc = acpi->UninstallAcpiTable ( acpi, key ) ) != 0 ) {
448 496
 			rc = -EEFI ( efirc );
449
-			DBGC ( sandev, "EFIBLK %#02x could not uninstall ACPI "
450
-			       "table: %s\n", sandev->drive, strerror ( rc ) );
497
+			DBGC ( acpi, "EFIBLK could not uninstall ACPI table "
498
+			       "%#lx: %s\n", ( ( unsigned long ) key ),
499
+			       strerror ( rc ) );
451 500
 			/* Continue anyway */
452 501
 		}
453
-		key = 0;
454
-	}
455
-
456
-	/* Reopen block device if necessary */
457
-	if ( sandev_needs_reopen ( sandev ) &&
458
-	     ( ( rc = sandev_reopen ( sandev ) ) != 0 ) )
459
-		return rc;
460
-	sanpath = sandev->active;
461
-	assert ( sanpath != NULL );
462
-
463
-	/* Clear table */
464
-	memset ( &xbftab, 0, sizeof ( xbftab ) );
465
-
466
-	/* Fill in common parameters */
467
-	strncpy ( xbftab.acpi.oem_id, "FENSYS",
468
-		  sizeof ( xbftab.acpi.oem_id ) );
469
-	strncpy ( xbftab.acpi.oem_table_id, "iPXE",
470
-		  sizeof ( xbftab.acpi.oem_table_id ) );
471
-
472
-	/* Fill in remaining parameters */
473
-	if ( ( rc = acpi_describe ( &sanpath->block, &xbftab.acpi,
474
-				    sizeof ( xbftab ) ) ) != 0 ) {
475
-		DBGC ( sandev, "EFIBLK %#02x could not create ACPI "
476
-		       "description: %s\n", sandev->drive, strerror ( rc ) );
477
-		return rc;
502
+		list_del ( &installed->list );
503
+		free ( installed );
478 504
 	}
479
-	len = le32_to_cpu ( xbftab.acpi.length );
480
-
481
-	/* Fix up ACPI checksum */
482
-	acpi_fix_checksum ( &xbftab.acpi );
483 505
 
484
-	/* Install table */
485
-	if ( ( efirc = acpi->InstallAcpiTable ( acpi, &xbftab, len,
486
-						&key ) ) != 0 ) {
487
-		rc = -EEFI ( efirc );
488
-		DBGC ( sandev, "EFIBLK %#02x could not install ACPI table: "
489
-		       "%s\n", sandev->drive, strerror ( rc ) );
506
+	/* Install ACPI tables */
507
+	if ( ( rc = acpi_install ( efi_block_install ) ) != 0 )  {
508
+		DBGC ( acpi, "EFIBLK could not install ACPI tables: %s\n",
509
+		       strerror ( rc ) );
490 510
 		return rc;
491 511
 	}
492 512
 

+ 67
- 23
src/net/aoe.c View File

@@ -53,6 +53,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
53 53
 FEATURE ( FEATURE_PROTOCOL, "AoE", DHCP_EB_FEATURE_AOE, 1 );
54 54
 
55 55
 struct net_protocol aoe_protocol __net_protocol;
56
+struct acpi_model abft_model __acpi_model;
56 57
 
57 58
 /******************************************************************************
58 59
  *
@@ -91,6 +92,9 @@ struct aoe_device {
91 92
 	struct interface config;
92 93
 	/** Device is configued */
93 94
 	int configured;
95
+
96
+	/** ACPI descriptor */
97
+	struct acpi_descriptor desc;
94 98
 };
95 99
 
96 100
 /** An AoE command */
@@ -790,32 +794,13 @@ static struct device * aoedev_identify_device ( struct aoe_device *aoedev ) {
790 794
 }
791 795
 
792 796
 /**
793
- * Describe AoE device in an ACPI table
797
+ * Get AoE ACPI descriptor
794 798
  *
795 799
  * @v aoedev		AoE device
796
- * @v acpi		ACPI table
797
- * @v len		Length of ACPI table
798
- * @ret rc		Return status code
800
+ * @ret desc		ACPI descriptor
799 801
  */
800
-static int aoedev_describe ( struct aoe_device *aoedev,
801
-			     struct acpi_description_header *acpi,
802
-			     size_t len ) {
803
-	struct abft_table *abft =
804
-		container_of ( acpi, struct abft_table, acpi );
805
-
806
-	/* Sanity check */
807
-	if ( len < sizeof ( *abft ) )
808
-		return -ENOBUFS;
809
-
810
-	/* Populate table */
811
-	abft->acpi.signature = cpu_to_le32 ( ABFT_SIG );
812
-	abft->acpi.length = cpu_to_le32 ( sizeof ( *abft ) );
813
-	abft->acpi.revision = 1;
814
-	abft->shelf = cpu_to_le16 ( aoedev->major );
815
-	abft->slot = aoedev->minor;
816
-	memcpy ( abft->mac, aoedev->netdev->ll_addr, sizeof ( abft->mac ) );
817
-
818
-	return 0;
802
+static struct acpi_descriptor * aoedev_describe ( struct aoe_device *aoedev ) {
803
+	return &aoedev->desc;
819 804
 }
820 805
 
821 806
 /** AoE device ATA interface operations */
@@ -869,6 +854,7 @@ static int aoedev_open ( struct interface *parent, struct net_device *netdev,
869 854
 	aoedev->minor = minor;
870 855
 	memcpy ( aoedev->target, netdev->ll_broadcast,
871 856
 		 netdev->ll_protocol->ll_addr_len );
857
+	acpi_init ( &aoedev->desc, &abft_model, &aoedev->refcnt );
872 858
 
873 859
 	/* Initiate configuration */
874 860
 	if ( ( rc = aoedev_cfg_command ( aoedev, &aoedev->config ) ) < 0 ) {
@@ -1059,3 +1045,61 @@ struct uri_opener aoe_uri_opener __uri_opener = {
1059 1045
 	.scheme = "aoe",
1060 1046
 	.open = aoe_open,
1061 1047
 };
1048
+
1049
+/******************************************************************************
1050
+ *
1051
+ * AoE boot firmware table (aBFT)
1052
+ *
1053
+ ******************************************************************************
1054
+ */
1055
+
1056
+/**
1057
+ * Check if AoE boot firmware table descriptor is complete
1058
+ *
1059
+ * @v desc		ACPI descriptor
1060
+ * @ret rc		Return status code
1061
+ */
1062
+static int abft_complete ( struct acpi_descriptor *desc __unused ) {
1063
+	return 0;
1064
+}
1065
+
1066
+/**
1067
+ * Install AoE boot firmware table(s)
1068
+ *
1069
+ * @v install		Installation method
1070
+ * @ret rc		Return status code
1071
+ */
1072
+static int abft_install ( int ( * install ) ( struct acpi_header *acpi ) ) {
1073
+	struct aoe_device *aoedev;
1074
+	struct abft_table abft;
1075
+	int rc;
1076
+
1077
+	list_for_each_entry ( aoedev, &abft_model.descs, desc.list ) {
1078
+
1079
+		/* Populate table */
1080
+		memset ( &abft, 0, sizeof ( abft ) );
1081
+		abft.acpi.signature = cpu_to_le32 ( ABFT_SIG );
1082
+		abft.acpi.length = cpu_to_le32 ( sizeof ( abft ) );
1083
+		abft.acpi.revision = 1;
1084
+		abft.shelf = cpu_to_le16 ( aoedev->major );
1085
+		abft.slot = aoedev->minor;
1086
+		memcpy ( abft.mac, aoedev->netdev->ll_addr,
1087
+			 sizeof ( abft.mac ) );
1088
+
1089
+		/* Install table */
1090
+		if ( ( rc = install ( &abft.acpi ) ) != 0 ) {
1091
+			DBGC ( aoedev, "AoE %s could not install aBFT: %s\n",
1092
+			       aoedev_name ( aoedev ), strerror ( rc ) );
1093
+			return rc;
1094
+		}
1095
+	}
1096
+
1097
+	return 0;
1098
+}
1099
+
1100
+/** aBFT model */
1101
+struct acpi_model abft_model __acpi_model = {
1102
+	.descs = LIST_HEAD_INIT ( abft_model.descs ),
1103
+	.complete = abft_complete,
1104
+	.install = abft_install,
1105
+};

+ 0
- 20
src/net/fcp.c View File

@@ -843,25 +843,6 @@ static size_t fcpdev_window ( struct fcp_device *fcpdev ) {
843 843
 		 ~( ( size_t ) 0 ) : 0 );
844 844
 }
845 845
 
846
-/**
847
- * Describe FCP device in an ACPI table
848
- *
849
- * @v fcpdev		FCP device
850
- * @v acpi		ACPI table
851
- * @v len		Length of ACPI table
852
- * @ret rc		Return status code
853
- */
854
-static int fcpdev_acpi_describe ( struct fcp_device *fcpdev,
855
-				  struct acpi_description_header *acpi,
856
-				  size_t len ) {
857
-
858
-	DBGC ( fcpdev, "FCP %p cannot yet describe device in an ACPI table\n",
859
-	       fcpdev );
860
-	( void ) acpi;
861
-	( void ) len;
862
-	return 0;
863
-}
864
-
865 846
 /**
866 847
  * Describe FCP device using EDD
867 848
  *
@@ -917,7 +898,6 @@ static struct interface_operation fcpdev_scsi_op[] = {
917 898
 	INTF_OP ( scsi_command, struct fcp_device *, fcpdev_scsi_command ),
918 899
 	INTF_OP ( xfer_window, struct fcp_device *, fcpdev_window ),
919 900
 	INTF_OP ( intf_close, struct fcp_device *, fcpdev_close ),
920
-	INTF_OP ( acpi_describe, struct fcp_device *, fcpdev_acpi_describe ),
921 901
 	INTF_OP ( edd_describe, struct fcp_device *, fcpdev_edd_describe ),
922 902
 	INTF_OP ( identify_device, struct fcp_device *,
923 903
 		  fcpdev_identify_device ),

+ 100
- 41
src/net/infiniband/ib_srp.c View File

@@ -60,6 +60,8 @@ FILE_LICENCE ( BSD2 );
60 60
 #define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \
61 61
 	( EINFO_EINVAL, 0x04, "Root path too short" )
62 62
 
63
+struct acpi_model ib_sbft_model __acpi_model;
64
+
63 65
 /******************************************************************************
64 66
  *
65 67
  * IB SRP devices
@@ -67,6 +69,20 @@ FILE_LICENCE ( BSD2 );
67 69
  ******************************************************************************
68 70
  */
69 71
 
72
+/**
73
+ * An IB SRP sBFT created by iPXE
74
+ */
75
+struct ipxe_ib_sbft {
76
+	/** The table header */
77
+	struct sbft_table table;
78
+	/** The SCSI subtable */
79
+	struct sbft_scsi_subtable scsi;
80
+	/** The SRP subtable */
81
+	struct sbft_srp_subtable srp;
82
+	/** The Infiniband subtable */
83
+	struct sbft_ib_subtable ib;
84
+};
85
+
70 86
 /** An Infiniband SRP device */
71 87
 struct ib_srp_device {
72 88
 	/** Reference count */
@@ -80,10 +96,10 @@ struct ib_srp_device {
80 96
 	/** Infiniband device */
81 97
 	struct ib_device *ibdev;
82 98
 
83
-	/** Destination GID (for boot firmware table) */
84
-	union ib_gid dgid;
85
-	/** Service ID (for boot firmware table) */
86
-	union ib_guid service_id;
99
+	/** ACPI descriptor */
100
+	struct acpi_descriptor desc;
101
+	/** Boot firmware table parameters */
102
+	struct ipxe_ib_sbft sbft;
87 103
 };
88 104
 
89 105
 /**
@@ -113,43 +129,15 @@ static void ib_srp_close ( struct ib_srp_device *ib_srp, int rc ) {
113 129
 }
114 130
 
115 131
 /**
116
- * Describe IB SRP device in an ACPI table
132
+ * Get IB SRP ACPI descriptor
117 133
  *
118
- * @v srpdev		SRP device
119
- * @v acpi		ACPI table
120
- * @v len		Length of ACPI table
121
- * @ret rc		Return status code
134
+ * @v ib_srp		IB SRP device
135
+ * @ret desc		ACPI descriptor
122 136
  */
123
-static int ib_srp_describe ( struct ib_srp_device *ib_srp,
124
-			     struct acpi_description_header *acpi,
125
-			     size_t len ) {
126
-	struct ib_device *ibdev = ib_srp->ibdev;
127
-	struct sbft_table *sbft =
128
-		container_of ( acpi, struct sbft_table, acpi );
129
-	struct sbft_ib_subtable *ib_sbft;
130
-	size_t used;
131
-
132
-	/* Sanity check */
133
-	if ( acpi->signature != SBFT_SIG )
134
-		return -EINVAL;
135
-
136
-	/* Append IB subtable to existing table */
137
-	used = le32_to_cpu ( sbft->acpi.length );
138
-	sbft->ib_offset = cpu_to_le16 ( used );
139
-	ib_sbft = ( ( ( void * ) sbft ) + used );
140
-	used += sizeof ( *ib_sbft );
141
-	if ( used > len )
142
-		return -ENOBUFS;
143
-	sbft->acpi.length = cpu_to_le32 ( used );
144
-
145
-	/* Populate subtable */
146
-	memcpy ( &ib_sbft->sgid, &ibdev->gid, sizeof ( ib_sbft->sgid ) );
147
-	memcpy ( &ib_sbft->dgid, &ib_srp->dgid, sizeof ( ib_sbft->dgid ) );
148
-	memcpy ( &ib_sbft->service_id, &ib_srp->service_id,
149
-		 sizeof ( ib_sbft->service_id ) );
150
-	ib_sbft->pkey = cpu_to_le16 ( ibdev->pkey );
137
+static struct acpi_descriptor *
138
+ib_srp_describe ( struct ib_srp_device *ib_srp ) {
151 139
 
152
-	return 0;
140
+	return &ib_srp->desc;
153 141
 }
154 142
 
155 143
 /** IB SRP CMRC interface operations */
@@ -188,6 +176,7 @@ static int ib_srp_open ( struct interface *block, struct ib_device *ibdev,
188 176
 			 union srp_port_id *initiator,
189 177
 			 union srp_port_id *target, struct scsi_lun *lun ) {
190 178
 	struct ib_srp_device *ib_srp;
179
+	struct ipxe_ib_sbft *sbft;
191 180
 	int rc;
192 181
 
193 182
 	/* Allocate and initialise structure */
@@ -200,13 +189,19 @@ static int ib_srp_open ( struct interface *block, struct ib_device *ibdev,
200 189
 	intf_init ( &ib_srp->srp, &ib_srp_srp_desc, &ib_srp->refcnt );
201 190
 	intf_init ( &ib_srp->cmrc, &ib_srp_cmrc_desc, &ib_srp->refcnt );
202 191
 	ib_srp->ibdev = ibdev_get ( ibdev );
192
+	acpi_init ( &ib_srp->desc, &ib_sbft_model, &ib_srp->refcnt );
203 193
 	DBGC ( ib_srp, "IBSRP %p for " IB_GID_FMT " " IB_GUID_FMT "\n",
204 194
 	       ib_srp, IB_GID_ARGS ( dgid ), IB_GUID_ARGS ( service_id ) );
205 195
 
206 196
 	/* Preserve parameters required for boot firmware table */
207
-	memcpy ( &ib_srp->dgid, dgid, sizeof ( ib_srp->dgid ) );
208
-	memcpy ( &ib_srp->service_id, service_id,
209
-		 sizeof ( ib_srp->service_id ) );
197
+	sbft = &ib_srp->sbft;
198
+	memcpy ( &sbft->scsi.lun, lun, sizeof ( sbft->scsi.lun ) );
199
+	memcpy ( &sbft->srp.initiator, initiator,
200
+		 sizeof ( sbft->srp.initiator ) );
201
+	memcpy ( &sbft->srp.target, target, sizeof ( sbft->srp.target ) );
202
+	memcpy ( &sbft->ib.dgid, dgid, sizeof ( sbft->ib.dgid ) );
203
+	memcpy ( &sbft->ib.service_id, service_id,
204
+		 sizeof ( sbft->ib.service_id ) );
210 205
 
211 206
 	/* Open CMRC socket */
212 207
 	if ( ( rc = ib_cmrc_open ( &ib_srp->cmrc, ibdev, dgid,
@@ -579,3 +574,67 @@ struct uri_opener ib_srp_uri_opener __uri_opener = {
579 574
 	.scheme = "ib_srp",
580 575
 	.open = ib_srp_open_uri,
581 576
 };
577
+
578
+/******************************************************************************
579
+ *
580
+ * IB SRP boot firmware table (sBFT)
581
+ *
582
+ ******************************************************************************
583
+ */
584
+
585
+/**
586
+ * Check if IB SRP boot firmware table descriptor is complete
587
+ *
588
+ * @v desc		ACPI descriptor
589
+ * @ret rc		Return status code
590
+ */
591
+static int ib_sbft_complete ( struct acpi_descriptor *desc __unused ) {
592
+	return 0;
593
+}
594
+
595
+/**
596
+ * Install IB SRP boot firmware table(s)
597
+ *
598
+ * @v install		Installation method
599
+ * @ret rc		Return status code
600
+ */
601
+static int ib_sbft_install ( int ( * install ) ( struct acpi_header *acpi ) ) {
602
+	struct ib_srp_device *ib_srp;
603
+	struct ipxe_ib_sbft *sbft;
604
+	struct ib_device *ibdev;
605
+	int rc;
606
+
607
+	list_for_each_entry ( ib_srp, &ib_sbft_model.descs, desc.list ) {
608
+
609
+		/* Complete table */
610
+		sbft = &ib_srp->sbft;
611
+		ibdev = ib_srp->ibdev;
612
+		sbft->table.acpi.signature = cpu_to_le32 ( SBFT_SIG );
613
+		sbft->table.acpi.length = cpu_to_le32 ( sizeof ( *sbft ) );
614
+		sbft->table.acpi.revision = 1;
615
+		sbft->table.scsi_offset =
616
+			cpu_to_le16 ( offsetof ( typeof ( *sbft ), scsi ) );
617
+		sbft->table.srp_offset =
618
+			cpu_to_le16 ( offsetof ( typeof ( *sbft ), srp ) );
619
+		sbft->table.ib_offset =
620
+			cpu_to_le16 ( offsetof ( typeof ( *sbft ), ib ) );
621
+		memcpy ( &sbft->ib.sgid, &ibdev->gid, sizeof ( sbft->ib.sgid ));
622
+		sbft->ib.pkey = cpu_to_le16 ( ibdev->pkey );
623
+
624
+		/* Install table */
625
+		if ( ( rc = install ( &sbft->table.acpi ) ) != 0 ) {
626
+			DBGC ( ib_srp, "IBSRP %p could not install sBFT: %s\n",
627
+			       ib_srp, strerror ( rc ) );
628
+			return rc;
629
+		}
630
+	}
631
+
632
+	return 0;
633
+}
634
+
635
+/** IB sBFT model */
636
+struct acpi_model ib_sbft_model __acpi_model = {
637
+	.descs = LIST_HEAD_INIT ( ib_sbft_model.descs ),
638
+	.complete = ib_sbft_complete,
639
+	.install = ib_sbft_install,
640
+};

+ 0
- 18
src/net/tcp/httpblock.c View File

@@ -114,21 +114,3 @@ int http_block_read_capacity ( struct http_transaction *http,
114 114
  err_open:
115 115
 	return rc;
116 116
 }
117
-
118
-/**
119
- * Describe device in ACPI table
120
- *
121
- * @v http		HTTP transaction
122
- * @v acpi		ACPI table
123
- * @v len		Length of ACPI table
124
- * @ret rc		Return status code
125
- */
126
-int http_acpi_describe ( struct http_transaction *http,
127
-			 struct acpi_description_header *acpi, size_t len ) {
128
-
129
-	DBGC ( http, "HTTP %p cannot yet describe device in an ACPI table\n",
130
-	       http );
131
-	( void ) acpi;
132
-	( void ) len;
133
-	return 0;
134
-}

+ 0
- 17
src/net/tcp/httpcore.c View File

@@ -509,28 +509,11 @@ __weak int http_block_read_capacity ( struct http_transaction *http __unused,
509 509
 	return -ENOTSUP;
510 510
 }
511 511
 
512
-/**
513
- * Describe device in ACPI table (when HTTP block device support is not present)
514
- *
515
- * @v http		HTTP transaction
516
- * @v acpi		ACPI table
517
- * @v len		Length of ACPI table
518
- * @ret rc		Return status code
519
- */
520
-__weak int http_acpi_describe ( struct http_transaction *http __unused,
521
-				struct acpi_description_header *acpi __unused,
522
-				size_t len __unused ) {
523
-
524
-	return -ENOTSUP;
525
-}
526
-
527 512
 /** HTTP data transfer interface operations */
528 513
 static struct interface_operation http_xfer_operations[] = {
529 514
 	INTF_OP ( block_read, struct http_transaction *, http_block_read ),
530 515
 	INTF_OP ( block_read_capacity, struct http_transaction *,
531 516
 		  http_block_read_capacity ),
532
-	INTF_OP ( acpi_describe, struct http_transaction *,
533
-		  http_acpi_describe ),
534 517
 	INTF_OP ( xfer_window_changed, struct http_transaction *, http_step ),
535 518
 	INTF_OP ( intf_close, struct http_transaction *, http_close ),
536 519
 };

+ 13
- 1
src/net/tcp/iscsi.c View File

@@ -1810,12 +1810,23 @@ static int iscsi_scsi_command ( struct iscsi_session *iscsi,
1810 1810
 	return iscsi->itt;
1811 1811
 }
1812 1812
 
1813
+/**
1814
+ * Get iSCSI ACPI descriptor
1815
+ *
1816
+ * @v iscsi		iSCSI session
1817
+ * @ret desc		ACPI descriptor
1818
+ */
1819
+static struct acpi_descriptor * iscsi_describe ( struct iscsi_session *iscsi ) {
1820
+
1821
+	return &iscsi->desc;
1822
+}
1823
+
1813 1824
 /** iSCSI SCSI command-issuing interface operations */
1814 1825
 static struct interface_operation iscsi_control_op[] = {
1815 1826
 	INTF_OP ( scsi_command, struct iscsi_session *, iscsi_scsi_command ),
1816 1827
 	INTF_OP ( xfer_window, struct iscsi_session *, iscsi_scsi_window ),
1817 1828
 	INTF_OP ( intf_close, struct iscsi_session *, iscsi_close ),
1818
-	INTF_OP ( acpi_describe, struct iscsi_session *, ibft_describe ),
1829
+	INTF_OP ( acpi_describe, struct iscsi_session *, iscsi_describe ),
1819 1830
 };
1820 1831
 
1821 1832
 /** iSCSI SCSI command-issuing interface descriptor */
@@ -2064,6 +2075,7 @@ static int iscsi_open ( struct interface *parent, struct uri *uri ) {
2064 2075
 	intf_init ( &iscsi->socket, &iscsi_socket_desc, &iscsi->refcnt );
2065 2076
 	process_init_stopped ( &iscsi->process, &iscsi_process_desc,
2066 2077
 			       &iscsi->refcnt );
2078
+	acpi_init ( &iscsi->desc, &ibft_model, &iscsi->refcnt );
2067 2079
 
2068 2080
 	/* Parse root path */
2069 2081
 	if ( ( rc = iscsi_parse_root_path ( iscsi, uri->opaque ) ) != 0 )

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

@@ -128,7 +128,9 @@ int uriboot ( struct uri *filename, struct uri **root_paths,
128 128
 
129 129
 	/* Hook SAN device, if applicable */
130 130
 	if ( root_path_count ) {
131
-		drive = san_hook ( drive, root_paths, root_path_count );
131
+		drive = san_hook ( drive, root_paths, root_path_count,
132
+				   ( ( flags & URIBOOT_NO_SAN_DESCRIBE ) ?
133
+				     SAN_NO_DESCRIBE : 0 ) );
132 134
 		if ( drive < 0 ) {
133 135
 			rc = drive;
134 136
 			printf ( "Could not open SAN device: %s\n",
@@ -140,9 +142,9 @@ int uriboot ( struct uri *filename, struct uri **root_paths,
140 142
 
141 143
 	/* Describe SAN device, if applicable */
142 144
 	if ( ! ( flags & URIBOOT_NO_SAN_DESCRIBE ) ) {
143
-		if ( ( rc = san_describe ( drive ) ) != 0 ) {
144
-			printf ( "Could not describe SAN device %#02x: %s\n",
145
-				 drive, strerror ( rc ) );
145
+		if ( ( rc = san_describe() ) != 0 ) {
146
+			printf ( "Could not describe SAN devices: %s\n",
147
+				 strerror ( rc ) );
146 148
 			goto err_san_describe;
147 149
 		}
148 150
 	}

Loading…
Cancel
Save