public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: edk2-devel-01 <edk2-devel@lists.01.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Jordan Justen <jordan.l.justen@intel.com>,
	Ruiyu Ni <ruiyu.ni@intel.com>, Eric Dong <eric.dong@intel.com>,
	Star Zeng <star.zeng@intel.com>
Subject: [PATCH 3/5] MdeModulePkg/UefiBootManagerLib: report EDKII_OS_LOADER_DETAIL status code
Date: Thu, 23 Nov 2017 00:58:47 +0100	[thread overview]
Message-ID: <20171122235849.4177-4-lersek@redhat.com> (raw)
In-Reply-To: <20171122235849.4177-1-lersek@redhat.com>

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.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1515418
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@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.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 <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
+        );
+
       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




  parent reply	other threads:[~2017-11-22 23:54 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-22 23:58 [PATCH 0/5] MdeModulePkg, OvmfPkg: more easily visible boot progress reporting Laszlo Ersek
2017-11-22 23:58 ` [PATCH 1/5] MdeModulePkg/BdsDxe: fall back to a Boot Manager Menu loop before hanging Laszlo Ersek
2017-11-23  3:43   ` Ni, Ruiyu
2017-11-23 13:09     ` Laszlo Ersek
2017-11-27 16:27       ` Laszlo Ersek
2017-11-22 23:58 ` [PATCH 2/5] MdeModulePkg: introduce the EDKII_OS_LOADER_DETAIL status code payload Laszlo Ersek
2017-11-22 23:58 ` Laszlo Ersek [this message]
2017-11-23  5:21   ` [PATCH 3/5] MdeModulePkg/UefiBootManagerLib: report EDKII_OS_LOADER_DETAIL status code Ni, Ruiyu
2017-11-23 14:03     ` Laszlo Ersek
2017-11-23 14:53       ` Ni, Ruiyu
2017-11-23 17:08         ` Laszlo Ersek
2017-11-23 23:00           ` Ni, Ruiyu
2017-11-22 23:58 ` [PATCH 4/5] OvmfPkg/PlatformBootManagerLib: print EDKII_OS_LOADER_DETAIL to ConOut Laszlo Ersek
2017-11-22 23:58 ` [PATCH 5/5] OvmfPkg: disable EFI_DEBUG_CODE reporting in RELEASE builds Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171122235849.4177-4-lersek@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox