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