Reviewed-by: Sean Rhodes <sean@starlabs.systems>
On Sun, 22 May 2022 at 19:47, Benjamin Doron <benjamin.doro...@gmail.com> wrote: > Writes TianoCore debug logs into the CBMEM console ringbuffer, from > where the user can retrieve them with the `cbmem` userspace utility. > > The intention is to aid in debugging non-fatal issues even in release > builds, or simply make TianoCore's logs available to those interested. > Consequently, MDEPKG_NDEBUG must be masked. As an in-memory debug > logging library, ASSERTs must be non-fatal to be seen, so they neither > dead-loop nor create a breakpoint. It is assumed that ASSERT() neither > enforces fatal conditions nor security integrity, as release builds do > not call DebugAssert() from the ASSERT macro. > > More detailed debug logs are produced with the DEBUG_CODE macro, but > this guards other debug-related code throughout the codebase. To avoid > changing behaviour on release builds, this is only set for debug builds. > > Tested on QEMU, dumping the appropriate memory region in the UEFI shell > shows the TianoCore log. An improved revision of the debug library used > in several coreboot-related EDK2 forks, including MrChromebox's. > Previous revisions also tested on an Acer Aspire VN7-572G laptop. > > Cc: Guo Dong <guo.d...@intel.com> > Cc: Ray Ni <ray...@intel.com> > Cc: Maurice Ma <maurice...@intel.com> > Cc: Benjamin You <benjamin....@intel.com> > Cc: Sean Rhodes <sean@starlabs.systems> > Signed-off-by: Benjamin Doron <benjamin.doro...@gmail.com> > --- > UefiPayloadPkg/Include/Coreboot.h | 12 + > UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.c | 258 > ++++++++++++++++++++ > UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.inf | 30 +++ > UefiPayloadPkg/UefiPayloadPkg.dsc | 25 +- > 4 files changed, 320 insertions(+), 5 deletions(-) > > diff --git a/UefiPayloadPkg/Include/Coreboot.h > b/UefiPayloadPkg/Include/Coreboot.h > index a3e1109fe84e..4c9cf965519b 100644 > --- a/UefiPayloadPkg/Include/Coreboot.h > +++ b/UefiPayloadPkg/Include/Coreboot.h > @@ -199,6 +199,12 @@ struct cb_forward { > UINT64 forward; > }; > > +struct cb_cbmem_ref { > + UINT32 tag; > + UINT32 size; > + UINT64 cbmem_addr; > +}; > + > #define CB_TAG_FRAMEBUFFER 0x0012 > struct cb_framebuffer { > UINT32 tag; > @@ -229,6 +235,12 @@ struct cb_vdat { > > #define CB_TAG_TIMESTAMPS 0x0016 > #define CB_TAG_CBMEM_CONSOLE 0x0017 > +struct cbmem_console { > + UINT32 size; > + UINT32 cursor; > + UINT8 body[0]; > +} __attribute__((packed)); > + > #define CB_TAG_MRC_CACHE 0x0018 > struct cb_cbmem_tab { > UINT32 tag; > diff --git a/UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.c > b/UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.c > new file mode 100644 > index 000000000000..f7c06b0f41e9 > --- /dev/null > +++ b/UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.c > @@ -0,0 +1,258 @@ > +/** @file > + CBMEM console SerialPortLib instance > + > + Copyright (c) 2022, Baruch Binyamin Doron > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include <Base.h> > +#include <Coreboot.h> > + > +#include <Library/BaseMemoryLib.h> > +#include <Library/BlParseLib.h> > +#include <Library/SerialPortLib.h> > + > +// Upper nibble contains flags > +#define CBMC_CURSOR_MASK ((1 << 28) - 1) > +#define CBMC_OVERFLOW (1 << 31) > + > +STATIC struct cbmem_console *gCbConsole = NULL; > + > +/** > + Find coreboot record with given Tag. > + NOTE: This coreboot-specific function definition is absent > + from the common BlParseLib header. > + > + @param Tag The tag id to be found > + > + @retval NULL The Tag is not found. > + @retval Others The pointer to the record found. > + > +**/ > +VOID * > +FindCbTag ( > + IN UINT32 Tag > + ); > + > +/** > + 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. > + > + @retval RETURN_SUCCESS The serial device was initialized. > + @retval RETURN_DEVICE_ERROR The serial device could not be > initialized. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortInitialize ( > + VOID > + ) > +{ > + struct cb_cbmem_ref *cbref = FindCbTag(CB_TAG_CBMEM_CONSOLE); > + if (!cbref) { > + return RETURN_DEVICE_ERROR; > + } > + > + gCbConsole = (VOID *)(UINTN)cbref->cbmem_addr; // Support PEI and DXE > + if (gCbConsole == NULL) { > + return RETURN_DEVICE_ERROR; > + } > + > + 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 write operation failed. > + > +**/ > +UINTN > +EFIAPI > +SerialPortWrite ( > + IN UINT8 *Buffer, > + IN UINTN NumberOfBytes > + ) > +{ > + UINT32 cursor; > + UINT32 flags; > + > + if (Buffer == NULL || NumberOfBytes == 0) { > + return 0; > + } > + > + if (!gCbConsole) { > + return 0; > + } > + > + cursor = gCbConsole->cursor & CBMC_CURSOR_MASK; > + flags = gCbConsole->cursor & ~CBMC_CURSOR_MASK; > + if (cursor >= gCbConsole->size) { > + // Already overflowed; bail out. TODO: Is this unnecessarily cautious? > + // - Supports old coreboot version with legacy overflow mechanism. > + return 0; > + } > + > + if (cursor + NumberOfBytes > gCbConsole->size) { > + // Will overflow, zero cursor and set flag. > + cursor = 0; > + flags |= CBMC_OVERFLOW; > + } > + > + // Longest debug messages supported by a DebugLib seems to be > CHAR16[0x100] == 512. > + // So, no chance that one message could overflow even the smallest > buffer. > + CopyMem (&gCbConsole->body[cursor], Buffer, NumberOfBytes); > + cursor += NumberOfBytes; > + > + if (cursor == gCbConsole->size) { > + // Next message will overflow, zero cursor. > + // - But not overflowed yet. Do not set flag. > + cursor = 0; > + } > + > + gCbConsole->cursor = flags | cursor; > + > + return NumberOfBytes; > +} > + > +/** > + Read data from serial device and save the datas in buffer. > + > + Reads NumberOfBytes data bytes from a serial device into the buffer > + specified by Buffer. The number of bytes actually read is returned. > + If Buffer is NULL, then ASSERT(). > + If NumberOfBytes is zero, then return 0. > + > + @param Buffer Pointer to the data buffer to store the data > read from the serial device. > + @param NumberOfBytes Number of bytes which will be read. > + > + @retval 0 Read data failed, no data is to be read. > + @retval >0 Actual number of bytes read from serial device. > + > +**/ > +UINTN > +EFIAPI > +SerialPortRead ( > + OUT UINT8 *Buffer, > + IN UINTN NumberOfBytes > +) > +{ > + return 0; > +} > + > +/** > + Polls a serial device to see if there is any data waiting to be read. > + > + @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 > + ) > +{ > + 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. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortSetControl ( > + IN UINT32 Control > + ) > +{ > + return RETURN_UNSUPPORTED; > +} > + > +/** > + 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. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortGetControl ( > + OUT UINT32 *Control > + ) > +{ > + return RETURN_UNSUPPORTED; > +} > + > +/** > + Sets the baud rate, receive FIFO depth, transmit/receive 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 ReceiveFifoDepth 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 > + value 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. > + > +**/ > +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 > + ) > +{ > + return RETURN_UNSUPPORTED; > +} > + > diff --git a/UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.inf > b/UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.inf > new file mode 100644 > index 000000000000..3df6a0c736a5 > --- /dev/null > +++ b/UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.inf > @@ -0,0 +1,30 @@ > +## @file > +# Component description file for CbSerialPortLib library. > +# > +# Copyright (c) 2022, Baruch Binyamin Doron > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = CbSerialPortLib > + FILE_GUID = 0DB3EF12-1426-4086-B012-113184C4CE11 > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + # Recall that debug logging can be unsafe to core. Route over RSC. > + LIBRARY_CLASS = SerialPortLib > + CONSTRUCTOR = SerialPortInitialize > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + UefiPayloadPkg/UefiPayloadPkg.dec > + > +[LibraryClasses] > + BaseMemoryLib > + BlParseLib > + > +[Sources] > + CbSerialPortLib.c > + > diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc > b/UefiPayloadPkg/UefiPayloadPkg.dsc > index 4d9bbc80c866..0e4248767756 100644 > --- a/UefiPayloadPkg/UefiPayloadPkg.dsc > +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc > @@ -37,6 +37,7 @@ > DEFINE ABOVE_4G_MEMORY = TRUE > DEFINE BOOT_MANAGER_ESCAPE = FALSE > DEFINE SD_MMC_TIMEOUT = 1000000 > + DEFINE USE_CBMEM_FOR_CONSOLE = FALSE > # > # SBL: UEFI payload for Slim Bootloader > # COREBOOT: UEFI payload for coreboot > @@ -121,10 +122,11 @@ > > [BuildOptions] > *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES > - GCC:*_UNIXGCC_*_CC_FLAGS = -DMDEPKG_NDEBUG > +!if $(USE_CBMEM_FOR_CONSOLE) == FALSE > GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG > INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG > MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG > +!endif > > [BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER] > GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000 > @@ -231,8 +233,13 @@ > TimerLib|UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.inf > !endif > ResetSystemLib|UefiPayloadPkg/Library/ResetSystemLib/ResetSystemLib.inf > +!if $(USE_CBMEM_FOR_CONSOLE) == TRUE > + SerialPortLib|UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.inf > + > PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf > +!else > > > SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf > > PlatformHookLib|UefiPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf > +!endif > > > PlatformBootManagerLib|UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf > > @@ -422,10 +429,18 @@ > gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, > 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, > 0x23, 0x31 } > gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7 > gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F > -!if $(SOURCE_DEBUG_ENABLE) > - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 > +!if $(USE_CBMEM_FOR_CONSOLE) == FALSE > + !if $(SOURCE_DEBUG_ENABLE) > + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 > + !else > + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F > + !endif > !else > - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F > + !if $(TARGET) == DEBUG > + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x07 > + !else > + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x03 > + !endif > !endif > > > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|$(MAX_SIZE_NON_POPULATE_CAPSULE) > # > @@ -471,7 +486,7 @@ > gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode > gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress > gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize > -!if $(TARGET) == DEBUG > +!if ($(TARGET) == DEBUG || $(USE_CBMEM_FOR_CONSOLE) == TRUE) > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE > !else > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE > -- > 2.36.1 > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#90039): https://edk2.groups.io/g/devel/message/90039 Mute This Topic: https://groups.io/mt/91273919/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-