summaryrefslogtreecommitdiffstats
path: root/src/include
diff options
context:
space:
mode:
authorMichael Brown2017-03-27 17:20:34 +0200
committerMichael Brown2017-03-28 18:12:48 +0200
commit7cfdd769aac76d605aa31146c69ba518b194bea7 (patch)
tree7c09e144792833f81297e6dacf0823733a2a399a /src/include
parent[block] Ignore redundant xfer_window_changed() messages (diff)
downloadipxe-7cfdd769aac76d605aa31146c69ba518b194bea7.tar.gz
ipxe-7cfdd769aac76d605aa31146c69ba518b194bea7.tar.xz
ipxe-7cfdd769aac76d605aa31146c69ba518b194bea7.zip
[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>
Diffstat (limited to 'src/include')
-rw-r--r--src/include/ipxe/acpi.h91
-rw-r--r--src/include/ipxe/aoe.h2
-rw-r--r--src/include/ipxe/ibft.h36
-rw-r--r--src/include/ipxe/iscsi.h7
-rw-r--r--src/include/ipxe/sanboot.h24
-rw-r--r--src/include/ipxe/srp.h2
6 files changed, 131 insertions, 31 deletions
diff --git a/src/include/ipxe/acpi.h b/src/include/ipxe/acpi.h
index 17d29b9d..f87b8ae9 100644
--- a/src/include/ipxe/acpi.h
+++ b/src/include/ipxe/acpi.h
@@ -10,8 +10,12 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
+#include <byteswap.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/list.h>
#include <ipxe/interface.h>
#include <ipxe/uaccess.h>
+#include <ipxe/tables.h>
/**
* An ACPI description header
@@ -19,7 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* This is the structure common to the start of all ACPI system
* description tables.
*/
-struct acpi_description_header {
+struct acpi_header {
/** ACPI signature (4 ASCII characters) */
uint32_t signature;
/** Length of table, in bytes, including header */
@@ -41,6 +45,22 @@ struct acpi_description_header {
} __attribute__ (( packed ));
/**
+ * Transcribe ACPI table signature (for debugging)
+ *
+ * @v signature ACPI table signature
+ * @ret name ACPI table signature name
+ */
+static inline const char * acpi_name ( uint32_t signature ) {
+ static union {
+ uint32_t signature;
+ char name[5];
+ } u;
+
+ u.signature = cpu_to_le32 ( signature );
+ return u.name;
+}
+
+/**
* Build ACPI signature
*
* @v a First character of ACPI signature
@@ -87,7 +107,7 @@ struct acpi_rsdp {
/** ACPI Root System Description Table (RSDT) */
struct acpi_rsdt {
/** ACPI header */
- struct acpi_description_header acpi;
+ struct acpi_header acpi;
/** ACPI table entries */
uint32_t entry[0];
} __attribute__ (( packed ));
@@ -98,7 +118,7 @@ struct acpi_rsdt {
/** Fixed ACPI Description Table (FADT) */
struct acpi_fadt {
/** ACPI header */
- struct acpi_description_header acpi;
+ struct acpi_header acpi;
/** Physical address of FACS */
uint32_t facs;
/** Physical address of DSDT */
@@ -122,17 +142,70 @@ struct acpi_fadt {
/** Secondary System Description Table (SSDT) signature */
#define SSDT_SIGNATURE ACPI_SIGNATURE ( 'S', 'S', 'D', 'T' )
-extern int acpi_describe ( struct interface *interface,
- struct acpi_description_header *acpi, size_t len );
+/** An ACPI descriptor (used to construct ACPI tables) */
+struct acpi_descriptor {
+ /** Reference count of containing object */
+ struct refcnt *refcnt;
+ /** Table model */
+ struct acpi_model *model;
+ /** List of ACPI descriptors for this model */
+ struct list_head list;
+};
+
+/**
+ * Initialise ACPI descriptor
+ *
+ * @v desc ACPI descriptor
+ * @v model Table model
+ * @v refcnt Reference count
+ */
+static inline __attribute__ (( always_inline )) void
+acpi_init ( struct acpi_descriptor *desc, struct acpi_model *model,
+ struct refcnt *refcnt ) {
+
+ desc->refcnt = refcnt;
+ desc->model = model;
+ INIT_LIST_HEAD ( &desc->list );
+}
+
+/** An ACPI table model */
+struct acpi_model {
+ /** List of descriptors */
+ struct list_head descs;
+ /**
+ * Check if ACPI descriptor is complete
+ *
+ * @v desc ACPI descriptor
+ * @ret rc Return status code
+ */
+ int ( * complete ) ( struct acpi_descriptor *desc );
+ /**
+ * Install ACPI tables
+ *
+ * @v install Installation method
+ * @ret rc Return status code
+ */
+ int ( * install ) ( int ( * install ) ( struct acpi_header *acpi ) );
+};
+
+/** ACPI models */
+#define ACPI_MODELS __table ( struct acpi_model, "acpi_models" )
+
+/** Declare an ACPI model */
+#define __acpi_model __table_entry ( ACPI_MODELS, 01 )
+
+extern struct acpi_descriptor *
+acpi_describe ( struct interface *interface );
#define acpi_describe_TYPE( object_type ) \
- typeof ( int ( object_type, \
- struct acpi_description_header *acpi, \
- size_t len ) )
+ typeof ( struct acpi_descriptor * ( object_type ) )
-extern void acpi_fix_checksum ( struct acpi_description_header *acpi );
+extern void acpi_fix_checksum ( struct acpi_header *acpi );
extern userptr_t acpi_find_rsdt ( userptr_t ebda );
extern userptr_t acpi_find ( userptr_t rsdt, uint32_t signature,
unsigned int index );
extern int acpi_sx ( userptr_t rsdt, uint32_t signature );
+extern void acpi_add ( struct acpi_descriptor *desc );
+extern void acpi_del ( struct acpi_descriptor *desc );
+extern int acpi_install ( int ( * install ) ( struct acpi_header *acpi ) );
#endif /* _IPXE_ACPI_H */
diff --git a/src/include/ipxe/aoe.h b/src/include/ipxe/aoe.h
index 0c656e7c..a51044d1 100644
--- a/src/include/ipxe/aoe.h
+++ b/src/include/ipxe/aoe.h
@@ -117,7 +117,7 @@ struct aoehdr {
*/
struct abft_table {
/** ACPI header */
- struct acpi_description_header acpi;
+ struct acpi_header acpi;
/** AoE shelf */
uint16_t shelf;
/** AoE slot */
diff --git a/src/include/ipxe/ibft.h b/src/include/ipxe/ibft.h
index 35f15105..51ce781a 100644
--- a/src/include/ipxe/ibft.h
+++ b/src/include/ipxe/ibft.h
@@ -49,6 +49,9 @@ FILE_LICENCE ( BSD2 );
/** iSCSI Boot Firmware Table signature */
#define IBFT_SIG ACPI_SIGNATURE ( 'i', 'B', 'F', 'T' )
+/** Alignment of structures within iBFT */
+#define IBFT_ALIGN 16
+
/** An offset from the start of the iBFT */
typedef uint16_t ibft_off_t;
@@ -98,6 +101,20 @@ struct ibft_header {
} __attribute__ (( packed ));
/**
+ * iBFT NIC and Target offset pair
+ *
+ * There is no implicit relation between the NIC and the Target, but
+ * using this structure simplifies the table construction code while
+ * matching the expected table layout.
+ */
+struct ibft_offset_pair {
+ /** Offset to NIC structure */
+ ibft_off_t nic;
+ /** Offset to Target structure */
+ ibft_off_t target;
+} __attribute__ (( packed ));
+
+/**
* iBFT Control structure
*
*/
@@ -108,14 +125,8 @@ struct ibft_control {
uint16_t extensions;
/** Offset to Initiator structure */
ibft_off_t initiator;
- /** Offset to NIC structure for NIC 0 */
- ibft_off_t nic_0;
- /** Offset to Target structure for target 0 */
- ibft_off_t target_0;
- /** Offset to NIC structure for NIC 1 */
- ibft_off_t nic_1;
- /** Offset to Target structure for target 1 */
- ibft_off_t target_1;
+ /** Offsets to NIC and Target structures */
+ struct ibft_offset_pair pair[2];
} __attribute__ (( packed ));
/** Structure ID for Control section */
@@ -262,18 +273,13 @@ struct ibft_target {
*/
struct ibft_table {
/** ACPI header */
- struct acpi_description_header acpi;
+ struct acpi_header acpi;
/** Reserved */
uint8_t reserved[12];
/** Control structure */
struct ibft_control control;
} __attribute__ (( packed ));
-struct iscsi_session;
-struct net_device;
-
-extern int ibft_describe ( struct iscsi_session *iscsi,
- struct acpi_description_header *acpi,
- size_t len );
+extern struct acpi_model ibft_model __acpi_model;
#endif /* _IPXE_IBFT_H */
diff --git a/src/include/ipxe/iscsi.h b/src/include/ipxe/iscsi.h
index c75ff418..966cf52b 100644
--- a/src/include/ipxe/iscsi.h
+++ b/src/include/ipxe/iscsi.h
@@ -16,6 +16,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/refcnt.h>
#include <ipxe/xfer.h>
#include <ipxe/process.h>
+#include <ipxe/acpi.h>
+#include <ipxe/settings.h>
/** Default iSCSI port */
#define ISCSI_PORT 3260
@@ -647,6 +649,8 @@ struct iscsi_session {
struct sockaddr target_sockaddr;
/** SCSI LUN (for boot firmware table) */
struct scsi_lun lun;
+ /** ACPI descriptor */
+ struct acpi_descriptor desc;
};
/** iSCSI session is currently in the security negotiation phase */
@@ -697,4 +701,7 @@ struct iscsi_session {
/** Default initiator IQN prefix */
#define ISCSI_DEFAULT_IQN_PREFIX "iqn.2010-04.org.ipxe"
+extern const struct setting
+initiator_iqn_setting __setting ( SETTING_SANBOOT_EXTRA, initiator-iqn );
+
#endif /* _IPXE_ISCSI_H */
diff --git a/src/include/ipxe/sanboot.h b/src/include/ipxe/sanboot.h
index 64b665a5..8737bbc0 100644
--- a/src/include/ipxe/sanboot.h
+++ b/src/include/ipxe/sanboot.h
@@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/retry.h>
#include <ipxe/process.h>
#include <ipxe/blockdev.h>
+#include <ipxe/acpi.h>
#include <config/sanboot.h>
/** A SAN path */
@@ -37,6 +38,9 @@ struct san_path {
struct process process;
/** Path status */
int path_rc;
+
+ /** ACPI descriptor (if applicable) */
+ struct acpi_descriptor *desc;
};
/** A SAN device */
@@ -48,6 +52,8 @@ struct san_device {
/** Drive number */
unsigned int drive;
+ /** Flags */
+ unsigned int flags;
/** Command interface */
struct interface command;
@@ -83,6 +89,12 @@ struct san_device {
struct san_path path[0];
};
+/** SAN device flags */
+enum san_device_flags {
+ /** Device should not be included in description tables */
+ SAN_NO_DESCRIBE = 0x0001,
+};
+
/**
* Calculate static inline sanboot API function name
*
@@ -126,9 +138,11 @@ struct san_device {
* @v drive Drive number
* @v uris List of URIs
* @v count Number of URIs
+ * @v flags Flags
* @ret drive Drive number, or negative error
*/
-int san_hook ( unsigned int drive, struct uri **uris, unsigned int count );
+int san_hook ( unsigned int drive, struct uri **uris, unsigned int count,
+ unsigned int flags );
/**
* Unhook SAN device
@@ -146,12 +160,11 @@ void san_unhook ( unsigned int drive );
int san_boot ( unsigned int drive );
/**
- * Describe SAN device for SAN-booted operating system
+ * Describe SAN devices for SAN-booted operating system
*
- * @v drive Drive number
* @ret rc Return status code
*/
-int san_describe ( unsigned int drive );
+int san_describe ( void );
extern struct list_head san_devices;
@@ -230,7 +243,8 @@ extern int sandev_rw ( struct san_device *sandev, uint64_t lba,
userptr_t buffer, size_t len ) );
extern struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
size_t priv_size );
-extern int register_sandev ( struct san_device *sandev );
+extern int register_sandev ( struct san_device *sandev, unsigned int drive,
+ unsigned int flags );
extern void unregister_sandev ( struct san_device *sandev );
extern unsigned int san_default_drive ( void );
diff --git a/src/include/ipxe/srp.h b/src/include/ipxe/srp.h
index 8d7f799c..3abb0995 100644
--- a/src/include/ipxe/srp.h
+++ b/src/include/ipxe/srp.h
@@ -790,7 +790,7 @@ typedef uint16_t sbft_off_t;
*/
struct sbft_table {
/** ACPI header */
- struct acpi_description_header acpi;
+ struct acpi_header acpi;
/** Offset to SCSI subtable */
sbft_off_t scsi_offset;
/** Offset to SRP subtable */