xref: /haiku/src/system/boot/platform/bios_ia32/debug.cpp (revision 28a2172c3f19a34e31ba20085148e5428544823a)
1*28a2172cSIngo Weinhold /*
2*28a2172cSIngo Weinhold  * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
3*28a2172cSIngo Weinhold  * Distributed under the terms of the MIT License.
4*28a2172cSIngo Weinhold  */
5*28a2172cSIngo Weinhold 
6*28a2172cSIngo Weinhold 
7*28a2172cSIngo Weinhold #include "debug.h"
8*28a2172cSIngo Weinhold 
9*28a2172cSIngo Weinhold #include <stdarg.h>
10*28a2172cSIngo Weinhold #include <string.h>
11*28a2172cSIngo Weinhold 
12*28a2172cSIngo Weinhold #include <boot/platform.h>
13*28a2172cSIngo Weinhold #include <boot/stage2.h>
14*28a2172cSIngo Weinhold #include <boot/stdio.h>
15*28a2172cSIngo Weinhold #include <kernel.h>
16*28a2172cSIngo Weinhold #include <util/ring_buffer.h>
17*28a2172cSIngo Weinhold 
18*28a2172cSIngo Weinhold #include "keyboard.h"
19*28a2172cSIngo Weinhold #include "mmu.h"
20*28a2172cSIngo Weinhold #include "serial.h"
21*28a2172cSIngo Weinhold 
22*28a2172cSIngo Weinhold 
23*28a2172cSIngo Weinhold static const char* const kDebugSyslogSignature = "Haiku syslog";
24*28a2172cSIngo Weinhold 
25*28a2172cSIngo Weinhold static char sBuffer[16384];
26*28a2172cSIngo Weinhold static uint32 sBufferPosition;
27*28a2172cSIngo Weinhold 
28*28a2172cSIngo Weinhold static ring_buffer* sDebugSyslogBuffer = NULL;
29*28a2172cSIngo Weinhold 
30*28a2172cSIngo Weinhold 
31*28a2172cSIngo Weinhold /*!	This works only after console_init() was called.
32*28a2172cSIngo Weinhold */
33*28a2172cSIngo Weinhold void
34*28a2172cSIngo Weinhold panic(const char *format, ...)
35*28a2172cSIngo Weinhold {
36*28a2172cSIngo Weinhold 	va_list list;
37*28a2172cSIngo Weinhold 
38*28a2172cSIngo Weinhold 	platform_switch_to_text_mode();
39*28a2172cSIngo Weinhold 
40*28a2172cSIngo Weinhold 	puts("*** PANIC ***");
41*28a2172cSIngo Weinhold 
42*28a2172cSIngo Weinhold 	va_start(list, format);
43*28a2172cSIngo Weinhold 	vprintf(format, list);
44*28a2172cSIngo Weinhold 	va_end(list);
45*28a2172cSIngo Weinhold 
46*28a2172cSIngo Weinhold 	puts("\nPress key to reboot.");
47*28a2172cSIngo Weinhold 
48*28a2172cSIngo Weinhold 	clear_key_buffer();
49*28a2172cSIngo Weinhold 	wait_for_key();
50*28a2172cSIngo Weinhold 	platform_exit();
51*28a2172cSIngo Weinhold }
52*28a2172cSIngo Weinhold 
53*28a2172cSIngo Weinhold 
54*28a2172cSIngo Weinhold void
55*28a2172cSIngo Weinhold dprintf(const char *format, ...)
56*28a2172cSIngo Weinhold {
57*28a2172cSIngo Weinhold 	char buffer[512];
58*28a2172cSIngo Weinhold 	va_list list;
59*28a2172cSIngo Weinhold 	int length;
60*28a2172cSIngo Weinhold 
61*28a2172cSIngo Weinhold 	va_start(list, format);
62*28a2172cSIngo Weinhold 	length = vsnprintf(buffer, sizeof(buffer), format, list);
63*28a2172cSIngo Weinhold 	va_end(list);
64*28a2172cSIngo Weinhold 
65*28a2172cSIngo Weinhold 	if (length >= (int)sizeof(buffer))
66*28a2172cSIngo Weinhold 		length = sizeof(buffer) - 1;
67*28a2172cSIngo Weinhold 
68*28a2172cSIngo Weinhold 	if (sBufferPosition + length < sizeof(sBuffer)) {
69*28a2172cSIngo Weinhold 		memcpy(sBuffer + sBufferPosition, buffer, length);
70*28a2172cSIngo Weinhold 		sBufferPosition += length;
71*28a2172cSIngo Weinhold 	}
72*28a2172cSIngo Weinhold 
73*28a2172cSIngo Weinhold 	serial_puts(buffer, length);
74*28a2172cSIngo Weinhold 
75*28a2172cSIngo Weinhold 	if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT)
76*28a2172cSIngo Weinhold 		fprintf(stderr, "%s", buffer);
77*28a2172cSIngo Weinhold }
78*28a2172cSIngo Weinhold 
79*28a2172cSIngo Weinhold 
80*28a2172cSIngo Weinhold // #pragma mark -
81*28a2172cSIngo Weinhold 
82*28a2172cSIngo Weinhold 
83*28a2172cSIngo Weinhold void
84*28a2172cSIngo Weinhold debug_init_post_mmu(void)
85*28a2172cSIngo Weinhold {
86*28a2172cSIngo Weinhold 	// allocate 1 MB memory at 16 MB
87*28a2172cSIngo Weinhold 	addr_t base = 16 * 1024 * 1024;
88*28a2172cSIngo Weinhold 	size_t size = 1024 * 1024;
89*28a2172cSIngo Weinhold 	if (!mmu_allocate_physical(base, size))
90*28a2172cSIngo Weinhold 		return;
91*28a2172cSIngo Weinhold 
92*28a2172cSIngo Weinhold 	void* buffer = (void*)mmu_map_physical_memory(base, size,
93*28a2172cSIngo Weinhold 		kDefaultPageFlags);
94*28a2172cSIngo Weinhold 	if (buffer == NULL)
95*28a2172cSIngo Weinhold 		return;
96*28a2172cSIngo Weinhold 
97*28a2172cSIngo Weinhold 	// check whether there's a previous syslog we can recover
98*28a2172cSIngo Weinhold 	size_t signatureLength = strlen(kDebugSyslogSignature);
99*28a2172cSIngo Weinhold 	bool recover = memcmp(buffer, kDebugSyslogSignature, signatureLength) == 0;
100*28a2172cSIngo Weinhold 
101*28a2172cSIngo Weinhold 	// clear the signature
102*28a2172cSIngo Weinhold 	memset(buffer, 0, signatureLength);
103*28a2172cSIngo Weinhold 
104*28a2172cSIngo Weinhold 	size -= signatureLength;
105*28a2172cSIngo Weinhold 	buffer = (uint8*)buffer + ROUNDUP(signatureLength, sizeof(void*));
106*28a2172cSIngo Weinhold 
107*28a2172cSIngo Weinhold 	sDebugSyslogBuffer = create_ring_buffer_etc(buffer, size,
108*28a2172cSIngo Weinhold 		recover ? RING_BUFFER_INIT_FROM_BUFFER : 0);
109*28a2172cSIngo Weinhold 
110*28a2172cSIngo Weinhold 	gKernelArgs.debug_output = sDebugSyslogBuffer;
111*28a2172cSIngo Weinhold 	gKernelArgs.debug_size = sDebugSyslogBuffer->size;
112*28a2172cSIngo Weinhold }
113*28a2172cSIngo Weinhold 
114*28a2172cSIngo Weinhold 
115*28a2172cSIngo Weinhold void
116*28a2172cSIngo Weinhold debug_cleanup(void)
117*28a2172cSIngo Weinhold {
118*28a2172cSIngo Weinhold 	if (gKernelArgs.keep_debug_output_buffer && sDebugSyslogBuffer != NULL) {
119*28a2172cSIngo Weinhold 		// copy the output gathered so far into the ring buffer
120*28a2172cSIngo Weinhold 		ring_buffer_clear(sDebugSyslogBuffer);
121*28a2172cSIngo Weinhold 		ring_buffer_write(sDebugSyslogBuffer, (uint8*)sBuffer, sBufferPosition);
122*28a2172cSIngo Weinhold 
123*28a2172cSIngo Weinhold 		// set the buffer signature, so we'll accept it as valid after reboot
124*28a2172cSIngo Weinhold 		size_t signatureLength = strlen(kDebugSyslogSignature);
125*28a2172cSIngo Weinhold 		memcpy((void*)ROUNDDOWN((addr_t)sDebugSyslogBuffer, B_PAGE_SIZE),
126*28a2172cSIngo Weinhold 			kDebugSyslogSignature, signatureLength);
127*28a2172cSIngo Weinhold 	} else {
128*28a2172cSIngo Weinhold 		gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition);
129*28a2172cSIngo Weinhold 		if (gKernelArgs.debug_output != NULL) {
130*28a2172cSIngo Weinhold 			memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition);
131*28a2172cSIngo Weinhold 			gKernelArgs.debug_size = sBufferPosition;
132*28a2172cSIngo Weinhold 		}
133*28a2172cSIngo Weinhold 	}
134*28a2172cSIngo Weinhold }
135