Add qemu 2.4.0
[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
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <stdio.h>
23 #include <stdint.h>
24 #include <stdarg.h>
25 #include <ctype.h>
26 #include <ipxe/console.h>
27
28 /**
29  * Print debug message
30  *
31  * @v fmt               Format string
32  * @v ...               Arguments
33  */
34 void dbg_printf ( const char *fmt, ... ) {
35         int saved_usage;
36         va_list args;
37
38         /* Mark console as in use for debugging messages */
39         saved_usage = console_set_usage ( CONSOLE_USAGE_DEBUG );
40
41         /* Print message */
42         va_start ( args, fmt );
43         vprintf ( fmt, args );
44         va_end ( args );
45
46         /* Restore console usage */
47         console_set_usage ( saved_usage );
48 }
49
50 /**
51  * Pause until a key is pressed
52  *
53  */
54 void dbg_pause ( void ) {
55         dbg_printf ( "\nPress a key..." );
56         getchar();
57         dbg_printf ( "\r              \r" );
58 }
59
60 /**
61  * Indicate more data to follow and pause until a key is pressed
62  *
63  */
64 void dbg_more ( void ) {
65         dbg_printf ( "---more---" );
66         getchar();
67         dbg_printf ( "\r          \r" );
68 }
69
70 /**
71  * Print row of a hex dump with specified display address
72  *
73  * @v dispaddr          Display address
74  * @v data              Data to print
75  * @v len               Length of data
76  * @v offset            Starting offset within data
77  */
78 static void dbg_hex_dump_da_row ( unsigned long dispaddr, const void *data,
79                                   unsigned long len, unsigned int offset ) {
80         const uint8_t *bytes = data;
81         unsigned int i;
82         uint8_t byte;
83
84         dbg_printf ( "%08lx :", ( dispaddr + offset ) );
85         for ( i = offset ; i < ( offset + 16 ) ; i++ ) {
86                 if ( i >= len ) {
87                         dbg_printf ( "   " );
88                         continue;
89                 }
90                 dbg_printf ( "%c%02x",
91                              ( ( ( i % 16 ) == 8 ) ? '-' : ' ' ), bytes[i] );
92         }
93         dbg_printf ( " : " );
94         for ( i = offset ; i < ( offset + 16 ) ; i++ ) {
95                 if ( i >= len ) {
96                         dbg_printf ( " " );
97                         continue;
98                 }
99                 byte = bytes[i];
100                 dbg_printf ( "%c", ( isprint ( byte ) ? byte : '.' ) );
101         }
102         dbg_printf ( "\n" );
103 }
104
105 /**
106  * Print hex dump with specified display address
107  *
108  * @v dispaddr          Display address
109  * @v data              Data to print
110  * @v len               Length of data
111  */
112 void dbg_hex_dump_da ( unsigned long dispaddr, const void *data,
113                        unsigned long len ) {
114         unsigned int offset;
115
116         for ( offset = 0 ; offset < len ; offset += 16 ) {
117                 dbg_hex_dump_da_row ( dispaddr, data, len, offset );
118         }
119 }
120
121 /**
122  * Base message stream colour
123  *
124  * We default to using 31 (red foreground) as the base colour.
125  */
126 #ifndef DBGCOL_MIN
127 #define DBGCOL_MIN 31
128 #endif
129
130 /**
131  * Maximum number of separately coloured message streams
132  *
133  * Six is the realistic maximum; there are 8 basic ANSI colours, one
134  * of which will be the terminal default and one of which will be
135  * invisible on the terminal because it matches the background colour.
136  */
137 #ifndef DBGCOL_MAX
138 #define DBGCOL_MAX ( DBGCOL_MIN + 6 - 1 )
139 #endif
140
141 /** A colour assigned to an autocolourised debug message stream */
142 struct autocolour {
143         /** Message stream ID */
144         unsigned long stream;
145         /** Last recorded usage */
146         unsigned long last_used;
147 };
148
149 /**
150  * Choose colour index for debug autocolourisation
151  *
152  * @v stream            Message stream ID
153  * @ret colour          Colour ID
154  */
155 static int dbg_autocolour ( unsigned long stream ) {
156         static struct autocolour acs[ DBGCOL_MAX - DBGCOL_MIN + 1 ];
157         static unsigned long use;
158         unsigned int i;
159         unsigned int oldest;
160         unsigned int oldest_last_used;
161
162         /* Increment usage iteration counter */
163         use++;
164
165         /* Scan through list for a currently assigned colour */
166         for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
167                 if ( acs[i].stream == stream ) {
168                         acs[i].last_used = use;
169                         return i;
170                 }
171         }
172
173         /* No colour found; evict the oldest from the list */
174         oldest = 0;
175         oldest_last_used = use;
176         for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
177                 if ( acs[i].last_used < oldest_last_used ) {
178                         oldest_last_used = acs[i].last_used;
179                         oldest = i;
180                 }
181         }
182         acs[oldest].stream = stream;
183         acs[oldest].last_used = use;
184         return oldest;
185 }
186
187 /**
188  * Select automatic colour for debug messages
189  *
190  * @v stream            Message stream ID
191  */
192 void dbg_autocolourise ( unsigned long stream ) {
193         dbg_printf ( "\033[%dm",
194                      ( stream ? ( DBGCOL_MIN + dbg_autocolour ( stream ) ) :0));
195 }
196
197 /**
198  * Revert to normal colour
199  *
200  */
201 void dbg_decolourise ( void ) {
202         dbg_printf ( "\033[0m" );
203 }