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