[libc] Enable automated extraction of error usage reports
authorMichael Brown <mcb30@ipxe.org>
Sun, 30 May 2010 14:29:05 +0000 (15:29 +0100)
committerStefan Hajnoczi <stefanha@gmail.com>
Wed, 7 Jul 2010 19:22:19 +0000 (20:22 +0100)
Add preprocessor magic to the error definitions to enable every error
usage to be tracked.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
22 files changed:
src/Makefile
src/Makefile.housekeeping
src/arch/i386/scripts/i386.lds
src/arch/x86/scripts/efi.lds
src/drivers/net/ipoib.c
src/hci/strerror.c
src/hci/wireless_errors.c
src/image/segment.c
src/include/errno.h
src/include/gpxe/errortab.h
src/include/gpxe/ieee80211.h
src/include/gpxe/net80211_err.h [new file with mode: 0644]
src/net/80211/net80211.c
src/net/80211/sec80211.c
src/net/infiniband.c
src/net/infiniband/ib_srp.c
src/net/netdevice.c
src/net/tcp/iscsi.c
src/net/udp/tftp.c
src/usr/iwmgmt.c
src/util/.gitignore
src/util/einfo.c [new file with mode: 0644]

index ffa046f..2acde3c 100644 (file)
@@ -43,6 +43,7 @@ ELF2EFI32     := ./util/elf2efi32
 ELF2EFI64      := ./util/elf2efi64
 EFIROM         := ./util/efirom
 ICCFIX         := ./util/iccfix
+EINFO          := ./util/einfo
 DOXYGEN                := doxygen
 BINUTILS_DIR   := /usr
 BFD_DIR                := $(BINUTILS_DIR)
index 7aadadf..b6b747e 100644 (file)
@@ -550,6 +550,18 @@ $(BIN)/embedded.o : override CC := env CCACHE_DISABLE=1 $(CC)
 
 CFLAGS_embedded = -DEMBED_ALL="$(EMBED_ALL)"
 
+# Generate error usage information
+#
+$(BIN)/%.einfo : $(BIN)/%.o
+       $(QM)$(ECHO) "  [EINFO] $@"
+       $(Q)$(OBJCOPY) -O binary -j .einfo --set-section-flags .einfo=alloc \
+               $< $@
+
+EINFOS         := $(patsubst $(BIN)/%.o,$(BIN)/%.einfo,$(BOBJS))
+$(BIN)/errors : $(EINFOS) $(EINFO)
+       $(QM)$(ECHO) "  [EINFO] $@"
+       $(Q)$(EINFO) $(EINFOS) | sort > $@
+
 # Generate the NIC file from the parsed source files.  The NIC file is
 # only for rom-o-matic.
 #
@@ -903,6 +915,15 @@ $(ICCFIX) : util/iccfix.c $(MAKEDEPS)
        $(Q)$(HOST_CC) -idirafter include -O2 -o $@ $<
 CLEANUP += $(ICCFIX)
 
+###############################################################################
+#
+# The error usage information utility
+#
+$(EINFO) : util/einfo.c $(MAKEDEPS)
+       $(QM)$(ECHO) "  [HOSTCC] $@"
+       $(Q)$(HOST_CC) -idirafter include -O2 -o $@ $<
+CLEANUP += $(EINFO)
+
 ###############################################################################
 #
 # Local configs
index 0ce2c10..610bfa1 100644 (file)
@@ -162,6 +162,8 @@ SECTIONS {
        *(.eh_frame.*)
        *(.rel)
        *(.rel.*)
+       *(.einfo)
+       *(.einfo.*)
        *(.discard)
     }
 
index 7525b81..eb7eb30 100644 (file)
@@ -101,6 +101,8 @@ SECTIONS {
        *(.eh_frame.*)
        *(.rel)
        *(.rel.*)
+       *(.einfo)
+       *(.einfo.*)
        *(.discard)
     }
 }
index 4b3741e..42a50af 100644 (file)
@@ -77,11 +77,13 @@ static struct ipoib_mac ipoib_broadcast = {
 };
 
 /** Link status for "broadcast join in progress" */
-#define EINPROGRESS_JOINING ( EINPROGRESS | EUNIQ_01 )
+#define EINPROGRESS_JOINING __einfo_error ( EINFO_EINPROGRESS_JOINING )
+#define EINFO_EINPROGRESS_JOINING __einfo_uniqify \
+       ( EINFO_EINPROGRESS, 0x01, "Joining" )
 
 /** Human-readable message for the link status */
 struct errortab ipoib_errors[] __errortab = {
-       { EINPROGRESS_JOINING, "Joining" },
+       __einfo_errortab ( EINFO_EINPROGRESS_JOINING ),
 };
 
 /****************************************************************************
index 94547dd..3a99811 100644 (file)
@@ -102,21 +102,21 @@ const char * strerror ( int errno ) {
 
 /** The most common errors */
 struct errortab common_errors[] __errortab = {
-       { 0, "No error" },
-       { EACCES, "Permission denied" },
-       { ECANCELED, "Operation cancelled" },
-       { ECONNRESET, "Connection reset" },
-       { EINVAL, "Invalid argument" },
-       { EIO, "Input/output error" },
-       { ENETUNREACH, "Network unreachable" },
-       { ENODEV, "No such device" },
-       { ENOENT, "File not found" },
-       { ENOEXEC, "Not an executable image" },
-       { ENOMEM, "Out of memory" },
-       { ENOSPC, "No space left on device" },
-       { ENOTCONN, "Not connected" },
-       { ENOTSUP, "Not supported" },
-       { EPERM, "Operation not permitted" },
-       { ERANGE, "Out of range" },
-       { ETIMEDOUT, "Connection timed out" },
+       __einfo_errortab ( EINFO_ENOERR ),
+       __einfo_errortab ( EINFO_EACCES ),
+       __einfo_errortab ( EINFO_ECANCELED ),
+       __einfo_errortab ( EINFO_ECONNRESET ),
+       __einfo_errortab ( EINFO_EINVAL ),
+       __einfo_errortab ( EINFO_EIO ),
+       __einfo_errortab ( EINFO_ENETUNREACH ),
+       __einfo_errortab ( EINFO_ENODEV ),
+       __einfo_errortab ( EINFO_ENOENT ),
+       __einfo_errortab ( EINFO_ENOEXEC ),
+       __einfo_errortab ( EINFO_ENOMEM ),
+       __einfo_errortab ( EINFO_ENOSPC ),
+       __einfo_errortab ( EINFO_ENOTCONN ),
+       __einfo_errortab ( EINFO_ENOTSUP ),
+       __einfo_errortab ( EINFO_EPERM ),
+       __einfo_errortab ( EINFO_ERANGE ),
+       __einfo_errortab ( EINFO_ETIMEDOUT ),
 };
index 46006f9..ab95a3c 100644 (file)
@@ -20,99 +20,89 @@ FILE_LICENCE ( GPL2_OR_LATER );
 
 #include <errno.h>
 #include <gpxe/errortab.h>
+#include <gpxe/net80211_err.h>
 
 /* Record errors as though they come from the 802.11 stack */
 #undef ERRFILE
 #define ERRFILE ERRFILE_net80211
 
 /** All 802.11 errors
- *
- * These follow the 802.11 standard as much as is feasible, but most
- * have been abbreviated to fit the 50-character limit imposed by
- * strerror.
  */
 struct errortab wireless_errors[] __errortab = {
-       /* gPXE 802.11 stack errors */
-       { EINVAL | EUNIQ_01, "Packet too short" },
-       { EINVAL | EUNIQ_02, "Packet 802.11 version not supported" },
-       { EINVAL | EUNIQ_03, "Packet not a data packet" },
-       { EINVAL | EUNIQ_04, "Packet not from an Access Point" },
-       { EINVAL | EUNIQ_05, "Packet has invalid LLC header" },
-       { EINVAL | EUNIQ_06, "Packet decryption error", },
-       { EINVAL | EUNIQ_07, "Invalid active scan requested" },
-
-       /* 802.11 status codes (IEEE Std 802.11-2007, Table 7-23) */
-       /* Maximum error length: 50 chars                                            | */
-       { ECONNREFUSED | EUNIQ_01, "Unspecified failure" },
-       { ECONNREFUSED | EUNIQ_0A, "Cannot support all requested capabilities" },
-       { ECONNREFUSED | EUNIQ_0B, "Reassociation denied due to lack of association" },
-       { ECONNREFUSED | EUNIQ_0C, "Association denied for another reason" },
-       { ECONNREFUSED | EUNIQ_0D, "Authentication algorithm unsupported" },
-       { ECONNREFUSED | EUNIQ_0E, "Authentication sequence number unexpected" },
-       { ECONNREFUSED | EUNIQ_0F, "Authentication rejected due to challenge failure" },
-       { ECONNREFUSED | EUNIQ_10, "Authentication rejected due to timeout" },
-       { ECONNREFUSED | EUNIQ_11, "Association denied because AP is out of resources" },
-       { ECONNREFUSED | EUNIQ_12, "Association denied; basic rate support required" },
-       { ECONNREFUSED | EUNIQ_13, "Association denied; short preamble support req'd" },
-       { ECONNREFUSED | EUNIQ_14, "Association denied; PBCC modulation support req'd" },
-       { ECONNREFUSED | EUNIQ_15, "Association denied; Channel Agility support req'd" },
-       { ECONNREFUSED | EUNIQ_16, "Association denied; Spectrum Management required" },
-       { ECONNREFUSED | EUNIQ_17, "Association denied; Power Capability unacceptable" },
-       { ECONNREFUSED | EUNIQ_18, "Association denied; Supported Channels unacceptable" },
-       { ECONNREFUSED | EUNIQ_19, "Association denied; Short Slot Tume support req'd" },
-       { ECONNREFUSED | EUNIQ_1A, "Association denied; DSSS-OFDM support required" },
-       { EHOSTUNREACH,            "Unspecified, QoS-related failure" },
-       { EHOSTUNREACH | EUNIQ_01, "Association denied; QoS AP out of QoS resources" },
-       { EHOSTUNREACH | EUNIQ_02, "Association denied due to excessively poor link" },
-       { EHOSTUNREACH | EUNIQ_03, "Association denied; QoS support required" },
-       { EHOSTUNREACH | EUNIQ_05, "The request has been declined" },
-       { EHOSTUNREACH | EUNIQ_06, "Request unsuccessful due to invalid parameters" },
-       { EHOSTUNREACH | EUNIQ_07, "TS not created due to bad specification" },
-       { EHOSTUNREACH | EUNIQ_08, "Invalid information element" },
-       { EHOSTUNREACH | EUNIQ_09, "Invalid group cipher" },
-       { EHOSTUNREACH | EUNIQ_0A, "Invalid pairwise cipher" },
-       { EHOSTUNREACH | EUNIQ_0B, "Invalid AKMP" },
-       { EHOSTUNREACH | EUNIQ_0C, "Unsupported RSN information element version" },
-       { EHOSTUNREACH | EUNIQ_0D, "Invalid RSN information element capabilities" },
-       { EHOSTUNREACH | EUNIQ_0E, "Cipher suite rejected because of security policy" },
-       { EHOSTUNREACH | EUNIQ_0F, "TS not created due to insufficient delay" },
-       { EHOSTUNREACH | EUNIQ_10, "Direct link is not allowed in the BSS by policy" },
-       { EHOSTUNREACH | EUNIQ_11, "The Destination STA is not present within the BSS" },
-       { EHOSTUNREACH | EUNIQ_12, "The Destination STA is not a QoS STA" },
-       { EHOSTUNREACH | EUNIQ_13, "Association denied; Listen Interval is too large" },
-
-       /* 802.11 reason codes (IEEE Std 802.11-2007, Table 7-22) */
-       /* Maximum error length: 50 chars                                          | */
-       { ECONNRESET | EUNIQ_01, "Unspecified reason" },
-       { ECONNRESET | EUNIQ_02, "Previous authentication no longer valid" },
-       { ECONNRESET | EUNIQ_03, "Deauthenticated due to leaving network" },
-       { ECONNRESET | EUNIQ_04, "Disassociated due to inactivity" },
-       { ECONNRESET | EUNIQ_05, "Disassociated because AP is out of resources" },
-       { ECONNRESET | EUNIQ_06, "Class 2 frame received from nonauthenticated STA" },
-       { ECONNRESET | EUNIQ_07, "Class 3 frame received from nonassociated STA" },
-       { ECONNRESET | EUNIQ_08, "Disassociated due to roaming" },
-       { ECONNRESET | EUNIQ_09, "STA requesting (re)association not authenticated" },
-       { ECONNRESET | EUNIQ_0A, "Disassociated; Power Capability unacceptable" },
-       { ECONNRESET | EUNIQ_0B, "Disassociated; Supported Channels unacceptable" },
-       { ECONNRESET | EUNIQ_0D, "Invalid information element" },
-       { ECONNRESET | EUNIQ_0E, "Message integrity code (MIC) failure" },
-       { ECONNRESET | EUNIQ_0F, "4-Way Handshake timeout" },
-       { ECONNRESET | EUNIQ_10, "Group Key Handshake timeout" },
-       { ECONNRESET | EUNIQ_11, "4-Way Handshake information element changed unduly" },
-       { ECONNRESET | EUNIQ_12, "Invalid group cipher" },
-       { ECONNRESET | EUNIQ_13, "Invalid pairwise cipher" },
-       { ECONNRESET | EUNIQ_14, "Invalid AKMP" },
-       { ECONNRESET | EUNIQ_15, "Unsupported RSN information element version" },
-       { ECONNRESET | EUNIQ_16, "Invalid RSN information element capabilities" },
-       { ECONNRESET | EUNIQ_17, "IEEE 802.1X authentication failed" },
-       { ECONNRESET | EUNIQ_18, "Cipher suite rejected because of security policy" },
-       { ENETRESET,            "Disassociated for unspecified, QoS-related reason" },
-       { ENETRESET | EUNIQ_01, "Disassociated; QoS AP is out of QoS resources" },
-       { ENETRESET | EUNIQ_02, "Disassociated due to excessively poor link" },
-       { ENETRESET | EUNIQ_03, "Disassociated due to TXOP limit violation" },
-       { ENETRESET | EUNIQ_04, "Requested; STA is leaving the BSS (or resetting)" },
-       { ENETRESET | EUNIQ_05, "Requested; does not want to use the mechanism" },
-       { ENETRESET | EUNIQ_06, "Requested; setup is required" },
-       { ENETRESET | EUNIQ_07, "Requested from peer STA due to timeout" },
-       { ENETRESET | EUNIQ_0D, "Peer STA does not support requested cipher suite" },
+       __einfo_errortab ( EINFO_EINVAL_PKT_TOO_SHORT ),
+       __einfo_errortab ( EINFO_EINVAL_PKT_VERSION ),
+       __einfo_errortab ( EINFO_EINVAL_PKT_NOT_DATA ),
+       __einfo_errortab ( EINFO_EINVAL_PKT_NOT_FROMDS ),
+       __einfo_errortab ( EINFO_EINVAL_PKT_LLC_HEADER ),
+       __einfo_errortab ( EINFO_EINVAL_CRYPTO_REQUEST ),
+       __einfo_errortab ( EINFO_EINVAL_ACTIVE_SCAN ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_FAILURE ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_CAPAB_UNSUPP ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_REASSOC_INVALID ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_DENIED ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_ALGO_UNSUPP ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_SEQ_INVALID ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_CHALL_INVALID ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_TIMEOUT ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NO_ROOM ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_RATE ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_PMBL ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_PBCC ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_BAD_POWER ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_BAD_CHANNELS ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_SLOT ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_NEED_DSSS_OFDM ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_QOS_FAILURE ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_QOS_NO_ROOM ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_LINK_IS_HORRIBLE ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_ASSOC_NEED_QOS ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_REQUEST_DECLINED ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_REQUEST_INVALID ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_TS_NOT_CREATED_AGAIN ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_INVALID_IE ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_GROUP_CIPHER_INVALID ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_PAIR_CIPHER_INVALID ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_AKMP_INVALID ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_RSN_VERSION_UNSUPP ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_RSN_CAPAB_INVALID ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_CIPHER_REJECTED ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_TS_NOT_CREATED_WAIT ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_DIRECT_LINK_FORBIDDEN ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_DEST_NOT_PRESENT ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_DEST_NOT_QOS ),
+       __einfo_errortab ( EINFO_EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH ),
+       __einfo_errortab ( EINFO_ECONNRESET_UNSPECIFIED ),
+       __einfo_errortab ( EINFO_ECONNRESET_AUTH_NO_LONGER_VALID ),
+       __einfo_errortab ( EINFO_ECONNRESET_LEAVING ),
+       __einfo_errortab ( EINFO_ECONNRESET_INACTIVITY ),
+       __einfo_errortab ( EINFO_ECONNRESET_OUT_OF_RESOURCES ),
+       __einfo_errortab ( EINFO_ECONNRESET_NEED_AUTH ),
+       __einfo_errortab ( EINFO_ECONNRESET_NEED_ASSOC ),
+       __einfo_errortab ( EINFO_ECONNRESET_LEAVING_TO_ROAM ),
+       __einfo_errortab ( EINFO_ECONNRESET_REASSOC_INVALID ),
+       __einfo_errortab ( EINFO_ECONNRESET_BAD_POWER ),
+       __einfo_errortab ( EINFO_ECONNRESET_BAD_CHANNELS ),
+       __einfo_errortab ( EINFO_ECONNRESET_INVALID_IE ),
+       __einfo_errortab ( EINFO_ECONNRESET_MIC_FAILURE ),
+       __einfo_errortab ( EINFO_ECONNRESET_4WAY_TIMEOUT ),
+       __einfo_errortab ( EINFO_ECONNRESET_GROUPKEY_TIMEOUT ),
+       __einfo_errortab ( EINFO_ECONNRESET_4WAY_INVALID ),
+       __einfo_errortab ( EINFO_ECONNRESET_GROUP_CIPHER_INVALID ),
+       __einfo_errortab ( EINFO_ECONNRESET_PAIR_CIPHER_INVALID ),
+       __einfo_errortab ( EINFO_ECONNRESET_AKMP_INVALID ),
+       __einfo_errortab ( EINFO_ECONNRESET_RSN_VERSION_INVALID ),
+       __einfo_errortab ( EINFO_ECONNRESET_RSN_CAPAB_INVALID ),
+       __einfo_errortab ( EINFO_ECONNRESET_8021X_FAILURE ),
+       __einfo_errortab ( EINFO_ECONNRESET_CIPHER_REJECTED ),
+       __einfo_errortab ( EINFO_ENETRESET_QOS_UNSPECIFIED ),
+       __einfo_errortab ( EINFO_ENETRESET_QOS_OUT_OF_RESOURCES ),
+       __einfo_errortab ( EINFO_ENETRESET_LINK_IS_HORRIBLE ),
+       __einfo_errortab ( EINFO_ENETRESET_INVALID_TXOP ),
+       __einfo_errortab ( EINFO_ENETRESET_REQUESTED_LEAVING ),
+       __einfo_errortab ( EINFO_ENETRESET_REQUESTED_NO_USE ),
+       __einfo_errortab ( EINFO_ENETRESET_REQUESTED_NEED_SETUP ),
+       __einfo_errortab ( EINFO_ENETRESET_REQUESTED_TIMEOUT ),
+       __einfo_errortab ( EINFO_ENETRESET_CIPHER_UNSUPPORTED ),
 };
index e247453..0f50fed 100644 (file)
@@ -31,6 +31,19 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <gpxe/errortab.h>
 #include <gpxe/segment.h>
 
+/**
+ * Segment-specific error messages
+ *
+ * This error happens sufficiently often to merit a user-friendly
+ * description.
+ */
+#define ERANGE_SEGMENT __einfo_error ( EINFO_ERANGE_SEGMENT )
+#define EINFO_ERANGE_SEGMENT \
+       __einfo_uniqify ( EINFO_ERANGE, 0x01, "Requested memory not available" )
+struct errortab segment_errors[] __errortab = {
+       __einfo_errortab ( EINFO_ERANGE_SEGMENT ),
+};
+
 /**
  * Prepare segment for loading
  *
@@ -73,15 +86,5 @@ int prep_segment ( userptr_t segment, size_t filesz, size_t memsz ) {
        /* No suitable memory region found */
        DBG ( "Segment [%lx,%lx,%lx) does not fit into available memory\n",
              start, mid, end );
-       return -ERANGE;
+       return -ERANGE_SEGMENT;
 }
-
-/**
- * Segment-specific error messages
- *
- * This error happens sufficiently often to merit a user-friendly
- * description.
- */
-struct errortab segment_errors[] __errortab = {
-       { ERANGE, "Requested memory not available" },
-};
index 56095ec..60db061 100644 (file)
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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 ERRNO_H
 #define ERRNO_H
 
@@ -40,19 +58,13 @@ FILE_LICENCE ( GPL2_OR_LATER );
  *
  *
  * The convention within the code is that errors are negative and
- * expressed using the POSIX error code and (optionally) a per-file
- * disambiguator, e.g.
+ * expressed using the POSIX error, e.g.
  *
  *     return -EINVAL;
  *
- * or
- *
- *     #define ETCP_BAD_CHECKSUM EUNIQ_02
- *     return -( EINVAL | ETCP_BAD_CHECKSUM )
- *
  * By various bits of preprocessor magic, the PXE error code and file
  * identifier are already incorporated into the definition of the
- * POSIX error code, which keeps the code relatively clean.
+ * POSIX error macro, which keeps the code relatively clean.
  *
  *
  * Functions that wish to return failures should be declared as
@@ -69,6 +81,21 @@ FILE_LICENCE ( GPL2_OR_LATER );
  * As illustrated in the above example, error returns should generally
  * be directly propagated upward to the calling function.
  *
+ *
+ * Individual files may declare localised errors using
+ * __einfo_uniqify().  For example, iscsi.c declares a localised
+ * version of EACCES for the error of "access denied due to incorrect
+ * target username":
+ *
+ *     #define EACCES_INCORRECT_TARGET_USERNAME        \
+ *         __einfo_error ( EINFO_EACCES_INCORRECT_TARGET_USERNAME )
+ *     #define EINFO_EACCES_INCORRECT_TARGET_USERNAME \
+ *         __einfo_uniqify ( EINFO_EACCESS, 0x01, "Incorrect target username" )
+ *
+ * which can then be used as:
+ *
+ *     return -EACCES_INCORRECT_TARGET_USERNAME;
+ *
  */
 
 /* Get definitions for file identifiers */
@@ -85,8 +112,121 @@ extern char missing_errfile_declaration[] __attribute__ (( deprecated ));
 #define ERRFILE ( 0 * ( ( int ) missing_errfile_declaration ) )
 #endif
 
-/** Derive PXENV_STATUS code from gPXE error number */
-#define PXENV_STATUS( rc ) ( (-(rc)) & 0x00ff )
+/**
+ * Declare error information
+ *
+ * @v pxe              PXE error number (0x00-0xff)
+ * @v posix            POSIX error number (0x00-0x7f)
+ * @v uniq             Error disambiguator (0x00-0x1f)
+ * @v desc             Error description
+ * @ret einfo          Error information
+ */
+#define __einfo( pxe, posix, uniq, desc ) ( pxe, posix, uniq, desc )
+
+/**
+ * Get PXE error number
+ *
+ * @v einfo            Error information
+ * @ret pxe            PXE error number
+ */
+#define __einfo_pxe( einfo ) __einfo_extract_pxe einfo
+#define __einfo_extract_pxe( pxe, posix, uniq, desc ) pxe
+
+/**
+ * Get POSIX error number
+ *
+ * @v einfo            Error information
+ * @ret posix          POSIX error number
+ */
+#define __einfo_posix( einfo ) __einfo_extract_posix einfo
+#define __einfo_extract_posix( pxe, posix, uniq, desc ) posix
+
+/**
+ * Get error disambiguator
+ *
+ * @v einfo            Error information
+ * @ret uniq           Error disambiguator
+ */
+#define __einfo_uniq( einfo ) __einfo_extract_uniq einfo
+#define __einfo_extract_uniq( pxe, posix, uniq, desc ) uniq
+
+/**
+ * Get error description
+ *
+ * @v einfo            Error information
+ * @ret desc           Error description
+ */
+#define __einfo_desc( einfo ) __einfo_extract_desc einfo
+#define __einfo_extract_desc( pxe, posix, uniq, desc ) desc
+
+/**
+ * Declare disambiguated error
+ *
+ * @v einfo_base       Base error information
+ * @v uniq             Error disambiguator
+ * @v desc             Error description
+ * @ret einfo          Error information
+ */
+#define __einfo_uniqify( einfo_base, uniq, desc )                      \
+       __einfo ( __einfo_pxe ( einfo_base ),                           \
+                 __einfo_posix ( einfo_base ),                         \
+                 uniq, desc )
+
+/**
+ * Get error number
+ *
+ * @v einfo            Error information
+ * @ret errno          Error number
+ */
+#define __einfo_errno( einfo )                                         \
+       ( ( __einfo_posix ( einfo ) << 24 ) | ( ERRFILE ) |             \
+         ( __einfo_uniq ( einfo ) << 8 ) |                             \
+         ( __einfo_pxe ( einfo ) << 0 ) )
+
+/**
+ * Disambiguate a base error based on non-constant information
+ *
+ * @v error_base       Base error
+ * @v uniq             Error disambiguator
+ * @v ...              List of expected possible disambiguated errors
+ * @ret error          Error
+ *
+ * EUNIQ() should be used when information from an external source is
+ * being incorporated into an error.  For example, the 802.11 stack
+ * uses EUNIQ() to incorporate 802.11 status codes returned by an
+ * access point into an error.
+ *
+ * EUNIQ() should not be used for constant error disambiguators; use
+ * __einfo_uniqify() instead.
+ */
+#define EUNIQ( errno, uniq, ... ) ( {                                  \
+       euniq_discard ( 0, ##__VA_ARGS__);                              \
+       ( (errno) | ( (uniq) << 8 ) ); } )
+static inline void euniq_discard ( int dummy __unused, ... ) {}
+
+/**
+ * Declare error
+ *
+ * @v einfo            Error information
+ * @ret error          Error
+ */
+#define __einfo_error( einfo ) ( {                                     \
+       __asm__ ( ".section \".einfo\", \"\", @progbits\n\t"            \
+                 ".align 8\n\t"                                        \
+                 "\n1:\n\t"                                            \
+                 ".long ( 4f - 1b )\n\t"                               \
+                 ".long %c0\n\t"                                       \
+                 ".long ( 2f - 1b )\n\t"                               \
+                 ".long ( 3f - 1b )\n\t"                               \
+                 ".long %c1\n\t"                                       \
+                 "\n2:\t.asciz \"" __einfo_desc ( einfo ) "\"\n\t"     \
+                 "\n3:\t.asciz \"" __FILE__ "\"\n\t"                   \
+                 ".align 8\n\t"                                        \
+                 "\n4:\n\t"                                            \
+                 ".previous\n\t" : :                                   \
+                 "i" ( __einfo_errno ( einfo) ),                       \
+                 "i" ( __LINE__ ) );                                   \
+       __einfo_errno ( einfo ); } )
 
 /**
  * @defgroup pxeerrors PXE error codes
@@ -199,309 +339,420 @@ extern char missing_errfile_declaration[] __attribute__ (( deprecated ));
 
 /** @} */
 
+/** Derive PXENV_STATUS code from gPXE error number */
+#define PXENV_STATUS( rc ) ( (-(rc)) & 0x00ff )
+
 /**
  * @defgroup posixerrors POSIX error codes
  *
  * The names and meanings (but not the values) of these error codes
- * are defined by POSIX.  We choose to assign unique values which
- * incorporate the closest equivalent PXE error code, so that code may
- * simply use ENOMEM, rather than having to use the cumbersome
- * (ENOMEM|PXENV_STATUS_OUT_OF_RESOURCES).
+ * are defined by POSIX.
  *
  * @{
  */
 
 /** Operation completed successfully */
-#define ENOERR                 ( ERRFILE | PXENV_STATUS_SUCCESS | 0x00000000 )
+#define ENOERR __einfo_error ( EINFO_ENOERR )
+#define EINFO_ENOERR __einfo ( PXENV_STATUS_SUCCESS, 0x00, 0, \
+                              "Operation completed successfully" )
 
-/** Arg list too long */
-#define E2BIG                 ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x01000000 )
+/** Argument list too long */
+#define E2BIG __einfo_error ( EINFO_E2BIG )
+#define EINFO_E2BIG __einfo ( PXENV_STATUS_BAD_FUNC, 0x01, 0, \
+                             "Argument list too long" )
 
 /** Permission denied */
-#define EACCES   ( ERRFILE | PXENV_STATUS_TFTP_ACCESS_VIOLATION | 0x02000000 )
+#define EACCES __einfo_error ( EINFO_EACCES )
+#define EINFO_EACCES __einfo ( PXENV_STATUS_TFTP_ACCESS_VIOLATION, 0x02, 0, \
+                              "Permission denied" )
 
-/** Address in use */
-#define EADDRINUSE            ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x03000000 )
+/** Address already in use */
+#define EADDRINUSE __einfo_error ( EINFO_EADDRINUSE )
+#define EINFO_EADDRINUSE __einfo ( PXENV_STATUS_UDP_OPEN, 0x03, 0, \
+                                  "Address already in use" )
 
 /** Address not available */
-#define EADDRNOTAVAIL         ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x04000000 )
+#define EADDRNOTAVAIL __einfo_error ( EINFO_EADDRNOTAVAIL )
+#define EINFO_EADDRNOTAVAIL __einfo ( PXENV_STATUS_UDP_OPEN, 0x04, 0, \
+                                     "Address not available" )
 
 /** Address family not supported */
-#define EAFNOSUPPORT       ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x05000000 )
+#define EAFNOSUPPORT __einfo_error ( EINFO_EAFNOSUPPORT )
+#define EINFO_EAFNOSUPPORT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x05, 0, \
+                                    "Address family not supported" )
 
 /** Resource temporarily unavailable */
-#define EAGAIN                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x06000000 )
+#define EAGAIN __einfo_error ( EINFO_EAGAIN )
+#define EINFO_EAGAIN __einfo ( PXENV_STATUS_FAILURE, 0x06, 0, \
+                              "Resource temporarily unavailable" )
 
 /** Connection already in progress */
-#define EALREADY              ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x07000000 )
+#define EALREADY __einfo_error ( EINFO_EALREADY )
+#define EINFO_EALREADY __einfo ( PXENV_STATUS_UDP_OPEN, 0x07, 0, \
+                                "Connection already in progress" )
 
 /** Bad file descriptor */
-#define EBADF              ( ERRFILE | PXENV_STATUS_TFTP_CLOSED | 0x08000000 )
+#define EBADF __einfo_error ( EINFO_EBADF )
+#define EINFO_EBADF __einfo ( PXENV_STATUS_TFTP_CLOSED, 0x08, 0, \
+                             "Bad file descriptor" )
 
 /** Bad message */
-#define EBADMSG                        ( ERRFILE | PXENV_STATUS_FAILURE | 0x09000000 )
+#define EBADMSG __einfo_error ( EINFO_EBADMSG )
+#define EINFO_EBADMSG __einfo ( PXENV_STATUS_FAILURE, 0x09, 0, \
+                               "Bad message" )
 
-/** Resource busy */
-#define EBUSY         ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x0a000000 )
+/** Device or resource busy */
+#define EBUSY __einfo_error ( EINFO_EBUSY )
+#define EINFO_EBUSY __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x0a, 0, \
+                             "Device or resource busy" )
 
 /** Operation canceled */
-#define ECANCELED \
-            ( ERRFILE | PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE | 0x0b000000 )
+#define ECANCELED __einfo_error ( EINFO_ECANCELED )
+#define EINFO_ECANCELED __einfo ( PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE, \
+                                 0x0b, 0, "Operation canceled" )
 
 /** No child processes */
-#define ECHILD     ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x0c000000 )
+#define ECHILD __einfo_error ( EINFO_ECHILD )
+#define EINFO_ECHILD __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x0c, 0, \
+                              "No child processes" )
 
 /** Connection aborted */
-#define ECONNABORTED \
-       ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x0d000000 )
+#define ECONNABORTED __einfo_error ( EINFO_ECONNABORTED )
+#define EINFO_ECONNABORTED                                               \
+       __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, 0x0d, 0, \
+                 "Connection aborted" )
 
 /** Connection refused */
-#define ECONNREFUSED \
-           ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION | 0x0e000000 )
+#define ECONNREFUSED __einfo_error ( EINFO_ECONNREFUSED )
+#define EINFO_ECONNREFUSED __einfo ( PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION, \
+                                    0x0e, 0, "Connection refused" )
 
 /** Connection reset */
-#define ECONNRESET \
-       ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x0f000000 )
+#define ECONNRESET __einfo_error ( EINFO_ECONNRESET )
+#define EINFO_ECONNRESET                                                 \
+       __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, 0x0f, 0, \
+                 "Connection reset" )
 
 /** Resource deadlock avoided */
-#define EDEADLK                        ( ERRFILE | PXENV_STATUS_FAILURE | 0x10000000 )
+#define EDEADLK __einfo_error ( EINFO_EDEADLK )
+#define EINFO_EDEADLK __einfo ( PXENV_STATUS_FAILURE, 0x10, 0, \
+                               "Resource deadlock avoided" )
 
 /** Destination address required */
-#define EDESTADDRREQ          ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x11000000 )
+#define EDESTADDRREQ __einfo_error ( EINFO_EDESTADDRREQ )
+#define EINFO_EDESTADDRREQ __einfo ( PXENV_STATUS_BAD_FUNC, 0x11, 0, \
+                                    "Destination address required" )
 
-/** Domain error */
-#define EDOM                   ( ERRFILE | PXENV_STATUS_FAILURE | 0x12000000 )
+/** Mathematics argument out of domain of function */
+#define EDOM __einfo_error ( EINFO_EDOM )
+#define EINFO_EDOM __einfo ( PXENV_STATUS_FAILURE, 0x12, 0, \
+                            "Mathematics argument out of domain of function" )
 
-/** Reserved */
-#define EDQUOT                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x13000000 )
+/** Disk quota exceeded */
+#define EDQUOT __einfo_error ( EINFO_EDQUOT )
+#define EINFO_EDQUOT __einfo ( PXENV_STATUS_FAILURE, 0x13, 0, \
+                              "Disk quote exceeded" )
 
 /** File exists */
-#define EEXIST                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x14000000 )
+#define EEXIST __einfo_error ( EINFO_EEXIST )
+#define EINFO_EEXIST __einfo ( PXENV_STATUS_FAILURE, 0x14, 0, \
+                              "File exists" )
 
 /** Bad address */
-#define EFAULT           ( ERRFILE | PXENV_STATUS_MCOPY_PROBLEM | 0x15000000 )
+#define EFAULT __einfo_error ( EINFO_EFAULT )
+#define EINFO_EFAULT __einfo ( PXENV_STATUS_MCOPY_PROBLEM, 0x15, 0, \
+                              "Bad address" )
 
 /** File too large */
-#define EFBIG            ( ERRFILE | PXENV_STATUS_MCOPY_PROBLEM | 0x16000000 )
+#define EFBIG __einfo_error ( EINFO_EFBIG )
+#define EINFO_EFBIG __einfo ( PXENV_STATUS_MCOPY_PROBLEM, 0x16, 0, \
+                             "File too large" )
 
 /** Host is unreachable */
-#define EHOSTUNREACH       ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x17000000 )
+#define EHOSTUNREACH __einfo_error ( EINFO_EHOSTUNREACH )
+#define EINFO_EHOSTUNREACH __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x17, 0, \
+                                    "Host is unreachable" )
 
 /** Identifier removed */
-#define EIDRM                  ( ERRFILE | PXENV_STATUS_FAILURE | 0x18000000 )
+#define EIDRM __einfo_error ( EINFO_EIDRM )
+#define EINFO_EIDRM __einfo ( PXENV_STATUS_FAILURE, 0x18, 0, \
+                             "Identifier removed" )
 
 /** Illegal byte sequence */
-#define EILSEQ                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x19000000 )
+#define EILSEQ __einfo_error ( EINFO_EILSEQ )
+#define EINFO_EILSEQ __einfo ( PXENV_STATUS_FAILURE, 0x19, 0, \
+                              "Illegal byte sequence" )
 
 /** Operation in progress */
-#define EINPROGRESS            ( ERRFILE | PXENV_STATUS_FAILURE | 0x1a000000 )
+#define EINPROGRESS __einfo_error ( EINFO_EINPROGRESS )
+#define EINFO_EINPROGRESS __einfo ( PXENV_STATUS_FAILURE, 0x1a, 0, \
+                                   "Operation in progress" )
 
 /** Interrupted function call */
-#define EINTR                  ( ERRFILE | PXENV_STATUS_FAILURE | 0x1b000000 )
+#define EINTR __einfo_error ( EINFO_EINTR )
+#define EINFO_EINTR __einfo ( PXENV_STATUS_FAILURE, 0x1b, 0, \
+                             "Interrupted function call" )
 
 /** Invalid argument */
-#define EINVAL                ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x1c000000 )
+#define EINVAL __einfo_error ( EINFO_EINVAL )
+#define EINFO_EINVAL __einfo ( PXENV_STATUS_BAD_FUNC, 0x1c, 0, \
+                              "Invalid argument" )
 
 /** Input/output error */
-#define EIO \
-       ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x1d000000 )
+#define EIO __einfo_error ( EINFO_EIO )
+#define EINFO_EIO __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, \
+                           0x1d, 0, "Input/output error" )
 
 /** Socket is connected */
-#define EISCONN                       ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x1e000000 )
+#define EISCONN __einfo_error ( EINFO_EISCONN )
+#define EINFO_EISCONN __einfo ( PXENV_STATUS_UDP_OPEN, 0x1e, 0, \
+                               "Socket is connected" )
 
 /** Is a directory */
-#define EISDIR                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x1f000000 )
+#define EISDIR __einfo_error ( EINFO_EISDIR )
+#define EINFO_EISDIR __einfo ( PXENV_STATUS_FAILURE, 0x1f, 0, \
+                              "Is a directory" )
 
 /** Too many levels of symbolic links */
-#define ELOOP                  ( ERRFILE | PXENV_STATUS_FAILURE | 0x20000000 )
+#define ELOOP __einfo_error ( EINFO_ELOOP )
+#define EINFO_ELOOP __einfo ( PXENV_STATUS_FAILURE, 0x20, 0, \
+                             "Too many levels of symbolic links" )
 
 /** Too many open files */
-#define EMFILE        ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x21000000 )
+#define EMFILE __einfo_error ( EINFO_EMFILE )
+#define EINFO_EMFILE __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x21, 0, \
+                              "Too many open files" )
 
 /** Too many links */
-#define EMLINK                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x22000000 )
+#define EMLINK __einfo_error ( EINFO_EMLINK )
+#define EINFO_EMLINK __einfo ( PXENV_STATUS_FAILURE, 0x22, 0, \
+                              "Too many links" )
 
-/** Inappropriate message buffer length */
-#define EMSGSIZE              ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x23000000 )
+/** Message too long */
+#define EMSGSIZE __einfo_error ( EINFO_EMSGSIZE )
+#define EINFO_EMSGSIZE __einfo ( PXENV_STATUS_BAD_FUNC, 0x23, 0, \
+                                "Message too long" )
 
-/** Reserved */
-#define EMULTIHOP              ( ERRFILE | PXENV_STATUS_FAILURE | 0x24000000 )
+/** Multihop attempted */
+#define EMULTIHOP __einfo_error ( EINFO_EMULTIHOP )
+#define EINFO_EMULTIHOP __einfo ( PXENV_STATUS_FAILURE, 0x24, 0, \
+                                 "Multihop attempted" )
 
 /** Filename too long */
-#define ENAMETOOLONG           ( ERRFILE | PXENV_STATUS_FAILURE | 0x25000000 )
+#define ENAMETOOLONG __einfo_error ( EINFO_ENAMETOOLONG )
+#define EINFO_ENAMETOOLONG __einfo ( PXENV_STATUS_FAILURE, 0x25, 0, \
+                                    "Filename too long" )
 
 /** Network is down */
-#define ENETDOWN           ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x26000000 )
+#define ENETDOWN __einfo_error ( EINFO_ENETDOWN )
+#define EINFO_ENETDOWN __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x26, 0, \
+                                "Network is down" )
 
 /** Connection aborted by network */
-#define ENETRESET              ( ERRFILE | PXENV_STATUS_FAILURE | 0x27000000 )
+#define ENETRESET __einfo_error ( EINFO_ENETRESET )
+#define EINFO_ENETRESET __einfo ( PXENV_STATUS_FAILURE, 0x27, 0, \
+                                 "Connection aborted by network" )
 
 /** Network unreachable */
-#define ENETUNREACH        ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x28000000 )
+#define ENETUNREACH __einfo_error ( EINFO_ENETUNREACH )
+#define EINFO_ENETUNREACH __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x28, 0, \
+                                   "Network unreachable" )
 
 /** Too many open files in system */
-#define ENFILE        ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x29000000 )
+#define ENFILE __einfo_error ( EINFO_ENFILE )
+#define EINFO_ENFILE __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x29, 0, \
+                              "Too many open files in system" )
 
 /** No buffer space available */
-#define ENOBUFS               ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x2a000000 )
+#define ENOBUFS __einfo_error ( EINFO_ENOBUFS )
+#define EINFO_ENOBUFS __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x2a, 0, \
+                               "No buffer space available" )
 
 /** No message is available on the STREAM head read queue */
-#define ENODATA                        ( ERRFILE | PXENV_STATUS_FAILURE | 0x2b000000 )
+#define ENODATA __einfo_error ( EINFO_ENODATA )
+#define EINFO_ENODATA                           \
+       __einfo ( PXENV_STATUS_FAILURE, 0x2b, 0, \
+                 "No message is available on the STREAM head read queue" )
 
 /** No such device */
-#define ENODEV     ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x2c000000 )
+#define ENODEV __einfo_error ( EINFO_ENODEV )
+#define EINFO_ENODEV __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x2c, 0, \
+                              "No such device" )
 
 /** No such file or directory */
-#define ENOENT     ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x2d000000 )
+#define ENOENT __einfo_error ( EINFO_ENOENT )
+#define EINFO_ENOENT __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x2d, 0, \
+                              "No such file or directory" )
 
 /** Exec format error */
-#define ENOEXEC                        ( ERRFILE | PXENV_STATUS_FAILURE | 0x2e000000 )
+#define ENOEXEC __einfo_error ( EINFO_ENOEXEC )
+#define EINFO_ENOEXEC __einfo ( PXENV_STATUS_FAILURE, 0x2e, 0, \
+                               "Exec format error" )
 
 /** No locks available */
-#define ENOLCK                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x2f000000 )
+#define ENOLCK __einfo_error ( EINFO_ENOLCK )
+#define EINFO_ENOLCK __einfo ( PXENV_STATUS_FAILURE, 0x2f, 0, \
+                              "No locks available" )
 
-/** Reserved */
-#define ENOLINK                        ( ERRFILE | PXENV_STATUS_FAILURE | 0x30000000 )
+/** Link has been severed */
+#define ENOLINK __einfo_error ( EINFO_ENOLINK )
+#define EINFO_ENOLINK __einfo ( PXENV_STATUS_FAILURE, 0x30, 0, \
+                               "Link has been severed" )
 
 /** Not enough space */
-#define ENOMEM        ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x31000000 )
+#define ENOMEM __einfo_error ( EINFO_ENOMEM )
+#define EINFO_ENOMEM __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x31, 0, \
+                              "Not enough space" )
 
 /** No message of the desired type */
-#define ENOMSG                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x32000000 )
+#define ENOMSG __einfo_error ( EINFO_ENOMSG )
+#define EINFO_ENOMSG __einfo ( PXENV_STATUS_FAILURE, 0x32, 0, \
+                              "No message of the desired type" )
 
 /** Protocol not available */
-#define ENOPROTOOPT        ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x33000000 )
+#define ENOPROTOOPT __einfo_error ( EINFO_ENOPROTOOPT )
+#define EINFO_ENOPROTOOPT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x33, 0, \
+                                   "Protocol not available" )
 
 /** No space left on device */
-#define ENOSPC        ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x34000000 )
+#define ENOSPC __einfo_error ( EINFO_ENOSPC )
+#define EINFO_ENOSPC __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x34, 0, \
+                              "No space left on device" )
 
 /** No STREAM resources */
-#define ENOSR         ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x35000000 )
+#define ENOSR __einfo_error ( EINFO_ENOSR )
+#define EINFO_ENOSR __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x35, 0, \
+                             "No STREAM resources" )
 
 /** Not a STREAM */
-#define ENOSTR                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x36000000 )
+#define ENOSTR __einfo_error ( EINFO_ENOSTR )
+#define EINFO_ENOSTR __einfo ( PXENV_STATUS_FAILURE, 0x36, 0, \
+                              "Not a STREAM" )
 
 /** Function not implemented */
-#define ENOSYS             ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x37000000 )
+#define ENOSYS __einfo_error ( EINFO_ENOSYS )
+#define EINFO_ENOSYS __einfo ( PXENV_STATUS_UNSUPPORTED, 0x37, 0, \
+                              "Function not implemented" )
 
 /** The socket is not connected */
-#define ENOTCONN               ( ERRFILE | PXENV_STATUS_FAILURE | 0x38000000 )
+#define ENOTCONN __einfo_error ( EINFO_ENOTCONN )
+#define EINFO_ENOTCONN __einfo ( PXENV_STATUS_FAILURE, 0x38, 0, \
+                                "The socket is not connected" )
 
 /** Not a directory */
-#define ENOTDIR                        ( ERRFILE | PXENV_STATUS_FAILURE | 0x39000000 )
+#define ENOTDIR __einfo_error ( EINFO_ENOTDIR )
+#define EINFO_ENOTDIR __einfo ( PXENV_STATUS_FAILURE, 0x39, 0, \
+                               "Not a directory" )
 
 /** Directory not empty */
-#define ENOTEMPTY              ( ERRFILE | PXENV_STATUS_FAILURE | 0x3a000000 )
+#define ENOTEMPTY __einfo_error ( EINFO_ENOTEMPTY )
+#define EINFO_ENOTEMPTY __einfo ( PXENV_STATUS_FAILURE, 0x3a, 0, \
+                                 "Directory not empty" )
 
 /** Not a socket */
-#define ENOTSOCK               ( ERRFILE | PXENV_STATUS_FAILURE | 0x3b000000 )
+#define ENOTSOCK __einfo_error ( EINFO_ENOTSOCK )
+#define EINFO_ENOTSOCK __einfo ( PXENV_STATUS_FAILURE, 0x3b, 0, \
+                                "Not a socket" )
 
-/** Not supported */
-#define ENOTSUP                    ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x3c000000 )
+/** Operation not supported */
+#define ENOTSUP __einfo_error ( EINFO_ENOTSUP )
+#define EINFO_ENOTSUP __einfo ( PXENV_STATUS_UNSUPPORTED, 0x3c, 0, \
+                               "Operation not supported" )
 
 /** Inappropriate I/O control operation */
-#define ENOTTY                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x3d000000 )
+#define ENOTTY __einfo_error ( EINFO_ENOTTY )
+#define EINFO_ENOTTY __einfo ( PXENV_STATUS_FAILURE, 0x3d, 0, \
+                              "Inappropriate I/O control operation" )
 
 /** No such device or address */
-#define ENXIO      ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x3e000000 )
+#define ENXIO __einfo_error ( EINFO_ENXIO )
+#define EINFO_ENXIO __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x3e, 0, \
+                             "No such device or address" )
 
 /** Operation not supported on socket */
-#define EOPNOTSUPP         ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x3f000000 )
+#define EOPNOTSUPP __einfo_error ( EINFO_EOPNOTSUPP )
+#define EINFO_EOPNOTSUPP __einfo ( PXENV_STATUS_UNSUPPORTED, 0x3f, 0, \
+                                  "Operation not supported on socket" )
 
 /** Value too large to be stored in data type */
-#define EOVERFLOW              ( ERRFILE | PXENV_STATUS_FAILURE | 0x40000000 )
+#define EOVERFLOW __einfo_error ( EINFO_EOVERFLOW )
+#define EINFO_EOVERFLOW __einfo ( PXENV_STATUS_FAILURE, 0x40, 0, \
+                                 "Value too large to be stored in data type" )
 
 /** Operation not permitted */
-#define EPERM    ( ERRFILE | PXENV_STATUS_TFTP_ACCESS_VIOLATION | 0x41000000 )
+#define EPERM __einfo_error ( EINFO_EPERM )
+#define EINFO_EPERM __einfo ( PXENV_STATUS_TFTP_ACCESS_VIOLATION, 0x41, 0, \
+                             "Operation not permitted" )
 
 /** Broken pipe */
-#define EPIPE                  ( ERRFILE | PXENV_STATUS_FAILURE | 0x42000000 )
+#define EPIPE __einfo_error ( EINFO_EPIPE )
+#define EINFO_EPIPE __einfo ( PXENV_STATUS_FAILURE, 0x42, 0, \
+                             "Broken pipe" )
 
 /** Protocol error */
-#define EPROTO                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x43000000 )
+#define EPROTO __einfo_error ( EINFO_EPROTO )
+#define EINFO_EPROTO __einfo ( PXENV_STATUS_FAILURE, 0x43, 0, \
+                              "Protocol error" )
 
 /** Protocol not supported */
-#define EPROTONOSUPPORT            ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x44000000 )
+#define EPROTONOSUPPORT __einfo_error ( EINFO_EPROTONOSUPPORT )
+#define EINFO_EPROTONOSUPPORT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x44, 0, \
+                                       "Protocol not supported" )
 
 /** Protocol wrong type for socket */
-#define EPROTOTYPE             ( ERRFILE | PXENV_STATUS_FAILURE | 0x45000000 )
+#define EPROTOTYPE __einfo_error ( EINFO_EPROTOTYPE )
+#define EINFO_EPROTOTYPE __einfo ( PXENV_STATUS_FAILURE, 0x45, 0, \
+                                  "Protocol wrong type for socket" )
 
 /** Result too large */
-#define ERANGE                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x46000000 )
+#define ERANGE __einfo_error ( EINFO_ERANGE )
+#define EINFO_ERANGE __einfo ( PXENV_STATUS_FAILURE, 0x46, 0, \
+                              "Result too large" )
 
 /** Read-only file system */
-#define EROFS                  ( ERRFILE | PXENV_STATUS_FAILURE | 0x47000000 )
+#define EROFS __einfo_error ( EINFO_EROFS )
+#define EINFO_EROFS __einfo ( PXENV_STATUS_FAILURE, 0x47, 0, \
+                             "Read-only file system" )
 
 /** Invalid seek */
-#define ESPIPE                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x48000000 )
+#define ESPIPE __einfo_error ( EINFO_ESPIPE )
+#define EINFO_ESPIPE __einfo ( PXENV_STATUS_FAILURE, 0x48, 0, \
+                              "Invalid seek" )
 
 /** No such process */
-#define ESRCH      ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x49000000 )
+#define ESRCH __einfo_error ( EINFO_ESRCH )
+#define EINFO_ESRCH __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x49, 0, \
+                             "No such process" )
 
 /** Stale file handle */
-#define ESTALE                 ( ERRFILE | PXENV_STATUS_FAILURE | 0x4a000000 )
+#define ESTALE __einfo_error ( EINFO_ESTALE )
+#define EINFO_ESTALE __einfo ( PXENV_STATUS_FAILURE, 0x4a, 0, \
+                              "Stale file handle" )
 
-/** STREAM ioctl() timeout */
-#define ETIME                  ( ERRFILE | PXENV_STATUS_FAILURE | 0x4b000000 )
+/** Timer expired */
+#define ETIME __einfo_error ( EINFO_ETIME )
+#define EINFO_ETIME __einfo ( PXENV_STATUS_FAILURE, 0x4b, 0, \
+                             "Timer expired" )
 
-/** Operation timed out */
-#define ETIMEDOUT     ( ERRFILE | PXENV_STATUS_TFTP_READ_TIMEOUT | 0x4c000000 )
+/** Connection timed out */
+#define ETIMEDOUT __einfo_error ( EINFO_ETIMEDOUT )
+#define EINFO_ETIMEDOUT __einfo ( PXENV_STATUS_TFTP_READ_TIMEOUT, 0x4c, 0, \
+                                 "Connection timed out" )
 
 /** Text file busy */
-#define ETXTBSY                        ( ERRFILE | PXENV_STATUS_FAILURE | 0x4d000000 )
+#define ETXTBSY __einfo_error ( EINFO_ETXTBSY )
+#define EINFO_ETXTBSY __einfo ( PXENV_STATUS_FAILURE, 0x4d, 0, \
+                               "Text file busy" )
 
-/** Operation would block (different from EAGAIN!) */
-#define EWOULDBLOCK          ( ERRFILE | PXENV_STATUS_TFTP_OPEN | 0x4e000000 )
+/** Operation would block */
+#define EWOULDBLOCK __einfo_error ( EINFO_EWOULDBLOCK )
+#define EINFO_EWOULDBLOCK __einfo ( PXENV_STATUS_TFTP_OPEN, 0x4e, 0, \
+                                   "Operation would block" )
 
 /** Improper link */
-#define EXDEV                  ( ERRFILE | PXENV_STATUS_FAILURE | 0x4f000000 )
-
-/** @} */
-
-/**
- * @defgroup euniq Per-file error disambiguators
- *
- * Files which use the same error number multiple times should
- * probably define their own error subspace using these
- * disambiguators.  For example:
- *
- *     #define ETCP_HEADER_TOO_SHORT   EUNIQ_01
- *     #define ETCP_BAD_CHECKSUM       EUNIQ_02
- *
- * @{
- */
-
-#define EUNIQ_01       0x00000100
-#define EUNIQ_02       0x00000200
-#define EUNIQ_03       0x00000300
-#define EUNIQ_04       0x00000400
-#define EUNIQ_05       0x00000500
-#define EUNIQ_06       0x00000600
-#define EUNIQ_07       0x00000700
-#define EUNIQ_08       0x00000800
-#define EUNIQ_09       0x00000900
-#define EUNIQ_0A       0x00000a00
-#define EUNIQ_0B       0x00000b00
-#define EUNIQ_0C       0x00000c00
-#define EUNIQ_0D       0x00000d00
-#define EUNIQ_0E       0x00000e00
-#define EUNIQ_0F       0x00000f00
-#define EUNIQ_10       0x00001000
-#define EUNIQ_11       0x00001100
-#define EUNIQ_12       0x00001200
-#define EUNIQ_13       0x00001300
-#define EUNIQ_14       0x00001400
-#define EUNIQ_15       0x00001500
-#define EUNIQ_16       0x00001600
-#define EUNIQ_17       0x00001700
-#define EUNIQ_18       0x00001800
-#define EUNIQ_19       0x00001900
-#define EUNIQ_1A       0x00001a00
-#define EUNIQ_1B       0x00001b00
-#define EUNIQ_1C       0x00001c00
-#define EUNIQ_1D       0x00001d00
-#define EUNIQ_1E       0x00001e00
-#define EUNIQ_1F       0x00001f00
+#define EXDEV __einfo_error ( EINFO_EXDEV )
+#define EINFO_EXDEV __einfo ( PXENV_STATUS_FAILURE, 0x4f, 0, \
+                             "Improper link" )
 
 /** @} */
 
index 35765d4..84e7dab 100644 (file)
@@ -20,4 +20,9 @@ struct errortab {
 
 #define __errortab __table_entry ( ERRORTAB, 01 )
 
+#define __einfo_errortab( einfo ) {                    \
+       .errno = __einfo_errno ( einfo ),               \
+       .text = __einfo_desc ( einfo ),                 \
+       }
+
 #endif /* _GPXE_ERRORTAB_H */
index e5b10c3..802ff5a 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _GPXE_IEEE80211_H
 #define _GPXE_IEEE80211_H
 
+#include <stddef.h>
 #include <gpxe/if_ether.h>     /* for ETH_ALEN */
 #include <endian.h>
 
diff --git a/src/include/gpxe/net80211_err.h b/src/include/gpxe/net80211_err.h
new file mode 100644 (file)
index 0000000..ff6f1e7
--- /dev/null
@@ -0,0 +1,633 @@
+#ifndef _GPXE_NET80211_ERR_H
+#define _GPXE_NET80211_ERR_H
+
+#include <errno.h>
+#include <gpxe/ieee80211.h>
+
+/*
+ * The gPXE 802.11 MAC layer.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * The gPXE 802.11 MAC layer errors.
+ */
+
+/* Disambiguate the EINVAL's a bit */
+#define EINVAL_PKT_TOO_SHORT __einfo_error ( EINFO_EINVAL_PKT_TOO_SHORT )
+#define EINFO_EINVAL_PKT_TOO_SHORT __einfo_uniqify \
+       ( EINFO_EINVAL, 0x01, "Packet too short" )
+#define EINVAL_PKT_VERSION __einfo_error ( EINFO_EINVAL_PKT_VERSION )
+#define EINFO_EINVAL_PKT_VERSION __einfo_uniqify \
+       ( EINFO_EINVAL, 0x02, "Packet 802.11 version not supported" )
+#define EINVAL_PKT_NOT_DATA __einfo_error ( EINFO_EINVAL_PKT_NOT_DATA )
+#define EINFO_EINVAL_PKT_NOT_DATA __einfo_uniqify \
+       ( EINFO_EINVAL, 0x03, "Packet not a data packet" )
+#define EINVAL_PKT_NOT_FROMDS __einfo_error ( EINFO_EINVAL_PKT_NOT_FROMDS )
+#define EINFO_EINVAL_PKT_NOT_FROMDS __einfo_uniqify \
+       ( EINFO_EINVAL, 0x04, "Packet not from an Access Point" )
+#define EINVAL_PKT_LLC_HEADER __einfo_error ( EINFO_EINVAL_PKT_LLC_HEADER )
+#define EINFO_EINVAL_PKT_LLC_HEADER __einfo_uniqify \
+       ( EINFO_EINVAL, 0x05, "Packet has invalid LLC header" )
+#define EINVAL_CRYPTO_REQUEST __einfo_error ( EINFO_EINVAL_CRYPTO_REQUEST )
+#define EINFO_EINVAL_CRYPTO_REQUEST __einfo_uniqify \
+       ( EINFO_EINVAL, 0x06, "Packet decryption error" )
+#define EINVAL_ACTIVE_SCAN __einfo_error ( EINFO_EINVAL_ACTIVE_SCAN )
+#define EINFO_EINVAL_ACTIVE_SCAN __einfo_uniqify \
+       ( EINFO_EINVAL, 0x07, "Invalid active scan requested" )
+
+/*
+ * 802.11 error codes: The AP can give us a status code explaining why
+ * authentication failed, or a reason code explaining why we were
+ * deauthenticated/disassociated. These codes range from 0-63 (the
+ * field is 16 bits wide, but only up to 45 or so are defined yet; we
+ * allow up to 63 for extensibility). This is encoded into an error
+ * code as such:
+ *
+ *                                      status & 0x1f goes here --vv--
+ *   Status code 0-31:  ECONNREFUSED | EUNIQ_(status & 0x1f) (0e1a6038)
+ *   Status code 32-63: EHOSTUNREACH | EUNIQ_(status & 0x1f) (171a6011)
+ *   Reason code 0-31:  ECONNRESET | EUNIQ_(reason & 0x1f)   (0f1a6039)
+ *   Reason code 32-63: ENETRESET | EUNIQ_(reason & 0x1f)    (271a6001)
+ *
+ * The POSIX error codes more or less convey the appropriate message
+ * (status codes occur when we can't associate at all, reason codes
+ * when we lose association unexpectedly) and let us extract the
+ * complete 802.11 error code from the rc value.
+ *
+ * The error messages follow the 802.11 standard as much as is
+ * feasible, but most have been abbreviated to fit the 50-character
+ * limit imposed by strerror().
+ */
+
+/* 802.11 status codes (IEEE Std 802.11-2007, Table 7-23) */
+
+#define ECONNREFUSED_FAILURE __einfo_error                             \
+       ( EINFO_ECONNREFUSED_FAILURE )
+#define EINFO_ECONNREFUSED_FAILURE __einfo_uniqify                     \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_FAILURE & 0x1f ),                          \
+         "Unspecified failure" )
+
+#define ECONNREFUSED_CAPAB_UNSUPP __einfo_error                                \
+       ( EINFO_ECONNREFUSED_CAPAB_UNSUPP )
+#define EINFO_ECONNREFUSED_CAPAB_UNSUPP __einfo_uniqify                        \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_CAPAB_UNSUPP & 0x1f ),                     \
+         "Cannot support all requested capabilities" )
+
+#define ECONNREFUSED_REASSOC_INVALID __einfo_error                     \
+       ( EINFO_ECONNREFUSED_REASSOC_INVALID )
+#define EINFO_ECONNREFUSED_REASSOC_INVALID __einfo_uniqify             \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_REASSOC_INVALID & 0x1f ),                  \
+         "Reassociation denied due to lack of association" )
+
+#define ECONNREFUSED_ASSOC_DENIED __einfo_error                                \
+       ( EINFO_ECONNREFUSED_ASSOC_DENIED )
+#define EINFO_ECONNREFUSED_ASSOC_DENIED __einfo_uniqify                        \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_DENIED & 0x1f ),                     \
+         "Association denied for another reason" )
+
+#define ECONNREFUSED_AUTH_ALGO_UNSUPP __einfo_error                    \
+       ( EINFO_ECONNREFUSED_AUTH_ALGO_UNSUPP )
+#define EINFO_ECONNREFUSED_AUTH_ALGO_UNSUPP __einfo_uniqify            \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_AUTH_ALGO_UNSUPP & 0x1f ),                 \
+         "Authentication algorithm unsupported" )
+
+#define ECONNREFUSED_AUTH_SEQ_INVALID __einfo_error                    \
+       ( EINFO_ECONNREFUSED_AUTH_SEQ_INVALID )
+#define EINFO_ECONNREFUSED_AUTH_SEQ_INVALID __einfo_uniqify            \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_AUTH_SEQ_INVALID & 0x1f ),                 \
+         "Authentication sequence number unexpected" )
+
+#define ECONNREFUSED_AUTH_CHALL_INVALID __einfo_error                  \
+       ( EINFO_ECONNREFUSED_AUTH_CHALL_INVALID )
+#define EINFO_ECONNREFUSED_AUTH_CHALL_INVALID __einfo_uniqify          \
+       ( EINFO_ECONNREFUSED,                                   \
+         ( IEEE80211_STATUS_AUTH_CHALL_INVALID & 0x1f ),               \
+         "Authentication rejected due to challenge failure" )
+
+#define ECONNREFUSED_AUTH_TIMEOUT __einfo_error                                \
+       ( EINFO_ECONNREFUSED_AUTH_TIMEOUT )
+#define EINFO_ECONNREFUSED_AUTH_TIMEOUT __einfo_uniqify                        \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_AUTH_TIMEOUT & 0x1f ),                     \
+         "Authentication rejected due to timeout" )
+
+#define ECONNREFUSED_ASSOC_NO_ROOM __einfo_error                       \
+       ( EINFO_ECONNREFUSED_ASSOC_NO_ROOM )
+#define EINFO_ECONNREFUSED_ASSOC_NO_ROOM __einfo_uniqify               \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_NO_ROOM & 0x1f ),                    \
+         "Association denied because AP is out of resources" )
+
+#define ECONNREFUSED_ASSOC_NEED_RATE __einfo_error                     \
+       ( EINFO_ECONNREFUSED_ASSOC_NEED_RATE )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_RATE __einfo_uniqify             \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_NEED_RATE & 0x1f ),                  \
+         "Association denied; basic rate support required" )
+
+#define ECONNREFUSED_ASSOC_NEED_SHORT_PMBL __einfo_error               \
+       ( EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_PMBL )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_PMBL __einfo_uniqify       \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_NEED_SHORT_PMBL & 0x1f ),            \
+         "Association denied; short preamble support req'd" )
+
+#define ECONNREFUSED_ASSOC_NEED_PBCC __einfo_error                     \
+       ( EINFO_ECONNREFUSED_ASSOC_NEED_PBCC )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_PBCC __einfo_uniqify             \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_NEED_PBCC & 0x1f ),                  \
+         "Association denied; PBCC modulation support req'd" )
+
+#define ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY __einfo_error             \
+       ( EINFO_ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY __einfo_uniqify     \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_NEED_CHAN_AGILITY & 0x1f ),          \
+         "Association denied; Channel Agility support req'd" )
+
+#define ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT __einfo_error            \
+       ( EINFO_ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT __einfo_uniqify    \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_NEED_SPECTRUM_MGMT & 0x1f ),         \
+         "Association denied; Spectrum Management required" )
+
+#define ECONNREFUSED_ASSOC_BAD_POWER __einfo_error                     \
+       ( EINFO_ECONNREFUSED_ASSOC_BAD_POWER )
+#define EINFO_ECONNREFUSED_ASSOC_BAD_POWER __einfo_uniqify             \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_BAD_POWER & 0x1f ),                  \
+         "Association denied; Power Capability unacceptable" )
+
+#define ECONNREFUSED_ASSOC_BAD_CHANNELS __einfo_error                  \
+       ( EINFO_ECONNREFUSED_ASSOC_BAD_CHANNELS )
+#define EINFO_ECONNREFUSED_ASSOC_BAD_CHANNELS __einfo_uniqify          \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_BAD_CHANNELS & 0x1f ),               \
+         "Association denied; Supported Channels unacceptable" )
+
+#define ECONNREFUSED_ASSOC_NEED_SHORT_SLOT __einfo_error               \
+       ( EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_SLOT )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_SHORT_SLOT __einfo_uniqify       \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_NEED_SHORT_SLOT & 0x1f ),            \
+         "Association denied; Short Slot Tume support req'd" )
+
+#define ECONNREFUSED_ASSOC_NEED_DSSS_OFDM __einfo_error                        \
+       ( EINFO_ECONNREFUSED_ASSOC_NEED_DSSS_OFDM )
+#define EINFO_ECONNREFUSED_ASSOC_NEED_DSSS_OFDM __einfo_uniqify                \
+       ( EINFO_ECONNREFUSED,                                           \
+         ( IEEE80211_STATUS_ASSOC_NEED_DSSS_OFDM & 0x1f ),             \
+         "Association denied; DSSS-OFDM support required" )
+
+#define EHOSTUNREACH_QOS_FAILURE __einfo_error                         \
+       ( EINFO_EHOSTUNREACH_QOS_FAILURE )
+#define EINFO_EHOSTUNREACH_QOS_FAILURE __einfo_uniqify                 \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_QOS_FAILURE & 0x1f ),                      \
+         "Unspecified, QoS-related failure" )
+
+#define EHOSTUNREACH_QOS_NO_ROOM __einfo_error                         \
+       ( EINFO_EHOSTUNREACH_QOS_NO_ROOM )
+#define EINFO_EHOSTUNREACH_QOS_NO_ROOM __einfo_uniqify                 \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_QOS_NO_ROOM & 0x1f ),                      \
+         "Association denied; QoS AP out of QoS resources" )
+
+#define EHOSTUNREACH_LINK_IS_HORRIBLE __einfo_error                    \
+       ( EINFO_EHOSTUNREACH_LINK_IS_HORRIBLE )
+#define EINFO_EHOSTUNREACH_LINK_IS_HORRIBLE __einfo_uniqify            \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_LINK_IS_HORRIBLE & 0x1f ),                 \
+         "Association denied due to excessively poor link" )
+
+#define EHOSTUNREACH_ASSOC_NEED_QOS __einfo_error                      \
+       ( EINFO_EHOSTUNREACH_ASSOC_NEED_QOS )
+#define EINFO_EHOSTUNREACH_ASSOC_NEED_QOS __einfo_uniqify              \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_ASSOC_NEED_QOS & 0x1f ),                   \
+         "Association denied; QoS support required" )
+
+#define EHOSTUNREACH_REQUEST_DECLINED __einfo_error                    \
+       ( EINFO_EHOSTUNREACH_REQUEST_DECLINED )
+#define EINFO_EHOSTUNREACH_REQUEST_DECLINED __einfo_uniqify            \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_REQUEST_DECLINED & 0x1f ),                 \
+         "The request has been declined" )
+
+#define EHOSTUNREACH_REQUEST_INVALID __einfo_error                     \
+       ( EINFO_EHOSTUNREACH_REQUEST_INVALID )
+#define EINFO_EHOSTUNREACH_REQUEST_INVALID __einfo_uniqify             \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_REQUEST_INVALID & 0x1f ),                  \
+         "Request unsuccessful due to invalid parameters" )
+
+#define EHOSTUNREACH_TS_NOT_CREATED_AGAIN __einfo_error                        \
+       ( EINFO_EHOSTUNREACH_TS_NOT_CREATED_AGAIN )
+#define EINFO_EHOSTUNREACH_TS_NOT_CREATED_AGAIN __einfo_uniqify                \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_TS_NOT_CREATED_AGAIN & 0x1f ),             \
+         "TS not created due to bad specification" )
+
+#define EHOSTUNREACH_INVALID_IE __einfo_error                          \
+       ( EINFO_EHOSTUNREACH_INVALID_IE )
+#define EINFO_EHOSTUNREACH_INVALID_IE __einfo_uniqify                  \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_INVALID_IE & 0x1f ),                       \
+         "Invalid information element" )
+
+#define EHOSTUNREACH_GROUP_CIPHER_INVALID __einfo_error                        \
+       ( EINFO_EHOSTUNREACH_GROUP_CIPHER_INVALID )
+#define EINFO_EHOSTUNREACH_GROUP_CIPHER_INVALID __einfo_uniqify                \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_GROUP_CIPHER_INVALID & 0x1f ),             \
+         "Invalid group cipher" )
+
+#define EHOSTUNREACH_PAIR_CIPHER_INVALID __einfo_error                 \
+       ( EINFO_EHOSTUNREACH_PAIR_CIPHER_INVALID )
+#define EINFO_EHOSTUNREACH_PAIR_CIPHER_INVALID __einfo_uniqify         \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_PAIR_CIPHER_INVALID & 0x1f ),              \
+         "Invalid pairwise cipher" )
+
+#define EHOSTUNREACH_AKMP_INVALID __einfo_error                                \
+       ( EINFO_EHOSTUNREACH_AKMP_INVALID )
+#define EINFO_EHOSTUNREACH_AKMP_INVALID __einfo_uniqify                        \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_AKMP_INVALID & 0x1f ),                     \
+         "Invalid AKMP" )
+
+#define EHOSTUNREACH_RSN_VERSION_UNSUPP __einfo_error                  \
+       ( EINFO_EHOSTUNREACH_RSN_VERSION_UNSUPP )
+#define EINFO_EHOSTUNREACH_RSN_VERSION_UNSUPP __einfo_uniqify          \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_RSN_VERSION_UNSUPP & 0x1f ),               \
+         "Unsupported RSN information element version" )
+
+#define EHOSTUNREACH_RSN_CAPAB_INVALID __einfo_error                   \
+       ( EINFO_EHOSTUNREACH_RSN_CAPAB_INVALID )
+#define EINFO_EHOSTUNREACH_RSN_CAPAB_INVALID __einfo_uniqify           \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_RSN_CAPAB_INVALID & 0x1f ),                \
+         "Invalid RSN information element capabilities" )
+
+#define EHOSTUNREACH_CIPHER_REJECTED __einfo_error                     \
+       ( EINFO_EHOSTUNREACH_CIPHER_REJECTED )
+#define EINFO_EHOSTUNREACH_CIPHER_REJECTED __einfo_uniqify             \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_CIPHER_REJECTED & 0x1f ),                  \
+         "Cipher suite rejected because of security policy" )
+
+#define EHOSTUNREACH_TS_NOT_CREATED_WAIT __einfo_error                 \
+       ( EINFO_EHOSTUNREACH_TS_NOT_CREATED_WAIT )
+#define EINFO_EHOSTUNREACH_TS_NOT_CREATED_WAIT __einfo_uniqify         \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_TS_NOT_CREATED_WAIT & 0x1f ),              \
+         "TS not created due to insufficient delay" )
+
+#define EHOSTUNREACH_DIRECT_LINK_FORBIDDEN __einfo_error               \
+       ( EINFO_EHOSTUNREACH_DIRECT_LINK_FORBIDDEN )
+#define EINFO_EHOSTUNREACH_DIRECT_LINK_FORBIDDEN __einfo_uniqify       \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_DIRECT_LINK_FORBIDDEN & 0x1f ),            \
+         "Direct link is not allowed in the BSS by policy" )
+
+#define EHOSTUNREACH_DEST_NOT_PRESENT __einfo_error                    \
+       ( EINFO_EHOSTUNREACH_DEST_NOT_PRESENT )
+#define EINFO_EHOSTUNREACH_DEST_NOT_PRESENT __einfo_uniqify            \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_DEST_NOT_PRESENT & 0x1f ),                 \
+         "The Destination STA is not present within the BSS" )
+
+#define EHOSTUNREACH_DEST_NOT_QOS __einfo_error                                \
+       ( EINFO_EHOSTUNREACH_DEST_NOT_QOS )
+#define EINFO_EHOSTUNREACH_DEST_NOT_QOS __einfo_uniqify                        \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_DEST_NOT_QOS & 0x1f ),                     \
+         "The Destination STA is not a QoS STA" )
+
+#define EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH __einfo_error               \
+       ( EINFO_EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH )
+#define EINFO_EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH __einfo_uniqify       \
+       ( EINFO_EHOSTUNREACH,                                           \
+         ( IEEE80211_STATUS_ASSOC_LISTEN_TOO_HIGH & 0x1f ),            \
+         "Association denied; Listen Interval is too large" )
+
+/* 802.11 reason codes (IEEE Std 802.11-2007, Table 7-22) */
+
+#define ECONNRESET_UNSPECIFIED __einfo_error                           \
+       ( EINFO_ECONNRESET_UNSPECIFIED )
+#define EINFO_ECONNRESET_UNSPECIFIED __einfo_uniqify                   \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_UNSPECIFIED & 0x1f ),                      \
+         "Unspecified reason" )
+
+#define ECONNRESET_AUTH_NO_LONGER_VALID __einfo_error                  \
+       ( EINFO_ECONNRESET_AUTH_NO_LONGER_VALID )
+#define EINFO_ECONNRESET_AUTH_NO_LONGER_VALID __einfo_uniqify          \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_AUTH_NO_LONGER_VALID & 0x1f ),             \
+         "Previous authentication no longer valid" )
+
+#define ECONNRESET_LEAVING __einfo_error                               \
+       ( EINFO_ECONNRESET_LEAVING )
+#define EINFO_ECONNRESET_LEAVING __einfo_uniqify                       \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_LEAVING & 0x1f ),                          \
+         "Deauthenticated due to leaving network" )
+
+#define ECONNRESET_INACTIVITY __einfo_error                            \
+       ( EINFO_ECONNRESET_INACTIVITY )
+#define EINFO_ECONNRESET_INACTIVITY __einfo_uniqify                    \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_INACTIVITY & 0x1f ),                       \
+         "Disassociated due to inactivity" )
+
+#define ECONNRESET_OUT_OF_RESOURCES __einfo_error                      \
+       ( EINFO_ECONNRESET_OUT_OF_RESOURCES )
+#define EINFO_ECONNRESET_OUT_OF_RESOURCES __einfo_uniqify              \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_OUT_OF_RESOURCES & 0x1f ),                 \
+         "Disassociated because AP is out of resources" )
+
+#define ECONNRESET_NEED_AUTH __einfo_error                             \
+       ( EINFO_ECONNRESET_NEED_AUTH )
+#define EINFO_ECONNRESET_NEED_AUTH __einfo_uniqify                     \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_NEED_AUTH & 0x1f ),                        \
+         "Class 2 frame received from nonauthenticated STA" )
+
+#define ECONNRESET_NEED_ASSOC __einfo_error                            \
+       ( EINFO_ECONNRESET_NEED_ASSOC )
+#define EINFO_ECONNRESET_NEED_ASSOC __einfo_uniqify                    \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_NEED_ASSOC & 0x1f ),                       \
+         "Class 3 frame received from nonassociated STA" )
+
+#define ECONNRESET_LEAVING_TO_ROAM __einfo_error                       \
+       ( EINFO_ECONNRESET_LEAVING_TO_ROAM )
+#define EINFO_ECONNRESET_LEAVING_TO_ROAM __einfo_uniqify               \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_LEAVING_TO_ROAM & 0x1f ),                  \
+         "Disassociated due to roaming" )
+
+#define ECONNRESET_REASSOC_INVALID __einfo_error                       \
+       ( EINFO_ECONNRESET_REASSOC_INVALID )
+#define EINFO_ECONNRESET_REASSOC_INVALID __einfo_uniqify               \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_REASSOC_INVALID & 0x1f ),                  \
+         "STA requesting (re)association not authenticated" )
+
+#define ECONNRESET_BAD_POWER __einfo_error                             \
+       ( EINFO_ECONNRESET_BAD_POWER )
+#define EINFO_ECONNRESET_BAD_POWER __einfo_uniqify                     \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_BAD_POWER & 0x1f ),                        \
+         "Disassociated; Power Capability unacceptable" )
+
+#define ECONNRESET_BAD_CHANNELS __einfo_error                          \
+       ( EINFO_ECONNRESET_BAD_CHANNELS )
+#define EINFO_ECONNRESET_BAD_CHANNELS __einfo_uniqify                  \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_BAD_CHANNELS & 0x1f ),                     \
+         "Disassociated; Supported Channels unacceptable" )
+
+#define ECONNRESET_INVALID_IE __einfo_error                            \
+       ( EINFO_ECONNRESET_INVALID_IE )
+#define EINFO_ECONNRESET_INVALID_IE __einfo_uniqify                    \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_INVALID_IE & 0x1f ),                       \
+         "Invalid information element" )
+
+#define ECONNRESET_MIC_FAILURE __einfo_error                           \
+       ( EINFO_ECONNRESET_MIC_FAILURE )
+#define EINFO_ECONNRESET_MIC_FAILURE __einfo_uniqify                   \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_MIC_FAILURE & 0x1f ),                      \
+         "Message integrity code (MIC) failure" )
+
+#define ECONNRESET_4WAY_TIMEOUT __einfo_error                          \
+       ( EINFO_ECONNRESET_4WAY_TIMEOUT )
+#define EINFO_ECONNRESET_4WAY_TIMEOUT __einfo_uniqify                  \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_4WAY_TIMEOUT & 0x1f ),                     \
+         "4-Way Handshake timeout" )
+
+#define ECONNRESET_GROUPKEY_TIMEOUT __einfo_error                      \
+       ( EINFO_ECONNRESET_GROUPKEY_TIMEOUT )
+#define EINFO_ECONNRESET_GROUPKEY_TIMEOUT __einfo_uniqify              \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_GROUPKEY_TIMEOUT & 0x1f ),                 \
+         "Group Key Handshake timeout" )
+
+#define ECONNRESET_4WAY_INVALID __einfo_error                          \
+       ( EINFO_ECONNRESET_4WAY_INVALID )
+#define EINFO_ECONNRESET_4WAY_INVALID __einfo_uniqify                  \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_4WAY_INVALID & 0x1f ),                     \
+         "4-Way Handshake information element changed unduly" )
+
+#define ECONNRESET_GROUP_CIPHER_INVALID __einfo_error                  \
+       ( EINFO_ECONNRESET_GROUP_CIPHER_INVALID )
+#define EINFO_ECONNRESET_GROUP_CIPHER_INVALID __einfo_uniqify          \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_GROUP_CIPHER_INVALID & 0x1f ),             \
+         "Invalid group cipher" )
+
+#define ECONNRESET_PAIR_CIPHER_INVALID __einfo_error                   \
+       ( EINFO_ECONNRESET_PAIR_CIPHER_INVALID )
+#define EINFO_ECONNRESET_PAIR_CIPHER_INVALID __einfo_uniqify           \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_PAIR_CIPHER_INVALID & 0x1f ),              \
+         "Invalid pairwise cipher" )
+
+#define ECONNRESET_AKMP_INVALID __einfo_error                          \
+       ( EINFO_ECONNRESET_AKMP_INVALID )
+#define EINFO_ECONNRESET_AKMP_INVALID __einfo_uniqify                  \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_AKMP_INVALID & 0x1f ),                     \
+         "Invalid AKMP" )
+
+#define ECONNRESET_RSN_VERSION_INVALID __einfo_error                   \
+       ( EINFO_ECONNRESET_RSN_VERSION_INVALID )
+#define EINFO_ECONNRESET_RSN_VERSION_INVALID __einfo_uniqify           \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_RSN_VERSION_INVALID & 0x1f ),              \
+         "Unsupported RSN information element version" )
+
+#define ECONNRESET_RSN_CAPAB_INVALID __einfo_error                     \
+       ( EINFO_ECONNRESET_RSN_CAPAB_INVALID )
+#define EINFO_ECONNRESET_RSN_CAPAB_INVALID __einfo_uniqify             \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_RSN_CAPAB_INVALID & 0x1f ),                \
+         "Invalid RSN information element capabilities" )
+
+#define ECONNRESET_8021X_FAILURE __einfo_error                         \
+       ( EINFO_ECONNRESET_8021X_FAILURE )
+#define EINFO_ECONNRESET_8021X_FAILURE __einfo_uniqify                 \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_8021X_FAILURE & 0x1f ),                    \
+         "IEEE 802.1X authentication failed" )
+
+#define ECONNRESET_CIPHER_REJECTED __einfo_error                       \
+       ( EINFO_ECONNRESET_CIPHER_REJECTED )
+#define EINFO_ECONNRESET_CIPHER_REJECTED __einfo_uniqify               \
+       ( EINFO_ECONNRESET,                                             \
+         ( IEEE80211_REASON_CIPHER_REJECTED & 0x1f ),                  \
+         "Cipher suite rejected because of security policy" )
+
+#define ENETRESET_QOS_UNSPECIFIED __einfo_error                                \
+       ( EINFO_ENETRESET_QOS_UNSPECIFIED )
+#define EINFO_ENETRESET_QOS_UNSPECIFIED __einfo_uniqify                        \
+       ( EINFO_ENETRESET,                                              \
+         ( IEEE80211_REASON_QOS_UNSPECIFIED & 0x1f ),                  \
+         "Disassociated for unspecified, QoS-related reason" )
+
+#define ENETRESET_QOS_OUT_OF_RESOURCES __einfo_error                   \
+       ( EINFO_ENETRESET_QOS_OUT_OF_RESOURCES )
+#define EINFO_ENETRESET_QOS_OUT_OF_RESOURCES __einfo_uniqify           \
+       ( EINFO_ENETRESET,                                              \
+         ( IEEE80211_REASON_QOS_OUT_OF_RESOURCES & 0x1f ),             \
+         "Disassociated; QoS AP is out of QoS resources" )
+
+#define ENETRESET_LINK_IS_HORRIBLE __einfo_error                       \
+       ( EINFO_ENETRESET_LINK_IS_HORRIBLE )
+#define EINFO_ENETRESET_LINK_IS_HORRIBLE __einfo_uniqify               \
+       ( EINFO_ENETRESET,                                              \
+         ( IEEE80211_REASON_LINK_IS_HORRIBLE & 0x1f ),                 \
+         "Disassociated due to excessively poor link" )
+
+#define ENETRESET_INVALID_TXOP __einfo_error                           \
+       ( EINFO_ENETRESET_INVALID_TXOP )
+#define EINFO_ENETRESET_INVALID_TXOP __einfo_uniqify                   \
+       ( EINFO_ENETRESET,                                              \
+         ( IEEE80211_REASON_INVALID_TXOP & 0x1f ),                     \
+         "Disassociated due to TXOP limit violation" )
+
+#define ENETRESET_REQUESTED_LEAVING __einfo_error                      \
+       ( EINFO_ENETRESET_REQUESTED_LEAVING )
+#define EINFO_ENETRESET_REQUESTED_LEAVING __einfo_uniqify              \
+       ( EINFO_ENETRESET,                                              \
+         ( IEEE80211_REASON_REQUESTED_LEAVING & 0x1f ),                \
+         "Requested; STA is leaving the BSS (or resetting)" )
+
+#define ENETRESET_REQUESTED_NO_USE __einfo_error                       \
+       ( EINFO_ENETRESET_REQUESTED_NO_USE )
+#define EINFO_ENETRESET_REQUESTED_NO_USE __einfo_uniqify               \
+       ( EINFO_ENETRESET,                                              \
+         ( IEEE80211_REASON_REQUESTED_NO_USE & 0x1f ),                 \
+         "Requested; does not want to use the mechanism" )
+
+#define ENETRESET_REQUESTED_NEED_SETUP __einfo_error                   \
+       ( EINFO_ENETRESET_REQUESTED_NEED_SETUP )
+#define EINFO_ENETRESET_REQUESTED_NEED_SETUP __einfo_uniqify           \
+       ( EINFO_ENETRESET,                                              \
+         ( IEEE80211_REASON_REQUESTED_NEED_SETUP & 0x1f ),             \
+         "Requested; setup is required" )
+
+#define ENETRESET_REQUESTED_TIMEOUT __einfo_error                      \
+       ( EINFO_ENETRESET_REQUESTED_TIMEOUT )
+#define EINFO_ENETRESET_REQUESTED_TIMEOUT __einfo_uniqify              \
+       ( EINFO_ENETRESET,                                              \
+         ( IEEE80211_REASON_REQUESTED_TIMEOUT & 0x1f ),                \
+         "Requested from peer STA due to timeout" )
+
+#define ENETRESET_CIPHER_UNSUPPORTED __einfo_error                     \
+       ( EINFO_ENETRESET_CIPHER_UNSUPPORTED )
+#define EINFO_ENETRESET_CIPHER_UNSUPPORTED __einfo_uniqify             \
+       ( EINFO_ENETRESET,                                              \
+         ( IEEE80211_REASON_CIPHER_UNSUPPORTED & 0x1f ),               \
+         "Peer STA does not support requested cipher suite" )
+
+/** Make return status code from 802.11 status code */
+#define E80211_STATUS( stat )                                          \
+       EUNIQ ( ( ( stat & 0x20 ) ? EHOSTUNREACH : ECONNREFUSED ),      \
+               ( stat &0x1f ),                                         \
+               ECONNREFUSED_FAILURE,                                   \
+               ECONNREFUSED_CAPAB_UNSUPP,                              \
+               ECONNREFUSED_REASSOC_INVALID,                           \
+               ECONNREFUSED_ASSOC_DENIED,                              \
+               ECONNREFUSED_AUTH_ALGO_UNSUPP,                          \
+               ECONNREFUSED_AUTH_SEQ_INVALID,                          \
+               ECONNREFUSED_AUTH_CHALL_INVALID,                        \
+               ECONNREFUSED_AUTH_TIMEOUT,                              \
+               ECONNREFUSED_ASSOC_NO_ROOM,                             \
+               ECONNREFUSED_ASSOC_NEED_RATE,                           \
+               ECONNREFUSED_ASSOC_NEED_SHORT_PMBL,                     \
+               ECONNREFUSED_ASSOC_NEED_PBCC,                           \
+               ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY,                   \
+               ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT,                  \
+               ECONNREFUSED_ASSOC_BAD_POWER,                           \
+               ECONNREFUSED_ASSOC_BAD_CHANNELS,                        \
+               ECONNREFUSED_ASSOC_NEED_SHORT_SLOT,                     \
+               ECONNREFUSED_ASSOC_NEED_DSSS_OFDM,                      \
+               EHOSTUNREACH_QOS_FAILURE,                               \
+               EHOSTUNREACH_QOS_NO_ROOM,                               \
+               EHOSTUNREACH_LINK_IS_HORRIBLE,                          \
+               EHOSTUNREACH_ASSOC_NEED_QOS,                            \
+               EHOSTUNREACH_REQUEST_DECLINED,                          \
+               EHOSTUNREACH_REQUEST_INVALID,                           \
+               EHOSTUNREACH_TS_NOT_CREATED_AGAIN,                      \
+               EHOSTUNREACH_INVALID_IE,                                \
+               EHOSTUNREACH_GROUP_CIPHER_INVALID,                      \
+               EHOSTUNREACH_PAIR_CIPHER_INVALID,                       \
+               EHOSTUNREACH_AKMP_INVALID,                              \
+               EHOSTUNREACH_RSN_VERSION_UNSUPP,                        \
+               EHOSTUNREACH_RSN_CAPAB_INVALID,                         \
+               EHOSTUNREACH_CIPHER_REJECTED,                           \
+               EHOSTUNREACH_TS_NOT_CREATED_WAIT,                       \
+               EHOSTUNREACH_DIRECT_LINK_FORBIDDEN,                     \
+               EHOSTUNREACH_DEST_NOT_PRESENT,                          \
+               EHOSTUNREACH_DEST_NOT_QOS,                              \
+               EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH )
+
+/** Make return status code from 802.11 reason code */
+#define E80211_REASON( reas )                                          \
+       EUNIQ ( ( ( reas & 0x20 ) ? ENETRESET : ECONNRESET ),           \
+               ( reas & 0x1f ),                                        \
+               ECONNRESET_UNSPECIFIED,                                 \
+               ECONNRESET_AUTH_NO_LONGER_VALID,                        \
+               ECONNRESET_LEAVING,                                     \
+               ECONNRESET_INACTIVITY,                                  \
+               ECONNRESET_OUT_OF_RESOURCES,                            \
+               ECONNRESET_NEED_AUTH,                                   \
+               ECONNRESET_NEED_ASSOC,                                  \
+               ECONNRESET_LEAVING_TO_ROAM,                             \
+               ECONNRESET_REASSOC_INVALID,                             \
+               ECONNRESET_BAD_POWER,                                   \
+               ECONNRESET_BAD_CHANNELS,                                \
+               ECONNRESET_INVALID_IE,                                  \
+               ECONNRESET_MIC_FAILURE,                                 \
+               ECONNRESET_4WAY_TIMEOUT,                                \
+               ECONNRESET_GROUPKEY_TIMEOUT,                            \
+               ECONNRESET_4WAY_INVALID,                                \
+               ECONNRESET_GROUP_CIPHER_INVALID,                        \
+               ECONNRESET_PAIR_CIPHER_INVALID,                         \
+               ECONNRESET_AKMP_INVALID,                                \
+               ECONNRESET_RSN_VERSION_INVALID,                         \
+               ECONNRESET_RSN_CAPAB_INVALID,                           \
+               ECONNRESET_8021X_FAILURE,                               \
+               ECONNRESET_CIPHER_REJECTED,                             \
+               ENETRESET_QOS_UNSPECIFIED,                              \
+               ENETRESET_QOS_OUT_OF_RESOURCES,                         \
+               ENETRESET_LINK_IS_HORRIBLE,                             \
+               ENETRESET_INVALID_TXOP,                                 \
+               ENETRESET_REQUESTED_LEAVING,                            \
+               ENETRESET_REQUESTED_NO_USE,                             \
+               ENETRESET_REQUESTED_NEED_SETUP,                         \
+               ENETRESET_REQUESTED_TIMEOUT,                            \
+               ENETRESET_CIPHER_UNSUPPORTED )
+
+#endif /* _GPXE_NET80211_ERR_H */
index 9baaaec..87c7b3d 100644 (file)
@@ -23,6 +23,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <string.h>
 #include <byteswap.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
 #include <gpxe/settings.h>
 #include <gpxe/if_arp.h>
 #include <gpxe/ethernet.h>
@@ -32,52 +34,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <gpxe/sec80211.h>
 #include <gpxe/timer.h>
 #include <gpxe/nap.h>
-#include <unistd.h>
-#include <errno.h>
+#include <gpxe/errortab.h>
+#include <gpxe/net80211_err.h>
 
 /** @file
  *
  * 802.11 device management
  */
 
-/* Disambiguate the EINVAL's a bit */
-#define EINVAL_PKT_TOO_SHORT   ( EINVAL | EUNIQ_01 )
-#define EINVAL_PKT_VERSION     ( EINVAL | EUNIQ_02 )
-#define EINVAL_PKT_NOT_DATA    ( EINVAL | EUNIQ_03 )
-#define EINVAL_PKT_NOT_FROMDS  ( EINVAL | EUNIQ_04 )
-#define EINVAL_PKT_LLC_HEADER  ( EINVAL | EUNIQ_05 )
-#define EINVAL_CRYPTO_REQUEST  ( EINVAL | EUNIQ_06 )
-#define EINVAL_ACTIVE_SCAN     ( EINVAL | EUNIQ_07 )
-
-/*
- * 802.11 error codes: The AP can give us a status code explaining why
- * authentication failed, or a reason code explaining why we were
- * deauthenticated/disassociated. These codes range from 0-63 (the
- * field is 16 bits wide, but only up to 45 or so are defined yet; we
- * allow up to 63 for extensibility). This is encoded into an error
- * code as such:
- *
- *                                      status & 0x1f goes here --vv--
- *   Status code 0-31:  ECONNREFUSED | EUNIQ_(status & 0x1f) (0e1a6038)
- *   Status code 32-63: EHOSTUNREACH | EUNIQ_(status & 0x1f) (171a6011)
- *   Reason code 0-31:  ECONNRESET | EUNIQ_(reason & 0x1f)   (0f1a6039)
- *   Reason code 32-63: ENETRESET | EUNIQ_(reason & 0x1f)    (271a6001)
- *
- * The POSIX error codes more or less convey the appropriate message
- * (status codes occur when we can't associate at all, reason codes
- * when we lose association unexpectedly) and let us extract the
- * complete 802.11 error code from the rc value.
- */
-
-/** Make return status code from 802.11 status code */
-#define E80211_STATUS( stat )  ( ((stat & 0x20)? EHOSTUNREACH : ECONNREFUSED) \
-                                       | ((stat & 0x1f) << 8) )
-
-/** Make return status code from 802.11 reason code */
-#define E80211_REASON( reas )  ( ((reas & 0x20)? ENETRESET : ECONNRESET) \
-                                       | ((reas & 0x1f) << 8) )
-
-
 /** List of 802.11 devices */
 static struct list_head net80211_devices = LIST_HEAD_INIT ( net80211_devices );
 
@@ -2838,3 +2802,15 @@ void net80211_tx_complete ( struct net80211_device *dev,
        /* Pass completion onward */
        netdev_tx_complete_err ( dev->netdev, iob, rc );
 }
+
+/** Common 802.11 errors */
+struct errortab common_wireless_errors[] __errortab = {
+       __einfo_errortab ( EINFO_EINVAL_CRYPTO_REQUEST ),
+       __einfo_errortab ( EINFO_ECONNRESET_UNSPECIFIED ),
+       __einfo_errortab ( EINFO_ECONNRESET_INACTIVITY ),
+       __einfo_errortab ( EINFO_ECONNRESET_4WAY_TIMEOUT ),
+       __einfo_errortab ( EINFO_ECONNRESET_8021X_FAILURE ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_FAILURE ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_ASSOC_DENIED ),
+       __einfo_errortab ( EINFO_ECONNREFUSED_AUTH_ALGO_UNSUPP ),
+};
index c5aa118..0ababa6 100644 (file)
@@ -34,6 +34,20 @@ FILE_LICENCE ( GPL2_OR_LATER );
  * static data in this file.
  */
 
+/* Unsupported cryptosystem error numbers */
+#define ENOTSUP_WEP __einfo_error ( EINFO_ENOTSUP_WEP )
+#define EINFO_ENOTSUP_WEP __einfo_uniqify ( EINFO_ENOTSUP, \
+       ( 0x10 | NET80211_CRYPT_WEP ), "WEP not supported" )
+#define ENOTSUP_TKIP __einfo_error ( EINFO_ENOTSUP_TKIP )
+#define EINFO_ENOTSUP_TKIP __einfo_uniqify ( EINFO_ENOTSUP, \
+       ( 0x10 | NET80211_CRYPT_TKIP ), "TKIP not supported" )
+#define ENOTSUP_CCMP __einfo_error ( EINFO_ENOTSUP_CCMP )
+#define EINFO_ENOTSUP_CCMP __einfo_uniqify ( EINFO_ENOTSUP, \
+       ( 0x10 | NET80211_CRYPT_CCMP ), "CCMP not supported" )
+#define ENOTSUP_CRYPT( crypt )              \
+       EUNIQ ( ENOTSUP, ( 0x10 | (crypt) ), \
+               ENOTSUP_WEP, ENOTSUP_TKIP, ENOTSUP_CCMP )
+
 /** Mapping from net80211 crypto/secprot types to RSN OUI descriptors */
 struct descriptor_map {
        /** Value of net80211_crypto_alg or net80211_security_proto */
@@ -130,7 +144,7 @@ int sec80211_install ( struct net80211_crypto **which,
 
        if ( ! crypto ) {
                DBG ( "802.11-Sec no support for cryptosystem %d\n", crypt );
-               return -( ENOTSUP | EUNIQ_10 | ( crypt << 8 ) );
+               return -ENOTSUP_CRYPT ( crypt );
        }
 
        *which = crypto;
index d781324..d2ca8dd 100644 (file)
@@ -50,13 +50,17 @@ struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices );
 static struct list_head open_ib_devices = LIST_HEAD_INIT ( open_ib_devices );
 
 /* Disambiguate the various possible EINPROGRESSes */
-#define EINPROGRESS_INIT ( EINPROGRESS | EUNIQ_01 )
-#define EINPROGRESS_ARMED ( EINPROGRESS | EUNIQ_02 )
+#define EINPROGRESS_INIT __einfo_error ( EINFO_EINPROGRESS_INIT )
+#define EINFO_EINPROGRESS_INIT __einfo_uniqify \
+       ( EINFO_EINPROGRESS, 0x01, "Initialising" )
+#define EINPROGRESS_ARMED __einfo_error ( EINFO_EINPROGRESS_ARMED )
+#define EINFO_EINPROGRESS_ARMED __einfo_uniqify \
+       ( EINFO_EINPROGRESS, 0x02, "Armed" )
 
 /** Human-readable message for the link statuses */
 struct errortab infiniband_errors[] __errortab = {
-       { EINPROGRESS_INIT, "Initialising" },
-       { EINPROGRESS_ARMED, "Armed" },
+       __einfo_errortab ( EINFO_EINPROGRESS_INIT ),
+       __einfo_errortab ( EINFO_EINPROGRESS_ARMED ),
 };
 
 /***************************************************************************
index 8880904..22e7d48 100644 (file)
@@ -46,10 +46,15 @@ FILE_LICENCE ( BSD2 );
  */
 
 /* Disambiguate the various possible EINVALs */
-#define EINVAL_BYTE_STRING_LEN ( EINVAL | EUNIQ_01 )
-#define EINVAL_BYTE_STRING ( EINVAL | EUNIQ_02 )
-#define EINVAL_INTEGER ( EINVAL | EUNIQ_03 )
-#define EINVAL_RP_TOO_SHORT ( EINVAL | EUNIQ_04 )
+#define EINVAL_BYTE_STRING_LEN __einfo_error ( EINFO_EINVAL_BYTE_STRING_LEN )
+#define EINFO_EINVAL_BYTE_STRING_LEN __einfo_uniqify \
+       ( EINFO_EINVAL, 0x01, "Invalid byte string length" )
+#define EINVAL_INTEGER __einfo_error ( EINFO_EINVAL_INTEGER )
+#define EINFO_EINVAL_INTEGER __einfo_uniqify \
+       ( EINFO_EINVAL, 0x03, "Invalid integer" )
+#define EINVAL_RP_TOO_SHORT __einfo_error ( EINFO_EINVAL_RP_TOO_SHORT )
+#define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \
+       ( EINFO_EINVAL, 0x04, "Root path too short" )
 
 /** IB SRP parse flags */
 enum ib_srp_parse_flags {
index b91f98c..e45f3d1 100644 (file)
@@ -46,11 +46,13 @@ struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
 static struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
 
 /** Default link status code */
-#define EUNKNOWN_LINK_STATUS EINPROGRESS
+#define EUNKNOWN_LINK_STATUS __einfo_error ( EINFO_EUNKNOWN_LINK_STATUS )
+#define EINFO_EUNKNOWN_LINK_STATUS \
+       __einfo_uniqify ( EINFO_EINPROGRESS, 0x01, "Unknown" )
 
 /** Human-readable message for the default link status */
 struct errortab netdev_errors[] __errortab = {
-       { EUNKNOWN_LINK_STATUS, "Unknown" },
+       __einfo_errortab ( EINFO_EUNKNOWN_LINK_STATUS ),
 };
 
 /**
@@ -60,16 +62,12 @@ struct errortab netdev_errors[] __errortab = {
  */
 void netdev_link_down ( struct net_device *netdev ) {
 
-       switch ( netdev->link_rc ) {
-       case 0:
-       case -EUNKNOWN_LINK_STATUS:
+       /* Avoid clobbering a more detailed link status code, if one
+        * is already set.
+        */
+       if ( ( netdev->link_rc == 0 ) ||
+            ( netdev->link_rc == -EUNKNOWN_LINK_STATUS ) ) {
                netdev->link_rc = -ENOTCONN;
-               break;
-       default:
-               /* Avoid clobbering a more detailed link status code,
-                * if one is already set.
-                */
-               break;
        }
 }
 
index dc05f6e..206f793 100644 (file)
@@ -48,17 +48,50 @@ FILE_LICENCE ( GPL2_OR_LATER );
 FEATURE ( FEATURE_PROTOCOL, "iSCSI", DHCP_EB_FEATURE_ISCSI, 1 );
 
 /* Disambiguate the various error causes */
-#define EACCES_INCORRECT_TARGET_USERNAME ( EACCES | EUNIQ_01 )
-#define EACCES_INCORRECT_TARGET_PASSWORD ( EACCES | EUNIQ_02 )
-#define ENOTSUP_INITIATOR_STATUS ( ENOTSUP | EUNIQ_01 )
-#define ENOTSUP_OPCODE ( ENOTSUP | EUNIQ_02 )
-#define ENOTSUP_DISCOVERY ( ENOTSUP | EUNIQ_03 )
-#define EPERM_INITIATOR_AUTHENTICATION ( EPERM | EUNIQ_01 )
-#define EPERM_INITIATOR_AUTHORISATION ( EPERM | EUNIQ_02 )
-#define EPROTO_INVALID_CHAP_ALGORITHM ( EPROTO | EUNIQ_01 )
-#define EPROTO_INVALID_CHAP_IDENTIFIER ( EPROTO | EUNIQ_02 )
-#define EPROTO_INVALID_LARGE_BINARY ( EPROTO | EUNIQ_03 )
-#define EPROTO_INVALID_CHAP_RESPONSE ( EPROTO | EUNIQ_04 )
+#define EACCES_INCORRECT_TARGET_USERNAME \
+       __einfo_error ( EINFO_EACCES_INCORRECT_TARGET_USERNAME )
+#define EINFO_EACCES_INCORRECT_TARGET_USERNAME \
+       __einfo_uniqify ( EINFO_EACCES, 0x01, "Incorrect target username" )
+#define EACCES_INCORRECT_TARGET_PASSWORD \
+       __einfo_error ( EINFO_EACCES_INCORRECT_TARGET_PASSWORD )
+#define EINFO_EACCES_INCORRECT_TARGET_PASSWORD \
+       __einfo_uniqify ( EINFO_EACCES, 0x02, "Incorrect target password" )
+#define ENOTSUP_INITIATOR_STATUS \
+       __einfo_error ( EINFO_ENOTSUP_INITIATOR_STATUS )
+#define EINFO_ENOTSUP_INITIATOR_STATUS \
+       __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported initiator status" )
+#define ENOTSUP_OPCODE \
+       __einfo_error ( EINFO_ENOTSUP_OPCODE )
+#define EINFO_ENOTSUP_OPCODE \
+       __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported opcode" )
+#define ENOTSUP_DISCOVERY \
+       __einfo_error ( EINFO_ENOTSUP_DISCOVERY )
+#define EINFO_ENOTSUP_DISCOVERY \
+       __einfo_uniqify ( EINFO_ENOTSUP, 0x03, "Discovery not supported" )
+#define EPERM_INITIATOR_AUTHENTICATION \
+       __einfo_error ( EINFO_EPERM_INITIATOR_AUTHENTICATION )
+#define EINFO_EPERM_INITIATOR_AUTHENTICATION \
+       __einfo_uniqify ( EINFO_EPERM, 0x01, "Initiator authentication failed" )
+#define EPERM_INITIATOR_AUTHORISATION \
+       __einfo_error ( EINFO_EPERM_INITIATOR_AUTHORISATION )
+#define EINFO_EPERM_INITIATOR_AUTHORISATION \
+       __einfo_uniqify ( EINFO_EPERM, 0x02, "Initiator not authorised" )
+#define EPROTO_INVALID_CHAP_ALGORITHM \
+       __einfo_error ( EINFO_EPROTO_INVALID_CHAP_ALGORITHM )
+#define EINFO_EPROTO_INVALID_CHAP_ALGORITHM \
+       __einfo_uniqify ( EINFO_EPROTO, 0x01, "Invalid CHAP algorithm" )
+#define EPROTO_INVALID_CHAP_IDENTIFIER \
+       __einfo_error ( EINFO_EPROTO_INVALID_CHAP_IDENTIFIER )
+#define EINFO_EPROTO_INVALID_CHAP_IDENTIFIER \
+       __einfo_uniqify ( EINFO_EPROTO, 0x02, "Invalid CHAP identifier" )
+#define EPROTO_INVALID_LARGE_BINARY \
+       __einfo_error ( EINFO_EPROTO_INVALID_LARGE_BINARY )
+#define EINFO_EPROTO_INVALID_LARGE_BINARY \
+       __einfo_uniqify ( EINFO_EPROTO, 0x03, "Invalid large binary" )
+#define EPROTO_INVALID_CHAP_RESPONSE \
+       __einfo_error ( EINFO_EPROTO_INVALID_CHAP_RESPONSE )
+#define EINFO_EPROTO_INVALID_CHAP_RESPONSE \
+       __einfo_uniqify ( EINFO_EPROTO, 0x04, "Invalid CHAP response" )
 
 /** iSCSI initiator name (explicitly specified) */
 static char *iscsi_explicit_initiator_iqn;
index 3de2fb9..8d9e8da 100644 (file)
@@ -48,13 +48,27 @@ FILE_LICENCE ( GPL2_OR_LATER );
 FEATURE ( FEATURE_PROTOCOL, "TFTP", DHCP_EB_FEATURE_TFTP, 1 );
 
 /* TFTP-specific error codes */
-#define ETFTP_INVALID_BLKSIZE  EUNIQ_01
-#define ETFTP_INVALID_TSIZE    EUNIQ_02
-#define ETFTP_MC_NO_PORT       EUNIQ_03
-#define ETFTP_MC_NO_MC         EUNIQ_04
-#define ETFTP_MC_INVALID_MC    EUNIQ_05
-#define ETFTP_MC_INVALID_IP    EUNIQ_06
-#define ETFTP_MC_INVALID_PORT  EUNIQ_07
+#define EINVAL_BLKSIZE         __einfo_error ( EINFO_EINVAL_BLKSIZE )
+#define EINFO_EINVAL_BLKSIZE __einfo_uniqify \
+       ( EINFO_EINVAL, 0x01, "Invalid blksize" )
+#define EINVAL_TSIZE __einfo_error ( EINFO_EINVAL_TSIZE )
+#define EINFO_EINVAL_TSIZE __einfo_uniqify \
+       ( EINFO_EINVAL, 0x02, "Invalid tsize" )
+#define EINVAL_MC_NO_PORT __einfo_error ( EINFO_EINVAL_MC_NO_PORT )
+#define EINFO_EINVAL_MC_NO_PORT __einfo_uniqify \
+       ( EINFO_EINVAL, 0x03, "Missing multicast port" )
+#define EINVAL_MC_NO_MC __einfo_error ( EINFO_EINVAL_MC_NO_MC )
+#define EINFO_EINVAL_MC_NO_MC __einfo_uniqify \
+       ( EINFO_EINVAL, 0x04, "Missing multicast mc" )
+#define EINVAL_MC_INVALID_MC __einfo_error ( EINFO_EINVAL_MC_INVALID_MC )
+#define EINFO_EINVAL_MC_INVALID_MC __einfo_uniqify \
+       ( EINFO_EINVAL, 0x05, "Missing multicast IP" )
+#define EINVAL_MC_INVALID_IP __einfo_error ( EINFO_EINVAL_MC_INVALID_IP )
+#define EINFO_EINVAL_MC_INVALID_IP __einfo_uniqify \
+       ( EINFO_EINVAL, 0x06, "Invalid multicast IP" )
+#define EINVAL_MC_INVALID_PORT __einfo_error ( EINFO_EINVAL_MC_INVALID_PORT )
+#define EINFO_EINVAL_MC_INVALID_PORT __einfo_uniqify \
+       ( EINFO_EINVAL, 0x07, "Invalid multicast port" )
 
 /**
  * A TFTP request
@@ -560,7 +574,7 @@ static int tftp_process_blksize ( struct tftp_request *tftp,
        if ( *end ) {
                DBGC ( tftp, "TFTP %p got invalid blksize \"%s\"\n",
                       tftp, value );
-               return -( EINVAL | ETFTP_INVALID_BLKSIZE );
+               return -EINVAL_BLKSIZE;
        }
        DBGC ( tftp, "TFTP %p blksize=%d\n", tftp, tftp->blksize );
 
@@ -582,7 +596,7 @@ static int tftp_process_tsize ( struct tftp_request *tftp,
        if ( *end ) {
                DBGC ( tftp, "TFTP %p got invalid tsize \"%s\"\n",
                       tftp, value );
-               return -( EINVAL | ETFTP_INVALID_TSIZE );
+               return -EINVAL_TSIZE;
        }
        DBGC ( tftp, "TFTP %p tsize=%ld\n", tftp, tftp->tsize );
 
@@ -616,13 +630,13 @@ static int tftp_process_multicast ( struct tftp_request *tftp,
        port = strchr ( addr, ',' );
        if ( ! port ) {
                DBGC ( tftp, "TFTP %p multicast missing port,mc\n", tftp );
-               return -( EINVAL | ETFTP_MC_NO_PORT );
+               return -EINVAL_MC_NO_PORT;
        }
        *(port++) = '\0';
        mc = strchr ( port, ',' );
        if ( ! mc ) {
                DBGC ( tftp, "TFTP %p multicast missing mc\n", tftp );
-               return -( EINVAL | ETFTP_MC_NO_MC );
+               return -EINVAL_MC_NO_MC;
        }
        *(mc++) = '\0';
 
@@ -631,7 +645,7 @@ static int tftp_process_multicast ( struct tftp_request *tftp,
                tftp->flags &= ~TFTP_FL_SEND_ACK;
        if ( *mc_end ) {
                DBGC ( tftp, "TFTP %p multicast invalid mc %s\n", tftp, mc );
-               return -( EINVAL | ETFTP_MC_INVALID_MC );
+               return -EINVAL_MC_INVALID_MC;
        }
        DBGC ( tftp, "TFTP %p is%s the master client\n",
               tftp, ( ( tftp->flags & TFTP_FL_SEND_ACK ) ? "" : " not" ) );
@@ -640,7 +654,7 @@ static int tftp_process_multicast ( struct tftp_request *tftp,
                if ( inet_aton ( addr, &socket.sin.sin_addr ) == 0 ) {
                        DBGC ( tftp, "TFTP %p multicast invalid IP address "
                               "%s\n", tftp, addr );
-                       return -( EINVAL | ETFTP_MC_INVALID_IP );
+                       return -EINVAL_MC_INVALID_IP;
                }
                DBGC ( tftp, "TFTP %p multicast IP address %s\n",
                       tftp, inet_ntoa ( socket.sin.sin_addr ) );
@@ -648,7 +662,7 @@ static int tftp_process_multicast ( struct tftp_request *tftp,
                if ( *port_end ) {
                        DBGC ( tftp, "TFTP %p multicast invalid port %s\n",
                               tftp, port );
-                       return -( EINVAL | ETFTP_MC_INVALID_PORT );
+                       return -EINVAL_MC_INVALID_PORT;
                }
                DBGC ( tftp, "TFTP %p multicast port %d\n",
                       tftp, ntohs ( socket.sin.sin_port ) );
@@ -872,12 +886,20 @@ static int tftp_rx_data ( struct tftp_request *tftp,
        return rc;
 }
 
-/** Translation between TFTP errors and internal error numbers */
-static const int tftp_errors[] = {
-       [TFTP_ERR_FILE_NOT_FOUND]       = ENOENT,
-       [TFTP_ERR_ACCESS_DENIED]        = EACCES,
-       [TFTP_ERR_ILLEGAL_OP]           = ENOTSUP,
-};
+/**
+ * Convert TFTP error code to return status code
+ *
+ * @v errcode          TFTP error code
+ * @ret rc             Return status code
+ */
+static int tftp_errcode_to_rc ( unsigned int errcode ) {
+       switch ( errcode ) {
+       case TFTP_ERR_FILE_NOT_FOUND:   return -ENOENT;
+       case TFTP_ERR_ACCESS_DENIED:    return -EACCES;
+       case TFTP_ERR_ILLEGAL_OP:       return -ENOTTY;
+       default:                        return -ENOTSUP;
+       }
+}
 
 /**
  * Receive ERROR
@@ -889,8 +911,7 @@ static const int tftp_errors[] = {
  */
 static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
        struct tftp_error *error = buf;
-       unsigned int err;
-       int rc = 0;
+       int rc;
 
        /* Sanity check */
        if ( len < sizeof ( *error ) ) {
@@ -903,11 +924,7 @@ static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
               "\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
        
        /* Determine final operation result */
-       err = ntohs ( error->errcode );
-       if ( err < ( sizeof ( tftp_errors ) / sizeof ( tftp_errors[0] ) ) )
-               rc = -tftp_errors[err];
-       if ( ! rc )
-               rc = -ENOTSUP;
+       rc = tftp_errcode_to_rc ( ntohs ( error->errcode ) );
 
        /* Close TFTP request */
        tftp_done ( tftp, rc );
index dd45662..a206439 100644 (file)
@@ -26,7 +26,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <gpxe/ethernet.h>
 #include <usr/ifmgmt.h>
 #include <usr/iwmgmt.h>
-#include <gpxe/errortab.h>
 
 /** @file
  *
@@ -225,20 +224,3 @@ int iwlist ( struct net80211_device *dev ) {
                 dev->netdev->name, strerror ( rc ) );
        return rc;
 }
-
-
-/* Record error codes as though they come from the 802.11 stack */
-#undef ERRFILE
-#define ERRFILE ERRFILE_net80211
-
-/** Common 802.11 errors */
-struct errortab common_wireless_errors[] __errortab = {
-       { EINVAL | EUNIQ_06, "Packet decryption error" },
-       { ECONNRESET | EUNIQ_01, "Unspecified reason" },
-       { ECONNRESET | EUNIQ_04, "Disassociated due to inactivity" },
-       { ECONNRESET | EUNIQ_0F, "4-Way Handshake timeout" },
-       { ECONNRESET | EUNIQ_17, "IEEE 802.1X authentication failed" },
-       { ECONNREFUSED | EUNIQ_01, "Unspecified failure" },
-       { ECONNREFUSED | EUNIQ_0C, "Association denied" },
-       { ECONNREFUSED | EUNIQ_0D, "Authentication method not supported" },
-};
index a375247..633ca32 100644 (file)
@@ -6,3 +6,4 @@ elf2efi32
 elf2efi64
 efirom
 iccfix
+einfo
diff --git a/src/util/einfo.c b/src/util/einfo.c
new file mode 100644 (file)
index 0000000..06736f2
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
+
+/** Command-line options */
+struct options {
+};
+
+/** Error usage information */
+struct einfo {
+       uint32_t size;
+       uint32_t error;
+       uint32_t desc;
+       uint32_t file;
+       uint32_t line;
+} __attribute__ (( packed ));
+
+/**
+ * Process einfo file
+ *
+ * @v infile           Filename
+ * @v opts             Command-line options
+ */
+static void einfo ( const char *infile, struct options *opts ) {
+       int fd;
+       struct stat stat;
+       size_t len;
+       void *start;
+       struct einfo *einfo;
+
+       /* Open einfo file */
+       if ( ( fd = open ( infile, O_RDONLY ) ) < 0 ) {
+               eprintf ( "Cannot open \"%s\": %s\n",
+                         infile, strerror ( errno ) );
+               exit ( 1 );
+       }
+
+       /* Get file size */
+       if ( fstat ( fd, &stat ) < 0 ) {
+               eprintf ( "Cannot stat \"%s\": %s\n",
+                         infile, strerror ( errno ) );
+               exit ( 1 );
+       }
+       len = stat.st_size;
+
+       if ( len ) {
+
+               /* Map file */
+               if ( ( start = mmap ( NULL, len, PROT_READ, MAP_SHARED,
+                                     fd, 0 ) ) == MAP_FAILED ) {
+                       eprintf ( "Cannot mmap \"%s\": %s\n",
+                                 infile, strerror ( errno ) );
+                       exit ( 1 );
+               }
+
+               /* Iterate over einfo records */
+               for ( einfo = start ; ( ( void * ) einfo ) < ( start + len ) ;
+                     einfo = ( ( ( void * ) einfo ) + einfo->size ) ) {
+                       printf ( "%08x\t%s\t%d\t%s\n", einfo->error,
+                                ( ( ( void * ) einfo ) + einfo->file ),
+                                einfo->line,
+                                ( ( ( void * ) einfo ) + einfo->desc ) );
+               }
+
+       }
+
+       /* Unmap and close file */
+       munmap ( start, len );
+       close ( fd );
+}
+
+/**
+ * Print help
+ *
+ * @v program_name     Program name
+ */
+static void print_help ( const char *program_name ) {
+       eprintf ( "Syntax: %s file1.einfo [file2.einfo...]\n",
+                 program_name );
+}
+
+/**
+ * Parse command-line options
+ *
+ * @v argc             Argument count
+ * @v argv             Argument list
+ * @v opts             Options structure to populate
+ */
+static int parse_options ( const int argc, char **argv,
+                          struct options *opts ) {
+       char *end;
+       int c;
+
+       while (1) {
+               int option_index = 0;
+               static struct option long_options[] = {
+                       { "help", 0, NULL, 'h' },
+                       { 0, 0, 0, 0 }
+               };
+
+               if ( ( c = getopt_long ( argc, argv, "s:h",
+                                        long_options,
+                                        &option_index ) ) == -1 ) {
+                       break;
+               }
+
+               switch ( c ) {
+               case 'h':
+                       print_help ( argv[0] );
+                       exit ( 0 );
+               case '?':
+               default:
+                       exit ( 2 );
+               }
+       }
+       return optind;
+}
+
+int main ( int argc, char **argv ) {
+       struct options opts = {
+       };
+       unsigned int infile_index;
+       const char *infile;
+
+       /* Parse command-line arguments */
+       infile_index = parse_options ( argc, argv, &opts );
+       if ( argc <= infile_index ) {
+               print_help ( argv[0] );
+               exit ( 2 );
+       }
+
+       /* Process each einfo file */
+       for ( ; infile_index < argc ; infile_index++ ) {
+               infile = argv[infile_index];
+               einfo ( infile, &opts );
+       }
+
+       return 0;
+}