Home | History | Annotate | Download | only in GdbSerialLib
      1 /** @file
      2   Basic serial IO abstaction for GDB
      3 
      4   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include <Uefi.h>
     17 #include <Library/GdbSerialLib.h>
     18 #include <Library/PcdLib.h>
     19 #include <Library/IoLib.h>
     20 #include <Library/DebugLib.h>
     21 
     22 
     23 //---------------------------------------------
     24 // UART Register Offsets
     25 //---------------------------------------------
     26 #define BAUD_LOW_OFFSET         0x00
     27 #define BAUD_HIGH_OFFSET        0x01
     28 #define IER_OFFSET              0x01
     29 #define LCR_SHADOW_OFFSET       0x01
     30 #define FCR_SHADOW_OFFSET       0x02
     31 #define IR_CONTROL_OFFSET       0x02
     32 #define FCR_OFFSET              0x02
     33 #define EIR_OFFSET              0x02
     34 #define BSR_OFFSET              0x03
     35 #define LCR_OFFSET              0x03
     36 #define MCR_OFFSET              0x04
     37 #define LSR_OFFSET              0x05
     38 #define MSR_OFFSET              0x06
     39 
     40 //---------------------------------------------
     41 // UART Register Bit Defines
     42 //---------------------------------------------
     43 #define LSR_TXRDY               0x20
     44 #define LSR_RXDA                0x01
     45 #define DLAB                    0x01
     46 #define ENABLE_FIFO             0x01
     47 #define CLEAR_FIFOS             0x06
     48 
     49 
     50 
     51 // IO Port Base for the UART
     52 UINTN gPort;
     53 
     54 
     55 /**
     56   The constructor function initializes the UART.
     57 
     58   @param  ImageHandle   The firmware allocated handle for the EFI image.
     59   @param  SystemTable   A pointer to the EFI System Table.
     60 
     61   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
     62 
     63 **/
     64 RETURN_STATUS
     65 EFIAPI
     66 GdbSerialLibConstructor (
     67   IN EFI_HANDLE        ImageHandle,
     68   IN EFI_SYSTEM_TABLE  *SystemTable
     69   )
     70 {
     71   UINT64    BaudRate;
     72   UINT8     DataBits;
     73   UINT8     Parity;
     74   UINT8     StopBits;
     75 
     76   gPort = (UINTN)PcdGet32 (PcdGdbUartPort);
     77 
     78   BaudRate = PcdGet64 (PcdGdbBaudRate);
     79   Parity   = PcdGet8 (PcdGdbParity);
     80   DataBits = PcdGet8 (PcdGdbDataBits);
     81   StopBits = PcdGet8 (PcdGdbStopBits);
     82 
     83   return GdbSerialInit (BaudRate, Parity, DataBits, StopBits);
     84 }
     85 
     86 
     87 
     88 /**
     89   Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
     90   data buts, and stop bits on a serial device. This call is optional as the serial
     91   port will be set up with defaults base on PCD values.
     92 
     93   @param  BaudRate         The requested baud rate. A BaudRate value of 0 will use the the
     94                            device's default interface speed.
     95   @param  Parity           The type of parity to use on this serial device. A Parity value of
     96                            DefaultParity will use the device's default parity value.
     97   @param  DataBits         The number of data bits to use on the serial device. A DataBits
     98                            vaule of 0 will use the device's default data bit setting.
     99   @param  StopBits         The number of stop bits to use on this serial device. A StopBits
    100                            value of DefaultStopBits will use the device's default number of
    101                            stop bits.
    102 
    103   @retval EFI_SUCCESS      The device was configured.
    104   @retval EFI_DEVICE_ERROR The serial device could not be coonfigured.
    105 
    106 **/
    107 RETURN_STATUS
    108 EFIAPI
    109 GdbSerialInit (
    110   IN UINT64     BaudRate,
    111   IN UINT8      Parity,
    112   IN UINT8      DataBits,
    113   IN UINT8      StopBits
    114   )
    115 {
    116   UINTN           Divisor;
    117   UINT8           OutputData;
    118   UINT8           Data;
    119   UINT8           BreakSet = 0;
    120 
    121   //
    122   // We assume the UART has been turned on to decode gPort address range
    123   //
    124 
    125   //
    126   // Map 5..8 to 0..3
    127   //
    128   Data = (UINT8) (DataBits - (UINT8)5);
    129 
    130   //
    131   // Calculate divisor for baud generator
    132   //
    133   Divisor = 115200/(UINTN)BaudRate;
    134 
    135   //
    136   // Set communications format
    137   //
    138   OutputData = (UINT8)((DLAB << 7) | ((BreakSet << 6) | ((Parity << 3) | ((StopBits << 2) | Data))));
    139   IoWrite8 (gPort + LCR_OFFSET, OutputData);
    140 
    141   //
    142   // Configure baud rate
    143   //
    144   IoWrite8 (gPort + BAUD_HIGH_OFFSET, (UINT8)(Divisor >> 8));
    145   IoWrite8 (gPort + BAUD_LOW_OFFSET, (UINT8)(Divisor & 0xff));
    146 
    147 
    148   //
    149   // Switch back to bank 0
    150   //
    151   OutputData = (UINT8)((~DLAB<<7)|((BreakSet<<6)|((Parity<<3)|((StopBits<<2)| Data))));
    152   IoWrite8 (gPort + LCR_OFFSET, OutputData);
    153 
    154   // Not sure this is the right place to enable the FIFOs....
    155   // We probably need the FIFO enabled to not drop input
    156   IoWrite8 (gPort + FCR_SHADOW_OFFSET, ENABLE_FIFO);
    157 
    158 
    159   // Configure the UART hardware here
    160   return RETURN_SUCCESS;
    161 }
    162 
    163 
    164 /**
    165   Check to see if a character is available from GDB. Do not read the character as that is
    166   done via GdbGetChar().
    167 
    168   @return TRUE  - Character available
    169   @return FALSE - Character not available
    170 
    171 **/
    172 BOOLEAN
    173 EFIAPI
    174 GdbIsCharAvailable (
    175   VOID
    176   )
    177 {
    178   UINT8   Data;
    179 
    180   Data = IoRead8 (gPort + LSR_OFFSET);
    181 
    182   return ((Data & LSR_RXDA) == LSR_RXDA);
    183 }
    184 
    185 
    186 /**
    187   Get a character from GDB. This function must be able to run in interrupt context.
    188 
    189   @return A character from GDB
    190 
    191 **/
    192 CHAR8
    193 EFIAPI
    194 GdbGetChar (
    195   VOID
    196   )
    197 {
    198   UINT8   Data;
    199   CHAR8   Char;
    200 
    201   // Wait for the serial port to be ready
    202   do {
    203     Data = IoRead8 (gPort + LSR_OFFSET);
    204   } while ((Data & LSR_RXDA) == 0);
    205 
    206   Char = IoRead8 (gPort);
    207 
    208   // Make this an EFI_D_INFO after we get everything debugged.
    209   DEBUG ((EFI_D_ERROR, "<%c<", Char));
    210   return Char;
    211 }
    212 
    213 
    214 /**
    215   Send a character to GDB. This function must be able to run in interrupt context.
    216 
    217 
    218   @param  Char    Send a character to GDB
    219 
    220 **/
    221 
    222 VOID
    223 EFIAPI
    224 GdbPutChar (
    225   IN  CHAR8   Char
    226   )
    227 {
    228   UINT8   Data;
    229 
    230   // Make this an EFI_D_INFO after we get everything debugged.
    231   DEBUG ((EFI_D_ERROR, ">%c>", Char));
    232 
    233   // Wait for the serial port to be ready
    234   do {
    235     Data = IoRead8 (gPort + LSR_OFFSET);
    236   } while ((Data & LSR_TXRDY) == 0);
    237 
    238   IoWrite8 (gPort, Char);
    239 }
    240 
    241 /**
    242   Send an ASCII string to GDB. This function must be able to run in interrupt context.
    243 
    244 
    245   @param  String    Send a string to GDB
    246 
    247 **/
    248 
    249 VOID
    250 GdbPutString (
    251   IN CHAR8  *String
    252   )
    253 {
    254   while (*String != '\0') {
    255     GdbPutChar (*String);
    256     String++;
    257   }
    258 }
    259 
    260 
    261 
    262 
    263