iPXE
|
00001 /* 00002 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>. 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License as 00006 * published by the Free Software Foundation; either version 2 of the 00007 * License, or any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, but 00010 * WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00017 * 02110-1301, USA. 00018 * 00019 * You can also choose to distribute this program under the terms of 00020 * the Unmodified Binary Distribution Licence (as given in the file 00021 * COPYING.UBDL), provided that you have satisfied its requirements. 00022 */ 00023 00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); 00025 00026 /** @file 00027 * 00028 * Serial console 00029 * 00030 */ 00031 00032 #include <stddef.h> 00033 #include <string.h> 00034 #include <ipxe/init.h> 00035 #include <ipxe/uart.h> 00036 #include <ipxe/console.h> 00037 #include <ipxe/serial.h> 00038 #include <config/console.h> 00039 #include <config/serial.h> 00040 00041 /* Set default console usage if applicable */ 00042 #if ! ( defined ( CONSOLE_SERIAL ) && CONSOLE_EXPLICIT ( CONSOLE_SERIAL ) ) 00043 #undef CONSOLE_SERIAL 00044 #define CONSOLE_SERIAL ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG ) 00045 #endif 00046 00047 /* UART port number */ 00048 #ifdef COMCONSOLE 00049 #define CONSOLE_PORT COMCONSOLE 00050 #else 00051 #define CONSOLE_PORT 0 00052 #endif 00053 00054 /* UART baud rate */ 00055 #ifdef COMPRESERVE 00056 #define CONSOLE_BAUD 0 00057 #else 00058 #define CONSOLE_BAUD COMSPEED 00059 #endif 00060 00061 /* UART line control register value */ 00062 #ifdef COMPRESERVE 00063 #define CONSOLE_LCR 0 00064 #else 00065 #define CONSOLE_LCR UART_LCR_WPS ( COMDATA, COMPARITY, COMSTOP ) 00066 #endif 00067 00068 /** Serial console UART */ 00069 struct uart serial_console; 00070 00071 /** 00072 * Print a character to serial console 00073 * 00074 * @v character Character to be printed 00075 */ 00076 static void serial_putchar ( int character ) { 00077 00078 /* Do nothing if we have no UART */ 00079 if ( ! serial_console.base ) 00080 return; 00081 00082 /* Transmit character */ 00083 uart_transmit ( &serial_console, character ); 00084 } 00085 00086 /** 00087 * Get character from serial console 00088 * 00089 * @ret character Character read from console 00090 */ 00091 static int serial_getchar ( void ) { 00092 uint8_t data; 00093 00094 /* Do nothing if we have no UART */ 00095 if ( ! serial_console.base ) 00096 return 0; 00097 00098 /* Wait for data to be ready */ 00099 while ( ! uart_data_ready ( &serial_console ) ) {} 00100 00101 /* Receive data */ 00102 data = uart_receive ( &serial_console ); 00103 00104 /* Strip any high bit and convert DEL to backspace */ 00105 data &= 0x7f; 00106 if ( data == 0x7f ) 00107 data = 0x08; 00108 00109 return data; 00110 } 00111 00112 /** 00113 * Check for character ready to read from serial console 00114 * 00115 * @ret True Character available to read 00116 * @ret False No character available to read 00117 */ 00118 static int serial_iskey ( void ) { 00119 00120 /* Do nothing if we have no UART */ 00121 if ( ! serial_console.base ) 00122 return 0; 00123 00124 /* Check UART */ 00125 return uart_data_ready ( &serial_console ); 00126 } 00127 00128 /** Serial console */ 00129 struct console_driver serial_console_driver __console_driver = { 00130 .putchar = serial_putchar, 00131 .getchar = serial_getchar, 00132 .iskey = serial_iskey, 00133 .usage = CONSOLE_SERIAL, 00134 }; 00135 00136 /** Initialise serial console */ 00137 static void serial_init ( void ) { 00138 int rc; 00139 00140 /* Do nothing if we have no default port */ 00141 if ( ! CONSOLE_PORT ) 00142 return; 00143 00144 /* Select UART */ 00145 if ( ( rc = uart_select ( &serial_console, CONSOLE_PORT ) ) != 0 ) { 00146 DBG ( "Could not select UART %d: %s\n", 00147 CONSOLE_PORT, strerror ( rc ) ); 00148 return; 00149 } 00150 00151 /* Initialise UART */ 00152 if ( ( rc = uart_init ( &serial_console, CONSOLE_BAUD, 00153 CONSOLE_LCR ) ) != 0 ) { 00154 DBG ( "Could not initialise UART %d baud %d LCR %#02x: %s\n", 00155 CONSOLE_PORT, CONSOLE_BAUD, CONSOLE_LCR, strerror ( rc )); 00156 return; 00157 } 00158 } 00159 00160 /** 00161 * Shut down serial console 00162 * 00163 * @v flags Shutdown flags 00164 */ 00165 static void serial_shutdown ( int flags __unused ) { 00166 00167 /* Do nothing if we have no UART */ 00168 if ( ! serial_console.base ) 00169 return; 00170 00171 /* Flush any pending output */ 00172 uart_flush ( &serial_console ); 00173 00174 /* Leave console enabled; it's still usable */ 00175 } 00176 00177 /** Serial console initialisation function */ 00178 struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = { 00179 .initialise = serial_init, 00180 }; 00181 00182 /** Serial console startup function */ 00183 struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = { 00184 .name = "serial", 00185 .shutdown = serial_shutdown, 00186 };