diff options
| author | Michael Brown | 2017-03-27 17:20:34 +0200 |
|---|---|---|
| committer | Michael Brown | 2017-03-28 18:12:48 +0200 |
| commit | 7cfdd769aac76d605aa31146c69ba518b194bea7 (patch) | |
| tree | 7c09e144792833f81297e6dacf0823733a2a399a /src/include/ipxe/acpi.h | |
| parent | [block] Ignore redundant xfer_window_changed() messages (diff) | |
| download | ipxe-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/ipxe/acpi.h')
| -rw-r--r-- | src/include/ipxe/acpi.h | 91 |
1 files changed, 82 insertions, 9 deletions
diff --git a/src/include/ipxe/acpi.h b/src/include/ipxe/acpi.h index 17d29b9df..f87b8ae9a 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 */ |
