iPXE
gdbserial.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>.
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 #include <stddef.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <assert.h>
00030 #include <ipxe/uart.h>
00031 #include <ipxe/gdbstub.h>
00032 #include <ipxe/gdbserial.h>
00033 #include <config/serial.h>
00034 
00035 /* UART port number */
00036 #ifdef COMCONSOLE
00037 #define GDBSERIAL_PORT COMCONSOLE
00038 #else
00039 #define GDBSERIAL_PORT 0
00040 #endif
00041 
00042 /* UART baud rate */
00043 #ifdef COMPRESERVE
00044 #define GDBSERIAL_BAUD 0
00045 #else
00046 #define GDBSERIAL_BAUD COMSPEED
00047 #endif
00048 
00049 /* UART line control register value */
00050 #ifdef COMPRESERVE
00051 #define GDBSERIAL_LCR 0
00052 #else
00053 #define GDBSERIAL_LCR UART_LCR_WPS ( COMDATA, COMPARITY, COMSTOP )
00054 #endif
00055 
00056 /** GDB serial UART */
00057 static struct uart gdbserial_uart;
00058 
00059 struct gdb_transport serial_gdb_transport __gdb_transport;
00060 
00061 static size_t gdbserial_recv ( char *buf, size_t len ) {
00062 
00063         assert ( len > 0 );
00064         while ( ! uart_data_ready ( &gdbserial_uart ) ) {}
00065         buf[0] = uart_receive ( &gdbserial_uart );
00066         return 1;
00067 }
00068 
00069 static void gdbserial_send ( const char *buf, size_t len ) {
00070 
00071         while ( len-- > 0 ) {
00072                 uart_transmit ( &gdbserial_uart, *buf++ );
00073         }
00074 }
00075 
00076 static int gdbserial_init ( int argc, char **argv ) {
00077         unsigned int port;
00078         char *endp;
00079 
00080         if ( argc == 0 ) {
00081                 port = GDBSERIAL_PORT;
00082         } else if ( argc == 1 ) {
00083                 port = strtoul ( argv[0], &endp, 10 );
00084                 if ( *endp ) {
00085                         printf ( "serial: invalid port\n" );
00086                         return 1;
00087                 }
00088         } else {
00089                 printf ( "serial: syntax <port>\n" );
00090                 return 1;
00091         }
00092 
00093         if ( ! gdbserial_configure ( port, GDBSERIAL_BAUD, GDBSERIAL_LCR ) ) {
00094                 printf ( "serial: unable to configure\n" );
00095                 return 1;
00096         }
00097 
00098         return 0;
00099 }
00100 
00101 struct gdb_transport serial_gdb_transport __gdb_transport = {
00102         .name = "serial",
00103         .init = gdbserial_init,
00104         .recv = gdbserial_recv,
00105         .send = gdbserial_send,
00106 };
00107 
00108 struct gdb_transport * gdbserial_configure ( unsigned int port,
00109                                              unsigned int baud, uint8_t lcr ) {
00110         int rc;
00111 
00112         if ( ( rc = uart_select ( &gdbserial_uart, port ) ) != 0 )
00113                 return NULL;
00114 
00115         if ( ( rc = uart_init ( &gdbserial_uart, baud, lcr ) ) != 0 )
00116                 return NULL;
00117 
00118         return &serial_gdb_transport;
00119 }