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