From nobody Mon Feb 9 05:19:00 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1511395147396145.08385115097735; Wed, 22 Nov 2017 15:59:07 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 0466E2035BB2E; Wed, 22 Nov 2017 15:54:47 -0800 (PST) Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A8E2F2034C5F5 for ; Wed, 22 Nov 2017 15:54:45 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2EA685AFED; Wed, 22 Nov 2017 23:59:02 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-120-45.rdu2.redhat.com [10.10.120.45]) by smtp.corp.redhat.com (Postfix) with ESMTP id AA0D36178B; Wed, 22 Nov 2017 23:59:00 +0000 (UTC) X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=209.132.183.28; helo=mx1.redhat.com; envelope-from=lersek@redhat.com; receiver=edk2-devel@lists.01.org From: Laszlo Ersek To: edk2-devel-01 Date: Thu, 23 Nov 2017 00:58:48 +0100 Message-Id: <20171122235849.4177-5-lersek@redhat.com> In-Reply-To: <20171122235849.4177-1-lersek@redhat.com> References: <20171122235849.4177-1-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 22 Nov 2017 23:59:02 +0000 (UTC) Subject: [edk2] [PATCH 4/5] OvmfPkg/PlatformBootManagerLib: print EDKII_OS_LOADER_DETAIL to ConOut X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ruiyu Ni , Jordan Justen , Anthony Perard , Ard Biesheuvel MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Parse and print the EDKII_OS_LOADER_DETAIL debug codes from UefiBootManagerLib (when it acts as part of BdsDxe -- not as part of UiApp, for example). In effect this displays LoadImage() and StartImage() attempts and failures on the splash screen, visibly to end-users. While at it, print two other (earlier) console messages about boot option generation and boot option filtering / reordering. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Ruiyu Ni Cc: Anthony Perard Cc: Julien Grall Ref: https://bugzilla.redhat.com/show_bug.cgi?id=3D1515418 Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek --- Notes: We can port this later to ArmVirtPkg. For that, first we'll have to replace commit 59541d41633c ("ArmVirtPkg: remove status code support", 2017-07-05) with a port of commit a6d594c5fabd ("OvmfPkg: use StatusCode Router and Handler from MdeModulePkg", 2016-08-03). OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf | 4 + OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h | 15 + OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c | 8 + OvmfPkg/Library/PlatformBootManagerLib/StatusCodeHandler.c | 298 ++= ++++++++++++++++++ 4 files changed, 325 insertions(+) diff --git a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.= inf b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf index 27789b7377bc..36901fc39d95 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf +++ b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -21,24 +21,25 @@ [Defines] LIBRARY_CLASS =3D PlatformBootManagerLib|DXE_DRIVER =20 # # The following information is for reference only and not required by the = build tools. # # VALID_ARCHITECTURES =3D IA32 X64 IPF EBC # =20 [Sources] BdsPlatform.c PlatformData.c QemuKernel.c + StatusCodeHandler.c BdsPlatform.h =20 [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec SourceLevelDebugPkg/SourceLevelDebugPkg.dec OvmfPkg/OvmfPkg.dec =20 [LibraryClasses] BaseLib MemoryAllocationLib @@ -54,28 +55,31 @@ [LibraryClasses] QemuFwCfgLib QemuFwCfgS3Lib LoadLinuxLib QemuBootOrderLib UefiLib =20 [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile + gEfiMdeModulePkgTokenSpaceGuid.PcdDebugCodeOsLoaderDetail =20 [Pcd.IA32, Pcd.X64] gEfiMdePkgTokenSpaceGuid.PcdFSBClock =20 [Protocols] gEfiDecompressProtocolGuid gEfiPciRootBridgeIoProtocolGuid gEfiS3SaveStateProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL SOMETIMES_PRODU= CED gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODU= CED gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED + gEfiRscHandlerProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED =20 [Guids] gEfiXenInfoGuid gEfiEndOfDxeEventGroupGuid gRootBridgesConnectedEventGroupGuid + gEdkiiStatusCodeDataTypeOsLoaderDetailGuid diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h b/OvmfPkg= /Library/PlatformBootManagerLib/BdsPlatform.h index 97ffbb514825..493cfee85f54 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h @@ -183,13 +183,28 @@ PlatformInitializeConsole ( =20 /** Loads and boots UEFI Linux via the FwCfg interface. =20 @retval EFI_NOT_FOUND - The Linux kernel was not found =20 **/ EFI_STATUS TryRunningQemuKernel ( VOID ); =20 +/** + Register a status code handler for printing EDKII_OS_LOADER_DETAIL repor= ts to + the console. + + @retval EFI_SUCCESS The status code handler has been successfully + registered. + + @return Error codes propagated from boot services and from + EFI_RSC_HANDLER_PROTOCOL. +**/ +EFI_STATUS +RegisterStatusCodeHandler ( + VOID + ); + #endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_ diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg= /Library/PlatformBootManagerLib/BdsPlatform.c index 025252e72b39..429f2926d2af 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c @@ -1454,35 +1454,43 @@ Routine Description: BootLogoEnableLogo (); =20 // // Perform some platform specific connect sequence // PlatformBdsConnectSequence (); =20 // // Process QEMU's -kernel command line option // TryRunningQemuKernel (); =20 + AsciiPrint ( + "%a: auto-generating trailing boot options for bootable devices\n", + gEfiCallerBaseName + ); EfiBootManagerRefreshAllBootOption (); =20 // // Register UEFI Shell // PlatformRegisterFvBootOption ( PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE ); =20 + AsciiPrint ("%a: filtering and reordering boot options\n", + gEfiCallerBaseName); RemoveStaleFvFileOptions (); SetBootOrderFromQemu (); + + RegisterStatusCodeHandler (); } =20 /** This notification function is invoked when an instance of the EFI_DEVICE_PATH_PROTOCOL is produced. =20 @param Event The event that occurred @param Context For EFI compatibility. Not used. =20 **/ VOID EFIAPI diff --git a/OvmfPkg/Library/PlatformBootManagerLib/StatusCodeHandler.c b/O= vmfPkg/Library/PlatformBootManagerLib/StatusCodeHandler.c new file mode 100644 index 000000000000..cec4fb6ed6ce --- /dev/null +++ b/OvmfPkg/Library/PlatformBootManagerLib/StatusCodeHandler.c @@ -0,0 +1,298 @@ +/** @file + Register a status code handler for printing EDKII_OS_LOADER_DETAIL repor= ts to + the console. + + This feature enables users that are not accustomed to analyzing the OVMF + debug log to glean some information about UEFI boot option processing + (loading and starting). + + Copyright (C) 2017, Red Hat, Inc. + + This program and the accompanying materials are licensed and made availa= ble + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WI= THOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include + +#include "BdsPlatform.h" + + +/** + Handle status codes reported through ReportStatusCodeLib / + EFI_STATUS_CODE_PROTOCOL.ReportStatusCode(). Format matching status code= s to + the system console. + + The highest TPL at which this handler can be registered with + EFI_RSC_HANDLER_PROTOCOL.Register() is TPL_NOTIFY. That's because + AsciiPrint() uses EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL internally. + + The parameter list of this function precisely matches that of + EFI_STATUS_CODE_PROTOCOL.ReportStatusCode(). + + The return status of this function is ignored by the caller, but the fun= ction + still returns sensible codes: + + @retval EFI_SUCCESS The status code has been processed; eithe= r as + a no-op, due to filtering, or by formatti= ng it + to the system console. + + @retval EFI_INVALID_PARAMETER Unknown or malformed contents have been + detected in EFI_STATUS_CODE_DATA, or in t= he + EDKII_OS_LOADER_DETAIL payload within + EFI_STATUS_CODE_DATA. +**/ +STATIC +EFI_STATUS +EFIAPI +HandleStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data + ) +{ + EDKII_OS_LOADER_DETAIL *OsLoaderDetail; + UINT8 *VariableSizeData; + CHAR16 *Description; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN DevPathStringIsDynamic; + CHAR16 *DevPathString; + EFI_STATUS Status; + + // + // Ignore all status codes other than OsLoaderDetail. + // + if (Value !=3D PcdGet32 (PcdDebugCodeOsLoaderDetail)) { + return EFI_SUCCESS; + } + + // + // The status codes we are interested in are emitted by UefiBootManagerL= ib. + // UefiBootManagerLib is built into several drivers and applications, e.= g. + // BdsDxe and UiApp. Process (i.e., print to the console) only those sta= tus + // codes that come from BdsDxe; that is, from the driver module that this + // PlatformBootManagerLib instance is also built into. + // + if (!CompareGuid (CallerId, &gEfiCallerIdGuid)) { + return EFI_SUCCESS; + } + + // + // Sanity checks -- now that Value has been validated, we have expectati= ons + // to enforce. + // + if ((Data =3D=3D NULL) || + (Data->HeaderSize < sizeof *Data) || + (Data->Size < sizeof *OsLoaderDetail) || + (!CompareGuid (&Data->Type, + &gEdkiiStatusCodeDataTypeOsLoaderDetailGuid))) { + DEBUG (( + DEBUG_ERROR, + "%a: unknown or malformed data for status code 0x%x\n", + __FUNCTION__, + PcdGet32 (PcdDebugCodeOsLoaderDetail) + )); + return EFI_INVALID_PARAMETER; + } + + OsLoaderDetail =3D (EDKII_OS_LOADER_DETAIL *)( + (UINT8 *)Data + Data->HeaderSize + ); + + // + // More sanity checks. The additions on the RHS are carried out in UINTN= and + // cannot overflow. + // + if (Data->Size < (sizeof *OsLoaderDetail + + OsLoaderDetail->DescriptionSize + + OsLoaderDetail->DevicePathSize)) { + DEBUG ((DEBUG_ERROR, "%a: malformed EDKII_OS_LOADER_DETAIL\n", + __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + // + // Extract the known variable size fields from the payload. + // + VariableSizeData =3D (UINT8 *)(OsLoaderDetail + 1); + + Description =3D (CHAR16 *)VariableSizeData; + VariableSizeData +=3D OsLoaderDetail->DescriptionSize; + + DevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *)VariableSizeData; + VariableSizeData +=3D OsLoaderDetail->DevicePathSize; + + ASSERT (VariableSizeData - (UINT8 *)OsLoaderDetail <=3D Data->Size); + + // + // Prepare the extracted variable size fields for printing. + // + if (OsLoaderDetail->DescriptionSize =3D=3D 0) { + Description =3D L""; + } + + DevPathStringIsDynamic =3D FALSE; + if (OsLoaderDetail->DevicePathSize =3D=3D 0) { + DevPathString =3D L""; + } else { + DevPathString =3D ConvertDevicePathToText ( + DevicePath, + FALSE, // DisplayOnly + FALSE // AllowShortcuts + ); + if (DevPathString =3D=3D NULL) { + DevPathString =3D L""; + } else { + DevPathStringIsDynamic =3D TRUE; + } + } + + // + // Print the message to the console. + // + switch (OsLoaderDetail->Type) { + case EDKII_OS_LOADER_DETAIL_TYPE_LOAD: + case EDKII_OS_LOADER_DETAIL_TYPE_START: + AsciiPrint ( + "%a: %a Boot%04x \"%s\" from %s\n", + gEfiCallerBaseName, + (OsLoaderDetail->Type =3D=3D EDKII_OS_LOADER_DETAIL_TYPE_LOAD ? + "loading" : + "starting"), + OsLoaderDetail->BootOptionNumber, + Description, + DevPathString + ); + break; + + case EDKII_OS_LOADER_DETAIL_TYPE_LOAD_ERROR: + case EDKII_OS_LOADER_DETAIL_TYPE_START_ERROR: + AsciiPrint ( + "%a: failed to %a Boot%04x \"%s\" from %s: %r\n", + gEfiCallerBaseName, + (OsLoaderDetail->Type =3D=3D EDKII_OS_LOADER_DETAIL_TYPE_LOAD_ERROR ? + "load" : + "start"), + OsLoaderDetail->BootOptionNumber, + Description, + DevPathString, + OsLoaderDetail->Status + ); + break; + + default: + DEBUG ((DEBUG_ERROR, "%a: unknown EDKII_OS_LOADER_DETAIL.Type 0x%x\n", + __FUNCTION__, OsLoaderDetail->Type)); + Status =3D EFI_INVALID_PARAMETER; + goto ReleaseDevPathString; + } + + Status =3D EFI_SUCCESS; + +ReleaseDevPathString: + if (DevPathStringIsDynamic) { + FreePool (DevPathString); + } + return Status; +} + + +/** + Unregister HandleStatusCode() at ExitBootServices(). + + (See EFI_RSC_HANDLER_PROTOCOL in Volume 3 of the Platform Init spec.) + + @param[in] Event Event whose notification function is being invoked. + + @param[in] Context Pointer to EFI_RSC_HANDLER_PROTOCOL, originally look= ed up + when HandleStatusCode() was registered. +**/ +STATIC +VOID +EFIAPI +UnregisterAtExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_RSC_HANDLER_PROTOCOL *StatusCodeRouter; + + StatusCodeRouter =3D Context; + StatusCodeRouter->Unregister (HandleStatusCode); +} + + +/** + Register a status code handler for printing EDKII_OS_LOADER_DETAIL repor= ts to + the console. + + @retval EFI_SUCCESS The status code handler has been successfully + registered. + + @return Error codes propagated from boot services and from + EFI_RSC_HANDLER_PROTOCOL. +**/ +EFI_STATUS +RegisterStatusCodeHandler ( + VOID + ) +{ + EFI_STATUS Status; + EFI_RSC_HANDLER_PROTOCOL *StatusCodeRouter; + EFI_EVENT ExitBootEvent; + + Status =3D gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, + NULL /* Registration */, (VOID **)&StatusCodeRouter); + // + // This protocol is provided by the ReportStatusCodeRouterRuntimeDxe dri= ver + // that we build into the firmware image. Given that PlatformBootManager= Lib + // is used as part of BdsDxe, and BDS Entry occurs after all DXE drivers= have + // been dispatched, the EFI_RSC_HANDLER_PROTOCOL is available at this po= int. + // + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Register the handler callback. + // + Status =3D StatusCodeRouter->Register (HandleStatusCode, TPL_CALLBACK); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: failed to register status code handler: %r\n= ", + __FUNCTION__, Status)); + return Status; + } + + // + // Status code reporting and routing/handling extend into OS runtime. Si= nce + // we don't want our handler to survive the BDS phase, we have to unregi= ster + // the callback at ExitBootServices(). (See EFI_RSC_HANDLER_PROTOCOL in + // Volume 3 of the Platform Init spec.) + // + Status =3D gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, // Type + TPL_CALLBACK, // NotifyTpl + UnregisterAtExitBootServices, // NotifyFunction + StatusCodeRouter, // NotifyContext + &ExitBootEvent // Event + ); + if (EFI_ERROR (Status)) { + // + // We have to unregister the callback right now, and fail the function. + // + DEBUG ((DEBUG_ERROR, "%a: failed to create ExitBootServices() event: %= r\n", + __FUNCTION__, Status)); + StatusCodeRouter->Unregister (HandleStatusCode); + return Status; + } + + return EFI_SUCCESS; +} --=20 2.14.1.3.gb7cf6e02401b _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel