Reviewed-by: Sean Rhodes <sean@starlabs.systems>

On Wed, 8 Jun 2022 at 16:05, Lean Sheng Tan <sheng....@9elements.com> wrote:

> Reviewed-by: Lean Sheng Tan <sheng....@9elements.com>
>
>
>
> On Mon, 6 Jun 2022 at 02:56, 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                          |  13 +
>>  UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.c   | 264
>> ++++++++++++++++++++
>>  UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.inf |  30 +++
>>  UefiPayloadPkg/UefiPayloadPkg.dsc                          |  25 +-
>>  4 files changed, 327 insertions(+), 5 deletions(-)
>>
>> diff --git a/UefiPayloadPkg/Include/Coreboot.h
>> b/UefiPayloadPkg/Include/Coreboot.h
>> index a3e1109fe84e..5892fae7682b 100644
>> --- a/UefiPayloadPkg/Include/Coreboot.h
>> +++ b/UefiPayloadPkg/Include/Coreboot.h
>> @@ -199,6 +199,13 @@ struct cb_forward {
>>    UINT64    forward;
>>  };
>>
>> +struct cb_cbmem_ref {
>> +  UINT32    tag;
>> +  // Field contains size of this struct = 0x0010
>> +  UINT32    size;
>> +  UINT64    cbmem_addr;
>> +};
>> +
>>  #define CB_TAG_FRAMEBUFFER  0x0012
>>  struct cb_framebuffer {
>>    UINT32    tag;
>> @@ -229,6 +236,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..863fbcfef2f0
>> --- /dev/null
>> +++ b/UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.c
>> @@ -0,0 +1,264 @@
>> +/** @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  *mCbConsole = 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
>> +  )
>> +{
>> +  // The coreboot table contains large structures as references
>> +  struct cb_cbmem_ref *cbref = FindCbTag(CB_TAG_CBMEM_CONSOLE);
>> +  if (!cbref) {
>> +    return RETURN_DEVICE_ERROR;
>> +  }
>> +
>> +  mCbConsole = (VOID *)(UINTN)cbref->cbmem_addr;  // Support PEI and DXE
>> +  if (mCbConsole == 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 (!mCbConsole) {
>> +    return 0;
>> +  }
>> +
>> +  cursor = mCbConsole->cursor & CBMC_CURSOR_MASK;
>> +  flags = mCbConsole->cursor & ~CBMC_CURSOR_MASK;
>> +  if (cursor >= mCbConsole->size) {
>> +    // Already overflowed; bail out. TODO: Is this unnecessarily
>> cautious?
>> +    // - Supports old coreboot version with legacy overflow mechanism.
>> +    return 0;
>> +  }
>> +
>> +  if (cursor + NumberOfBytes > mCbConsole->size) {
>> +    // Will overflow, zero cursor and set flag.
>> +    cursor = 0;
>> +    flags |= CBMC_OVERFLOW;
>> +  }
>> +
>> +  if (NumberOfBytes > mCbConsole->size) {
>> +    // This one debug message is longer than the entire buffer. Truncate
>> it.
>> +    // - TODO: Is this unnecessarily cautious?
>> +    NumberOfBytes = mCbConsole->size;
>> +  }
>> +
>> +  CopyMem (&mCbConsole->body[cursor], Buffer, NumberOfBytes);
>> +  cursor += NumberOfBytes;
>> +
>> +  if (cursor == mCbConsole->size) {
>> +    // Next message will overflow, zero cursor.
>> +    // - Set flag preemptively. This could not be determined later.
>> +    cursor = 0;
>> +    flags |= CBMC_OVERFLOW;
>> +  }
>> +
>> +  mCbConsole->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 (#90214): https://edk2.groups.io/g/devel/message/90214
>> Mute This Topic: https://groups.io/mt/91568694/6757431
>> Group Owner: devel+ow...@edk2.groups.io
>> Unsubscribe: https://edk2.groups.io/g/devel/unsub [
>> sheng....@9elements.com]
>> ------------
>>
>>
>>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#90382): https://edk2.groups.io/g/devel/message/90382
Mute This Topic: https://groups.io/mt/91568694/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to