Added auto-colourising DBGC() macro
[gpxe.git] / src / core / debug.c
1 #include <stdint.h>
2 #include <stdarg.h>
3 #include <io.h>
4 #include <console.h>
5
6 void pause ( void ) {
7         printf ( "\nPress a key" );
8         getchar();
9         printf ( "\r           \r" );
10 }
11
12 void more ( void ) {
13         printf ( "---more---" );
14         getchar();
15         printf ( "\r          \r" );
16 }
17
18 /* Produce a paged hex dump of the specified data and length */
19 void hex_dump ( const unsigned char *data, const unsigned int len ) {
20         unsigned int index;
21         for ( index = 0; index < len; index++ ) {
22                 if ( ( index % 16 ) == 0 ) {
23                         printf ( "\n" );
24                 }
25                 if ( ( index % 368 ) == 352 ) {
26                         more();
27                 }
28                 if ( ( index % 16 ) == 0 ) {
29                         printf ( "%p [%lx] : %04x :", data + index,
30                                  virt_to_phys ( data + index ), index );
31                 }
32                 printf ( " %02x", data[index] );
33         }
34         printf ( "\n" );
35 }
36
37 #define GUARD_SYMBOL ( ( 'M' << 24 ) | ( 'I' << 16 ) | ( 'N' << 8 ) | 'E' )
38 /* Fill a region with guard markers.  We use a 4-byte pattern to make
39  * it less likely that check_region will find spurious 1-byte regions
40  * of non-corruption.
41  */
42 void guard_region ( void *region, size_t len ) {
43         uint32_t offset = 0;
44
45         len &= ~0x03;
46         for ( offset = 0; offset < len ; offset += 4 ) {
47                 *((uint32_t *)(region + offset)) = GUARD_SYMBOL;
48         }
49 }
50
51 /* Check a region that has been guarded with guard_region() for
52  * corruption.
53  */
54 int check_region ( void *region, size_t len ) {
55         uint8_t corrupted = 0;
56         uint8_t in_corruption = 0;
57         uint32_t offset = 0;
58         uint32_t test = 0;
59
60         len &= ~0x03;
61         for ( offset = 0; offset < len ; offset += 4 ) {
62                 test = *((uint32_t *)(region + offset)) = GUARD_SYMBOL;
63                 if ( ( in_corruption == 0 ) &&
64                      ( test != GUARD_SYMBOL ) ) {
65                         /* Start of corruption */
66                         if ( corrupted == 0 ) {
67                                 corrupted = 1;
68                                 printf ( "Region %p-%p (physical %#lx-%#lx) "
69                                          "corrupted\n",
70                                          region, region + len,
71                                          virt_to_phys ( region ),
72                                          virt_to_phys ( region + len ) );
73                         }
74                         in_corruption = 1;
75                         printf ( "--- offset %#lx ", offset );
76                 } else if ( ( in_corruption != 0 ) &&
77                             ( test == GUARD_SYMBOL ) ) {
78                         /* End of corruption */
79                         in_corruption = 0;
80                         printf ( "to offset %#lx", offset );
81                 }
82
83         }
84         if ( in_corruption != 0 ) {
85                 printf ( "to offset %#x (end of region)\n", len-1 );
86         }
87         return corrupted;
88 }
89
90 #define NUM_AUTO_COLOURS 6
91
92 struct autocolour {
93         void * id;
94         unsigned long last_used;
95 };
96
97 static int autocolourise ( void *id ) {
98         static struct autocolour acs[NUM_AUTO_COLOURS];
99         static unsigned long use;
100         unsigned int i;
101         unsigned int oldest;
102         unsigned int oldest_last_used;
103
104         /* Increment usage iteration counter */
105         use++;
106
107         /* Scan through list for a currently assigned colour */
108         for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
109                 if ( acs[i].id == id ) {
110                         acs[i].last_used = use;
111                         return i;
112                 }
113         }
114
115         /* No colour found; evict the oldest from the list */
116         oldest = 0;
117         oldest_last_used = use;
118         for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
119                 if ( acs[i].last_used < oldest_last_used ) {
120                         oldest_last_used = acs[i].last_used;
121                         oldest = i;
122                 }
123         }
124         acs[oldest].id = id;
125         acs[oldest].last_used = use;
126         return oldest;
127 }
128
129 /** printf() for debugging with automatic colourisation
130  *
131  * @v id                Message stream ID
132  * @v fmt               printf() format
133  * @v ...               printf() argument list
134  */
135 void dbg_printf_autocolour ( void *id, const char *fmt, ... ) {
136         va_list args;
137
138         printf ( "\033[%dm", ( id ? ( 31 + autocolourise ( id ) ) : 0 ) );
139         va_start ( args, fmt );
140         vprintf ( fmt, args );
141         va_end ( args );
142         printf ( "\033[0m" );
143 }