debug.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdint.h>
00003 #include <stdarg.h>
00004 #include <gpxe/io.h>
00005 #include <console.h>
00006 
00007 void pause ( void ) {
00008         printf ( "\nPress a key" );
00009         getchar();
00010         printf ( "\r           \r" );
00011 }
00012 
00013 void more ( void ) {
00014         printf ( "---more---" );
00015         getchar();
00016         printf ( "\r          \r" );
00017 }
00018 
00019 /**
00020  * Print row of a hex dump with specified display address
00021  *
00022  * @v dispaddr          Display address
00023  * @v data              Data to print
00024  * @v len               Length of data
00025  * @v offset            Starting offset within data
00026  */
00027 static void dbg_hex_dump_da_row ( unsigned long dispaddr, const void *data,
00028                                   unsigned long len, unsigned int offset ) {
00029         const uint8_t *bytes = data;
00030         unsigned int i;
00031         uint8_t byte;
00032 
00033         printf ( "%08lx :", ( dispaddr + offset ) );
00034         for ( i = offset ; i < ( offset + 16 ) ; i++ ) {
00035                 if ( i >= len ) {
00036                         printf ( "   " );
00037                         continue;
00038                 }
00039                 printf ( "%c%02x",
00040                          ( ( ( i % 16 ) == 8 ) ? '-' : ' ' ), bytes[i] );
00041         }
00042         printf ( " : " );
00043         for ( i = offset ; i < ( offset + 16 ) ; i++ ) {
00044                 if ( i >= len ) {
00045                         printf ( " " );
00046                         continue;
00047                 }
00048                 byte = bytes[i];
00049                 if ( ( byte < 0x20 ) || ( byte >= 0x7f ) )
00050                         byte = '.';
00051                 printf ( "%c", byte );
00052         }
00053         printf ( "\n" );
00054 }
00055 
00056 /**
00057  * Print hex dump with specified display address
00058  *
00059  * @v dispaddr          Display address
00060  * @v data              Data to print
00061  * @v len               Length of data
00062  */
00063 void dbg_hex_dump_da ( unsigned long dispaddr, const void *data,
00064                        unsigned long len ) {
00065         unsigned int offset;
00066 
00067         for ( offset = 0 ; offset < len ; offset += 16 ) {
00068                 dbg_hex_dump_da_row ( dispaddr, data, len, offset );
00069         }
00070 }
00071 
00072 #define GUARD_SYMBOL ( ( 'M' << 24 ) | ( 'I' << 16 ) | ( 'N' << 8 ) | 'E' )
00073 /* Fill a region with guard markers.  We use a 4-byte pattern to make
00074  * it less likely that check_region will find spurious 1-byte regions
00075  * of non-corruption.
00076  */
00077 void guard_region ( void *region, size_t len ) {
00078         uint32_t offset = 0;
00079 
00080         len &= ~0x03;
00081         for ( offset = 0; offset < len ; offset += 4 ) {
00082                 *((uint32_t *)(region + offset)) = GUARD_SYMBOL;
00083         }
00084 }
00085 
00086 /* Check a region that has been guarded with guard_region() for
00087  * corruption.
00088  */
00089 int check_region ( void *region, size_t len ) {
00090         uint8_t corrupted = 0;
00091         uint8_t in_corruption = 0;
00092         uint32_t offset = 0;
00093         uint32_t test = 0;
00094 
00095         len &= ~0x03;
00096         for ( offset = 0; offset < len ; offset += 4 ) {
00097                 test = *((uint32_t *)(region + offset)) = GUARD_SYMBOL;
00098                 if ( ( in_corruption == 0 ) &&
00099                      ( test != GUARD_SYMBOL ) ) {
00100                         /* Start of corruption */
00101                         if ( corrupted == 0 ) {
00102                                 corrupted = 1;
00103                                 printf ( "Region %p-%p (physical %#lx-%#lx) "
00104                                          "corrupted\n",
00105                                          region, region + len,
00106                                          virt_to_phys ( region ),
00107                                          virt_to_phys ( region + len ) );
00108                         }
00109                         in_corruption = 1;
00110                         printf ( "--- offset %#x ", offset );
00111                 } else if ( ( in_corruption != 0 ) &&
00112                             ( test == GUARD_SYMBOL ) ) {
00113                         /* End of corruption */
00114                         in_corruption = 0;
00115                         printf ( "to offset %#x", offset );
00116                 }
00117 
00118         }
00119         if ( in_corruption != 0 ) {
00120                 printf ( "to offset %#zx (end of region)\n", len-1 );
00121         }
00122         return corrupted;
00123 }
00124 
00125 /**
00126  * Maximum number of separately coloured message streams
00127  *
00128  * Six is the realistic maximum; there are 8 basic ANSI colours, one
00129  * of which will be the terminal default and one of which will be
00130  * invisible on the terminal because it matches the background colour.
00131  */
00132 #define NUM_AUTO_COLOURS 6
00133 
00134 /** A colour assigned to an autocolourised debug message stream */
00135 struct autocolour {
00136         /** Message stream ID */
00137         unsigned long stream;
00138         /** Last recorded usage */
00139         unsigned long last_used;
00140 };
00141 
00142 /**
00143  * Choose colour index for debug autocolourisation
00144  *
00145  * @v stream            Message stream ID
00146  * @ret colour          Colour ID
00147  */
00148 static int dbg_autocolour ( unsigned long stream ) {
00149         static struct autocolour acs[NUM_AUTO_COLOURS];
00150         static unsigned long use;
00151         unsigned int i;
00152         unsigned int oldest;
00153         unsigned int oldest_last_used;
00154 
00155         /* Increment usage iteration counter */
00156         use++;
00157 
00158         /* Scan through list for a currently assigned colour */
00159         for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
00160                 if ( acs[i].stream == stream ) {
00161                         acs[i].last_used = use;
00162                         return i;
00163                 }
00164         }
00165 
00166         /* No colour found; evict the oldest from the list */
00167         oldest = 0;
00168         oldest_last_used = use;
00169         for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
00170                 if ( acs[i].last_used < oldest_last_used ) {
00171                         oldest_last_used = acs[i].last_used;
00172                         oldest = i;
00173                 }
00174         }
00175         acs[oldest].stream = stream;
00176         acs[oldest].last_used = use;
00177         return oldest;
00178 }
00179 
00180 /**
00181  * Select automatic colour for debug messages
00182  *
00183  * @v stream            Message stream ID
00184  */
00185 void dbg_autocolourise ( unsigned long stream ) {
00186         printf ( "\033[%dm",
00187                  ( stream ? ( 31 + dbg_autocolour ( stream ) ) : 0 ) );
00188 }
00189 
00190 /**
00191  * Revert to normal colour
00192  *
00193  */
00194 void dbg_decolourise ( void ) {
00195         printf ( "\033[0m" );
00196 }

Generated on Tue Apr 6 20:00:51 2010 for gPXE by  doxygen 1.5.7.1