public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Alexander Graf" <graf@amazon.com>
To: <devel@edk2.groups.io>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Leif Lindholm <quic_llindhol@quicinc.com>,
	Dandan Bi <dandan.bi@intel.com>,
	Zhichao Gao <zhichao.gao@intel.com>,
	Liming Gao <gaoliming@byosoft.com.cn>
Subject: [PATCH 07/12] MdePkg: Add Dxe phase BaseDebugBootlog
Date: Fri, 27 May 2022 04:43:12 +0200	[thread overview]
Message-ID: <20220527024317.13476-8-graf@amazon.com> (raw)
In-Reply-To: <20220527024317.13476-1-graf@amazon.com>

This patch adds the main bootlog infrastructure to dynamically create the
bootlog configuration table and edk2 bootlog at DXE phase. It attempts to
do all this dynamically: The bootlog configuration table may first get
created by a UEFI application.

This code also collects all PEI phase log entries and assembles them into
the final bootlog.

Signed-off-by: Alexander Graf <graf@amazon.com>
---
 .../BaseDebugBootlog/BaseDebugBootlogLib.inf  |  61 +++
 .../BaseDebugBootlog/DebugBootlogDxe.c        | 349 ++++++++++++++++++
 2 files changed, 410 insertions(+)
 create mode 100644 MdePkg/Library/BaseDebugBootlog/BaseDebugBootlogLib.inf
 create mode 100644 MdePkg/Library/BaseDebugBootlog/DebugBootlogDxe.c

diff --git a/MdePkg/Library/BaseDebugBootlog/BaseDebugBootlogLib.inf b/MdePkg/Library/BaseDebugBootlog/BaseDebugBootlogLib.inf
new file mode 100644
index 0000000000..49cdd3f9ad
--- /dev/null
+++ b/MdePkg/Library/BaseDebugBootlog/BaseDebugBootlogLib.inf
@@ -0,0 +1,61 @@
+## @file
+#  Base Debug library instance for a RAM based boot log
+#  It provides functions to store debug messages in RAM and make them available as
+#  Bootlog Configuration Table.
+#
+#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2012, Red Hat, Inc.<BR>
+#  Copyright (c) 2022, Amazon Development Center Germany GmbH. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseDebugBootlog
+  FILE_GUID                      = DF934DA3-CD31-49FE-AF50-B3C87C79325C
+  MODULE_TYPE                    = DXE_CORE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = DebugBootlogLib|DXE_CORE DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION
+  CONSTRUCTOR                    = BaseDebugBootlogLibConstructor
+
+[Sources]
+  DebugBootlog.c
+  DebugBootlogDxe.c
+
+[Sources.IA32, Sources.X64]
+  DebugBootlogX86.c
+
+[Sources.ARM, Sources.AARCH64]
+  DebugBootlogArm.c
+
+[Sources.EBC, Sources.RISCV64]
+  DebugBootlogNotime.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[Packages.AARCH64]
+  ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  PcdLib
+  PrintLib
+  BaseLib
+  DebugPrintErrorLevelLib
+
+[LibraryClasses.AARCH64]
+  ArmGenericTimerCounterLib
+
+[LibraryClasses.ARM]
+  ArmGenericTimerCounterLib
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdDebugBootlogErrorLevel       ## CONSUMES
+
+[Guids]
+  gBootlogConfigTableGuid ## CONSUMES
+  gEfiHobListGuid ## CONSUMES
diff --git a/MdePkg/Library/BaseDebugBootlog/DebugBootlogDxe.c b/MdePkg/Library/BaseDebugBootlog/DebugBootlogDxe.c
new file mode 100644
index 0000000000..b95cb969f1
--- /dev/null
+++ b/MdePkg/Library/BaseDebugBootlog/DebugBootlogDxe.c
@@ -0,0 +1,349 @@
+/** @file
+  Base Debug library instance for a RAM based boot log
+  It provides functions to store debug messages in RAM and make them available as
+  Bootlog Configuration Table.
+
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2012, Red Hat, Inc.<BR>
+  Copyright (c) 2022, Amazon Development Center Germany GmbH.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BaseDebugBootlog.h"
+
+//
+// Cached pointer to the current bootlog structure
+//
+BOOTLOG_HEADER *gBootlog;
+
+//
+// We can not link against UefiBootServicesTableLib as that itself references
+// DebugLib, so instead we save our own copies of the System Table and Boot
+// Services structs.
+//
+static EFI_SYSTEM_TABLE *mDebugST;
+
+/**
+  We can not link against UefiBootServicesTableLib as that itself references
+  DebugLib, so instead we save our own copies of the System Table and Boot
+  Services structs.
+
+  @retval EFI_SUCCESS   The constructor always returns RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+BaseDebugBootlogLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  mDebugST = SystemTable;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+BaseDebugBootlogAppendInternal (
+  IN  CONST CHAR8  *String,
+  IN        UINTN  Length,
+  IN        UINTN  ErrorLevel,
+  IN        UINT64 Ticks
+  );
+
+static
+EFI_STATUS
+EFIAPI
+UpdateEdk2Bootlog (
+  IN BOOTLOG_CONFIG_TABLE *Table,
+  IN BOOTLOG_HEADER       *OldBootlog,
+  IN BOOTLOG_HEADER       *NewBootlog
+  )
+{
+  UINTN Index;
+
+  for (Index = 0; Index < Table->NrLogs; Index++) {
+    if (Table->LogAddress[Index] == (EFI_PHYSICAL_ADDRESS) OldBootlog) {
+      Table->LogAddress[Index] = (EFI_PHYSICAL_ADDRESS) NewBootlog;
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+static
+EFI_STATUS
+EFIAPI
+FindEdk2Bootlog (
+  IN  BOOTLOG_CONFIG_TABLE  *Table,
+  OUT BOOTLOG_HEADER       **Bootlog
+  )
+{
+  UINTN Index;
+  BOOTLOG_HEADER *Cur;
+
+  for (Index = 0; Index < Table->NrLogs; Index++) {
+    Cur = (BOOTLOG_HEADER *)Table->LogAddress[Index];
+    if (Cur->Signature == SIG_BOOTLOG_HEADER &&
+        CompareMem(Cur->Producer, BOOTLOG_PRODUCER, sizeof(Cur->Producer)) == 0 &&
+        Cur->ExtraHeaderType == BOOTLOG_EXTRA_HEADER_EDK2) {
+      *Bootlog = Cur;
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+static
+EFI_STATUS
+EFIAPI
+FindConfigTable (
+  IN  EFI_GUID *TableGuid,
+  OUT VOID     *Table
+  )
+{
+  EFI_SYSTEM_TABLE  *SystemTable;
+  VOID             **_Table = Table;
+  UINTN             Index;
+
+  if (TableGuid == NULL || Table == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  SystemTable = mDebugST;
+  *_Table      = NULL;
+  for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) {
+    if (CompareGuid (TableGuid, &(SystemTable->ConfigurationTable[Index].VendorGuid))) {
+      *_Table = SystemTable->ConfigurationTable[Index].VendorTable;
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+static
+EFI_STATUS
+EFIAPI
+AllocateTable (
+  IN EFI_BOOT_SERVICES     *BS,
+  IN BOOTLOG_CONFIG_TABLE **pTable
+  )
+{
+  EFI_STATUS Status;
+  UINTN TableLength = sizeof(BOOTLOG_CONFIG_TABLE) + MAX_LOGS * sizeof(UINT64);
+
+  Status = BS->AllocatePool (
+                  EfiBootServicesData,
+                  TableLength,
+                  (VOID **)pTable
+                  );
+  if (Status != EFI_SUCCESS)
+    return Status;
+
+  ZeroMem (*pTable, TableLength);
+  (*pTable)->Signature = SIG_BOOTLOG_CONFIG_TABLE;
+  (*pTable)->MaxLogs = MAX_LOGS;
+
+  return Status;
+}
+
+static
+EFI_STATUS
+EFIAPI
+AllocateBootlog (
+  IN EFI_BOOT_SERVICES  *BS,
+  IN BOOTLOG_HEADER    **NewBootlog,
+  IN UINTN               Size
+  )
+{
+  EFI_STATUS Status;
+
+  Status = BS->AllocatePages (
+                  AllocateAnyPages,
+                  EfiBootServicesData,
+                  EFI_SIZE_TO_PAGES (Size),
+                  (EFI_PHYSICAL_ADDRESS *)NewBootlog
+                  );
+  if (Status != EFI_SUCCESS)
+    return Status;
+
+  ZeroMem (*NewBootlog, Size);
+
+  return Status;
+}
+
+static
+VOID
+EFIAPI
+BaseDebugLibBootlogInitialize (
+  IN BOOTLOG_HEADER *Bootlog,
+  IN UINT64 Size
+  )
+{
+  Bootlog->Signature = SIG_BOOTLOG_HEADER;
+  CopyMem(Bootlog->Producer, BOOTLOG_PRODUCER, sizeof(Bootlog->Producer));
+  Bootlog->ExtraHeaderType = BOOTLOG_EXTRA_HEADER_EDK2;
+  Bootlog->ExtraHeaderSize = sizeof(Bootlog->ExtraHeader);
+  Bootlog->MsgExtraHeaderSize = sizeof(BOOTLOG_ENTRY_EDK2) - sizeof(BOOTLOG_ENTRY);
+  Bootlog->LastByte = OFFSET_OF(BOOTLOG_HEADER, Data);
+  Bootlog->TicksPerSecond = BaseDebugLibBootlogTicksPerSecond();
+  Bootlog->ExtraHeader.AllocatedSize = Size;
+}
+
+static
+EFI_STATUS
+EFIAPI
+BaseDebugLibFindAndExpandBootlog (
+  IN BOOTLOG_HEADER **pBootlog,
+  IN UINTN AppendDataLength
+  )
+{
+  EFI_BOOT_SERVICES    *BS;
+  BOOTLOG_HEADER       *Bootlog;
+  BOOTLOG_HEADER       *NewBootlog;
+  BOOTLOG_CONFIG_TABLE *Table;
+  EFI_STATUS            Status = EFI_SUCCESS;
+  UINTN                 NewSize;
+  EFI_PEI_HOB_POINTERS  Hob;
+
+  if (!mDebugST || !mDebugST->BootServices)
+    return EFI_NOT_FOUND;
+
+  BS = mDebugST->BootServices;
+
+  if (!gBootlog) {
+    /* Allocate a new Bootlog Configuration Table if not present */
+    if (FindConfigTable (&gBootlogConfigTableGuid, &Table) != EFI_SUCCESS) {
+      Status = AllocateTable (BS, &Table);
+      if (Status != EFI_SUCCESS) {
+        return Status;
+      }
+
+      Status = BS->InstallConfigurationTable (
+                      &gBootlogConfigTableGuid,
+                      Table
+                      );
+      if (Status != EFI_SUCCESS) {
+        return Status;
+      }
+    }
+
+    /* Allocate a Bootlog structure if none is in the table */
+    if (FindEdk2Bootlog (Table, &Bootlog) != EFI_SUCCESS) {
+      /*
+       * There is a tiny phase right after DXE entry where gEfiHobListGuid is
+       * not populated yet. But we need the HobList to carry PEI logs over.
+       * Let's just drop any line that we get in that period.
+       */
+      Status = FindConfigTable (&gEfiHobListGuid, &Hob.Raw);
+      if (Status != EFI_SUCCESS) {
+        return Status;
+      }
+
+      Status = AllocateBootlog (BS, &Bootlog, BOOTLOG_MIN_SIZE);
+      if (Status != EFI_SUCCESS) {
+        return Status;
+      }
+      BaseDebugLibBootlogInitialize(Bootlog, BOOTLOG_MIN_SIZE);
+
+      if (Table->NrLogs >= Table->MaxLogs) {
+        return EFI_NOT_FOUND;
+      }
+      Table->LogAddress[Table->NrLogs++] = (EFI_PHYSICAL_ADDRESS) Bootlog;
+
+      gBootlog = Bootlog;
+
+      /*
+       * This is the first time we go from PEI -> DXE. Copy all PEI log entries
+       * into our full fledged boot log structure
+       */
+      if (Status == EFI_SUCCESS) {
+        while (!END_OF_HOB_LIST (Hob)) {
+          if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION &&
+              CompareGuid (&gBootlogConfigTableGuid, &Hob.Guid->Name) &&
+              GET_HOB_LENGTH (Hob) > sizeof (BOOTLOG_ENTRY_EDK2)) {
+              BOOTLOG_ENTRY_EDK2 *Entry = GET_GUID_HOB_DATA (Hob);
+              BaseDebugBootlogAppendInternal (
+                  Entry->Log.String,
+                  AsciiStrLen (Entry->Log.String),
+                  Entry->ErrorLevel,
+                  Entry->Log.Ticks
+                  );
+          }
+
+          Hob.Raw = GET_NEXT_HOB (Hob);
+        }
+      }
+    }
+
+    gBootlog = Bootlog;
+  } else {
+    Bootlog = gBootlog;
+  }
+
+  /* Resize if the new string would not fit */
+  if ((Bootlog->LastByte + AppendDataLength) > Bootlog->ExtraHeader.AllocatedSize) {
+    NewSize = ALIGN_VALUE (Bootlog->LastByte + AppendDataLength + EFI_PAGE_SIZE * 16,
+                           EFI_PAGE_SIZE);
+    Status = AllocateBootlog (BS, &NewBootlog, NewSize);
+    if (Status != EFI_SUCCESS) {
+      return Status;
+    }
+
+    CopyMem (NewBootlog, Bootlog, Bootlog->LastByte);
+    NewBootlog->ExtraHeader.AllocatedSize = NewSize;
+    UpdateEdk2Bootlog (Table, Bootlog, NewBootlog);
+    BS->FreePages ((EFI_PHYSICAL_ADDRESS) Bootlog,
+                   EFI_SIZE_TO_PAGES (Bootlog->ExtraHeader.AllocatedSize));
+    Bootlog = gBootlog = NewBootlog;
+  }
+
+  *pBootlog = Bootlog;
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+BaseDebugBootlogAppendInternal (
+  IN  CONST CHAR8  *String,
+  IN        UINTN  Length,
+  IN        UINTN  ErrorLevel,
+  IN        UINT64 Ticks
+  )
+{
+  BOOTLOG_HEADER     *Bootlog;
+  BOOTLOG_ENTRY_EDK2  Hdr;
+
+  if (BaseDebugLibFindAndExpandBootlog (&Bootlog, Length + sizeof(Hdr)) != EFI_SUCCESS)
+    return EFI_SUCCESS;
+
+  Hdr.ErrorLevel = ErrorLevel;
+  Hdr.Log.Ticks = Ticks;
+
+  CopyMem (((VOID *)Bootlog) + Bootlog->LastByte, &Hdr, sizeof(Hdr));
+  Bootlog->LastByte += sizeof(Hdr);
+  CopyMem (((VOID *)Bootlog) + Bootlog->LastByte, String, Length);
+  Bootlog->LastByte += Length;
+  *((CHAR8 *)Bootlog + Bootlog->LastByte) = '\0';
+  Bootlog->LastByte += 1;
+
+  return EFI_SUCCESS;
+}
+
+RETURN_STATUS
+EFIAPI
+DebugBootlogAppend (
+  IN  CONST CHAR8  *String,
+  IN        UINTN  Length,
+  IN        UINTN  ErrorLevel
+  )
+{
+  return BaseDebugBootlogAppendInternal(String, Length, ErrorLevel,
+                                        BaseDebugLibBootlogTicks ());
+}
-- 
2.28.0.394.ge197136389




Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879




  parent reply	other threads:[~2022-05-27  2:43 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-27  2:43 [PATCH 00/12] Introduce Bootlog DEBUG() output Alexander Graf
2022-05-27  2:43 ` [PATCH 01/12] MdePkg: Add DebugBootlog header Alexander Graf
2022-05-27  2:43 ` [PATCH 02/12] MdePkg: Add Null BaseDebugBootlog Alexander Graf
2022-05-27  2:43 ` [PATCH 03/12] MdePkg: Add Fallback timer support for BaseDebugBootlog Alexander Graf
2022-05-27  2:43 ` [PATCH 04/12] MdePkg: Add X86 " Alexander Graf
2022-05-27  2:43 ` [PATCH 05/12] MdePkg: Add ARM " Alexander Graf
2022-05-27  2:43 ` [PATCH 06/12] MdePkg: Add Pei phase BaseDebugBootlog Alexander Graf
2022-05-27  2:43 ` Alexander Graf [this message]
2022-05-27  2:43 ` [PATCH 08/12] MdePkg: Add BaseDebugLibBootlog Alexander Graf
2022-05-27  2:43 ` [PATCH 09/12] Scripts: Add bootlog decyphering script Alexander Graf
2022-05-27  2:43 ` [PATCH 10/12] BaseDebugLibSerialPort: Include BaseDebugBootlog in all dscs Alexander Graf
2022-05-27  2:43 ` [PATCH 11/12] BaseDebugLibSerialPort: Emit messages to boot log Alexander Graf
2022-05-27  2:43 ` [PATCH 12/12] OvmfPkg/PlatformDebugLibIoPort: Add Bootlog support Alexander Graf
2022-06-01  9:33 ` [edk2-devel] [PATCH 00/12] Introduce Bootlog DEBUG() output Gerd Hoffmann
2022-06-01 16:58   ` Benjamin Doron
2022-06-02  8:35     ` Gerd Hoffmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220527024317.13476-8-graf@amazon.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox