From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 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 298FC201B0430 for ; Wed, 20 Feb 2019 02:04:48 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9BE0A1F8C5; Wed, 20 Feb 2019 10:04:47 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-120-220.rdu2.redhat.com [10.10.120.220]) by smtp.corp.redhat.com (Postfix) with ESMTP id 23E5660140; Wed, 20 Feb 2019 10:04:44 +0000 (UTC) From: Laszlo Ersek To: edk2-devel@lists.01.org Cc: Anthony Perard , Jordan Justen References: <20190220081644.8238-1-lersek@redhat.com> <20190220081644.8238-3-lersek@redhat.com> Message-ID: Date: Wed, 20 Feb 2019 11:04:44 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <20190220081644.8238-3-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 20 Feb 2019 10:04:47 +0000 (UTC) Subject: Re: [PATCH v2 2/5] OvmfPkg: add library to track boot option loading/starting on the console X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Feb 2019 10:04:48 -0000 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit On 02/20/19 09:16, Laszlo Ersek wrote: > Introduce the Platform Boot Manager Print Status Code Library (for short, > PlatformBmPrintScLib) class for catching and printing the LoadImage() / > StartImage() preparations, and return statuses, that are reported by > UefiBootManagerLib. > > In the primary library instance, catch only such status codes that > UefiBootManagerLib reports from the same module that contains > PlatformBmPrintScLib. The intent is to establish a reporting-printing > channel within BdsDxe, between UefiBootManagerLib and > PlatformBmPrintScLib. Ignore status codes originating elsewhence, e.g. > from UiApp's copy of UefiBootManagerLib. > > Cc: Anthony Perard > Cc: Ard Biesheuvel > Cc: Jordan Justen > Cc: Julien Grall > Cc: Ray Ni > Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1515418 > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Laszlo Ersek > --- > > Notes: > v2: > > - Split the status code handling to a separate library, so that it's > easy to reuse in ArmVirtPkg. > > - Rework the logic based on > and > , and follow Ray's > advice in > : > > - The boot option details are fetched via BootCurrent. > > - For reporting LoadImage() and StartImage() preparations, replace the > originally proposed PcdDebugCodeOsLoaderDetail status code with the > existent (edk2-specific) PcdProgressCodeOsLoaderLoad and > PcdProgressCodeOsLoaderStart status codes. > > - For reporting LoadImage() and StartImage() return values, replace > the originally proposed PcdDebugCodeOsLoaderDetail status code with > the standard EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR and > EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED status codes. > > - For all four kinds of reports, replace the originally proposed "OS > Loader Detail" structure (and GUID) with the recently standardized > EFI_RETURN_STATUS_EXTENDED_DATA structure. > > OvmfPkg/OvmfPkg.dec | 5 + > OvmfPkg/OvmfPkgIa32.dsc | 1 + > OvmfPkg/OvmfPkgIa32X64.dsc | 1 + > OvmfPkg/OvmfPkgX64.dsc | 1 + > OvmfPkg/Include/Library/PlatformBmPrintScLib.h | 41 +++ > OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf | 66 +++++ > OvmfPkg/Library/PlatformBmPrintScLib/StatusCodeHandler.c | 310 ++++++++++++++++++++ > 7 files changed, 425 insertions(+) > > diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec > index 7666297cf8f1..e50c6179a249 100644 > --- a/OvmfPkg/OvmfPkg.dec > +++ b/OvmfPkg/OvmfPkg.dec > @@ -45,6 +45,11 @@ [LibraryClasses] > # access. > PciCapPciSegmentLib|Include/Library/PciCapPciSegmentLib.h > > + ## @libraryclass Register a status code handler for printing the Boot > + # Manager's LoadImage() and StartImage() preparations, and > + # return codes, to the UEFI console. > + PlatformBmPrintScLib|Include/Library/PlatformBmPrintScLib.h > + > ## @libraryclass Access QEMU's firmware configuration interface > # > QemuFwCfgLib|Include/Library/QemuFwCfgLib.h > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc > index f9216af479f4..5b885590b275 100644 > --- a/OvmfPkg/OvmfPkgIa32.dsc > +++ b/OvmfPkg/OvmfPkgIa32.dsc > @@ -348,6 +348,7 @@ [LibraryClasses.common.DXE_DRIVER] > UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf > DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf > PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > + PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf > QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf > CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf > !if $(SMM_REQUIRE) == TRUE > diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc > index 1e470de74434..bbf0853ee6b9 100644 > --- a/OvmfPkg/OvmfPkgIa32X64.dsc > +++ b/OvmfPkg/OvmfPkgIa32X64.dsc > @@ -353,6 +353,7 @@ [LibraryClasses.common.DXE_DRIVER] > UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf > DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf > PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > + PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf > QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf > CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf > !if $(SMM_REQUIRE) == TRUE > diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc > index e4929d8cf4a8..d81460f52041 100644 > --- a/OvmfPkg/OvmfPkgX64.dsc > +++ b/OvmfPkg/OvmfPkgX64.dsc > @@ -353,6 +353,7 @@ [LibraryClasses.common.DXE_DRIVER] > UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf > DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf > PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > + PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf > QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf > CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf > !if $(SMM_REQUIRE) == TRUE > diff --git a/OvmfPkg/Include/Library/PlatformBmPrintScLib.h b/OvmfPkg/Include/Library/PlatformBmPrintScLib.h > new file mode 100644 > index 000000000000..1777f9d7c947 > --- /dev/null > +++ b/OvmfPkg/Include/Library/PlatformBmPrintScLib.h > @@ -0,0 +1,41 @@ > +/** @file > + Register a status code handler for printing the Boot Manager's LoadImage() > + and StartImage() preparations, and return codes, to the UEFI console. > + > + This feature enables users that are not accustomed to analyzing the firmware > + log to glean some information about UEFI boot option processing (loading and > + starting). > + > + Copyright (C) 2019, Red Hat, Inc. > + > + This program and the accompanying materials are licensed and made available > + 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, WITHOUT > + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +**/ > + > +#ifndef __PLATFORM_BM_PRINT_SC_LIB__ > +#define __PLATFORM_BM_PRINT_SC_LIB__ > + > +#include > + > +/** > + Register a status code handler for printing the Boot Manager's LoadImage() > + and StartImage() preparations, and return codes, to the UEFI 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 > +EFIAPI > +PlatformBmPrintScRegisterHandler ( > + VOID > + ); > + > +#endif // __PLATFORM_BM_PRINT_SC_LIB__ > diff --git a/OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf b/OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf > new file mode 100644 > index 000000000000..8f02e0b48236 > --- /dev/null > +++ b/OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf > @@ -0,0 +1,66 @@ > +## @file > +# Register a status code handler for printing the Boot Manager's LoadImage() > +# and StartImage() preparations, and return codes, to the UEFI console. > +# > +# This feature enables users that are not accustomed to analyzing the firmware > +# log to glean some information about UEFI boot option processing (loading and > +# starting). > +# > +# This library instance filters out (ignores) status codes that are not > +# reported by the containing firmware module. The intent is to link this > +# library instance into BdsDxe via PlatformBootManagerLib (which BdsDxe depends > +# upon), then catch only those status codes that BdsDxe reports (which happens > +# via UefiBootManagerLib). Status codes reported by other modules (such as > +# UiApp), via UefiBootManagerLib or otherwise, are meant to be ignored. > +# > +# Copyright (C) 2019, Red Hat, Inc. > +# > +# This program and the accompanying materials are licensed and made available > +# 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, WITHOUT > +# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +## > + > +[Defines] > + INF_VERSION = 1.27 > + BASE_NAME = PlatformBmPrintScLib > + FILE_GUID = 3417c705-903e-41a7-9485-3fafebf60917 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = PlatformBmPrintScLib|DXE_DRIVER > + > +[Sources] > + StatusCodeHandler.c > + > +[Packages] > + MdeModulePkg/MdeModulePkg.dec > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + BaseMemoryLib > + DebugLib > + DevicePathLib > + MemoryAllocationLib > + PcdLib > + PrintLib > + UefiBootManagerLib > + UefiBootServicesTableLib > + UefiLib > + UefiRuntimeServicesTableLib > + > +[Pcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad ## CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderStart ## CONSUMES > + > +[Protocols] > + gEfiRscHandlerProtocolGuid ## CONSUMES > + > +[Guids] > + gEfiGlobalVariableGuid ## CONSUMES > + gEfiStatusCodeSpecificDataGuid ## CONSUMES > + > +[Depex.common.DXE_DRIVER] > + gEfiRscHandlerProtocolGuid AND gEfiVariableArchProtocolGuid > diff --git a/OvmfPkg/Library/PlatformBmPrintScLib/StatusCodeHandler.c b/OvmfPkg/Library/PlatformBmPrintScLib/StatusCodeHandler.c > new file mode 100644 > index 000000000000..9806d3c7411e > --- /dev/null > +++ b/OvmfPkg/Library/PlatformBmPrintScLib/StatusCodeHandler.c > @@ -0,0 +1,310 @@ > +/** @file > + Register a status code handler for printing the Boot Manager's LoadImage() > + and StartImage() preparations, and return codes, to the UEFI console. > + > + This feature enables users that are not accustomed to analyzing the firmware > + log to glean some information about UEFI boot option processing (loading and > + starting). > + > + This library instance filters out (ignores) status codes that are not > + reported by the containing firmware module. The intent is to link this > + library instance into BdsDxe via PlatformBootManagerLib (which BdsDxe depends > + upon), then catch only those status codes that BdsDxe reports (which happens > + via UefiBootManagerLib). Status codes reported by other modules (such as > + UiApp), via UefiBootManagerLib or otherwise, are meant to be ignored. > + > + Copyright (C) 2019, Red Hat, Inc. > + > + This program and the accompanying materials are licensed and made available > + 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, WITHOUT > + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#include > +#include > + > +#include > + > + > +// > +// Convenience variables for the status codes that are relevant for LoadImage() > +// and StartImage() preparations and return codes. > +// > +STATIC EFI_STATUS_CODE_VALUE mLoadPrep; > +STATIC EFI_STATUS_CODE_VALUE mLoadFail; > +STATIC EFI_STATUS_CODE_VALUE mStartPrep; > +STATIC EFI_STATUS_CODE_VALUE mStartFail; > + > + > +/** > + Handle status codes reported through ReportStatusCodeLib / > + EFI_STATUS_CODE_PROTOCOL.ReportStatusCode(). Format matching status codes 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 Print() > + uses EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL internally. Sorry, this is a stale comment from v1; I should have updated it. The callback now uses the variable services, and those are restricted to <= TPL_CALLBACK. The code is correct (it does use TPL_CALLBACK), so if there's no other change necessary, I could update the comment on push too. I can also post v3 just for this, if that's preferred. Thanks Laszlo > + > + 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 function > + still returns sensible codes: > + > + @retval EFI_SUCCESS The status code has been processed; either > + as a no-op, due to filtering, or by > + formatting it to the system console. > + > + @retval EFI_INVALID_PARAMETER Unknown or malformed contents have been > + detected in Data. > + > + @retval EFI_INCOMPATIBLE_VERSION Unexpected UEFI variable behavior has been > + encountered. > + > + @return Error codes propagated from underlying > + services. > +**/ > +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 > + ) > +{ > + UINTN VariableSize; > + UINT16 BootCurrent; > + EFI_STATUS Status; > + CHAR16 BootOptionName[ARRAY_SIZE (L"Boot####")]; > + EFI_BOOT_MANAGER_LOAD_OPTION BmBootOption; > + BOOLEAN DevPathStringIsDynamic; > + CHAR16 *DevPathString; > + > + // > + // Ignore all status codes that are irrelevant for LoadImage() and > + // StartImage() preparations and return codes. > + // > + if (Value != mLoadPrep && Value != mLoadFail && > + Value != mStartPrep && Value != mStartFail) { > + return EFI_SUCCESS; > + } > + // > + // Ignore status codes that are not reported by the same containing module. > + // > + if (!CompareGuid (CallerId, &gEfiCallerIdGuid)) { > + return EFI_SUCCESS; > + } > + > + // > + // Sanity-check Data in case of failure reports. > + // > + if ((Value == mLoadFail || Value == mStartFail) && > + (Data == NULL || > + Data->HeaderSize != sizeof *Data || > + Data->Size != sizeof (EFI_RETURN_STATUS_EXTENDED_DATA) - sizeof *Data || > + !CompareGuid (&Data->Type, &gEfiStatusCodeSpecificDataGuid))) { > + DEBUG ((DEBUG_ERROR, "%a:%a: malformed Data\n", gEfiCallerBaseName, > + __FUNCTION__)); > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Get the number of the Boot#### option that the status code applies to. > + // > + VariableSize = sizeof BootCurrent; > + Status = gRT->GetVariable (EFI_BOOT_CURRENT_VARIABLE_NAME, > + &gEfiGlobalVariableGuid, NULL /* Attributes */, > + &VariableSize, &BootCurrent); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:%a: failed to get %g:\"%s\": %r\n", > + gEfiCallerBaseName, __FUNCTION__, &gEfiGlobalVariableGuid, > + EFI_BOOT_CURRENT_VARIABLE_NAME, Status)); > + return Status; > + } > + if (VariableSize != sizeof BootCurrent) { > + DEBUG ((DEBUG_ERROR, "%a:%a: got %Lu bytes for %g:\"%s\", expected %Lu\n", > + gEfiCallerBaseName, __FUNCTION__, (UINT64)VariableSize, > + &gEfiGlobalVariableGuid, EFI_BOOT_CURRENT_VARIABLE_NAME, > + (UINT64)sizeof BootCurrent)); > + return EFI_INCOMPATIBLE_VERSION; > + } > + > + // > + // Get the Boot#### option that the status code applies to. > + // > + UnicodeSPrint (BootOptionName, sizeof BootOptionName, L"Boot%04x", > + BootCurrent); > + Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BmBootOption); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, > + "%a:%a: EfiBootManagerVariableToLoadOption(\"%s\"): %r\n", > + gEfiCallerBaseName, __FUNCTION__, BootOptionName, Status)); > + return Status; > + } > + > + // > + // Format the device path. > + // > + DevPathStringIsDynamic = TRUE; > + DevPathString = ConvertDevicePathToText ( > + BmBootOption.FilePath, > + FALSE, // DisplayOnly > + FALSE // AllowShortcuts > + ); > + if (DevPathString == NULL) { > + DevPathStringIsDynamic = FALSE; > + DevPathString = L""; > + } > + > + // > + // Print the message to the console. > + // > + if (Value == mLoadPrep || Value == mStartPrep) { > + Print ( > + L"%a: %a %s \"%s\" from %s\n", > + gEfiCallerBaseName, > + Value == mLoadPrep ? "loading" : "starting", > + BootOptionName, > + BmBootOption.Description, > + DevPathString > + ); > + } else { > + Print ( > + L"%a: failed to %a %s \"%s\" from %s: %r\n", > + gEfiCallerBaseName, > + Value == mLoadFail ? "load" : "start", > + BootOptionName, > + BmBootOption.Description, > + DevPathString, > + ((EFI_RETURN_STATUS_EXTENDED_DATA *)Data)->ReturnStatus > + ); > + } > + > + // > + // Done. > + // > + if (DevPathStringIsDynamic) { > + FreePool (DevPathString); > + } > + EfiBootManagerFreeLoadOption (&BmBootOption); > + return EFI_SUCCESS; > +} > + > + > +/** > + 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 looked up > + when HandleStatusCode() was registered. > +**/ > +STATIC > +VOID > +EFIAPI > +UnregisterAtExitBootServices ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + EFI_RSC_HANDLER_PROTOCOL *StatusCodeRouter; > + > + StatusCodeRouter = Context; > + StatusCodeRouter->Unregister (HandleStatusCode); > +} > + > + > +/** > + Register a status code handler for printing the Boot Manager's LoadImage() > + and StartImage() preparations, and return codes, to the UEFI 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 > +EFIAPI > +PlatformBmPrintScRegisterHandler ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + EFI_RSC_HANDLER_PROTOCOL *StatusCodeRouter; > + EFI_EVENT ExitBootEvent; > + > + Status = gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, > + NULL /* Registration */, (VOID **)&StatusCodeRouter); > + ASSERT_EFI_ERROR (Status); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Set the EFI_STATUS_CODE_VALUE convenience variables. > + // > + mLoadPrep = PcdGet32 (PcdProgressCodeOsLoaderLoad); > + mLoadFail = (EFI_SOFTWARE_DXE_BS_DRIVER | > + EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR); > + mStartPrep = PcdGet32 (PcdProgressCodeOsLoaderStart); > + mStartFail = (EFI_SOFTWARE_DXE_BS_DRIVER | > + EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED); > + > + // > + // Register the handler callback. > + // > + Status = StatusCodeRouter->Register (HandleStatusCode, TPL_CALLBACK); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:%a: failed to register status code handler: %r\n", > + gEfiCallerBaseName, __FUNCTION__, Status)); > + return Status; > + } > + > + // > + // Status code reporting and routing/handling extend into OS runtime. Since > + // we don't want our handler to survive the BDS phase, we have to unregister > + // the callback at ExitBootServices(). (See EFI_RSC_HANDLER_PROTOCOL in > + // Volume 3 of the Platform Init spec.) > + // > + Status = 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:%a: failed to create ExitBootServices() event: " > + "%r\n", gEfiCallerBaseName, __FUNCTION__, Status)); > + StatusCodeRouter->Unregister (HandleStatusCode); > + return Status; > + } > + > + return EFI_SUCCESS; > +} >