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