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 D67CC2034C5D9 for ; Wed, 22 Nov 2017 15:54:43 -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 56EDA356EA; Wed, 22 Nov 2017 23:59:00 +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 A2FD44A1; Wed, 22 Nov 2017 23:58:58 +0000 (UTC) From: Laszlo Ersek To: edk2-devel-01 Cc: Ard Biesheuvel , Jordan Justen , Ruiyu Ni , Eric Dong , Star Zeng Date: Thu, 23 Nov 2017 00:58:47 +0100 Message-Id: <20171122235849.4177-4-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.30]); Wed, 22 Nov 2017 23:59:00 +0000 (UTC) Subject: [PATCH 3/5] MdeModulePkg/UefiBootManagerLib: report EDKII_OS_LOADER_DETAIL status code 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: , X-List-Received-Date: Wed, 22 Nov 2017 23:54:44 -0000 The EfiBootManagerBoot() function reports progress codes about LoadImage() preparation and failure, and StartImage() preparation and failure. These codes are flat (scalar) constants. Extend this by "broadcasting" the Boot#### option number, description, device path, and -- on load / start failure -- the error result at the same locations, through EFI_DEBUG_CODE reporting. Use the PcdDebugCodeOsLoaderDetail status code value and the EDKII_OS_LOADER_DETAIL status code structure introduced earlier in this series. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Ruiyu Ni Cc: Eric Dong Cc: Star Zeng Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1515418 Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek --- MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf | 2 + MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h | 84 ++++++++++ MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c | 51 +++++- MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c | 166 ++++++++++++++++++++ 4 files changed, 301 insertions(+), 2 deletions(-) diff --git a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf index ad4901db5713..633906fc6ca4 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf +++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf @@ -79,24 +79,25 @@ [Guids] ## SOMETIMES_PRODUCES ## Variable:L"BootCurrent" (The boot option of current boot) ## SOMETIMES_CONSUMES ## Variable:L"BootXX" (Boot option variable) ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array) ## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" (The driver order list) ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device) ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device) ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device) gEfiGlobalVariableGuid gPerformanceProtocolGuid ## SOMETIMES_CONSUMES ## Variable:L"PerfDataMemAddr" (The ACPI address of performance data) gEdkiiStatusCodeDataTypeVariableGuid ## SOMETIMES_CONSUMES ## GUID + gEdkiiStatusCodeDataTypeOsLoaderDetailGuid ## SOMETIMES_CONSUMES ## GUID gEfiDiskInfoAhciInterfaceGuid ## SOMETIMES_CONSUMES ## GUID gEfiDiskInfoIdeInterfaceGuid ## SOMETIMES_CONSUMES ## GUID gEfiDiskInfoScsiInterfaceGuid ## SOMETIMES_CONSUMES ## GUID gEfiDiskInfoSdMmcInterfaceGuid ## SOMETIMES_CONSUMES ## GUID [Protocols] gEfiPciRootBridgeIoProtocolGuid ## CONSUMES gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES gEfiLoadFileProtocolGuid ## SOMETIMES_CONSUMES gEfiSimpleTextOutProtocolGuid ## SOMETIMES_CONSUMES gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMES gEfiLoadedImageProtocolGuid ## CONSUMES @@ -112,16 +113,17 @@ [Protocols] gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES gEfiNvmExpressPassThruProtocolGuid ## SOMETIMES_CONSUMES gEfiDiskInfoProtocolGuid ## SOMETIMES_CONSUMES gEfiDriverHealthProtocolGuid ## SOMETIMES_CONSUMES gEfiFormBrowser2ProtocolGuid ## SOMETIMES_CONSUMES gEfiRamDiskProtocolGuid ## SOMETIMES_CONSUMES gEfiDeferredImageLoadProtocolGuid ## SOMETIMES_CONSUMES [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderStart ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdDebugCodeOsLoaderDetail ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdDriverHealthConfigureForm ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMaxRepairCount ## CONSUMES diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h index 0224bd34a9ed..ddcb0347aef6 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h +++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h @@ -44,24 +44,25 @@ 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 #include #include #include #include #include #include #include #include #include @@ -298,24 +299,107 @@ BmStopHotkeyService ( @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. **/ EFI_STATUS BmSetVariableAndReportStatusCodeOnError ( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data ); +/** + Dynamically allocate and initialize an EDKII_OS_LOADER_DETAIL status code + payload. + + @param[in] BootOption Capture the OptionNumber, FilePath and + Description fields of BootOption in the + EDKII_OS_LOADER_DETAIL payload. + + @param[out] OsLoaderDetail On successful return, set to the + EDKII_OS_LOADER_DETAIL object that has been + allocated and initialized. On failure, not + modified. + + @param[out] OsLoaderDetailSize On successful return, set to the size of the + EDKII_OS_LOADER_DETAIL object that has been + allocated and initialized. On failure, not + modified. + + @retval EFI_UNSUPPORTED EFI_DEBUG_CODE reporting is disabled in the + platform. + + @retval EFI_INVALID_PARAMETER BootOption->OptionNumber is not in + 0x0000..0xFFFF, inclusive. + + @retval EFI_BAD_BUFFER_SIZE BootOption->FilePath and/or + BootOption->Description would exceed the + UINT16 size limits presented by + EDKII_OS_LOADER_DETAIL or + EFI_STATUS_CODE_DATA. + + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + + @retval EFI_SUCCESS The EDKII_OS_LOADER_DETAIL object has been + allocated and initialized. The caller is + responsible for freeing the object with + FreePool(). +**/ +EFI_STATUS +BmCreateOsLoaderDetail ( + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption, + OUT EDKII_OS_LOADER_DETAIL **OsLoaderDetail, + OUT UINTN *OsLoaderDetailSize + ); + +/** + Report an EFI_DEBUG_CODE status code with EDKII_OS_LOADER_DETAIL as payload + (i.e., extended data). + + @param[in,out] OsLoaderDetail The EDKII_OS_LOADER_DETAIL payload previously + created with BmCreateOsLoaderDetail(), and + modified zero or more times by + BmReportOsLoaderDetail(). If OsLoaderDetail is + NULL, the function does nothing. Otherwise, + the Type and Status fields are overwritten in + OsLoaderDetail, and a status code is reported. + + @param[in] OsLoaderDetailSize The size returned by BmCreateOsLoaderDetail(). + If OsLoaderDetail is NULL, OsLoaderDetailSize + may be zero. + + @param[in] DetailType OsLoaderDetail->Type is set to DetailType + before reporting the status code. The caller + is responsible for passing an + EDKII_OS_LOADER_DETAIL_TYPE_* value. + + @param[in] DetailStatus OsLoaderDetail->Status is set to DetailStatus + before reporting the status code. + + @retval EFI_UNSUPPORTED EFI_DEBUG_CODE reporting is disabled in the + platform. + + @retval EFI_ABORTED OsLoaderDetail is NULL. + + @return Values propagated from REPORT_STATUS_CODE_EX(). +**/ +EFI_STATUS +BmReportOsLoaderDetail ( + IN OUT EDKII_OS_LOADER_DETAIL *OsLoaderDetail OPTIONAL, + IN UINTN OsLoaderDetailSize, + IN UINT32 DetailType, + IN EFI_STATUS DetailStatus + ); + /** Function compares a device path data structure to that of all the nodes of a second device path instance. @param Multi A pointer to a multi-instance device path data structure. @param Single A pointer to a single-instance device path data structure. @retval TRUE If the Single device path is contained within Multi device path. @retval FALSE The Single device path is not match within Multi device path. diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c index d6844823aa55..049afbf7d1f9 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c @@ -1665,34 +1665,39 @@ EfiBootManagerBoot ( EFI_STATUS Status; EFI_HANDLE ImageHandle; EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; UINT16 Uint16; UINTN OptionNumber; UINTN OriginalOptionNumber; EFI_DEVICE_PATH_PROTOCOL *FilePath; EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath; VOID *FileBuffer; UINTN FileSize; EFI_BOOT_LOGO_PROTOCOL *BootLogo; EFI_EVENT LegacyBootEvent; + EDKII_OS_LOADER_DETAIL *OsLoaderDetail; + UINTN OsLoaderDetailSize; if (BootOption == NULL) { return; } if (BootOption->FilePath == NULL || BootOption->OptionType != LoadOptionTypeBoot) { BootOption->Status = EFI_INVALID_PARAMETER; return; } + OsLoaderDetail = NULL; + OsLoaderDetailSize = 0; + // // 1. Create Boot#### for a temporary boot if there is no match Boot#### (i.e. a boot by selected a EFI Shell using "Boot From File") // OptionNumber = BmFindBootOptionInVariable (BootOption); if (OptionNumber == LoadOptionNumberUnassigned) { Status = BmGetFreeOptionNumber (LoadOptionTypeBoot, &Uint16); if (!EFI_ERROR (Status)) { // // Save the BootOption->OptionNumber to restore later // OptionNumber = Uint16; OriginalOptionNumber = BootOption->OptionNumber; @@ -1751,68 +1756,93 @@ EfiBootManagerBoot ( // // 6. Load EFI boot option to ImageHandle // DEBUG_CODE_BEGIN (); if (BootOption->Description == NULL) { DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting from unknown device path\n")); } else { DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting %s\n", BootOption->Description)); } DEBUG_CODE_END (); + // + // Try to create the status code payload structure for detailed debug + // reporting. + // + Status = BmCreateOsLoaderDetail (BootOption, &OsLoaderDetail, + &OsLoaderDetailSize); + if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) { + DEBUG ((DEBUG_WARN | DEBUG_LOAD, "[Bds]BmCreateOsLoaderDetail(): %r\n", + Status)); + } + ImageHandle = NULL; RamDiskDevicePath = NULL; if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) { Status = EFI_NOT_FOUND; FilePath = NULL; EfiBootManagerConnectDevicePath (BootOption->FilePath, NULL); FileBuffer = BmGetNextLoadOptionBuffer (LoadOptionTypeBoot, BootOption->FilePath, &FilePath, &FileSize); if (FileBuffer != NULL) { RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad)); + BmReportOsLoaderDetail ( + OsLoaderDetail, + OsLoaderDetailSize, + EDKII_OS_LOADER_DETAIL_TYPE_LOAD, + 0 // DetailStatus -- unused here + ); + Status = gBS->LoadImage ( TRUE, gImageHandle, FilePath, FileBuffer, FileSize, &ImageHandle ); } if (FileBuffer != NULL) { FreePool (FileBuffer); } if (FilePath != NULL) { FreePool (FilePath); } if (EFI_ERROR (Status)) { // // Report Status Code to indicate that the failure to load boot option // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR) ); + BmReportOsLoaderDetail ( + OsLoaderDetail, + OsLoaderDetailSize, + EDKII_OS_LOADER_DETAIL_TYPE_LOAD_ERROR, + Status + ); + BootOption->Status = Status; // // Destroy the RAM disk // if (RamDiskDevicePath != NULL) { BmDestroyRamDisk (RamDiskDevicePath); FreePool (RamDiskDevicePath); } - return; + goto FreeOsLoaderDetail; } } // // Check to see if we should legacy BOOT. If yes then do the legacy boot // Write boot to OS performance data for Legacy boot // if ((DevicePathType (BootOption->FilePath) == BBS_DEVICE_PATH) && (DevicePathSubType (BootOption->FilePath) == BBS_BBS_DP)) { if (mBmLegacyBoot != NULL) { // // Write boot to OS performance data for legacy boot. // @@ -1826,25 +1856,25 @@ EfiBootManagerBoot ( NULL, &LegacyBootEvent ); ASSERT_EFI_ERROR (Status); ); mBmLegacyBoot (BootOption); } else { BootOption->Status = EFI_UNSUPPORTED; } PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber); - return; + goto FreeOsLoaderDetail; } // // Provide the image with its load options // Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo); ASSERT_EFI_ERROR (Status); if (!BmIsAutoCreateBootOption (BootOption)) { ImageInfo->LoadOptionsSize = BootOption->OptionalDataSize; ImageInfo->LoadOptions = BootOption->OptionalData; } @@ -1858,36 +1888,48 @@ EfiBootManagerBoot ( // Before calling the image, enable the Watchdog Timer for 5 minutes period // gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL); // // Write boot to OS performance data for UEFI boot // PERF_CODE ( BmWriteBootToOsPerformanceData (NULL, NULL); ); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderStart)); + BmReportOsLoaderDetail ( + OsLoaderDetail, + OsLoaderDetailSize, + EDKII_OS_LOADER_DETAIL_TYPE_START, + 0 // DetailStatus -- unused here + ); Status = gBS->StartImage (ImageHandle, &BootOption->ExitDataSize, &BootOption->ExitData); DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status)); BootOption->Status = Status; if (EFI_ERROR (Status)) { // // Report Status Code to indicate that boot failure // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED) ); + BmReportOsLoaderDetail ( + OsLoaderDetail, + OsLoaderDetailSize, + EDKII_OS_LOADER_DETAIL_TYPE_START_ERROR, + Status + ); } PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber); // // Destroy the RAM disk // if (RamDiskDevicePath != NULL) { BmDestroyRamDisk (RamDiskDevicePath); FreePool (RamDiskDevicePath); } // @@ -1912,24 +1954,29 @@ EfiBootManagerBoot ( L"BootCurrent", &gEfiGlobalVariableGuid, 0, 0, NULL ); // // Deleting variable with current variable implementation shouldn't fail. // When BootXXXX (e.g.: BootManagerMenu) boots BootYYYY, exiting BootYYYY causes BootCurrent deleted, // exiting BootXXXX causes deleting BootCurrent returns EFI_NOT_FOUND. // ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND); + +FreeOsLoaderDetail: + if (OsLoaderDetail != NULL) { + FreePool (OsLoaderDetail); + } } /** Check whether there is a instance in BlockIoDevicePath, which contain multi device path instances, has the same partition node with HardDriveDevicePath device path @param BlockIoDevicePath Multi device path instances which need to check @param HardDriveDevicePath A device path which starts with a hard drive media device path. @retval TRUE There is a matched device path instance. @retval FALSE There is no matched device path instance. diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c b/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c index 81d365940043..29da896854b8 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c @@ -369,24 +369,190 @@ BmSetVariableAndReportStatusCodeOnError ( SetVariableStatus, sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize ); FreePool (SetVariableStatus); } } return Status; } +/** + Dynamically allocate and initialize an EDKII_OS_LOADER_DETAIL status code + payload. + + @param[in] BootOption Capture the OptionNumber, FilePath and + Description fields of BootOption in the + EDKII_OS_LOADER_DETAIL payload. + + @param[out] OsLoaderDetail On successful return, set to the + EDKII_OS_LOADER_DETAIL object that has been + allocated and initialized. On failure, not + modified. + + @param[out] OsLoaderDetailSize On successful return, set to the size of the + EDKII_OS_LOADER_DETAIL object that has been + allocated and initialized. On failure, not + modified. + + @retval EFI_UNSUPPORTED EFI_DEBUG_CODE reporting is disabled in the + platform. + + @retval EFI_INVALID_PARAMETER BootOption->OptionNumber is not in + 0x0000..0xFFFF, inclusive. + + @retval EFI_BAD_BUFFER_SIZE BootOption->FilePath and/or + BootOption->Description would exceed the + UINT16 size limits presented by + EDKII_OS_LOADER_DETAIL or + EFI_STATUS_CODE_DATA. + + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + + @retval EFI_SUCCESS The EDKII_OS_LOADER_DETAIL object has been + allocated and initialized. The caller is + responsible for freeing the object with + FreePool(). +**/ +EFI_STATUS +BmCreateOsLoaderDetail ( + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption, + OUT EDKII_OS_LOADER_DETAIL **OsLoaderDetail, + OUT UINTN *OsLoaderDetailSize + ) +{ + UINTN DescriptionSize; + UINTN DevicePathSize; + UINTN PayloadSize; + EDKII_OS_LOADER_DETAIL *Payload; + UINT8 *VariableSizeData; + + if (!ReportDebugCodeEnabled ()) { + return EFI_UNSUPPORTED; + } + + if (BootOption->OptionNumber >= LoadOptionNumberMax) { + return EFI_INVALID_PARAMETER; + } + + DescriptionSize = (BootOption->Description == NULL) ? + 0 : + StrSize (BootOption->Description); + DevicePathSize = GetDevicePathSize (BootOption->FilePath); + PayloadSize = sizeof *Payload + DescriptionSize + DevicePathSize; + + if (DescriptionSize > MAX_UINT16 || + DevicePathSize > MAX_UINT16 || + PayloadSize > MAX_UINT16) { + return EFI_BAD_BUFFER_SIZE; + } + + Payload = AllocateZeroPool (PayloadSize); + if (Payload == NULL) { + return EFI_OUT_OF_RESOURCES; + } + VariableSizeData = (UINT8 *)(Payload + 1); + + // + // Populate the variable size fields at the end of the payload. + // + CopyMem (VariableSizeData, BootOption->Description, DescriptionSize); + VariableSizeData += DescriptionSize; + + CopyMem (VariableSizeData, BootOption->FilePath, DevicePathSize); + VariableSizeData += DevicePathSize; + + ASSERT (VariableSizeData - (UINT8 *)Payload == PayloadSize); + + // + // Populate the fixed fields in the payload. Any members not listed below + // remain zero-filled at this point. + // + Payload->BootOptionNumber = (UINT16)BootOption->OptionNumber; + Payload->DescriptionSize = (UINT16)DescriptionSize; + Payload->DevicePathSize = (UINT16)DevicePathSize; + + *OsLoaderDetail = Payload; + *OsLoaderDetailSize = PayloadSize; + return EFI_SUCCESS; +} + + +/** + Report an EFI_DEBUG_CODE status code with EDKII_OS_LOADER_DETAIL as payload + (i.e., extended data). + + @param[in,out] OsLoaderDetail The EDKII_OS_LOADER_DETAIL payload previously + created with BmCreateOsLoaderDetail(), and + modified zero or more times by + BmReportOsLoaderDetail(). If OsLoaderDetail is + NULL, the function does nothing. Otherwise, + the Type and Status fields are overwritten in + OsLoaderDetail, and a status code is reported. + + @param[in] OsLoaderDetailSize The size returned by BmCreateOsLoaderDetail(). + If OsLoaderDetail is NULL, OsLoaderDetailSize + may be zero. + + @param[in] DetailType OsLoaderDetail->Type is set to DetailType + before reporting the status code. The caller + is responsible for passing an + EDKII_OS_LOADER_DETAIL_TYPE_* value. + + @param[in] DetailStatus OsLoaderDetail->Status is set to DetailStatus + before reporting the status code. + + @retval EFI_UNSUPPORTED EFI_DEBUG_CODE reporting is disabled in the + platform. + + @retval EFI_ABORTED OsLoaderDetail is NULL. + + @return Values propagated from REPORT_STATUS_CODE_EX(). +**/ +EFI_STATUS +BmReportOsLoaderDetail ( + IN OUT EDKII_OS_LOADER_DETAIL *OsLoaderDetail OPTIONAL, + IN UINTN OsLoaderDetailSize, + IN UINT32 DetailType, + IN EFI_STATUS DetailStatus + ) +{ + EFI_STATUS Status; + + if (!ReportDebugCodeEnabled ()) { + return EFI_UNSUPPORTED; + } + + if (OsLoaderDetail == NULL) { + return EFI_ABORTED; + } + + OsLoaderDetail->Type = DetailType; + OsLoaderDetail->Status = DetailStatus; + + Status = REPORT_STATUS_CODE_EX ( + EFI_DEBUG_CODE, // Type + PcdGet32 (PcdDebugCodeOsLoaderDetail), // Value + 0, // Instance + &gEfiCallerIdGuid, // CallerId + &gEdkiiStatusCodeDataTypeOsLoaderDetailGuid, // ExtendedDataGuid + OsLoaderDetail, // ExtendedData + OsLoaderDetailSize // ExtendedDataSize + ); + return Status; +} + + /** Print the device path info. @param DevicePath The device path need to print. **/ VOID BmPrintDp ( EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { CHAR16 *Str; -- 2.14.1.3.gb7cf6e02401b