These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / core / debug.c
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <stdarg.h>
29 #include <ctype.h>
30 #include <ipxe/console.h>
31
32 /**
33  * Print debug message
34  *
35  * @v fmt               Format string
36  * @v ...               Arguments
37  */
38 void dbg_printf ( const char *fmt, ... ) {
39         int saved_usage;
40         va_list args;
41
42         /* Mark console as in use for debugging messages */
43         saved_usage = console_set_usage ( CONSOLE_USAGE_DEBUG );
44
45         /* Print message */
46         va_start ( args, fmt );
47         vprintf ( fmt, args );
48         va_end ( args );
49
50         /* Restore console usage */
51         console_set_usage ( saved_usage );
52 }
53
54 /**
55  * Pause until a key is pressed
56  *
57  */
58 void dbg_pause ( void ) {
59         dbg_printf ( "\nPress a key..." );
60         getchar();
61         dbg_printf ( "\r              \r" );
62 }
63
64 /**
65  * Indicate more data to follow and pause until a key is pressed
66  *
67  */
68 void dbg_more ( void ) {
69         dbg_printf ( "---more---" );
70         getchar();
71         dbg_printf ( "\r          \r" );
72 }
73
74 /**
75  * Print row of a hex dump with specified display address
76  *
77  * @v dispaddr          Display address
78  * @v data              Data to print
79  * @v len               Length of data
80  * @v offset            Starting offset within data
81  */
82 static void dbg_hex_dump_da_row ( unsigned long dispaddr, const void *data,
83                                   unsigned long len, unsigned int offset ) {
84         const uint8_t *bytes = data;
85         unsigned int i;
86         uint8_t byte;
87
88         dbg_printf ( "%08lx :", ( dispaddr + offset ) );
89         for ( i = offset ; i < ( offset + 16 ) ; i++ ) {
90                 if ( i >= len ) {
91                         dbg_printf ( "   " );
92                         continue;
93                 }
94                 dbg_printf ( "%c%02x",
95                              ( ( ( i % 16 ) == 8 ) ? '-' : ' ' ), bytes[i] );
96         }
97         dbg_printf ( " : " );
98         for ( i = offset ; i < ( offset + 16 ) ; i++ ) {
99                 if ( i >= len ) {
100                         dbg_printf ( " " );
101                         continue;
102                 }
103                 byte = bytes[i];
104                 dbg_printf ( "%c", ( isprint ( byte ) ? byte : '.' ) );
105         }
106         dbg_printf ( "\n" );
107 }
108
109 /**
110  * Print hex dump with specified display address
111  *
112  * @v dispaddr          Display address
113  * @v data              Data to print
114  * @v len               Length of data
115  */
116 void dbg_hex_dump_da ( unsigned long dispaddr, const void *data,
117                        unsigned long len ) {
118         unsigned int offset;
119
120         for ( offset = 0 ; offset < len ; offset += 16 ) {
121                 dbg_hex_dump_da_row ( dispaddr, data, len, offset );
122         }
123 }
124
125 /**
126  * Base message stream colour
127  *
128  * We default to using 31 (red foreground) as the base colour.
129  */
130 #ifndef DBGCOL_MIN
131 #define DBGCOL_MIN 31
132 #endif
133
134 /**
135  * Maximum number of separately coloured message streams
136  *
137  * Six is the realistic maximum; there are 8 basic ANSI colours, one
138  * of which will be the terminal default and one of which will be
139  * invisible on the terminal because it matches the background colour.
140  */
141 #ifndef DBGCOL_MAX
142 #define DBGCOL_MAX ( DBGCOL_MIN + 6 - 1 )
143 #endif
144
145 /** A colour assigned to an autocolourised debug message stream */
146 struct autocolour {
147         /** Message stream ID */
148         unsigned long stream;
149         /** Last recorded usage */
150         unsigned long last_used;
151 };
152
153 /**
154  * Choose colour index for debug autocolourisation
155  *
156  * @v stream            Message stream ID
157  * @ret colour          Colour ID
158  */
159 static int dbg_autocolour ( unsigned long stream ) {
160         static struct autocolour acs[ DBGCOL_MAX - DBGCOL_MIN + 1 ];
161         static unsigned long use;
162         unsigned int i;
163         unsigned int oldest;
164         unsigned int oldest_last_used;
165
166         /* Increment usage iteration counter */
167         use++;
168
169         /* Scan through list for a currently assigned colour */
170         for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
171                 if ( acs[i].stream == stream ) {
172                         acs[i].last_used = use;
173                         return i;
174                 }
175         }
176
177         /* No colour found; evict the oldest from the list */
178         oldest = 0;
179         oldest_last_used = use;
180         for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
181                 if ( acs[i].last_used < oldest_last_used ) {
182                         oldest_last_used = acs[i].last_used;
183                         oldest = i;
184                 }
185         }
186         acs[oldest].stream = stream;
187         acs[oldest].last_used = use;
188         return oldest;
189 }
190
191 /**
192  * Select automatic colour for debug messages
193  *
194  * @v stream            Message stream ID
195  */
196 void dbg_autocolourise ( unsigned long stream ) {
197         dbg_printf ( "\033[%dm",
198                      ( stream ? ( DBGCOL_MIN + dbg_autocolour ( stream ) ) :0));
199 }
200
201 /**
202  * Revert to normal colour
203  *
204  */
205 void dbg_decolourise ( void ) {
206         dbg_printf ( "\033[0m" );
207 }