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
next prev 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