4995ffa438
Users tend to gloss over cryptic-looking error messages such as "Boot failed: Exec format error (Error 0x2e852001)" In particular, users tend not to report the error number, which is the single most useful piece of diagnostic information in an iPXE error message. Try replacing the "Error 0x2e852001" portion with a URL, giving "Boot failed: Exec format error (http://ipxe.org/2e852001)" in the hope that users will, upon seeing something that is recognisably a URL, try viewing it in a web browser. Such users will be greeted by a web page containing a more detailed description of the error (automatically generated from the einfo text), including links to each line of code that might generate the error, and a section for additional user-contributed notes. At the time of writing, a user who visits http://ipxe.org/2e852001 would see a note saying "This error usually indicates that the SAN disk is empty, and does not yet contain a bootable operating system." which may be more useful than "Exec format error (Error 0x2e852001)". Signed-off-by: Michael Brown <mcb30@ipxe.org>
126 lines
3.1 KiB
C
126 lines
3.1 KiB
C
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <ipxe/errortab.h>
|
|
|
|
/** @file
|
|
*
|
|
* Error descriptions.
|
|
*
|
|
* The error numbers used by Etherboot are a superset of those defined
|
|
* by the PXE specification version 2.1. See errno.h for a listing of
|
|
* the error values.
|
|
*
|
|
* To save space in ROM images, error string tables are optional. Use
|
|
* the ERRORMSG_XXX options in config.h to select which error string
|
|
* tables you want to include. If an error string table is omitted,
|
|
* strerror() will simply return the text "Error 0x<errno>".
|
|
*
|
|
*/
|
|
|
|
FILE_LICENCE ( GPL2_OR_LATER );
|
|
|
|
/**
|
|
* Find error description
|
|
*
|
|
* @v errno Error number
|
|
* @ret errortab Error description, or NULL
|
|
*/
|
|
static struct errortab * find_error ( int errno ) {
|
|
struct errortab *errortab;
|
|
|
|
for_each_table_entry ( errortab, ERRORTAB ) {
|
|
if ( errortab->errno == errno )
|
|
return errortab;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* Find closest error description
|
|
*
|
|
* @v errno Error number
|
|
* @ret errortab Error description, or NULL
|
|
*
|
|
*
|
|
*/
|
|
static struct errortab * find_closest_error ( int errno ) {
|
|
struct errortab *errortab;
|
|
|
|
/* First, look for an exact match */
|
|
if ( ( errortab = find_error ( errno ) ) != NULL )
|
|
return errortab;
|
|
|
|
/* Second, try masking off the iPXE-specific bit and seeing if
|
|
* we have an entry for the generic POSIX error message.
|
|
*/
|
|
if ( ( errortab = find_error ( errno & 0x7f0000ff ) ) != NULL )
|
|
return errortab;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* Retrieve string representation of error number.
|
|
*
|
|
* @v errno/rc Error number or return status code
|
|
* @ret strerror Pointer to error text
|
|
*
|
|
* If the error is not found in the linked-in error tables, generates
|
|
* a generic "Error 0x<errno>" message.
|
|
*
|
|
* The pointer returned by strerror() is valid only until the next
|
|
* call to strerror().
|
|
*
|
|
*/
|
|
const char * strerror ( int errno ) {
|
|
static char errbuf[64];
|
|
struct errortab *errortab;
|
|
|
|
/* Allow for strerror(rc) as well as strerror(errno) */
|
|
if ( errno < 0 )
|
|
errno = -errno;
|
|
|
|
/* Find the error description, if one exists */
|
|
errortab = find_closest_error ( errno );
|
|
|
|
/* Construct the error message */
|
|
if ( errortab ) {
|
|
snprintf ( errbuf, sizeof ( errbuf ),
|
|
"%s (http://ipxe.org/%08x)",
|
|
errortab->text, errno );
|
|
} else {
|
|
snprintf ( errbuf, sizeof ( errbuf ),
|
|
"Error %#08x (http://ipxe.org/%08x)",
|
|
errno, 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 = {
|
|
__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 ),
|
|
};
|