Laszlo,
When booting a boot option, UefiBootManagerBoot() sets a Boot#### variable
and saves #### to BootCurrent variable.
So all the details (except the EDKII_OS_LOADER_DETAIL.Status) can be retrieved
from reading Boot#### variable.

4 more comments below.


Thanks/Ray

> -----Original Message-----
> From: Laszlo Ersek [mailto:ler...@redhat.com]
> Sent: Thursday, November 23, 2017 7:59 AM
> To: edk2-devel-01 <edk2-devel@lists.01.org>
> Cc: Ard Biesheuvel <ard.biesheu...@linaro.org>; Justen, Jordan L
> <jordan.l.jus...@intel.com>; Ni, Ruiyu <ruiyu...@intel.com>; Dong, Eric
> <eric.d...@intel.com>; Zeng, Star <star.z...@intel.com>
> Subject: [PATCH 3/5] MdeModulePkg/UefiBootManagerLib: report
> EDKII_OS_LOADER_DETAIL status code
> 
> 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 <ard.biesheu...@linaro.org>
> Cc: Jordan Justen <jordan.l.jus...@intel.com>
> Cc: Ruiyu Ni <ruiyu...@intel.com>
> Cc: Eric Dong <eric.d...@intel.com>
> Cc: Star Zeng <star.z...@intel.com>
> Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1515418
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Laszlo Ersek <ler...@redhat.com>
> ---
>  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.PcdResetOnMemoryTypeInformationC
> hange      ## 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 <Protocol/BootLogo.h>
>  #include <Protocol/DriverHealth.h>
>  #include <Protocol/FormBrowser2.h>
>  #include <Protocol/VariableLock.h>
>  #include <Protocol/RamDisk.h>
>  #include <Protocol/DeferredImageLoad.h>
> 
>  #include <Guid/MemoryTypeInformation.h>  #include <Guid/FileInfo.h>
> #include <Guid/GlobalVariable.h>  #include <Guid/Performance.h>  #include
> <Guid/StatusCodeDataTypeVariable.h>
> +#include <Guid/StatusCodeDataTypeOsLoaderDetail.h>
> 
>  #include <Library/PrintLib.h>
>  #include <Library/DebugLib.h>
>  #include <Library/BaseMemoryLib.h>
>  #include <Library/UefiBootServicesTableLib.h>
>  #include <Library/UefiRuntimeServicesTableLib.h>
>  #include <Library/UefiLib.h>
>  #include <Library/MemoryAllocationLib.h>  #include
> <Library/DxeServicesTableLib.h>  #include <Library/HobLib.h>  #include
> <Library/BaseLib.h>  #include <Library/DevicePathLib.h> @@ -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
> +        );
> +

1. With the BootCurrent, this change is not necessary because
others can hook PcdProgressCodeOsLoaderLoad to get the current
loading boot option.

>        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
> +        );
> +

2. I think firstly, the OsLoaderDetail is not needed.
Secondly, I prefer to submit a PI spec change to include extended
data for EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR status code.
Instead of inventing a new status code.

>        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
> +    );
> 

3. As above comment #1, this change is not needed.

>    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
> +      );
>    }

4. Similar comments to #2.

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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to