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