From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp-fw-80006.amazon.com (smtp-fw-80006.amazon.com [99.78.197.217]) by mx.groups.io with SMTP id smtpd.web11.3218.1653619433155395947 for ; Thu, 26 May 2022 19:43:53 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@amazon.com header.s=amazon201209 header.b=SFWmrYc8; spf=pass (domain: amazon.de, ip: 99.78.197.217, mailfrom: prvs=139655964=graf@amazon.de) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1653619434; x=1685155434; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=r4Mc1ucOI7ov58d9yNiWTjStUR5VeWUirR53E8oU6a0=; b=SFWmrYc84e4xwcty01D2vglQ/4TgHb1mcCT0J6WlZQ/1ZztsLWAb/+yl pes9azgIM1slTzVTIX0UUAUi5naJeDWBTVLfMcthA4M9QhOrx3jdS5vR4 oY2Vp5Cy9ezPMMGL/3CDPXYs3mr6SgFIyRtquAn+oJmUHs3WGqy7f2M5n I=; X-IronPort-AV: E=Sophos;i="5.91,254,1647302400"; d="scan'208";a="92377795" Received: from pdx4-co-svc-p1-lb2-vlan3.amazon.com (HELO email-inbound-relay-iad-1e-90d70b14.us-east-1.amazon.com) ([10.25.36.214]) by smtp-border-fw-80006.pdx80.corp.amazon.com with ESMTP; 27 May 2022 02:43:49 +0000 Received: from EX13MTAUWC002.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan3.iad.amazon.com [10.40.163.38]) by email-inbound-relay-iad-1e-90d70b14.us-east-1.amazon.com (Postfix) with ESMTPS id DEA00C0919; Fri, 27 May 2022 02:43:46 +0000 (UTC) Received: from EX13D20UWC001.ant.amazon.com (10.43.162.244) by EX13MTAUWC002.ant.amazon.com (10.43.162.240) with Microsoft SMTP Server (TLS) id 15.0.1497.36; Fri, 27 May 2022 02:43:46 +0000 Received: from u79c5a0a55de558.ant.amazon.com (10.43.161.125) by EX13D20UWC001.ant.amazon.com (10.43.162.244) with Microsoft SMTP Server (TLS) id 15.0.1497.36; Fri, 27 May 2022 02:43:44 +0000 From: "Alexander Graf" To: CC: Ard Biesheuvel , Leif Lindholm , Dandan Bi , Zhichao Gao , Liming Gao Subject: [PATCH 07/12] MdePkg: Add Dxe phase BaseDebugBootlog Date: Fri, 27 May 2022 04:43:12 +0200 Message-ID: <20220527024317.13476-8-graf@amazon.com> X-Mailer: git-send-email 2.28.0.394.ge197136389 In-Reply-To: <20220527024317.13476-1-graf@amazon.com> References: <20220527024317.13476-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.161.125] X-ClientProxiedBy: EX13D06UWC001.ant.amazon.com (10.43.162.91) To EX13D20UWC001.ant.amazon.com (10.43.162.244) Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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 --- .../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.
+# Copyright (c) 2012, Red Hat, Inc.
+# Copyright (c) 2022, Amazon Development Center Germany GmbH. All rights reserved.
+# +# 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.
+ Copyright (c) 2012, Red Hat, Inc.
+ Copyright (c) 2022, Amazon Development Center Germany GmbH.
+ 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