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