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
  * @v drive		Drive number
1239
  * @v drive		Drive number
1240
  * @v uris		List of URIs
1240
  * @v uris		List of URIs
1241
  * @v count		Number of URIs
1241
  * @v count		Number of URIs
1242
+ * @v flags		Flags
1242
  * @ret drive		Drive number, or negative error
1243
  * @ret drive		Drive number, or negative error
1243
  *
1244
  *
1244
  * Registers the drive with the INT 13 emulation subsystem, and hooks
1245
  * Registers the drive with the INT 13 emulation subsystem, and hooks
1245
  * the INT 13 interrupt vector (if not already hooked).
1246
  * the INT 13 interrupt vector (if not already hooked).
1246
  */
1247
  */
1247
 static int int13_hook ( unsigned int drive, struct uri **uris,
1248
 static int int13_hook ( unsigned int drive, struct uri **uris,
1248
-			unsigned int count ) {
1249
+			unsigned int count, unsigned int flags ) {
1249
 	struct san_device *sandev;
1250
 	struct san_device *sandev;
1250
 	struct int13_data *int13;
1251
 	struct int13_data *int13;
1251
 	unsigned int natural_drive;
1252
 	unsigned int natural_drive;
1267
 		rc = -ENOMEM;
1268
 		rc = -ENOMEM;
1268
 		goto err_alloc;
1269
 		goto err_alloc;
1269
 	}
1270
 	}
1270
-	sandev->drive = drive;
1271
 	int13 = sandev->priv;
1271
 	int13 = sandev->priv;
1272
 	int13->natural_drive = natural_drive;
1272
 	int13->natural_drive = natural_drive;
1273
 
1273
 
1274
 	/* Register SAN device */
1274
 	/* Register SAN device */
1275
-	if ( ( rc = register_sandev ( sandev ) ) != 0 ) {
1275
+	if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
1276
 		DBGC ( sandev, "INT13 drive %02x could not register: %s\n",
1276
 		DBGC ( sandev, "INT13 drive %02x could not register: %s\n",
1277
-		       sandev->drive, strerror ( rc ) );
1277
+		       drive, strerror ( rc ) );
1278
 		goto err_register;
1278
 		goto err_register;
1279
 	}
1279
 	}
1280
 
1280
 
1544
 	return -ECANCELED; /* -EIMPOSSIBLE */
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
 #define xbftab __use_data16 ( xbftab )
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
  * @ret rc		Return status code
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
 	struct segoff xbft_address;
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
 	memset ( &xbftab, 0, sizeof ( xbftab ) );
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
 		return rc;
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
 	return 0;
1624
 	return 0;
1612
 }
1625
 }
1613
 
1626
 

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

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
  * Fix up ACPI table checksum
46
  * Fix up ACPI table checksum
63
  *
47
  *
64
  * @v acpi		ACPI table header
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
 	unsigned int i = 0;
51
 	unsigned int i = 0;
68
 	uint8_t sum = 0;
52
 	uint8_t sum = 0;
69
 
53
 
147
  * @ret table		Table, or UNULL if not found
131
  * @ret table		Table, or UNULL if not found
148
  */
132
  */
149
 userptr_t acpi_find ( userptr_t rsdt, uint32_t signature, unsigned int index ) {
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
 	struct acpi_rsdt *rsdtab;
135
 	struct acpi_rsdt *rsdtab;
152
 	typeof ( rsdtab->entry[0] ) entry;
136
 	typeof ( rsdtab->entry[0] ) entry;
153
 	userptr_t table;
137
 	userptr_t table;
227
  * the ACPI specification itself.
211
  * the ACPI specification itself.
228
  */
212
  */
229
 static int acpi_sx_zsdt ( userptr_t zsdt, uint32_t signature ) {
213
 static int acpi_sx_zsdt ( userptr_t zsdt, uint32_t signature ) {
230
-	struct acpi_description_header acpi;
214
+	struct acpi_header acpi;
231
 	union {
215
 	union {
232
 		uint32_t dword;
216
 		uint32_t dword;
233
 		uint8_t byte[4];
217
 		uint8_t byte[4];
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
  * @v intf		Interface
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
 	struct interface *dest;
355
 	struct interface *dest;
350
 	acpi_describe_TYPE ( void * ) *op =
356
 	acpi_describe_TYPE ( void * ) *op =
351
 		intf_get_dest_op ( intf, acpi_describe, &dest );
357
 		intf_get_dest_op ( intf, acpi_describe, &dest );
352
 	void *object = intf_object ( dest );
358
 	void *object = intf_object ( dest );
353
-	int rc;
359
+	struct acpi_descriptor *desc;
354
 
360
 
355
 	if ( op ) {
361
 	if ( op ) {
356
-		rc = op ( object, acpi, len );
362
+		desc = op ( object );
357
 	} else {
363
 	} else {
358
-		/* Default is to fail to describe */
359
-		rc = -EOPNOTSUPP;
364
+		desc = NULL;
360
 	}
365
 	}
361
 
366
 
362
 	intf_put ( dest );
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
  * @v drive		Drive number
38
  * @v drive		Drive number
39
  * @v uris		List of URIs
39
  * @v uris		List of URIs
40
  * @v count		Number of URIs
40
  * @v count		Number of URIs
41
+ * @v flags		Flags
41
  * @ret drive		Drive number, or negative error
42
  * @ret drive		Drive number, or negative error
42
  */
43
  */
43
 static int dummy_san_hook ( unsigned int drive, struct uri **uris,
44
 static int dummy_san_hook ( unsigned int drive, struct uri **uris,
44
-			    unsigned int count ) {
45
+			    unsigned int count, unsigned int flags ) {
45
 	struct san_device *sandev;
46
 	struct san_device *sandev;
46
 	int rc;
47
 	int rc;
47
 
48
 
51
 		rc = -ENOMEM;
52
 		rc = -ENOMEM;
52
 		goto err_alloc;
53
 		goto err_alloc;
53
 	}
54
 	}
54
-	sandev->drive = drive;
55
 
55
 
56
 	/* Register SAN device */
56
 	/* Register SAN device */
57
-	if ( ( rc = register_sandev ( sandev ) ) != 0 ) {
57
+	if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
58
 		DBGC ( sandev, "SAN %#02x could not register: %s\n",
58
 		DBGC ( sandev, "SAN %#02x could not register: %s\n",
59
 		       sandev->drive, strerror ( rc ) );
59
 		       sandev->drive, strerror ( rc ) );
60
 		goto err_register;
60
 		goto err_register;
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
 	return 0;
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
 PROVIDE_SANBOOT ( dummy, san_hook, dummy_san_hook );
127
 PROVIDE_SANBOOT ( dummy, san_hook, dummy_san_hook );
115
 PROVIDE_SANBOOT ( dummy, san_unhook, dummy_san_unhook );
128
 PROVIDE_SANBOOT ( dummy, san_unhook, dummy_san_unhook );
116
 PROVIDE_SANBOOT ( dummy, san_boot, dummy_san_boot );
129
 PROVIDE_SANBOOT ( dummy, san_boot, dummy_san_boot );

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

28
 
28
 
29
 static int null_san_hook ( unsigned int drive __unused,
29
 static int null_san_hook ( unsigned int drive __unused,
30
 			   struct uri **uris __unused,
30
 			   struct uri **uris __unused,
31
-			   unsigned int count __unused ) {
31
+			   unsigned int count __unused,
32
+			   unsigned int flags __unused ) {
32
 	return -EOPNOTSUPP;
33
 	return -EOPNOTSUPP;
33
 }
34
 }
34
 
35
 
40
 	return -EOPNOTSUPP;
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
 	return -EOPNOTSUPP;
45
 	return -EOPNOTSUPP;
45
 }
46
 }
46
 
47
 

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

119
 	assert ( ! timer_running ( &sandev->timer ) );
119
 	assert ( ! timer_running ( &sandev->timer ) );
120
 	assert ( ! sandev->active );
120
 	assert ( ! sandev->active );
121
 	assert ( list_empty ( &sandev->opened ) );
121
 	assert ( list_empty ( &sandev->opened ) );
122
-	for ( i = 0 ; i < sandev->paths ; i++ )
122
+	for ( i = 0 ; i < sandev->paths ; i++ ) {
123
 		uri_put ( sandev->path[i].uri );
123
 		uri_put ( sandev->path[i].uri );
124
+		assert ( sandev->path[i].desc == NULL );
125
+	}
124
 	free ( sandev );
126
 	free ( sandev );
125
 }
127
 }
126
 
128
 
199
 		return rc;
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
 	/* Start process */
213
 	/* Start process */
203
 	process_add ( &sanpath->process );
214
 	process_add ( &sanpath->process );
204
 
215
 
606
 	return 0;
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
  * Configure SAN device as a CD-ROM, if applicable
687
  * Configure SAN device as a CD-ROM, if applicable
611
  *
688
  *
729
  * Register SAN device
806
  * Register SAN device
730
  *
807
  *
731
  * @v sandev		SAN device
808
  * @v sandev		SAN device
809
+ * @v drive		Drive number
810
+ * @v flags		Flags
732
  * @ret rc		Return status code
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
 	int rc;
815
 	int rc;
736
 
816
 
737
 	/* Check that drive number is not in use */
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
 		rc = -EADDRINUSE;
820
 		rc = -EADDRINUSE;
741
 		goto err_in_use;
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
 	/* Check that device is capable of being opened (i.e. that all
828
 	/* Check that device is capable of being opened (i.e. that all
745
 	 * URIs are well-formed and that at least one path is
829
 	 * URIs are well-formed and that at least one path is
746
 	 * working).
830
 	 * working).
748
 	if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
832
 	if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
749
 		goto err_reopen;
833
 		goto err_reopen;
750
 
834
 
835
+	/* Describe device */
836
+	if ( ( rc = sandev_describe ( sandev ) ) != 0 )
837
+		goto err_describe;
838
+
751
 	/* Read device capacity */
839
 	/* Read device capacity */
752
 	if ( ( rc = sandev_command ( sandev, sandev_command_read_capacity,
840
 	if ( ( rc = sandev_command ( sandev, sandev_command_read_capacity,
753
 				     NULL ) ) != 0 )
841
 				     NULL ) ) != 0 )
766
 	list_del ( &sandev->list );
854
 	list_del ( &sandev->list );
767
  err_iso9660:
855
  err_iso9660:
768
  err_capacity:
856
  err_capacity:
857
+ err_describe:
769
  err_reopen:
858
  err_reopen:
770
 	sandev_restart ( sandev, rc );
859
 	sandev_restart ( sandev, rc );
860
+	sandev_undescribe ( sandev );
771
  err_in_use:
861
  err_in_use:
772
 	return rc;
862
 	return rc;
773
 }
863
 }
788
 	/* Shut down interfaces */
878
 	/* Shut down interfaces */
789
 	sandev_restart ( sandev, 0 );
879
 	sandev_restart ( sandev, 0 );
790
 
880
 
881
+	/* Remove ACPI descriptors */
882
+	sandev_undescribe ( sandev );
883
+
791
 	DBGC ( sandev, "SAN %#02x unregistered\n", sandev->drive );
884
 	DBGC ( sandev, "SAN %#02x unregistered\n", sandev->drive );
792
 }
885
 }
793
 
886
 

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

28
 FILE_LICENCE ( BSD2 );
28
 FILE_LICENCE ( BSD2 );
29
 
29
 
30
 #include <stdint.h>
30
 #include <stdint.h>
31
+#include <stdlib.h>
31
 #include <stdio.h>
32
 #include <stdio.h>
32
 #include <string.h>
33
 #include <string.h>
33
 #include <errno.h>
34
 #include <errno.h>
38
 #include <ipxe/netdevice.h>
39
 #include <ipxe/netdevice.h>
39
 #include <ipxe/ethernet.h>
40
 #include <ipxe/ethernet.h>
40
 #include <ipxe/vlan.h>
41
 #include <ipxe/vlan.h>
42
+#include <ipxe/tcpip.h>
41
 #include <ipxe/dhcp.h>
43
 #include <ipxe/dhcp.h>
42
 #include <ipxe/iscsi.h>
44
 #include <ipxe/iscsi.h>
43
 #include <ipxe/ibft.h>
45
 #include <ipxe/ibft.h>
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
  * This is an internal structure that we use to keep track of the
61
  * This is an internal structure that we use to keep track of the
77
  * allocation of string data.
62
  * allocation of string data.
78
  */
63
  */
79
 struct ibft_strings {
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
 	size_t len;
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
  * Fill in an IP address field within iBFT
85
  * Fill in an IP address field within iBFT
90
  *
86
  *
141
  */
137
  */
142
 static char * ibft_alloc_string ( struct ibft_strings *strings,
138
 static char * ibft_alloc_string ( struct ibft_strings *strings,
143
 				  struct ibft_string *string, size_t len ) {
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
 		return NULL;
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
 	string->len = cpu_to_le16 ( len );
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
  */
227
  */
218
 static const char * ibft_string ( struct ibft_strings *strings,
228
 static const char * ibft_string ( struct ibft_strings *strings,
219
 				  struct ibft_string *string ) {
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
 	nic->header.length = cpu_to_le16 ( sizeof ( *nic ) );
275
 	nic->header.length = cpu_to_le16 ( sizeof ( *nic ) );
246
 	nic->header.flags = ( IBFT_FL_NIC_BLOCK_VALID |
276
 	nic->header.flags = ( IBFT_FL_NIC_BLOCK_VALID |
247
 			      IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED );
277
 			      IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED );
278
+	DBG ( "iBFT NIC %d is %s\n", nic->header.index, netdev->name );
248
 
279
 
249
 	/* Determine origin of IP address */
280
 	/* Determine origin of IP address */
250
 	fetch_setting ( parent, &ip_setting, &origin, NULL, NULL, 0 );
281
 	fetch_setting ( parent, &ip_setting, &origin, NULL, NULL, 0 );
251
 	nic->origin = ( ( origin == parent ) ?
282
 	nic->origin = ( ( origin == parent ) ?
252
 			IBFT_NIC_ORIGIN_MANUAL : IBFT_NIC_ORIGIN_DHCP );
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
 	/* Extract values from configuration settings */
286
 	/* Extract values from configuration settings */
256
 	ibft_set_ipaddr_setting ( parent, &nic->ip_address, &ip_setting, 1 );
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
 	ibft_set_ipaddr_setting ( parent, &nic->gateway, &gateway_setting, 1 );
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
 	ibft_set_ipaddr_setting ( NULL, &nic->dns[0], &dns_setting,
293
 	ibft_set_ipaddr_setting ( NULL, &nic->dns[0], &dns_setting,
261
 				  ( sizeof ( nic->dns ) /
294
 				  ( sizeof ( nic->dns ) /
262
 				    sizeof ( nic->dns[0] ) ) );
295
 				    sizeof ( nic->dns[0] ) ) );
263
 	ibft_set_ipaddr_setting ( parent, &nic->dhcp, &dhcp_server_setting, 1 );
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
 	DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) );
299
 	DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) );
266
 	if ( ( rc = ibft_set_string_setting ( NULL, strings, &nic->hostname,
300
 	if ( ( rc = ibft_set_string_setting ( NULL, strings, &nic->hostname,
267
 					      &hostname_setting ) ) != 0 )
301
 					      &hostname_setting ) ) != 0 )
268
 		return rc;
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
 	/* Derive subnet mask prefix from subnet mask */
306
 	/* Derive subnet mask prefix from subnet mask */
273
 	fetch_ipv4_setting ( parent, &netmask_setting, &netmask_addr );
307
 	fetch_ipv4_setting ( parent, &netmask_setting, &netmask_addr );
277
 		netmask_addr.s_addr >>= 1;
311
 		netmask_addr.s_addr >>= 1;
278
 	}
312
 	}
279
 	nic->subnet_mask_prefix = netmask_count;
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
 	/* Extract values from net-device configuration */
317
 	/* Extract values from net-device configuration */
283
 	nic->vlan = cpu_to_le16 ( vlan_tag ( netdev ) );
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
 	if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr,
321
 	if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr,
286
 					    nic->mac_address ) ) != 0 ) {
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
 		return rc;
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
 	nic->pci_bus_dev_func = cpu_to_le16 ( netdev->dev->desc.location );
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
 	return 0;
333
 	return 0;
295
 }
334
 }
299
  *
338
  *
300
  * @v initiator		Initiator portion of iBFT
339
  * @v initiator		Initiator portion of iBFT
301
  * @v strings		iBFT string block descriptor
340
  * @v strings		iBFT string block descriptor
302
- * @v iscsi		iSCSI session
303
  * @ret rc		Return status code
341
  * @ret rc		Return status code
304
  */
342
  */
305
 static int ibft_fill_initiator ( struct ibft_initiator *initiator,
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
 	int rc;
345
 	int rc;
309
 
346
 
310
 	/* Fill in common header */
347
 	/* Fill in common header */
314
 	initiator->header.flags = ( IBFT_FL_INITIATOR_BLOCK_VALID |
351
 	initiator->header.flags = ( IBFT_FL_INITIATOR_BLOCK_VALID |
315
 				    IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED );
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
 		return rc;
358
 		return rc;
321
-	DBG ( "iBFT initiator hostname = %s\n",
359
+	DBG ( "iBFT initiator name = %s\n",
322
 	      ibft_string ( strings, &initiator->initiator_name ) );
360
 	      ibft_string ( strings, &initiator->initiator_name ) );
323
 
361
 
324
 	return 0;
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
  * Fill in Target CHAP portion of iBFT
406
  * Fill in Target CHAP portion of iBFT
329
  *
407
  *
347
 	if ( ( rc = ibft_set_string ( strings, &target->chap_name,
425
 	if ( ( rc = ibft_set_string ( strings, &target->chap_name,
348
 				      iscsi->initiator_username ) ) != 0 )
426
 				      iscsi->initiator_username ) ) != 0 )
349
 		return rc;
427
 		return rc;
350
-	DBG ( "iBFT target username = %s\n",
428
+	DBG ( "iBFT target %d username = %s\n", target->header.index,
351
 	      ibft_string ( strings, &target->chap_name ) );
429
 	      ibft_string ( strings, &target->chap_name ) );
352
 	if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
430
 	if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
353
 				      iscsi->initiator_password ) ) != 0 )
431
 				      iscsi->initiator_password ) ) != 0 )
354
 		return rc;
432
 		return rc;
355
-	DBG ( "iBFT target password = <redacted>\n" );
433
+	DBG ( "iBFT target %d password = <redacted>\n", target->header.index );
356
 
434
 
357
 	return 0;
435
 	return 0;
358
 }
436
 }
382
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
460
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
383
 				      iscsi->target_username ) ) != 0 )
461
 				      iscsi->target_username ) ) != 0 )
384
 		return rc;
462
 		return rc;
385
-	DBG ( "iBFT target reverse username = %s\n",
463
+	DBG ( "iBFT target %d reverse username = %s\n", target->header.index,
386
 	      ibft_string ( strings, &target->chap_name ) );
464
 	      ibft_string ( strings, &target->chap_name ) );
387
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
465
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
388
 				      iscsi->target_password ) ) != 0 )
466
 				      iscsi->target_password ) ) != 0 )
389
 		return rc;
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
 	return 0;
471
 	return 0;
393
 }
472
 }
403
 static int ibft_fill_target ( struct ibft_target *target,
482
 static int ibft_fill_target ( struct ibft_target *target,
404
 			      struct ibft_strings *strings,
483
 			      struct ibft_strings *strings,
405
 			      struct iscsi_session *iscsi ) {
484
 			      struct iscsi_session *iscsi ) {
485
+	struct sockaddr_tcpip *st_target =
486
+		( struct sockaddr_tcpip * ) &iscsi->target_sockaddr;
406
 	struct sockaddr_in *sin_target =
487
 	struct sockaddr_in *sin_target =
407
 		( struct sockaddr_in * ) &iscsi->target_sockaddr;
488
 		( struct sockaddr_in * ) &iscsi->target_sockaddr;
408
 	int rc;
489
 	int rc;
416
 
497
 
417
 	/* Fill in Target values */
498
 	/* Fill in Target values */
418
 	ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
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
 	memcpy ( &target->boot_lun, &iscsi->lun, sizeof ( target->boot_lun ) );
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
 	if ( ( rc = ibft_set_string ( strings, &target->target_name,
508
 	if ( ( rc = ibft_set_string ( strings, &target->target_name,
426
 				      iscsi->target_iqn ) ) != 0 )
509
 				      iscsi->target_iqn ) ) != 0 )
427
 		return rc;
510
 		return rc;
428
-	DBG ( "iBFT target name = %s\n",
511
+	DBG ( "iBFT target %d name = %s\n", target->header.index,
429
 	      ibft_string ( strings, &target->target_name ) );
512
 	      ibft_string ( strings, &target->target_name ) );
513
+	if ( ( rc = ibft_fill_target_nic_association ( target, iscsi ) ) != 0 )
514
+		return rc;
430
 	if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
515
 	if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
431
 		return rc;
516
 		return rc;
432
 	if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,
517
 	if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,
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
  * @ret rc		Return status code
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
 	struct net_device *netdev;
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
 	int rc;
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
 	/* Fill in Control block */
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
 	/** Login completed successfully */
113
 	/** Login completed successfully */
114
 	int logged_in;
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
 	/** List of active commands */
116
 	/** List of active commands */
124
 	struct list_head commands;
117
 	struct list_head commands;
125
 };
118
 };
684
 	return ( srpdev->logged_in ? ~( ( size_t ) 0 ) : 0 );
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
 /** SRP device socket interface operations */
680
 /** SRP device socket interface operations */
743
 static struct interface_operation srpdev_socket_op[] = {
681
 static struct interface_operation srpdev_socket_op[] = {
744
 	INTF_OP ( xfer_deliver, struct srp_device *, srpdev_deliver ),
682
 	INTF_OP ( xfer_deliver, struct srp_device *, srpdev_deliver ),
755
 	INTF_OP ( scsi_command, struct srp_device *, srpdev_scsi_command ),
693
 	INTF_OP ( scsi_command, struct srp_device *, srpdev_scsi_command ),
756
 	INTF_OP ( xfer_window, struct srp_device *, srpdev_window ),
694
 	INTF_OP ( xfer_window, struct srp_device *, srpdev_window ),
757
 	INTF_OP ( intf_close, struct srp_device *, srpdev_close ),
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
 /** SRP device SCSI interface descriptor */
698
 /** SRP device SCSI interface descriptor */
797
 	       ntohl ( target->dwords[0] ), ntohl ( target->dwords[1] ),
734
 	       ntohl ( target->dwords[0] ), ntohl ( target->dwords[1] ),
798
 	       ntohl ( target->dwords[2] ), ntohl ( target->dwords[3] ) );
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
 	/* Attach to socket interface and initiate login */
737
 	/* Attach to socket interface and initiate login */
806
 	intf_plug_plug ( &srpdev->socket, socket );
738
 	intf_plug_plug ( &srpdev->socket, socket );
807
 	tag = srp_new_tag ( srpdev );
739
 	tag = srp_new_tag ( srpdev );

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

10
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
10
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
 
11
 
12
 #include <stdint.h>
12
 #include <stdint.h>
13
+#include <byteswap.h>
14
+#include <ipxe/refcnt.h>
15
+#include <ipxe/list.h>
13
 #include <ipxe/interface.h>
16
 #include <ipxe/interface.h>
14
 #include <ipxe/uaccess.h>
17
 #include <ipxe/uaccess.h>
18
+#include <ipxe/tables.h>
15
 
19
 
16
 /**
20
 /**
17
  * An ACPI description header
21
  * An ACPI description header
19
  * This is the structure common to the start of all ACPI system
23
  * This is the structure common to the start of all ACPI system
20
  * description tables.
24
  * description tables.
21
  */
25
  */
22
-struct acpi_description_header {
26
+struct acpi_header {
23
 	/** ACPI signature (4 ASCII characters) */
27
 	/** ACPI signature (4 ASCII characters) */
24
 	uint32_t signature;
28
 	uint32_t signature;
25
 	/** Length of table, in bytes, including header */
29
 	/** Length of table, in bytes, including header */
40
 	uint32_t asl_compiler_revision;
44
 	uint32_t asl_compiler_revision;
41
 } __attribute__ (( packed ));
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
  * Build ACPI signature
64
  * Build ACPI signature
45
  *
65
  *
87
 /** ACPI Root System Description Table (RSDT) */
107
 /** ACPI Root System Description Table (RSDT) */
88
 struct acpi_rsdt {
108
 struct acpi_rsdt {
89
 	/** ACPI header */
109
 	/** ACPI header */
90
-	struct acpi_description_header acpi;
110
+	struct acpi_header acpi;
91
 	/** ACPI table entries */
111
 	/** ACPI table entries */
92
 	uint32_t entry[0];
112
 	uint32_t entry[0];
93
 } __attribute__ (( packed ));
113
 } __attribute__ (( packed ));
98
 /** Fixed ACPI Description Table (FADT) */
118
 /** Fixed ACPI Description Table (FADT) */
99
 struct acpi_fadt {
119
 struct acpi_fadt {
100
 	/** ACPI header */
120
 	/** ACPI header */
101
-	struct acpi_description_header acpi;
121
+	struct acpi_header acpi;
102
 	/** Physical address of FACS */
122
 	/** Physical address of FACS */
103
 	uint32_t facs;
123
 	uint32_t facs;
104
 	/** Physical address of DSDT */
124
 	/** Physical address of DSDT */
122
 /** Secondary System Description Table (SSDT) signature */
142
 /** Secondary System Description Table (SSDT) signature */
123
 #define SSDT_SIGNATURE ACPI_SIGNATURE ( 'S', 'S', 'D', 'T' )
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
 #define acpi_describe_TYPE( object_type )				\
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
 extern userptr_t acpi_find_rsdt ( userptr_t ebda );
203
 extern userptr_t acpi_find_rsdt ( userptr_t ebda );
134
 extern userptr_t acpi_find ( userptr_t rsdt, uint32_t signature,
204
 extern userptr_t acpi_find ( userptr_t rsdt, uint32_t signature,
135
 			     unsigned int index );
205
 			     unsigned int index );
136
 extern int acpi_sx ( userptr_t rsdt, uint32_t signature );
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
 #endif /* _IPXE_ACPI_H */
211
 #endif /* _IPXE_ACPI_H */

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

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

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

49
 /** iSCSI Boot Firmware Table signature */
49
 /** iSCSI Boot Firmware Table signature */
50
 #define IBFT_SIG ACPI_SIGNATURE ( 'i', 'B', 'F', 'T' )
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
 /** An offset from the start of the iBFT */
55
 /** An offset from the start of the iBFT */
53
 typedef uint16_t ibft_off_t;
56
 typedef uint16_t ibft_off_t;
54
 
57
 
97
 	uint8_t flags;
100
 	uint8_t flags;
98
 } __attribute__ (( packed ));
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
  * iBFT Control structure
118
  * iBFT Control structure
102
  *
119
  *
108
 	uint16_t extensions;
125
 	uint16_t extensions;
109
 	/** Offset to Initiator structure */
126
 	/** Offset to Initiator structure */
110
 	ibft_off_t initiator;
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
 } __attribute__ (( packed ));
130
 } __attribute__ (( packed ));
120
 
131
 
121
 /** Structure ID for Control section */
132
 /** Structure ID for Control section */
262
  */
273
  */
263
 struct ibft_table {
274
 struct ibft_table {
264
 	/** ACPI header */
275
 	/** ACPI header */
265
-	struct acpi_description_header acpi;
276
+	struct acpi_header acpi;
266
 	/** Reserved */
277
 	/** Reserved */
267
 	uint8_t reserved[12];
278
 	uint8_t reserved[12];
268
 	/** Control structure */
279
 	/** Control structure */
269
 	struct ibft_control control;
280
 	struct ibft_control control;
270
 } __attribute__ (( packed ));
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
 #endif /* _IPXE_IBFT_H */
285
 #endif /* _IPXE_IBFT_H */

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

16
 #include <ipxe/refcnt.h>
16
 #include <ipxe/refcnt.h>
17
 #include <ipxe/xfer.h>
17
 #include <ipxe/xfer.h>
18
 #include <ipxe/process.h>
18
 #include <ipxe/process.h>
19
+#include <ipxe/acpi.h>
20
+#include <ipxe/settings.h>
19
 
21
 
20
 /** Default iSCSI port */
22
 /** Default iSCSI port */
21
 #define ISCSI_PORT 3260
23
 #define ISCSI_PORT 3260
647
 	struct sockaddr target_sockaddr;
649
 	struct sockaddr target_sockaddr;
648
 	/** SCSI LUN (for boot firmware table) */
650
 	/** SCSI LUN (for boot firmware table) */
649
 	struct scsi_lun lun;
651
 	struct scsi_lun lun;
652
+	/** ACPI descriptor */
653
+	struct acpi_descriptor desc;
650
 };
654
 };
651
 
655
 
652
 /** iSCSI session is currently in the security negotiation phase */
656
 /** iSCSI session is currently in the security negotiation phase */
697
 /** Default initiator IQN prefix */
701
 /** Default initiator IQN prefix */
698
 #define ISCSI_DEFAULT_IQN_PREFIX "iqn.2010-04.org.ipxe"
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
 #endif /* _IPXE_ISCSI_H */
707
 #endif /* _IPXE_ISCSI_H */

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

18
 #include <ipxe/retry.h>
18
 #include <ipxe/retry.h>
19
 #include <ipxe/process.h>
19
 #include <ipxe/process.h>
20
 #include <ipxe/blockdev.h>
20
 #include <ipxe/blockdev.h>
21
+#include <ipxe/acpi.h>
21
 #include <config/sanboot.h>
22
 #include <config/sanboot.h>
22
 
23
 
23
 /** A SAN path */
24
 /** A SAN path */
37
 	struct process process;
38
 	struct process process;
38
 	/** Path status */
39
 	/** Path status */
39
 	int path_rc;
40
 	int path_rc;
41
+
42
+	/** ACPI descriptor (if applicable) */
43
+	struct acpi_descriptor *desc;
40
 };
44
 };
41
 
45
 
42
 /** A SAN device */
46
 /** A SAN device */
48
 
52
 
49
 	/** Drive number */
53
 	/** Drive number */
50
 	unsigned int drive;
54
 	unsigned int drive;
55
+	/** Flags */
56
+	unsigned int flags;
51
 
57
 
52
 	/** Command interface */
58
 	/** Command interface */
53
 	struct interface command;
59
 	struct interface command;
83
 	struct san_path path[0];
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
  * Calculate static inline sanboot API function name
99
  * Calculate static inline sanboot API function name
88
  *
100
  *
126
  * @v drive		Drive number
138
  * @v drive		Drive number
127
  * @v uris		List of URIs
139
  * @v uris		List of URIs
128
  * @v count		Number of URIs
140
  * @v count		Number of URIs
141
+ * @v flags		Flags
129
  * @ret drive		Drive number, or negative error
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
  * Unhook SAN device
148
  * Unhook SAN device
146
 int san_boot ( unsigned int drive );
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
  * @ret rc		Return status code
165
  * @ret rc		Return status code
153
  */
166
  */
154
-int san_describe ( unsigned int drive );
167
+int san_describe ( void );
155
 
168
 
156
 extern struct list_head san_devices;
169
 extern struct list_head san_devices;
157
 
170
 
230
 					    userptr_t buffer, size_t len ) );
243
 					    userptr_t buffer, size_t len ) );
231
 extern struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
244
 extern struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
232
 					  size_t priv_size );
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
 extern void unregister_sandev ( struct san_device *sandev );
248
 extern void unregister_sandev ( struct san_device *sandev );
235
 extern unsigned int san_default_drive ( void );
249
 extern unsigned int san_default_drive ( void );
236
 
250
 

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

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

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

254
  * @v drive		Drive number
254
  * @v drive		Drive number
255
  * @v uris		List of URIs
255
  * @v uris		List of URIs
256
  * @v count		Number of URIs
256
  * @v count		Number of URIs
257
+ * @v flags		Flags
257
  * @ret drive		Drive number, or negative error
258
  * @ret drive		Drive number, or negative error
258
  */
259
  */
259
 static int efi_block_hook ( unsigned int drive, struct uri **uris,
260
 static int efi_block_hook ( unsigned int drive, struct uri **uris,
260
-			    unsigned int count ) {
261
+			    unsigned int count, unsigned int flags ) {
261
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
262
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
262
 	EFI_DEVICE_PATH_PROTOCOL *end;
263
 	EFI_DEVICE_PATH_PROTOCOL *end;
263
 	struct efi_block_vendor_path *vendor;
264
 	struct efi_block_vendor_path *vendor;
301
 		rc = -ENOMEM;
302
 		rc = -ENOMEM;
302
 		goto err_alloc;
303
 		goto err_alloc;
303
 	}
304
 	}
304
-	sandev->drive = drive;
305
 	block = sandev->priv;
305
 	block = sandev->priv;
306
 	block->sandev = sandev;
306
 	block->sandev = sandev;
307
 	block->media.MediaPresent = 1;
307
 	block->media.MediaPresent = 1;
331
 	end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
331
 	end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
332
 	end->Length[0] = sizeof ( *end );
332
 	end->Length[0] = sizeof ( *end );
333
 	DBGC ( sandev, "EFIBLK %#02x has device path %s\n",
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
 	/* Register SAN device */
336
 	/* Register SAN device */
337
-	if ( ( rc = register_sandev ( sandev ) ) != 0 ) {
337
+	if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
338
 		DBGC ( sandev, "EFIBLK %#02x could not register: %s\n",
338
 		DBGC ( sandev, "EFIBLK %#02x could not register: %s\n",
339
-		       sandev->drive, strerror ( rc ) );
339
+		       drive, strerror ( rc ) );
340
 		goto err_register;
340
 		goto err_register;
341
 	}
341
 	}
342
 
342
 
408
 	sandev_put ( sandev );
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
  * @ret rc		Return status code
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
 	EFI_STATUS efirc;
431
 	EFI_STATUS efirc;
429
 	int rc;
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
 	/* Sanity check */
486
 	/* Sanity check */
439
 	if ( ! acpi ) {
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
 		return -ENOTSUP;
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
 		if ( ( efirc = acpi->UninstallAcpiTable ( acpi, key ) ) != 0 ) {
495
 		if ( ( efirc = acpi->UninstallAcpiTable ( acpi, key ) ) != 0 ) {
448
 			rc = -EEFI ( efirc );
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
 			/* Continue anyway */
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
 		return rc;
510
 		return rc;
491
 	}
511
 	}
492
 
512
 

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

53
 FEATURE ( FEATURE_PROTOCOL, "AoE", DHCP_EB_FEATURE_AOE, 1 );
53
 FEATURE ( FEATURE_PROTOCOL, "AoE", DHCP_EB_FEATURE_AOE, 1 );
54
 
54
 
55
 struct net_protocol aoe_protocol __net_protocol;
55
 struct net_protocol aoe_protocol __net_protocol;
56
+struct acpi_model abft_model __acpi_model;
56
 
57
 
57
 /******************************************************************************
58
 /******************************************************************************
58
  *
59
  *
91
 	struct interface config;
92
 	struct interface config;
92
 	/** Device is configued */
93
 	/** Device is configued */
93
 	int configured;
94
 	int configured;
95
+
96
+	/** ACPI descriptor */
97
+	struct acpi_descriptor desc;
94
 };
98
 };
95
 
99
 
96
 /** An AoE command */
100
 /** An AoE command */
790
 }
794
 }
791
 
795
 
792
 /**
796
 /**
793
- * Describe AoE device in an ACPI table
797
+ * Get AoE ACPI descriptor
794
  *
798
  *
795
  * @v aoedev		AoE device
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
 /** AoE device ATA interface operations */
806
 /** AoE device ATA interface operations */
869
 	aoedev->minor = minor;
854
 	aoedev->minor = minor;
870
 	memcpy ( aoedev->target, netdev->ll_broadcast,
855
 	memcpy ( aoedev->target, netdev->ll_broadcast,
871
 		 netdev->ll_protocol->ll_addr_len );
856
 		 netdev->ll_protocol->ll_addr_len );
857
+	acpi_init ( &aoedev->desc, &abft_model, &aoedev->refcnt );
872
 
858
 
873
 	/* Initiate configuration */
859
 	/* Initiate configuration */
874
 	if ( ( rc = aoedev_cfg_command ( aoedev, &aoedev->config ) ) < 0 ) {
860
 	if ( ( rc = aoedev_cfg_command ( aoedev, &aoedev->config ) ) < 0 ) {
1059
 	.scheme = "aoe",
1045
 	.scheme = "aoe",
1060
 	.open = aoe_open,
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
 		 ~( ( size_t ) 0 ) : 0 );
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
  * Describe FCP device using EDD
847
  * Describe FCP device using EDD
867
  *
848
  *
917
 	INTF_OP ( scsi_command, struct fcp_device *, fcpdev_scsi_command ),
898
 	INTF_OP ( scsi_command, struct fcp_device *, fcpdev_scsi_command ),
918
 	INTF_OP ( xfer_window, struct fcp_device *, fcpdev_window ),
899
 	INTF_OP ( xfer_window, struct fcp_device *, fcpdev_window ),
919
 	INTF_OP ( intf_close, struct fcp_device *, fcpdev_close ),
900
 	INTF_OP ( intf_close, struct fcp_device *, fcpdev_close ),
920
-	INTF_OP ( acpi_describe, struct fcp_device *, fcpdev_acpi_describe ),
921
 	INTF_OP ( edd_describe, struct fcp_device *, fcpdev_edd_describe ),
901
 	INTF_OP ( edd_describe, struct fcp_device *, fcpdev_edd_describe ),
922
 	INTF_OP ( identify_device, struct fcp_device *,
902
 	INTF_OP ( identify_device, struct fcp_device *,
923
 		  fcpdev_identify_device ),
903
 		  fcpdev_identify_device ),

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

60
 #define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \
60
 #define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \
61
 	( EINFO_EINVAL, 0x04, "Root path too short" )
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
  * IB SRP devices
67
  * IB SRP devices
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
 /** An Infiniband SRP device */
86
 /** An Infiniband SRP device */
71
 struct ib_srp_device {
87
 struct ib_srp_device {
72
 	/** Reference count */
88
 	/** Reference count */
80
 	/** Infiniband device */
96
 	/** Infiniband device */
81
 	struct ib_device *ibdev;
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
 }
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
 /** IB SRP CMRC interface operations */
143
 /** IB SRP CMRC interface operations */
188
 			 union srp_port_id *initiator,
176
 			 union srp_port_id *initiator,
189
 			 union srp_port_id *target, struct scsi_lun *lun ) {
177
 			 union srp_port_id *target, struct scsi_lun *lun ) {
190
 	struct ib_srp_device *ib_srp;
178
 	struct ib_srp_device *ib_srp;
179
+	struct ipxe_ib_sbft *sbft;
191
 	int rc;
180
 	int rc;
192
 
181
 
193
 	/* Allocate and initialise structure */
182
 	/* Allocate and initialise structure */
200
 	intf_init ( &ib_srp->srp, &ib_srp_srp_desc, &ib_srp->refcnt );
189
 	intf_init ( &ib_srp->srp, &ib_srp_srp_desc, &ib_srp->refcnt );
201
 	intf_init ( &ib_srp->cmrc, &ib_srp_cmrc_desc, &ib_srp->refcnt );
190
 	intf_init ( &ib_srp->cmrc, &ib_srp_cmrc_desc, &ib_srp->refcnt );
202
 	ib_srp->ibdev = ibdev_get ( ibdev );
191
 	ib_srp->ibdev = ibdev_get ( ibdev );
192
+	acpi_init ( &ib_srp->desc, &ib_sbft_model, &ib_srp->refcnt );
203
 	DBGC ( ib_srp, "IBSRP %p for " IB_GID_FMT " " IB_GUID_FMT "\n",
193
 	DBGC ( ib_srp, "IBSRP %p for " IB_GID_FMT " " IB_GUID_FMT "\n",
204
 	       ib_srp, IB_GID_ARGS ( dgid ), IB_GUID_ARGS ( service_id ) );
194
 	       ib_srp, IB_GID_ARGS ( dgid ), IB_GUID_ARGS ( service_id ) );
205
 
195
 
206
 	/* Preserve parameters required for boot firmware table */
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
 	/* Open CMRC socket */
206
 	/* Open CMRC socket */
212
 	if ( ( rc = ib_cmrc_open ( &ib_srp->cmrc, ibdev, dgid,
207
 	if ( ( rc = ib_cmrc_open ( &ib_srp->cmrc, ibdev, dgid,
579
 	.scheme = "ib_srp",
574
 	.scheme = "ib_srp",
580
 	.open = ib_srp_open_uri,
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
  err_open:
114
  err_open:
115
 	return rc;
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
 	return -ENOTSUP;
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
 /** HTTP data transfer interface operations */
512
 /** HTTP data transfer interface operations */
528
 static struct interface_operation http_xfer_operations[] = {
513
 static struct interface_operation http_xfer_operations[] = {
529
 	INTF_OP ( block_read, struct http_transaction *, http_block_read ),
514
 	INTF_OP ( block_read, struct http_transaction *, http_block_read ),
530
 	INTF_OP ( block_read_capacity, struct http_transaction *,
515
 	INTF_OP ( block_read_capacity, struct http_transaction *,
531
 		  http_block_read_capacity ),
516
 		  http_block_read_capacity ),
532
-	INTF_OP ( acpi_describe, struct http_transaction *,
533
-		  http_acpi_describe ),
534
 	INTF_OP ( xfer_window_changed, struct http_transaction *, http_step ),
517
 	INTF_OP ( xfer_window_changed, struct http_transaction *, http_step ),
535
 	INTF_OP ( intf_close, struct http_transaction *, http_close ),
518
 	INTF_OP ( intf_close, struct http_transaction *, http_close ),
536
 };
519
 };

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

1810
 	return iscsi->itt;
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
 /** iSCSI SCSI command-issuing interface operations */
1824
 /** iSCSI SCSI command-issuing interface operations */
1814
 static struct interface_operation iscsi_control_op[] = {
1825
 static struct interface_operation iscsi_control_op[] = {
1815
 	INTF_OP ( scsi_command, struct iscsi_session *, iscsi_scsi_command ),
1826
 	INTF_OP ( scsi_command, struct iscsi_session *, iscsi_scsi_command ),
1816
 	INTF_OP ( xfer_window, struct iscsi_session *, iscsi_scsi_window ),
1827
 	INTF_OP ( xfer_window, struct iscsi_session *, iscsi_scsi_window ),
1817
 	INTF_OP ( intf_close, struct iscsi_session *, iscsi_close ),
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
 /** iSCSI SCSI command-issuing interface descriptor */
1832
 /** iSCSI SCSI command-issuing interface descriptor */
2064
 	intf_init ( &iscsi->socket, &iscsi_socket_desc, &iscsi->refcnt );
2075
 	intf_init ( &iscsi->socket, &iscsi_socket_desc, &iscsi->refcnt );
2065
 	process_init_stopped ( &iscsi->process, &iscsi_process_desc,
2076
 	process_init_stopped ( &iscsi->process, &iscsi_process_desc,
2066
 			       &iscsi->refcnt );
2077
 			       &iscsi->refcnt );
2078
+	acpi_init ( &iscsi->desc, &ibft_model, &iscsi->refcnt );
2067
 
2079
 
2068
 	/* Parse root path */
2080
 	/* Parse root path */
2069
 	if ( ( rc = iscsi_parse_root_path ( iscsi, uri->opaque ) ) != 0 )
2081
 	if ( ( rc = iscsi_parse_root_path ( iscsi, uri->opaque ) ) != 0 )

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

128
 
128
 
129
 	/* Hook SAN device, if applicable */
129
 	/* Hook SAN device, if applicable */
130
 	if ( root_path_count ) {
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
 		if ( drive < 0 ) {
134
 		if ( drive < 0 ) {
133
 			rc = drive;
135
 			rc = drive;
134
 			printf ( "Could not open SAN device: %s\n",
136
 			printf ( "Could not open SAN device: %s\n",
140
 
142
 
141
 	/* Describe SAN device, if applicable */
143
 	/* Describe SAN device, if applicable */
142
 	if ( ! ( flags & URIBOOT_NO_SAN_DESCRIBE ) ) {
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
 			goto err_san_describe;
148
 			goto err_san_describe;
147
 		}
149
 		}
148
 	}
150
 	}

Loading…
Cancel
Save