Add generic SerialPortLib instance for 16550 UARTs configured through PCDs. Depends on new library class called PlatformHookLib to perform platform specific initialization of the UART.

Add PlatformHookLib.h that defines the PlatformHookLib class
Add PlatformHookLibNull instance that is a Null implementation of the PlatformHookLib class





git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11184 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
mdkinney 2010-12-18 01:02:59 +00:00
parent ccc96db96e
commit 467d15ae63
7 changed files with 526 additions and 0 deletions

View File

@ -0,0 +1,38 @@
/** @file
Platform hook library. Platform can provide an implementation of this
library class to provide hooks that may be required for some type of
platform initialization.
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __PLATFORM_HOOK_LIB__
#define __PLATFORM_HOOK_LIB__
/**
Performs platform specific initialization required for the CPU to access
the hardware associated with a SerialPortLib instance. This function does
not intiailzie the serial port hardware itself. Instead, it initializes
hardware devices that are required for the CPU to access the serial port
hardware. This function may be called more than once.
@retval RETURN_SUCCESS The platform specific initialization succeeded.
@retval RETURN_DEVICE_ERROR The platform specific initialization could not be completed.
**/
RETURN_STATUS
EFIAPI
PlatformHookSerialPortInitialize (
VOID
);
#endif // __PLATFORM_HOOK_LIB__

View File

@ -0,0 +1,37 @@
/** @file
Null Platform Hook Library instance.
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Base.h>
#include <Library/PlatformHookLib.h>
/**
Performs platform specific initialization required for the CPU to access
the hardware associated with a SerialPortLib instance. This function does
not intiailzie the serial port hardware itself. Instead, it initializes
hardware devices that are required for the CPU to access the serial port
hardware. This function may be called more than once.
@retval RETURN_SUCCESS The platform specific initialization succeeded.
@retval RETURN_DEVICE_ERROR The platform specific initialization could not be completed.
**/
RETURN_STATUS
EFIAPI
PlatformHookSerialPortInitialize (
VOID
)
{
return RETURN_SUCCESS;
}

View File

@ -0,0 +1,34 @@
## @file
# Null Platform Hook Library instance.
#
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = BasePlatformHookLibNull
FILE_GUID = EBC3AEAD-CC13-49b0-A678-5BED93956955
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = PlatformHookLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
BasePlatformHookLibNull.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec

View File

@ -0,0 +1,336 @@
/** @file
16550 UART Serial Port library functions
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Base.h>
#include <Library/SerialPortLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/PlatformHookLib.h>
//
// 16550 UART register offsets and bitfields
//
#define R_UART_RXBUF 0
#define R_UART_TXBUF 0
#define R_UART_BAUD_LOW 0
#define R_UART_BAUD_HIGH 1
#define R_UART_FCR 2
#define B_UART_FCR_FIFOE BIT0
#define B_UART_FCR_FIFO64 BIT5
#define R_UART_LCR 3
#define B_UART_LCR_DLAB BIT7
#define R_UART_MCR 4
#define B_UART_MCR_RTS BIT1
#define R_UART_LSR 5
#define B_UART_LSR_RXRDY BIT0
#define B_UART_LSR_TXRDY BIT5
#define B_UART_LSR_TEMT BIT6
#define R_UART_MSR 6
#define B_UART_MSR_CTS BIT4
#define B_UART_MSR_DCD BIT7
/**
Read an 8-bit 16550 register. If PcdSerialUseMmio is TRUE, then the value is read from
MMIO space. If PcdSerialUseMmio is FALSE, then the value is read from I/O space. The
parameter Offset is added to the base address of the 16550 registers that is specified
by PcdSerialRegisterBase.
@param Offset The offset of the 16550 register to read.
@return The value read from the 16550 register.
**/
UINT8
SerialPortReadRegister (
UINTN Offset
)
{
if (PcdGetBool (PcdSerialUseMmio)) {
return MmioRead8 ((UINTN)PcdGet64 (PcdSerialRegisterBase) + Offset);
} else {
return IoRead8 ((UINT16)PcdGet64 (PcdSerialRegisterBase) + Offset);
}
}
/**
Write an 8-bit 16550 register. If PcdSerialUseMmio is TRUE, then the value is written to
MMIO space. If PcdSerialUseMmio is FALSE, then the value is written to I/O space. The
parameter Offset is added to the base address of the 16550 registers that is specified
by PcdSerialRegisterBase.
@param Offset The offset of the 16550 register to read.
@return The value written to the 16550 register.
**/
UINT8
SerialPortWriteRegister (
UINTN Offset,
UINT8 Value
)
{
if (PcdGetBool (PcdSerialUseMmio)) {
return MmioWrite8 ((UINTN)PcdGet64 (PcdSerialRegisterBase) + Offset, Value);
} else {
return IoWrite8 ((UINT16)PcdGet64 (PcdSerialRegisterBase) + Offset, Value);
}
}
/**
Initialize the serial device hardware.
If no initialization is required, then return RETURN_SUCCESS.
If the serial device was successfuly initialized, then return RETURN_SUCCESS.
If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
@retval RETURN_SUCCESS The serial device was initialized.
@retval RETURN_DEVICE_ERROR The serial device could not be initialized.
**/
RETURN_STATUS
EFIAPI
SerialPortInitialize (
VOID
)
{
RETURN_STATUS Status;
UINTN Divisor;
BOOLEAN Initialized;
//
// Perform platform specific initialization required to enable use of the 16550 device
// at the location specified by PcdSerialUseMmio and PcdSerialRegisterBase.
//
Status = PlatformHookSerialPortInitialize ();
if (RETURN_ERROR (Status)) {
return Status;
}
//
// See if the serial port is already initialized
//
Initialized = TRUE;
if ((SerialPortReadRegister (R_UART_FCR) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)) !=
(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)) ) {
Initialized = FALSE;
}
if ((SerialPortReadRegister (R_UART_LCR) & 0x3F) != (PcdGet8 (PcdSerialLineControl) & 0x3F)) {
Initialized = FALSE;
}
SerialPortWriteRegister (R_UART_LCR, SerialPortReadRegister (R_UART_LCR) | B_UART_LCR_DLAB);
Divisor = (SerialPortReadRegister (R_UART_BAUD_HIGH) << 8) | SerialPortReadRegister (R_UART_BAUD_LOW);
SerialPortWriteRegister (R_UART_LCR, SerialPortReadRegister (R_UART_LCR) & ~B_UART_LCR_DLAB);
if (Divisor != 115200 / PcdGet32 (PcdSerialBaudRate)) {
Initialized = FALSE;
}
if (Initialized) {
return RETURN_SUCCESS;
}
//
// Configure baud rate
//
Divisor = 115200 / PcdGet32 (PcdSerialBaudRate);
SerialPortWriteRegister (R_UART_LCR, B_UART_LCR_DLAB);
SerialPortWriteRegister (R_UART_BAUD_HIGH, (UINT8) (Divisor >> 8));
SerialPortWriteRegister (R_UART_BAUD_LOW, (UINT8) (Divisor & 0xff));
//
// Clear DLAB and configure Data Bits, Parity, and Stop Bits.
// Strip reserved bits from PcdSerialLineControl
//
SerialPortWriteRegister (R_UART_LCR, PcdGet8 (PcdSerialLineControl) & 0x3F);
//
// Enable and reset FIFOs
// Strip reserved bits from PcdSerialFifoControl
//
SerialPortWriteRegister (R_UART_FCR, PcdGet8 (PcdSerialFifoControl) & 0x17);
//
// Put Modem Control Register(MCR) into its reset state of 0x00.
//
SerialPortWriteRegister (R_UART_MCR, 0x00);
return RETURN_SUCCESS;
}
/**
Write data from buffer to serial device.
Writes NumberOfBytes data bytes from Buffer to the serial device.
The number of bytes actually written to the serial device is returned.
If the return value is less than NumberOfBytes, then the write operation failed.
If Buffer is NULL, then ASSERT().
If NumberOfBytes is zero, then return 0.
@param Buffer Pointer to the data buffer to be written.
@param NumberOfBytes Number of bytes to written to the serial device.
@retval 0 NumberOfBytes is 0.
@retval >0 The number of bytes written to the serial device.
If this value is less than NumberOfBytes, then the read operation failed.
**/
UINTN
EFIAPI
SerialPortWrite (
IN UINT8 *Buffer,
IN UINTN NumberOfBytes
)
{
UINTN Result;
UINTN Index;
UINTN FifoSize;
if (Buffer == NULL) {
return 0;
}
//
// Compute the maximum size of the Tx FIFO
//
FifoSize = 1;
if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) {
if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) {
FifoSize = 16;
} else {
FifoSize = 64;
}
}
Result = NumberOfBytes;
while (NumberOfBytes != 0) {
//
// Wait for the serial port to be ready, to make sure both the transmit FIFO
// and shift register empty.
//
while ((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_TEMT) == 0);
//
// Fill then entire Tx FIFO
//
for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++, NumberOfBytes--, Buffer++) {
if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
//
// Wait for notification from peer to send data
//
while ((SerialPortReadRegister (R_UART_MSR) & (B_UART_MSR_CTS | B_UART_MSR_DCD)) == B_UART_MSR_DCD);
}
//
// Write byte to the transmit buffer.
//
SerialPortWriteRegister (R_UART_TXBUF, *Buffer);
}
}
return Result;
}
/**
Reads data from a serial device into a buffer.
@param Buffer Pointer to the data buffer to store the data read from the serial device.
@param NumberOfBytes Number of bytes to read from the serial device.
@retval 0 NumberOfBytes is 0.
@retval >0 The number of bytes read from the serial device.
If this value is less than NumberOfBytes, then the read operation failed.
**/
UINTN
EFIAPI
SerialPortRead (
OUT UINT8 *Buffer,
IN UINTN NumberOfBytes
)
{
UINTN Result;
UINT8 Mcr;
if (NULL == Buffer) {
return 0;
}
Mcr = SerialPortReadRegister (R_UART_MCR) & ~B_UART_MCR_RTS;
for (Result = 0; NumberOfBytes-- != 0; Result++, Buffer++) {
//
// Wait for the serial port to have some data.
//
while ((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_RXRDY) == 0) {
if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
//
// Set RTS to let the peer send some data
//
SerialPortWriteRegister (R_UART_MCR, Mcr | B_UART_MCR_RTS);
}
}
if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
//
// Clear RTS to prevent peer from sending data
//
SerialPortWriteRegister (R_UART_MCR, Mcr);
}
//
// Read byte from the receive buffer.
//
*Buffer = SerialPortReadRegister (R_UART_RXBUF);
}
return Result;
}
/**
Polls a serial device to see if there is any data waiting to be read.
Polls aserial device to see if there is any data waiting to be read.
If there is data waiting to be read from the serial device, then TRUE is returned.
If there is no data waiting to be read from the serial device, then FALSE is returned.
@retval TRUE Data is waiting to be read from the serial device.
@retval FALSE There is no data waiting to be read from the serial device.
**/
BOOLEAN
EFIAPI
SerialPortPoll (
VOID
)
{
//
// Read the serial port status
//
if ((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_RXRDY) != 0) {
if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
//
// Clear RTS to prevent peer from sending data
//
SerialPortWriteRegister (R_UART_MCR, SerialPortReadRegister (R_UART_MCR) & ~B_UART_MCR_RTS);
}
return TRUE;
}
if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
//
// Set RTS to let the peer send some data
//
SerialPortWriteRegister (R_UART_MCR, SerialPortReadRegister (R_UART_MCR) | B_UART_MCR_RTS);
}
return FALSE;
}

View File

@ -0,0 +1,41 @@
## @file
# SerialPortLib instance for 16550 UART
#
# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = BaseSerialPortLib16550
FILE_GUID = 9E7C00CF-355A-4d4e-BF60-0428CFF95540
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SerialPortLib
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
PcdLib
IoLib
PlatformHookLib
[Sources]
BaseSerialPortLib16550.c
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl

View File

@ -82,6 +82,10 @@
#
DebugAgentLib|Include/Library/DebugAgentLib.h
## @libraryclass Provide platform specific hooks.
#
PlatformHookLib|Include/Library/PlatformHookLib.h
[Guids]
## MdeModule package token space guid
# Include/Guid/MdeModulePkgTokenSpace.h
@ -394,6 +398,40 @@
## RTC Update Timeout Value
gEfiMdeModulePkgTokenSpaceGuid.PcdRealTimeClockUpdateTimeout|100000|UINT32|0x00010034
## If TRUE, then 16550 serial port registers are in MMIO space.
# If FALSE, then 16550 serial port registers are in I/O space. Default value.
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|FALSE|BOOLEAN|0x00020000
## If TRUE, then the 16550 serial port hardware flow control is enabled.
# If FALSE, then the 16550 serial port hardware flow control is disabled. Default value.
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|FALSE|BOOLEAN|0x00020001
## Base address of 16550 serial port registers in MMIO or I/O space. Default is 0x3F8.
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x03F8|UINT64|0x00020002
## Baud rate for the 16550 serial port. Default is 115200 baud.
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate|115200|UINT32|0x00020003
## Line Control Register (LCR) for the 16550 serial port. This encodes data bits, parity, and stop bits.
# BIT1..BIT0 - Data bits. 00b = 5 bits, 01b = 6 bits, 10b = 7 bits, 11b = 8 bits
# BIT2 - Stop Bits. 0 = 1 stop bit. 1 = 1.5 stop bits if 5 data bits selected, otherwise 2 stop bits.
# BIT5..BIT2 - Parity. xx0b = No Parity, 001b = Odd Parity, 011b = Even Parity, 101b = Mark Parity, 111b=Stick Parity
# BIT7..BIT6 - Reserved. Must be 0.
#
# Default is No Parity, 8 Data Bits, 1 Stop Bit.
#
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl|0x03|UINT8|0x00020004
## FIFO Control Register (FCR) for the 16550 serial port.
# BIT0 - FIFO Enable. 0 = Disable FIFOs. 1 = Enable FIFOs.
# BIT1 - Clear receive FIFO. 1 = Clear FIFO.
# BIT2 - Clear transmit FIFO. 1 = Clear FIFO.
# BIT7..BIT3 - Reserved. Must be 0.
#
# Default is to enable and clear all FIFOs.
#
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl|0x07|UINT8|0x00020005
## Maximum address that the DXE Core will allocate the EFI_SYSTEM_TABLE_POINTER
# structure. The default value for this PCD is 0, which means that the DXE Core
# will allocate the buffer from the EFI_SYSTEM_TABLE_POINTER structure on a 4MB

View File

@ -221,6 +221,8 @@
MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf