1 /* 2 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2012, Alexander von Gluck, kallisti5@unixzen.com 6 * Distributed under the terms of the MIT License. 7 */ 8 9 10 #include "serial.h" 11 12 #include <debug_uart_8250.h> 13 #include <board_config.h> 14 #include <boot/platform.h> 15 #include <arch/cpu.h> 16 #include <boot/stage2.h> 17 #include <new> 18 #include <string.h> 19 20 extern "C" { 21 #include <fdt.h> 22 #include <libfdt.h> 23 #include <libfdt_env.h> 24 }; 25 26 27 extern "C" DebugUART *debug_uart_from_fdt(const void *fdt); 28 29 DebugUART* gUART; 30 31 static int32 sSerialEnabled = 0; 32 static char sBuffer[16384]; 33 static uint32 sBufferPosition; 34 35 36 static void 37 serial_putc(char c) 38 { 39 gUART->PutChar(c); 40 } 41 42 43 extern "C" int 44 serial_getc(bool wait) 45 { 46 return gUART->GetChar(wait); 47 } 48 49 50 extern "C" void 51 serial_puts(const char* string, size_t size) 52 { 53 if (sSerialEnabled <= 0) 54 return; 55 56 if (sBufferPosition + size < sizeof(sBuffer)) { 57 memcpy(sBuffer + sBufferPosition, string, size); 58 sBufferPosition += size; 59 } 60 61 while (size-- != 0) { 62 char c = string[0]; 63 64 if (c == '\n') { 65 serial_putc('\r'); 66 serial_putc('\n'); 67 } else if (c != '\r') 68 serial_putc(c); 69 70 string++; 71 } 72 } 73 74 75 extern "C" void 76 serial_disable(void) 77 { 78 sSerialEnabled = 0; 79 } 80 81 82 extern "C" void 83 serial_enable(void) 84 { 85 /* should already be initialized by U-Boot */ 86 /* 87 gUART->InitEarly(); 88 gUART->InitPort(9600); 89 */ 90 sSerialEnabled++; 91 } 92 93 94 extern "C" void 95 serial_cleanup(void) 96 { 97 if (sSerialEnabled <= 0) 98 return; 99 100 gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition); 101 if (gKernelArgs.debug_output != NULL) { 102 memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition); 103 gKernelArgs.debug_size = sBufferPosition; 104 } 105 } 106 107 108 extern "C" void 109 serial_init(const void *fdt) 110 { 111 // first try with hints from the FDT 112 gUART = debug_uart_from_fdt(fdt); 113 114 #ifdef BOARD_UART_DEBUG 115 // fallback to hardcoded board UART 116 if (gUART == NULL) 117 gUART = arch_get_uart_8250(BOARD_UART_DEBUG, BOARD_UART_CLOCK); 118 #endif 119 120 if (gUART == NULL) 121 return; 122 123 serial_enable(); 124 } 125