diff options
Diffstat (limited to 'gpxe/src/include/gpxe')
145 files changed, 5781 insertions, 319 deletions
diff --git a/gpxe/src/include/gpxe/acpi.h b/gpxe/src/include/gpxe/acpi.h index 33b1b2b7..12edda90 100644 --- a/gpxe/src/include/gpxe/acpi.h +++ b/gpxe/src/include/gpxe/acpi.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> /** diff --git a/gpxe/src/include/gpxe/aes.h b/gpxe/src/include/gpxe/aes.h index bdb4b351..fc1694b3 100644 --- a/gpxe/src/include/gpxe/aes.h +++ b/gpxe/src/include/gpxe/aes.h @@ -1,8 +1,30 @@ #ifndef _GPXE_AES_H #define _GPXE_AES_H +FILE_LICENCE ( GPL2_OR_LATER ); + struct cipher_algorithm; +/** Basic AES blocksize */ +#define AES_BLOCKSIZE 16 + +#include "crypto/axtls/crypto.h" + +/** AES context */ +struct aes_context { + /** AES context for AXTLS */ + AES_CTX axtls_ctx; + /** Cipher is being used for decrypting */ + int decrypting; +}; + +/** AES context size */ +#define AES_CTX_SIZE sizeof ( struct aes_context ) + +extern struct cipher_algorithm aes_algorithm; extern struct cipher_algorithm aes_cbc_algorithm; +int aes_wrap ( const void *kek, const void *src, void *dest, int nblk ); +int aes_unwrap ( const void *kek, const void *src, void *dest, int nblk ); + #endif /* _GPXE_AES_H */ diff --git a/gpxe/src/include/gpxe/ansiesc.h b/gpxe/src/include/gpxe/ansiesc.h index ccc4ca65..85f7a9f3 100644 --- a/gpxe/src/include/gpxe/ansiesc.h +++ b/gpxe/src/include/gpxe/ansiesc.h @@ -26,6 +26,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** A handler for an escape sequence */ struct ansiesc_handler { /** The control function identifier diff --git a/gpxe/src/include/gpxe/aoe.h b/gpxe/src/include/gpxe/aoe.h index 6de6b965..6b42fd5b 100644 --- a/gpxe/src/include/gpxe/aoe.h +++ b/gpxe/src/include/gpxe/aoe.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/list.h> #include <gpxe/if_ether.h> diff --git a/gpxe/src/include/gpxe/api.h b/gpxe/src/include/gpxe/api.h index df5d1ae3..ff2ba595 100644 --- a/gpxe/src/include/gpxe/api.h +++ b/gpxe/src/include/gpxe/api.h @@ -11,6 +11,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** @defgroup Single-implementation APIs * * These are APIs for which only a single implementation may be diff --git a/gpxe/src/include/gpxe/arc4.h b/gpxe/src/include/gpxe/arc4.h new file mode 100644 index 00000000..9917628a --- /dev/null +++ b/gpxe/src/include/gpxe/arc4.h @@ -0,0 +1,22 @@ +#ifndef _GPXE_ARC4_H +#define _GPXE_ARC4_H + +FILE_LICENCE ( GPL2_OR_LATER ); + +struct cipher_algorithm; + +#include <stdint.h> + +struct arc4_ctx { + int i, j; + u8 state[256]; +}; + +#define ARC4_CTX_SIZE sizeof ( struct arc4_ctx ) + +extern struct cipher_algorithm arc4_algorithm; + +void arc4_skip ( const void *key, size_t keylen, size_t skip, + const void *src, void *dst, size_t msglen ); + +#endif /* _GPXE_ARC4_H */ diff --git a/gpxe/src/include/gpxe/arp.h b/gpxe/src/include/gpxe/arp.h index 6464ce0c..0623d35c 100644 --- a/gpxe/src/include/gpxe/arp.h +++ b/gpxe/src/include/gpxe/arp.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/tables.h> struct net_device; @@ -26,9 +28,12 @@ struct arp_net_protocol { const void *net_addr ); }; +/** ARP protocol table */ +#define ARP_NET_PROTOCOLS \ + __table ( struct arp_net_protocol, "arp_net_protocols" ) + /** Declare an ARP protocol */ -#define __arp_net_protocol \ - __table ( struct arp_net_protocol, arp_net_protocols, 01 ) +#define __arp_net_protocol __table_entry ( ARP_NET_PROTOCOLS, 01 ) extern struct net_protocol arp_protocol; diff --git a/gpxe/src/include/gpxe/asn1.h b/gpxe/src/include/gpxe/asn1.h index 5440c48c..477c209d 100644 --- a/gpxe/src/include/gpxe/asn1.h +++ b/gpxe/src/include/gpxe/asn1.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #define ASN1_INTEGER 0x02 #define ASN1_BIT_STRING 0x03 #define ASN1_OCTET_STRING 0x04 diff --git a/gpxe/src/include/gpxe/ata.h b/gpxe/src/include/gpxe/ata.h index b6da3930..3c565844 100644 --- a/gpxe/src/include/gpxe/ata.h +++ b/gpxe/src/include/gpxe/ata.h @@ -12,6 +12,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** * An ATA Logical Block Address * @@ -152,6 +154,8 @@ struct ata_command { * sectors in size. */ userptr_t data_in; + /** Command status code */ + int rc; }; /** diff --git a/gpxe/src/include/gpxe/base64.h b/gpxe/src/include/gpxe/base64.h index 3321971a..e38bef01 100644 --- a/gpxe/src/include/gpxe/base64.h +++ b/gpxe/src/include/gpxe/base64.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> /** diff --git a/gpxe/src/include/gpxe/bitbash.h b/gpxe/src/include/gpxe/bitbash.h index 62bdce00..f2ba9f7a 100644 --- a/gpxe/src/include/gpxe/bitbash.h +++ b/gpxe/src/include/gpxe/bitbash.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + struct bit_basher; /** Bit-bashing operations */ diff --git a/gpxe/src/include/gpxe/bitmap.h b/gpxe/src/include/gpxe/bitmap.h index 0c2f53c8..d6911a51 100644 --- a/gpxe/src/include/gpxe/bitmap.h +++ b/gpxe/src/include/gpxe/bitmap.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <stddef.h> #include <stdlib.h> diff --git a/gpxe/src/include/gpxe/bitops.h b/gpxe/src/include/gpxe/bitops.h index 5405c854..8db34312 100644 --- a/gpxe/src/include/gpxe/bitops.h +++ b/gpxe/src/include/gpxe/bitops.h @@ -19,6 +19,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** * @file * diff --git a/gpxe/src/include/gpxe/blockdev.h b/gpxe/src/include/gpxe/blockdev.h index 8222984a..cf28524d 100644 --- a/gpxe/src/include/gpxe/blockdev.h +++ b/gpxe/src/include/gpxe/blockdev.h @@ -8,6 +8,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/uaccess.h> struct block_device; diff --git a/gpxe/src/include/gpxe/cbc.h b/gpxe/src/include/gpxe/cbc.h index fcc115eb..1262f1db 100644 --- a/gpxe/src/include/gpxe/cbc.h +++ b/gpxe/src/include/gpxe/cbc.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/crypto.h> /** diff --git a/gpxe/src/include/gpxe/chap.h b/gpxe/src/include/gpxe/chap.h index 87e5484f..e86ede35 100644 --- a/gpxe/src/include/gpxe/chap.h +++ b/gpxe/src/include/gpxe/chap.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/md5.h> diff --git a/gpxe/src/include/gpxe/command.h b/gpxe/src/include/gpxe/command.h index 5d8057ab..51ca6d6d 100644 --- a/gpxe/src/include/gpxe/command.h +++ b/gpxe/src/include/gpxe/command.h @@ -1,6 +1,8 @@ #ifndef _GPXE_COMMAND_H #define _GPXE_COMMAND_H +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/tables.h> /** A command-line command */ @@ -17,6 +19,8 @@ struct command { int ( * exec ) ( int argc, char **argv ); }; -#define __command __table ( struct command, commands, 01 ) +#define COMMANDS __table ( struct command, "commands" ) + +#define __command __table_entry ( COMMANDS, 01 ) #endif /* _GPXE_COMMAND_H */ diff --git a/gpxe/src/include/gpxe/cpio.h b/gpxe/src/include/gpxe/cpio.h index ba6f844a..f462cec1 100644 --- a/gpxe/src/include/gpxe/cpio.h +++ b/gpxe/src/include/gpxe/cpio.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** A CPIO archive header * * All field are hexadecimal ASCII numbers padded with '0' on the diff --git a/gpxe/src/include/gpxe/crc32.h b/gpxe/src/include/gpxe/crc32.h new file mode 100644 index 00000000..d1c7437d --- /dev/null +++ b/gpxe/src/include/gpxe/crc32.h @@ -0,0 +1,10 @@ +#ifndef _GPXE_CRC32_H +#define _GPXE_CRC32_H + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> + +u32 crc32_le ( u32 seed, const void *data, size_t len ); + +#endif diff --git a/gpxe/src/include/gpxe/crypto.h b/gpxe/src/include/gpxe/crypto.h index 10882d37..ecda5f6d 100644 --- a/gpxe/src/include/gpxe/crypto.h +++ b/gpxe/src/include/gpxe/crypto.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <stddef.h> @@ -127,7 +129,7 @@ static inline void cipher_encrypt ( struct cipher_algorithm *cipher, cipher->encrypt ( ctx, src, dst, len ); } #define cipher_encrypt( cipher, ctx, src, dst, len ) do { \ - assert ( ( len & ( (cipher)->blocksize - 1 ) ) == 0 ); \ + assert ( ( (len) & ( (cipher)->blocksize - 1 ) ) == 0 ); \ cipher_encrypt ( (cipher), (ctx), (src), (dst), (len) ); \ } while ( 0 ) @@ -137,7 +139,7 @@ static inline void cipher_decrypt ( struct cipher_algorithm *cipher, cipher->decrypt ( ctx, src, dst, len ); } #define cipher_decrypt( cipher, ctx, src, dst, len ) do { \ - assert ( ( len & ( (cipher)->blocksize - 1 ) ) == 0 ); \ + assert ( ( (len) & ( (cipher)->blocksize - 1 ) ) == 0 ); \ cipher_decrypt ( (cipher), (ctx), (src), (dst), (len) ); \ } while ( 0 ) @@ -149,4 +151,6 @@ extern struct digest_algorithm digest_null; extern struct cipher_algorithm cipher_null; extern struct pubkey_algorithm pubkey_null; +void get_random_bytes ( void *buf, size_t len ); + #endif /* _GPXE_CRYPTO_H */ diff --git a/gpxe/src/include/gpxe/device.h b/gpxe/src/include/gpxe/device.h index f40cc95a..1db3ff90 100644 --- a/gpxe/src/include/gpxe/device.h +++ b/gpxe/src/include/gpxe/device.h @@ -8,6 +8,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/list.h> #include <gpxe/tables.h> @@ -102,7 +104,10 @@ struct root_driver { void ( * remove ) ( struct root_device *rootdev ); }; +/** Root device table */ +#define ROOT_DEVICES __table ( struct root_device, "root_devices" ) + /** Declare a root device */ -#define __root_device __table ( struct root_device, root_devices, 01 ) +#define __root_device __table_entry ( ROOT_DEVICES, 01 ) #endif /* _GPXE_DEVICE_H */ diff --git a/gpxe/src/include/gpxe/dhcp.h b/gpxe/src/include/gpxe/dhcp.h index 33e0c5d4..ebfe8ede 100644 --- a/gpxe/src/include/gpxe/dhcp.h +++ b/gpxe/src/include/gpxe/dhcp.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/in.h> #include <gpxe/list.h> @@ -14,6 +16,7 @@ #include <gpxe/tables.h> #include <gpxe/uuid.h> #include <gpxe/netdevice.h> +#include <gpxe/uaccess.h> struct job_interface; struct dhcp_options; @@ -330,6 +333,16 @@ struct dhcp_netdev_desc { uint16_t device; } __attribute__ (( packed )); +/** Use cached network settings + * + * Cached network settings may be available from a prior DHCP request + * (if running as a PXE NBP), non-volatile storage on the NIC, or + * settings set via the command line or an embedded image. If this + * flag is not set, it will be assumed that those sources are + * insufficient and that DHCP should still be run when autobooting. + */ +#define DHCP_EB_USE_CACHED DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb2 ) + /** BIOS drive number * * This is the drive number for a drive emulated via INT 13. 0x80 is @@ -599,6 +612,8 @@ struct dhcphdr { /** Setting block name used for BootServerDHCP responses */ #define PXEBS_SETTINGS_NAME "pxebs" +extern void * dhcp_chaddr ( struct net_device *netdev, uint8_t *hlen, + uint16_t *flags ); extern int dhcp_create_packet ( struct dhcp_packet *dhcppkt, struct net_device *netdev, uint8_t msgtype, const void *options, size_t options_len, @@ -611,4 +626,12 @@ extern int start_dhcp ( struct job_interface *job, struct net_device *netdev ); extern int start_pxebs ( struct job_interface *job, struct net_device *netdev, unsigned int pxe_type ); +/* In environments that can provide cached DHCP packets, this function + * should look for such a packet and call store_cached_dhcpack() with + * it if it exists. + */ +__weak_decl ( void, get_cached_dhcpack, ( void ), (), ); + +extern void store_cached_dhcpack ( userptr_t data, size_t len ); + #endif /* _GPXE_DHCP_H */ diff --git a/gpxe/src/include/gpxe/dhcpopts.h b/gpxe/src/include/gpxe/dhcpopts.h index 8391a9d4..3d90f411 100644 --- a/gpxe/src/include/gpxe/dhcpopts.h +++ b/gpxe/src/include/gpxe/dhcpopts.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> /** A DHCP options block */ diff --git a/gpxe/src/include/gpxe/dhcppkt.h b/gpxe/src/include/gpxe/dhcppkt.h index e8f8fafd..6007ccab 100644 --- a/gpxe/src/include/gpxe/dhcppkt.h +++ b/gpxe/src/include/gpxe/dhcppkt.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/dhcp.h> #include <gpxe/dhcpopts.h> #include <gpxe/refcnt.h> diff --git a/gpxe/src/include/gpxe/dns.h b/gpxe/src/include/gpxe/dns.h index 3e3cff1b..9e5e874f 100644 --- a/gpxe/src/include/gpxe/dns.h +++ b/gpxe/src/include/gpxe/dns.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/in.h> diff --git a/gpxe/src/include/gpxe/downloader.h b/gpxe/src/include/gpxe/downloader.h index 33aa7692..7f21e07b 100644 --- a/gpxe/src/include/gpxe/downloader.h +++ b/gpxe/src/include/gpxe/downloader.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + struct job_interface; struct image; diff --git a/gpxe/src/include/gpxe/eapol.h b/gpxe/src/include/gpxe/eapol.h new file mode 100644 index 00000000..c9855d09 --- /dev/null +++ b/gpxe/src/include/gpxe/eapol.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPXE_EAPOL_H +#define _GPXE_EAPOL_H + +/** @file + * + * Definitions for EAPOL (Extensible Authentication Protocol over + * LANs) frames. Definitions for the packets usually encapsulated in + * them are elsewhere. + */ + +#include <gpxe/tables.h> +#include <stdint.h> + +FILE_LICENCE ( GPL2_OR_LATER ); + + +/** + * @defgroup eapol_type EAPOL archetype identifiers + * @{ + */ +#define EAPOL_TYPE_EAP 0 /**< EAP authentication handshake packet */ +#define EAPOL_TYPE_START 1 /**< Request by Peer to begin (no data) */ +#define EAPOL_TYPE_LOGOFF 2 /**< Request by Peer to terminate (no data) */ +#define EAPOL_TYPE_KEY 3 /**< EAPOL-Key packet */ +/** @} */ + +/** Expected EAPOL version field value + * + * Version 2 is often seen and has no format differences from version 1; + * however, many older APs will completely drop version-2 packets, so + * we advertise ourselves as version 1. + */ +#define EAPOL_THIS_VERSION 1 + +/** Length of an EAPOL frame header */ +#define EAPOL_HDR_LEN 4 + +/** An EAPOL frame + * + * This may encapsulate an eap_pkt, an eapol_key_pkt, or a Start or + * Logoff request with no data attached. It is transmitted directly in + * an Ethernet frame, with no IP packet header. + */ +struct eapol_frame +{ + /** EAPOL version identifier, always 1 */ + u8 version; + + /** EAPOL archetype identifier indicating format of payload */ + u8 type; + + /** Length of payload, in network byte order */ + u16 length; + + /** Payload, if @a type is EAP or EAPOL-Key */ + u8 data[0]; +} __attribute__ (( packed )); + + +/** An EAPOL frame type handler + * + * Normally there will be at most two of these, one for EAP and one + * for EAPOL-Key frames. The EAPOL interface code handles Start and + * Logoff directly. + */ +struct eapol_handler +{ + /** EAPOL archetype identifier for payload this handler will handle */ + u8 type; + + /** Receive EAPOL-encapsulated packet of specified type + * + * @v iob I/O buffer containing packet payload + * @v netdev Network device from which packet was received + * @v ll_source Source link-layer address from which packet was received + * @ret rc Return status code + * + * The I/O buffer will have the EAPOL header pulled off it, so + * @c iob->data points to the first byte of the payload. + * + * This function takes ownership of the I/O buffer passed to it. + */ + int ( * rx ) ( struct io_buffer *iob, struct net_device *netdev, + const void *ll_source ); +}; + +#define EAPOL_HANDLERS __table ( struct eapol_handler, "eapol_handlers" ) +#define __eapol_handler __table_entry ( EAPOL_HANDLERS, 01 ) + + +extern struct net_protocol eapol_protocol __net_protocol; + + +#endif /* _GPXE_EAPOL_H */ diff --git a/gpxe/src/include/gpxe/editbox.h b/gpxe/src/include/gpxe/editbox.h index 007b042f..b7cc411b 100644 --- a/gpxe/src/include/gpxe/editbox.h +++ b/gpxe/src/include/gpxe/editbox.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <curses.h> #include <gpxe/editstring.h> diff --git a/gpxe/src/include/gpxe/editstring.h b/gpxe/src/include/gpxe/editstring.h index fad8bd5a..48c1baa0 100644 --- a/gpxe/src/include/gpxe/editstring.h +++ b/gpxe/src/include/gpxe/editstring.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** An editable string */ struct edit_string { /** Buffer for string */ diff --git a/gpxe/src/include/gpxe/efi/efi.h b/gpxe/src/include/gpxe/efi/efi.h index c7f63b6c..f4459b74 100644 --- a/gpxe/src/include/gpxe/efi/efi.h +++ b/gpxe/src/include/gpxe/efi/efi.h @@ -31,11 +31,17 @@ /* EFI headers rudely redefine NULL */ #undef NULL +/* EFI headers expect ICC to define __GNUC__ */ +#if defined ( __ICC ) && ! defined ( __GNUC__ ) +#define __GNUC__ 1 +#endif + /* Include the top-level EFI header files */ #include <gpxe/efi/Uefi.h> #include <gpxe/efi/PiDxe.h> /* Reset any trailing #pragma pack directives */ +#pragma pack(1) #pragma pack() #include <gpxe/tables.h> @@ -54,9 +60,11 @@ struct efi_protocol { void **protocol; }; +/** EFI protocol table */ +#define EFI_PROTOCOLS __table ( struct efi_protocol, "efi_protocols" ) + /** Declare an EFI protocol used by gPXE */ -#define __efi_protocol \ - __table ( struct efi_protocol, efi_protocols, 01 ) +#define __efi_protocol __table_entry ( EFI_PROTOCOLS, 01 ) /** Declare an EFI protocol to be required by gPXE * @@ -67,7 +75,7 @@ struct efi_protocol { struct efi_protocol __ ## _protocol __efi_protocol = { \ .u.guid = _protocol ## _GUID, \ .protocol = ( ( void ** ) ( void * ) \ - ( ( (_ptr) == ( ( _protocol ** ) NULL ) ) ? \ + ( ( (_ptr) == ( ( _protocol ** ) (_ptr) ) ) ? \ (_ptr) : (_ptr) ) ), \ } @@ -86,9 +94,12 @@ struct efi_config_table { int required; }; +/** EFI configuration table table */ +#define EFI_CONFIG_TABLES \ + __table ( struct efi_config_table, "efi_config_tables" ) + /** Declare an EFI configuration table used by gPXE */ -#define __efi_config_table \ - __table ( struct efi_config_table, efi_config_tables, 01 ) +#define __efi_config_table __table_entry ( EFI_CONFIG_TABLES, 01 ) /** Declare an EFI configuration table to be used by gPXE * diff --git a/gpxe/src/include/gpxe/efi/efi_io.h b/gpxe/src/include/gpxe/efi/efi_io.h index 93f559db..7ad5ffe7 100644 --- a/gpxe/src/include/gpxe/efi/efi_io.h +++ b/gpxe/src/include/gpxe/efi/efi_io.h @@ -10,6 +10,8 @@ * no-ops. I/O is handled using the EFI_CPU_IO_PROTOCOL. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #ifdef IOAPI_EFI #define IOAPI_PREFIX_efi #else diff --git a/gpxe/src/include/gpxe/efi/efi_pci.h b/gpxe/src/include/gpxe/efi/efi_pci.h index 8be331ab..59c0eb1d 100644 --- a/gpxe/src/include/gpxe/efi/efi_pci.h +++ b/gpxe/src/include/gpxe/efi/efi_pci.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #ifdef PCIAPI_EFI #define PCIAPI_PREFIX_efi #else diff --git a/gpxe/src/include/gpxe/efi/efi_smbios.h b/gpxe/src/include/gpxe/efi/efi_smbios.h index df947de5..01631e52 100644 --- a/gpxe/src/include/gpxe/efi/efi_smbios.h +++ b/gpxe/src/include/gpxe/efi/efi_smbios.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #ifdef SMBIOS_EFI #define SMBIOS_PREFIX_efi #else diff --git a/gpxe/src/include/gpxe/efi/efi_timer.h b/gpxe/src/include/gpxe/efi/efi_timer.h index c332c9d6..e0531d5a 100644 --- a/gpxe/src/include/gpxe/efi/efi_timer.h +++ b/gpxe/src/include/gpxe/efi/efi_timer.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #ifdef TIMER_EFI #define TIMER_PREFIX_efi #else diff --git a/gpxe/src/include/gpxe/efi/efi_uaccess.h b/gpxe/src/include/gpxe/efi/efi_uaccess.h index bae5fb41..a6b61c58 100644 --- a/gpxe/src/include/gpxe/efi/efi_uaccess.h +++ b/gpxe/src/include/gpxe/efi/efi_uaccess.h @@ -10,6 +10,8 @@ * no-ops. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #ifdef UACCESS_EFI #define UACCESS_PREFIX_efi #else diff --git a/gpxe/src/include/gpxe/efi/efi_umalloc.h b/gpxe/src/include/gpxe/efi/efi_umalloc.h index def17b2d..0388dd10 100644 --- a/gpxe/src/include/gpxe/efi/efi_umalloc.h +++ b/gpxe/src/include/gpxe/efi/efi_umalloc.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #ifdef UMALLOC_EFI #define UMALLOC_PREFIX_efi #else diff --git a/gpxe/src/include/gpxe/eisa.h b/gpxe/src/include/gpxe/eisa.h index e9d890e1..f76e4b9d 100644 --- a/gpxe/src/include/gpxe/eisa.h +++ b/gpxe/src/include/gpxe/eisa.h @@ -1,6 +1,8 @@ #ifndef EISA_H #define EISA_H +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/isa_ids.h> #include <gpxe/device.h> @@ -79,8 +81,11 @@ struct eisa_driver { void ( * remove ) ( struct eisa_device *eisa ); }; +/** EISA driver table */ +#define EISA_DRIVERS __table ( struct eisa_driver, "eisa_drivers" ) + /** Declare an EISA driver */ -#define __eisa_driver __table ( struct eisa_driver, eisa_drivers, 01 ) +#define __eisa_driver __table_entry ( EISA_DRIVERS, 01 ) extern void eisa_device_enabled ( struct eisa_device *eisa, int enabled ); diff --git a/gpxe/src/include/gpxe/elf.h b/gpxe/src/include/gpxe/elf.h index db28a60a..da9d2fc0 100644 --- a/gpxe/src/include/gpxe/elf.h +++ b/gpxe/src/include/gpxe/elf.h @@ -8,6 +8,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <elf.h> extern int elf_load ( struct image *image ); diff --git a/gpxe/src/include/gpxe/errfile.h b/gpxe/src/include/gpxe/errfile.h index dcfd4e4a..def8f357 100644 --- a/gpxe/src/include/gpxe/errfile.h +++ b/gpxe/src/include/gpxe/errfile.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <bits/errfile.h> /** @@ -108,11 +110,20 @@ #define ERRFILE_phantom ( ERRFILE_DRIVER | 0x004b0000 ) #define ERRFILE_ne2k_isa ( ERRFILE_DRIVER | 0x004c0000 ) #define ERRFILE_b44 ( ERRFILE_DRIVER | 0x004d0000 ) +#define ERRFILE_rtl818x ( ERRFILE_DRIVER | 0x004e0000 ) +#define ERRFILE_sky2 ( ERRFILE_DRIVER | 0x004f0000 ) +#define ERRFILE_ath5k ( ERRFILE_DRIVER | 0x00500000 ) +#define ERRFILE_atl1e ( ERRFILE_DRIVER | 0x00510000 ) +#define ERRFILE_sis190 ( ERRFILE_DRIVER | 0x00520000 ) +#define ERRFILE_myri10ge ( ERRFILE_DRIVER | 0x00530000 ) +#define ERRFILE_skge ( ERRFILE_DRIVER | 0x00540000 ) #define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 ) #define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 ) #define ERRFILE_hermon ( ERRFILE_DRIVER | 0x00720000 ) #define ERRFILE_linda ( ERRFILE_DRIVER | 0x00730000 ) +#define ERRFILE_ata ( ERRFILE_DRIVER | 0x00740000 ) +#define ERRFILE_srp ( ERRFILE_DRIVER | 0x00750000 ) #define ERRFILE_aoe ( ERRFILE_NET | 0x00000000 ) #define ERRFILE_arp ( ERRFILE_NET | 0x00010000 ) @@ -140,6 +151,22 @@ #define ERRFILE_ib_sma ( ERRFILE_NET | 0x00170000 ) #define ERRFILE_ib_packet ( ERRFILE_NET | 0x00180000 ) #define ERRFILE_icmp ( ERRFILE_NET | 0x00190000 ) +#define ERRFILE_ib_qset ( ERRFILE_NET | 0x001a0000 ) +#define ERRFILE_ib_gma ( ERRFILE_NET | 0x001b0000 ) +#define ERRFILE_ib_pathrec ( ERRFILE_NET | 0x001c0000 ) +#define ERRFILE_ib_mcast ( ERRFILE_NET | 0x001d0000 ) +#define ERRFILE_ib_cm ( ERRFILE_NET | 0x001e0000 ) +#define ERRFILE_net80211 ( ERRFILE_NET | 0x001f0000 ) +#define ERRFILE_ib_mi ( ERRFILE_NET | 0x00200000 ) +#define ERRFILE_ib_cmrc ( ERRFILE_NET | 0x00210000 ) +#define ERRFILE_ib_srp ( ERRFILE_NET | 0x00220000 ) +#define ERRFILE_sec80211 ( ERRFILE_NET | 0x00230000 ) +#define ERRFILE_wep ( ERRFILE_NET | 0x00240000 ) +#define ERRFILE_eapol ( ERRFILE_NET | 0x00250000 ) +#define ERRFILE_wpa ( ERRFILE_NET | 0x00260000 ) +#define ERRFILE_wpa_psk ( ERRFILE_NET | 0x00270000 ) +#define ERRFILE_wpa_tkip ( ERRFILE_NET | 0x00280000 ) +#define ERRFILE_wpa_ccmp ( ERRFILE_NET | 0x00290000 ) #define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 ) #define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 ) @@ -172,6 +199,8 @@ #define ERRFILE_pxemenu ( ERRFILE_OTHER | 0x00150000 ) #define ERRFILE_x509 ( ERRFILE_OTHER | 0x00160000 ) #define ERRFILE_login_ui ( ERRFILE_OTHER | 0x00170000 ) +#define ERRFILE_ib_srpboot ( ERRFILE_OTHER | 0x00180000 ) +#define ERRFILE_iwmgmt ( ERRFILE_OTHER | 0x00190000 ) /** @} */ diff --git a/gpxe/src/include/gpxe/errortab.h b/gpxe/src/include/gpxe/errortab.h index e9a56768..35765d48 100644 --- a/gpxe/src/include/gpxe/errortab.h +++ b/gpxe/src/include/gpxe/errortab.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/tables.h> struct errortab { @@ -14,6 +16,8 @@ struct errortab { const char *text; }; -#define __errortab __table ( struct errortab, errortab, 01 ) +#define ERRORTAB __table ( struct errortab, "errortab" ) + +#define __errortab __table_entry ( ERRORTAB, 01 ) #endif /* _GPXE_ERRORTAB_H */ diff --git a/gpxe/src/include/gpxe/ethernet.h b/gpxe/src/include/gpxe/ethernet.h index ff0fd6c1..4dfc24d3 100644 --- a/gpxe/src/include/gpxe/ethernet.h +++ b/gpxe/src/include/gpxe/ethernet.h @@ -7,29 +7,15 @@ * */ -#include <stdint.h> -#include <gpxe/netdevice.h> -#include <gpxe/if_ether.h> +FILE_LICENCE ( GPL2_OR_LATER ); -extern struct ll_protocol ethernet_protocol; +#include <stdint.h> +extern void eth_init_addr ( const void *hw_addr, void *ll_addr ); extern const char * eth_ntoa ( const void *ll_addr ); - -/** - * Allocate Ethernet device - * - * @v priv_size Size of driver private data - * @ret netdev Network device, or NULL - */ -static inline struct net_device * alloc_etherdev ( size_t priv_size ) { - struct net_device *netdev; - - netdev = alloc_netdev ( priv_size ); - if ( netdev ) { - netdev->ll_protocol = ðernet_protocol; - netdev->max_pkt_len = ETH_FRAME_LEN; - } - return netdev; -} +extern int eth_mc_hash ( unsigned int af, const void *net_addr, + void *ll_addr ); +extern int eth_eth_addr ( const void *ll_addr, void *eth_addr ); +extern struct net_device * alloc_etherdev ( size_t priv_size ); #endif /* _GPXE_ETHERNET_H */ diff --git a/gpxe/src/include/gpxe/fakedhcp.h b/gpxe/src/include/gpxe/fakedhcp.h index 550b74f7..c603bdc4 100644 --- a/gpxe/src/include/gpxe/fakedhcp.h +++ b/gpxe/src/include/gpxe/fakedhcp.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> struct net_device; diff --git a/gpxe/src/include/gpxe/features.h b/gpxe/src/include/gpxe/features.h index 32c31694..34431867 100644 --- a/gpxe/src/include/gpxe/features.h +++ b/gpxe/src/include/gpxe/features.h @@ -11,6 +11,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** * @defgroup featurecat Feature categories * @{ @@ -42,6 +44,7 @@ #define DHCP_EB_FEATURE_BZIMAGE 0x18 /**< bzImage format */ #define DHCP_EB_FEATURE_MULTIBOOT 0x19 /**< Multiboot format */ #define DHCP_EB_FEATURE_SLAM 0x1a /**< SLAM protocol */ +#define DHCP_EB_FEATURE_SRP 0x1b /**< SRP protocol */ #define DHCP_EB_FEATURE_NBI 0x20 /**< NBI format */ #define DHCP_EB_FEATURE_PXE 0x21 /**< PXE format */ #define DHCP_EB_FEATURE_ELF 0x22 /**< ELF format */ @@ -50,8 +53,11 @@ /** @} */ +/** DHCP feature table */ +#define DHCP_FEATURES __table ( uint8_t, "dhcp_features" ) + /** Declare a feature code for DHCP */ -#define __dhcp_feature __table ( uint8_t, dhcp_features, 01 ) +#define __dhcp_feature __table_entry ( DHCP_FEATURES, 01 ) /** Construct a DHCP feature table entry */ #define DHCP_FEATURE( feature_opt, ... ) \ @@ -69,9 +75,11 @@ struct feature { char *name; }; +/** Named feature table */ +#define FEATURES __table ( struct feature, "features" ) + /** Declare a named feature */ -#define __feature_name( category ) \ - __table ( struct feature, features, category ) +#define __feature_name( category ) __table_entry ( FEATURES, category ) /** Construct a named feature */ #define FEATURE_NAME( category, text ) \ diff --git a/gpxe/src/include/gpxe/filter.h b/gpxe/src/include/gpxe/filter.h index 126f6347..1f59fccc 100644 --- a/gpxe/src/include/gpxe/filter.h +++ b/gpxe/src/include/gpxe/filter.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stddef.h> #include <gpxe/xfer.h> diff --git a/gpxe/src/include/gpxe/ftp.h b/gpxe/src/include/gpxe/ftp.h index 370285c6..93194f65 100644 --- a/gpxe/src/include/gpxe/ftp.h +++ b/gpxe/src/include/gpxe/ftp.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** FTP default port */ #define FTP_PORT 21 diff --git a/gpxe/src/include/gpxe/gdbserial.h b/gpxe/src/include/gpxe/gdbserial.h index 1863e907..2613ab47 100644 --- a/gpxe/src/include/gpxe/gdbserial.h +++ b/gpxe/src/include/gpxe/gdbserial.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + struct gdb_transport; /** diff --git a/gpxe/src/include/gpxe/gdbstub.h b/gpxe/src/include/gpxe/gdbstub.h index bf5d24d2..8f9b7c1d 100644 --- a/gpxe/src/include/gpxe/gdbstub.h +++ b/gpxe/src/include/gpxe/gdbstub.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/tables.h> #include <gdbmach.h> @@ -45,7 +47,9 @@ struct gdb_transport { void ( * send ) ( const char *buf, size_t len ); }; -#define __gdb_transport __table ( struct gdb_transport, gdb_transports, 01 ) +#define GDB_TRANSPORTS __table ( struct gdb_transport, "gdb_transports" ) + +#define __gdb_transport __table_entry ( GDB_TRANSPORTS, 01 ) /** * Look up GDB transport by name diff --git a/gpxe/src/include/gpxe/gdbudp.h b/gpxe/src/include/gpxe/gdbudp.h index 1a990933..5f02faaa 100644 --- a/gpxe/src/include/gpxe/gdbudp.h +++ b/gpxe/src/include/gpxe/gdbudp.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + struct sockaddr_in; struct gdb_transport; diff --git a/gpxe/src/include/gpxe/hidemem.h b/gpxe/src/include/gpxe/hidemem.h index 010fdb58..01b3fc24 100644 --- a/gpxe/src/include/gpxe/hidemem.h +++ b/gpxe/src/include/gpxe/hidemem.h @@ -8,6 +8,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> extern void hide_umalloc ( physaddr_t start, physaddr_t end ); diff --git a/gpxe/src/include/gpxe/hmac.h b/gpxe/src/include/gpxe/hmac.h index 67aefdce..cb001b9d 100644 --- a/gpxe/src/include/gpxe/hmac.h +++ b/gpxe/src/include/gpxe/hmac.h @@ -6,6 +6,8 @@ * Keyed-Hashing for Message Authentication */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/crypto.h> /** diff --git a/gpxe/src/include/gpxe/http.h b/gpxe/src/include/gpxe/http.h index fa92a950..baa6d83e 100644 --- a/gpxe/src/include/gpxe/http.h +++ b/gpxe/src/include/gpxe/http.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** HTTP default port */ #define HTTP_PORT 80 diff --git a/gpxe/src/include/gpxe/i2c.h b/gpxe/src/include/gpxe/i2c.h index 9d229546..87b89d46 100644 --- a/gpxe/src/include/gpxe/i2c.h +++ b/gpxe/src/include/gpxe/i2c.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/bitbash.h> diff --git a/gpxe/src/include/gpxe/ib_cm.h b/gpxe/src/include/gpxe/ib_cm.h new file mode 100644 index 00000000..670fffda --- /dev/null +++ b/gpxe/src/include/gpxe/ib_cm.h @@ -0,0 +1,72 @@ +#ifndef _GPXE_IB_CM_H +#define _GPXE_IB_CM_H + +/** @file + * + * Infiniband communication management + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <gpxe/infiniband.h> +#include <gpxe/retry.h> + +struct ib_mad_transaction; +struct ib_connection; + +/** Infiniband connection operations */ +struct ib_connection_operations { + /** Handle change of connection status + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v conn Connection + * @v rc Connection status code + * @v private_data Private data, if available + * @v private_data_len Length of private data + */ + void ( * changed ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, + struct ib_connection *conn, int rc, + void *private_data, size_t private_data_len ); +}; + +/** An Infiniband connection */ +struct ib_connection { + /** Infiniband device */ + struct ib_device *ibdev; + /** Queue pair */ + struct ib_queue_pair *qp; + /** Local communication ID */ + uint32_t local_id; + /** Remote communication ID */ + uint32_t remote_id; + /** Target service ID */ + struct ib_gid_half service_id; + /** Connection operations */ + struct ib_connection_operations *op; + + /** List of connections */ + struct list_head list; + + /** Path to target */ + struct ib_path *path; + /** Connection request management transaction */ + struct ib_mad_transaction *madx; + + /** Length of connection request private data */ + size_t private_data_len; + /** Connection request private data */ + uint8_t private_data[0]; +}; + +extern struct ib_connection * +ib_create_conn ( struct ib_device *ibdev, struct ib_queue_pair *qp, + struct ib_gid *dgid, struct ib_gid_half *service_id, + void *req_private_data, size_t req_private_data_len, + struct ib_connection_operations *op ); +extern void ib_destroy_conn ( struct ib_device *ibdev, + struct ib_queue_pair *qp, + struct ib_connection *conn ); + +#endif /* _GPXE_IB_CM_H */ diff --git a/gpxe/src/include/gpxe/ib_cmrc.h b/gpxe/src/include/gpxe/ib_cmrc.h new file mode 100644 index 00000000..efa741ac --- /dev/null +++ b/gpxe/src/include/gpxe/ib_cmrc.h @@ -0,0 +1,20 @@ +#ifndef _GPXE_IB_CMRC_H +#define _GPXE_IB_CMRC_H + +/** @file + * + * Infiniband Communication-managed Reliable Connections + * + */ + +FILE_LICENCE ( BSD2 ); + +#include <gpxe/infiniband.h> +#include <gpxe/xfer.h> + +extern int ib_cmrc_open ( struct xfer_interface *xfer, + struct ib_device *ibdev, + struct ib_gid *dgid, + struct ib_gid_half *service_id ); + +#endif /* _GPXE_IB_CMRC_H */ diff --git a/gpxe/src/include/gpxe/ib_mad.h b/gpxe/src/include/gpxe/ib_mad.h index 6c4e95b7..8b497183 100644 --- a/gpxe/src/include/gpxe/ib_mad.h +++ b/gpxe/src/include/gpxe/ib_mad.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/ib_packet.h> @@ -73,9 +75,9 @@ struct ib_node_info { uint8_t class_version; uint8_t node_type; uint8_t num_ports; - uint8_t sys_guid[8]; - uint8_t node_guid[8]; - uint8_t port_guid[8]; + struct ib_gid_half sys_guid; + struct ib_gid_half node_guid; + struct ib_gid_half port_guid; uint16_t partition_cap; uint16_t device_id; uint32_t revision; @@ -199,6 +201,10 @@ struct ib_smp_class_specific { ***************************************************************************** */ +#define IB_SA_CLASS_VERSION 2 + +#define IB_SA_METHOD_DELETE_RESP 0x95 + struct ib_rmpp_hdr { uint32_t raw[3]; } __attribute__ (( packed )); @@ -275,6 +281,188 @@ union ib_sa_data { /***************************************************************************** * + * Communication management MADs + * + ***************************************************************************** + */ + +/** Communication management class version */ +#define IB_CM_CLASS_VERSION 2 + +/* Communication management attributes */ +#define IB_CM_ATTR_CLASS_PORT_INFO 0x0001 +#define IB_CM_ATTR_CONNECT_REQUEST 0x0010 +#define IB_CM_ATTR_MSG_RCPT_ACK 0x0011 +#define IB_CM_ATTR_CONNECT_REJECT 0x0012 +#define IB_CM_ATTR_CONNECT_REPLY 0x0013 +#define IB_CM_ATTR_READY_TO_USE 0x0014 +#define IB_CM_ATTR_DISCONNECT_REQUEST 0x0015 +#define IB_CM_ATTR_DISCONNECT_REPLY 0x0016 +#define IB_CM_ATTR_SERVICE_ID_RES_REQ 0x0016 +#define IB_CM_ATTR_SERVICE_ID_RES_REQ_RESP 0x0018 +#define IB_CM_ATTR_LOAD_ALTERNATE_PATH 0x0019 +#define IB_CM_ATTR_ALTERNATE_PATH_RESPONSE 0x001a + +/** Communication management common fields */ +struct ib_cm_common { + /** Local communication ID */ + uint32_t local_id; + /** Remote communication ID */ + uint32_t remote_id; + /** Reserved */ + uint8_t reserved[224]; +} __attribute__ (( packed )); + +/** A communication management path */ +struct ib_cm_path { + /** Local port LID */ + uint16_t local_lid; + /** Remote port LID */ + uint16_t remote_lid; + /** Local port GID */ + struct ib_gid local_gid; + /** Remote port GID */ + struct ib_gid remote_gid; + /** Flow label and rate */ + uint32_t flow_label__rate; + /** Traffic class */ + uint8_t tc; + /** Hop limit */ + uint8_t hop_limit; + /** SL and subnet local*/ + uint8_t sl__subnet_local; + /** Local ACK timeout */ + uint8_t local_ack_timeout; +} __attribute__ (( packed )); + +/** A communication management connection request + * + * Defined in section 12.6.5 of the IBA. + */ +struct ib_cm_connect_request { + /** Local communication ID */ + uint32_t local_id; + /** Reserved */ + uint32_t reserved0[1]; + /** Service ID */ + struct ib_gid_half service_id; + /** Local CA GUID */ + struct ib_gid_half local_ca; + /** Reserved */ + uint32_t reserved1[1]; + /** Local queue key */ + uint32_t local_qkey; + /** Local QPN and responder resources*/ + uint32_t local_qpn__responder_resources; + /** Local EECN and initiator depth */ + uint32_t local_eecn__initiator_depth; + /** Remote EECN, remote CM response timeout, transport service + * type, EE flow control + */ + uint32_t remote_eecn__remote_timeout__service_type__ee_flow_ctrl; + /** Starting PSN, local CM response timeout and retry count */ + uint32_t starting_psn__local_timeout__retry_count; + /** Partition key */ + uint16_t pkey; + /** Path packet payload MTU, RDC exists, RNR retry count */ + uint8_t payload_mtu__rdc_exists__rnr_retry; + /** Max CM retries and SRQ */ + uint8_t max_cm_retries__srq; + /** Primary path */ + struct ib_cm_path primary; + /** Alternate path */ + struct ib_cm_path alternate; + /** Private data */ + uint8_t private_data[92]; +} __attribute__ (( packed )); + +/** CM transport types */ +#define IB_CM_TRANSPORT_RC 0 +#define IB_CM_TRANSPORT_UC 1 +#define IB_CM_TRANSPORT_RD 2 + +/** A communication management connection rejection + * + * Defined in section 12.6.7 of the IBA. + */ +struct ib_cm_connect_reject { + /** Local communication ID */ + uint32_t local_id; + /** Remote communication ID */ + uint32_t remote_id; + /** Message rejected */ + uint8_t message; + /** Reject information length */ + uint8_t info_len; + /** Rejection reason */ + uint16_t reason; + /** Additional rejection information */ + uint8_t info[72]; + /** Private data */ + uint8_t private_data[148]; +} __attribute__ (( packed )); + +/** CM rejection reasons */ +#define IB_CM_REJECT_BAD_SERVICE_ID 8 +#define IB_CM_REJECT_STALE_CONN 10 +#define IB_CM_REJECT_CONSUMER 28 + +/** A communication management connection reply + * + * Defined in section 12.6.8 of the IBA. + */ +struct ib_cm_connect_reply { + /** Local communication ID */ + uint32_t local_id; + /** Remote communication ID */ + uint32_t remote_id; + /** Local queue key */ + uint32_t local_qkey; + /** Local QPN */ + uint32_t local_qpn; + /** Local EECN */ + uint32_t local_eecn; + /** Starting PSN */ + uint32_t starting_psn; + /** Responder resources */ + uint8_t responder_resources; + /** Initiator depth */ + uint8_t initiator_depth; + /** Target ACK delay, failover accepted, and end-to-end flow control */ + uint8_t target_ack_delay__failover_accepted__ee_flow_ctrl; + /** RNR retry count, SRQ */ + uint8_t rnr_retry__srq; + /** Local CA GUID */ + struct ib_gid_half local_ca; + /** Private data */ + uint8_t private_data[196]; +} __attribute__ (( packed )); + +/** A communication management ready to use reply + * + * Defined in section 12.6.9 of the IBA. + */ +struct ib_cm_ready_to_use { + /** Local communication ID */ + uint32_t local_id; + /** Remote communication ID */ + uint32_t remote_id; + /** Private data */ + uint8_t private_data[224]; +} __attribute__ (( packed )); + +/** A communication management attribute */ +union ib_cm_data { + struct ib_cm_common common; + struct ib_cm_connect_request connect_request; + struct ib_cm_connect_reject connect_reject; + struct ib_cm_connect_reply connect_reply; + struct ib_cm_ready_to_use ready_to_use; + uint8_t bytes[232]; +} __attribute__ (( packed )); + +/***************************************************************************** + * * MADs * ***************************************************************************** @@ -316,7 +504,9 @@ struct ib_mad_hdr { #define IB_MGMT_CLASS_CM 0x07 #define IB_MGMT_CLASS_SNMP 0x08 #define IB_MGMT_CLASS_VENDOR_RANGE2_START 0x30 -#define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4F +#define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4f + +#define IB_MGMT_CLASS_MASK 0x7f /* Management methods */ #define IB_MGMT_METHOD_GET 0x01 @@ -353,11 +543,18 @@ struct ib_mad_sa { union ib_sa_data sa_data; } __attribute__ (( packed )); +/** A communication management MAD */ +struct ib_mad_cm { + struct ib_mad_hdr mad_hdr; + union ib_cm_data cm_data; +} __attribute__ (( packed )); + /** A management datagram */ union ib_mad { struct ib_mad_hdr hdr; struct ib_mad_smp smp; struct ib_mad_sa sa; + struct ib_mad_cm cm; uint8_t bytes[256]; } __attribute__ (( packed )); diff --git a/gpxe/src/include/gpxe/ib_mcast.h b/gpxe/src/include/gpxe/ib_mcast.h new file mode 100644 index 00000000..74eccd0b --- /dev/null +++ b/gpxe/src/include/gpxe/ib_mcast.h @@ -0,0 +1,48 @@ +#ifndef _GPXE_IB_MCAST_H +#define _GPXE_IB_MCAST_H + +/** @file + * + * Infiniband multicast groups + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <gpxe/infiniband.h> + +struct ib_mad_transaction; + +/** An Infiniband multicast group membership */ +struct ib_mc_membership { + /** Queue pair */ + struct ib_queue_pair *qp; + /** Multicast GID */ + struct ib_gid gid; + /** Multicast group join transaction */ + struct ib_mad_transaction *madx; + /** Handle join success/failure + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v membership Multicast group membership + * @v rc Status code + * @v mad Response MAD (or NULL on error) + */ + void ( * complete ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, + struct ib_mc_membership *membership, int rc, + union ib_mad *mad ); +}; + +extern int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp, + struct ib_mc_membership *membership, + struct ib_gid *gid, + void ( * joined ) ( struct ib_device *ibdev, + struct ib_queue_pair *qp, + struct ib_mc_membership *memb, + int rc, union ib_mad *mad ) ); + +extern void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp, + struct ib_mc_membership *membership ); + +#endif /* _GPXE_IB_MCAST_H */ diff --git a/gpxe/src/include/gpxe/ib_mi.h b/gpxe/src/include/gpxe/ib_mi.h new file mode 100644 index 00000000..b1cf686d --- /dev/null +++ b/gpxe/src/include/gpxe/ib_mi.h @@ -0,0 +1,135 @@ +#ifndef _GPXE_IB_MI_H +#define _GPXE_IB_MI_H + +/** @file + * + * Infiniband management interfaces + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <gpxe/list.h> +#include <gpxe/retry.h> +#include <gpxe/tables.h> +#include <gpxe/infiniband.h> + +struct ib_mad_interface; +struct ib_mad_transaction; + +/** An Infiniband management agent */ +struct ib_mad_agent { + /** Management class */ + uint8_t mgmt_class; + /** Class version */ + uint8_t class_version; + /** Attribute (in network byte order) */ + uint16_t attr_id; + /** Handle MAD + * + * @v ibdev Infiniband device + * @v mi Management interface + * @v mad Received MAD + * @v av Source address vector + * @ret rc Return status code + */ + void ( * handle ) ( struct ib_device *ibdev, + struct ib_mad_interface *mi, + union ib_mad *mad, + struct ib_address_vector *av ); +}; + +/** Infiniband management agents */ +#define IB_MAD_AGENTS __table ( struct ib_mad_agent, "ib_mad_agents" ) + +/** Declare an Infiniband management agent */ +#define __ib_mad_agent __table_entry ( IB_MAD_AGENTS, 01 ) + +/** Infiniband management transaction operations */ +struct ib_mad_transaction_operations { + /** Handle transaction completion + * + * @v ibdev Infiniband device + * @v mi Management interface + * @v madx Management transaction + * @v rc Status code + * @v mad Received MAD (or NULL on error) + * @v av Source address vector (or NULL on error) + * + * The completion handler should in most cases call + * ib_destroy_madx() to free up the completed transaction. + */ + void ( * complete ) ( struct ib_device *ibdev, + struct ib_mad_interface *mi, + struct ib_mad_transaction *madx, + int rc, union ib_mad *mad, + struct ib_address_vector *av ); +}; + +/** An Infiniband management transaction */ +struct ib_mad_transaction { + /** Associated management interface */ + struct ib_mad_interface *mi; + /** List of transactions */ + struct list_head list; + /** Retry timer */ + struct retry_timer timer; + /** Destination address vector */ + struct ib_address_vector av; + /** MAD being sent */ + union ib_mad mad; + /** Transaction operations */ + struct ib_mad_transaction_operations *op; + /** Owner private data */ + void *owner_priv; +}; + +/** An Infiniband management interface */ +struct ib_mad_interface { + /** Infiniband device */ + struct ib_device *ibdev; + /** Completion queue */ + struct ib_completion_queue *cq; + /** Queue pair */ + struct ib_queue_pair *qp; + /** List of management transactions */ + struct list_head madx; +}; + +/** + * Set Infiniband management transaction owner-private data + * + * @v madx Management transaction + * @v priv Private data + */ +static inline __always_inline void +ib_madx_set_ownerdata ( struct ib_mad_transaction *madx, void *priv ) { + madx->owner_priv = priv; +} + +/** + * Get Infiniband management transaction owner-private data + * + * @v madx Management transaction + * @ret priv Private data + */ +static inline __always_inline void * +ib_madx_get_ownerdata ( struct ib_mad_transaction *madx ) { + return madx->owner_priv; +} + +extern int ib_mi_send ( struct ib_device *ibdev, struct ib_mad_interface *mi, + union ib_mad *mad, struct ib_address_vector *av ); +extern struct ib_mad_transaction * +ib_create_madx ( struct ib_device *ibdev, struct ib_mad_interface *mi, + union ib_mad *mad, struct ib_address_vector *av, + struct ib_mad_transaction_operations *op ); +extern void ib_destroy_madx ( struct ib_device *ibdev, + struct ib_mad_interface *mi, + struct ib_mad_transaction *madx ); +extern struct ib_mad_interface * ib_create_mi ( struct ib_device *ibdev, + enum ib_queue_pair_type type ); +extern void ib_destroy_mi ( struct ib_device *ibdev, + struct ib_mad_interface *mi ); + +#endif /* _GPXE_IB_MI_H */ diff --git a/gpxe/src/include/gpxe/ib_packet.h b/gpxe/src/include/gpxe/ib_packet.h index 5374802c..d4688596 100644 --- a/gpxe/src/include/gpxe/ib_packet.h +++ b/gpxe/src/include/gpxe/ib_packet.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + struct ib_device; struct ib_queue_pair; struct ib_address_vector; @@ -14,7 +16,11 @@ struct io_buffer; /** Half of an Infiniband Global Identifier */ struct ib_gid_half { - uint8_t bytes[8]; + union { + uint8_t bytes[8]; + uint16_t words[4]; + uint32_t dwords[2]; + } u; }; /** An Infiniband Global Identifier */ @@ -104,12 +110,6 @@ enum ib_bth_opcode { BTH_OPCODE_UD_SEND = 0x64, }; -/** Default Infiniband partition key */ -#define IB_PKEY_NONE 0xffff - -/** Subnet management queue pair number */ -#define IB_QPN_SMP 0 - /** An Infiniband Datagram Extended Transport Header */ struct ib_datagram_extended_transport_header { /** Queue key */ diff --git a/gpxe/src/include/gpxe/ib_pathrec.h b/gpxe/src/include/gpxe/ib_pathrec.h new file mode 100644 index 00000000..5884d536 --- /dev/null +++ b/gpxe/src/include/gpxe/ib_pathrec.h @@ -0,0 +1,76 @@ +#ifndef _GPXE_IB_PATHREC_H +#define _GPXE_IB_PATHREC_H + +/** @file + * + * Infiniband path records + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <gpxe/infiniband.h> + +struct ib_mad_transaction; +struct ib_path; + +/** Infiniband path operations */ +struct ib_path_operations { + /** Handle path transaction completion + * + * @v ibdev Infiniband device + * @v path Path + * @v rc Status code + * @v av Address vector, or NULL on error + */ + void ( * complete ) ( struct ib_device *ibdev, + struct ib_path *path, int rc, + struct ib_address_vector *av ); +}; + +/** An Infiniband path */ +struct ib_path { + /** Infiniband device */ + struct ib_device *ibdev; + /** Address vector */ + struct ib_address_vector av; + /** Management transaction */ + struct ib_mad_transaction *madx; + /** Path operations */ + struct ib_path_operations *op; + /** Owner private data */ + void *owner_priv; +}; + +/** + * Set Infiniband path owner-private data + * + * @v path Path + * @v priv Private data + */ +static inline __always_inline void +ib_path_set_ownerdata ( struct ib_path *path, void *priv ) { + path->owner_priv = priv; +} + +/** + * Get Infiniband path owner-private data + * + * @v path Path + * @ret priv Private data + */ +static inline __always_inline void * +ib_path_get_ownerdata ( struct ib_path *path ) { + return path->owner_priv; +} + +extern struct ib_path * +ib_create_path ( struct ib_device *ibdev, struct ib_address_vector *av, + struct ib_path_operations *op ); +extern void ib_destroy_path ( struct ib_device *ibdev, + struct ib_path *path ); + +extern int ib_resolve_path ( struct ib_device *ibdev, + struct ib_address_vector *av ); + +#endif /* _GPXE_IB_PATHREC_H */ diff --git a/gpxe/src/include/gpxe/ib_sma.h b/gpxe/src/include/gpxe/ib_sma.h index 835ed4ea..78fc6729 100644 --- a/gpxe/src/include/gpxe/ib_sma.h +++ b/gpxe/src/include/gpxe/ib_sma.h @@ -3,61 +3,18 @@ /** @file * - * Infiniband Subnet Management Agent + * Infiniband subnet management agent * */ -#include <gpxe/infiniband.h> -#include <gpxe/process.h> +FILE_LICENCE ( GPL2_OR_LATER ); -/** Infiniband Subnet Management Agent operations */ -struct ib_sma_operations { - /** Set port information - * - * @v ibdev Infiniband device - * @v port_info New port information - */ - int ( * set_port_info ) ( struct ib_device *ibdev, - const struct ib_port_info *port_info ); -}; +struct ib_device; +struct ib_mad_interface; -/** An Infiniband Subnet Management Agent */ -struct ib_sma { - /** Infiniband device */ - struct ib_device *ibdev; - /** SMA operations */ - struct ib_sma_operations *op; - /** SMA completion queue */ - struct ib_completion_queue *cq; - /** SMA queue pair */ - struct ib_queue_pair *qp; - /** Poll process */ - struct process poll; -}; - -/** SMA payload size allocated for received packets */ -#define IB_SMA_PAYLOAD_LEN 2048 - -/** SMA number of send WQEs - * - * This is a policy decision. - */ -#define IB_SMA_NUM_SEND_WQES 4 - -/** SMA number of receive WQEs - * - * This is a policy decision. - */ -#define IB_SMA_NUM_RECV_WQES 2 - -/** SMA number of completion queue entries - * - * This is a policy decision - */ -#define IB_SMA_NUM_CQES 8 - -extern int ib_create_sma ( struct ib_sma *sma, struct ib_device *ibdev, - struct ib_sma_operations *op ); -extern void ib_destroy_sma ( struct ib_sma *sma ); +extern int ib_create_sma ( struct ib_device *ibdev, + struct ib_mad_interface *mi ); +extern void ib_destroy_sma ( struct ib_device *ibdev, + struct ib_mad_interface *mi ); #endif /* _GPXE_IB_SMA_H */ diff --git a/gpxe/src/include/gpxe/ib_smc.h b/gpxe/src/include/gpxe/ib_smc.h index bb9020bf..fdd1c9cc 100644 --- a/gpxe/src/include/gpxe/ib_smc.h +++ b/gpxe/src/include/gpxe/ib_smc.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/infiniband.h> typedef int ( * ib_local_mad_t ) ( struct ib_device *ibdev, diff --git a/gpxe/src/include/gpxe/ib_srp.h b/gpxe/src/include/gpxe/ib_srp.h new file mode 100644 index 00000000..cf705b30 --- /dev/null +++ b/gpxe/src/include/gpxe/ib_srp.h @@ -0,0 +1,79 @@ +#ifndef _GPXE_IB_SRP_H +#define _GPXE_IB_SRP_H + +/** @file + * + * SCSI RDMA Protocol over Infiniband + * + */ + +FILE_LICENCE ( BSD2 ); + +#include <stdint.h> +#include <gpxe/infiniband.h> +#include <gpxe/srp.h> + +/** SRP initiator port identifier for Infiniband */ +struct ib_srp_initiator_port_id { + /** Identifier extension */ + struct ib_gid_half id_ext; + /** IB channel adapter GUID */ + struct ib_gid_half hca_guid; +} __attribute__ (( packed )); + +/** SRP target port identifier for Infiniband */ +struct ib_srp_target_port_id { + /** Identifier extension */ + struct ib_gid_half id_ext; + /** I/O controller GUID */ + struct ib_gid_half ioc_guid; +} __attribute__ (( packed )); + +/** + * Get Infiniband-specific initiator port ID + * + * @v port_ids SRP port IDs + * @ret initiator_port_id Infiniband-specific initiator port ID + */ +static inline __always_inline struct ib_srp_initiator_port_id * +ib_srp_initiator_port_id ( struct srp_port_ids *port_ids ) { + return ( ( struct ib_srp_initiator_port_id * ) &port_ids->initiator ); +} + +/** + * Get Infiniband-specific target port ID + * + * @v port_ids SRP port IDs + * @ret target_port_id Infiniband-specific target port ID + */ +static inline __always_inline struct ib_srp_target_port_id * +ib_srp_target_port_id ( struct srp_port_ids *port_ids ) { + return ( ( struct ib_srp_target_port_id * ) &port_ids->target ); +} + +/** Infiniband-specific SRP parameters */ +struct ib_srp_parameters { + /** Source GID */ + struct ib_gid sgid; + /** Destination GID */ + struct ib_gid dgid; + /** Service ID */ + struct ib_gid_half service_id; + /** Partition key */ + uint16_t pkey; +}; + +/** + * Get Infiniband-specific transport parameters + * + * @v srp SRP device + * @ret ib_params Infiniband-specific transport parameters + */ +static inline __always_inline struct ib_srp_parameters * +ib_srp_params ( struct srp_device *srp ) { + return srp_transport_priv ( srp ); +} + +extern struct srp_transport_type ib_srp_transport; + +#endif /* _GPXE_IB_SRP_H */ diff --git a/gpxe/src/include/gpxe/icmp.h b/gpxe/src/include/gpxe/icmp.h index 49ade2f2..bb8fce8b 100644 --- a/gpxe/src/include/gpxe/icmp.h +++ b/gpxe/src/include/gpxe/icmp.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** An ICMP header */ struct icmp_header { /** Type */ diff --git a/gpxe/src/include/gpxe/icmp6.h b/gpxe/src/include/gpxe/icmp6.h index 34093616..e8fd1eb3 100644 --- a/gpxe/src/include/gpxe/icmp6.h +++ b/gpxe/src/include/gpxe/icmp6.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/ip6.h> #include <gpxe/ndp.h> diff --git a/gpxe/src/include/gpxe/ieee80211.h b/gpxe/src/include/gpxe/ieee80211.h new file mode 100644 index 00000000..e5b10c30 --- /dev/null +++ b/gpxe/src/include/gpxe/ieee80211.h @@ -0,0 +1,1160 @@ +#ifndef _GPXE_IEEE80211_H +#define _GPXE_IEEE80211_H + +#include <gpxe/if_ether.h> /* for ETH_ALEN */ +#include <endian.h> + +/** @file + * Constants and data structures defined in IEEE 802.11, subsetted + * according to what gPXE knows how to use. + */ + +FILE_LICENCE(GPL2_OR_LATER); + +/* ---------- Maximum lengths of things ---------- */ + +/** + * @defgroup ieee80211_maxlen Maximum lengths in the 802.11 protocol + * @{ + */ + +/** Maximum length of frame payload + * + * This does not include cryptographic overhead, which can be up to 20 + * bytes, but it DOES include the 802.2 LLC/SNAP headers that are used + * on data frames (but not management frames). + */ +#define IEEE80211_MAX_DATA_LEN 2304 + +/** Length of LLC/SNAP headers on data frames */ +#define IEEE80211_LLC_HEADER_LEN 8 + +/** Maximum cryptographic overhead before encrypted data */ +#define IEEE80211_MAX_CRYPTO_HEADER 8 + +/** Maximum cryptographic overhead after encrypted data + * + * This does not count the MIC in TKIP frames, since that is + * considered to be part of the MSDU and thus contributes to the size + * of the data field. + * + * It @e does count the MIC in CCMP frames, which is considered part + * of the MPDU (outside the data field). + */ +#define IEEE80211_MAX_CRYPTO_TRAILER 8 + +/** Total maximum cryptographic overhead */ +#define IEEE80211_MAX_CRYPTO_OVERHEAD 16 + +/** Bytes of network-layer data that can go into a regular data frame */ +#define IEEE80211_MAX_FRAME_DATA 2296 + +/** Frame header length for frames we might work with + * + * QoS adds a two-byte field on top of this, and APs communicating + * with each other in Wireless Distribution System (WDS) mode add an + * extra 6-byte MAC address field, but we do not work with such + * frames. + */ +#define IEEE80211_TYP_FRAME_HEADER_LEN 24 + +/** Theoretical maximum frame header length + * + * This includes the QoS and WDS Addr4 fields that we should never + * see. + */ +#define IEEE80211_MAX_FRAME_HEADER_LEN 32 + +/** Maximum combined frame length + * + * The biggest frame will include 32 frame header bytes, 16 bytes of + * crypto overhead, and 2304 data bytes. + */ +#define IEEE80211_MAX_FRAME_LEN 2352 + +/** Maximum length of an ESSID */ +#define IEEE80211_MAX_SSID_LEN 32 + +/** @} */ + + +/* ---------- Frame Control defines ---------- */ + +/** + * @defgroup ieee80211_fc 802.11 Frame Control field bits + * @{ + */ + +/** 802.11 Frame Control field, Version bitmask */ +#define IEEE80211_FC_VERSION 0x0003 + +/** Expected value of Version bits in Frame Control */ +#define IEEE80211_THIS_VERSION 0x0000 + + +/** 802.11 Frame Control field, Frame Type bitmask */ +#define IEEE80211_FC_TYPE 0x000C + +/** Type value for management (layer-2) frames */ +#define IEEE80211_TYPE_MGMT 0x0000 + +/** Type value for control (layer-1, hardware-managed) frames */ +#define IEEE80211_TYPE_CTRL 0x0004 + +/** Type value for data frames */ +#define IEEE80211_TYPE_DATA 0x0008 + + +/** 802.11 Frame Control field, Frame Subtype bitmask */ +#define IEEE80211_FC_SUBTYPE 0x00F0 + +/** Subtype value for association-request management frames + * + * Association request frames are sent after authentication from the + * client to the Access Point to establish the client as part of the + * Access Point's network. + */ +#define IEEE80211_STYPE_ASSOC_REQ 0x0000 + +/** Subtype value for association-response management frames + * + * Association response frames are sent by the Access Point to confirm + * or deny the association requested in an association request frame. + */ +#define IEEE80211_STYPE_ASSOC_RESP 0x0010 + +/** Subtype value for reassociation-request management frames + * + * Reassociation request frames are sent by clients wishing to change + * from one Access Point to another while roaming within the same + * extended network (same ESSID). + */ +#define IEEE80211_STYPE_REASSOC_REQ 0x0020 + +/** Subtype value for reassociation-response management frames + * + * Reassociation response frames are sent by the Access Point to + * confirm or deny the swap requested in a reassociation request + * frame. + */ +#define IEEE80211_STYPE_REASSOC_RESP 0x0030 + +/** Subtype value for probe-request management frames + * + * Probe request frames are sent by clients to request that all Access + * Points on the sending channel, or all belonging to a particular + * ESSID, identify themselves by BSSID, supported transfer rates, RF + * configuration, and other capabilities. + */ +#define IEEE80211_STYPE_PROBE_REQ 0x0040 + +/** Subtype value for probe-response management frames + * + * Probe response frames are sent by Access Points in response to + * probe request frames, providing the requested information. + */ +#define IEEE80211_STYPE_PROBE_RESP 0x0050 + +/** Subtype value for beacon management frames + * + * Beacon frames are sent by Access Points at regular intervals, + * usually ten per second, on the channel on which they communicate. + * They can be used to probe passively for access points on a channel + * where local regulatory restrictions prohibit active scanning, or + * due to their regularity as a mechanism to determine the fraction of + * packets that are being dropped. + */ +#define IEEE80211_STYPE_BEACON 0x0080 + +/** Subtype value for disassociation management frames + * + * Disassociation frames are sent by either a client or an Access + * Point to unequivocally terminate the association between the two. + * They may be sent by clients upon leaving the network, or by an + * Access Point upon reconfiguration, among other reasons; they are + * usually more "polite" than deauthentication frames. + */ +#define IEEE80211_STYPE_DISASSOC 0x00A0 + +/** Subtype value for authentication management frames + * + * Authentication frames are exchanged between a client and an Access + * Point before association may be performed. Confusingly, in the most + * common authentication method (Open System) no security tokens are + * exchanged at all. Modern 802.11 security handshaking takes place + * after association. + */ +#define IEEE80211_STYPE_AUTH 0x00B0 + +/** Subtype value for deauthentication management frames + * + * Deauthentication frames are sent by either a client or an Access + * Point to terminate the authentication (and therefore also the + * association) between the two. They are generally more forceful than + * disassociation frames, sent for such reasons as a failure to + * set up security properly after associating. + */ +#define IEEE80211_STYPE_DEAUTH 0x00C0 + +/** Subtype value for action management frames + * + * Action frames are used to implement spectrum management and QoS + * features that gPXE currently does not support. + */ +#define IEEE80211_STYPE_ACTION 0x00D0 + + +/** Subtype value for RTS (request to send) control frames */ +#define IEEE80211_STYPE_RTS 0x00B0 + +/** Subtype value for CTS (clear to send) control frames */ +#define IEEE80211_STYPE_CTS 0x00C0 + +/** Subtype value for ACK (acknowledgement) control frames */ +#define IEEE80211_STYPE_ACK 0x00D0 + + +/** Subtype value for ordinary data frames, with no QoS or CF add-ons */ +#define IEEE80211_STYPE_DATA 0x0000 + +/** Subtype value for data frames containing no data */ +#define IEEE80211_STYPE_NODATA 0x0040 + + +/** 802.11 Frame Control field: To Data System flag + * + * This is set on data frames sent to an Access Point. + */ +#define IEEE80211_FC_TODS 0x0100 + +/** 802.11 Frame Control field: From Data System flag + * + * This is set on data frames sent from an Access Point. If both TODS + * and FROMDS are set, the frame header is a 4-address format used for + * inter-Access Point communication. + */ +#define IEEE80211_FC_FROMDS 0x0200 + +/** 802.11 Frame Control field: More Fragments flag */ +#define IEEE80211_FC_MORE_FRAG 0x0400 + +/** 802.11 Frame Control field: Retransmission flag */ +#define IEEE80211_FC_RETRY 0x0800 + +/** 802.11 Frame Control field: Power Managed flag + * + * This is set on any frame sent by a low-power station that will go + * into a power-saving mode immediately after this frame. Access + * Points are not allowed to act as low-power stations. + */ +#define IEEE80211_FC_PWR_MGMT 0x1000 + +/** 802.11 Frame Control field: More Data flag + * + * This is set on any frame sent by a station that has more data + * queued to be sent than is in the frame. + */ +#define IEEE80211_FC_MORE_DATA 0x2000 + +/** 802.11 Frame Control field: Protected flag + * + * This is set on frames in which data is encrypted (by any method). + */ +#define IEEE80211_FC_PROTECTED 0x4000 + +/** 802.11 Frame Control field: Ordered flag [?] */ +#define IEEE80211_FC_ORDER 0x8000 + +/** @} */ + + +/* ---------- Sequence Control defines ---------- */ + +/** + * @defgroup ieee80211_seq 802.11 Sequence Control field handling + * @{ + */ + +/** Extract sequence number from 802.11 Sequence Control field */ +#define IEEE80211_SEQNR( seq ) ( ( seq ) >> 4 ) + +/** Extract fragment number from 802.11 Sequence Control field */ +#define IEEE80211_FRAG( seq ) ( ( seq ) & 0x000F ) + +/** Make 802.11 Sequence Control field from sequence and fragment numbers */ +#define IEEE80211_MAKESEQ( seqnr, frag ) \ + ( ( ( ( seqnr ) & 0xFFF ) << 4 ) | ( ( frag ) & 0xF ) ) + +/** @} */ + + +/* ---------- Frame header formats ---------- */ + +/** + * @defgroup ieee80211_hdr 802.11 frame header formats + * @{ + */ + +/** An 802.11 data or management frame without QoS or WDS header fields */ +struct ieee80211_frame +{ + u16 fc; /**< 802.11 Frame Control field */ + u16 duration; /**< Microseconds to reserve link */ + u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */ + u8 addr2[ETH_ALEN]; /**< Address 2 (immediate sender) */ + u8 addr3[ETH_ALEN]; /**< Address 3 (often "forward to") */ + u16 seq; /**< 802.11 Sequence Control field */ + u8 data[0]; /**< Beginning of frame data */ +} __attribute__((packed)); + +/** The 802.2 LLC/SNAP header sent before actual data in a data frame + * + * This header is not acknowledged in the 802.11 standard at all; it + * is treated just like data for MAC-layer purposes, including + * fragmentation and encryption. It is actually two headers + * concatenated: a three-byte 802.2 LLC header indicating Subnetwork + * Accesss Protocol (SNAP) in both source and destination Service + * Access Point (SAP) fields, and a five-byte SNAP header indicating a + * zero OUI and two-byte Ethernet protocol type field. + * + * Thus, an eight-byte header in which six of the bytes are redundant. + * Lovely, isn't it? + */ +struct ieee80211_llc_snap_header +{ + /* LLC part: */ + u8 dsap; /**< Destination SAP ID */ + u8 ssap; /**< Source SAP ID */ + u8 ctrl; /**< Control information */ + + /* SNAP part: */ + u8 oui[3]; /**< Organization code, usually 0 */ + u16 ethertype; /**< Ethernet Type field */ +} __attribute__((packed)); + +/** Value for DSAP field in 802.2 LLC header for 802.11 frames: SNAP */ +#define IEEE80211_LLC_DSAP 0xAA + +/** Value for SSAP field in 802.2 LLC header for 802.11 frames: SNAP */ +#define IEEE80211_LLC_SSAP 0xAA + +/** Value for control field in 802.2 LLC header for 802.11 frames + * + * "Unnumbered Information". + */ +#define IEEE80211_LLC_CTRL 0x03 + + +/** 16-byte RTS frame format, with abbreviated header */ +struct ieee80211_rts +{ + u16 fc; /**< 802.11 Frame Control field */ + u16 duration; /**< Microseconds to reserve link */ + u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */ + u8 addr2[ETH_ALEN]; /**< Address 2 (immediate sender) */ +} __attribute__((packed)); + +/** Length of 802.11 RTS control frame */ +#define IEEE80211_RTS_LEN 16 + +/** 10-byte CTS or ACK frame format, with abbreviated header */ +struct ieee80211_cts_or_ack +{ + u16 fc; /**< 802.11 Frame Control field */ + u16 duration; /**< Microseconds to reserve link */ + u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */ +} __attribute__((packed)); + +#define ieee80211_cts ieee80211_cts_or_ack +#define ieee80211_ack ieee80211_cts_or_ack + +/** Length of 802.11 CTS control frame */ +#define IEEE80211_CTS_LEN 10 + +/** Length of 802.11 ACK control frame */ +#define IEEE80211_ACK_LEN 10 + +/** @} */ + + +/* ---------- Capability bits, status and reason codes ---------- */ + +/** + * @defgroup ieee80211_capab 802.11 management frame capability field bits + * @{ + */ + +/** Set if using an Access Point (managed mode) */ +#define IEEE80211_CAPAB_MANAGED 0x0001 + +/** Set if operating in IBSS (no-AP, "Ad-Hoc") mode */ +#define IEEE80211_CAPAB_ADHOC 0x0002 + +/** Set if we support Contention-Free Period operation */ +#define IEEE80211_CAPAB_CFPOLL 0x0004 + +/** Set if we wish to be polled for Contention-Free operation */ +#define IEEE80211_CAPAB_CFPR 0x0008 + +/** Set if the network is encrypted (by any method) */ +#define IEEE80211_CAPAB_PRIVACY 0x0010 + +/** Set if PHY supports short preambles on 802.11b */ +#define IEEE80211_CAPAB_SHORT_PMBL 0x0020 + +/** Set if PHY supports PBCC modulation */ +#define IEEE80211_CAPAB_PBCC 0x0040 + +/** Set if we support Channel Agility */ +#define IEEE80211_CAPAB_CHAN_AGILITY 0x0080 + +/** Set if we support spectrum management (DFS and TPC) on the 5GHz band */ +#define IEEE80211_CAPAB_SPECTRUM_MGMT 0x0100 + +/** Set if we support Quality of Service enhancements */ +#define IEEE80211_CAPAB_QOS 0x0200 + +/** Set if PHY supports short slot time on 802.11g */ +#define IEEE80211_CAPAB_SHORT_SLOT 0x0400 + +/** Set if PHY supports APSD option */ +#define IEEE80211_CAPAB_APSD 0x0800 + +/** Set if PHY supports DSSS/OFDM modulation (one way of 802.11 b/g mixing) */ +#define IEEE80211_CAPAB_DSSS_OFDM 0x2000 + +/** Set if we support delayed block ACK */ +#define IEEE80211_CAPAB_DELAYED_BACK 0x4000 + +/** Set if we support immediate block ACK */ +#define IEEE80211_CAPAB_IMMED_BACK 0x8000 + +/** @} */ + + +/** + * @defgroup ieee80211_status 802.11 status codes + * + * These are returned to indicate an immediate denial of + * authentication or association. In gPXE, the lower 5 bits of the + * status code are encoded into the file-unique portion of an error + * code, the ERRFILE portion is always @c ERRFILE_net80211, and the + * POSIX error code is @c ECONNREFUSED for status 0-31 or @c + * EHOSTUNREACH for status 32-63. + * + * For a complete table with non-abbreviated error messages, see IEEE + * Std 802.11-2007, Table 7-23, p.94. + * + * @{ + */ + +#define IEEE80211_STATUS_SUCCESS 0 +#define IEEE80211_STATUS_FAILURE 1 +#define IEEE80211_STATUS_CAPAB_UNSUPP 10 +#define IEEE80211_STATUS_REASSOC_INVALID 11 +#define IEEE80211_STATUS_ASSOC_DENIED 12 +#define IEEE80211_STATUS_AUTH_ALGO_UNSUPP 13 +#define IEEE80211_STATUS_AUTH_SEQ_INVALID 14 +#define IEEE80211_STATUS_AUTH_CHALL_INVALID 15 +#define IEEE80211_STATUS_AUTH_TIMEOUT 16 +#define IEEE80211_STATUS_ASSOC_NO_ROOM 17 +#define IEEE80211_STATUS_ASSOC_NEED_RATE 18 +#define IEEE80211_STATUS_ASSOC_NEED_SHORT_PMBL 19 +#define IEEE80211_STATUS_ASSOC_NEED_PBCC 20 +#define IEEE80211_STATUS_ASSOC_NEED_CHAN_AGILITY 21 +#define IEEE80211_STATUS_ASSOC_NEED_SPECTRUM_MGMT 22 +#define IEEE80211_STATUS_ASSOC_BAD_POWER 23 +#define IEEE80211_STATUS_ASSOC_BAD_CHANNELS 24 +#define IEEE80211_STATUS_ASSOC_NEED_SHORT_SLOT 25 +#define IEEE80211_STATUS_ASSOC_NEED_DSSS_OFDM 26 +#define IEEE80211_STATUS_QOS_FAILURE 32 +#define IEEE80211_STATUS_QOS_NO_ROOM 33 +#define IEEE80211_STATUS_LINK_IS_HORRIBLE 34 +#define IEEE80211_STATUS_ASSOC_NEED_QOS 35 +#define IEEE80211_STATUS_REQUEST_DECLINED 37 +#define IEEE80211_STATUS_REQUEST_INVALID 38 +#define IEEE80211_STATUS_TS_NOT_CREATED_AGAIN 39 +#define IEEE80211_STATUS_INVALID_IE 40 +#define IEEE80211_STATUS_GROUP_CIPHER_INVALID 41 +#define IEEE80211_STATUS_PAIR_CIPHER_INVALID 42 +#define IEEE80211_STATUS_AKMP_INVALID 43 +#define IEEE80211_STATUS_RSN_VERSION_UNSUPP 44 +#define IEEE80211_STATUS_RSN_CAPAB_INVALID 45 +#define IEEE80211_STATUS_CIPHER_REJECTED 46 +#define IEEE80211_STATUS_TS_NOT_CREATED_WAIT 47 +#define IEEE80211_STATUS_DIRECT_LINK_FORBIDDEN 48 +#define IEEE80211_STATUS_DEST_NOT_PRESENT 49 +#define IEEE80211_STATUS_DEST_NOT_QOS 50 +#define IEEE80211_STATUS_ASSOC_LISTEN_TOO_HIGH 51 + +/** @} */ + + + +/** + * @defgroup ieee80211_reason 802.11 reason codes + * + * These are returned to indicate the reason for a deauthentication or + * disassociation sent (usually) after authentication or association + * had succeeded. In gPXE, the lower 5 bits of the reason code are + * encoded into the file-unique portion of an error code, the ERRFILE + * portion is always @c ERRFILE_net80211, and the POSIX error code is + * @c ECONNRESET for reason 0-31 or @c ENETRESET for reason 32-63. + * + * For a complete table with non-abbreviated error messages, see IEEE + * Std 802.11-2007, Table 7-22, p.92. + * + * @{ + */ + +#define IEEE80211_REASON_NONE 0 +#define IEEE80211_REASON_UNSPECIFIED 1 +#define IEEE80211_REASON_AUTH_NO_LONGER_VALID 2 +#define IEEE80211_REASON_LEAVING 3 +#define IEEE80211_REASON_INACTIVITY 4 +#define IEEE80211_REASON_OUT_OF_RESOURCES 5 +#define IEEE80211_REASON_NEED_AUTH 6 +#define IEEE80211_REASON_NEED_ASSOC 7 +#define IEEE80211_REASON_LEAVING_TO_ROAM 8 +#define IEEE80211_REASON_REASSOC_INVALID 9 +#define IEEE80211_REASON_BAD_POWER 10 +#define IEEE80211_REASON_BAD_CHANNELS 11 +#define IEEE80211_REASON_INVALID_IE 13 +#define IEEE80211_REASON_MIC_FAILURE 14 +#define IEEE80211_REASON_4WAY_TIMEOUT 15 +#define IEEE80211_REASON_GROUPKEY_TIMEOUT 16 +#define IEEE80211_REASON_4WAY_INVALID 17 +#define IEEE80211_REASON_GROUP_CIPHER_INVALID 18 +#define IEEE80211_REASON_PAIR_CIPHER_INVALID 19 +#define IEEE80211_REASON_AKMP_INVALID 20 +#define IEEE80211_REASON_RSN_VERSION_INVALID 21 +#define IEEE80211_REASON_RSN_CAPAB_INVALID 22 +#define IEEE80211_REASON_8021X_FAILURE 23 +#define IEEE80211_REASON_CIPHER_REJECTED 24 +#define IEEE80211_REASON_QOS_UNSPECIFIED 32 +#define IEEE80211_REASON_QOS_OUT_OF_RESOURCES 33 +#define IEEE80211_REASON_LINK_IS_HORRIBLE 34 +#define IEEE80211_REASON_INVALID_TXOP 35 +#define IEEE80211_REASON_REQUESTED_LEAVING 36 +#define IEEE80211_REASON_REQUESTED_NO_USE 37 +#define IEEE80211_REASON_REQUESTED_NEED_SETUP 38 +#define IEEE80211_REASON_REQUESTED_TIMEOUT 39 +#define IEEE80211_REASON_CIPHER_UNSUPPORTED 45 + +/** @} */ + +/* ---------- Information element declarations ---------- */ + +/** + * @defgroup ieee80211_ie 802.11 information elements + * + * Many management frames include a section that amounts to a + * concatenation of these information elements, so that the sender can + * choose which information to send and the receiver can ignore the + * parts it doesn't understand. Each IE contains a two-byte header, + * one byte ID and one byte length, followed by IE-specific data. The + * length does not include the two-byte header. Information elements + * are required to be sorted by ID, but gPXE does not require that in + * those it receives. + * + * This group also includes a few inline functions to simplify common + * tasks in IE processing. + * + * @{ + */ + +/** Generic 802.11 information element header */ +struct ieee80211_ie_header { + u8 id; /**< Information element ID */ + u8 len; /**< Information element length */ +} __attribute__ ((packed)); + + +/** 802.11 SSID information element */ +struct ieee80211_ie_ssid { + u8 id; /**< SSID ID: 0 */ + u8 len; /**< SSID length */ + char ssid[0]; /**< SSID data, not NUL-terminated */ +} __attribute__ ((packed)); + +/** Information element ID for SSID information element */ +#define IEEE80211_IE_SSID 0 + + +/** 802.11 rates information element + * + * The first 8 rates go in an IE of type RATES (1), and any more rates + * go in one of type EXT_RATES (50). Each rate is a byte with the low + * 7 bits equal to the rate in units of 500 kbps, and the high bit set + * if and only if the rate is "basic" (must be supported by all + * connected stations). + */ +struct ieee80211_ie_rates { + u8 id; /**< Rates ID: 1 or 50 */ + u8 len; /**< Number of rates */ + u8 rates[0]; /**< Rates data, one rate per byte */ +} __attribute__ ((packed)); + +/** Information element ID for rates information element */ +#define IEEE80211_IE_RATES 1 + +/** Information element ID for extended rates information element */ +#define IEEE80211_IE_EXT_RATES 50 + + +/** 802.11 Direct Spectrum parameter information element + * + * This just contains the channel number. It has the fancy name + * because IEEE 802.11 also defines a frequency-hopping PHY that + * changes channels at regular intervals following a predetermined + * pattern; in practice nobody uses the FH PHY. + */ +struct ieee80211_ie_ds_param { + u8 id; /**< DS parameter ID: 3 */ + u8 len; /**< DS parameter length: 1 */ + u8 current_channel; /**< Current channel number, 1-14 */ +} __attribute__ ((packed)); + +/** Information element ID for Direct Spectrum parameter information element */ +#define IEEE80211_IE_DS_PARAM 3 + + +/** 802.11 Country information element regulatory extension triplet */ +struct ieee80211_ie_country_ext_triplet { + u8 reg_ext_id; /**< Regulatory extension ID */ + u8 reg_class_id; /**< Regulatory class ID */ + u8 coverage_class; /**< Coverage class */ +} __attribute__ ((packed)); + +/** 802.11 Country information element regulatory band triplet */ +struct ieee80211_ie_country_band_triplet { + u8 first_channel; /**< Channel number for first channel in band */ + u8 nr_channels; /**< Number of contiguous channels in band */ + u8 max_txpower; /**< Maximum TX power in dBm */ +} __attribute__ ((packed)); + +/** 802.11 Country information element regulatory triplet + * + * It is a band triplet if the first byte is 200 or less, and a + * regulatory extension triplet otherwise. + */ +union ieee80211_ie_country_triplet { + /** Differentiator between band and ext triplets */ + u8 first; + + /** Information about a band of channels */ + struct ieee80211_ie_country_band_triplet band; + + /** Regulatory extension information */ + struct ieee80211_ie_country_ext_triplet ext; +}; + +/** 802.11 Country information element + * + * This contains some data about RF regulations. + */ +struct ieee80211_ie_country { + u8 id; /**< Country information ID: 7 */ + u8 len; /**< Country information length: varies */ + char name[2]; /**< ISO Alpha2 country code */ + char in_out; /**< 'I' for indoor, 'O' for outdoor */ + + /** List of regulatory triplets */ + union ieee80211_ie_country_triplet triplet[0]; +} __attribute__ ((packed)); + +/** Information element ID for Country information element */ +#define IEEE80211_IE_COUNTRY 7 + + +/** 802.11 Request information element + * + * This contains a list of information element types we would like to + * be included in probe response frames. + */ +struct ieee80211_ie_request { + u8 id; /**< Request ID: 10 */ + u8 len; /**< Number of IEs requested */ + u8 request[0]; /**< List of IEs requested */ +} __attribute__ ((packed)); + +/** Information element ID for Request information element */ +#define IEEE80211_IE_REQUEST 10 + + +/** 802.11 Challenge Text information element + * + * This is used in authentication frames under Shared Key + * authentication. + */ +struct ieee80211_ie_challenge_text { + u8 id; /**< Challenge Text ID: 16 */ + u8 len; /**< Challenge Text length: usually 128 */ + u8 challenge_text[0]; /**< Challenge Text data */ +} __attribute__ ((packed)); + +/** Information element ID for Challenge Text information element */ +#define IEEE80211_IE_CHALLENGE_TEXT 16 + + +/** 802.11 Power Constraint information element + * + * This is used to specify an additional power limitation on top of + * the Country requirements. + */ +struct ieee80211_ie_power_constraint { + u8 id; /**< Power Constraint ID: 52 */ + u8 len; /**< Power Constraint length: 1 */ + u8 power_constraint; /**< Decrease in allowed TX power, dBm */ +} __attribute__ ((packed)); + +/** Information element ID for Power Constraint information element */ +#define IEEE80211_IE_POWER_CONSTRAINT 52 + + +/** 802.11 Power Capability information element + * + * This is used in association request frames to indicate the extremes + * of our TX power abilities. It is required only if we indicate + * support for spectrum management. + */ +struct ieee80211_ie_power_capab { + u8 id; /**< Power Capability ID: 33 */ + u8 len; /**< Power Capability length: 2 */ + u8 min_txpower; /**< Minimum possible TX power, dBm */ + u8 max_txpower; /**< Maximum possible TX power, dBm */ +} __attribute__ ((packed)); + +/** Information element ID for Power Capability information element */ +#define IEEE80211_IE_POWER_CAPAB 33 + + +/** 802.11 Channels information element channel band tuple */ +struct ieee80211_ie_channels_channel_band { + u8 first_channel; /**< Channel number of first channel in band */ + u8 nr_channels; /**< Number of channels in band */ +} __attribute__ ((packed)); + +/** 802.11 Channels information element + * + * This is used in association frames to indicate the channels we can + * use. It is required only if we indicate support for spectrum + * management. + */ +struct ieee80211_ie_channels { + u8 id; /**< Channels ID: 36 */ + u8 len; /**< Channels length: 2 */ + + /** List of (start, length) channel bands we can use */ + struct ieee80211_ie_channels_channel_band channels[0]; +} __attribute__ ((packed)); + +/** Information element ID for Channels information element */ +#define IEEE80211_IE_CHANNELS 36 + + +/** 802.11 ERP Information information element + * + * This is used to communicate some PHY-level flags. + */ +struct ieee80211_ie_erp_info { + u8 id; /**< ERP Information ID: 42 */ + u8 len; /**< ERP Information length: 1 */ + u8 erp_info; /**< ERP flags */ +} __attribute__ ((packed)); + +/** Information element ID for ERP Information information element */ +#define IEEE80211_IE_ERP_INFO 42 + +/** ERP information element: Flag set if 802.11b stations are present */ +#define IEEE80211_ERP_NONERP_PRESENT 0x01 + +/** ERP information element: Flag set if CTS protection must be used */ +#define IEEE80211_ERP_USE_PROTECTION 0x02 + +/** ERP information element: Flag set if long preambles must be used */ +#define IEEE80211_ERP_BARKER_LONG 0x04 + + +/** 802.11 Robust Security Network ("WPA") information element + * + * Showing once again a striking clarity of design, the IEEE folks put + * dynamically-sized data in the middle of this structure. As such, + * the below structure definition only works for IEs we create + * ourselves, which always have one pairwise cipher and one AKM; + * received IEs should be parsed piecemeal. + * + * Also inspired was IEEE's choice of 16-bit fields to count the + * number of 4-byte elements in a structure with a maximum length of + * 255 bytes. + * + * Many fields reference a cipher or authentication-type ID; this is a + * three-byte OUI followed by one byte identifying the cipher with + * respect to that OUI. For all standard ciphers the OUI is 00:0F:AC, + * except in old-style WPA IEs encapsulated in vendor-specific IEs, + * where it's 00:50:F2. + */ +struct ieee80211_ie_rsn { + /** Information element ID */ + u8 id; + + /** Information element length */ + u8 len; + + /** RSN information element version */ + u16 version; + + /** Cipher ID for the cipher used in multicast/broadcast frames */ + u32 group_cipher; + + /** Number of unicast ciphers supported */ + u16 pairwise_count; + + /** List of cipher IDs for supported unicast frame ciphers */ + u32 pairwise_cipher[1]; + + /** Number of authentication types supported */ + u16 akm_count; + + /** List of authentication type IDs for supported types */ + u32 akm_list[1]; + + /** Security capabilities field (RSN only) */ + u16 rsn_capab; + + /** Number of PMKIDs included (present only in association frames) */ + u16 pmkid_count; + + /** List of PMKIDs included, each a 16-byte SHA1 hash */ + u8 pmkid_list[0]; +} __attribute__((packed)); + +/** Information element ID for Robust Security Network information element */ +#define IEEE80211_IE_RSN 48 + +/** Calculate necessary size of RSN information element + * + * @v npair Number of pairwise ciphers supported + * @v nauth Number of authentication types supported + * @v npmkid Number of PMKIDs to include + * @v is_rsn If TRUE, calculate RSN IE size; if FALSE, calculate WPA IE size + * @ret size Necessary size of IE, including header bytes + */ +static inline size_t ieee80211_rsn_size ( int npair, int nauth, int npmkid, + int rsn_ie ) { + return 16 + 4 * ( npair + nauth ) + 16 * npmkid - 4 * ! rsn_ie; +} + +/** Make OUI plus type byte into 32-bit integer for easy comparison */ +#if __BYTE_ORDER == __BIG_ENDIAN +#define _MKOUI( a, b, c, t ) \ + ( ( ( a ) << 24 ) | ( ( b ) << 16 ) | ( ( c ) << 8 ) | ( d ) ) +#define OUI_ORG_MASK 0xFFFFFF00 +#define OUI_TYPE_MASK 0x000000FF +#else +#define _MKOUI( a, b, c, t ) \ + ( ( ( t ) << 24 ) | ( ( c ) << 16 ) | ( ( b ) << 8 ) | ( a ) ) +#define OUI_ORG_MASK 0x00FFFFFF +#define OUI_TYPE_MASK 0xFF000000 +#endif + +/** Organization part for OUIs in standard RSN IE */ +#define IEEE80211_RSN_OUI _MKOUI ( 0x00, 0x0F, 0xAC, 0 ) + +/** Organization part for OUIs in old WPA IE */ +#define IEEE80211_WPA_OUI _MKOUI ( 0x00, 0x50, 0xF2, 0 ) + +/** Old vendor-type WPA IE OUI type + subtype */ +#define IEEE80211_WPA_OUI_VEN _MKOUI ( 0x00, 0x50, 0xF2, 0x01 ) + + +/** 802.11 RSN IE: expected version number */ +#define IEEE80211_RSN_VERSION 1 + +/** 802.11 RSN IE: cipher type for 40-bit WEP */ +#define IEEE80211_RSN_CTYPE_WEP40 _MKOUI ( 0, 0, 0, 0x01 ) + +/** 802.11 RSN IE: cipher type for 104-bit WEP */ +#define IEEE80211_RSN_CTYPE_WEP104 _MKOUI ( 0, 0, 0, 0x05 ) + +/** 802.11 RSN IE: cipher type for TKIP ("WPA") */ +#define IEEE80211_RSN_CTYPE_TKIP _MKOUI ( 0, 0, 0, 0x02 ) + +/** 802.11 RSN IE: cipher type for CCMP ("WPA2") */ +#define IEEE80211_RSN_CTYPE_CCMP _MKOUI ( 0, 0, 0, 0x04 ) + +/** 802.11 RSN IE: cipher type for "use group" + * + * This can only appear as a pairwise cipher, and means unicast frames + * should be encrypted in the same way as broadcast/multicast frames. + */ +#define IEEE80211_RSN_CTYPE_USEGROUP _MKOUI ( 0, 0, 0, 0x00 ) + +/** 802.11 RSN IE: auth method type for using an 802.1X server */ +#define IEEE80211_RSN_ATYPE_8021X _MKOUI ( 0, 0, 0, 0x01 ) + +/** 802.11 RSN IE: auth method type for using a pre-shared key */ +#define IEEE80211_RSN_ATYPE_PSK _MKOUI ( 0, 0, 0, 0x02 ) + +/** 802.11 RSN IE capabilities: AP supports pre-authentication */ +#define IEEE80211_RSN_CAPAB_PREAUTH 0x001 + +/** 802.11 RSN IE capabilities: Node has conflict between TKIP and WEP + * + * This is a legacy issue; APs always set it to 0, and gPXE sets it to + * 0. + */ +#define IEEE80211_RSN_CAPAB_NO_PAIRWISE 0x002 + +/** 802.11 RSN IE capabilities: Number of PTKSA replay counters + * + * A value of 0 means one replay counter, 1 means two, 2 means four, + * and 3 means sixteen. + */ +#define IEEE80211_RSN_CAPAB_PTKSA_REPLAY 0x00C + +/** 802.11 RSN IE capabilities: Number of GTKSA replay counters + * + * A value of 0 means one replay counter, 1 means two, 2 means four, + * and 3 means sixteen. + */ +#define IEEE80211_RSN_CAPAB_GTKSA_REPLAY 0x030 + +/** 802.11 RSN IE capabilities: PeerKey Handshaking is suported */ +#define IEEE80211_RSN_CAPAB_PEERKEY 0x200 + + +/** 802.11 RSN IE capabilities: One replay counter + * + * This should be AND'ed with @c IEEE80211_RSN_CAPAB_PTKSA_REPLAY or + * @c IEEE80211_RSN_CAPAB_GTKSA_REPLAY (or both) to produce a value + * which can be OR'ed into the capabilities field. + */ +#define IEEE80211_RSN_1_CTR 0x000 + +/** 802.11 RSN IE capabilities: Two replay counters */ +#define IEEE80211_RSN_2_CTR 0x014 + +/** 802.11 RSN IE capabilities: Four replay counters */ +#define IEEE80211_RSN_4_CTR 0x028 + +/** 802.11 RSN IE capabilities: 16 replay counters */ +#define IEEE80211_RSN_16_CTR 0x03C + + +/** 802.11 Vendor Specific information element + * + * One often sees the RSN IE masquerading as vendor-specific on + * devices that were produced prior to 802.11i (the WPA amendment) + * being finalized. + */ +struct ieee80211_ie_vendor { + u8 id; /**< Vendor-specific ID: 221 */ + u8 len; /**< Vendor-specific length: variable */ + u32 oui; /**< OUI and vendor-specific type byte */ + u8 data[0]; /**< Vendor-specific data */ +} __attribute__ ((packed)); + +/** Information element ID for Vendor Specific information element */ +#define IEEE80211_IE_VENDOR 221 + + + + +/** Any 802.11 information element + * + * This is formatted for ease of use, so IEs with complex structures + * get referenced in full, while those with only one byte of data or a + * simple array are pulled in to avoid a layer of indirection like + * ie->channels.channels[0]. + */ +union ieee80211_ie +{ + /** Generic and simple information element info */ + struct { + u8 id; /**< Information element ID */ + u8 len; /**< Information element data length */ + union { + char ssid[0]; /**< SSID text */ + u8 rates[0]; /**< Rates data */ + u8 request[0]; /**< Request list */ + u8 challenge_text[0]; /**< Challenge text data */ + u8 power_constraint; /**< Power constraint, dBm */ + u8 erp_info; /**< ERP information flags */ + /** List of channels */ + struct ieee80211_ie_channels_channel_band channels[0]; + }; + }; + + /** DS parameter set */ + struct ieee80211_ie_ds_param ds_param; + + /** Country information */ + struct ieee80211_ie_country country; + + /** Power capability */ + struct ieee80211_ie_power_capab power_capab; + + /** Security information */ + struct ieee80211_ie_rsn rsn; + + /** Vendor-specific */ + struct ieee80211_ie_vendor vendor; +}; + +/** Check that 802.11 information element is bounded by buffer + * + * @v ie Information element + * @v end End of buffer in which information element is stored + * @ret ok TRUE if the IE is completely contained within the buffer + */ +static inline int ieee80211_ie_bound ( union ieee80211_ie *ie, void *end ) +{ + void *iep = ie; + return ( iep + 2 <= end && iep + 2 + ie->len <= end ); +} + +/** Advance to next 802.11 information element + * + * @v ie Current information element pointer + * @v end Pointer to first byte not in information element space + * @ret next Pointer to next information element, or NULL if no more + * + * When processing received IEs, @a end should be set to the I/O + * buffer tail pointer; when marshalling IEs for sending, @a end + * should be NULL. + */ +static inline union ieee80211_ie * ieee80211_next_ie ( union ieee80211_ie *ie, + void *end ) +{ + void *next_ie_byte = ( void * ) ie + ie->len + 2; + union ieee80211_ie *next_ie = next_ie_byte; + + if ( ! end ) + return next_ie; + + if ( ieee80211_ie_bound ( next_ie, end ) ) + return next_ie; + + return NULL; +} + +/** @} */ + + +/* ---------- Management frame data formats ---------- */ + +/** + * @defgroup ieee80211_mgmt_data Management frame data payloads + * @{ + */ + +/** Beacon or probe response frame data */ +struct ieee80211_beacon_or_probe_resp +{ + /** 802.11 TSFT value at frame send */ + u64 timestamp; + + /** Interval at which beacons are sent, in units of 1024 us */ + u16 beacon_interval; + + /** Capability flags */ + u16 capability; + + /** List of information elements */ + union ieee80211_ie info_element[0]; +} __attribute__((packed)); + +#define ieee80211_beacon ieee80211_beacon_or_probe_resp +#define ieee80211_probe_resp ieee80211_beacon_or_probe_resp + +/** Disassociation or deauthentication frame data */ +struct ieee80211_disassoc_or_deauth +{ + /** Reason code */ + u16 reason; +} __attribute__((packed)); + +#define ieee80211_disassoc ieee80211_disassoc_or_deauth +#define ieee80211_deauth ieee80211_disassoc_or_deauth + +/** Association request frame data */ +struct ieee80211_assoc_req +{ + /** Capability flags */ + u16 capability; + + /** Interval at which we wake up, in units of the beacon interval */ + u16 listen_interval; + + /** List of information elements */ + union ieee80211_ie info_element[0]; +} __attribute__((packed)); + +/** Association or reassociation response frame data */ +struct ieee80211_assoc_or_reassoc_resp +{ + /** Capability flags */ + u16 capability; + + /** Status code */ + u16 status; + + /** Association ID */ + u16 aid; + + /** List of information elements */ + union ieee80211_ie info_element[0]; +} __attribute__((packed)); + +#define ieee80211_assoc_resp ieee80211_assoc_or_reassoc_resp +#define ieee80211_reassoc_resp ieee80211_assoc_or_reassoc_resp + +/** Reassociation request frame data */ +struct ieee80211_reassoc_req +{ + /** Capability flags */ + u16 capability; + + /** Interval at which we wake up, in units of the beacon interval */ + u16 listen_interval; + + /** MAC address of current Access Point */ + u8 current_addr[ETH_ALEN]; + + /** List of information elements */ + union ieee80211_ie info_element[0]; +} __attribute__((packed)); + +/** Probe request frame data */ +struct ieee80211_probe_req +{ + /** List of information elements */ + union ieee80211_ie info_element[0]; +} __attribute__((packed)); + +/** Authentication frame data */ +struct ieee80211_auth +{ + /** Authentication algorithm (Open System or Shared Key) */ + u16 algorithm; + + /** Sequence number of this frame; first from client to AP is 1 */ + u16 tx_seq; + + /** Status code */ + u16 status; + + /** List of information elements */ + union ieee80211_ie info_element[0]; +} __attribute__((packed)); + +/** Open System authentication algorithm */ +#define IEEE80211_AUTH_OPEN_SYSTEM 0 + +/** Shared Key authentication algorithm */ +#define IEEE80211_AUTH_SHARED_KEY 1 + +/** @} */ + +#endif diff --git a/gpxe/src/include/gpxe/if_arp.h b/gpxe/src/include/gpxe/if_arp.h index 5b250337..932bb3b2 100644 --- a/gpxe/src/include/gpxe/if_arp.h +++ b/gpxe/src/include/gpxe/if_arp.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> /* ARP protocol HARDWARE identifiers. */ diff --git a/gpxe/src/include/gpxe/if_ether.h b/gpxe/src/include/gpxe/if_ether.h index 2f3f33d4..b96bee08 100644 --- a/gpxe/src/include/gpxe/if_ether.h +++ b/gpxe/src/include/gpxe/if_ether.h @@ -1,6 +1,8 @@ #ifndef _GPXE_IF_ETHER_H #define _GPXE_IF_ETHER_H +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #define ETH_ALEN 6 /* Size of Ethernet address */ @@ -18,6 +20,7 @@ #define ETH_P_RARP 0x8035 /* Reverse Address resolution Protocol */ #define ETH_P_IPV6 0x86DD /* IPv6 over blueblook */ #define ETH_P_SLOW 0x8809 /* Ethernet slow protocols */ +#define ETH_P_EAPOL 0x888E /* 802.1X EAP over LANs */ #define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ /** An Ethernet link-layer header */ diff --git a/gpxe/src/include/gpxe/image.h b/gpxe/src/include/gpxe/image.h index b953e150..10db8af2 100644 --- a/gpxe/src/include/gpxe/image.h +++ b/gpxe/src/include/gpxe/image.h @@ -8,6 +8,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/tables.h> #include <gpxe/list.h> #include <gpxe/uaccess.h> @@ -123,9 +125,11 @@ struct image_type { */ #define PROBE_PXE 03 +/** Executable or loadable image type table */ +#define IMAGE_TYPES __table ( struct image_type, "image_types" ) + /** An executable or loadable image type */ -#define __image_type( probe_order ) \ - __table ( struct image_type, image_types, probe_order ) +#define __image_type( probe_order ) __table_entry ( IMAGE_TYPES, probe_order ) extern struct list_head images; diff --git a/gpxe/src/include/gpxe/in.h b/gpxe/src/include/gpxe/in.h index 831a6110..c313717c 100644 --- a/gpxe/src/include/gpxe/in.h +++ b/gpxe/src/include/gpxe/in.h @@ -1,13 +1,14 @@ #ifndef _GPXE_IN_H #define _GPXE_IN_H +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/socket.h> /* Protocol numbers */ #define IP_ICMP 1 -#define IP_IGMP 2 #define IP_TCP 6 #define IP_UDP 17 #define IP_ICMP6 58 diff --git a/gpxe/src/include/gpxe/infiniband.h b/gpxe/src/include/gpxe/infiniband.h index 196b5950..d90b1c10 100644 --- a/gpxe/src/include/gpxe/infiniband.h +++ b/gpxe/src/include/gpxe/infiniband.h @@ -7,25 +7,88 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/refcnt.h> #include <gpxe/device.h> #include <gpxe/ib_packet.h> #include <gpxe/ib_mad.h> -/** Subnet administrator QPN */ -#define IB_SA_QPN 1 +/** Subnet management interface QPN */ +#define IB_QPN_SMI 0 + +/** Subnet management interface queue key */ +#define IB_QKEY_SMI 0 + +/** General service interface QPN */ +#define IB_QPN_GSI 1 + +/** General service interface queue key */ +#define IB_QKEY_GSI 0x80010000UL /** Broadcast QPN */ -#define IB_BROADCAST_QPN 0xffffffUL +#define IB_QPN_BROADCAST 0xffffffUL + +/** QPN mask */ +#define IB_QPN_MASK 0xffffffUL + +/** Default Infiniband partition key */ +#define IB_PKEY_DEFAULT 0xffff -/** Subnet administrator queue key */ -#define IB_GLOBAL_QKEY 0x80010000UL +/** Infiniband partition key full membership flag */ +#define IB_PKEY_FULL 0x8000 + +/** + * Maximum payload size + * + * This is currently hard-coded in various places (drivers, subnet + * management agent, etc.) to 2048. + */ +#define IB_MAX_PAYLOAD_SIZE 2048 struct ib_device; struct ib_queue_pair; struct ib_address_vector; struct ib_completion_queue; +struct ib_mad_interface; + +/** Infiniband transmission rates */ +enum ib_rate { + IB_RATE_2_5 = 2, + IB_RATE_10 = 3, + IB_RATE_30 = 4, + IB_RATE_5 = 5, + IB_RATE_20 = 6, + IB_RATE_40 = 7, + IB_RATE_60 = 8, + IB_RATE_80 = 9, + IB_RATE_120 = 10, +}; + +/** An Infiniband Address Vector */ +struct ib_address_vector { + /** Queue Pair Number */ + unsigned long qpn; + /** Queue key + * + * Not specified for received packets. + */ + unsigned long qkey; + /** Local ID */ + unsigned int lid; + /** Rate + * + * Not specified for received packets. + */ + enum ib_rate rate; + /** Service level */ + unsigned int sl; + /** GID is present */ + unsigned int gid_present; + /** GID, if present */ + struct ib_gid gid; +}; /** An Infiniband Work Queue */ struct ib_work_queue { @@ -37,6 +100,8 @@ struct ib_work_queue { struct ib_completion_queue *cq; /** List of work queues on this completion queue */ struct list_head list; + /** Packet sequence number */ + uint32_t psn; /** Number of work queue entries */ unsigned int num_wqes; /** Number of occupied work queue entries */ @@ -63,14 +128,31 @@ struct ib_multicast_gid { struct ib_gid gid; }; +/** An Infiniband queue pair type */ +enum ib_queue_pair_type { + IB_QPT_SMI, + IB_QPT_GSI, + IB_QPT_UD, + IB_QPT_RC, +}; + /** An Infiniband Queue Pair */ struct ib_queue_pair { /** Containing Infiniband device */ struct ib_device *ibdev; /** List of queue pairs on this Infiniband device */ struct list_head list; - /** Queue Pair Number */ + /** Queue pair number */ unsigned long qpn; + /** Externally-visible queue pair number + * + * This may differ from the real queue pair number (e.g. when + * the HCA cannot use the management QPNs 0 and 1 as hardware + * QPNs and needs to remap them). + */ + unsigned long ext_qpn; + /** Queue pair type */ + enum ib_queue_pair_type type; /** Queue key */ unsigned long qkey; /** Send queue */ @@ -79,41 +161,14 @@ struct ib_queue_pair { struct ib_work_queue recv; /** List of multicast GIDs */ struct list_head mgids; + /** Address vector */ + struct ib_address_vector av; /** Driver private data */ void *drv_priv; /** Queue owner private data */ void *owner_priv; }; -/** Infiniband queue pair modification flags */ -enum ib_queue_pair_mods { - IB_MODIFY_QKEY = 0x0001, -}; - -/** An Infiniband Address Vector */ -struct ib_address_vector { - /** Queue Pair Number */ - unsigned long qpn; - /** Queue key - * - * Not specified for received packets. - */ - unsigned long qkey; - /** Local ID */ - unsigned int lid; - /** Rate - * - * Not specified for received packets. - */ - unsigned int rate; - /** Service level */ - unsigned int sl; - /** GID is present */ - unsigned int gid_present; - /** GID, if present */ - struct ib_gid gid; -}; - /** Infiniband completion queue operations */ struct ib_completion_queue_operations { /** @@ -144,6 +199,10 @@ struct ib_completion_queue_operations { /** An Infiniband Completion Queue */ struct ib_completion_queue { + /** Containing Infiniband device */ + struct ib_device *ibdev; + /** List of completion queues on this Infiniband device */ + struct list_head list; /** Completion queue number */ unsigned long cqn; /** Number of completion queue entries */ @@ -197,12 +256,10 @@ struct ib_device_operations { * * @v ibdev Infiniband device * @v qp Queue pair - * @v mod_list Modification list * @ret rc Return status code */ int ( * modify_qp ) ( struct ib_device *ibdev, - struct ib_queue_pair *qp, - unsigned long mod_list ); + struct ib_queue_pair *qp ); /** Destroy queue pair * * @v ibdev Infiniband device @@ -290,6 +347,25 @@ struct ib_device_operations { void ( * mcast_detach ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ); + /** Set port information + * + * @v ibdev Infiniband device + * @v mad Set port information MAD + * + * This method is required only by adapters that do not have + * an embedded SMA. + */ + int ( * set_port_info ) ( struct ib_device *ibdev, union ib_mad *mad ); + /** Set partition key table + * + * @v ibdev Infiniband device + * @v mad Set partition key table MAD + * + * This method is required only by adapters that do not have + * an embedded SMA. + */ + int ( * set_pkey_table ) ( struct ib_device *ibdev, + union ib_mad *mad ); }; /** An Infiniband device */ @@ -298,8 +374,12 @@ struct ib_device { struct refcnt refcnt; /** List of Infiniband devices */ struct list_head list; + /** List of open Infiniband devices */ + struct list_head open_list; /** Underlying device */ struct device *dev; + /** List of completion queues */ + struct list_head cqs; /** List of queue pairs */ struct list_head qps; /** Infiniband operations */ @@ -311,10 +391,18 @@ struct ib_device { /** Port state */ uint8_t port_state; - /** Link width */ - uint8_t link_width; - /** Link speed */ - uint8_t link_speed; + /** Link width supported */ + uint8_t link_width_supported; + /** Link width enabled */ + uint8_t link_width_enabled; + /** Link width active */ + uint8_t link_width_active; + /** Link speed supported */ + uint8_t link_speed_supported; + /** Link speed enabled */ + uint8_t link_speed_enabled; + /** Link speed active */ + uint8_t link_speed_active; /** Port GID */ struct ib_gid gid; /** Port LID */ @@ -326,8 +414,17 @@ struct ib_device { /** Partition key */ uint16_t pkey; - /** Outbound packet sequence number */ - uint32_t psn; + /** RDMA key + * + * This is a single key allowing unrestricted access to + * memory. + */ + uint32_t rdma_key; + + /** Subnet management interface */ + struct ib_mad_interface *smi; + /** General services interface */ + struct ib_mad_interface *gsi; /** Driver private data */ void *drv_priv; @@ -340,12 +437,14 @@ ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes, struct ib_completion_queue_operations *op ); extern void ib_destroy_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq ); +extern void ib_poll_cq ( struct ib_device *ibdev, + struct ib_completion_queue *cq ); extern struct ib_queue_pair * -ib_create_qp ( struct ib_device *ibdev, unsigned int num_send_wqes, - struct ib_completion_queue *send_cq, unsigned int num_recv_wqes, - struct ib_completion_queue *recv_cq, unsigned long qkey ); -extern int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp, - unsigned long mod_list, unsigned long qkey ); +ib_create_qp ( struct ib_device *ibdev, enum ib_queue_pair_type type, + unsigned int num_send_wqes, struct ib_completion_queue *send_cq, + unsigned int num_recv_wqes, + struct ib_completion_queue *recv_cq ); +extern int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ); extern void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ); extern struct ib_queue_pair * ib_find_qp_qpn ( struct ib_device *ibdev, @@ -366,16 +465,26 @@ extern void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *av, struct io_buffer *iobuf, int rc ); +extern void ib_refill_recv ( struct ib_device *ibdev, + struct ib_queue_pair *qp ); extern int ib_open ( struct ib_device *ibdev ); extern void ib_close ( struct ib_device *ibdev ); +extern int ib_link_rc ( struct ib_device *ibdev ); extern int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ); extern void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ); +extern int ib_get_hca_info ( struct ib_device *ibdev, + struct ib_gid_half *hca_guid ); +extern int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad ); +extern int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad ); extern struct ib_device * alloc_ibdev ( size_t priv_size ); extern int register_ibdev ( struct ib_device *ibdev ); extern void unregister_ibdev ( struct ib_device *ibdev ); +extern struct ib_device * find_ibdev ( struct ib_gid *gid ); +extern struct ib_device * last_opened_ibdev ( void ); extern void ib_link_state_changed ( struct ib_device *ibdev ); +extern void ib_poll_eq ( struct ib_device *ibdev ); extern struct list_head ib_devices; /** Iterate over all network devices */ @@ -383,17 +492,6 @@ extern struct list_head ib_devices; list_for_each_entry ( (ibdev), &ib_devices, list ) /** - * Poll completion queue - * - * @v ibdev Infiniband device - * @v cq Completion queue - */ -static inline __always_inline void -ib_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq ) { - ibdev->op->poll_cq ( ibdev, cq ); -} - -/** * Check link state * * @v ibdev Infiniband device diff --git a/gpxe/src/include/gpxe/init.h b/gpxe/src/include/gpxe/init.h index e0e9f9c8..a72cba7a 100644 --- a/gpxe/src/include/gpxe/init.h +++ b/gpxe/src/include/gpxe/init.h @@ -1,6 +1,8 @@ #ifndef _GPXE_INIT_H #define _GPXE_INIT_H +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/tables.h> /** @@ -13,9 +15,11 @@ struct init_fn { void ( * initialise ) ( void ); }; +/** Initialisation function table */ +#define INIT_FNS __table ( struct init_fn, "init_fns" ) + /** Declare an initialisation functon */ -#define __init_fn( init_order ) \ - __table ( struct init_fn, init_fns, init_order ) +#define __init_fn( init_order ) __table_entry ( INIT_FNS, init_order ) /** @defgroup initfn_order Initialisation function ordering * @{ @@ -49,9 +53,12 @@ struct startup_fn { void ( * shutdown ) ( int flags ); }; +/** Startup/shutdown function table */ +#define STARTUP_FNS __table ( struct startup_fn, "startup_fns" ) + /** Declare a startup/shutdown function */ #define __startup_fn( startup_order ) \ - __table ( struct startup_fn, startup_fns, startup_order ) + __table_entry ( STARTUP_FNS, startup_order ) /** @defgroup startfn_order Startup/shutdown function ordering * diff --git a/gpxe/src/include/gpxe/interface.h b/gpxe/src/include/gpxe/interface.h index 94c711a9..114ebf32 100644 --- a/gpxe/src/include/gpxe/interface.h +++ b/gpxe/src/include/gpxe/interface.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/refcnt.h> /** An object communication interface */ diff --git a/gpxe/src/include/gpxe/io.h b/gpxe/src/include/gpxe/io.h index ebb8ba30..919823d9 100644 --- a/gpxe/src/include/gpxe/io.h +++ b/gpxe/src/include/gpxe/io.h @@ -16,6 +16,8 @@ * the address parameter. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/api.h> #include <config/ioapi.h> diff --git a/gpxe/src/include/gpxe/iobuf.h b/gpxe/src/include/gpxe/iobuf.h index 6d1a58a4..8f05f9ea 100644 --- a/gpxe/src/include/gpxe/iobuf.h +++ b/gpxe/src/include/gpxe/iobuf.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <assert.h> #include <gpxe/list.h> diff --git a/gpxe/src/include/gpxe/ip.h b/gpxe/src/include/gpxe/ip.h index b1b0c48c..4342a0c7 100644 --- a/gpxe/src/include/gpxe/ip.h +++ b/gpxe/src/include/gpxe/ip.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/in.h> #include <gpxe/list.h> diff --git a/gpxe/src/include/gpxe/ip6.h b/gpxe/src/include/gpxe/ip6.h index dc0ae31f..edb2863c 100644 --- a/gpxe/src/include/gpxe/ip6.h +++ b/gpxe/src/include/gpxe/ip6.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/in.h> diff --git a/gpxe/src/include/gpxe/ipoib.h b/gpxe/src/include/gpxe/ipoib.h index 80adee5b..1d02f792 100644 --- a/gpxe/src/include/gpxe/ipoib.h +++ b/gpxe/src/include/gpxe/ipoib.h @@ -6,10 +6,9 @@ * IP over Infiniband */ -#include <gpxe/infiniband.h> +FILE_LICENCE ( GPL2_OR_LATER ); -/** IPoIB packet length */ -#define IPOIB_PKT_LEN 2048 +#include <gpxe/infiniband.h> /** IPoIB MAC address length */ #define IPOIB_ALEN 20 @@ -18,9 +17,10 @@ struct ipoib_mac { /** Queue pair number * - * MSB must be zero; QPNs are only 24-bit. + * MSB indicates support for IPoIB "connected mode". Lower 24 + * bits are the QPN. */ - uint32_t qpn; + uint32_t flags__qpn; /** Port GID */ struct ib_gid gid; } __attribute__ (( packed )); @@ -52,29 +52,10 @@ struct ipoib_hdr { } __attribute__ (( packed )) u; } __attribute__ (( packed )); -extern struct ll_protocol ipoib_protocol; - extern const char * ipoib_ntoa ( const void *ll_addr ); - -/** - * Allocate IPoIB device - * - * @v priv_size Size of driver private data - * @ret netdev Network device, or NULL - */ -static inline struct net_device * alloc_ipoibdev ( size_t priv_size ) { - struct net_device *netdev; - - netdev = alloc_netdev ( priv_size ); - if ( netdev ) { - netdev->ll_protocol = &ipoib_protocol; - netdev->max_pkt_len = IPOIB_PKT_LEN; - } - return netdev; -} - extern void ipoib_link_state_changed ( struct ib_device *ibdev ); extern int ipoib_probe ( struct ib_device *ibdev ); extern void ipoib_remove ( struct ib_device *ibdev ); +extern struct net_device * alloc_ipoibdev ( size_t priv_size ); #endif /* _GPXE_IPOIB_H */ diff --git a/gpxe/src/include/gpxe/isa.h b/gpxe/src/include/gpxe/isa.h index bb25dbce..63027a5a 100644 --- a/gpxe/src/include/gpxe/isa.h +++ b/gpxe/src/include/gpxe/isa.h @@ -1,6 +1,8 @@ #ifndef ISA_H #define ISA_H +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/isa_ids.h> #include <gpxe/device.h> @@ -58,8 +60,11 @@ struct isa_driver { void ( * remove ) ( struct isa_device *isa ); }; +/** ISA driver table */ +#define ISA_DRIVERS __table ( struct isa_driver, "isa_drivers" ) + /** Declare an ISA driver */ -#define __isa_driver __table ( struct isa_driver, isa_drivers, 01 ) +#define __isa_driver __table_entry ( ISA_DRIVERS, 01 ) /** * Set ISA driver-private data diff --git a/gpxe/src/include/gpxe/isa_ids.h b/gpxe/src/include/gpxe/isa_ids.h index bf3f1015..1faf1148 100644 --- a/gpxe/src/include/gpxe/isa_ids.h +++ b/gpxe/src/include/gpxe/isa_ids.h @@ -19,6 +19,8 @@ * the underlying "meaning" is big-endian. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <byteswap.h> /* diff --git a/gpxe/src/include/gpxe/isapnp.h b/gpxe/src/include/gpxe/isapnp.h index 07797a99..b58a87e4 100644 --- a/gpxe/src/include/gpxe/isapnp.h +++ b/gpxe/src/include/gpxe/isapnp.h @@ -33,6 +33,8 @@ * ***************************************************************************/ +FILE_LICENCE ( GPL2_OR_LATER ); + #ifndef ISAPNP_H #define ISAPNP_H @@ -223,8 +225,11 @@ struct isapnp_driver { void ( * remove ) ( struct isapnp_device *isapnp ); }; +/** ISAPnP driver table */ +#define ISAPNP_DRIVERS __table ( struct isapnp_driver, "isapnp_drivers" ) + /** Declare an ISAPnP driver */ -#define __isapnp_driver __table ( struct isapnp_driver, isapnp_drivers, 01 ) +#define __isapnp_driver __table_entry ( ISAPNP_DRIVERS, 01 ) extern uint16_t isapnp_read_port; diff --git a/gpxe/src/include/gpxe/iscsi.h b/gpxe/src/include/gpxe/iscsi.h index 0510974e..00717d2b 100644 --- a/gpxe/src/include/gpxe/iscsi.h +++ b/gpxe/src/include/gpxe/iscsi.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/socket.h> #include <gpxe/scsi.h> @@ -247,7 +249,7 @@ struct iscsi_bhs_scsi_command { /** Segment lengths */ union iscsi_segment_lengths lengths; /** SCSI Logical Unit Number */ - uint64_t lun; + struct scsi_lun lun; /** Initiator Task Tag */ uint32_t itt; /** Expected data transfer length */ @@ -342,7 +344,7 @@ struct iscsi_bhs_data_in { /** Segment lengths */ union iscsi_segment_lengths lengths; /** Logical Unit Number */ - uint64_t lun; + struct scsi_lun lun; /** Initiator Task Tag */ uint32_t itt; /** Target Transfer Tag */ @@ -390,7 +392,7 @@ struct iscsi_bhs_data_out { /** Segment lengths */ union iscsi_segment_lengths lengths; /** Logical Unit Number */ - uint64_t lun; + struct scsi_lun lun; /** Initiator Task Tag */ uint32_t itt; /** Target Transfer Tag */ @@ -426,7 +428,7 @@ struct iscsi_bhs_r2t { /** Segment lengths */ union iscsi_segment_lengths lengths; /** Logical Unit Number */ - uint64_t lun; + struct scsi_lun lun; /** Initiator Task Tag */ uint32_t itt; /** Target Transfer Tag */ @@ -505,7 +507,7 @@ struct iscsi_session { /** Target IQN */ char *target_iqn; /** Logical Unit Number (LUN) */ - uint64_t lun; + struct scsi_lun lun; /** Target socket address (recorded only for iBFT) */ struct sockaddr target_sockaddr; @@ -612,11 +614,6 @@ struct iscsi_session { * Set to NULL when command is complete. */ struct scsi_command *command; - /** SCSI command return code - * - * Set to -EINPROGRESS while command is processing. - */ - int rc; /** Instant return code * * Set to a non-zero value if all requests should return diff --git a/gpxe/src/include/gpxe/job.h b/gpxe/src/include/gpxe/job.h index 8e11aa33..f1bcada4 100644 --- a/gpxe/src/include/gpxe/job.h +++ b/gpxe/src/include/gpxe/job.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stddef.h> #include <gpxe/interface.h> @@ -66,6 +68,8 @@ extern struct job_interface_operations null_job_ops; extern void job_done ( struct job_interface *job, int rc ); extern void job_kill ( struct job_interface *job ); +extern void job_progress ( struct job_interface *job, + struct job_progress *progress ); extern void ignore_job_done ( struct job_interface *job, int rc ); extern void ignore_job_kill ( struct job_interface *job ); diff --git a/gpxe/src/include/gpxe/keys.h b/gpxe/src/include/gpxe/keys.h index 3da8a1ff..25bc9bc0 100644 --- a/gpxe/src/include/gpxe/keys.h +++ b/gpxe/src/include/gpxe/keys.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /* * Symbolic names for some standard ASCII characters * diff --git a/gpxe/src/include/gpxe/linebuf.h b/gpxe/src/include/gpxe/linebuf.h index 676731a9..cfa21472 100644 --- a/gpxe/src/include/gpxe/linebuf.h +++ b/gpxe/src/include/gpxe/linebuf.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <stddef.h> diff --git a/gpxe/src/include/gpxe/linux_compat.h b/gpxe/src/include/gpxe/linux_compat.h index 2c3cbbde..577512eb 100644 --- a/gpxe/src/include/gpxe/linux_compat.h +++ b/gpxe/src/include/gpxe/linux_compat.h @@ -10,6 +10,8 @@ * intended to be a substitute for proper porting. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <errno.h> #include <stdio.h> diff --git a/gpxe/src/include/gpxe/list.h b/gpxe/src/include/gpxe/list.h index 602382be..22ba2015 100644 --- a/gpxe/src/include/gpxe/list.h +++ b/gpxe/src/include/gpxe/list.h @@ -9,6 +9,8 @@ * list.h. */ +FILE_LICENCE ( GPL2_ONLY ); + #include <stddef.h> #include <assert.h> diff --git a/gpxe/src/include/gpxe/login_ui.h b/gpxe/src/include/gpxe/login_ui.h index d92ba8f3..4196f7b1 100644 --- a/gpxe/src/include/gpxe/login_ui.h +++ b/gpxe/src/include/gpxe/login_ui.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + extern int login_ui ( void ); #endif /* _GPXE_LOGIN_UI_H */ diff --git a/gpxe/src/include/gpxe/malloc.h b/gpxe/src/include/gpxe/malloc.h index cce5d1d3..c02a8668 100644 --- a/gpxe/src/include/gpxe/malloc.h +++ b/gpxe/src/include/gpxe/malloc.h @@ -9,6 +9,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /* * Prototypes for the standard functions (malloc() et al) are in * stdlib.h. Include <gpxe/malloc.h> only if you need the diff --git a/gpxe/src/include/gpxe/mca.h b/gpxe/src/include/gpxe/mca.h index 21f9e74d..da9d73e4 100644 --- a/gpxe/src/include/gpxe/mca.h +++ b/gpxe/src/include/gpxe/mca.h @@ -5,6 +5,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #ifndef MCA_H #define MCA_H @@ -77,8 +79,11 @@ struct mca_driver { void ( * remove ) ( struct mca_device *mca ); }; +/** MCA driver table */ +#define MCA_DRIVERS __table ( struct mca_driver, "mca_drivers" ) + /** Declare an MCA driver */ -#define __mca_driver __table ( struct mca_driver, mca_drivers, 01 ) +#define __mca_driver __table_entry ( MCA_DRIVERS, 01 ) /** * Set MCA driver-private data diff --git a/gpxe/src/include/gpxe/md5.h b/gpxe/src/include/gpxe/md5.h index f8976a19..03d65c1a 100644 --- a/gpxe/src/include/gpxe/md5.h +++ b/gpxe/src/include/gpxe/md5.h @@ -1,6 +1,8 @@ #ifndef _GPXE_MD5_H #define _GPXE_MD5_H +FILE_LICENCE ( GPL2_OR_LATER ); + struct digest_algorithm; #include <stdint.h> diff --git a/gpxe/src/include/gpxe/memmap.h b/gpxe/src/include/gpxe/memmap.h index 836a1b92..dc5bec3b 100644 --- a/gpxe/src/include/gpxe/memmap.h +++ b/gpxe/src/include/gpxe/memmap.h @@ -10,6 +10,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** A usable memory region */ struct memory_region { /** Physical start address */ diff --git a/gpxe/src/include/gpxe/monojob.h b/gpxe/src/include/gpxe/monojob.h index aaa38d03..35ff4fd3 100644 --- a/gpxe/src/include/gpxe/monojob.h +++ b/gpxe/src/include/gpxe/monojob.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + struct job_interface; extern struct job_interface monojob; diff --git a/gpxe/src/include/gpxe/nap.h b/gpxe/src/include/gpxe/nap.h index f9ae3cf4..6c2e40cf 100644 --- a/gpxe/src/include/gpxe/nap.h +++ b/gpxe/src/include/gpxe/nap.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/api.h> #include <config/nap.h> diff --git a/gpxe/src/include/gpxe/net80211.h b/gpxe/src/include/gpxe/net80211.h new file mode 100644 index 00000000..027e091c --- /dev/null +++ b/gpxe/src/include/gpxe/net80211.h @@ -0,0 +1,1186 @@ +#ifndef _GPXE_NET80211_H +#define _GPXE_NET80211_H + +#include <gpxe/process.h> +#include <gpxe/ieee80211.h> +#include <gpxe/iobuf.h> +#include <gpxe/netdevice.h> +#include <gpxe/rc80211.h> + +/** @file + * + * The gPXE 802.11 MAC layer. + */ + +/* + * Major things NOT YET supported: + * - any type of security + * - 802.11n + * + * Major things that probably will NEVER be supported, barring a + * compelling use case and/or corporate sponsorship: + * - QoS + * - 802.1X authentication ("WPA Enterprise") + * - Contention-free periods + * - "ad-hoc" networks (IBSS), monitor mode, host AP mode + * - hidden networks on the 5GHz band due to regulatory issues + * - spectrum management on the 5GHz band (TPC and DFS), as required + * in some non-US regulatory domains + * - Clause 14 PHYs (Frequency-Hopping Spread Spectrum on 2.4GHz) + * and Clause 16 PHYs (infrared) - I'm not aware of any real-world + * use of these. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/* All 802.11 devices are handled using a generic "802.11 device" + net_device, with a link in its `priv' field to a net80211_device + which we use to handle 802.11-specific details. */ + + +/** @defgroup net80211_band RF bands on which an 802.11 device can transmit */ +/** @{ */ + +/** The 2.4 GHz ISM band, unlicensed in most countries */ +#define NET80211_BAND_2GHZ 0 +/** The band from 4.9 GHz to 5.7 GHz, which tends to be more restricted */ +#define NET80211_BAND_5GHZ 1 +/** Number of RF bands */ +#define NET80211_NR_BANDS 2 + +/** Bitmask for the 2GHz band */ +#define NET80211_BAND_BIT_2GHZ (1 << 0) +/** Bitmask for the 5GHz band */ +#define NET80211_BAND_BIT_5GHZ (1 << 1) + +/** @} */ + + +/** @defgroup net80211_mode 802.11 operation modes supported by hardware */ +/** @{ */ + +/** 802.11a: 54 Mbps operation using OFDM signaling on the 5GHz band */ +#define NET80211_MODE_A (1 << 0) + +/** 802.11b: 1-11 Mbps operation using DSSS/CCK signaling on the 2.4GHz band */ +#define NET80211_MODE_B (1 << 1) + +/** 802.11g: 54 Mbps operation using ERP/OFDM signaling on the 2.4GHz band */ +#define NET80211_MODE_G (1 << 2) + +/** 802.11n: High-rate operation using MIMO technology on 2.4GHz or 5GHz */ +#define NET80211_MODE_N (1 << 3) + +/** @} */ + + +/** @defgroup net80211_cfg Constants for the net80211 config callback */ +/** @{ */ + +/** Channel choice (@c dev->channel) or regulatory parameters have changed */ +#define NET80211_CFG_CHANNEL (1 << 0) + +/** Requested transmission rate (@c dev->rate) has changed */ +#define NET80211_CFG_RATE (1 << 1) + +/** Association has been established with a new BSS (@c dev->bssid) */ +#define NET80211_CFG_ASSOC (1 << 2) + +/** Low-level link parameters (short preamble, protection, etc) have changed */ +#define NET80211_CFG_PHY_PARAMS (1 << 3) + +/** @} */ + + +/** An 802.11 security handshaking protocol */ +enum net80211_security_proto { + /** No security handshaking + * + * This might be used with an open network or with WEP, as + * WEP does not have a cryptographic handshaking phase. + */ + NET80211_SECPROT_NONE = 0, + + /** Pre-shared key handshaking + * + * This implements the "WPA Personal" handshake. 802.1X + * authentication is not performed -- the user supplies a + * pre-shared key directly -- but there is a 4-way handshake + * between client and AP to verify that both have the same key + * without revealing the contents of that key. + */ + NET80211_SECPROT_PSK = 1, + + /** Full EAP 802.1X handshaking + * + * This implements the "WPA Enterprise" handshake, connecting + * to an 802.1X authentication server to provide credentials + * and receive a pairwise master key (PMK), which is then used + * in the same 4-way handshake as the PSK method. + */ + NET80211_SECPROT_EAP = 2, + + /** Dummy value used when the handshaking type can't be detected */ + NET80211_SECPROT_UNKNOWN = 3, +}; + + +/** An 802.11 data encryption algorithm */ +enum net80211_crypto_alg { + /** No security, an "Open" network */ + NET80211_CRYPT_NONE = 0, + + /** Network protected with WEP (awful RC4-based system) + * + * WEP uses a naive application of RC4, with a monotonically + * increasing initialization vector that is prepended to the + * key to initialize the RC4 keystream. It is highly insecure + * and can be completely cracked or subverted using automated, + * robust, freely available tools (aircrack-ng) in minutes. + * + * 40-bit and 104-bit WEP are differentiated only by the size + * of the key. They may be advertised as 64-bit and 128-bit, + * counting the non-random IV as part of the key bits. + */ + NET80211_CRYPT_WEP = 1, + + /** Network protected with TKIP (better RC4-based system) + * + * Usually known by its trade name of WPA (Wi-Fi Protected + * Access), TKIP implements a message integrity code (MIC) + * called Michael, a timestamp counter for replay prevention, + * and a key mixing function that together remove almost all + * the security problems with WEP. Countermeasures are + * implemented to prevent high data-rate attacks. + * + * There exists one known attack on TKIP, that allows one to + * send between 7 and 15 arbitrary short data packets on a + * QoS-enabled network given about an hour of data + * gathering. Since gPXE does not support QoS for 802.11 + * networks, this is not a threat to us. The only other method + * is a brute-force passphrase attack. + */ + NET80211_CRYPT_TKIP = 2, + + /** Network protected with CCMP (AES-based system) + * + * Often called WPA2 in commerce, or RSNA (Robust Security + * Network Architecture) in the 802.11 standard, CCMP is + * highly secure and does not have any known attack vectors. + * Since it is based on a block cipher, the statistical + * correlation and "chopchop" attacks used with great success + * against WEP and minor success against TKIP fail. + */ + NET80211_CRYPT_CCMP = 3, + + /** Dummy value used when the cryptosystem can't be detected */ + NET80211_CRYPT_UNKNOWN = 4, +}; + + +/** @defgroup net80211_state Bits for the 802.11 association state field */ +/** @{ */ + +/** An error code indicating the failure mode, or 0 if successful */ +#define NET80211_STATUS_MASK 0x7F + +/** Whether the error code provided is a "reason" code, not a "status" code */ +#define NET80211_IS_REASON 0x80 + +/** Whether we have found the network we will be associating with */ +#define NET80211_PROBED (1 << 8) + +/** Whether we have successfully authenticated with the network + * + * This usually has nothing to do with actual security; it is a + * holdover from older 802.11 implementation ideas. + */ +#define NET80211_AUTHENTICATED (1 << 9) + +/** Whether we have successfully associated with the network */ +#define NET80211_ASSOCIATED (1 << 10) + +/** Whether we have completed security handshaking with the network + * + * Once this is set, we can send data packets. For that reason this + * bit is set even in cases where no security handshaking is + * required. + */ +#define NET80211_CRYPTO_SYNCED (1 << 11) + +/** Whether the auto-association task is running */ +#define NET80211_WORKING (1 << 12) + +/** Whether the auto-association task is waiting for a reply from the AP */ +#define NET80211_WAITING (1 << 13) + +/** Whether the auto-association task should be suppressed + * + * This is set by the `iwlist' command so that it can open the device + * without starting another probe process that will interfere with its + * own. + */ +#define NET80211_NO_ASSOC (1 << 14) + +/** Whether this association was performed using a broadcast SSID + * + * If the user opened this device without netX/ssid set, the device's + * SSID will be set to that of the network it chooses to associate + * with, but the netX/ssid setting will remain blank. If we don't + * remember that we started from no specified SSID, it will appear + * every time settings are updated (e.g. after DHCP) that we need to + * reassociate due to the difference between the set SSID and our own. + */ +#define NET80211_AUTO_SSID (1 << 15) + + +/** @} */ + + +/** @defgroup net80211_phy 802.11 physical layer flags */ +/** @{ */ + +/** Whether to use RTS/CTS or CTS-to-self protection for transmissions + * + * Since the RTS or CTS is transmitted using 802.11b signaling, and + * includes a field indicating the amount of time that will be used by + * transmission of the following packet, this serves as an effective + * protection mechanism to avoid 802.11b clients interfering with + * 802.11g clients on mixed networks. + */ +#define NET80211_PHY_USE_PROTECTION (1 << 1) + +/** Whether to use 802.11b short preamble operation + * + * Short-preamble operation can moderately increase throughput on + * 802.11b networks operating between 2Mbps and 11Mbps. It is + * irrelevant for 802.11g data rates, since they use a different + * modulation scheme. + */ +#define NET80211_PHY_USE_SHORT_PREAMBLE (1 << 2) + +/** Whether to use 802.11g short slot operation + * + * This affects a low-level timing parameter of 802.11g transmissions. + */ +#define NET80211_PHY_USE_SHORT_SLOT (1 << 3) + +/** @} */ + + +/** The maximum number of TX rates we allow to be configured simultaneously */ +#define NET80211_MAX_RATES 16 + +/** The maximum number of channels we allow to be configured simultaneously */ +#define NET80211_MAX_CHANNELS 32 + +/** Seconds we'll wait to get all fragments of a packet */ +#define NET80211_FRAG_TIMEOUT 2 + +/** The number of fragments we can receive at once + * + * The 802.11 standard requires that this be at least 3. + */ +#define NET80211_NR_CONCURRENT_FRAGS 3 + +/** Maximum TX power to allow (dBm), if we don't get a regulatory hint */ +#define NET80211_REG_TXPOWER 20 + + +struct net80211_device; + +/** Operations that must be implemented by an 802.11 driver */ +struct net80211_device_operations { + /** Open 802.11 device + * + * @v dev 802.11 device + * @ret rc Return status code + * + * This method should allocate RX I/O buffers and enable the + * hardware to start transmitting and receiving packets on the + * channels its net80211_register() call indicated it could + * handle. It does not need to tune the antenna to receive + * packets on any particular channel. + */ + int ( * open ) ( struct net80211_device *dev ); + + /** Close 802.11 network device + * + * @v dev 802.11 device + * + * This method should stop the flow of packets, and call + * net80211_tx_complete() for any packets remaining in the + * device's TX queue. + */ + void ( * close ) ( struct net80211_device *dev ); + + /** Transmit packet on 802.11 network device + * + * @v dev 802.11 device + * @v iobuf I/O buffer + * @ret rc Return status code + * + * This method should cause the hardware to initiate + * transmission of the I/O buffer, using the channel and rate + * most recently indicated by an appropriate call to the + * @c config callback. The 802.11 layer guarantees that said + * channel and rate will be the same as those currently + * reflected in the fields of @a dev. + * + * If this method returns success, the I/O buffer remains + * owned by the network layer's TX queue, and the driver must + * eventually call net80211_tx_complete() to free the buffer + * whether transmission succeeded or not. If this method + * returns failure, it will be interpreted as "failure to + * enqueue buffer" and the I/O buffer will be immediately + * released. + * + * This method is guaranteed to be called only when the device + * is open. + */ + int ( * transmit ) ( struct net80211_device *dev, + struct io_buffer *iobuf ); + + /** Poll for completed and received packets + * + * @v dev 802.11 device + * + * This method should cause the hardware to check for + * completed transmissions and received packets. Any received + * packets should be delivered via net80211_rx(), and + * completed transmissions should be indicated using + * net80211_tx_complete(). + * + * This method is guaranteed to be called only when the device + * is open. + */ + void ( * poll ) ( struct net80211_device *dev ); + + /** Enable or disable interrupts + * + * @v dev 802.11 device + * @v enable If TRUE, interrupts should be enabled + */ + void ( * irq ) ( struct net80211_device *dev, int enable ); + + /** Update hardware state to match 802.11 layer state + * + * @v dev 802.11 device + * @v changed Set of flags indicating what may have changed + * @ret rc Return status code + * + * This method should cause the hardware state to be + * reinitialized from the state indicated in fields of + * net80211_device, in the areas indicated by bits set in + * @a changed. If the hardware is unable to do so, this method + * may return an appropriate error indication. + * + * This method is guaranteed to be called only when the device + * is open. + */ + int ( * config ) ( struct net80211_device *dev, int changed ); +}; + +/** An 802.11 RF channel. */ +struct net80211_channel +{ + /** The band with which this channel is associated */ + u8 band; + + /** A channel number interpreted according to the band + * + * The 2.4GHz band uses channel numbers from 1-13 at 5MHz + * intervals such that channel 1 is 2407 MHz; channel 14, + * legal for use only in Japan, is defined separately as 2484 + * MHz. Adjacent channels will overlap, since 802.11 + * transmissions use a 20 MHz (4-channel) bandwidth. Most + * commonly, channels 1, 6, and 11 are used. + * + * The 5GHz band uses channel numbers derived directly from + * the frequency; channel 0 is 5000 MHz, and channels are + * always spaced 5 MHz apart. Channel numbers over 180 are + * relative to 4GHz instead of 5GHz, but these are rarely + * seen. Most channels are not legal for use. + */ + u8 channel_nr; + + /** The center frequency for this channel + * + * Currently a bandwidth of 20 MHz is assumed. + */ + u16 center_freq; + + /** Hardware channel value */ + u16 hw_value; + + /** Maximum allowable transmit power, in dBm + * + * This should be interpreted as EIRP, the power supplied to + * an ideal isotropic antenna in order to achieve the same + * average signal intensity as the real hardware at a + * particular distance. + * + * Currently no provision is made for directional antennas. + */ + u8 maxpower; +}; + +/** Information on the capabilities of an 802.11 hardware device + * + * In its probe callback, an 802.11 driver must read hardware + * registers to determine the appropriate contents of this structure, + * fill it, and pass it to net80211_register() so that the 802.11 + * layer knows how to treat the hardware and what to advertise as + * supported to access points. + */ +struct net80211_hw_info +{ + /** Default hardware MAC address. + * + * The user may change this by setting the @c netX/mac setting + * before the driver's open function is called; in that case + * the driver must set the hardware MAC address to the address + * contained in the wrapping net_device's ll_addr field, or if + * that is impossible, set that ll_addr field back to the + * unchangeable hardware MAC address. + */ + u8 hwaddr[ETH_ALEN]; + + /** A bitwise OR of the 802.11x modes supported by this device */ + int modes; + + /** A bitwise OR of the bands on which this device can communicate */ + int bands; + + /** A set of flags indicating peculiarities of this device. */ + enum { + /** Received frames include a frame check sequence. */ + NET80211_HW_RX_HAS_FCS = (1 << 1), + + /** Hardware doesn't support 2.4GHz short preambles + * + * This is only relevant for 802.11b operation above + * 2Mbps. All 802.11g devices support short preambles. + */ + NET80211_HW_NO_SHORT_PREAMBLE = (1 << 2), + + /** Hardware doesn't support 802.11g short slot operation */ + NET80211_HW_NO_SHORT_SLOT = (1 << 3), + } flags; + + /** Signal strength information that can be provided by the device + * + * Signal strength is passed to net80211_rx(), primarily to + * allow determination of the closest access point for a + * multi-AP network. The units are provided for completeness + * of status displays. + */ + enum { + /** No signal strength information supported */ + NET80211_SIGNAL_NONE = 0, + /** Signal strength in arbitrary units */ + NET80211_SIGNAL_ARBITRARY, + /** Signal strength in decibels relative to arbitrary base */ + NET80211_SIGNAL_DB, + /** Signal strength in decibels relative to 1mW */ + NET80211_SIGNAL_DBM, + } signal_type; + + /** Maximum signal in arbitrary cases + * + * If signal_type is NET80211_SIGNAL_ARBITRARY or + * NET80211_SIGNAL_DB, the driver should report it on a scale + * from 0 to signal_max. + */ + unsigned signal_max; + + /** List of RF channels supported by the card */ + struct net80211_channel channels[NET80211_MAX_CHANNELS]; + + /** Number of supported channels */ + int nr_channels; + + /** List of transmission rates supported by the card, indexed by band + * + * Rates should be in 100kbps increments (e.g. 11 Mbps would + * be represented as the number 110). + */ + u16 rates[NET80211_NR_BANDS][NET80211_MAX_RATES]; + + /** Number of supported rates, indexed by band */ + int nr_rates[NET80211_NR_BANDS]; + + /** Estimate of the time required to change channels, in microseconds + * + * If this is not known, a guess on the order of a few + * milliseconds (value of 1000-5000) is reasonable. + */ + unsigned channel_change_time; +}; + +/** Structure tracking received fragments for a packet + * + * We set up a fragment cache entry when we receive a packet marked as + * fragment 0 with the "more fragments" bit set in its frame control + * header. We are required by the 802.11 standard to track 3 + * fragmented packets arriving simultaneously; if we receive more we + * may drop some. Upon receipt of a new fragment-0 packet, if no entry + * is available or expired, we take over the most @e recent entry for + * the new packet, since we don't want to starve old entries from ever + * finishing at all. If we get a fragment after the zeroth with no + * cache entry for its packet, we drop it. + */ +struct net80211_frag_cache +{ + /** Whether this cache entry is in use */ + u8 in_use; + + /** Sequence number of this MSDU (packet) */ + u16 seqnr; + + /** Timestamp from point at which first fragment was collected */ + u32 start_ticks; + + /** Buffers for each fragment */ + struct io_buffer *iob[16]; +}; + + +/** Interface to an 802.11 security handshaking protocol + * + * Security handshaking protocols handle parsing a user-specified key + * into a suitable input to the encryption algorithm, and for WPA and + * better systems, manage performing whatever authentication with the + * network is necessary. + * + * At all times when any method in this structure is called with a + * net80211_device argument @a dev, a dynamically allocated copy of + * the handshaker structure itself with space for the requested amount + * of private data may be accessed as @c dev->handshaker. The + * structure will not be modified, and will only be freed during + * reassociation and device closing after the @a stop method has been + * called. + */ +struct net80211_handshaker +{ + /** The security handshaking protocol implemented */ + enum net80211_security_proto protocol; + + /** Initialize security handshaking protocol + * + * @v dev 802.11 device + * @ret rc Return status code + * + * This method is expected to access @c netX/key or other + * applicable settings to determine the parameters for + * handshaking. If no handshaking is required, it should call + * sec80211_install() with the cryptosystem and key that are + * to be used, and @c start and @c step should be set to @c + * NULL. + * + * This is always called just before association is performed, + * but after its parameters have been set; in particular, you + * may rely on the contents of the @a essid field in @a dev. + */ + int ( * init ) ( struct net80211_device *dev ); + + /** Start handshaking + * + * @v dev 802.11 device + * @ret rc Return status code + * + * This method is expected to set up internal state so that + * packets sent immediately after association, before @a step + * can be called, will be handled appropriately. + * + * This is always called just before association is attempted. + */ + int ( * start ) ( struct net80211_device *dev ); + + /** Process handshaking state + * + * @v dev 802.11 device + * @ret rc Return status code, or positive if done + * + * This method is expected to perform as much progress on the + * protocol it implements as is possible without blocking. It + * should return 0 if it wishes to be called again, a negative + * return status code on error, or a positive value if + * handshaking is complete. In the case of a positive return, + * net80211_crypto_install() must have been called. + * + * If handshaking may require further action (e.g. an AP that + * might decide to rekey), handlers must be installed by this + * function that will act without further calls to @a step. + */ + int ( * step ) ( struct net80211_device *dev ); + + /** Change cryptographic key based on setting + * + * @v dev 802.11 device + * @ret rc Return status code + * + * This method is called whenever the @c netX/key setting + * @e may have been changed. It is expected to determine + * whether it did in fact change, and if so, to install the + * new key using net80211_crypto_install(). If it is not + * possible to do this immediately, this method should return + * an error; in that case the 802.11 stack will reassociate, + * following the usual init/start/step sequence. + * + * This method is only relevant when it is possible to + * associate successfully with an incorrect key. When it is + * not, a failed association will be retried until the user + * changes the key setting, and a successful association will + * not be dropped due to such a change. When association with + * an incorrect key is impossible, this function should return + * 0 after performing no action. + */ + int ( * change_key ) ( struct net80211_device *dev ); + + /** Stop security handshaking handlers + * + * @v dev 802.11 device + * + * This method is called just before freeing a security + * handshaker; it could, for example, delete a process that @a + * start had created to manage the security of the connection. + * If not needed it may be set to NULL. + */ + void ( * stop ) ( struct net80211_device *dev ); + + /** Amount of private data requested + * + * Before @c init is called for the first time, this structure's + * @c priv pointer will point to this many bytes of allocated + * data, where the allocation will be performed separately for + * each net80211_device. + */ + int priv_len; + + /** Whether @a start has been called + * + * Reset to 0 after @a stop is called. + */ + int started; + + /** Pointer to private data + * + * In initializing this structure statically for a linker + * table, set this to NULL. + */ + void *priv; +}; + +#define NET80211_HANDSHAKERS __table ( struct net80211_handshaker, \ + "net80211_handshakers" ) +#define __net80211_handshaker __table_entry ( NET80211_HANDSHAKERS, 01 ) + + +/** Interface to an 802.11 cryptosystem + * + * Cryptosystems define a net80211_crypto structure statically, using + * a gPXE linker table to make it available to the 802.11 layer. When + * the cryptosystem needs to be used, the 802.11 code will allocate a + * copy of the static definition plus whatever space the algorithm has + * requested for private state, and point net80211_device::crypto or + * net80211_device::gcrypto at it. + */ +struct net80211_crypto +{ + /** The cryptographic algorithm implemented */ + enum net80211_crypto_alg algorithm; + + /** Initialize cryptosystem using a given key + * + * @v crypto 802.11 cryptosystem + * @v key Pointer to key bytes + * @v keylen Number of key bytes + * @v rsc Initial receive sequence counter, if applicable + * @ret rc Return status code + * + * This method is passed the communication key provided by the + * security handshake handler, which will already be in the + * low-level form required. It may not store a pointer to the + * key after returning; it must copy it to its private storage. + */ + int ( * init ) ( struct net80211_crypto *crypto, const void *key, + int keylen, const void *rsc ); + + /** Encrypt a frame using the cryptosystem + * + * @v crypto 802.11 cryptosystem + * @v iob I/O buffer + * @ret eiob Newly allocated I/O buffer with encrypted packet + * + * This method is called to encrypt a single frame. It is + * guaranteed that initialize() will have completed + * successfully before this method is called. + * + * The frame passed already has an 802.11 header prepended, + * but the PROTECTED bit in the frame control field will not + * be set; this method is responsible for setting it. The + * returned I/O buffer should contain a complete copy of @a + * iob, including the 802.11 header, but with the PROTECTED + * bit set, the data encrypted, and whatever encryption + * headers/trailers are necessary added. + * + * This method should never free the passed I/O buffer. + * + * Return NULL if the packet could not be encrypted, due to + * memory limitations or otherwise. + */ + struct io_buffer * ( * encrypt ) ( struct net80211_crypto *crypto, + struct io_buffer *iob ); + + /** Decrypt a frame using the cryptosystem + * + * @v crypto 802.11 cryptosystem + * @v eiob Encrypted I/O buffer + * @ret iob Newly allocated I/O buffer with decrypted packet + * + * This method is called to decrypt a single frame. It is + * guaranteed that initialize() will have completed + * successfully before this method is called. + * + * Decryption follows the reverse of the pattern used for + * encryption: this method must copy the 802.11 header into + * the returned packet, decrypt the data stream, remove any + * encryption header or trailer, and clear the PROTECTED bit + * in the frame control header. + * + * This method should never free the passed I/O buffer. + * + * Return NULL if memory was not available for decryption, if + * a consistency or integrity check on the decrypted frame + * failed, or if the decrypted frame should not be processed + * by the network stack for any other reason. + */ + struct io_buffer * ( * decrypt ) ( struct net80211_crypto *crypto, + struct io_buffer *iob ); + + /** Length of private data requested to be allocated */ + int priv_len; + + /** Private data for the algorithm to store key and state info */ + void *priv; +}; + +#define NET80211_CRYPTOS __table ( struct net80211_crypto, "net80211_cryptos" ) +#define __net80211_crypto __table_entry ( NET80211_CRYPTOS, 01 ) + + +struct net80211_probe_ctx; +struct net80211_assoc_ctx; + + +/** Structure encapsulating the complete state of an 802.11 device + * + * An 802.11 device is always wrapped by a network device, and this + * network device is always pointed to by the @a netdev field. In + * general, operations should never be performed by 802.11 code using + * netdev functions directly. It is usually the case that the 802.11 + * layer might need to do some processing or bookkeeping on top of + * what the netdevice code will do. + */ +struct net80211_device +{ + /** The net_device that wraps us. */ + struct net_device *netdev; + + /** List of 802.11 devices. */ + struct list_head list; + + /** 802.11 device operations */ + struct net80211_device_operations *op; + + /** Driver private data */ + void *priv; + + /** Information about the hardware, provided to net80211_register() */ + struct net80211_hw_info *hw; + + /* ---------- Channel and rate fields ---------- */ + + /** A list of all possible channels we might use */ + struct net80211_channel channels[NET80211_MAX_CHANNELS]; + + /** The number of channels in the channels array */ + u8 nr_channels; + + /** The channel currently in use, as an index into the channels array */ + u8 channel; + + /** A list of all possible TX rates we might use + * + * Rates are in units of 100 kbps. + */ + u16 rates[NET80211_MAX_RATES]; + + /** The number of transmission rates in the rates array */ + u8 nr_rates; + + /** The rate currently in use, as an index into the rates array */ + u8 rate; + + /** The rate to use for RTS/CTS transmissions + * + * This is always the fastest basic rate that is not faster + * than the data rate in use. Also an index into the rates array. + */ + u8 rtscts_rate; + + /** Bitmask of basic rates + * + * If bit N is set in this value, with the LSB considered to + * be bit 0, then rate N in the rates array is a "basic" rate. + * + * We don't decide which rates are "basic"; our AP does, and + * we respect its wishes. We need to be able to identify basic + * rates in order to calculate the duration of a CTS packet + * used for 802.11 g/b interoperability. + */ + u32 basic_rates; + + /* ---------- Association fields ---------- */ + + /** The asynchronous association process. + * + * When an 802.11 netdev is opened, or when the user changes + * the SSID setting on an open 802.11 device, an + * autoassociation task is started by net80211_autoassocate() + * to associate with the new best network. The association is + * asynchronous, but no packets can be transmitted until it is + * complete. If it is successful, the wrapping net_device is + * set as "link up". If it fails, @c assoc_rc will be set with + * an error indication. + */ + struct process proc_assoc; + + /** Network with which we are associating + * + * This will be NULL when we are not actively in the process + * of associating with a network we have already successfully + * probed for. + */ + struct net80211_wlan *associating; + + /** Context for the association process + * + * This is a probe_ctx if the @c PROBED flag is not set in @c + * state, and an assoc_ctx otherwise. + */ + union { + struct net80211_probe_ctx *probe; + struct net80211_assoc_ctx *assoc; + } ctx; + + /** Security handshaker being used */ + struct net80211_handshaker *handshaker; + + /** State of our association to the network + * + * Since the association process happens asynchronously, it's + * necessary to have some channel of communication so the + * driver can say "I got an association reply and we're OK" or + * similar. This variable provides that link. It is a bitmask + * of any of NET80211_PROBED, NET80211_AUTHENTICATED, + * NET80211_ASSOCIATED, NET80211_CRYPTO_SYNCED to indicate how + * far along in associating we are; NET80211_WORKING if the + * association task is running; and NET80211_WAITING if a + * packet has been sent that we're waiting for a reply to. We + * can only be crypto-synced if we're associated, we can + * only be associated if we're authenticated, we can only be + * authenticated if we've probed. + * + * If an association process fails (that is, we receive a + * packet with an error indication), the error code is copied + * into bits 6-0 of this variable and bit 7 is set to specify + * what type of error code it is. An AP can provide either a + * "status code" (0-51 are defined) explaining why it refused + * an association immediately, or a "reason code" (0-45 are + * defined) explaining why it canceled an association after it + * had originally OK'ed it. Status and reason codes serve + * similar functions, but they use separate error message + * tables. A gPXE-formatted return status code (negative) is + * placed in @c assoc_rc. + * + * If the failure to associate is indicated by a status code, + * the NET80211_IS_REASON bit will be clear; if it is + * indicated by a reason code, the bit will be set. If we were + * successful, both zero status and zero reason mean success, + * so there is no ambiguity. + * + * To prevent association when opening the device, user code + * can set the NET80211_NO_ASSOC bit. The final bit in this + * variable, NET80211_AUTO_SSID, is used to remember whether + * we picked our SSID through automated probing as opposed to + * user specification; the distinction becomes relevant in the + * settings applicator. + */ + u16 state; + + /** Return status code associated with @c state */ + int assoc_rc; + + /** RSN or WPA information element to include with association + * + * If set to @c NULL, none will be included. It is expected + * that this will be set by the @a init function of a security + * handshaker if it is needed. + */ + union ieee80211_ie *rsn_ie; + + /* ---------- Parameters of currently associated network ---------- */ + + /** 802.11 cryptosystem for our current network + * + * For an open network, this will be set to NULL. + */ + struct net80211_crypto *crypto; + + /** 802.11 cryptosystem for multicast and broadcast frames + * + * If this is NULL, the cryptosystem used for receiving + * unicast frames will also be used for receiving multicast + * and broadcast frames. Transmitted multicast and broadcast + * frames are always sent unicast to the AP, who multicasts + * them on our behalf; thus they always use the unicast + * cryptosystem. + */ + struct net80211_crypto *gcrypto; + + /** MAC address of the access point most recently associated */ + u8 bssid[ETH_ALEN]; + + /** SSID of the access point we are or will be associated with + * + * Although the SSID field in 802.11 packets is generally not + * NUL-terminated, here and in net80211_wlan we add a NUL for + * convenience. + */ + char essid[IEEE80211_MAX_SSID_LEN+1]; + + /** Association ID given to us by the AP */ + u16 aid; + + /** TSFT value for last beacon received, microseconds */ + u64 last_beacon_timestamp; + + /** Time between AP sending beacons, microseconds */ + u32 tx_beacon_interval; + + /** Smoothed average time between beacons, microseconds */ + u32 rx_beacon_interval; + + /* ---------- Physical layer information ---------- */ + + /** Physical layer options + * + * These control the use of CTS protection, short preambles, + * and short-slot operation. + */ + int phy_flags; + + /** Signal strength of last received packet */ + int last_signal; + + /** Rate control state */ + struct rc80211_ctx *rctl; + + /* ---------- Packet handling state ---------- */ + + /** Fragment reassembly state */ + struct net80211_frag_cache frags[NET80211_NR_CONCURRENT_FRAGS]; + + /** The sequence number of the last packet we sent */ + u16 last_tx_seqnr; + + /** Packet duplication elimination state + * + * We are only required to handle immediate duplicates for + * each direct sender, and since we can only have one direct + * sender (the AP), we need only keep the sequence control + * field from the most recent packet we've received. Thus, + * this field stores the last sequence control field we've + * received for a packet from the AP. + */ + u16 last_rx_seq; + + /** RX management packet queue + * + * Sometimes we want to keep probe, beacon, and action packets + * that we receive, such as when we're scanning for networks. + * Ordinarily we drop them because they are sent at a large + * volume (ten beacons per second per AP, broadcast) and we + * have no need of them except when we're scanning. + * + * When keep_mgmt is TRUE, received probe, beacon, and action + * management packets will be stored in this queue. + */ + struct list_head mgmt_queue; + + /** RX management packet info queue + * + * We need to keep track of the signal strength for management + * packets we're keeping, because that provides the only way + * to distinguish between multiple APs for the same network. + * Since we can't extend io_buffer to store signal, this field + * heads a linked list of "RX packet info" structures that + * contain that signal strength field. Its entries always + * parallel the entries in mgmt_queue, because the two queues + * are always added to or removed from in parallel. + */ + struct list_head mgmt_info_queue; + + /** Whether to store management packets + * + * Received beacon, probe, and action packets will be added to + * mgmt_queue (and their signal strengths added to + * mgmt_info_queue) only when this variable is TRUE. It should + * be set by net80211_keep_mgmt() (which returns the old + * value) only when calling code is prepared to poll the + * management queue frequently, because packets will otherwise + * pile up and exhaust memory. + */ + int keep_mgmt; +}; + +/** Structure representing a probed network. + * + * This is returned from the net80211_probe_finish functions and + * passed to the low-level association functions. At least essid, + * bssid, channel, beacon, and security must be filled in if you want + * to build this structure manually. + */ +struct net80211_wlan +{ + /** The human-readable ESSID (network name) + * + * Although the 802.11 SSID field is generally not + * NUL-terminated, the gPXE code adds an extra NUL (and + * expects one in this structure) for convenience. + */ + char essid[IEEE80211_MAX_SSID_LEN+1]; + + /** MAC address of the strongest-signal access point for this ESSID */ + u8 bssid[ETH_ALEN]; + + /** Signal strength of beacon frame from that access point */ + int signal; + + /** The channel on which that access point communicates + * + * This is a raw channel number (net80211_channel::channel_nr), + * so that it will not be affected by reconfiguration of the + * device channels array. + */ + int channel; + + /** The complete beacon or probe-response frame received */ + struct io_buffer *beacon; + + /** Security handshaking method used on the network */ + enum net80211_security_proto handshaking; + + /** Cryptographic algorithm used on the network */ + enum net80211_crypto_alg crypto; + + /** Link to allow chaining multiple structures into a list to + be returned from net80211_probe_finish_all(). */ + struct list_head list; +}; + + +/** 802.11 encryption key setting */ +extern struct setting net80211_key_setting __setting; + + +/** + * @defgroup net80211_probe 802.11 network location API + * @{ + */ +int net80211_prepare_probe ( struct net80211_device *dev, int band, + int active ); +struct net80211_probe_ctx * net80211_probe_start ( struct net80211_device *dev, + const char *essid, + int active ); +int net80211_probe_step ( struct net80211_probe_ctx *ctx ); +struct net80211_wlan * +net80211_probe_finish_best ( struct net80211_probe_ctx *ctx ); +struct list_head *net80211_probe_finish_all ( struct net80211_probe_ctx *ctx ); + +void net80211_free_wlan ( struct net80211_wlan *wlan ); +void net80211_free_wlanlist ( struct list_head *list ); +/** @} */ + + +/** + * @defgroup net80211_mgmt 802.11 network management API + * @{ + */ +struct net80211_device * net80211_get ( struct net_device *netdev ); +void net80211_autoassociate ( struct net80211_device *dev ); + +int net80211_change_channel ( struct net80211_device *dev, int channel ); +void net80211_set_rate_idx ( struct net80211_device *dev, int rate ); + +int net80211_keep_mgmt ( struct net80211_device *dev, int enable ); +struct io_buffer * net80211_mgmt_dequeue ( struct net80211_device *dev, + int *signal ); +int net80211_tx_mgmt ( struct net80211_device *dev, u16 fc, + u8 bssid[ETH_ALEN], struct io_buffer *iob ); +/** @} */ + + +/** + * @defgroup net80211_assoc 802.11 network association API + * @{ + */ +int net80211_prepare_assoc ( struct net80211_device *dev, + struct net80211_wlan *wlan ); +int net80211_send_auth ( struct net80211_device *dev, + struct net80211_wlan *wlan, int method ); +int net80211_send_assoc ( struct net80211_device *dev, + struct net80211_wlan *wlan ); +void net80211_deauthenticate ( struct net80211_device *dev, int rc ); +/** @} */ + + +/** + * @defgroup net80211_driver 802.11 driver interface API + * @{ + */ +struct net80211_device *net80211_alloc ( size_t priv_size ); +int net80211_register ( struct net80211_device *dev, + struct net80211_device_operations *ops, + struct net80211_hw_info *hw ); +u16 net80211_duration ( struct net80211_device *dev, int bytes, u16 rate ); +void net80211_rx ( struct net80211_device *dev, struct io_buffer *iob, + int signal, u16 rate ); +void net80211_rx_err ( struct net80211_device *dev, + struct io_buffer *iob, int rc ); +void net80211_tx_complete ( struct net80211_device *dev, + struct io_buffer *iob, int retries, int rc ); +void net80211_unregister ( struct net80211_device *dev ); +void net80211_free ( struct net80211_device *dev ); +/** @} */ + +/** + * Calculate duration field for a CTS control frame + * + * @v dev 802.11 device + * @v size Size of the packet being cleared to send + * + * A CTS control frame's duration field captures the frame being + * protected and its 10-byte ACK. + */ +static inline u16 net80211_cts_duration ( struct net80211_device *dev, + int size ) +{ + return ( net80211_duration ( dev, 10, + dev->rates[dev->rtscts_rate] ) + + net80211_duration ( dev, size, dev->rates[dev->rate] ) ); +} + +#endif diff --git a/gpxe/src/include/gpxe/netdevice.h b/gpxe/src/include/gpxe/netdevice.h index f1585de0..858d8e97 100644 --- a/gpxe/src/include/gpxe/netdevice.h +++ b/gpxe/src/include/gpxe/netdevice.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/list.h> #include <gpxe/tables.h> @@ -19,11 +21,26 @@ struct net_protocol; struct ll_protocol; struct device; -/** Maximum length of a link-layer address */ +/** Maximum length of a hardware address + * + * The longest currently-supported link-layer address is for IPoIB. + */ +#define MAX_HW_ADDR_LEN 8 + +/** Maximum length of a link-layer address + * + * The longest currently-supported link-layer address is for IPoIB. + */ #define MAX_LL_ADDR_LEN 20 -/** Maximum length of a link-layer header */ -#define MAX_LL_HEADER_LEN 6 +/** Maximum length of a link-layer header + * + * The longest currently-supported link-layer header is for 802.11: a + * 24-byte frame header plus an 8-byte 802.3 LLC/SNAP header. (The + * IPoIB link-layer pseudo-header doesn't actually include link-layer + * addresses; see ipoib.c for details). + */ +#define MAX_LL_HEADER_LEN 32 /** Maximum length of a network-layer address */ #define MAX_NET_ADDR_LEN 4 @@ -78,30 +95,41 @@ struct ll_protocol { /** * Add link-layer header * + * @v netdev Network device * @v iobuf I/O buffer * @v ll_dest Link-layer destination address * @v ll_source Source link-layer address * @v net_proto Network-layer protocol, in network-byte order * @ret rc Return status code */ - int ( * push ) ( struct io_buffer *iobuf, const void *ll_dest, - const void *ll_source, uint16_t net_proto ); + int ( * push ) ( struct net_device *netdev, struct io_buffer *iobuf, + const void *ll_dest, const void *ll_source, + uint16_t net_proto ); /** * Remove link-layer header * + * @v netdev Network device * @v iobuf I/O buffer * @ret ll_dest Link-layer destination address * @ret ll_source Source link-layer address * @ret net_proto Network-layer protocol, in network-byte order * @ret rc Return status code */ - int ( * pull ) ( struct io_buffer *iobuf, const void **ll_dest, - const void **ll_source, uint16_t *net_proto ); + int ( * pull ) ( struct net_device *netdev, struct io_buffer *iobuf, + const void **ll_dest, const void **ll_source, + uint16_t *net_proto ); + /** + * Initialise link-layer address + * + * @v hw_addr Hardware address + * @v ll_addr Link-layer address to fill in + */ + void ( * init_addr ) ( const void *hw_addr, void *ll_addr ); /** * Transcribe link-layer address * - * @v ll_addr Link-layer address - * @ret string Human-readable transcription of address + * @v ll_addr Link-layer address + * @ret string Human-readable transcription of address * * This method should convert the link-layer address into a * human-readable format. @@ -109,28 +137,35 @@ struct ll_protocol { * The buffer used to hold the transcription is statically * allocated. */ - const char * ( * ntoa ) ( const void * ll_addr ); + const char * ( * ntoa ) ( const void *ll_addr ); /** * Hash multicast address * - * @v af Address family - * @v net_addr Network-layer address - * @v ll_addr Link-layer address to fill in - * @ret rc Return status code + * @v af Address family + * @v net_addr Network-layer address + * @v ll_addr Link-layer address to fill in + * @ret rc Return status code */ int ( * mc_hash ) ( unsigned int af, const void *net_addr, void *ll_addr ); + /** + * Generate Ethernet-compatible compressed link-layer address + * + * @v ll_addr Link-layer address + * @v eth_addr Ethernet-compatible address to fill in + */ + int ( * eth_addr ) ( const void *ll_addr, void *eth_addr ); /** Link-layer protocol * * This is an ARPHRD_XXX constant, in network byte order. */ uint16_t ll_proto; + /** Hardware address length */ + uint8_t hw_addr_len; /** Link-layer address length */ uint8_t ll_addr_len; /** Link-layer header length */ uint8_t ll_header_len; - /** Link-layer broadcast address */ - const uint8_t *ll_broadcast; }; /** Network device operations */ @@ -241,17 +276,35 @@ struct net_device { /** Link-layer protocol */ struct ll_protocol *ll_protocol; + /** Hardware address + * + * This is an address which is an intrinsic property of the + * hardware, e.g. an address held in EEPROM. + * + * Note that the hardware address may not be the same length + * as the link-layer address. + */ + uint8_t hw_addr[MAX_HW_ADDR_LEN]; /** Link-layer address * - * For Ethernet, this is the MAC address. + * This is the current link-layer address assigned to the + * device. It can be changed at runtime. */ uint8_t ll_addr[MAX_LL_ADDR_LEN]; + /** Link-layer broadcast address */ + const uint8_t *ll_broadcast; /** Current device state * * This is the bitwise-OR of zero or more NETDEV_XXX constants. */ unsigned int state; + /** Link status code + * + * Zero indicates that the link is up; any other value + * indicates the error preventing link-up. + */ + int link_rc; /** Maximum packet length * * This length includes any link-layer headers. @@ -267,7 +320,7 @@ struct net_device { struct net_device_stats rx_stats; /** Configuration settings applicable to this device */ - struct simple_settings settings; + struct generic_settings settings; /** Driver private data */ void *priv; @@ -276,17 +329,21 @@ struct net_device { /** Network device is open */ #define NETDEV_OPEN 0x0001 -/** Network device has link */ -#define NETDEV_LINK_UP 0x0002 +/** Link-layer protocol table */ +#define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" ) /** Declare a link-layer protocol */ -#define __ll_protocol __table ( struct ll_protocol, ll_protocols, 01 ) +#define __ll_protocol __table_entry ( LL_PROTOCOLS, 01 ) + +/** Network-layer protocol table */ +#define NET_PROTOCOLS __table ( struct net_protocol, "net_protocols" ) /** Declare a network-layer protocol */ -#define __net_protocol __table ( struct net_protocol, net_protocols, 01 ) +#define __net_protocol __table_entry ( NET_PROTOCOLS, 01 ) extern struct list_head net_devices; extern struct net_device_operations null_netdev_operations; +extern struct settings_operations netdev_settings_operations; /** * Initialise a network device @@ -312,12 +369,12 @@ static inline void netdev_nullify ( struct net_device *netdev ) { } /** - * Get printable network device hardware address + * Get printable network device link-layer address * * @v netdev Network device - * @ret name Hardware address + * @ret name Link-layer address */ -static inline const char * netdev_hwaddr ( struct net_device *netdev ) { +static inline const char * netdev_addr ( struct net_device *netdev ) { return netdev->ll_protocol->ntoa ( netdev->ll_addr ); } @@ -378,23 +435,38 @@ netdev_settings ( struct net_device *netdev ) { } /** + * Initialise a per-netdevice configuration settings block + * + * @v generics Generic settings block + * @v refcnt Containing object reference counter, or NULL + * @v name Settings block name + */ +static inline __attribute__ (( always_inline )) void +netdev_settings_init ( struct net_device *netdev ) { + generic_settings_init ( &netdev->settings, + &netdev->refcnt, netdev->name ); + netdev->settings.settings.op = &netdev_settings_operations; +} + +/** * Mark network device as having link up * * @v netdev Network device */ static inline __attribute__ (( always_inline )) void netdev_link_up ( struct net_device *netdev ) { - netdev->state |= NETDEV_LINK_UP; + netdev->link_rc = 0; } /** - * Mark network device as having link down + * Mark network device as having link down due to a specific error * * @v netdev Network device + * @v rc Link status code */ static inline __attribute__ (( always_inline )) void -netdev_link_down ( struct net_device *netdev ) { - netdev->state &= ~NETDEV_LINK_UP; +netdev_link_err ( struct net_device *netdev, int rc ) { + netdev->link_rc = rc; } /** @@ -405,9 +477,10 @@ netdev_link_down ( struct net_device *netdev ) { */ static inline __attribute__ (( always_inline )) int netdev_link_ok ( struct net_device *netdev ) { - return ( netdev->state & NETDEV_LINK_UP ); + return ( netdev->link_rc == 0 ); } +extern void netdev_link_down ( struct net_device *netdev ); extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ); extern void netdev_tx_complete_err ( struct net_device *netdev, struct io_buffer *iobuf, int rc ); @@ -432,8 +505,6 @@ extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev, uint16_t net_proto, const void *ll_source ); -extern struct settings_operations netdev_settings_operations; - /** * Complete network transmission * diff --git a/gpxe/src/include/gpxe/null_nap.h b/gpxe/src/include/gpxe/null_nap.h index 6dd0cda3..0f46eaa2 100644 --- a/gpxe/src/include/gpxe/null_nap.h +++ b/gpxe/src/include/gpxe/null_nap.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #ifdef NAP_NULL #define NAP_PREFIX_null #else diff --git a/gpxe/src/include/gpxe/nvo.h b/gpxe/src/include/gpxe/nvo.h index 28068f4b..c9650706 100644 --- a/gpxe/src/include/gpxe/nvo.h +++ b/gpxe/src/include/gpxe/nvo.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/dhcpopts.h> #include <gpxe/settings.h> diff --git a/gpxe/src/include/gpxe/nvs.h b/gpxe/src/include/gpxe/nvs.h index b026dd46..5c90c655 100644 --- a/gpxe/src/include/gpxe/nvs.h +++ b/gpxe/src/include/gpxe/nvs.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> /** A non-volatile storage device */ diff --git a/gpxe/src/include/gpxe/open.h b/gpxe/src/include/gpxe/open.h index 81d5fc24..ebf754da 100644 --- a/gpxe/src/include/gpxe/open.h +++ b/gpxe/src/include/gpxe/open.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdarg.h> #include <gpxe/tables.h> #include <gpxe/socket.h> @@ -58,8 +60,11 @@ struct uri_opener { int ( * open ) ( struct xfer_interface *xfer, struct uri *uri ); }; +/** URI opener table */ +#define URI_OPENERS __table ( struct uri_opener, "uri_openers" ) + /** Register a URI opener */ -#define __uri_opener __table ( struct uri_opener, uri_openers, 01 ) +#define __uri_opener __table_entry ( URI_OPENERS, 01 ) /** A socket opener */ struct socket_opener { @@ -78,8 +83,11 @@ struct socket_opener { struct sockaddr *local ); }; +/** Socket opener table */ +#define SOCKET_OPENERS __table ( struct socket_opener, "socket_openers" ) + /** Register a socket opener */ -#define __socket_opener __table ( struct socket_opener, socket_openers, 01 ) +#define __socket_opener __table_entry ( SOCKET_OPENERS, 01 ) extern int xfer_open_uri ( struct xfer_interface *xfer, struct uri *uri ); extern int xfer_open_uri_string ( struct xfer_interface *xfer, @@ -91,5 +99,7 @@ extern int xfer_open_socket ( struct xfer_interface *xfer, int semantics, struct sockaddr *peer, struct sockaddr *local ); extern int xfer_vopen ( struct xfer_interface *xfer, int type, va_list args ); extern int xfer_open ( struct xfer_interface *xfer, int type, ... ); +extern int xfer_vreopen ( struct xfer_interface *xfer, int type, + va_list args ); #endif /* _GPXE_OPEN_H */ diff --git a/gpxe/src/include/gpxe/pci.h b/gpxe/src/include/gpxe/pci.h index 1ccdb100..8bcf1e0c 100644 --- a/gpxe/src/include/gpxe/pci.h +++ b/gpxe/src/include/gpxe/pci.h @@ -16,6 +16,8 @@ * your option) any later version. */ +FILE_LICENCE ( GPL2_ONLY ); + #include <stdint.h> #include <gpxe/device.h> #include <gpxe/tables.h> @@ -41,6 +43,7 @@ #define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ #define PCI_COMMAND_SERR 0x100 /* Enable SERR */ #define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ +#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ #define PCI_VENDOR_ID 0x00 /* 16 bits */ @@ -233,6 +236,33 @@ #define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */ #define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ +/* Advanced Error Reporting */ + +#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */ +#define PCI_ERR_UNC_TRAIN 0x00000001 /* Training */ +#define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */ +#define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */ +#define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */ +#define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */ +#define PCI_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */ +#define PCI_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */ +#define PCI_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */ +#define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */ +#define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */ +#define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */ +#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */ + /* Same bits as above */ +#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */ + /* Same bits as above */ +#define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */ +#define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */ +#define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */ +#define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */ +#define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */ +#define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */ +#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */ + /* Same bits as above */ + /** A PCI device ID list entry */ struct pci_device_id { /** Name */ @@ -241,6 +271,8 @@ struct pci_device_id { uint16_t vendor; /** PCI device ID */ uint16_t device; + /** Arbitrary driver data */ + unsigned long driver_data; }; /** Match-anything ID */ @@ -308,12 +340,16 @@ struct pci_driver { void ( * remove ) ( struct pci_device *pci ); }; +/** PCI driver table */ +#define PCI_DRIVERS __table ( struct pci_driver, "pci_drivers" ) + /** Declare a PCI driver */ -#define __pci_driver __table ( struct pci_driver, pci_drivers, 01 ) +#define __pci_driver __table_entry ( PCI_DRIVERS, 01 ) #define PCI_DEVFN( slot, func ) ( ( (slot) << 3 ) | (func) ) #define PCI_SLOT( devfn ) ( ( (devfn) >> 3 ) & 0x1f ) #define PCI_FUNC( devfn ) ( (devfn) & 0x07 ) +#define PCI_BUS( busdevfn ) ( (busdevfn) >> 8 ) #define PCI_BUSDEVFN( bus, devfn ) ( ( (bus) << 8 ) | (devfn) ) #define PCI_BASE_CLASS( class ) ( (class) >> 16 ) @@ -324,12 +360,18 @@ struct pci_driver { * PCI_ROM is used to build up entries in a struct pci_id array. It * is also parsed by parserom.pl to generate Makefile rules and files * for rom-o-matic. + * + * PCI_ID can be used to generate entries without creating a + * corresponding ROM in the build process. */ -#define PCI_ROM( _vendor, _device, _name, _description ) { \ - .vendor = _vendor, \ - .device = _device, \ - .name = _name, \ +#define PCI_ID( _vendor, _device, _name, _description, _data ) { \ + .vendor = _vendor, \ + .device = _device, \ + .name = _name, \ + .driver_data = _data \ } +#define PCI_ROM( _vendor, _device, _name, _description, _data ) \ + PCI_ID( _vendor, _device, _name, _description, _data ) extern void adjust_pci_device ( struct pci_device *pci ); extern unsigned long pci_bar_start ( struct pci_device *pci, diff --git a/gpxe/src/include/gpxe/pci_ids.h b/gpxe/src/include/gpxe/pci_ids.h index 075ff96b..42070138 100644 --- a/gpxe/src/include/gpxe/pci_ids.h +++ b/gpxe/src/include/gpxe/pci_ids.h @@ -7,6 +7,8 @@ * Please keep sorted. */ +FILE_LICENCE ( GPL2_ONLY ); + /* Device classes and subclasses */ #define PCI_CLASS_NOT_DEFINED 0x0000 @@ -315,6 +317,7 @@ #define PCI_VENDOR_ID_TIMEDIA 0x1409 #define PCI_VENDOR_ID_OXSEMI 0x1415 #define PCI_VENDOR_ID_AIRONET 0x14b9 +#define PCI_VENDOR_ID_MYRICOM 0x14c1 #define PCI_VENDOR_ID_TITAN 0x14D2 #define PCI_VENDOR_ID_PANACOM 0x14d4 #define PCI_VENDOR_ID_BROADCOM 0x14e4 diff --git a/gpxe/src/include/gpxe/pci_io.h b/gpxe/src/include/gpxe/pci_io.h index 365166c8..8b2729ab 100644 --- a/gpxe/src/include/gpxe/pci_io.h +++ b/gpxe/src/include/gpxe/pci_io.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/api.h> #include <config/ioapi.h> diff --git a/gpxe/src/include/gpxe/pcibackup.h b/gpxe/src/include/gpxe/pcibackup.h new file mode 100644 index 00000000..3d295c0f --- /dev/null +++ b/gpxe/src/include/gpxe/pcibackup.h @@ -0,0 +1,33 @@ +#ifndef _GPXE_PCIBACKUP_H +#define _GPXE_PCIBACKUP_H + +/** @file + * + * PCI configuration space backup and restoration + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> + +/** A PCI configuration space backup */ +struct pci_config_backup { + uint32_t dwords[64]; +}; + +/** PCI configuration space backup exclusion list end marker */ +#define PCI_CONFIG_BACKUP_EXCLUDE_END 0xff + +/** Define a PCI configuration space backup exclusion list */ +#define PCI_CONFIG_BACKUP_EXCLUDE(...) \ + { __VA_ARGS__, PCI_CONFIG_BACKUP_EXCLUDE_END } + +extern void pci_backup ( struct pci_device *pci, + struct pci_config_backup *backup, + const uint8_t *exclude ); +extern void pci_restore ( struct pci_device *pci, + struct pci_config_backup *backup, + const uint8_t *exclude ); + +#endif /* _GPXE_PCIBACKUP_H */ diff --git a/gpxe/src/include/gpxe/posix_io.h b/gpxe/src/include/gpxe/posix_io.h index 9984db00..3063dfff 100644 --- a/gpxe/src/include/gpxe/posix_io.h +++ b/gpxe/src/include/gpxe/posix_io.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/uaccess.h> diff --git a/gpxe/src/include/gpxe/process.h b/gpxe/src/include/gpxe/process.h index 8d9b109a..944858d7 100644 --- a/gpxe/src/include/gpxe/process.h +++ b/gpxe/src/include/gpxe/process.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/list.h> #include <gpxe/refcnt.h> #include <gpxe/tables.h> @@ -45,6 +47,7 @@ static inline __attribute__ (( always_inline )) void process_init_stopped ( struct process *process, void ( * step ) ( struct process *process ), struct refcnt *refcnt ) { + INIT_LIST_HEAD ( &process->list ); process->step = step; process->refcnt = refcnt; } @@ -63,13 +66,15 @@ process_init ( struct process *process, process_add ( process ); } +/** Permanent process table */ +#define PERMANENT_PROCESSES __table ( struct process, "processes" ) + /** * Declare a permanent process * * Permanent processes will be automatically added to the process list * at initialisation time. */ -#define __permanent_process \ - __table ( struct process, processes, 01 ) +#define __permanent_process __table_entry ( PERMANENT_PROCESSES, 01 ) #endif /* _GPXE_PROCESS_H */ diff --git a/gpxe/src/include/gpxe/profile.h b/gpxe/src/include/gpxe/profile.h index d46ca05a..a5bdd3a4 100644 --- a/gpxe/src/include/gpxe/profile.h +++ b/gpxe/src/include/gpxe/profile.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> /** diff --git a/gpxe/src/include/gpxe/ramdisk.h b/gpxe/src/include/gpxe/ramdisk.h index 4a77f05e..31a1d998 100644 --- a/gpxe/src/include/gpxe/ramdisk.h +++ b/gpxe/src/include/gpxe/ramdisk.h @@ -8,6 +8,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/uaccess.h> #include <gpxe/blockdev.h> diff --git a/gpxe/src/include/gpxe/rarp.h b/gpxe/src/include/gpxe/rarp.h index 81e03bde..7ade8312 100644 --- a/gpxe/src/include/gpxe/rarp.h +++ b/gpxe/src/include/gpxe/rarp.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + struct net_protocol; extern struct net_protocol rarp_protocol; diff --git a/gpxe/src/include/gpxe/rc80211.h b/gpxe/src/include/gpxe/rc80211.h new file mode 100644 index 00000000..0856896c --- /dev/null +++ b/gpxe/src/include/gpxe/rc80211.h @@ -0,0 +1,19 @@ +#ifndef _GPXE_RC80211_H +#define _GPXE_RC80211_H + +/** @file + * + * Rate-control algorithm prototype for 802.11. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +struct net80211_device; +struct rc80211_ctx; + +struct rc80211_ctx * rc80211_init ( struct net80211_device *dev ); +void rc80211_update_tx ( struct net80211_device *dev, int retries, int rc ); +void rc80211_update_rx ( struct net80211_device *dev, int retry, u16 rate ); +void rc80211_free ( struct rc80211_ctx *ctx ); + +#endif /* _GPXE_RC80211_H */ diff --git a/gpxe/src/include/gpxe/refcnt.h b/gpxe/src/include/gpxe/refcnt.h index 68e0fd4b..e56f1d31 100644 --- a/gpxe/src/include/gpxe/refcnt.h +++ b/gpxe/src/include/gpxe/refcnt.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** * A reference counter * diff --git a/gpxe/src/include/gpxe/resolv.h b/gpxe/src/include/gpxe/resolv.h index e73c8201..33bb0986 100644 --- a/gpxe/src/include/gpxe/resolv.h +++ b/gpxe/src/include/gpxe/resolv.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/refcnt.h> #include <gpxe/interface.h> #include <gpxe/tables.h> @@ -149,9 +151,11 @@ struct resolver { /** Normal resolver priority */ #define RESOLV_NORMAL 02 +/** Resolvers table */ +#define RESOLVERS __table ( struct resolver, "resolvers" ) + /** Register as a name resolver */ -#define __resolver( resolv_order ) \ - __table ( struct resolver, resolvers, resolv_order ) +#define __resolver( resolv_order ) __table_entry ( RESOLVERS, resolv_order ) extern void resolv_done ( struct resolv_interface *resolv, struct sockaddr *sa, int rc ); diff --git a/gpxe/src/include/gpxe/retry.h b/gpxe/src/include/gpxe/retry.h index 1e7fde4c..ada0204d 100644 --- a/gpxe/src/include/gpxe/retry.h +++ b/gpxe/src/include/gpxe/retry.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/list.h> /** Default timeout value */ diff --git a/gpxe/src/include/gpxe/rotate.h b/gpxe/src/include/gpxe/rotate.h index 42ec7196..0371c578 100644 --- a/gpxe/src/include/gpxe/rotate.h +++ b/gpxe/src/include/gpxe/rotate.h @@ -6,6 +6,8 @@ * Bit operations */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> static inline uint32_t rol32 ( uint32_t data, unsigned int rotation ) { diff --git a/gpxe/src/include/gpxe/rsa.h b/gpxe/src/include/gpxe/rsa.h index e30e1a5a..5052ad46 100644 --- a/gpxe/src/include/gpxe/rsa.h +++ b/gpxe/src/include/gpxe/rsa.h @@ -1,6 +1,8 @@ #ifndef _GPXE_RSA_H #define _GPXE_RSA_H +FILE_LICENCE ( GPL2_OR_LATER ); + struct pubkey_algorithm; extern struct pubkey_algorithm rsa_algorithm; diff --git a/gpxe/src/include/gpxe/sanboot.h b/gpxe/src/include/gpxe/sanboot.h index ea26a356..fd063164 100644 --- a/gpxe/src/include/gpxe/sanboot.h +++ b/gpxe/src/include/gpxe/sanboot.h @@ -1,6 +1,8 @@ #ifndef _GPXE_SANBOOT_H #define _GPXE_SANBOOT_H +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/tables.h> struct sanboot_protocol { @@ -8,7 +10,11 @@ struct sanboot_protocol { int ( * boot ) ( const char *root_path ); }; -#define __sanboot_protocol \ - __table ( struct sanboot_protocol, sanboot_protocols, 01 ) +#define SANBOOT_PROTOCOLS \ + __table ( struct sanboot_protocol, "sanboot_protocols" ) + +#define __sanboot_protocol __table_entry ( SANBOOT_PROTOCOLS, 01 ) + +extern int keep_san ( void ); #endif /* _GPXE_SANBOOT_H */ diff --git a/gpxe/src/include/gpxe/scsi.h b/gpxe/src/include/gpxe/scsi.h index e820117b..97416970 100644 --- a/gpxe/src/include/gpxe/scsi.h +++ b/gpxe/src/include/gpxe/scsi.h @@ -12,6 +12,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** * @defgroup scsiops SCSI operation codes * @{ @@ -234,18 +236,23 @@ struct scsi_command { uint8_t status; /** SCSI sense response code */ uint8_t sense_response; + /** Command status code */ + int rc; }; +/** A SCSI LUN + * + * This is a four-level LUN as specified by SAM-2, in big-endian + * order. + */ +struct scsi_lun { + uint16_t u16[4]; +} __attribute__ (( packed )); + /** A SCSI device */ struct scsi_device { /** Block device interface */ struct block_device blockdev; - /** Logical unit number (LUN) - * - * This is a four-level LUN as specified by SAM-2, in - * big-endian order. - */ - uint64_t lun; /** * Issue SCSI command * @@ -254,10 +261,11 @@ struct scsi_device { * @ret rc Return status code * * Note that a successful return status code indicates only - * that the SCSI command completed. The caller must check the - * status field in the command structure to see if, for - * example, the device returned CHECK CONDITION or some other - * non-success status code. + * that the SCSI command was issued. The caller must check + * the status field in the command structure to see when the + * command completes and whether, for example, the device + * returned CHECK CONDITION or some other non-success status + * code. */ int ( * command ) ( struct scsi_device *scsi, struct scsi_command *command ); @@ -265,6 +273,9 @@ struct scsi_device { struct refcnt *backend; }; +extern int scsi_detached_command ( struct scsi_device *scsi, + struct scsi_command *command ); extern int init_scsidev ( struct scsi_device *scsi ); +extern int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun ); #endif /* _GPXE_SCSI_H */ diff --git a/gpxe/src/include/gpxe/sec80211.h b/gpxe/src/include/gpxe/sec80211.h new file mode 100644 index 00000000..502ebf7d --- /dev/null +++ b/gpxe/src/include/gpxe/sec80211.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPXE_SEC80211_H +#define _GPXE_SEC80211_H + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <gpxe/net80211.h> +#include <errno.h> + +/** @file + * + * Definitions for general secured-network routines. + * + * Any function in this file which may be referenced by code which is + * not exclusive to encryption-enabled builds (e.g. sec80211_detect(), + * which is called by net80211_probe_step() to fill the net80211_wlan + * structure's security fields) must be declared as a weak symbol, + * using an inline interface similar to that used for + * sec80211_detect() below. This prevents secure network support from + * bloating general builds by any more than a few tiny hooks to call + * crypto functions when crypto structures are non-NULL. + */ + +int _sec80211_detect ( struct io_buffer *iob, + enum net80211_security_proto *secprot, + enum net80211_crypto_alg *crypt ) + __attribute__ (( weak )); + + +/** + * Inline safety wrapper for _sec80211_detect() + * + * @v iob I/O buffer containing beacon frame + * @ret secprot Security handshaking protocol used by network + * @ret crypt Cryptosystem used by network + * @ret rc Return status code + * + * This function transparently calls _sec80211_detect() if the file + * containing it was compiled in, or returns an error indication of + * @c -ENOTSUP if not. + */ +static inline int sec80211_detect ( struct io_buffer *iob, + enum net80211_security_proto *secprot, + enum net80211_crypto_alg *crypt ) { + if ( _sec80211_detect ) + return _sec80211_detect ( iob, secprot, crypt ); + return -ENOTSUP; +} + +int sec80211_detect_ie ( int is_rsn, u8 *start, u8 *end, + enum net80211_security_proto *secprot, + enum net80211_crypto_alg *crypt ); +u8 * sec80211_find_rsn ( union ieee80211_ie *ie, void *ie_end, + int *is_rsn, u8 **end ); + +int sec80211_install ( struct net80211_crypto **which, + enum net80211_crypto_alg crypt, + const void *key, int len, const void *rsc ); + +u32 sec80211_rsn_get_crypto_desc ( enum net80211_crypto_alg crypt, int rsnie ); +u32 sec80211_rsn_get_akm_desc ( enum net80211_security_proto secprot, + int rsnie ); +enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt ( u32 desc ); + +#endif /* _GPXE_SEC80211_H */ + diff --git a/gpxe/src/include/gpxe/segment.h b/gpxe/src/include/gpxe/segment.h index 5ab91699..5b59c54c 100644 --- a/gpxe/src/include/gpxe/segment.h +++ b/gpxe/src/include/gpxe/segment.h @@ -8,6 +8,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/uaccess.h> extern int prep_segment ( userptr_t segment, size_t filesz, size_t memsz ); diff --git a/gpxe/src/include/gpxe/serial.h b/gpxe/src/include/gpxe/serial.h index 2825b936..a72ca7e8 100644 --- a/gpxe/src/include/gpxe/serial.h +++ b/gpxe/src/include/gpxe/serial.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + extern void serial_putc ( int ch ); extern int serial_getc ( void ); extern int serial_ischar ( void ); diff --git a/gpxe/src/include/gpxe/settings.h b/gpxe/src/include/gpxe/settings.h index 9e62cdea..efefe73a 100644 --- a/gpxe/src/include/gpxe/settings.h +++ b/gpxe/src/include/gpxe/settings.h @@ -7,11 +7,12 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/tables.h> #include <gpxe/list.h> #include <gpxe/refcnt.h> -#include <gpxe/dhcpopts.h> struct settings; struct in_addr; @@ -36,8 +37,11 @@ struct setting { unsigned int tag; }; +/** Configuration setting table */ +#define SETTINGS __table ( struct setting, "settings" ) + /** Declare a configuration setting */ -#define __setting __table ( struct setting, settings, 01 ) +#define __setting __table_entry ( SETTINGS, 01 ) /** Settings block operations */ struct settings_operations { @@ -64,6 +68,11 @@ struct settings_operations { */ int ( * fetch ) ( struct settings *settings, struct setting *setting, void *data, size_t len ); + /** Clear settings block + * + * @v settings Settings block + */ + void ( * clear ) ( struct settings *settings ); }; /** A settings block */ @@ -123,9 +132,11 @@ struct setting_type { char *buf, size_t len ); }; +/** Configuration setting type table */ +#define SETTING_TYPES __table ( struct setting_type, "setting_types" ) + /** Declare a configuration setting type */ -#define __setting_type \ - __table ( struct setting_type, setting_types, 01 ) +#define __setting_type __table_entry ( SETTING_TYPES, 01 ) /** * A settings applicator @@ -139,28 +150,32 @@ struct settings_applicator { int ( * apply ) ( void ); }; +/** Settings applicator table */ +#define SETTINGS_APPLICATORS \ + __table ( struct settings_applicator, "settings_applicators" ) + /** Declare a settings applicator */ -#define __settings_applicator \ - __table ( struct settings_applicator, settings_applicators, 01 ) +#define __settings_applicator __table_entry ( SETTINGS_APPLICATORS, 01 ) /** - * A simple settings block + * A generic settings block * */ -struct simple_settings { +struct generic_settings { /** Settings block */ struct settings settings; - /** DHCP options */ - struct dhcp_options dhcpopts; + /** List of generic settings */ + struct list_head list; }; -extern struct settings_operations simple_settings_operations; -extern int simple_settings_store ( struct settings *settings, - struct setting *setting, - const void *data, size_t len ); -extern int simple_settings_fetch ( struct settings *settings, - struct setting *setting, - void *data, size_t len ); +extern struct settings_operations generic_settings_operations; +extern int generic_settings_store ( struct settings *settings, + struct setting *setting, + const void *data, size_t len ); +extern int generic_settings_fetch ( struct settings *settings, + struct setting *setting, + void *data, size_t len ); +extern void generic_settings_clear ( struct settings *settings ); extern int register_settings ( struct settings *settings, struct settings *parent ); @@ -191,10 +206,9 @@ extern unsigned long fetch_uintz_setting ( struct settings *settings, struct setting *setting ); extern int fetch_uuid_setting ( struct settings *settings, struct setting *setting, union uuid *uuid ); +extern void clear_settings ( struct settings *settings ); extern int setting_cmp ( struct setting *a, struct setting *b ); -extern struct settings * find_child_settings ( struct settings *parent, - const char *name ); extern struct settings * find_settings ( const char *name ); extern int storef_setting ( struct settings *settings, @@ -228,6 +242,7 @@ extern struct setting priority_setting __setting; extern struct setting uuid_setting __setting; extern struct setting next_server_setting __setting; extern struct setting mac_setting __setting; +extern struct setting busid_setting __setting; extern struct setting user_class_setting __setting; /** @@ -255,15 +270,16 @@ static inline void settings_init ( struct settings *settings, /** * Initialise a settings block * - * @v simple Simple settings block + * @v generics Generic settings block * @v refcnt Containing object reference counter, or NULL * @v name Settings block name */ -static inline void simple_settings_init ( struct simple_settings *simple, - struct refcnt *refcnt, - const char *name ) { - settings_init ( &simple->settings, &simple_settings_operations, +static inline void generic_settings_init ( struct generic_settings *generics, + struct refcnt *refcnt, + const char *name ) { + settings_init ( &generics->settings, &generic_settings_operations, refcnt, name, 0 ); + INIT_LIST_HEAD ( &generics->list ); } /** diff --git a/gpxe/src/include/gpxe/settings_ui.h b/gpxe/src/include/gpxe/settings_ui.h index 48548fd5..a82d7336 100644 --- a/gpxe/src/include/gpxe/settings_ui.h +++ b/gpxe/src/include/gpxe/settings_ui.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + struct settings; extern int settings_ui ( struct settings *settings ) __nonnull; diff --git a/gpxe/src/include/gpxe/sha1.h b/gpxe/src/include/gpxe/sha1.h index 66370d42..c203d995 100644 --- a/gpxe/src/include/gpxe/sha1.h +++ b/gpxe/src/include/gpxe/sha1.h @@ -1,6 +1,8 @@ #ifndef _GPXE_SHA1_H #define _GPXE_SHA1_H +FILE_LICENCE ( GPL2_OR_LATER ); + #include "crypto/axtls/crypto.h" struct digest_algorithm; @@ -10,4 +12,13 @@ struct digest_algorithm; extern struct digest_algorithm sha1_algorithm; +/* SHA1-wrapping functions defined in sha1extra.c: */ + +void prf_sha1 ( const void *key, size_t key_len, const char *label, + const void *data, size_t data_len, void *prf, size_t prf_len ); + +void pbkdf2_sha1 ( const void *passphrase, size_t pass_len, + const void *salt, size_t salt_len, + int iterations, void *key, size_t key_len ); + #endif /* _GPXE_SHA1_H */ diff --git a/gpxe/src/include/gpxe/shell.h b/gpxe/src/include/gpxe/shell.h index c353fc4d..a65a3443 100644 --- a/gpxe/src/include/gpxe/shell.h +++ b/gpxe/src/include/gpxe/shell.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + extern void shell ( void ); #endif /* _GPXE_SHELL_H */ diff --git a/gpxe/src/include/gpxe/shell_banner.h b/gpxe/src/include/gpxe/shell_banner.h index f8e92a4d..28482be8 100644 --- a/gpxe/src/include/gpxe/shell_banner.h +++ b/gpxe/src/include/gpxe/shell_banner.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + extern int shell_banner ( void ); #endif /* _GPXE_SHELL_BANNER_H */ diff --git a/gpxe/src/include/gpxe/smbios.h b/gpxe/src/include/gpxe/smbios.h index 2b0fcbd1..4df25c3e 100644 --- a/gpxe/src/include/gpxe/smbios.h +++ b/gpxe/src/include/gpxe/smbios.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/api.h> #include <config/general.h> @@ -113,6 +115,25 @@ struct smbios_system_information { /** SMBIOS system information structure type */ #define SMBIOS_TYPE_SYSTEM_INFORMATION 1 +/** SMBIOS enclosure information structure */ +struct smbios_enclosure_information { + /** SMBIOS structure header */ + struct smbios_header header; + /** Manufacturer string */ + uint8_t manufacturer; + /** Type string */ + uint8_t type; + /** Version string */ + uint8_t version; + /** Serial number string */ + uint8_t serial; + /** Asset tag */ + uint8_t asset_tag; +} __attribute__ (( packed )); + +/** SMBIOS enclosure information structure type */ +#define SMBIOS_TYPE_ENCLOSURE_INFORMATION 3 + /** * SMBIOS entry point descriptor * diff --git a/gpxe/src/include/gpxe/socket.h b/gpxe/src/include/gpxe/socket.h index b683bed6..9ea0db94 100644 --- a/gpxe/src/include/gpxe/socket.h +++ b/gpxe/src/include/gpxe/socket.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> /** diff --git a/gpxe/src/include/gpxe/spi.h b/gpxe/src/include/gpxe/spi.h index 8f90e3d4..8e4a6763 100644 --- a/gpxe/src/include/gpxe/spi.h +++ b/gpxe/src/include/gpxe/spi.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/nvs.h> /** @@ -102,6 +104,14 @@ struct spi_device { unsigned int munge_address : 1; }; +/** + * SPI magic autodetection address length + * + * Set @c spi_device::address_len to @c SPI_AUTODETECT_ADDRESS_LEN if + * the address length should be autodetected. + */ +#define SPI_AUTODETECT_ADDRESS_LEN 0 + static inline __attribute__ (( always_inline )) struct spi_device * nvs_to_spi ( struct nvs_device *nvs ) { return container_of ( nvs, struct spi_device, nvs ); diff --git a/gpxe/src/include/gpxe/spi_bit.h b/gpxe/src/include/gpxe/spi_bit.h index ced85ceb..8bd25196 100644 --- a/gpxe/src/include/gpxe/spi_bit.h +++ b/gpxe/src/include/gpxe/spi_bit.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/spi.h> #include <gpxe/bitbash.h> diff --git a/gpxe/src/include/gpxe/srp.h b/gpxe/src/include/gpxe/srp.h new file mode 100644 index 00000000..85f39b93 --- /dev/null +++ b/gpxe/src/include/gpxe/srp.h @@ -0,0 +1,868 @@ +#ifndef _GPXE_SRP_H +#define _GPXE_SRP_H + +/** @file + * + * SCSI RDMA Protocol + * + */ + +FILE_LICENCE ( BSD2 ); + +#include <stdint.h> +#include <byteswap.h> +#include <gpxe/iobuf.h> +#include <gpxe/xfer.h> +#include <gpxe/scsi.h> + +/***************************************************************************** + * + * Common fields + * + ***************************************************************************** + */ + +/** An SRP information unit tag */ +struct srp_tag { + uint32_t dwords[2]; +} __attribute__ (( packed )); + +/** An SRP port ID */ +struct srp_port_id { + uint8_t bytes[16]; +} __attribute__ (( packed )); + +/** An SRP port ID pair */ +struct srp_port_ids { + /** Initiator port ID */ + struct srp_port_id initiator; + /** Target port ID */ + struct srp_port_id target; +} __attribute__ (( packed )); + +/** SRP information unit common fields */ +struct srp_common { + /** Information unit type */ + uint8_t type; + /** Reserved */ + uint8_t reserved0[7]; + /** Tag */ + struct srp_tag tag; +} __attribute__ (( packed )); + +/***************************************************************************** + * + * Login request + * + ***************************************************************************** + */ + +/** An SRP login request information unit */ +struct srp_login_req { + /** Information unit type + * + * This must be @c SRP_LOGIN_REQ + */ + uint8_t type; + /** Reserved */ + uint8_t reserved0[7]; + /** Tag */ + struct srp_tag tag; + /** Requested maximum initiator to target IU length */ + uint32_t max_i_t_iu_len; + /** Reserved */ + uint8_t reserved1[4]; + /** Required buffer formats + * + * This is the bitwise OR of one or more @c + * SRP_LOGIN_REQ_FMT_XXX constants. + */ + uint16_t required_buffer_formats; + /** Flags + * + * This is the bitwise OR of zero or more @c + * SRP_LOGIN_REQ_FLAG_XXX and @c SRP_LOGIN_REQ_MCA_XXX + * constants. + */ + uint8_t flags; + /** Reserved */ + uint8_t reserved2[5]; + /** Initiator and target port identifiers */ + struct srp_port_ids port_ids; +} __attribute__ (( packed )); + +/** Type of an SRP login request */ +#define SRP_LOGIN_REQ 0x00 + +/** Require indirect data buffer descriptor format */ +#define SRP_LOGIN_REQ_FMT_IDBD 0x04 + +/** Require direct data buffer descriptor format */ +#define SRP_LOGIN_REQ_FMT_DDBD 0x02 + +/** Use solicited notification for asynchronous events */ +#define SRP_LOGIN_REQ_FLAG_AESOLNT 0x40 + +/** Use solicited notification for credit request */ +#define SRP_LOGIN_REQ_FLAG_CRSOLNT 0x20 + +/** Use solicited notification for logouts */ +#define SRP_LOGIN_REQ_FLAG_LOSOLNT 0x10 + +/** Multi-channel action mask */ +#define SRP_LOGIN_REQ_MCA_MASK 0x03 + +/** Single RDMA channel operation */ +#define SRP_LOGIN_REQ_MCA_SINGLE_CHANNEL 0x00 + +/** Multiple independent RDMA channel operation */ +#define SRP_LOGIN_REQ_MCA_MULTIPLE_CHANNELS 0x01 + +/***************************************************************************** + * + * Login response + * + ***************************************************************************** + */ + +/** An SRP login response */ +struct srp_login_rsp { + /** Information unit type + * + * This must be @c SRP_LOGIN_RSP + */ + uint8_t type; + /** Reserved */ + uint8_t reserved0[3]; + /** Request limit delta */ + uint32_t request_limit_delta; + /** Tag */ + struct srp_tag tag; + /** Maximum initiator to target IU length */ + uint32_t max_i_t_iu_len; + /** Maximum target to initiator IU length */ + uint32_t max_t_i_iu_len; + /** Supported buffer formats + * + * This is the bitwise OR of one or more @c + * SRP_LOGIN_RSP_FMT_XXX constants. + */ + uint16_t supported_buffer_formats; + /** Flags + * + * This is the bitwise OR of zero or more @c + * SRP_LOGIN_RSP_FLAG_XXX and @c SRP_LOGIN_RSP_MCR_XXX + * constants. + */ + uint8_t flags; + /** Reserved */ + uint8_t reserved1[25]; +} __attribute__ (( packed )); + +/** Type of an SRP login response */ +#define SRP_LOGIN_RSP 0xc0 + +/** Indirect data buffer descriptor format supported */ +#define SRP_LOGIN_RSP_FMT_IDBD 0x04 + +/** Direct data buffer descriptor format supported */ +#define SRP_LOGIN_RSP_FMT_DDBD 0x02 + +/** Solicited notification is supported */ +#define SRP_LOGIN_RSP_FLAG_SOLNTSUP 0x10 + +/** Multi-channel result mask */ +#define SRP_LOGIN_RSP_MCR_MASK 0x03 + +/** No existing RDMA channels were associated with the same I_T nexus */ +#define SRP_LOGIN_RSP_MCR_NO_EXISTING_CHANNELS 0x00 + +/** One or more existing RDMA channels were terminated */ +#define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_TERMINATED 0x01 + +/** One or more existing RDMA channels continue to operate independently */ +#define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_CONTINUE 0x02 + +/***************************************************************************** + * + * Login rejection + * + ***************************************************************************** + */ + +/** An SRP login rejection */ +struct srp_login_rej { + /** Information unit type + * + * This must be @c SRP_LOGIN_REJ + */ + uint8_t type; + /** Reserved */ + uint8_t reserved0[3]; + /** Reason + * + * This is a @c SRP_LOGIN_REJ_REASON_XXX constant. + */ + uint32_t reason; + /** Tag */ + struct srp_tag tag; + /** Reserved */ + uint8_t reserved1[8]; + /** Supported buffer formats + * + * This is the bitwise OR of one or more @c + * SRP_LOGIN_REJ_FMT_XXX constants. + */ + uint16_t supported_buffer_formats; + /** Reserved */ + uint8_t reserved2[6]; +} __attribute__ (( packed )); + +/** Type of an SRP login rejection */ +#define SRP_LOGIN_REJ 0xc2 + +/** Unable to establish RDMA channel, no reason specified */ +#define SRP_LOGIN_REJ_REASON_UNKNOWN 0x00010000UL + +/** Insufficient RDMA channel resources */ +#define SRP_LOGIN_REJ_REASON_INSUFFICIENT_RESOURCES 0x00010001UL + +/** Requested maximum initiator to target IU length value too large */ +#define SRP_LOGIN_REJ_REASON_BAD_MAX_I_T_IU_LEN 0x00010002UL + +/** Unable to associate RDMA channel with specified I_T nexus */ +#define SRP_LOGIN_REJ_REASON_CANNOT_ASSOCIATE 0x00010003UL + +/** One or more requested data buffer descriptor formats are not supported */ +#define SRP_LOGIN_REJ_REASON_UNSUPPORTED_BUFFER_FORMAT 0x00010004UL + +/** SRP target port does not support multiple RDMA channels per I_T nexus */ +#define SRP_LOGIN_REJ_REASON_NO_MULTIPLE_CHANNELS 0x00010005UL + +/** RDMA channel limit reached for this initiator */ +#define SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS 0x00010006UL + +/** Indirect data buffer descriptor format supported */ +#define SRP_LOGIN_REJ_FMT_IDBD 0x04 + +/** Direct data buffer descriptor format supported */ +#define SRP_LOGIN_REJ_FMT_DDBD 0x02 + +/***************************************************************************** + * + * Initiator logout + * + ***************************************************************************** + */ + +/** An SRP initiator logout request */ +struct srp_i_logout { + /** Information unit type + * + * This must be @c SRP_I_LOGOUT + */ + uint8_t type; + /** Reserved */ + uint8_t reserved0[7]; + /** Tag */ + struct srp_tag tag; +} __attribute__ (( packed )); + +/** Type of an SRP initiator logout request */ +#define SRP_I_LOGOUT 0x03 + +/***************************************************************************** + * + * Target logout + * + ***************************************************************************** + */ + +/** An SRP target logout request */ +struct srp_t_logout { + /** Information unit type + * + * This must be @c SRP_T_LOGOUT + */ + uint8_t type; + /** Flags + * + * This is the bitwise OR of zero or more @c + * SRP_T_LOGOUT_FLAG_XXX constants. + */ + uint8_t flags; + /** Reserved */ + uint8_t reserved0[2]; + /** Reason + * + * This is a @c SRP_T_LOGOUT_REASON_XXX constant. + */ + uint32_t reason; + /** Tag */ + struct srp_tag tag; +} __attribute__ (( packed )); + +/** Type of an SRP target logout request */ +#define SRP_T_LOGOUT 0x80 + +/** The initiator specified solicited notification of logouts */ +#define SRP_T_LOGOUT_FLAG_SOLNT 0x01 + +/** No reason specified */ +#define SRP_T_LOGOUT_REASON_UNKNOWN 0x00000000UL + +/** Inactive RDMA channel (reclaiming resources) */ +#define SRP_T_LOGOUT_REASON_INACTIVE 0x00000001UL + +/** Invalid information unit type code received by SRP target port */ +#define SRP_T_LOGOUT_REASON_INVALID_TYPE 0x00000002UL + +/** SRP initiator port sent response with no corresponding request */ +#define SRP_T_LOGOUT_REASON_SPURIOUS_RESPONSE 0x00000003UL + +/** RDMA channel disconnected due to multi-channel action code in new login */ +#define SRP_T_LOGOUT_REASON_MCA 0x00000004UL + +/** Unsuppported format code value specified in data-out buffer descriptor */ +#define SRP_T_LOGOUT_UNSUPPORTED_DATA_OUT_FORMAT 0x00000005UL + +/** Unsuppported format code value specified in data-in buffer descriptor */ +#define SRP_T_LOGOUT_UNSUPPORTED_DATA_IN_FORMAT 0x00000006UL + +/** Invalid length for IU type */ +#define SRP_T_LOGOUT_INVALID_IU_LEN 0x00000008UL + +/***************************************************************************** + * + * Task management + * + ***************************************************************************** + */ + +/** An SRP task management request */ +struct srp_tsk_mgmt { + /** Information unit type + * + * This must be @c SRP_TSK_MGMT + */ + uint8_t type; + /** Flags + * + * This is the bitwise OR of zero or more + * @c SRP_TSK_MGMT_FLAG_XXX constants. + */ + uint8_t flags; + /** Reserved */ + uint8_t reserved0[6]; + /** Tag */ + struct srp_tag tag; + /** Reserved */ + uint8_t reserved1[4]; + /** Logical unit number */ + struct scsi_lun lun; + /** Reserved */ + uint8_t reserved2[2]; + /** Task management function + * + * This is a @c SRP_TASK_MGMT_FUNC_XXX constant + */ + uint8_t function; + /** Reserved */ + uint8_t reserved3[1]; + /** Tag of task to be managed */ + struct srp_tag managed_tag; + /** Reserved */ + uint8_t reserved4[8]; +} __attribute__ (( packed )); + +/** Type of an SRP task management request */ +#define SRP_TSK_MGMT 0x01 + +/** Use solicited notification for unsuccessful completions */ +#define SRP_TSK_MGMT_FLAG_UCSOLNT 0x04 + +/** Use solicited notification for successful completions */ +#define SRP_TSK_MGMT_FLAG_SCSOLNT 0x02 + +/** The task manager shall perform an ABORT TASK function */ +#define SRP_TSK_MGMT_FUNC_ABORT_TASK 0x01 + +/** The task manager shall perform an ABORT TASK SET function */ +#define SRP_TSK_MGMT_FUNC_ABORT_TASK_SET 0x02 + +/** The task manager shall perform a CLEAR TASK SET function */ +#define SRP_TSK_MGMT_FUNC_CLEAR_TASK_SET 0x04 + +/** The task manager shall perform a LOGICAL UNIT RESET function */ +#define SRP_TSK_MGMT_FUNC_LOGICAL_UNIT_RESET 0x08 + +/** The task manager shall perform a CLEAR ACA function */ +#define SRP_TSK_MGMT_FUNC_CLEAR_ACA 0x40 + +/***************************************************************************** + * + * SCSI command + * + ***************************************************************************** + */ + +/** An SRP SCSI command */ +struct srp_cmd { + /** Information unit type + * + * This must be @c SRP_CMD + */ + uint8_t type; + /** Flags + * + * This is the bitwise OR of zero or more @c SRP_CMD_FLAG_XXX + * constants. + */ + uint8_t flags; + /** Reserved */ + uint8_t reserved0[3]; + /** Data buffer descriptor formats + * + * This is the bitwise OR of one @c SRP_CMD_DO_FMT_XXX and one @c + * SRP_CMD_DI_FMT_XXX constant. + */ + uint8_t data_buffer_formats; + /** Data-out buffer descriptor count */ + uint8_t data_out_buffer_count; + /** Data-in buffer descriptor count */ + uint8_t data_in_buffer_count; + /** Tag */ + struct srp_tag tag; + /** Reserved */ + uint8_t reserved1[4]; + /** Logical unit number */ + struct scsi_lun lun; + /** Reserved */ + uint8_t reserved2[1]; + /** Task attribute + * + * This is a @c SRP_CMD_TASK_ATTR_XXX constant. + */ + uint8_t task_attr; + /** Reserved */ + uint8_t reserved3[1]; + /** Additional CDB length */ + uint8_t additional_cdb_len; + /** Command data block */ + union scsi_cdb cdb; +} __attribute__ (( packed )); + +/** Type of an SRP SCSI command */ +#define SRP_CMD 0x02 + +/** Use solicited notification for unsuccessful completions */ +#define SRP_CMD_FLAG_UCSOLNT 0x04 + +/** Use solicited notification for successful completions */ +#define SRP_CMD_FLAG_SCSOLNT 0x02 + +/** Data-out buffer format mask */ +#define SRP_CMD_DO_FMT_MASK 0xf0 + +/** Direct data-out buffer format */ +#define SRP_CMD_DO_FMT_DIRECT 0x10 + +/** Indirect data-out buffer format */ +#define SRP_CMD_DO_FMT_INDIRECT 0x20 + +/** Data-in buffer format mask */ +#define SRP_CMD_DI_FMT_MASK 0x0f + +/** Direct data-in buffer format */ +#define SRP_CMD_DI_FMT_DIRECT 0x01 + +/** Indirect data-in buffer format */ +#define SRP_CMD_DI_FMT_INDIRECT 0x02 + +/** Use the rules for a simple task attribute */ +#define SRP_CMD_TASK_ATTR_SIMPLE 0x00 + +/** Use the rules for a head of queue task attribute */ +#define SRP_CMD_TASK_ATTR_QUEUE_HEAD 0x01 + +/** Use the rules for an ordered task attribute */ +#define SRP_CMD_TASK_ATTR_ORDERED 0x02 + +/** Use the rules for an automatic contingent allegiance task attribute */ +#define SRP_CMD_TASK_ATTR_AUTOMATIC_CONTINGENT_ALLEGIANCE 0x08 + +/** An SRP memory descriptor */ +struct srp_memory_descriptor { + /** Virtual address */ + uint64_t address; + /** Memory handle */ + uint32_t handle; + /** Data length */ + uint32_t len; +} __attribute__ (( packed )); + +/***************************************************************************** + * + * SCSI response + * + ***************************************************************************** + */ + +/** An SRP SCSI response */ +struct srp_rsp { + /** Information unit type + * + * This must be @c SRP_RSP + */ + uint8_t type; + /** Flags + * + * This is the bitwise OR of zero or more @c SRP_RSP_FLAG_XXX + * constants. + */ + uint8_t flags; + /** Reserved */ + uint8_t reserved0[2]; + /** Request limit delta */ + uint32_t request_limit_delta; + /** Tag */ + struct srp_tag tag; + /** Reserved */ + uint8_t reserved1[2]; + /** Valid fields + * + * This is the bitwise OR of zero or more @c SRP_RSP_VALID_XXX + * constants. + */ + uint8_t valid; + /** Status + * + * This is the SCSI status code. + */ + uint8_t status; + /** Data-out residual count */ + uint32_t data_out_residual_count; + /** Data-in residual count */ + uint32_t data_in_residual_count; + /** Sense data list length */ + uint32_t sense_data_len; + /** Response data list length */ + uint32_t response_data_len; +} __attribute__ (( packed )); + +/** Type of an SRP SCSI response */ +#define SRP_RSP 0xc1 + +/** The initiator specified solicited notification of this response */ +#define SRP_RSP_FLAG_SOLNT 0x01 + +/** Data-in residual count field is valid and represents an underflow */ +#define SRP_RSP_VALID_DIUNDER 0x20 + +/** Data-in residual count field is valid and represents an overflow */ +#define SRP_RSP_VALID_DIOVER 0x10 + +/** Data-out residual count field is valid and represents an underflow */ +#define SRP_RSP_VALID_DOUNDER 0x08 + +/** Data-out residual count field is valid and represents an overflow */ +#define SRP_RSP_VALID_DOOVER 0x04 + +/** Sense data list length field is valid */ +#define SRP_RSP_VALID_SNSVALID 0x02 + +/** Response data list length field is valid */ +#define SRP_RSP_VALID_RSPVALID 0x01 + +/** + * Get response data portion of SCSI response + * + * @v rsp SCSI response + * @ret response_data Response data, or NULL if not present + */ +static inline void * srp_rsp_response_data ( struct srp_rsp *rsp ) { + return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ? + ( ( ( void * ) rsp ) + sizeof ( *rsp ) ) : NULL ); +} + +/** + * Get length of response data portion of SCSI response + * + * @v rsp SCSI response + * @ret response_data_len Response data length + */ +static inline size_t srp_rsp_response_data_len ( struct srp_rsp *rsp ) { + return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ? + ntohl ( rsp->response_data_len ) : 0 ); +} + +/** + * Get sense data portion of SCSI response + * + * @v rsp SCSI response + * @ret sense_data Sense data, or NULL if not present + */ +static inline void * srp_rsp_sense_data ( struct srp_rsp *rsp ) { + return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ? + ( ( ( void * ) rsp ) + sizeof ( *rsp ) + + srp_rsp_response_data_len ( rsp ) ) : NULL ); +} + +/** + * Get length of sense data portion of SCSI response + * + * @v rsp SCSI response + * @ret sense_data_len Sense data length + */ +static inline size_t srp_rsp_sense_data_len ( struct srp_rsp *rsp ) { + return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ? + ntohl ( rsp->sense_data_len ) : 0 ); +} + +/***************************************************************************** + * + * Credit request + * + ***************************************************************************** + */ + +/** An SRP credit request */ +struct srp_cred_req { + /** Information unit type + * + * This must be @c SRP_CRED_REQ + */ + uint8_t type; + /** Flags + * + * This is the bitwise OR of zero or more + * @c SRP_CRED_REQ_FLAG_XXX constants. + */ + uint8_t flags; + /** Reserved */ + uint8_t reserved0[2]; + /** Request limit delta */ + uint32_t request_limit_delta; + /** Tag */ + struct srp_tag tag; +} __attribute__ (( packed )); + +/** Type of an SRP credit request */ +#define SRP_CRED_REQ 0x81 + +/** The initiator specified solicited notification of credit requests */ +#define SRP_CRED_REQ_FLAG_SOLNT 0x01 + +/***************************************************************************** + * + * Credit response + * + ***************************************************************************** + */ + +/** An SRP credit response */ +struct srp_cred_rsp { + /** Information unit type + * + * This must be @c SRP_CRED_RSP + */ + uint8_t type; + /** Reserved */ + uint8_t reserved0[7]; + /** Tag */ + struct srp_tag tag; +} __attribute__ (( packed )); + +/** Type of an SRP credit response */ +#define SRP_CRED_RSP 0x41 + +/***************************************************************************** + * + * Asynchronous event request + * + ***************************************************************************** + */ + +/** An SRP asynchronous event request */ +struct srp_aer_req { + /** Information unit type + * + * This must be @c SRP_AER_REQ + */ + uint8_t type; + /** Flags + * + * This is the bitwise OR of zero or more @c + * SRP_AER_REQ_FLAG_XXX constants. + */ + uint8_t flags; + /** Reserved */ + uint8_t reserved0[2]; + /** Request limit delta */ + uint32_t request_limit_delta; + /** Tag */ + struct srp_tag tag; + /** Reserved */ + uint8_t reserved1[4]; + /** Logical unit number */ + struct scsi_lun lun; + /** Sense data list length */ + uint32_t sense_data_len; + /** Reserved */ + uint8_t reserved2[4]; +} __attribute__ (( packed )); + +/** Type of an SRP asynchronous event request */ +#define SRP_AER_REQ 0x82 + +/** The initiator specified solicited notification of asynchronous events */ +#define SRP_AER_REQ_FLAG_SOLNT 0x01 + +/** + * Get sense data portion of asynchronous event request + * + * @v aer_req SRP asynchronous event request + * @ret sense_data Sense data + */ +static inline __always_inline void * +srp_aer_req_sense_data ( struct srp_aer_req *aer_req ) { + return ( ( ( void * ) aer_req ) + sizeof ( *aer_req ) ); +} + +/** + * Get length of sense data portion of asynchronous event request + * + * @v aer_req SRP asynchronous event request + * @ret sense_data_len Sense data length + */ +static inline __always_inline size_t +srp_aer_req_sense_data_len ( struct srp_aer_req *aer_req ) { + return ( ntohl ( aer_req->sense_data_len ) ); +} + +/***************************************************************************** + * + * Asynchronous event response + * + ***************************************************************************** + */ + +/** An SRP asynchronous event response */ +struct srp_aer_rsp { + /** Information unit type + * + * This must be @c SRP_AER_RSP + */ + uint8_t type; + /** Reserved */ + uint8_t reserved0[7]; + /** Tag */ + struct srp_tag tag; +} __attribute__ (( packed )); + +/** Type of an SRP asynchronous event response */ +#define SRP_AER_RSP 0x42 + +/***************************************************************************** + * + * Information units + * + ***************************************************************************** + */ + +/** Maximum length of any initiator-to-target IU that we will send + * + * The longest IU is a SRP_CMD with no additional CDB and two direct + * data buffer descriptors, which comes to 80 bytes. + */ +#define SRP_MAX_I_T_IU_LEN 80 + +/***************************************************************************** + * + * SRP device + * + ***************************************************************************** + */ + +struct srp_device; + +/** An SRP transport type */ +struct srp_transport_type { + /** Length of transport private data */ + size_t priv_len; + /** Parse root path + * + * @v srp SRP device + * @v root_path Root path + * @ret Return status code + */ + int ( * parse_root_path ) ( struct srp_device *srp, + const char *root_path ); + /** Connect SRP session + * + * @v srp SRP device + * @ret rc Return status code + * + * This method should open the underlying socket. + */ + int ( * connect ) ( struct srp_device *srp ); +}; + +/** An SRP device */ +struct srp_device { + /** Reference count */ + struct refcnt refcnt; + + /** Initiator and target port IDs */ + struct srp_port_ids port_ids; + /** Logical unit number */ + struct scsi_lun lun; + /** Memory handle */ + uint32_t memory_handle; + + /** Current state + * + * This is the bitwise-OR of zero or more @c SRP_STATE_XXX + * flags. + */ + unsigned int state; + /** Retry counter */ + unsigned int retry_count; + /** Current SCSI command */ + struct scsi_command *command; + + /** Underlying data transfer interface */ + struct xfer_interface socket; + + /** Transport type */ + struct srp_transport_type *transport; + /** Transport private data */ + char transport_priv[0]; +}; + +/** + * Get SRP transport private data + * + * @v srp SRP device + * @ret priv SRP transport private data + */ +static inline __always_inline void * +srp_transport_priv ( struct srp_device *srp ) { + return ( ( void * ) srp->transport_priv ); +} + +/** SRP state flags */ +enum srp_state { + /** Underlying socket is open */ + SRP_STATE_SOCKET_OPEN = 0x0001, + /** Session is logged in */ + SRP_STATE_LOGGED_IN = 0x0002, +}; + +/** Maximum number of SRP retry attempts */ +#define SRP_MAX_RETRIES 3 + +extern int srp_attach ( struct scsi_device *scsi, const char *root_path ); +extern void srp_detach ( struct scsi_device *scsi ); + +#endif /* _GPXE_SRP_H */ diff --git a/gpxe/src/include/gpxe/tables.h b/gpxe/src/include/gpxe/tables.h index b2c56ab6..7dfced8c 100644 --- a/gpxe/src/include/gpxe/tables.h +++ b/gpxe/src/include/gpxe/tables.h @@ -1,6 +1,8 @@ #ifndef _GPXE_TABLES_H #define _GPXE_TABLES_H +FILE_LICENCE ( GPL2_OR_LATER ); + /** @page ifdef_harmful #ifdef considered harmful * * Overuse of @c #ifdef has long been a problem in Etherboot. @@ -98,7 +100,7 @@ * The linker script takes care of assembling the tables for us. All * our table sections have names of the format @c .tbl.NAME.NN where * @c NAME designates the data structure stored in the table (e.g. @c - * init_fn) and @c NN is a two-digit decimal number used to impose an + * init_fns) and @c NN is a two-digit decimal number used to impose an * ordering upon the tables if required. @c NN=00 is reserved for the * symbol indicating "table start", and @c NN=99 is reserved for the * symbol indicating "table end". @@ -115,7 +117,9 @@ * void ( *frob ) ( void ); // The frobnicating function itself * }; * - * #define __frobnicator __table ( frobnicators, 01 ) + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * #define __frobnicator __table_entry ( FROBNICATORS, 01 ) * * @endcode * @@ -145,14 +149,11 @@ * * #include "frob.h" * - * static struct frob frob_start[0] __table_start ( frobnicators ); - * static struct frob frob_end[0] __table_end ( frobnicators ); - * * // Call all linked-in frobnicators * void frob_all ( void ) { * struct frob *frob; * - * for ( frob = frob_start ; frob < frob_end ; frob++ ) { + * for_each_table ( frob, FROBNICATORS ) { * printf ( "Calling frobnicator \"%s\"\n", frob->name ); * frob->frob (); * } @@ -168,62 +169,266 @@ #define __attribute__( x ) #endif -#define __table_str( x ) #x -#define __table_section( table, idx ) \ - __section__ ( ".tbl." __table_str ( table ) "." __table_str ( idx ) ) +/** + * Declare a linker table + * + * @v type Data type + * @v name Table name + * @ret table Linker table + */ +#define __table( type, name ) ( type, name ) -#define __table_section_start( table ) __table_section ( table, 00 ) -#define __table_section_end( table ) __table_section ( table, 99 ) +/** + * Get linker table data type + * + * @v table Linker table + * @ret type Data type + */ +#define __table_type( table ) __table_extract_type table +#define __table_extract_type( type, name ) type -#define __natural_alignment( type ) __aligned__ ( __alignof__ ( type ) ) +/** + * Get linker table name + * + * @v table Linker table + * @ret name Table name + */ +#define __table_name( table ) __table_extract_name table +#define __table_extract_name( type, name ) name /** - * Linker table entry. + * Get linker table section name * - * Declares a data structure to be part of a linker table. Use as - * e.g. + * @v table Linker table + * @v idx Sub-table index + * @ret section Section name + */ +#define __table_section( table, idx ) \ + ".tbl." __table_name ( table ) "." __table_str ( idx ) +#define __table_str( x ) #x + +/** + * Get linker table alignment + * + * @v table Linker table + * @ret align Alignment + */ +#define __table_alignment( table ) __alignof__ ( __table_type ( table ) ) + +/** + * Declare a linker table entry + * + * @v table Linker table + * @v idx Sub-table index + * + * Example usage: * * @code * - * struct my_foo __table ( foo, 01 ) = { + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * #define __frobnicator __table_entry ( FROBNICATORS, 01 ) + * + * struct frobnicator my_frob __frobnicator = { * ... * }; * * @endcode + */ +#define __table_entry( table, idx ) \ + __attribute__ (( __section__ ( __table_section ( table, idx ) ),\ + __aligned__ ( __table_alignment ( table ) ) )) + +/** + * Get start of linker table entries + * + * @v table Linker table + * @v idx Sub-table index + * @ret entries Start of entries + */ +#define __table_entries( table, idx ) ( { \ + static __table_type ( table ) __table_entries[0] \ + __table_entry ( table, idx ); \ + __table_entries; } ) + +/** + * Get start of linker table + * + * @v table Linker table + * @ret start Start of linker table + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * struct frobnicator *frobs = table_start ( FROBNICATORS ); + * + * @endcode + */ +#define table_start( table ) __table_entries ( table, 00 ) + +/** + * Get end of linker table + * + * @v table Linker table + * @ret end End of linker table + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * struct frobnicator *frobs_end = table_end ( FROBNICATORS ); + * + * @endcode + */ +#define table_end( table ) __table_entries ( table, 99 ) + +/** + * Get number of entries in linker table + * + * @v table Linker table + * @ret num_entries Number of entries in linker table + * + * Example usage: + * + * @code + * + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * unsigned int num_frobs = table_num_entries ( FROBNICATORS ); + * + * @endcode * */ -#define __table( type, table, idx ) \ - __attribute__ (( __table_section ( table, idx ), \ - __natural_alignment ( type ) )) +#define table_num_entries( table ) \ + ( ( unsigned int ) ( table_end ( table ) - \ + table_start ( table ) ) ) /** - * Linker table start marker. + * Iterate through all entries within a linker table + * + * @v pointer Entry pointer + * @v table Linker table * - * Declares a data structure (usually an empty data structure) to be - * the start of a linker table. Use as e.g. + * Example usage: * * @code * - * static struct foo_start[0] __table_start ( foo ); + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * struct frobnicator *frob; + * + * for_each_table_entry ( frob, FROBNICATORS ) { + * ... + * } * * @endcode * */ -#define __table_start( type, table ) __table ( type, table, 00 ) +#define for_each_table_entry( pointer, table ) \ + for ( pointer = table_start ( table ) ; \ + pointer < table_end ( table ) ; \ + pointer++ ) /** - * Linker table end marker. + * Iterate through all entries within a linker table in reverse order * - * Declares a data structure (usually an empty data structure) to be - * the end of a linker table. Use as e.g. + * @v pointer Entry pointer + * @v table Linker table + * + * Example usage: * * @code * - * static struct foo_end[0] __table_end ( foo ); + * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" ) + * + * struct frobnicator *frob; + * + * for_each_table_entry_reverse ( frob, FROBNICATORS ) { + * ... + * } * * @endcode * */ -#define __table_end( type, table ) __table ( type, table, 99 ) +#define for_each_table_entry_reverse( pointer, table ) \ + for ( pointer = ( table_end ( table ) - 1 ) ; \ + pointer >= table_start ( table ) ; \ + pointer-- ) + +/****************************************************************************** + * + * Intel's C compiler chokes on several of the constructs used in this + * file. The workarounds are ugly, so we use them only for an icc + * build. + * + */ +#define ICC_ALIGN_HACK_FACTOR 128 +#ifdef __ICC + +/* + * icc miscompiles zero-length arrays by inserting padding to a length + * of two array elements. We therefore have to generate the + * __table_entries() symbols by hand in asm. + * + */ +#undef __table_entries +#define __table_entries( table, idx ) ( { \ + extern __table_type ( table ) \ + __table_temp_sym ( idx, __LINE__ ) [] \ + __table_entry ( table, idx ) \ + asm ( __table_entries_sym ( table, idx ) ); \ + __asm__ ( ".ifndef %c0\n\t" \ + ".section " __table_section ( table, idx ) "\n\t" \ + ".align %c1\n\t" \ + "\n%c0:\n\t" \ + ".previous\n\t" \ + ".endif\n\t" \ + : : "i" ( __table_temp_sym ( idx, __LINE__ ) ), \ + "i" ( __table_alignment ( table ) ) ); \ + __table_temp_sym ( idx, __LINE__ ); } ) +#define __table_entries_sym( table, idx ) \ + "__tbl_" __table_name ( table ) "_" #idx +#define __table_temp_sym( a, b ) \ + ___table_temp_sym( __table_, a, _, b ) +#define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d + +/* + * icc ignores __attribute__ (( aligned (x) )) when it is used to + * decrease the compiler's default choice of alignment (which may be + * higher than the alignment actually required by the structure). We + * work around this by forcing the alignment to a large multiple of + * the required value (so that we are never attempting to decrease the + * default alignment) and then postprocessing the object file to + * reduce the alignment back down to the "real" value. + * + */ +#undef __table_alignment +#define __table_alignment( table ) \ + ( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) ) + +/* + * Because of the alignment hack, we must ensure that the compiler + * never tries to place multiple objects within the same section, + * otherwise the assembler will insert padding to the (incorrect) + * alignment boundary. Do this by appending the line number to table + * section names. + * + * Note that we don't need to worry about padding between array + * elements, since the alignment is declared on the variable (i.e. the + * whole array) rather than on the type (i.e. on all individual array + * elements). + */ +#undef __table_section +#define __table_section( table, idx ) \ + ".tbl." __table_name ( table ) "." __table_str ( idx ) \ + "." __table_xstr ( __LINE__ ) +#define __table_xstr( x ) __table_str ( x ) + +#endif /* __ICC */ #endif /* _GPXE_TABLES_H */ diff --git a/gpxe/src/include/gpxe/tcp.h b/gpxe/src/include/gpxe/tcp.h index 264ec29b..7ae7eab9 100644 --- a/gpxe/src/include/gpxe/tcp.h +++ b/gpxe/src/include/gpxe/tcp.h @@ -9,6 +9,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/tcpip.h> /** @@ -227,6 +229,16 @@ struct tcp_options { TCP_STATE_SENT ( TCP_FIN ) ) ) \ == TCP_STATE_ACKED ( TCP_SYN ) ) +/** Have ever been fully established + * + * We have been fully established if we have both received a SYN and + * had our own SYN acked. + */ +#define TCP_HAS_BEEN_ESTABLISHED(state) \ + ( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN ) | \ + TCP_STATE_RCVD ( TCP_SYN ) ) ) \ + == ( TCP_STATE_ACKED ( TCP_SYN ) | TCP_STATE_RCVD ( TCP_SYN ) ) ) + /** Have closed gracefully * * We have closed gracefully if we have both received a FIN and had diff --git a/gpxe/src/include/gpxe/tcpip.h b/gpxe/src/include/gpxe/tcpip.h index da89530e..f71d7d6d 100644 --- a/gpxe/src/include/gpxe/tcpip.h +++ b/gpxe/src/include/gpxe/tcpip.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/socket.h> #include <gpxe/in.h> @@ -98,13 +100,18 @@ struct tcpip_net_protocol { uint16_t *trans_csum ); }; +/** TCP/IP transport-layer protocol table */ +#define TCPIP_PROTOCOLS __table ( struct tcpip_protocol, "tcpip_protocols" ) + /** Declare a TCP/IP transport-layer protocol */ -#define __tcpip_protocol \ - __table ( struct tcpip_protocol, tcpip_protocols, 01 ) +#define __tcpip_protocol __table_entry ( TCPIP_PROTOCOLS, 01 ) + +/** TCP/IP network-layer protocol table */ +#define TCPIP_NET_PROTOCOLS \ + __table ( struct tcpip_net_protocol, "tcpip_net_protocols" ) /** Declare a TCP/IP network-layer protocol */ -#define __tcpip_net_protocol \ - __table ( struct tcpip_net_protocol, tcpip_net_protocols, 01 ) +#define __tcpip_net_protocol __table_entry ( TCPIP_NET_PROTOCOLS, 01 ) extern int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto, struct sockaddr_tcpip *st_src, diff --git a/gpxe/src/include/gpxe/tftp.h b/gpxe/src/include/gpxe/tftp.h index 0177a95a..c57bb254 100644 --- a/gpxe/src/include/gpxe/tftp.h +++ b/gpxe/src/include/gpxe/tftp.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #define TFTP_PORT 69 /**< Default TFTP server port */ diff --git a/gpxe/src/include/gpxe/threewire.h b/gpxe/src/include/gpxe/threewire.h index 865fc25d..e23284af 100644 --- a/gpxe/src/include/gpxe/threewire.h +++ b/gpxe/src/include/gpxe/threewire.h @@ -10,6 +10,8 @@ * support. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/spi.h> #include <limits.h> @@ -43,6 +45,7 @@ extern int threewire_read ( struct nvs_device *nvs, unsigned int address, void *data, size_t len ); extern int threewire_write ( struct nvs_device *nvs, unsigned int address, const void *data, size_t len ); +extern int threewire_detect_address_len ( struct spi_device *device ); /** * @defgroup tdevs Three-wire device types @@ -84,6 +87,19 @@ init_at93c56 ( struct spi_device *device, unsigned int organisation ) { init_at93cx6 ( device, organisation ); } +/** + * Initialise Atmel AT93C66 serial EEPROM + * + * @v device SPI device + * @v organisation Word organisation (8 or 16) + */ +static inline __attribute__ (( always_inline )) void +init_at93c66 ( struct spi_device *device, unsigned int organisation ) { + device->nvs.size = ( 4096 / organisation ); + device->address_len = ( ( organisation == 8 ) ? 9 : 8 ); + init_at93cx6 ( device, organisation ); +} + /** @} */ #endif /* _GPXE_THREEWIRE_H */ diff --git a/gpxe/src/include/gpxe/timer.h b/gpxe/src/include/gpxe/timer.h index 862d87b3..86722dca 100644 --- a/gpxe/src/include/gpxe/timer.h +++ b/gpxe/src/include/gpxe/timer.h @@ -9,6 +9,8 @@ * for a monotonically increasing tick counter. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/api.h> #include <config/timer.h> diff --git a/gpxe/src/include/gpxe/tls.h b/gpxe/src/include/gpxe/tls.h index ddec7bec..e2da0462 100644 --- a/gpxe/src/include/gpxe/tls.h +++ b/gpxe/src/include/gpxe/tls.h @@ -7,6 +7,8 @@ * Transport Layer Security Protocol */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <gpxe/refcnt.h> #include <gpxe/filter.h> diff --git a/gpxe/src/include/gpxe/uaccess.h b/gpxe/src/include/gpxe/uaccess.h index 33aaed18..5a8f2921 100644 --- a/gpxe/src/include/gpxe/uaccess.h +++ b/gpxe/src/include/gpxe/uaccess.h @@ -19,6 +19,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <string.h> #include <gpxe/api.h> diff --git a/gpxe/src/include/gpxe/udp.h b/gpxe/src/include/gpxe/udp.h index e515f650..670c5e5a 100644 --- a/gpxe/src/include/gpxe/udp.h +++ b/gpxe/src/include/gpxe/udp.h @@ -9,6 +9,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stddef.h> #include <gpxe/iobuf.h> #include <gpxe/tcpip.h> diff --git a/gpxe/src/include/gpxe/umalloc.h b/gpxe/src/include/gpxe/umalloc.h index e6fc7bf0..b0e55645 100644 --- a/gpxe/src/include/gpxe/umalloc.h +++ b/gpxe/src/include/gpxe/umalloc.h @@ -8,6 +8,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <gpxe/api.h> #include <config/umalloc.h> #include <gpxe/uaccess.h> diff --git a/gpxe/src/include/gpxe/uri.h b/gpxe/src/include/gpxe/uri.h index 3803868d..405d0ce9 100644 --- a/gpxe/src/include/gpxe/uri.h +++ b/gpxe/src/include/gpxe/uri.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stddef.h> #include <stdlib.h> #include <gpxe/refcnt.h> @@ -18,6 +20,10 @@ * * Note that all fields within a URI are optional and may be NULL. * + * The pointers to the various fields are packed together so they can + * be accessed in array fashion in some places in uri.c where doing so + * saves significant code size. + * * Some examples are probably helpful: * * http://www.etherboot.org/wiki : @@ -59,8 +65,40 @@ struct uri { const char *query; /** Fragment */ const char *fragment; +} __attribute__ (( packed )); + +/** A field in a URI + * + * The order of the indices in this enumeration must match the order + * of the fields in the URI structure. + */ +enum { + URI_SCHEME = 0, URI_SCHEME_BIT = ( 1 << URI_SCHEME ), + URI_OPAQUE = 1, URI_OPAQUE_BIT = ( 1 << URI_OPAQUE ), + URI_USER = 2, URI_USER_BIT = ( 1 << URI_USER ), + URI_PASSWORD = 3, URI_PASSWORD_BIT = ( 1 << URI_PASSWORD ), + URI_HOST = 4, URI_HOST_BIT = ( 1 << URI_HOST ), + URI_PORT = 5, URI_PORT_BIT = ( 1 << URI_PORT ), + URI_PATH = 6, URI_PATH_BIT = ( 1 << URI_PATH ), + URI_QUERY = 7, URI_QUERY_BIT = ( 1 << URI_QUERY ), + URI_FRAGMENT = 8, URI_FRAGMENT_BIT = ( 1 << URI_FRAGMENT ), + + URI_FIRST_FIELD = URI_SCHEME, + URI_LAST_FIELD = URI_FRAGMENT, }; +/** Extract field from URI */ +#define uri_get_field( uri, field ) (&uri->scheme)[field] + +/** All URI fields */ +#define URI_ALL ( URI_SCHEME_BIT | URI_OPAQUE_BIT | URI_USER_BIT | \ + URI_PASSWORD_BIT | URI_HOST_BIT | URI_PORT_BIT | \ + URI_PATH_BIT | URI_QUERY_BIT | URI_FRAGMENT_BIT ) + +/** URI fields that should be decoded on storage */ +#define URI_ENCODED ( URI_USER_BIT | URI_PASSWORD_BIT | URI_HOST_BIT | \ + URI_PATH_BIT | URI_QUERY_BIT | URI_FRAGMENT_BIT ) + /** * URI is an absolute URI * @@ -129,14 +167,16 @@ extern struct uri *cwuri; extern struct uri * parse_uri ( const char *uri_string ); extern unsigned int uri_port ( struct uri *uri, unsigned int default_port ); -extern int unparse_uri ( char *buf, size_t size, struct uri *uri ); +extern int unparse_uri ( char *buf, size_t size, struct uri *uri, + unsigned int fields ); extern struct uri * uri_dup ( struct uri *uri ); extern char * resolve_path ( const char *base_path, const char *relative_path ); extern struct uri * resolve_uri ( struct uri *base_uri, struct uri *relative_uri ); extern void churi ( struct uri *uri ); -extern size_t uri_encode ( const char *raw_string, char *buf, size_t len ); -extern size_t uri_decode ( const char *encoded_string, char *buf, size_t len ); +extern size_t uri_encode ( const char *raw_string, char *buf, ssize_t len, + int field ); +extern size_t uri_decode ( const char *encoded_string, char *buf, ssize_t len ); #endif /* _GPXE_URI_H */ diff --git a/gpxe/src/include/gpxe/uuid.h b/gpxe/src/include/gpxe/uuid.h index 18d1f141..019cd052 100644 --- a/gpxe/src/include/gpxe/uuid.h +++ b/gpxe/src/include/gpxe/uuid.h @@ -6,6 +6,8 @@ * Universally unique IDs */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> /** A universally unique ID */ diff --git a/gpxe/src/include/gpxe/vsprintf.h b/gpxe/src/include/gpxe/vsprintf.h index aa8f8a33..ee860a52 100644 --- a/gpxe/src/include/gpxe/vsprintf.h +++ b/gpxe/src/include/gpxe/vsprintf.h @@ -31,6 +31,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <stdarg.h> #include <stdio.h> diff --git a/gpxe/src/include/gpxe/wpa.h b/gpxe/src/include/gpxe/wpa.h new file mode 100644 index 00000000..a7f19d71 --- /dev/null +++ b/gpxe/src/include/gpxe/wpa.h @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPXE_WPA_H +#define _GPXE_WPA_H + +#include <gpxe/ieee80211.h> +#include <gpxe/list.h> + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Common definitions for all types of WPA-protected networks. + */ + + +/** EAPOL-Key type field for modern 802.11i/RSN WPA packets */ +#define EAPOL_KEY_TYPE_RSN 2 + +/** Old EAPOL-Key type field used by WPA1 hardware before 802.11i ratified */ +#define EAPOL_KEY_TYPE_WPA 254 + + +/** + * @defgroup eapol_key_info EAPOL-Key Info field bits + * @{ + */ + +/** Key descriptor version, indicating WPA or WPA2 */ +#define EAPOL_KEY_INFO_VERSION 0x0007 + +/** Key type bit, indicating pairwise or group */ +#define EAPOL_KEY_INFO_TYPE 0x0008 + +/** Key install bit; set on message 3 except when legacy hacks are used */ +#define EAPOL_KEY_INFO_INSTALL 0x0040 + +/** Key ACK bit; set when a response is required, on all messages except #4 */ +#define EAPOL_KEY_INFO_KEY_ACK 0x0080 + +/** Key MIC bit; set when the MIC field is valid, on messages 3 and 4 */ +#define EAPOL_KEY_INFO_KEY_MIC 0x0100 + +/** Secure bit; set when both sides have both keys, on messages 3 and 4 */ +#define EAPOL_KEY_INFO_SECURE 0x0200 + +/** Error bit; set on a MIC failure for TKIP */ +#define EAPOL_KEY_INFO_ERROR 0x0400 + +/** Request bit; set when authentication is initiated by the Peer (unusual) */ +#define EAPOL_KEY_INFO_REQUEST 0x0800 + +/** Key Encrypted bit; set when the Key Data field is encrypted */ +#define EAPOL_KEY_INFO_KEY_ENC 0x1000 + +/** SMC Message bit; set when this frame is part of an IBSS SMK handshake */ +#define EAPOL_KEY_INFO_SMC_MESS 0x2000 + + +/** Key descriptor version field value for WPA (TKIP) */ +#define EAPOL_KEY_VERSION_WPA 1 + +/** Key descriptor version field value for WPA2 (CCMP) */ +#define EAPOL_KEY_VERSION_WPA2 2 + +/** Key type field value for a PTK (pairwise) key handshake */ +#define EAPOL_KEY_TYPE_PTK 0x0008 + +/** Key type field value for a GTK (group) key handshake */ +#define EAPOL_KEY_TYPE_GTK 0x0000 + +/** @} */ + + + +/** An EAPOL-Key packet. + * + * These are used for the WPA 4-Way Handshake, whether or not prior + * authentication has been performed using EAP. + * + * On LANs, an eapol_key_pkt is always encapsulated in the data field + * of an eapol_frame, with the frame's type code set to EAPOL_TYPE_KEY. + * + * Unlike 802.11 frame headers, the fields in this structure are + * stored in big-endian! + */ +struct eapol_key_pkt +{ + /** One of the EAPOL_KEY_TYPE_* defines. */ + u8 type; + + /** Bitfield of key characteristics, network byte order */ + u16 info; + + /** Length of encryption key to be used, network byte order + * + * This is 16 for CCMP, 32 for TKIP, and 5 or 13 for WEP. + */ + u16 keysize; + + /** Monotonically increasing value for EAPOL-Key conversations + * + * In another classic demonstration of overengineering, this + * 8-byte value will rarely be anything above 1. It's stored + * in network byte order. + */ + u64 replay; + + /** Nonce value + * + * This is the authenticator's ANonce in frame 1, the peer's + * SNonce in frame 2, and 0 in frames 3 and 4. + */ + u8 nonce[32]; + + /** Initialization vector + * + * This contains the IV used with the Key Encryption Key, or 0 + * if the key is unencrypted or encrypted using an algorithm + * that does not require an IV. + */ + u8 iv[16]; + + /** Receive sequence counter for GTK + * + * This is used to synchronize the client's replay counter for + * ordinary data packets. The first six bytes contain PN0 + * through PN5 for CCMP mode, or TSC0 through TSC5 for TKIP + * mode. The last two bytes are zero. + */ + u8 rsc[8]; + + /** Reserved bytes */ + u8 _reserved[8]; + + /** Message integrity code over the entire EAPOL frame + * + * This is calculated using HMAC-MD5 when the key descriptor + * version field in @a info is 1, and HMAC-SHA1 ignoring the + * last 4 bytes of the hash when the version field in @a info + * is 2. + */ + u8 mic[16]; + + /** Length of the @a data field in bytes, network byte order */ + u16 datalen; + + /** Key data + * + * This is formatted as a series of 802.11 information + * elements, with cryptographic data encapsulated using a + * "vendor-specific IE" code and an IEEE-specified OUI. + */ + u8 data[0]; +} __attribute__ (( packed )); + + +/** WPA handshaking state */ +enum wpa_state { + /** Waiting for PMK to be set */ + WPA_WAITING = 0, + + /** Ready for 4-Way Handshake */ + WPA_READY, + + /** Performing 4-Way Handshake */ + WPA_WORKING, + + /** 4-Way Handshake succeeded */ + WPA_SUCCESS, + + /** 4-Way Handshake failed */ + WPA_FAILURE, +}; + +/** Bitfield indicating a selection of WPA transient keys */ +enum wpa_keymask { + /** Pairwise transient key */ + WPA_PTK = 1, + + /** Group transient key */ + WPA_GTK = 2, +}; + + +/** Length of a nonce */ +#define WPA_NONCE_LEN 32 + +/** Length of a TKIP main key */ +#define WPA_TKIP_KEY_LEN 16 + +/** Length of a TKIP MIC key */ +#define WPA_TKIP_MIC_KEY_LEN 8 + +/** Length of a CCMP key */ +#define WPA_CCMP_KEY_LEN 16 + +/** Length of an EAPOL Key Confirmation Key */ +#define WPA_KCK_LEN 16 + +/** Length of an EAPOL Key Encryption Key */ +#define WPA_KEK_LEN 16 + +/** Usual length of a Pairwise Master Key */ +#define WPA_PMK_LEN 32 + +/** Length of a PMKID */ +#define WPA_PMKID_LEN 16 + + +/** Structure of the Temporal Key for TKIP encryption */ +struct tkip_tk +{ + /** Main key: input to TKIP Phase 1 and Phase 2 key mixing functions */ + u8 key[WPA_TKIP_KEY_LEN]; + + /** Michael MIC keys */ + struct { + /** MIC key for packets from the AP */ + u8 rx[WPA_TKIP_MIC_KEY_LEN]; + + /** MIC key for packets to the AP */ + u8 tx[WPA_TKIP_MIC_KEY_LEN]; + } __attribute__ (( packed )) mic; +} __attribute__ (( packed )); + +/** Structure of a generic Temporal Key */ +union wpa_tk +{ + /** CCMP key */ + u8 ccmp[WPA_CCMP_KEY_LEN]; + + /** TKIP keys */ + struct tkip_tk tkip; +}; + +/** Structure of the Pairwise Transient Key */ +struct wpa_ptk +{ + /** EAPOL-Key Key Confirmation Key (KCK) */ + u8 kck[WPA_KCK_LEN]; + + /** EAPOL-Key Key Encryption Key (KEK) */ + u8 kek[WPA_KEK_LEN]; + + /** Temporal key */ + union wpa_tk tk; +} __attribute__ (( packed )); + +/** Structure of the Group Transient Key */ +struct wpa_gtk +{ + /** Temporal key */ + union wpa_tk tk; +} __attribute__ (( packed )); + + +/** Common context for WPA security handshaking + * + * Any implementor of a particular handshaking type (e.g. PSK or EAP) + * must include this structure at the very beginning of their private + * data context structure, to allow the EAPOL-Key handling code to + * work. When the preliminary authentication is done, it is necessary + * to call wpa_start(), passing the PMK (derived from PSK or EAP MSK) + * as an argument. The handshaker can use its @a step function to + * monitor @a state in this wpa_ctx structure for success or + * failure. On success, the keys will be available in @a ptk and @a + * gtk according to the state of the @a valid bitmask. + * + * After an initial success, the parent handshaker does not need to + * concern itself with rekeying; the WPA common code takes care of + * that. + */ +struct wpa_common_ctx +{ + /** 802.11 device we are authenticating for */ + struct net80211_device *dev; + + /** The Pairwise Master Key to use in handshaking + * + * This is set either by running the PBKDF2 algorithm on a + * passphrase with the SSID as salt to generate a pre-shared + * key, or by copying the first 32 bytes of the EAP Master + * Session Key in 802.1X-served authentication. + */ + u8 pmk[WPA_PMK_LEN]; + + /** Length of the Pairwise Master Key + * + * This is always 32 except with one EAP method which only + * gives 16 bytes. + */ + int pmk_len; + + /** State of EAPOL-Key handshaking */ + enum wpa_state state; + + /** Replay counter for this association + * + * This stores the replay counter value for the most recent + * packet we've accepted. It is initially initialised to ~0 to + * show we'll accept anything. + */ + u64 replay; + + /** Mask of valid keys after authentication success + * + * If the PTK is not valid, the GTK should be used for both + * unicast and multicast decryption; if the GTK is not valid, + * multicast packets cannot be decrypted. + */ + enum wpa_keymask valid; + + /** The cipher to use for unicast RX and all TX */ + enum net80211_crypto_alg crypt; + + /** The cipher to use for broadcast and multicast RX */ + enum net80211_crypto_alg gcrypt; + + /** The Pairwise Transient Key derived from the handshake */ + struct wpa_ptk ptk; + + /** The Group Transient Key derived from the handshake */ + struct wpa_gtk gtk; + + /** Authenticator-provided nonce */ + u8 Anonce[WPA_NONCE_LEN]; + + /** Supplicant-generated nonce (that's us) */ + u8 Snonce[WPA_NONCE_LEN]; + + /** Whether we should refrain from generating another SNonce */ + int have_Snonce; + + /** Data in WPA or RSN IE from AP's beacon frame */ + void *ap_rsn_ie; + + /** Length of @a ap_rsn_ie */ + int ap_rsn_ie_len; + + /** Whether @a ap_rsn_ie is an RSN IE (as opposed to old WPA) */ + int ap_rsn_is_rsn; + + /** List entry */ + struct list_head list; +}; + + +/** WPA handshake key integrity and encryption handler + * + * Note that due to the structure of the 4-Way Handshake we never + * actually need to encrypt key data, only decrypt it. + */ +struct wpa_kie { + /** Value of version bits in EAPOL-Key info field for which to use + * + * This should be one of the @c EAPOL_KEY_VERSION_* constants. + */ + int version; + + /** Calculate MIC over message + * + * @v kck Key Confirmation Key, 16 bytes + * @v msg Message to calculate MIC over + * @v len Number of bytes to calculate MIC over + * @ret mic Calculated MIC, 16 bytes long + * + * The @a mic return may point within @a msg, so it must not + * be filled until the calculation has been performed. + */ + void ( * mic ) ( const void *kck, const void *msg, size_t len, + void *mic ); + + /** Decrypt key data + * + * @v kek Key Encryption Key, 16 bytes + * @v iv Initialisation vector for encryption, 16 bytes + * @v msg Message to decrypt (Key Data field) + * @v len Length of message + * @ret msg Decrypted message in place of original + * @ret len Updated to reflect encrypted length + * @ret rc Return status code + * + * The decrypted message is written over the encrypted one. + */ + int ( * decrypt ) ( const void *kek, const void *iv, void *msg, + u16 *len ); +}; + +#define WPA_KIES __table ( struct wpa_kie, "wpa_kies" ) +#define __wpa_kie __table_entry ( WPA_KIES, 01 ) + + + +/** + * @defgroup wpa_kde Key descriptor element types + * @{ + */ + +/** Payload structure of the GTK-encapsulating KDE + * + * This does not include the IE type, length, or OUI bytes, which are + * generic to all KDEs. + */ +struct wpa_kde_gtk_encap +{ + /** Key ID and TX bit */ + u8 id; + + /** Reserved byte */ + u8 _rsvd; + + /** Encapsulated group transient key */ + struct wpa_gtk gtk; +} __attribute__ (( packed )); + +/** Mask for Key ID in wpa_kde_gtk::id field */ +#define WPA_GTK_KID 0x03 + +/** Mask for Tx bit in wpa_kde_gtk::id field */ +#define WPA_GTK_TXBIT 0x04 + + +/** KDE type for an encapsulated Group Transient Key (requires encryption) */ +#define WPA_KDE_GTK _MKOUI ( 0x00, 0x0F, 0xAC, 0x01 ) + +/** KDE type for a MAC address */ +#define WPA_KDE_MAC _MKOUI ( 0x00, 0x0F, 0xAC, 0x03 ) + +/** KDE type for a PMKID */ +#define WPA_KDE_PMKID _MKOUI ( 0x00, 0x0F, 0xAC, 0x04 ) + +/** KDE type for a nonce */ +#define WPA_KDE_NONCE _MKOUI ( 0x00, 0x0F, 0xAC, 0x06 ) + +/** KDE type for a lifetime value */ +#define WPA_KDE_LIFETIME _MKOUI ( 0x00, 0x0F, 0xAC, 0x07 ) + + +/** Any key descriptor element type + * + * KDEs follow the 802.11 information element format of a type byte + * (in this case "vendor-specific", with the requisite OUI+subtype + * after length) and a length byte whose value does not include the + * length of the type and length bytes. + */ +struct wpa_kde +{ + /** Information element type: always 0xDD (IEEE80211_IE_VENDOR) */ + u8 ie_type; + + /** Length, not including ie_type and length fields */ + u8 len; + + /** OUI + type byte */ + u32 oui_type; + + /** Payload data */ + union { + /** For GTK-type KDEs, encapsulated GTK */ + struct wpa_kde_gtk_encap gtk_encap; + + /** For MAC-type KDEs, the MAC address */ + u8 mac[ETH_ALEN]; + + /** For PMKID-type KDEs, the PMKID */ + u8 pmkid[WPA_PMKID_LEN]; + + /** For Nonce-type KDEs, the nonce */ + u8 nonce[WPA_NONCE_LEN]; + + /** For Lifetime-type KDEs, the lifetime in seconds + * + * This is in network byte order! + */ + u32 lifetime; + }; +} __attribute__ (( packed )); + +/** @} */ + +int wpa_make_rsn_ie ( struct net80211_device *dev, union ieee80211_ie **ie ); +int wpa_start ( struct net80211_device *dev, struct wpa_common_ctx *ctx, + const void *pmk, size_t pmk_len ); +void wpa_stop ( struct net80211_device *dev ); + +#endif /* _GPXE_WPA_H */ diff --git a/gpxe/src/include/gpxe/x509.h b/gpxe/src/include/gpxe/x509.h index 071e1de5..1b9d9aab 100644 --- a/gpxe/src/include/gpxe/x509.h +++ b/gpxe/src/include/gpxe/x509.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> struct asn1_cursor; diff --git a/gpxe/src/include/gpxe/xfer.h b/gpxe/src/include/gpxe/xfer.h index e592fa38..edd37034 100644 --- a/gpxe/src/include/gpxe/xfer.h +++ b/gpxe/src/include/gpxe/xfer.h @@ -7,6 +7,8 @@ * */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stddef.h> #include <stdarg.h> #include <gpxe/interface.h> |