/** @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
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
(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
{\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
//\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