xref: /haiku/src/system/boot/platform/efi/debug.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 /*
2  * Copyright 2016-2022 Haiku, Inc. All rights reserved.
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 <util/ring_buffer.h>
15 
16 #include "efi_platform.h"
17 #include "serial.h"
18 
19 
20 static char sBuffer[16384];
21 static uint32 sBufferPosition;
22 
23 static ring_buffer* sDebugSyslogBuffer = NULL;
24 
25 
26 static void
27 syslog_write(const char* buffer, size_t length)
28 {
29 	if (sDebugSyslogBuffer != NULL) {
30 		ring_buffer_write(sDebugSyslogBuffer, (const uint8*)buffer, length);
31 	} else if (sBufferPosition + length < sizeof(sBuffer)) {
32 		memcpy(sBuffer + sBufferPosition, buffer, length);
33 		sBufferPosition += length;
34 	}
35 }
36 
37 
38 static void
39 dprintf_args(const char *format, va_list args)
40 {
41 	char buffer[512];
42 	int length = vsnprintf(buffer, sizeof(buffer), format, args);
43 	if (length == 0)
44 		return;
45 
46 	if (length >= (int)sizeof(buffer))
47 		length = sizeof(buffer) - 1;
48 
49 	syslog_write(buffer, length);
50 	serial_puts(buffer, length);
51 }
52 
53 
54 extern "C" void
55 dprintf(const char *format, ...)
56 {
57 	va_list args;
58 
59 	va_start(args, format);
60 	dprintf_args(format, args);
61 	va_end(args);
62 }
63 
64 
65 extern "C" void
66 panic(const char *format, ...)
67 {
68 	va_list args;
69 
70 	platform_switch_to_text_mode();
71 
72 	puts("*** PANIC ***");
73 
74 	va_start(args, format);
75 	vprintf(format, args);
76 	va_end(args);
77 
78 	while (true)
79 		kBootServices->Stall(1000000);
80 }
81 
82 
83 static void
84 allocate_ring_buffer(void)
85 {
86 	// allocate 1 MB memory
87 	void* buffer = NULL;
88 	size_t size = 1024 * 1024;
89 
90 	if (platform_allocate_region(&buffer, size, 0, false) != B_OK)
91 		return;
92 
93 	sDebugSyslogBuffer = create_ring_buffer_etc(buffer, size, 0);
94 
95 	gKernelArgs.debug_output = sDebugSyslogBuffer;
96 	gKernelArgs.debug_size = sDebugSyslogBuffer->size;
97 }
98 
99 
100 void
101 debug_cleanup(void)
102 {
103 	allocate_ring_buffer();
104 
105 	if (sDebugSyslogBuffer != NULL) {
106 		if (gKernelArgs.keep_debug_output_buffer) {
107 			// copy the output gathered so far into the ring buffer
108 			ring_buffer_clear(sDebugSyslogBuffer);
109 			ring_buffer_write(sDebugSyslogBuffer, (uint8*)sBuffer,
110 				sBufferPosition);
111 		}
112 	} else {
113 		gKernelArgs.keep_debug_output_buffer = false;
114 	}
115 
116 	if (!gKernelArgs.keep_debug_output_buffer) {
117 		gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition);
118 		if (gKernelArgs.debug_output != NULL) {
119 			memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition);
120 			gKernelArgs.debug_size = sBufferPosition;
121 		}
122 	}
123 }
124 
125 
126 char*
127 platform_debug_get_log_buffer(size_t *_size)
128 {
129 	if (_size != NULL)
130 		*_size = sizeof(sBuffer);
131 
132 	return sBuffer;
133 }
134