Handle structured error codes.
authorMichael Brown <mcb30@etherboot.org>
Fri, 19 Jan 2007 13:52:50 +0000 (13:52 +0000)
committerMichael Brown <mcb30@etherboot.org>
Fri, 19 Jan 2007 13:52:50 +0000 (13:52 +0000)
src/hci/strerror.c

index 56b07e8..045e635 100644 (file)
@@ -24,9 +24,60 @@ static struct errortab errortab_end[0]
        __table_end ( struct errortab, errortab );
 
 /**
- * Retrieve string representation of error number.
+ * Find error description
+ *
+ * @v errno            Error number
+ * @v mask             Mask of bits that we care about
+ * @ret errortab       Error description, or NULL
+ */
+static struct errortab * find_error ( int errno, int mask ) {
+       struct errortab *errortab;
+
+       for ( errortab = errortab_start ; errortab < errortab_end ;
+             errortab++ ) {
+               if ( ( ( errortab->errno ^ errno ) & mask ) == 0 )
+                       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, 0x7fffffff ) ) != NULL )
+               return errortab;
+
+       /* 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 )
+               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
@@ -37,21 +88,25 @@ static struct errortab errortab_end[0]
  *
  */
 const char * strerror ( int errno ) {
-       static char *generic_message = "Error 0x0000";
+       static char errbuf[64];
        struct errortab *errortab;
 
        /* Allow for strerror(rc) as well as strerror(errno) */
        if ( errno < 0 )
                errno = -errno;
 
-       for ( errortab = errortab_start ; errortab < errortab_end ;
-             errortab++ ) {
-               if ( errortab->errno == errno )
-                       return errortab->text;
+       /* Find the error description, if one exists */
+       errortab = find_closest_error ( errno );
+
+       /* Construct the error message */
+       if ( errortab ) {
+               snprintf ( errbuf, sizeof ( errbuf ), "%s (%#08x)",
+                          errortab->text, errno );
+       } else {
+               snprintf ( errbuf, sizeof ( errbuf ), "Error %#08x", errno );
        }
 
-       sprintf ( generic_message + 8, "%hx", errno );
-       return generic_message;
+       return errbuf;
 }
 
 /** The most common errors */