* [PATCH 1/3] UefiPayloadPkg: Implement a new DebugLib instance @ 2022-07-14 4:31 kavya 2022-07-14 4:31 ` [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instance kavya ` (2 more replies) 0 siblings, 3 replies; 5+ messages in thread From: kavya @ 2022-07-14 4:31 UTC (permalink / raw) To: devel; +Cc: Kavya, Guo Dong, Ray Ni, Maurice Ma, Benjamin You, Sean Rhodes Add new Debug library instance to support multiple channel debug message. Cc: Guo Dong <guo.dong@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Maurice Ma <maurice.ma@intel.com> Cc: Benjamin You <benjamin.you@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Signed-off-by: Kavya <k.kavyax.sravanthi@intel.com> --- UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.c | 295 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.inf | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 332 insertions(+) diff --git a/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.c b/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.c new file mode 100644 index 0000000000..0fd9e795a3 --- /dev/null +++ b/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.c @@ -0,0 +1,295 @@ +/** @file + Instance of Debug Library based on Serial Port Library. + + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Base.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/PrintLib.h> +#include <Library/PcdLib.h> +#include <Library/DebugPrintErrorLevelLib.h> + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +/** + Initialize the serial device hardware. + + If no initialization is required, then return RETURN_SUCCESS. + If the serial device was successfully initialized, then return RETURN_SUCCESS. + If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. + If gUniversalPayloadSerialPortInfoGuid not found, then return RETURN_NOT_FOUND. + + @retval RETURN_SUCCESS The serial device was initialized. + @retval RETURN_DEVICE_ERROR The serial device could not be initialized. + @retval RETURN_NOT_FOUND GuidHob not found. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ); + +/** + 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 return 0. + 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 write operation failed. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ); + +/** + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and the + associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param ... Variable argument list whose contents are accessed + based on the format string specified by Format. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + ... + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { + return; + } + + // + // Convert the DEBUG() message to an ASCII String + // + VA_START (Marker, Format); + AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker); + VA_END (Marker); + + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); +} + +/** + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n" + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recursion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed. + If Description is NULL, then a <Description> string of "(NULL) Description" is printed. + + @param FileName The pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description The pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + // + // Generate the ASSERT() message in Ascii format + // + AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT [%a] %a(%d): %a\n", gEfiCallerBaseName, FileName, LineNumber, Description); + + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); + + // + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings + // + if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { + CpuBreakpoint (); + } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { + CpuDeadLoop (); + } +} + +/** + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to be filled with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer Pointer to the target buffer filled with PcdDebugClearMemoryValue. + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + ASSERT (Buffer != NULL); + + return SetMem (Buffer, Length, PcdGet8 (PcdDebugClearMemoryValue)); +} + +/** + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + +/** + Returns TRUE if DEBUG() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + +/** + Returns TRUE if DEBUG_CODE() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + +/** + Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} + +/** + Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel. + + This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel. + + @retval TRUE Current ErrorLevel is supported. + @retval FALSE Current ErrorLevel is not supported. + +**/ +BOOLEAN +EFIAPI +DebugPrintLevelEnabled ( + IN CONST UINTN ErrorLevel + ) +{ + return (BOOLEAN)((ErrorLevel & PcdGet32 (PcdFixedDebugPrintErrorLevel)) != 0); +} + +/** + The constructor function to initialize Debug port Library + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +BaseDebugLibHobConstructor ( + VOID + ) +{ + return SerialPortInitialize (); +} diff --git a/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.inf b/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.inf new file mode 100644 index 0000000000..11ed8de08b --- /dev/null +++ b/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.inf @@ -0,0 +1,37 @@ +## @file +# Instance of Debug Library based on Serial Port Library. +# +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseDebugLibHob + FILE_GUID = ae4cc887-ea47-4d5c-a8f9-1d08405b5f8b + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib + CONSTRUCTOR = BaseDebugLibHobConstructor + +[Sources] + BaseDebugLibHob.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + PcdLib + DebugPrintErrorLevelLib + BaseMemoryLib + PrintLib + SerialPortLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel -- 2.30.2.windows.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instance 2022-07-14 4:31 [PATCH 1/3] UefiPayloadPkg: Implement a new DebugLib instance kavya @ 2022-07-14 4:31 ` kavya 2022-07-14 7:04 ` Ni, Ray 2022-07-14 4:31 ` [PATCH 3/3] UefiPayloadPkg: Allow DxeMain.inf to consume the new DebugLib and SerialPortLib kavya 2022-07-14 7:07 ` [PATCH 1/3] UefiPayloadPkg: Implement a new DebugLib instance Ni, Ray 2 siblings, 1 reply; 5+ messages in thread From: kavya @ 2022-07-14 4:31 UTC (permalink / raw) To: devel; +Cc: Kavya, Guo Dong, Ray Ni, Maurice Ma, Benjamin You, Sean Rhodes Add new Serial port library instance that consumes the HOB defined in MdeModulePkg/Include/UniversalPayload/SerialPortInfo.h to support multiple UART's. Cc: Guo Dong <guo.dong@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Maurice Ma <maurice.ma@intel.com> Cc: Benjamin You <benjamin.you@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Signed-off-by: Kavya <k.kavyax.sravanthi@intel.com> --- UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c | 802 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 841 insertions(+) diff --git a/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c new file mode 100644 index 0000000000..6f62b2a5d2 --- /dev/null +++ b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c @@ -0,0 +1,802 @@ +/** @file + UART Serial Port library functions. + + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include <PiDxe.h> +#include <Base.h> +#include <Library/PcdLib.h> +#include <Library/IoLib.h> +#include <Library/BaseLib.h> +#include <Library/HobLib.h> +#include <Library/TimerLib.h> +#include <Protocol/SerialIo.h> +#include <UniversalPayload/SerialPortInfo.h> + +// +// 16550 UART register offsets and bitfields +// +#define R_UART_RXBUF 0 // LCR_DLAB = 0 +#define R_UART_TXBUF 0 // LCR_DLAB = 0 +#define R_UART_BAUD_LOW 0 // LCR_DLAB = 1 +#define R_UART_BAUD_HIGH 1 // LCR_DLAB = 1 +#define R_UART_IER 1 // LCR_DLAB = 0 +#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_DTRC BIT0 +#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_DSR BIT5 +#define B_UART_MSR_RI BIT6 +#define B_UART_MSR_DCD BIT7 + +/** + Reads an 8-bit register. If UseMmio is TRUE, then the value is read from + MMIO space. If UseMmio is FALSE, then the value is read from I/O space. The + parameter Offset is added to the base address of the register. + + @param Base The base address register of UART device. + @param Offset The offset of the register to read. + @param UseMmio Check if value has to be read from MMIO space or IO space. + + @return The value read from the register. + +**/ +UINT8 +SerialPortReadRegister ( + UINTN Base, + UINTN Offset, + BOOLEAN UseMmio + ) +{ + if (UseMmio) { + return MmioRead8 (Base + Offset/4); + } else { + return IoRead8 (Base + Offset); + } +} + +/** + Writes an 8-bit register.. If UseMmio is TRUE, then the value is written to + MMIO space. If UseMmio is FALSE, then the value is written to I/O space. The + parameter Offset is added to the base address of the registers. + + @param Base The base address register of UART device. + @param Offset The offset of the register to write. + @param Value Value to be written. + @param UseMmio Check if value has to be written to MMIO space or IO space. + + @return The value written to the register. + +**/ +UINT8 +SerialPortWriteRegister ( + UINTN Base, + UINTN Offset, + UINT8 Value, + BOOLEAN UseMmio + ) +{ + if (UseMmio) { + return MmioWrite8 (Base + Offset/4, Value); + } else { + return IoWrite8 (Base + Offset, Value); + } +} + +/** + Initialize the serial device hardware. + + If no initialization is required, then return RETURN_SUCCESS. + If the serial device was successfully initialized, then return RETURN_SUCCESS. + If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. + If gUniversalPayloadSerialPortInfoGuid not found, then return RETURN_NOT_FOUND. + + @retval RETURN_SUCCESS The serial device was initialized. + @retval RETURN_DEVICE_ERROR The serial device could not be initialized. + @retval RETURN_NOT_FOUND GuidHob not found. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; + EFI_HOB_GUID_TYPE *GuidHob; + UINTN SerialRegisterBase; + UINT32 Divisor; + UINT32 CurrentDivisor; + UINT32 BaudRate; + BOOLEAN Initialized; + BOOLEAN MmioEnable; + + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); + if (GuidHob == NULL) { + return RETURN_NOT_FOUND; + } + while (GuidHob != NULL) { + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); + SerialRegisterBase = SerialPortInfo->RegisterBase; + MmioEnable = SerialPortInfo->UseMmio; + BaudRate = SerialPortInfo->BaudRate; + + if (SerialRegisterBase == 0) { + return RETURN_DEVICE_ERROR; + } + + Divisor = PcdGet32 (PcdSerialClockRate) / (BaudRate * 16); + if ((PcdGet32 (PcdSerialClockRate) % (BaudRate * 16)) >= BaudRate * 8) { + Divisor++; + } + + // + // See if the serial port is already initialized + // + Initialized = TRUE; + if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEnable) & 0x3F) != (PcdGet8 (PcdSerialLineControl) & 0x3F)) { + Initialized = FALSE; + } + + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEnable) | B_UART_LCR_DLAB), MmioEnable); + CurrentDivisor = SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_HIGH, MmioEnable) << 8; + CurrentDivisor |= (UINT32)SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_LOW, MmioEnable); + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEnable) & ~B_UART_LCR_DLAB), MmioEnable); + if (CurrentDivisor != Divisor) { + Initialized = FALSE; + } + + if (Initialized) { + return RETURN_SUCCESS; + } + + // + // Wait for the serial port to be ready. + // Verify that both the transmit FIFO and the shift register are empty. + // + while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR, MmioEnable) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) { + } + + // + // Configure baud rate + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB, MmioEnable); + SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8)(Divisor >> 8), MmioEnable); + SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8)(Divisor & 0xff), MmioEnable); + + // + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. + // Strip reserved bits from PcdSerialLineControl + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3F), MmioEnable); + + // + // Enable and reset FIFOs + // Strip reserved bits from PcdSerialFifoControl + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, 0x00, MmioEnable); + SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)), MmioEnable); + + // + // Set FIFO Polled Mode by clearing IER after setting FCR + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_IER, 0x00, MmioEnable); + + // + // Put Modem Control Register(MCR) into its reset state of 0x00. + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, 0x00, MmioEnable); + + GuidHob = GET_NEXT_HOB (GuidHob); + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); + } + + 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 return 0. + + 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 write operation failed. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ) +{ + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; + EFI_HOB_GUID_TYPE *GuidHob; + UINTN BaseAddress; + BOOLEAN UseMmio; + UINTN BytesLeft; + UINTN Index; + UINTN FifoSize; + UINT8 *DataBuffer; + + if (Buffer == NULL || NumberOfBytes == 0) { + 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 = PcdGet32 (PcdSerialExtendedTxFifoSize); + } + } + + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); + while (GuidHob != NULL) { + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); + BaseAddress = SerialPortInfo->RegisterBase; + UseMmio = SerialPortInfo->UseMmio; + + DataBuffer = Buffer; + BytesLeft = NumberOfBytes; + + while (BytesLeft != 0) { + // + // Fill the entire Tx FIFO + // + for (Index = 0; Index < FifoSize && BytesLeft != 0; Index++, BytesLeft--, DataBuffer++) { + // + // Write byte to the transmit buffer. + // + SerialPortWriteRegister (BaseAddress, R_UART_TXBUF, *DataBuffer, UseMmio); + } + MicroSecondDelay (20); + } + GuidHob = GET_NEXT_HOB (GuidHob); + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); + } + + return NumberOfBytes; +} + +/** + 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 + ) +{ + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; + EFI_HOB_GUID_TYPE *GuidHob; + UINTN BaseAddress; + BOOLEAN UseMmio; + UINT8 *DataBuffer; + UINTN BytesLeft; + UINTN Result; + UINT8 Mcr; + + if (Buffer == NULL) { + return 0; + } + + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); + while (GuidHob != NULL) { + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); + BaseAddress = SerialPortInfo->RegisterBase; + UseMmio = SerialPortInfo->UseMmio; + + DataBuffer = Buffer; + BytesLeft = NumberOfBytes; + + if (BaseAddress == 0) { + return 0; + } + + Mcr = (UINT8)(SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio) & ~B_UART_MCR_RTS); + + for (Result = 0; BytesLeft-- != 0; Result++, DataBuffer++) { + // + // Wait for the serial port to have some data. + // + while ((SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio) & B_UART_LSR_RXRDY) == 0) { + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + // + // Set RTS to let the peer send some data + // + SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(Mcr | B_UART_MCR_RTS), UseMmio); + } + } + + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + // + // Clear RTS to prevent peer from sending data + // + SerialPortWriteRegister (BaseAddress, R_UART_MCR, Mcr, UseMmio); + } + + // + // Read byte from the receive buffer. + // + *DataBuffer = SerialPortReadRegister (BaseAddress, R_UART_RXBUF, UseMmio); + } + + GuidHob = GET_NEXT_HOB (GuidHob); + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); + } + + return Result; +} + +/** + Polls a serial device to see if there is any data waiting to be read. + + Polls a serial 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 + ) +{ + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; + EFI_HOB_GUID_TYPE *GuidHob; + UINTN BaseAddress; + BOOLEAN UseMmio; + + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); + while (GuidHob != NULL) { + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); + BaseAddress = SerialPortInfo->RegisterBase; + UseMmio = SerialPortInfo->UseMmio; + + if (BaseAddress == 0) { + return FALSE; + } + + // + // Read the serial port status + // + if ((SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio) & B_UART_LSR_RXRDY) != 0) { + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + // + // Clear RTS to prevent peer from sending data + // + SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio) & ~B_UART_MCR_RTS), UseMmio); + } + return TRUE; + } + + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + // + // Set RTS to let the peer send some data + // + SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio) | B_UART_MCR_RTS), UseMmio); + } + + GuidHob = GET_NEXT_HOB (GuidHob); + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); + } + return FALSE; +} + +/** + Sets the control bits on a serial device. + + @param Control Sets the bits of Control that are settable. + + @retval RETURN_SUCCESS The new control bits were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + @retval RETURN_NOT_FOUND GuidHob not found. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; + EFI_HOB_GUID_TYPE *GuidHob; + UINTN BaseAddress; + BOOLEAN UseMmio; + UINT8 Mcr; + + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); + if (GuidHob == NULL) { + return RETURN_NOT_FOUND; + } + while (GuidHob != NULL) { + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); + BaseAddress = SerialPortInfo->RegisterBase; + UseMmio = SerialPortInfo->UseMmio; + + if (BaseAddress == 0) { + return RETURN_UNSUPPORTED; + } + + // + // First determine the parameter is invalid. + // + if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) + { + return RETURN_UNSUPPORTED; + } + + // + // Read the Modem Control Register. + // + Mcr = SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio); + Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS)); + + if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) { + Mcr |= B_UART_MCR_DTRC; + } + + if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) { + Mcr |= B_UART_MCR_RTS; + } + + // + // Write the Modem Control Register. + // + SerialPortWriteRegister (BaseAddress, R_UART_MCR, Mcr, UseMmio); + + GuidHob = GET_NEXT_HOB (GuidHob); + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); + } + + return RETURN_SUCCESS; +} + +/** + Retrieve the status of the control bits on a serial device. + + @param Control A pointer to return the current control signals from the serial device. + + @retval RETURN_SUCCESS The control bits were read from the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + @retval RETURN_NOT_FOUND GuidHob not found. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; + EFI_HOB_GUID_TYPE *GuidHob; + UINTN BaseAddress; + BOOLEAN UseMmio; + UINT8 Msr; + UINT8 Mcr; + UINT8 Lsr; + + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); + if (GuidHob == NULL) { + return RETURN_NOT_FOUND; + } + while (GuidHob != NULL) { + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); + BaseAddress = SerialPortInfo->RegisterBase; + UseMmio = SerialPortInfo->UseMmio; + + if (BaseAddress == 0) { + return RETURN_UNSUPPORTED; + } + + *Control = 0; + + // + // Read the Modem Status Register. + // + Msr = SerialPortReadRegister (BaseAddress, R_UART_MSR, UseMmio); + + if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) { + *Control |= EFI_SERIAL_CLEAR_TO_SEND; + } + + if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) { + *Control |= EFI_SERIAL_DATA_SET_READY; + } + + if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) { + *Control |= EFI_SERIAL_RING_INDICATE; + } + + if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) { + *Control |= EFI_SERIAL_CARRIER_DETECT; + } + + // + // Read the Modem Control Register. + // + Mcr = SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio); + + if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) { + *Control |= EFI_SERIAL_DATA_TERMINAL_READY; + } + + if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) { + *Control |= EFI_SERIAL_REQUEST_TO_SEND; + } + + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; + } + + // + // Read the Line Status Register. + // + Lsr = SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio); + + if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) == (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) { + *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + + if ((Lsr & B_UART_LSR_RXRDY) == 0) { + *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY; + } + + GuidHob = GET_NEXT_HOB (GuidHob); + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); + } + + return RETURN_SUCCESS; +} + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data bits, and stop bits on a serial device. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the + device's default interface speed. + On output, the value actually set. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's default FIFO depth. + On output, the value actually set. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + On output, the value actually set. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + On output, the value actually set. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + On output, the value actually set. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + On output, the value actually set. + + @retval RETURN_SUCCESS The new attributes were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + @retval RETURN_NOT_FOUND GuidHob not found. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits + ) +{ + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; + EFI_HOB_GUID_TYPE *GuidHob; + UINTN BaseAddress; + BOOLEAN UseMmio; + UINT32 SerialBaudRate; + UINTN Divisor; + UINT8 Lcr; + UINT8 LcrData; + UINT8 LcrParity; + UINT8 LcrStop; + + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); + if (GuidHob == NULL) { + return RETURN_NOT_FOUND; + } + while (GuidHob != NULL) { + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); + BaseAddress = SerialPortInfo->RegisterBase; + UseMmio = SerialPortInfo->UseMmio; + + if (BaseAddress == 0) { + return RETURN_UNSUPPORTED; + } + + // + // Check for default settings and fill in actual values. + // + if (*BaudRate == 0) { + *BaudRate = SerialPortInfo->BaudRate; + } + + SerialBaudRate = (UINT32)*BaudRate; + + if (*DataBits == 0) { + LcrData = (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3); + *DataBits = LcrData + 5; + } else { + if ((*DataBits < 5) || (*DataBits > 8)) { + return RETURN_INVALID_PARAMETER; + } + + // + // Map 5..8 to 0..3 + // + LcrData = (UINT8)(*DataBits - (UINT8)5); + } + + if (*Parity == DefaultParity) { + LcrParity = (UINT8)((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7); + switch (LcrParity) { + case 0: + *Parity = NoParity; + break; + + case 3: + *Parity = EvenParity; + break; + + case 1: + *Parity = OddParity; + break; + + case 7: + *Parity = SpaceParity; + break; + + case 5: + *Parity = MarkParity; + break; + + default: + break; + } + } else { + switch (*Parity) { + case NoParity: + LcrParity = 0; + break; + + case EvenParity: + LcrParity = 3; + break; + + case OddParity: + LcrParity = 1; + break; + + case SpaceParity: + LcrParity = 7; + break; + + case MarkParity: + LcrParity = 5; + break; + + default: + return RETURN_INVALID_PARAMETER; + } + } + + if (*StopBits == DefaultStopBits) { + LcrStop = (UINT8)((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1); + switch (LcrStop) { + case 0: + *StopBits = OneStopBit; + break; + + case 1: + if (*DataBits == 5) { + *StopBits = OneFiveStopBits; + } else { + *StopBits = TwoStopBits; + } + + break; + + default: + break; + } + } else { + switch (*StopBits) { + case OneStopBit: + LcrStop = 0; + break; + + case OneFiveStopBits: + case TwoStopBits: + LcrStop = 1; + break; + + default: + return RETURN_INVALID_PARAMETER; + } + } + + // + // Calculate divisor for baud generator + // Ref_Clk_Rate / Baud_Rate / 16 + // + Divisor = PcdGet32 (PcdSerialClockRate) / (SerialBaudRate * 16); + if ((PcdGet32 (PcdSerialClockRate) % (SerialBaudRate * 16)) >= SerialBaudRate * 8) { + Divisor++; + } + + // + // Configure baud rate + // + SerialPortWriteRegister (BaseAddress, R_UART_LCR, B_UART_LCR_DLAB, UseMmio); + SerialPortWriteRegister (BaseAddress, R_UART_BAUD_HIGH, (UINT8)(Divisor >> 8), UseMmio); + SerialPortWriteRegister (BaseAddress, R_UART_BAUD_LOW, (UINT8)(Divisor & 0xff), UseMmio); + + // + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. + // Strip reserved bits from line control value + // + Lcr = (UINT8)((LcrParity << 3) | (LcrStop << 2) | LcrData); + SerialPortWriteRegister (BaseAddress, R_UART_LCR, (UINT8)(Lcr & 0x3F), UseMmio); + + GuidHob = GET_NEXT_HOB (GuidHob); + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); + } + + return RETURN_SUCCESS; +} diff --git a/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf new file mode 100644 index 0000000000..ac857d3eea --- /dev/null +++ b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf @@ -0,0 +1,39 @@ +## @file +# SerialPortLib instance for UART information retrieved from bootloader. +# +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseSerialPortLibHob + FILE_GUID = d8d22930-e8ec-469f-8184-5a069149b2ff + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + PcdLib + IoLib + HobLib + TimerLib + +[Sources] + BaseSerialPortLibHob.c + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl + +[Guids] + gUniversalPayloadSerialPortInfoGuid -- 2.30.2.windows.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instance 2022-07-14 4:31 ` [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instance kavya @ 2022-07-14 7:04 ` Ni, Ray 0 siblings, 0 replies; 5+ messages in thread From: Ni, Ray @ 2022-07-14 7:04 UTC (permalink / raw) To: Sravanthi, K KavyaX, devel@edk2.groups.io Cc: Dong, Guo, Maurice Ma, You, Benjamin, Rhodes, Sean The implementation looks good. But it limits the usage of SerialPortRead/Write to be called only from BSP because GetFirstGuidHob() can not be called from APs. An alternative implementation is to cache the UART instances data into a library global array so SerialPortRead/Write don't need to call GetFirstGuidHob() again. Such change allows APs call the APIs. > -----Original Message----- > From: Sravanthi, K KavyaX <k.kavyax.sravanthi@intel.com> > Sent: Thursday, July 14, 2022 12:31 PM > To: devel@edk2.groups.io > Cc: Sravanthi, K KavyaX <k.kavyax.sravanthi@intel.com>; Dong, Guo <guo.dong@intel.com>; Ni, Ray <ray.ni@intel.com>; > Maurice Ma <maurice.ma@intel.com>; You, Benjamin <benjamin.you@intel.com>; Rhodes, Sean > <sean@starlabs.systems> > Subject: [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instance > > Add new Serial port library instance that consumes the HOB defined > in MdeModulePkg/Include/UniversalPayload/SerialPortInfo.h to support > multiple UART's. > > Cc: Guo Dong <guo.dong@intel.com> > Cc: Ray Ni <ray.ni@intel.com> > Cc: Maurice Ma <maurice.ma@intel.com> > Cc: Benjamin You <benjamin.you@intel.com> > Cc: Sean Rhodes <sean@starlabs.systems> > Signed-off-by: Kavya <k.kavyax.sravanthi@intel.com> > --- > UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c | 802 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf | 39 > +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 841 insertions(+) > > diff --git a/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c > b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c > new file mode 100644 > index 0000000000..6f62b2a5d2 > --- /dev/null > +++ b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.c > @@ -0,0 +1,802 @@ > +/** @file > + UART Serial Port library functions. > + > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR> > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include <PiDxe.h> > +#include <Base.h> > +#include <Library/PcdLib.h> > +#include <Library/IoLib.h> > +#include <Library/BaseLib.h> > +#include <Library/HobLib.h> > +#include <Library/TimerLib.h> > +#include <Protocol/SerialIo.h> > +#include <UniversalPayload/SerialPortInfo.h> > + > +// > +// 16550 UART register offsets and bitfields > +// > +#define R_UART_RXBUF 0 // LCR_DLAB = 0 > +#define R_UART_TXBUF 0 // LCR_DLAB = 0 > +#define R_UART_BAUD_LOW 0 // LCR_DLAB = 1 > +#define R_UART_BAUD_HIGH 1 // LCR_DLAB = 1 > +#define R_UART_IER 1 // LCR_DLAB = 0 > +#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_DTRC BIT0 > +#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_DSR BIT5 > +#define B_UART_MSR_RI BIT6 > +#define B_UART_MSR_DCD BIT7 > + > +/** > + Reads an 8-bit register. If UseMmio is TRUE, then the value is read from > + MMIO space. If UseMmio is FALSE, then the value is read from I/O space. The > + parameter Offset is added to the base address of the register. > + > + @param Base The base address register of UART device. > + @param Offset The offset of the register to read. > + @param UseMmio Check if value has to be read from MMIO space or IO space. > + > + @return The value read from the register. > + > +**/ > +UINT8 > +SerialPortReadRegister ( > + UINTN Base, > + UINTN Offset, > + BOOLEAN UseMmio > + ) > +{ > + if (UseMmio) { > + return MmioRead8 (Base + Offset/4); > + } else { > + return IoRead8 (Base + Offset); > + } > +} > + > +/** > + Writes an 8-bit register.. If UseMmio is TRUE, then the value is written to > + MMIO space. If UseMmio is FALSE, then the value is written to I/O space. The > + parameter Offset is added to the base address of the registers. > + > + @param Base The base address register of UART device. > + @param Offset The offset of the register to write. > + @param Value Value to be written. > + @param UseMmio Check if value has to be written to MMIO space or IO space. > + > + @return The value written to the register. > + > +**/ > +UINT8 > +SerialPortWriteRegister ( > + UINTN Base, > + UINTN Offset, > + UINT8 Value, > + BOOLEAN UseMmio > + ) > +{ > + if (UseMmio) { > + return MmioWrite8 (Base + Offset/4, Value); > + } else { > + return IoWrite8 (Base + Offset, Value); > + } > +} > + > +/** > + Initialize the serial device hardware. > + > + If no initialization is required, then return RETURN_SUCCESS. > + If the serial device was successfully initialized, then return RETURN_SUCCESS. > + If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. > + If gUniversalPayloadSerialPortInfoGuid not found, then return RETURN_NOT_FOUND. > + > + @retval RETURN_SUCCESS The serial device was initialized. > + @retval RETURN_DEVICE_ERROR The serial device could not be initialized. > + @retval RETURN_NOT_FOUND GuidHob not found. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortInitialize ( > + VOID > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN SerialRegisterBase; > + UINT32 Divisor; > + UINT32 CurrentDivisor; > + UINT32 BaudRate; > + BOOLEAN Initialized; > + BOOLEAN MmioEnable; > + > + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + if (GuidHob == NULL) { > + return RETURN_NOT_FOUND; > + } > + while (GuidHob != NULL) { > + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); > + SerialRegisterBase = SerialPortInfo->RegisterBase; > + MmioEnable = SerialPortInfo->UseMmio; > + BaudRate = SerialPortInfo->BaudRate; > + > + if (SerialRegisterBase == 0) { > + return RETURN_DEVICE_ERROR; > + } > + > + Divisor = PcdGet32 (PcdSerialClockRate) / (BaudRate * 16); > + if ((PcdGet32 (PcdSerialClockRate) % (BaudRate * 16)) >= BaudRate * 8) { > + Divisor++; > + } > + > + // > + // See if the serial port is already initialized > + // > + Initialized = TRUE; > + if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEnable) & 0x3F) != (PcdGet8 (PcdSerialLineControl) > & 0x3F)) { > + Initialized = FALSE; > + } > + > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, > R_UART_LCR, MmioEnable) | B_UART_LCR_DLAB), MmioEnable); > + CurrentDivisor = SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_HIGH, MmioEnable) << 8; > + CurrentDivisor |= (UINT32)SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_LOW, MmioEnable); > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, > R_UART_LCR, MmioEnable) & ~B_UART_LCR_DLAB), MmioEnable); > + if (CurrentDivisor != Divisor) { > + Initialized = FALSE; > + } > + > + if (Initialized) { > + return RETURN_SUCCESS; > + } > + > + // > + // Wait for the serial port to be ready. > + // Verify that both the transmit FIFO and the shift register are empty. > + // > + while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR, MmioEnable) & (B_UART_LSR_TEMT | > B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) { > + } > + > + // > + // Configure baud rate > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB, MmioEnable); > + SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8)(Divisor >> 8), MmioEnable); > + SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8)(Divisor & 0xff), MmioEnable); > + > + // > + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. > + // Strip reserved bits from PcdSerialLineControl > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3F), > MmioEnable); > + > + // > + // Enable and reset FIFOs > + // Strip reserved bits from PcdSerialFifoControl > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, 0x00, MmioEnable); > + SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & > (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)), MmioEnable); > + > + // > + // Set FIFO Polled Mode by clearing IER after setting FCR > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_IER, 0x00, MmioEnable); > + > + // > + // Put Modem Control Register(MCR) into its reset state of 0x00. > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, 0x00, MmioEnable); > + > + GuidHob = GET_NEXT_HOB (GuidHob); > + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); > + } > + > + 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 return 0. > + > + 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 write operation failed. > + > +**/ > +UINTN > +EFIAPI > +SerialPortWrite ( > + IN UINT8 *Buffer, > + IN UINTN NumberOfBytes > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + UINTN BytesLeft; > + UINTN Index; > + UINTN FifoSize; > + UINT8 *DataBuffer; > + > + if (Buffer == NULL || NumberOfBytes == 0) { > + 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 = PcdGet32 (PcdSerialExtendedTxFifoSize); > + } > + } > + > + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + while (GuidHob != NULL) { > + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); > + BaseAddress = SerialPortInfo->RegisterBase; > + UseMmio = SerialPortInfo->UseMmio; > + > + DataBuffer = Buffer; > + BytesLeft = NumberOfBytes; > + > + while (BytesLeft != 0) { > + // > + // Fill the entire Tx FIFO > + // > + for (Index = 0; Index < FifoSize && BytesLeft != 0; Index++, BytesLeft--, DataBuffer++) { > + // > + // Write byte to the transmit buffer. > + // > + SerialPortWriteRegister (BaseAddress, R_UART_TXBUF, *DataBuffer, UseMmio); > + } > + MicroSecondDelay (20); > + } > + GuidHob = GET_NEXT_HOB (GuidHob); > + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); > + } > + > + return NumberOfBytes; > +} > + > +/** > + 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 > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + UINT8 *DataBuffer; > + UINTN BytesLeft; > + UINTN Result; > + UINT8 Mcr; > + > + if (Buffer == NULL) { > + return 0; > + } > + > + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + while (GuidHob != NULL) { > + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); > + BaseAddress = SerialPortInfo->RegisterBase; > + UseMmio = SerialPortInfo->UseMmio; > + > + DataBuffer = Buffer; > + BytesLeft = NumberOfBytes; > + > + if (BaseAddress == 0) { > + return 0; > + } > + > + Mcr = (UINT8)(SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio) & ~B_UART_MCR_RTS); > + > + for (Result = 0; BytesLeft-- != 0; Result++, DataBuffer++) { > + // > + // Wait for the serial port to have some data. > + // > + while ((SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio) & B_UART_LSR_RXRDY) == 0) { > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + // > + // Set RTS to let the peer send some data > + // > + SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(Mcr | B_UART_MCR_RTS), UseMmio); > + } > + } > + > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + // > + // Clear RTS to prevent peer from sending data > + // > + SerialPortWriteRegister (BaseAddress, R_UART_MCR, Mcr, UseMmio); > + } > + > + // > + // Read byte from the receive buffer. > + // > + *DataBuffer = SerialPortReadRegister (BaseAddress, R_UART_RXBUF, UseMmio); > + } > + > + GuidHob = GET_NEXT_HOB (GuidHob); > + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); > + } > + > + return Result; > +} > + > +/** > + Polls a serial device to see if there is any data waiting to be read. > + > + Polls a serial 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 > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + > + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + while (GuidHob != NULL) { > + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); > + BaseAddress = SerialPortInfo->RegisterBase; > + UseMmio = SerialPortInfo->UseMmio; > + > + if (BaseAddress == 0) { > + return FALSE; > + } > + > + // > + // Read the serial port status > + // > + if ((SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio) & B_UART_LSR_RXRDY) != 0) { > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + // > + // Clear RTS to prevent peer from sending data > + // > + SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(SerialPortReadRegister (BaseAddress, R_UART_MCR, > UseMmio) & ~B_UART_MCR_RTS), UseMmio); > + } > + return TRUE; > + } > + > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + // > + // Set RTS to let the peer send some data > + // > + SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(SerialPortReadRegister (BaseAddress, R_UART_MCR, > UseMmio) | B_UART_MCR_RTS), UseMmio); > + } > + > + GuidHob = GET_NEXT_HOB (GuidHob); > + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); > + } > + return FALSE; > +} > + > +/** > + Sets the control bits on a serial device. > + > + @param Control Sets the bits of Control that are settable. > + > + @retval RETURN_SUCCESS The new control bits were set on the serial device. > + @retval RETURN_UNSUPPORTED The serial device does not support this operation. > + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. > + @retval RETURN_NOT_FOUND GuidHob not found. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortSetControl ( > + IN UINT32 Control > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + UINT8 Mcr; > + > + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + if (GuidHob == NULL) { > + return RETURN_NOT_FOUND; > + } > + while (GuidHob != NULL) { > + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); > + BaseAddress = SerialPortInfo->RegisterBase; > + UseMmio = SerialPortInfo->UseMmio; > + > + if (BaseAddress == 0) { > + return RETURN_UNSUPPORTED; > + } > + > + // > + // First determine the parameter is invalid. > + // > + if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | > + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) > + { > + return RETURN_UNSUPPORTED; > + } > + > + // > + // Read the Modem Control Register. > + // > + Mcr = SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio); > + Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS)); > + > + if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) { > + Mcr |= B_UART_MCR_DTRC; > + } > + > + if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) { > + Mcr |= B_UART_MCR_RTS; > + } > + > + // > + // Write the Modem Control Register. > + // > + SerialPortWriteRegister (BaseAddress, R_UART_MCR, Mcr, UseMmio); > + > + GuidHob = GET_NEXT_HOB (GuidHob); > + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); > + } > + > + return RETURN_SUCCESS; > +} > + > +/** > + Retrieve the status of the control bits on a serial device. > + > + @param Control A pointer to return the current control signals from the serial device. > + > + @retval RETURN_SUCCESS The control bits were read from the serial device. > + @retval RETURN_UNSUPPORTED The serial device does not support this operation. > + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. > + @retval RETURN_NOT_FOUND GuidHob not found. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortGetControl ( > + OUT UINT32 *Control > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + UINT8 Msr; > + UINT8 Mcr; > + UINT8 Lsr; > + > + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + if (GuidHob == NULL) { > + return RETURN_NOT_FOUND; > + } > + while (GuidHob != NULL) { > + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); > + BaseAddress = SerialPortInfo->RegisterBase; > + UseMmio = SerialPortInfo->UseMmio; > + > + if (BaseAddress == 0) { > + return RETURN_UNSUPPORTED; > + } > + > + *Control = 0; > + > + // > + // Read the Modem Status Register. > + // > + Msr = SerialPortReadRegister (BaseAddress, R_UART_MSR, UseMmio); > + > + if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) { > + *Control |= EFI_SERIAL_CLEAR_TO_SEND; > + } > + > + if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) { > + *Control |= EFI_SERIAL_DATA_SET_READY; > + } > + > + if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) { > + *Control |= EFI_SERIAL_RING_INDICATE; > + } > + > + if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) { > + *Control |= EFI_SERIAL_CARRIER_DETECT; > + } > + > + // > + // Read the Modem Control Register. > + // > + Mcr = SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio); > + > + if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) { > + *Control |= EFI_SERIAL_DATA_TERMINAL_READY; > + } > + > + if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) { > + *Control |= EFI_SERIAL_REQUEST_TO_SEND; > + } > + > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; > + } > + > + // > + // Read the Line Status Register. > + // > + Lsr = SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio); > + > + if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) == (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) { > + *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY; > + } > + > + if ((Lsr & B_UART_LSR_RXRDY) == 0) { > + *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY; > + } > + > + GuidHob = GET_NEXT_HOB (GuidHob); > + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); > + } > + > + return RETURN_SUCCESS; > +} > + > +/** > + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, > + data bits, and stop bits on a serial device. > + > + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the > + device's default interface speed. > + On output, the value actually set. > + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the > + serial interface. A ReceiveFifoDepth value of 0 will use > + the device's default FIFO depth. > + On output, the value actually set. > + @param Timeout The requested time out for a single character in microseconds. > + This timeout applies to both the transmit and receive side of the > + interface. A Timeout value of 0 will use the device's default time > + out value. > + On output, the value actually set. > + @param Parity The type of parity to use on this serial device. A Parity value of > + DefaultParity will use the device's default parity value. > + On output, the value actually set. > + @param DataBits The number of data bits to use on the serial device. A DataBits > + vaule of 0 will use the device's default data bit setting. > + On output, the value actually set. > + @param StopBits The number of stop bits to use on this serial device. A StopBits > + value of DefaultStopBits will use the device's default number of > + stop bits. > + On output, the value actually set. > + > + @retval RETURN_SUCCESS The new attributes were set on the serial device. > + @retval RETURN_UNSUPPORTED The serial device does not support this operation. > + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. > + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. > + @retval RETURN_NOT_FOUND GuidHob not found. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortSetAttributes ( > + IN OUT UINT64 *BaudRate, > + IN OUT UINT32 *ReceiveFifoDepth, > + IN OUT UINT32 *Timeout, > + IN OUT EFI_PARITY_TYPE *Parity, > + IN OUT UINT8 *DataBits, > + IN OUT EFI_STOP_BITS_TYPE *StopBits > + ) > +{ > + UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN BaseAddress; > + BOOLEAN UseMmio; > + UINT32 SerialBaudRate; > + UINTN Divisor; > + UINT8 Lcr; > + UINT8 LcrData; > + UINT8 LcrParity; > + UINT8 LcrStop; > + > + GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); > + if (GuidHob == NULL) { > + return RETURN_NOT_FOUND; > + } > + while (GuidHob != NULL) { > + SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); > + BaseAddress = SerialPortInfo->RegisterBase; > + UseMmio = SerialPortInfo->UseMmio; > + > + if (BaseAddress == 0) { > + return RETURN_UNSUPPORTED; > + } > + > + // > + // Check for default settings and fill in actual values. > + // > + if (*BaudRate == 0) { > + *BaudRate = SerialPortInfo->BaudRate; > + } > + > + SerialBaudRate = (UINT32)*BaudRate; > + > + if (*DataBits == 0) { > + LcrData = (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3); > + *DataBits = LcrData + 5; > + } else { > + if ((*DataBits < 5) || (*DataBits > 8)) { > + return RETURN_INVALID_PARAMETER; > + } > + > + // > + // Map 5..8 to 0..3 > + // > + LcrData = (UINT8)(*DataBits - (UINT8)5); > + } > + > + if (*Parity == DefaultParity) { > + LcrParity = (UINT8)((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7); > + switch (LcrParity) { > + case 0: > + *Parity = NoParity; > + break; > + > + case 3: > + *Parity = EvenParity; > + break; > + > + case 1: > + *Parity = OddParity; > + break; > + > + case 7: > + *Parity = SpaceParity; > + break; > + > + case 5: > + *Parity = MarkParity; > + break; > + > + default: > + break; > + } > + } else { > + switch (*Parity) { > + case NoParity: > + LcrParity = 0; > + break; > + > + case EvenParity: > + LcrParity = 3; > + break; > + > + case OddParity: > + LcrParity = 1; > + break; > + > + case SpaceParity: > + LcrParity = 7; > + break; > + > + case MarkParity: > + LcrParity = 5; > + break; > + > + default: > + return RETURN_INVALID_PARAMETER; > + } > + } > + > + if (*StopBits == DefaultStopBits) { > + LcrStop = (UINT8)((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1); > + switch (LcrStop) { > + case 0: > + *StopBits = OneStopBit; > + break; > + > + case 1: > + if (*DataBits == 5) { > + *StopBits = OneFiveStopBits; > + } else { > + *StopBits = TwoStopBits; > + } > + > + break; > + > + default: > + break; > + } > + } else { > + switch (*StopBits) { > + case OneStopBit: > + LcrStop = 0; > + break; > + > + case OneFiveStopBits: > + case TwoStopBits: > + LcrStop = 1; > + break; > + > + default: > + return RETURN_INVALID_PARAMETER; > + } > + } > + > + // > + // Calculate divisor for baud generator > + // Ref_Clk_Rate / Baud_Rate / 16 > + // > + Divisor = PcdGet32 (PcdSerialClockRate) / (SerialBaudRate * 16); > + if ((PcdGet32 (PcdSerialClockRate) % (SerialBaudRate * 16)) >= SerialBaudRate * 8) { > + Divisor++; > + } > + > + // > + // Configure baud rate > + // > + SerialPortWriteRegister (BaseAddress, R_UART_LCR, B_UART_LCR_DLAB, UseMmio); > + SerialPortWriteRegister (BaseAddress, R_UART_BAUD_HIGH, (UINT8)(Divisor >> 8), UseMmio); > + SerialPortWriteRegister (BaseAddress, R_UART_BAUD_LOW, (UINT8)(Divisor & 0xff), UseMmio); > + > + // > + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. > + // Strip reserved bits from line control value > + // > + Lcr = (UINT8)((LcrParity << 3) | (LcrStop << 2) | LcrData); > + SerialPortWriteRegister (BaseAddress, R_UART_LCR, (UINT8)(Lcr & 0x3F), UseMmio); > + > + GuidHob = GET_NEXT_HOB (GuidHob); > + GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); > + } > + > + return RETURN_SUCCESS; > +} > diff --git a/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf > b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf > new file mode 100644 > index 0000000000..ac857d3eea > --- /dev/null > +++ b/UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf > @@ -0,0 +1,39 @@ > +## @file > +# SerialPortLib instance for UART information retrieved from bootloader. > +# > +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR> > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = BaseSerialPortLibHob > + FILE_GUID = d8d22930-e8ec-469f-8184-5a069149b2ff > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = SerialPortLib > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + > +[LibraryClasses] > + PcdLib > + IoLib > + HobLib > + TimerLib > + > +[Sources] > + BaseSerialPortLibHob.c > + > +[Pcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl > + > +[Guids] > + gUniversalPayloadSerialPortInfoGuid > -- > 2.30.2.windows.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 3/3] UefiPayloadPkg: Allow DxeMain.inf to consume the new DebugLib and SerialPortLib 2022-07-14 4:31 [PATCH 1/3] UefiPayloadPkg: Implement a new DebugLib instance kavya 2022-07-14 4:31 ` [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instance kavya @ 2022-07-14 4:31 ` kavya 2022-07-14 7:07 ` [PATCH 1/3] UefiPayloadPkg: Implement a new DebugLib instance Ni, Ray 2 siblings, 0 replies; 5+ messages in thread From: kavya @ 2022-07-14 4:31 UTC (permalink / raw) To: devel; +Cc: Kavya, Guo Dong, Ray Ni, Maurice Ma, Benjamin You, Sean Rhodes Let DxeMain.inf consume new DebugLib and SerialPortLib to support multiple channel debug message on early DXE. Cc: Guo Dong <guo.dong@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Maurice Ma <maurice.ma@intel.com> Cc: Benjamin You <benjamin.you@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Signed-off-by: Kavya <k.kavyax.sravanthi@intel.com> --- UefiPayloadPkg/UefiPayloadPkg.dsc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index 2428bb2ce9..b781cee744 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -573,6 +573,8 @@ # MdeModulePkg/Core/Dxe/DxeMain.inf { <LibraryClasses> + DebugLib|UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.inf + SerialPortLib|UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf } -- 2.30.2.windows.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/3] UefiPayloadPkg: Implement a new DebugLib instance 2022-07-14 4:31 [PATCH 1/3] UefiPayloadPkg: Implement a new DebugLib instance kavya 2022-07-14 4:31 ` [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instance kavya 2022-07-14 4:31 ` [PATCH 3/3] UefiPayloadPkg: Allow DxeMain.inf to consume the new DebugLib and SerialPortLib kavya @ 2022-07-14 7:07 ` Ni, Ray 2 siblings, 0 replies; 5+ messages in thread From: Ni, Ray @ 2022-07-14 7:07 UTC (permalink / raw) To: Sravanthi, K KavyaX, devel@edk2.groups.io Cc: Dong, Guo, Maurice Ma, You, Benjamin, Rhodes, Sean Why need a separate DebugLib instance? > -----Original Message----- > From: Sravanthi, K KavyaX <k.kavyax.sravanthi@intel.com> > Sent: Thursday, July 14, 2022 12:31 PM > To: devel@edk2.groups.io > Cc: Sravanthi, K KavyaX <k.kavyax.sravanthi@intel.com>; Dong, Guo <guo.dong@intel.com>; Ni, Ray <ray.ni@intel.com>; > Maurice Ma <maurice.ma@intel.com>; You, Benjamin <benjamin.you@intel.com>; Rhodes, Sean > <sean@starlabs.systems> > Subject: [PATCH 1/3] UefiPayloadPkg: Implement a new DebugLib instance > > Add new Debug library instance to support multiple channel debug message. > > Cc: Guo Dong <guo.dong@intel.com> > Cc: Ray Ni <ray.ni@intel.com> > Cc: Maurice Ma <maurice.ma@intel.com> > Cc: Benjamin You <benjamin.you@intel.com> > Cc: Sean Rhodes <sean@starlabs.systems> > Signed-off-by: Kavya <k.kavyax.sravanthi@intel.com> > --- > UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.c | 295 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++ > UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.inf | 37 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 332 insertions(+) > > diff --git a/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.c > b/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.c > new file mode 100644 > index 0000000000..0fd9e795a3 > --- /dev/null > +++ b/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.c > @@ -0,0 +1,295 @@ > +/** @file > + Instance of Debug Library based on Serial Port Library. > + > + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR> > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include <Base.h> > +#include <Library/BaseLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/PrintLib.h> > +#include <Library/PcdLib.h> > +#include <Library/DebugPrintErrorLevelLib.h> > + > +// > +// Define the maximum debug and assert message length that this library supports > +// > +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 > + > +/** > + Initialize the serial device hardware. > + > + If no initialization is required, then return RETURN_SUCCESS. > + If the serial device was successfully initialized, then return RETURN_SUCCESS. > + If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. > + If gUniversalPayloadSerialPortInfoGuid not found, then return RETURN_NOT_FOUND. > + > + @retval RETURN_SUCCESS The serial device was initialized. > + @retval RETURN_DEVICE_ERROR The serial device could not be initialized. > + @retval RETURN_NOT_FOUND GuidHob not found. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortInitialize ( > + VOID > + ); > + > +/** > + 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 return 0. > + 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 write operation failed. > + > +**/ > +UINTN > +EFIAPI > +SerialPortWrite ( > + IN UINT8 *Buffer, > + IN UINTN NumberOfBytes > + ); > + > +/** > + Prints a debug message to the debug output device if the specified error level is enabled. > + > + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function > + GetDebugPrintErrorLevel (), then print the message specified by Format and the > + associated variable argument list to the debug output device. > + > + If Format is NULL, then ASSERT(). > + > + @param ErrorLevel The error level of the debug message. > + @param Format Format string for the debug message to print. > + @param ... Variable argument list whose contents are accessed > + based on the format string specified by Format. > + > +**/ > +VOID > +EFIAPI > +DebugPrint ( > + IN UINTN ErrorLevel, > + IN CONST CHAR8 *Format, > + ... > + ) > +{ > + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; > + VA_LIST Marker; > + > + // > + // If Format is NULL, then ASSERT(). > + // > + ASSERT (Format != NULL); > + > + // > + // Check driver debug mask value and global mask > + // > + if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { > + return; > + } > + > + // > + // Convert the DEBUG() message to an ASCII String > + // > + VA_START (Marker, Format); > + AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker); > + VA_END (Marker); > + > + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); > +} > + > +/** > + Prints an assert message containing a filename, line number, and description. > + This may be followed by a breakpoint or a dead loop. > + > + Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n" > + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of > + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if > + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then > + CpuDeadLoop() is called. If neither of these bits are set, then this function > + returns immediately after the message is printed to the debug output device. > + DebugAssert() must actively prevent recursion. If DebugAssert() is called while > + processing another DebugAssert(), then DebugAssert() must return immediately. > + > + If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed. > + If Description is NULL, then a <Description> string of "(NULL) Description" is printed. > + > + @param FileName The pointer to the name of the source file that generated the assert condition. > + @param LineNumber The line number in the source file that generated the assert condition > + @param Description The pointer to the description of the assert condition. > + > +**/ > +VOID > +EFIAPI > +DebugAssert ( > + IN CONST CHAR8 *FileName, > + IN UINTN LineNumber, > + IN CONST CHAR8 *Description > + ) > +{ > + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; > + > + // > + // Generate the ASSERT() message in Ascii format > + // > + AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT [%a] %a(%d): %a\n", gEfiCallerBaseName, FileName, LineNumber, > Description); > + > + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); > + > + // > + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings > + // > + if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { > + CpuBreakpoint (); > + } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { > + CpuDeadLoop (); > + } > +} > + > +/** > + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. > + > + This function fills Length bytes of Buffer with the value specified by > + PcdDebugClearMemoryValue, and returns Buffer. > + > + If Buffer is NULL, then ASSERT(). > + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). > + > + @param Buffer Pointer to the target buffer to be filled with PcdDebugClearMemoryValue. > + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. > + > + @return Buffer Pointer to the target buffer filled with PcdDebugClearMemoryValue. > + > +**/ > +VOID * > +EFIAPI > +DebugClearMemory ( > + OUT VOID *Buffer, > + IN UINTN Length > + ) > +{ > + ASSERT (Buffer != NULL); > + > + return SetMem (Buffer, Length, PcdGet8 (PcdDebugClearMemoryValue)); > +} > + > +/** > + Returns TRUE if ASSERT() macros are enabled. > + > + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of > + PcdDebugProperyMask is set. Otherwise FALSE is returned. > + > + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. > + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. > + > +**/ > +BOOLEAN > +EFIAPI > +DebugAssertEnabled ( > + VOID > + ) > +{ > + return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); > +} > + > +/** > + Returns TRUE if DEBUG() macros are enabled. > + > + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of > + PcdDebugProperyMask is set. Otherwise FALSE is returned. > + > + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. > + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. > + > +**/ > +BOOLEAN > +EFIAPI > +DebugPrintEnabled ( > + VOID > + ) > +{ > + return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); > +} > + > +/** > + Returns TRUE if DEBUG_CODE() macros are enabled. > + > + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of > + PcdDebugProperyMask is set. Otherwise FALSE is returned. > + > + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. > + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. > + > +**/ > +BOOLEAN > +EFIAPI > +DebugCodeEnabled ( > + VOID > + ) > +{ > + return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); > +} > + > +/** > + Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled. > + > + This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of > + PcdDebugProperyMask is set. Otherwise FALSE is returned. > + > + @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. > + @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. > + > +**/ > +BOOLEAN > +EFIAPI > +DebugClearMemoryEnabled ( > + VOID > + ) > +{ > + return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); > +} > + > +/** > + Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel. > + > + This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel. > + > + @retval TRUE Current ErrorLevel is supported. > + @retval FALSE Current ErrorLevel is not supported. > + > +**/ > +BOOLEAN > +EFIAPI > +DebugPrintLevelEnabled ( > + IN CONST UINTN ErrorLevel > + ) > +{ > + return (BOOLEAN)((ErrorLevel & PcdGet32 (PcdFixedDebugPrintErrorLevel)) != 0); > +} > + > +/** > + The constructor function to initialize Debug port Library > + > + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. > + > +**/ > +RETURN_STATUS > +EFIAPI > +BaseDebugLibHobConstructor ( > + VOID > + ) > +{ > + return SerialPortInitialize (); > +} > diff --git a/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.inf > b/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.inf > new file mode 100644 > index 0000000000..11ed8de08b > --- /dev/null > +++ b/UefiPayloadPkg/Library/BaseDebugLibHob/BaseDebugLibHob.inf > @@ -0,0 +1,37 @@ > +## @file > +# Instance of Debug Library based on Serial Port Library. > +# > +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR> > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = BaseDebugLibHob > + FILE_GUID = ae4cc887-ea47-4d5c-a8f9-1d08405b5f8b > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = DebugLib > + CONSTRUCTOR = BaseDebugLibHobConstructor > + > +[Sources] > + BaseDebugLibHob.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + > +[LibraryClasses] > + BaseLib > + PcdLib > + DebugPrintErrorLevelLib > + BaseMemoryLib > + PrintLib > + SerialPortLib > + > +[Pcd] > + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue > + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask > + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel > -- > 2.30.2.windows.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2022-07-14 7:07 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-07-14 4:31 [PATCH 1/3] UefiPayloadPkg: Implement a new DebugLib instance kavya 2022-07-14 4:31 ` [PATCH 2/3] UefiPayloadPkg: Implement a new SerialPortLib instance kavya 2022-07-14 7:04 ` Ni, Ray 2022-07-14 4:31 ` [PATCH 3/3] UefiPayloadPkg: Allow DxeMain.inf to consume the new DebugLib and SerialPortLib kavya 2022-07-14 7:07 ` [PATCH 1/3] UefiPayloadPkg: Implement a new DebugLib instance Ni, Ray
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox