3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #if DBG && !defined(_M_ARM)
28 // #define DEBUG_INIFILE
29 // #define DEBUG_REACTOS
30 // #define DEBUG_CUSTOM
33 #define DBG_DEFAULT_LEVELS (ERR_LEVEL|FIXME_LEVEL)
35 static UCHAR DbgChannels
[DBG_CHANNELS_COUNT
];
41 #define BOCHS_OUTPUT_PORT 0xE9
43 ULONG DebugPort
= RS232
;
45 /* Serial debug connection */
46 ULONG ComPort
= 0; // The COM port initializer chooses the first available port starting from COM4 down to COM1.
47 ULONG BaudRate
= 115200;
48 ULONG PortIrq
= 0; // Not used at the moment.
50 BOOLEAN DebugStartOfLine
= TRUE
;
52 VOID
DebugInit(BOOLEAN MainInit
)
54 PCHAR CommandLine
, PortString
, BaudString
, IrqString
;
56 CHAR DebugString
[256];
58 /* Always reset the debugging channels */
60 #if defined (DEBUG_ALL)
61 memset(DbgChannels
, MAX_LEVEL
, DBG_CHANNELS_COUNT
);
62 #elif defined (DEBUG_WARN)
63 memset(DbgChannels
, WARN_LEVEL
|FIXME_LEVEL
|ERR_LEVEL
, DBG_CHANNELS_COUNT
);
64 #elif defined (DEBUG_ERR)
65 memset(DbgChannels
, ERR_LEVEL
, DBG_CHANNELS_COUNT
);
67 memset(DbgChannels
, 0, DBG_CHANNELS_COUNT
);
70 #if defined (DEBUG_INIFILE)
71 DbgChannels
[DPRINT_INIFILE
] = MAX_LEVEL
;
72 #elif defined (DEBUG_REACTOS)
73 DbgChannels
[DPRINT_REACTOS
] = MAX_LEVEL
;
74 DbgChannels
[DPRINT_REGISTRY
] = MAX_LEVEL
;
75 #elif defined (DEBUG_CUSTOM)
76 DbgChannels
[DPRINT_WARNING
] = MAX_LEVEL
;
77 DbgChannels
[DPRINT_WINDOWS
] = MAX_LEVEL
;
80 /* Check for pre- or main initialization phase */
83 /* Pre-initialization phase: use the FreeLdr command-line debugging string */
84 CommandLine
= (PCHAR
)CmdLineGetDebugString();
86 /* If no command-line is provided, initialize the debug port with default settings */
87 if (CommandLine
== NULL
)
90 strcpy(DebugString
, CommandLine
);
94 /* Main initialization phase: use the FreeLdr INI debugging string */
98 if (!IniOpenSection("FreeLoader", &SectionId
))
101 if (!IniReadSettingByName(SectionId
, "Debug", DebugString
, sizeof(DebugString
)))
105 /* Get the Command Line */
106 CommandLine
= DebugString
;
109 _strupr(CommandLine
);
111 /* Get the port and baud rate */
112 PortString
= strstr(CommandLine
, "DEBUGPORT");
113 BaudString
= strstr(CommandLine
, "BAUDRATE");
114 IrqString
= strstr(CommandLine
, "IRQ");
117 * Check if we got /DEBUGPORT parameters.
118 * NOTE: Inspired by reactos/ntoskrnl/kd/kdinit.c, KdInitSystem(...)
122 /* Move past the actual string, to reach the port*/
123 PortString
+= strlen("DEBUGPORT");
125 /* Now get past any spaces and skip the equal sign */
126 while (*PortString
== ' ') PortString
++;
129 /* Check for possible ports and set the port to use */
130 if (strncmp(PortString
, "SCREEN", 6) == 0)
135 else if (strncmp(PortString
, "BOCHS", 5) == 0)
140 else if (strncmp(PortString
, "COM", 3) == 0)
145 /* Set the port to use */
146 Value
= atol(PortString
);
147 if (Value
) ComPort
= Value
;
150 PortString
= strstr(PortString
, "DEBUGPORT");
153 /* Check if we got a baud rate */
156 /* Move past the actual string, to reach the rate */
157 BaudString
+= strlen("BAUDRATE");
159 /* Now get past any spaces */
160 while (*BaudString
== ' ') BaudString
++;
162 /* And make sure we have a rate */
165 /* Read and set it */
166 Value
= atol(BaudString
+ 1);
167 if (Value
) BaudRate
= Value
;
171 /* Check Serial Port Settings [IRQ] */
174 /* Move past the actual string, to reach the rate */
175 IrqString
+= strlen("IRQ");
177 /* Now get past any spaces */
178 while (*IrqString
== ' ') IrqString
++;
180 /* And make sure we have an IRQ */
183 /* Read and set it */
184 Value
= atol(IrqString
+ 1);
185 if (Value
) PortIrq
= Value
;
190 /* Try to initialize the port; if it fails, remove the corresponding flag */
191 if (DebugPort
& RS232
)
193 if (!Rs232PortInitialize(ComPort
, BaudRate
))
198 VOID
DebugPrintChar(UCHAR Character
)
200 if (Character
== '\n')
201 DebugStartOfLine
= TRUE
;
203 if (DebugPort
& RS232
)
205 if (Character
== '\n')
206 Rs232PortPutByte('\r');
208 Rs232PortPutByte(Character
);
210 if (DebugPort
& BOCHS
)
212 WRITE_PORT_UCHAR((PUCHAR
)BOCHS_OUTPUT_PORT
, Character
);
214 if (DebugPort
& SCREEN
)
216 MachConsPutChar(Character
);
221 DbgPrint(const char *Format
, ...)
228 va_start(ap
, Format
);
229 Length
= _vsnprintf(Buffer
, sizeof(Buffer
), Format
, ap
);
232 /* Check if we went past the buffer */
235 /* Terminate it if we went over-board */
236 Buffer
[sizeof(Buffer
) - 1] = '\n';
239 Length
= sizeof(Buffer
);
244 DebugPrintChar(*ptr
++);
250 DbgPrint2(ULONG Mask
, ULONG Level
, const char *File
, ULONG Line
, char *Format
, ...)
256 /* Mask out unwanted debug messages */
257 if (!(DbgChannels
[Mask
] & Level
) && !(Level
& DBG_DEFAULT_LEVELS
))
262 /* Print the header if we have started a new line */
263 if (DebugStartOfLine
)
265 DbgPrint("(%s:%lu) ", File
, Line
);
283 DebugStartOfLine
= FALSE
;
286 va_start(ap
, Format
);
287 vsprintf(Buffer
, Format
, ap
);
292 DebugPrintChar(*ptr
++);
297 DebugDumpBuffer(ULONG Mask
, PVOID Buffer
, ULONG Length
)
299 PUCHAR BufPtr
= (PUCHAR
)Buffer
;
300 ULONG Offset
, Count
, i
;
302 /* Mask out unwanted debug messages */
303 if (!(DbgChannels
[Mask
] & TRACE_LEVEL
))
306 DebugStartOfLine
= FALSE
; // We don't want line headers
307 DbgPrint("Dumping buffer at %p with length of %lu bytes:\n", Buffer
, Length
);
310 while (Offset
< Length
)
312 /* We don't want line headers */
313 DebugStartOfLine
= FALSE
;
315 /* Print the offset */
316 DbgPrint("%04x:\t", Offset
);
318 /* Print either 16 or the remaining number of bytes */
319 Count
= min(Length
- Offset
, 16);
320 for (i
= 0; i
< Count
; i
++, Offset
++)
322 DbgPrint("%02x%c", BufPtr
[Offset
], (i
== 7) ? '-' : ' ');
330 DbgAddDebugChannel(CHAR
* channel
, CHAR
* level
, CHAR op
)
332 int iLevel
, iChannel
;
334 if (channel
== NULL
|| *channel
== '\0' || strlen(channel
) == 0)
337 if (level
== NULL
|| *level
== '\0' || strlen(level
) == 0)
339 else if (strcmp(level
, "err") == 0)
341 else if (strcmp(level
, "fixme") == 0)
342 iLevel
= FIXME_LEVEL
;
343 else if (strcmp(level
, "warn") == 0)
345 else if (strcmp(level
, "trace") == 0)
346 iLevel
= TRACE_LEVEL
;
350 if (strcmp(channel
, "memory" ) == 0) iChannel
= DPRINT_MEMORY
;
351 else if (strcmp(channel
, "filesystem") == 0) iChannel
= DPRINT_FILESYSTEM
;
352 else if (strcmp(channel
, "inifile" ) == 0) iChannel
= DPRINT_INIFILE
;
353 else if (strcmp(channel
, "ui" ) == 0) iChannel
= DPRINT_UI
;
354 else if (strcmp(channel
, "disk" ) == 0) iChannel
= DPRINT_DISK
;
355 else if (strcmp(channel
, "cache" ) == 0) iChannel
= DPRINT_CACHE
;
356 else if (strcmp(channel
, "registry" ) == 0) iChannel
= DPRINT_REGISTRY
;
357 else if (strcmp(channel
, "linux" ) == 0) iChannel
= DPRINT_LINUX
;
358 else if (strcmp(channel
, "hwdetect" ) == 0) iChannel
= DPRINT_HWDETECT
;
359 else if (strcmp(channel
, "windows" ) == 0) iChannel
= DPRINT_WINDOWS
;
360 else if (strcmp(channel
, "peloader" ) == 0) iChannel
= DPRINT_PELOADER
;
361 else if (strcmp(channel
, "scsiport" ) == 0) iChannel
= DPRINT_SCSIPORT
;
362 else if (strcmp(channel
, "heap" ) == 0) iChannel
= DPRINT_HEAP
;
363 else if (strcmp(channel
, "all" ) == 0)
367 for (i
= 0; i
< DBG_CHANNELS_COUNT
; i
++)
370 DbgChannels
[i
] |= iLevel
;
372 DbgChannels
[i
] &= ~iLevel
;
380 DbgChannels
[iChannel
] |= iLevel
;
382 DbgChannels
[iChannel
] &= ~iLevel
;
388 DbgParseDebugChannels(PCHAR Value
)
390 CHAR
*str
, *separator
, *c
, op
;
396 separator
= strchr(str
, ',');
397 if (separator
!= NULL
)
400 c
= strchr(str
, '+');
402 c
= strchr(str
, '-');
410 DbgAddDebugChannel(c
, str
, op
);
414 } while (separator
!= NULL
);
420 DbgPrint(PCCH Format
, ...)
428 MsgBoxPrint(const char *Format
, ...)
434 va_start(ap
, Format
);
436 /* Construct a string */
437 Length
= _vsnprintf(Buffer
, 512, Format
, ap
);
439 /* Check if we went past the buffer */
440 if (Length
== MAXULONG
)
442 /* Terminate it if we went over-board */
443 Buffer
[sizeof(Buffer
) - 1] = '\n';
446 Length
= sizeof(Buffer
);
449 /* Show it as a message box */
450 UiMessageBox(Buffer
);
452 /* Cleanup and exit */
461 IN ULONG BugCheckCode
,
462 IN ULONG_PTR BugCheckParameter1
,
463 IN ULONG_PTR BugCheckParameter2
,
464 IN ULONG_PTR BugCheckParameter3
,
465 IN ULONG_PTR BugCheckParameter4
)
468 sprintf(Buffer
, "*** STOP: 0x%08lX (0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX)",
469 BugCheckCode
, BugCheckParameter1
, BugCheckParameter2
,
470 BugCheckParameter3
, BugCheckParameter4
);
471 UiMessageBoxCritical(Buffer
);
478 RtlAssert(IN PVOID FailedAssertion
,
481 IN PCHAR Message OPTIONAL
)
485 DbgPrint("Assertion \'%s\' failed at %s line %u: %s\n",
486 (PCHAR
)FailedAssertion
,
493 DbgPrint("Assertion \'%s\' failed at %s line %u\n",
494 (PCHAR
)FailedAssertion
,
502 char *BugCodeStrings
[] =
505 "MISSING_HARDWARE_REQUIREMENTS",
506 "FREELDR_IMAGE_CORRUPTION",
507 "MEMORY_INIT_FAILURE",
510 ULONG_PTR BugCheckInfo
[5];