From 9aa61ad5a26e04493a38bf4f9b6bd1228fef7a79 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 24 Jul 2007 17:11:31 +0100 Subject: Add per-file error identifiers --- src/arch/i386/include/bits/errfile.h | 31 ++++ src/core/iobuf.c | 20 +++ src/crypto/axtls_aes.c | 1 + src/crypto/cipher.c | 24 +++ src/hci/strerror.c | 15 +- src/include/compiler.h | 3 + src/include/errno.h | 281 ++++++++++++++++++++++------------- src/include/gpxe/crypto.h | 28 +--- src/include/gpxe/errfile.h | 121 +++++++++++++++ src/include/gpxe/errortab.h | 1 - src/include/gpxe/iobuf.h | 20 +-- src/include/gpxe/ndp.h | 1 - src/interface/pxe/pxe_errors.c | 1 + src/interface/pxe/pxe_tftp.c | 1 + src/net/nullnet.c | 1 + src/net/tcp.c | 22 +-- 16 files changed, 393 insertions(+), 178 deletions(-) create mode 100644 src/arch/i386/include/bits/errfile.h create mode 100644 src/crypto/cipher.c create mode 100644 src/include/gpxe/errfile.h (limited to 'src') diff --git a/src/arch/i386/include/bits/errfile.h b/src/arch/i386/include/bits/errfile.h new file mode 100644 index 00000000..a6f87825 --- /dev/null +++ b/src/arch/i386/include/bits/errfile.h @@ -0,0 +1,31 @@ +#ifndef _BITS_ERRFILE_H +#define _BITS_ERRFILE_H + +/** + * @addtogroup errfile Error file identifiers + * @{ + */ + +#define ERRFILE_umalloc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00000000 ) +#define ERRFILE_memmap ( ERRFILE_ARCH | ERRFILE_CORE | 0x00010000 ) +#define ERRFILE_pnpbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00020000 ) +#define ERRFILE_smbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 ) +#define ERRFILE_biosint ( ERRFILE_ARCH | ERRFILE_CORE | 0x00040000 ) +#define ERRFILE_int13 ( ERRFILE_ARCH | ERRFILE_CORE | 0x00050000 ) + +#define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 ) +#define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 ) +#define ERRFILE_eltorito ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00020000 ) +#define ERRFILE_multiboot ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00030000 ) +#define ERRFILE_nbi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00040000 ) +#define ERRFILE_pxe_image ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00050000 ) + +#define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 ) +#define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 ) +#define ERRFILE_undinet ( ERRFILE_ARCH | ERRFILE_NET | 0x00020000 ) +#define ERRFILE_undionly ( ERRFILE_ARCH | ERRFILE_NET | 0x00030000 ) +#define ERRFILE_undirom ( ERRFILE_ARCH | ERRFILE_NET | 0x00040000 ) + +/** @} */ + +#endif /* _BITS_ERRFILE_H */ diff --git a/src/core/iobuf.c b/src/core/iobuf.c index d04ede51..cc4aedea 100644 --- a/src/core/iobuf.c +++ b/src/core/iobuf.c @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -72,3 +73,22 @@ void free_iob ( struct io_buffer *iobuf ) { ( iobuf->end - iobuf->head ) + sizeof ( *iobuf ) ); } } + +/** + * Ensure I/O buffer has sufficient headroom + * + * @v iobuf I/O buffer + * @v len Required headroom + * + * This function currently only checks for the required headroom; it + * does not reallocate the I/O buffer if required. If we ever have a + * code path that requires this functionality, it's a fairly trivial + * change to make. + */ +int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ) { + + if ( iob_headroom ( iobuf ) >= len ) + return 0; + return -ENOBUFS; +} + diff --git a/src/crypto/axtls_aes.c b/src/crypto/axtls_aes.c index a587c5cb..ac7e921d 100644 --- a/src/crypto/axtls_aes.c +++ b/src/crypto/axtls_aes.c @@ -1,5 +1,6 @@ #include "crypto/axtls/crypto.h" #include +#include #include #include diff --git a/src/crypto/cipher.c b/src/crypto/cipher.c new file mode 100644 index 00000000..9c392009 --- /dev/null +++ b/src/crypto/cipher.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int cipher_encrypt ( struct crypto_algorithm *crypto, + void *ctx, const void *src, void *dst, + size_t len ) { + if ( ( len & ( crypto->blocksize - 1 ) ) ) { + return -EINVAL; + } + crypto->encode ( ctx, src, dst, len ); + return 0; +} + +int cipher_decrypt ( struct crypto_algorithm *crypto, + void *ctx, const void *src, void *dst, + size_t len ) { + if ( ( len & ( crypto->blocksize - 1 ) ) ) { + return -EINVAL; + } + crypto->decode ( ctx, src, dst, len ); + return 0; +} + diff --git a/src/hci/strerror.c b/src/hci/strerror.c index 7609f03e..4fc15d01 100644 --- a/src/hci/strerror.c +++ b/src/hci/strerror.c @@ -60,15 +60,7 @@ static struct errortab * find_closest_error ( int errno ) { /* Second, try masking off the gPXE-specific bit and seeing if * we have an entry for the generic POSIX error message. */ - if ( ( errortab = find_error ( errno, 0x0000ffff ) ) != NULL ) - return errortab; - - /* Lastly, try masking off the POSIX bits and seeing if we - * have a match just based on the PXENV component. This - * allows us to report errors from underlying PXE stacks. - */ - if ( ( errortab = find_error ( ( errno & 0x000000ff ), - 0xffff00ff ) ) != NULL ) + if ( ( errortab = find_error ( errno, 0x4f0000ff ) ) != NULL ) return errortab; return NULL; @@ -109,6 +101,10 @@ const char * strerror ( int errno ) { return errbuf; } +/* Do not include ERRFILE portion in the numbers in the error table */ +#undef ERRFILE +#define ERRFILE 0 + /** The most common errors */ struct errortab common_errors[] __errortab = { { 0, "No error" }, @@ -121,4 +117,5 @@ struct errortab common_errors[] __errortab = { { ENETUNREACH, "Network unreachable" }, { ETIMEDOUT, "Connection timed out" }, { EPIPE, "Broken pipe" }, + { ECANCELED, "Operation cancelled" }, }; diff --git a/src/include/compiler.h b/src/include/compiler.h index 18ca75c9..376936d0 100644 --- a/src/include/compiler.h +++ b/src/include/compiler.h @@ -267,6 +267,9 @@ extern void dbg_hex_dump_da ( unsigned long dispaddr, #define NDEBUG #endif +/** Select file identifier for errno.h (if used) */ +#define ERRFILE PREFIX_OBJECT ( ERRFILE_ ) + /** Declare a data structure as packed. */ #define PACKED __attribute__ (( packed )) diff --git a/src/include/errno.h b/src/include/errno.h index 1eb28fbe..03d1ebd6 100644 --- a/src/include/errno.h +++ b/src/include/errno.h @@ -7,35 +7,53 @@ * * Return status codes as used within gPXE are designed to allow for * maximum visibility into the source of an error even in an end-user - * build with no debugging. They are constructed in three parts: a - * PXE error code, a POSIX error code, and a gPXE-specific error code. + * build with no debugging. They are constructed as follows: * - * The low byte is the closest equivalent PXE error code + * Bits 7-0 : PXE error code + * + * This is the closest equivalent PXE error code * (e.g. PXENV_STATUS_OUT_OF_RESOURCES), and is the only part of the * error that will be returned via the PXE API, since PXE has * predefined error codes. * - * The next byte is the closest equivalent POSIX error code - * (e.g. ENOMEM). + * Bits 12-8 : Per-file disambiguator + * + * When the same error number can be generated from multiple points + * within a file, this field can be used to identify the unique + * instance. + * + * Bits 23-13 : File identifier + * + * This is a unique identifier for the file generating the error + * (e.g. ERRFILE_tcp for tcp.c). + * + * Bits 30-24 : POSIX error code + * + * This is the closest equivalent POSIX error code (e.g. ENOMEM). + * + * Bit 31 : Reserved + * + * Errors are usually return as negative error numbers (e.g. -EINVAL); + * bit 31 is therefore unusable. * - * The remaining bytes are the gPXE-specific error code, which allow - * us to disambiguate between errors which should have the same POSIX - * error code but which mean very different things to the user - * (e.g. ENOENT due to a DNS name not existing versus ENOENT due to - * a web server returning HTTP/404 Not Found). * * The convention within the code is that errors are negative and - * expressed as the bitwise OR of a POSIX error code and (optionally) - * a gPXE error code, as in + * expressed using the POSIX error code and (optionally) a per-file + * disambiguator, e.g. * - * return -( ENOENT | NO_SUCH_FILE ); + * return -EINVAL; * - * The POSIX error code is #defined to include the closest matching - * PXE error code (which, in most cases, is just - * PXENV_STATUS_FAILURE), so we don't need to litter the codebase with - * PXEisms. + * or * - * Functions that wish to return failure should be declared as + * #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. + * + * + * Functions that wish to return failures should be declared as * returning an integer @c rc "Return status code". A return value of * zero indicates success, a non-zero value indicates failure. The * return value can be passed directly to strerror() in order to @@ -51,6 +69,20 @@ * */ +/* Get definitions for file identifiers */ +#include + +/* If we do not have a valid file identifier, generate a compiler + * warning upon usage of any error codes. (Don't just use a #warning, + * because some files include errno.h but don't ever actually use any + * error codes.) + */ +#if ! ERRFILE +extern char missing_errfile_declaration[] __attribute__ (( deprecated )); +#undef ERRFILE +#define ERRFILE ( 0 * ( ( int ) missing_errfile_declaration ) ) +#endif + /** Derive PXENV_STATUS code from gPXE error number */ #define PXENV_STATUS( rc ) ( (-(rc)) & 0x00ff ) @@ -178,262 +210,297 @@ */ /** Operation completed successfully */ -#define ENOERR ( PXENV_STATUS_SUCCESS | 0x0000 ) +#define ENOERR ( ERRFILE | PXENV_STATUS_SUCCESS | 0x00000000 ) /** Arg list too long */ -#define E2BIG ( PXENV_STATUS_BAD_FUNC | 0x0100 ) +#define E2BIG ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x01000000 ) /** Permission denied */ -#define EACCES ( PXENV_STATUS_TFTP_ACCESS_VIOLATION | 0x0200 ) +#define EACCES ( ERRFILE | PXENV_STATUS_TFTP_ACCESS_VIOLATION | 0x02000000 ) /** Address in use */ -#define EADDRINUSE ( PXENV_STATUS_UDP_OPEN | 0x0300 ) +#define EADDRINUSE ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x03000000 ) /** Address not available */ -#define EADDRNOTAVAIL ( PXENV_STATUS_UDP_OPEN | 0x0400 ) +#define EADDRNOTAVAIL ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x04000000 ) /** Address family not supported */ -#define EAFNOSUPPORT ( PXENV_STATUS_UNSUPPORTED | 0x0500 ) +#define EAFNOSUPPORT ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x05000000 ) /** Resource temporarily unavailable */ -#define EAGAIN ( PXENV_STATUS_FAILURE | 0x0600 ) +#define EAGAIN ( ERRFILE | PXENV_STATUS_FAILURE | 0x06000000 ) /** Connection already in progress */ -#define EALREADY ( PXENV_STATUS_UDP_OPEN | 0x0700 ) +#define EALREADY ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x07000000 ) /** Bad file descriptor */ -#define EBADF ( PXENV_STATUS_TFTP_CLOSED | 0x0800 ) +#define EBADF ( ERRFILE | PXENV_STATUS_TFTP_CLOSED | 0x08000000 ) /** Bad message */ -#define EBADMSG ( PXENV_STATUS_FAILURE | 0x0900 ) +#define EBADMSG ( ERRFILE | PXENV_STATUS_FAILURE | 0x09000000 ) /** Resource busy */ -#define EBUSY ( PXENV_STATUS_OUT_OF_RESOURCES | 0x0a00 ) +#define EBUSY ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x0a000000 ) /** Operation canceled */ -#define ECANCELED ( PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE | 0x0b00 ) +#define ECANCELED \ + ( ERRFILE | PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE | 0x0b000000 ) /** No child processes */ -#define ECHILD ( PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x0c00 ) +#define ECHILD ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x0c000000 ) /** Connection aborted */ -#define ECONNABORTED ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x0d00 ) +#define ECONNABORTED \ + ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x0d000000 ) /** Connection refused */ -#define ECONNREFUSED ( PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION | 0x0e00 ) +#define ECONNREFUSED \ + ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION | 0x0e000000 ) /** Connection reset */ -#define ECONNRESET ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x0f00 ) +#define ECONNRESET \ + ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x0f000000 ) /** Resource deadlock avoided */ -#define EDEADLK ( PXENV_STATUS_FAILURE | 0x1000 ) +#define EDEADLK ( ERRFILE | PXENV_STATUS_FAILURE | 0x10000000 ) /** Destination address required */ -#define EDESTADDRREQ ( PXENV_STATUS_BAD_FUNC | 0x1100 ) +#define EDESTADDRREQ ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x11000000 ) /** Domain error */ -#define EDOM ( PXENV_STATUS_FAILURE | 0x1200 ) +#define EDOM ( ERRFILE | PXENV_STATUS_FAILURE | 0x12000000 ) /** Reserved */ -#define EDQUOT ( PXENV_STATUS_FAILURE | 0x1300 ) +#define EDQUOT ( ERRFILE | PXENV_STATUS_FAILURE | 0x13000000 ) /** File exists */ -#define EEXIST ( PXENV_STATUS_FAILURE | 0x1400 ) +#define EEXIST ( ERRFILE | PXENV_STATUS_FAILURE | 0x14000000 ) /** Bad address */ -#define EFAULT ( PXENV_STATUS_MCOPY_PROBLEM | 0x1500 ) +#define EFAULT ( ERRFILE | PXENV_STATUS_MCOPY_PROBLEM | 0x15000000 ) /** File too large */ -#define EFBIG ( PXENV_STATUS_MCOPY_PROBLEM | 0x1600 ) +#define EFBIG ( ERRFILE | PXENV_STATUS_MCOPY_PROBLEM | 0x16000000 ) /** Host is unreachable */ -#define EHOSTUNREACH ( PXENV_STATUS_ARP_TIMEOUT | 0x1700 ) +#define EHOSTUNREACH ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x17000000 ) /** Identifier removed */ -#define EIDRM ( PXENV_STATUS_FAILURE | 0x1800 ) +#define EIDRM ( ERRFILE | PXENV_STATUS_FAILURE | 0x18000000 ) /** Illegal byte sequence */ -#define EILSEQ ( PXENV_STATUS_FAILURE | 0x1900 ) +#define EILSEQ ( ERRFILE | PXENV_STATUS_FAILURE | 0x19000000 ) /** Operation in progress */ -#define EINPROGRESS ( PXENV_STATUS_FAILURE | 0x1a00 ) +#define EINPROGRESS ( ERRFILE | PXENV_STATUS_FAILURE | 0x1a000000 ) /** Interrupted function call */ -#define EINTR ( PXENV_STATUS_FAILURE | 0x1b00 ) +#define EINTR ( ERRFILE | PXENV_STATUS_FAILURE | 0x1b000000 ) /** Invalid argument */ -#define EINVAL ( PXENV_STATUS_BAD_FUNC | 0x1c00 ) +#define EINVAL ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x1c000000 ) /** Input/output error */ -#define EIO ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x1d00 ) +#define EIO \ + ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x1d000000 ) /** Socket is connected */ -#define EISCONN ( PXENV_STATUS_UDP_OPEN | 0x1e00 ) +#define EISCONN ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x1e000000 ) /** Is a directory */ -#define EISDIR ( PXENV_STATUS_FAILURE | 0x1f00 ) +#define EISDIR ( ERRFILE | PXENV_STATUS_FAILURE | 0x1f000000 ) /** Too many levels of symbolic links */ -#define ELOOP ( PXENV_STATUS_FAILURE | 0x2000 ) +#define ELOOP ( ERRFILE | PXENV_STATUS_FAILURE | 0x20000000 ) /** Too many open files */ -#define EMFILE ( PXENV_STATUS_OUT_OF_RESOURCES | 0x2100 ) +#define EMFILE ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x21000000 ) /** Too many links */ -#define EMLINK ( PXENV_STATUS_FAILURE | 0x2200 ) +#define EMLINK ( ERRFILE | PXENV_STATUS_FAILURE | 0x22000000 ) /** Inappropriate message buffer length */ -#define EMSGSIZE ( PXENV_STATUS_BAD_FUNC | 0x2300 ) +#define EMSGSIZE ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x23000000 ) /** Reserved */ -#define EMULTIHOP ( PXENV_STATUS_FAILURE | 0x2400 ) +#define EMULTIHOP ( ERRFILE | PXENV_STATUS_FAILURE | 0x24000000 ) /** Filename too long */ -#define ENAMETOOLONG ( PXENV_STATUS_FAILURE | 0x2500 ) +#define ENAMETOOLONG ( ERRFILE | PXENV_STATUS_FAILURE | 0x25000000 ) /** Network is down */ -#define ENETDOWN ( PXENV_STATUS_ARP_TIMEOUT | 0x2600 ) +#define ENETDOWN ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x26000000 ) /** Connection aborted by network */ -#define ENETRESET ( PXENV_STATUS_FAILURE | 0x2700 ) +#define ENETRESET ( ERRFILE | PXENV_STATUS_FAILURE | 0x27000000 ) /** Network unreachable */ -#define ENETUNREACH ( PXENV_STATUS_ARP_TIMEOUT | 0x2800 ) +#define ENETUNREACH ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x28000000 ) /** Too many open files in system */ -#define ENFILE ( PXENV_STATUS_OUT_OF_RESOURCES | 0x2900 ) +#define ENFILE ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x29000000 ) /** No buffer space available */ -#define ENOBUFS ( PXENV_STATUS_OUT_OF_RESOURCES | 0x2a00 ) +#define ENOBUFS ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x2a000000 ) /** No message is available on the STREAM head read queue */ -#define ENODATA ( PXENV_STATUS_FAILURE | 0x2b00 ) +#define ENODATA ( ERRFILE | PXENV_STATUS_FAILURE | 0x2b000000 ) /** No such device */ -#define ENODEV ( PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x2c00 ) +#define ENODEV ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x2c000000 ) /** No such file or directory */ -#define ENOENT ( PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x2d00 ) +#define ENOENT ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x2d000000 ) /** Exec format error */ -#define ENOEXEC ( PXENV_STATUS_FAILURE | 0x2e00 ) +#define ENOEXEC ( ERRFILE | PXENV_STATUS_FAILURE | 0x2e000000 ) /** No locks available */ -#define ENOLCK ( PXENV_STATUS_FAILURE | 0x2f00 ) +#define ENOLCK ( ERRFILE | PXENV_STATUS_FAILURE | 0x2f000000 ) /** Reserved */ -#define ENOLINK ( PXENV_STATUS_FAILURE | 0x3000 ) +#define ENOLINK ( ERRFILE | PXENV_STATUS_FAILURE | 0x30000000 ) /** Not enough space */ -#define ENOMEM ( PXENV_STATUS_OUT_OF_RESOURCES | 0x3100 ) +#define ENOMEM ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x31000000 ) /** No message of the desired type */ -#define ENOMSG ( PXENV_STATUS_FAILURE | 0x3200 ) +#define ENOMSG ( ERRFILE | PXENV_STATUS_FAILURE | 0x32000000 ) /** Protocol not available */ -#define ENOPROTOOPT ( PXENV_STATUS_UNSUPPORTED | 0x3300 ) +#define ENOPROTOOPT ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x33000000 ) /** No space left on device */ -#define ENOSPC ( PXENV_STATUS_OUT_OF_RESOURCES | 0x3400 ) +#define ENOSPC ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x34000000 ) /** No STREAM resources */ -#define ENOSR ( PXENV_STATUS_OUT_OF_RESOURCES | 0x3500 ) +#define ENOSR ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x35000000 ) /** Not a STREAM */ -#define ENOSTR ( PXENV_STATUS_FAILURE | 0x3600 ) +#define ENOSTR ( ERRFILE | PXENV_STATUS_FAILURE | 0x36000000 ) /** Function not implemented */ -#define ENOSYS ( PXENV_STATUS_UNSUPPORTED | 0x3700 ) +#define ENOSYS ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x37000000 ) /** The socket is not connected */ -#define ENOTCONN ( PXENV_STATUS_FAILURE | 0x3800 ) +#define ENOTCONN ( ERRFILE | PXENV_STATUS_FAILURE | 0x38000000 ) /** Not a directory */ -#define ENOTDIR ( PXENV_STATUS_FAILURE | 0x3900 ) +#define ENOTDIR ( ERRFILE | PXENV_STATUS_FAILURE | 0x39000000 ) /** Directory not empty */ -#define ENOTEMPTY ( PXENV_STATUS_FAILURE | 0x3a00 ) +#define ENOTEMPTY ( ERRFILE | PXENV_STATUS_FAILURE | 0x3a000000 ) /** Not a socket */ -#define ENOTSOCK ( PXENV_STATUS_FAILURE | 0x3b00 ) +#define ENOTSOCK ( ERRFILE | PXENV_STATUS_FAILURE | 0x3b000000 ) /** Not supported */ -#define ENOTSUP ( PXENV_STATUS_UNSUPPORTED | 0x3c00 ) +#define ENOTSUP ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x3c000000 ) /** Inappropriate I/O control operation */ -#define ENOTTY ( PXENV_STATUS_FAILURE | 0x3d00 ) +#define ENOTTY ( ERRFILE | PXENV_STATUS_FAILURE | 0x3d000000 ) /** No such device or address */ -#define ENXIO ( PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x3e00 ) +#define ENXIO ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x3e000000 ) /** Operation not supported on socket */ -#define EOPNOTSUPP ( PXENV_STATUS_UNSUPPORTED | 0x3f00 ) +#define EOPNOTSUPP ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x3f000000 ) /** Value too large to be stored in data type */ -#define EOVERFLOW ( PXENV_STATUS_FAILURE | 0x4000 ) +#define EOVERFLOW ( ERRFILE | PXENV_STATUS_FAILURE | 0x40000000 ) /** Operation not permitted */ -#define EPERM ( PXENV_STATUS_TFTP_ACCESS_VIOLATION | 0x4100 ) +#define EPERM ( ERRFILE | PXENV_STATUS_TFTP_ACCESS_VIOLATION | 0x41000000 ) /** Broken pipe */ -#define EPIPE ( PXENV_STATUS_FAILURE | 0x4200 ) +#define EPIPE ( ERRFILE | PXENV_STATUS_FAILURE | 0x42000000 ) /** Protocol error */ -#define EPROTO ( PXENV_STATUS_FAILURE | 0x4300 ) +#define EPROTO ( ERRFILE | PXENV_STATUS_FAILURE | 0x43000000 ) /** Protocol not supported */ -#define EPROTONOSUPPORT ( PXENV_STATUS_UNSUPPORTED | 0x4400 ) +#define EPROTONOSUPPORT ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x44000000 ) /** Protocol wrong type for socket */ -#define EPROTOTYPE ( PXENV_STATUS_FAILURE | 0x4500 ) +#define EPROTOTYPE ( ERRFILE | PXENV_STATUS_FAILURE | 0x45000000 ) /** Result too large */ -#define ERANGE ( PXENV_STATUS_FAILURE | 0x4600 ) +#define ERANGE ( ERRFILE | PXENV_STATUS_FAILURE | 0x46000000 ) /** Read-only file system */ -#define EROFS ( PXENV_STATUS_FAILURE | 0x4700 ) +#define EROFS ( ERRFILE | PXENV_STATUS_FAILURE | 0x47000000 ) /** Invalid seek */ -#define ESPIPE ( PXENV_STATUS_FAILURE | 0x4800 ) +#define ESPIPE ( ERRFILE | PXENV_STATUS_FAILURE | 0x48000000 ) /** No such process */ -#define ESRCH ( PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x4900 ) +#define ESRCH ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x49000000 ) /** Stale file handle */ -#define ESTALE ( PXENV_STATUS_FAILURE | 0x4a00 ) +#define ESTALE ( ERRFILE | PXENV_STATUS_FAILURE | 0x4a000000 ) /** STREAM ioctl() timeout */ -#define ETIME ( PXENV_STATUS_FAILURE | 0x4b00 ) +#define ETIME ( ERRFILE | PXENV_STATUS_FAILURE | 0x4b000000 ) /** Operation timed out */ -#define ETIMEDOUT ( PXENV_STATUS_TFTP_READ_TIMEOUT | 0x4c00 ) +#define ETIMEDOUT ( ERRFILE | PXENV_STATUS_TFTP_READ_TIMEOUT | 0x4c000000 ) /** Text file busy */ -#define ETXTBSY ( PXENV_STATUS_FAILURE | 0x4d00 ) +#define ETXTBSY ( ERRFILE | PXENV_STATUS_FAILURE | 0x4d000000 ) /** Operation would block */ -#define EWOULDBLOCK ( PXENV_STATUS_FAILURE | 0x4e00 ) +#define EWOULDBLOCK ( ERRFILE | PXENV_STATUS_FAILURE | 0x4e000000 ) /** Improper link */ -#define EXDEV ( PXENV_STATUS_FAILURE | 0x4f00 ) +#define EXDEV ( ERRFILE | PXENV_STATUS_FAILURE | 0x4f000000 ) /** @} */ /** - * @defgroup gpxeerrors gPXE-specific error codes + * @defgroup euniq Per-file error disambiguators * - * The names, meanings, and values of these error codes are defined by - * this file. A gPXE-specific error code should be defined only where - * the POSIX error code does not identify the error with sufficient - * specificity. For example, ENOMEM probably encapsulates everything - * that needs to be known about the error (we've run out of heap - * space), while EACCES does not (did the server refuse the - * connection, or did we decide that the server failed to provide a - * valid SSL/TLS certificate?). + * 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 + /** @} */ extern int errno; diff --git a/src/include/gpxe/crypto.h b/src/include/gpxe/crypto.h index fc1f50bc..95665acc 100644 --- a/src/include/gpxe/crypto.h +++ b/src/include/gpxe/crypto.h @@ -9,7 +9,6 @@ #include #include -#include /** A cryptographic algorithm */ struct crypto_algorithm { @@ -101,30 +100,17 @@ static inline int cipher_setkey ( struct crypto_algorithm *crypto, return crypto->setkey ( ctx, key, keylen ); } -static inline int cipher_encrypt ( struct crypto_algorithm *crypto, - void *ctx, const void *src, void *dst, - size_t len ) { - if ( ( len & ( crypto->blocksize - 1 ) ) ) { - return -EINVAL; - } - crypto->encode ( ctx, src, dst, len ); - return 0; -} - -static inline int cipher_decrypt ( struct crypto_algorithm *crypto, - void *ctx, const void *src, void *dst, - size_t len ) { - if ( ( len & ( crypto->blocksize - 1 ) ) ) { - return -EINVAL; - } - crypto->decode ( ctx, src, dst, len ); - return 0; -} - static inline int is_stream_cipher ( struct crypto_algorithm *crypto ) { return ( crypto->blocksize == 1 ); } extern struct crypto_algorithm crypto_null; +extern int cipher_encrypt ( struct crypto_algorithm *crypto, + void *ctx, const void *src, void *dst, + size_t len ); +extern int cipher_decrypt ( struct crypto_algorithm *crypto, + void *ctx, const void *src, void *dst, + size_t len ); + #endif /* _GPXE_CRYPTO_H */ diff --git a/src/include/gpxe/errfile.h b/src/include/gpxe/errfile.h new file mode 100644 index 00000000..0615818f --- /dev/null +++ b/src/include/gpxe/errfile.h @@ -0,0 +1,121 @@ +#ifndef _GPXE_ERRFILE_H +#define _GPXE_ERRFILE_H + +/** @file + * + * Error file identifiers + * + */ + +#include + +/** + * @defgroup errfilecat Error file identifier categories + * + * @{ + */ + +#define ERRFILE_CORE 0x00002000 /**< Core code */ +#define ERRFILE_DRIVER 0x00004000 /**< Driver code */ +#define ERRFILE_NET 0x00006000 /**< Networking code */ +#define ERRFILE_IMAGE 0x00008000 /**< Image code */ +#define ERRFILE_OTHER 0x0000e000 /**< Any other code */ + +/** @} */ + +/** Flag for architecture-dependent error files */ +#define ERRFILE_ARCH 0x00800000 + +/** + * @defgroup errfile Error file identifiers + * + * These values are automatically incorporated into the definitions + * for error numbers such as EINVAL. + * + * @{ + */ + +#define ERRFILE_asprintf ( ERRFILE_CORE | 0x00000000 ) +#define ERRFILE_downloader ( ERRFILE_CORE | 0x00010000 ) +#define ERRFILE_exec ( ERRFILE_CORE | 0x00020000 ) +#define ERRFILE_hw ( ERRFILE_CORE | 0x00030000 ) +#define ERRFILE_iobuf ( ERRFILE_CORE | 0x00040000 ) +#define ERRFILE_job ( ERRFILE_CORE | 0x00050000 ) +#define ERRFILE_linebuf ( ERRFILE_CORE | 0x00060000 ) +#define ERRFILE_monojob ( ERRFILE_CORE | 0x00070000 ) +#define ERRFILE_nvo ( ERRFILE_CORE | 0x00080000 ) +#define ERRFILE_open ( ERRFILE_CORE | 0x00090000 ) +#define ERRFILE_posix_io ( ERRFILE_CORE | 0x000a0000 ) +#define ERRFILE_resolv ( ERRFILE_CORE | 0x000b0000 ) +#define ERRFILE_settings ( ERRFILE_CORE | 0x000c0000 ) +#define ERRFILE_vsprintf ( ERRFILE_CORE | 0x000d0000 ) +#define ERRFILE_xfer ( ERRFILE_CORE | 0x000e0000 ) + +#define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 ) +#define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 ) +#define ERRFILE_isapnp ( ERRFILE_DRIVER | 0x00020000 ) +#define ERRFILE_mca ( ERRFILE_DRIVER | 0x00030000 ) +#define ERRFILE_pci ( ERRFILE_DRIVER | 0x00040000 ) + +#define ERRFILE_nvs ( ERRFILE_DRIVER | 0x00100000 ) +#define ERRFILE_spi ( ERRFILE_DRIVER | 0x00110000 ) +#define ERRFILE_i2c_bit ( ERRFILE_DRIVER | 0x00120000 ) +#define ERRFILE_spi_bit ( ERRFILE_DRIVER | 0x00130000 ) + +#define ERRFILE_3c509 ( ERRFILE_DRIVER | 0x00200000 ) +#define ERRFILE_bnx2 ( ERRFILE_DRIVER | 0x00210000 ) +#define ERRFILE_cs89x0 ( ERRFILE_DRIVER | 0x00220000 ) +#define ERRFILE_eepro ( ERRFILE_DRIVER | 0x00230000 ) +#define ERRFILE_etherfabric ( ERRFILE_DRIVER | 0x00240000 ) +#define ERRFILE_legacy ( ERRFILE_DRIVER | 0x00250000 ) +#define ERRFILE_natsemi ( ERRFILE_DRIVER | 0x00260000 ) +#define ERRFILE_pnic ( ERRFILE_DRIVER | 0x00270000 ) +#define ERRFILE_prism2_pci ( ERRFILE_DRIVER | 0x00280000 ) +#define ERRFILE_prism2_plx ( ERRFILE_DRIVER | 0x00290000 ) +#define ERRFILE_rtl8139 ( ERRFILE_DRIVER | 0x002a0000 ) +#define ERRFILE_smc9000 ( ERRFILE_DRIVER | 0x002b0000 ) +#define ERRFILE_tg3 ( ERRFILE_DRIVER | 0x002c0000 ) + +#define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 ) + +#define ERRFILE_aoe ( ERRFILE_NET | 0x00000000 ) +#define ERRFILE_arp ( ERRFILE_NET | 0x00010000 ) +#define ERRFILE_dhcpopts ( ERRFILE_NET | 0x00020000 ) +#define ERRFILE_ethernet ( ERRFILE_NET | 0x00030000 ) +#define ERRFILE_icmpv6 ( ERRFILE_NET | 0x00040000 ) +#define ERRFILE_ipv4 ( ERRFILE_NET | 0x00050000 ) +#define ERRFILE_ipv6 ( ERRFILE_NET | 0x00060000 ) +#define ERRFILE_ndp ( ERRFILE_NET | 0x00070000 ) +#define ERRFILE_netdevice ( ERRFILE_NET | 0x00080000 ) +#define ERRFILE_nullnet ( ERRFILE_NET | 0x00090000 ) +#define ERRFILE_tcp ( ERRFILE_NET | 0x000a0000 ) +#define ERRFILE_ftp ( ERRFILE_NET | 0x000b0000 ) +#define ERRFILE_http ( ERRFILE_NET | 0x000c0000 ) +#define ERRFILE_iscsi ( ERRFILE_NET | 0x000d0000 ) +#define ERRFILE_tcpip ( ERRFILE_NET | 0x000e0000 ) +#define ERRFILE_udp ( ERRFILE_NET | 0x000f0000 ) +#define ERRFILE_dhcp ( ERRFILE_NET | 0x00100000 ) +#define ERRFILE_dns ( ERRFILE_NET | 0x00110000 ) +#define ERRFILE_tftp ( ERRFILE_NET | 0x00120000 ) + +#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 ) +#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 ) +#define ERRFILE_script ( ERRFILE_IMAGE | 0x00020000 ) +#define ERRFILE_segment ( ERRFILE_IMAGE | 0x00030000 ) + +#define ERRFILE_asn1 ( ERRFILE_OTHER | 0x00000000 ) +#define ERRFILE_chap ( ERRFILE_OTHER | 0x00010000 ) +#define ERRFILE_aoeboot ( ERRFILE_OTHER | 0x00020000 ) +#define ERRFILE_autoboot ( ERRFILE_OTHER | 0x00030000 ) +#define ERRFILE_dhcpmgmt ( ERRFILE_OTHER | 0x00040000 ) +#define ERRFILE_imgmgmt ( ERRFILE_OTHER | 0x00050000 ) +#define ERRFILE_pxe_tftp ( ERRFILE_OTHER | 0x00060000 ) +#define ERRFILE_pxe_udp ( ERRFILE_OTHER | 0x00070000 ) +#define ERRFILE_axtls_aes ( ERRFILE_OTHER | 0x00080000 ) +#define ERRFILE_cipher ( ERRFILE_OTHER | 0x00090000 ) +#define ERRFILE_image_cmd ( ERRFILE_OTHER | 0x000a0000 ) +#define ERRFILE_uri_test ( ERRFILE_OTHER | 0x000b0000 ) + +/** @} */ + +#endif /* _GPXE_ERRFILE_H */ diff --git a/src/include/gpxe/errortab.h b/src/include/gpxe/errortab.h index 470f7e79..e9a56768 100644 --- a/src/include/gpxe/errortab.h +++ b/src/include/gpxe/errortab.h @@ -7,7 +7,6 @@ * */ -#include #include struct errortab { diff --git a/src/include/gpxe/iobuf.h b/src/include/gpxe/iobuf.h index c7451a08..c0dfd434 100644 --- a/src/include/gpxe/iobuf.h +++ b/src/include/gpxe/iobuf.h @@ -9,7 +9,6 @@ #include #include -#include #include /** @@ -162,26 +161,9 @@ static inline size_t iob_tailroom ( struct io_buffer *iobuf ) { return ( iobuf->end - iobuf->tail ); } -/** - * Ensure I/O buffer has sufficient headroom - * - * @v iobuf I/O buffer - * @v len Required headroom - * - * This function currently only checks for the required headroom; it - * does not reallocate the I/O buffer if required. If we ever have a - * code path that requires this functionality, it's a fairly trivial - * change to make. - */ -static inline __attribute__ (( always_inline )) int -iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ) { - if ( iob_headroom ( iobuf ) >= len ) - return 0; - return -ENOBUFS; -} - extern struct io_buffer * alloc_iob ( size_t len ); extern void free_iob ( struct io_buffer *iobuf ); extern void iob_pad ( struct io_buffer *iobuf, size_t min_len ); +extern int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ); #endif /* _GPXE_IOBUF_H */ diff --git a/src/include/gpxe/ndp.h b/src/include/gpxe/ndp.h index 2eae2958..db32b0c8 100644 --- a/src/include/gpxe/ndp.h +++ b/src/include/gpxe/ndp.h @@ -1,6 +1,5 @@ #include #include -#include #include #include #include diff --git a/src/interface/pxe/pxe_errors.c b/src/interface/pxe/pxe_errors.c index 3b00127b..f884ef8a 100644 --- a/src/interface/pxe/pxe_errors.c +++ b/src/interface/pxe/pxe_errors.c @@ -1,3 +1,4 @@ +#include #include /* diff --git a/src/interface/pxe/pxe_tftp.c b/src/interface/pxe/pxe_tftp.c index 44fb820e..5197a631 100644 --- a/src/interface/pxe/pxe_tftp.c +++ b/src/interface/pxe/pxe_tftp.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include diff --git a/src/net/nullnet.c b/src/net/nullnet.c index 4b6ba4c1..7e199ce3 100644 --- a/src/net/nullnet.c +++ b/src/net/nullnet.c @@ -17,6 +17,7 @@ */ #include +#include #include #include diff --git a/src/net/tcp.c b/src/net/tcp.c index b2d9b2de..01daf75a 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -395,7 +395,6 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) { size_t seq_len; size_t app_win; size_t rcv_win; - int rc; /* If retransmission timer is already running, do nothing */ if ( timer_running ( &tcp->timer ) ) @@ -485,25 +484,8 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) { DBGC ( tcp, "\n" ); /* Transmit packet */ - rc = tcpip_tx ( iobuf, &tcp_protocol, &tcp->peer, NULL, &tcphdr->csum ); - - /* If we got -ENETUNREACH, kill the connection immediately - * because there is no point retrying. This isn't strictly - * necessary (since we will eventually time out anyway), but - * it avoids irritating needless delays. Don't do this for - * RST packets transmitted on connection abort, to avoid a - * potential infinite loop. - */ - if ( ( ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_RST ) ) ) && - ( rc == -ENETUNREACH ) ) { - DBGC ( tcp, "TCP %p aborting after TX failed: %s\n", - tcp, strerror ( rc ) ); - tcp->tcp_state = TCP_CLOSED; - tcp_dump_state ( tcp ); - tcp_close ( tcp, rc ); - } - - return rc; + return tcpip_tx ( iobuf, &tcp_protocol, &tcp->peer, NULL, + &tcphdr->csum ); } /** -- cgit v1.2.3-55-g7522