]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/DxeReportStatusCodeLib/ReportStatusCodeLib.c
MdeModulePkg: SmmReportStatusCodeLib: ReportStatusCodeLib in StandaloneMm
[mirror_edk2.git] / MdeModulePkg / Library / DxeReportStatusCodeLib / ReportStatusCodeLib.c
index f32e167d94a112a2090f54e4f26e352909e2ef66..92559a54f354219a4174f9cf05a1c5b7edc12678 100644 (file)
@@ -1,65 +1,68 @@
 /** @file\r
   Report Status Code Library for DXE Phase.\r
 \r
-  Copyright (c) 2006 - 2009, Intel Corporation<BR>\r
-  All rights reserved. This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include <Library/ReportStatusCodeLib.h>\r
+#include <Library/BaseLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
 #include <Library/PcdLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
 #include <Library/DevicePathLib.h>\r
 \r
+#include <Protocol/StatusCode.h>\r
+\r
 #include <Guid/StatusCodeDataTypeId.h>\r
 #include <Guid/StatusCodeDataTypeDebug.h>\r
-#include <Protocol/StatusCode.h>\r
 \r
-EFI_REPORT_STATUS_CODE  mReportStatusCode = NULL;\r
+//\r
+// Define the maximum extended data size that is supported when a status code is\r
+// reported at TPL_HIGH_LEVEL.\r
+//\r
+#define MAX_EXTENDED_DATA_SIZE  0x200\r
+\r
+EFI_STATUS_CODE_PROTOCOL  *mReportStatusCodeLibStatusCodeProtocol = NULL;\r
 \r
 /**\r
   Locate the report status code service.\r
 \r
-  @return   Function pointer to the report status code service.\r
-            NULL is returned if no status code service is available.\r
+  Retrieve ReportStatusCode() API of Report Status Code Protocol.\r
 \r
 **/\r
-EFI_REPORT_STATUS_CODE\r
+VOID\r
 InternalGetReportStatusCode (\r
   VOID\r
   )\r
 {\r
-  EFI_STATUS_CODE_PROTOCOL  *StatusCodeProtocol;\r
-  EFI_STATUS                Status;\r
+  EFI_STATUS  Status;\r
 \r
+  if (mReportStatusCodeLibStatusCodeProtocol != NULL) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Check gBS just in case ReportStatusCode is called before gBS is initialized.\r
+  //\r
   if (gBS != NULL && gBS->LocateProtocol != NULL) {\r
-    Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol);\r
-    if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) {\r
-      return StatusCodeProtocol->ReportStatusCode;\r
+    Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**) &mReportStatusCodeLibStatusCodeProtocol);\r
+    if (EFI_ERROR (Status)) {\r
+      mReportStatusCodeLibStatusCodeProtocol = NULL;\r
     }\r
   }\r
-\r
-  return NULL;\r
 }\r
 \r
 /**\r
-  Internal worker function that reports a status code through the status code service.\r
+  Internal worker function that reports a status code through the Report Status Code Protocol.\r
 \r
-  If status code service is not cached, then this function checks if status code service is\r
-  available in system.  If status code service is not available, then EFI_UNSUPPORTED is\r
-  returned.  If status code service is present, then it is cached in mReportStatusCode.\r
-  Finally this function reports status code through the status code service.\r
+  If status code service is not cached, then this function checks if Report Status Code\r
+  Protocol is available in system.  If Report Status Code Protocol is not available, then\r
+  EFI_UNSUPPORTED is returned.  If Report Status Code Protocol is present, then it is\r
+  cached in mReportStatusCodeLibStatusCodeProtocol. Finally this function reports status\r
+  code through the Report Status Code Protocol.\r
 \r
   @param  Type              Status code type.\r
   @param  Value             Status code value.\r
@@ -71,7 +74,7 @@ InternalGetReportStatusCode (
                             optional parameter that may be NULL.\r
 \r
   @retval EFI_SUCCESS       The status code was reported.\r
-  @retval EFI_UNSUPPORTED   Status code service is not available.\r
+  @retval EFI_UNSUPPORTED   Report Status Code Protocol is not available.\r
   @retval EFI_UNSUPPORTED   Status code type is not supported.\r
 \r
 **/\r
@@ -88,21 +91,19 @@ InternalReportStatusCode (
       (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ||\r
       (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE)) {\r
     //\r
-    // If mReportStatusCode is NULL, then check if status code service is available in system.\r
+    // If mReportStatusCodeLibStatusCodeProtocol is NULL, then check if Report Status Code Protocol is available in system.\r
     //\r
-    if (mReportStatusCode == NULL) {\r
-      mReportStatusCode = InternalGetReportStatusCode ();\r
-      if (mReportStatusCode == NULL) {\r
-        return EFI_UNSUPPORTED;\r
-      }\r
+    InternalGetReportStatusCode ();\r
+    if (mReportStatusCodeLibStatusCodeProtocol == NULL) {\r
+      return EFI_UNSUPPORTED;\r
     }\r
-  \r
+\r
     //\r
-    // A status code service is present in system, so pass in all the parameters to the service.\r
+    // A Report Status Code Protocol is present in system, so pass in all the parameters to the service.\r
     //\r
-    return (*mReportStatusCode) (Type, Value, Instance, (EFI_GUID *)CallerId, Data);\r
+    return mReportStatusCodeLibStatusCodeProtocol->ReportStatusCode (Type, Value, Instance, (EFI_GUID *)CallerId, Data);\r
   }\r
-  \r
+\r
   return EFI_UNSUPPORTED;\r
 }\r
 \r
@@ -483,28 +484,47 @@ ReportStatusCodeEx (
 {\r
   EFI_STATUS            Status;\r
   EFI_STATUS_CODE_DATA  *StatusCodeData;\r
+  EFI_TPL               Tpl;\r
+  UINT64                Buffer[(MAX_EXTENDED_DATA_SIZE / sizeof (UINT64)) + 1];\r
 \r
   ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0)));\r
   ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0)));\r
 \r
-  if (gBS == NULL || gBS->AllocatePool == NULL || gBS->FreePool == NULL) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
+  if (ExtendedDataSize <= (MAX_EXTENDED_DATA_SIZE - sizeof (EFI_STATUS_CODE_DATA))) {\r
+    //\r
+    // Use Buffer instead of allocating if possible.\r
+    //\r
+    StatusCodeData = (EFI_STATUS_CODE_DATA *)Buffer;\r
+  } else {\r
+    if (gBS == NULL || gBS->AllocatePool == NULL || gBS->FreePool == NULL) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
 \r
-  //\r
-  // Allocate space for the Status Code Header and its buffer\r
-  //\r
-  StatusCodeData = NULL;\r
-  gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_STATUS_CODE_DATA) + ExtendedDataSize, (VOID **)&StatusCodeData);\r
-  if (StatusCodeData == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    //\r
+    // Retrieve the current TPL\r
+    //\r
+    Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+    gBS->RestoreTPL (Tpl);\r
+\r
+    if (Tpl > TPL_NOTIFY) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Allocate space for the Status Code Header and its buffer\r
+    //\r
+    StatusCodeData = NULL;\r
+    gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_STATUS_CODE_DATA) + ExtendedDataSize, (VOID **)&StatusCodeData);\r
+    if (StatusCodeData == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
   }\r
 \r
   //\r
   // Fill in the extended data header\r
   //\r
-  StatusCodeData->HeaderSize = sizeof (EFI_STATUS_CODE_DATA);\r
-  StatusCodeData->Size = (UINT16)ExtendedDataSize;\r
+  StatusCodeData->HeaderSize = (UINT16) sizeof (EFI_STATUS_CODE_DATA);\r
+  StatusCodeData->Size = (UINT16) ExtendedDataSize;\r
   if (ExtendedDataGuid == NULL) {\r
     ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid;\r
   }\r
@@ -528,7 +548,9 @@ ReportStatusCodeEx (
   //\r
   // Free the allocated buffer\r
   //\r
-  gBS->FreePool (StatusCodeData);\r
+  if (StatusCodeData != (EFI_STATUS_CODE_DATA  *)Buffer) {\r
+    gBS->FreePool (StatusCodeData);\r
+  }\r
 \r
   return Status;\r
 }\r