/** @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
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+ 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
\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
return EFI_UNSUPPORTED;\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
\r
//\r
- // Allocate space for the Status Code Header and its buffer\r
+ // Retrieve the current TPL\r
//\r
+ Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+ gBS->RestoreTPL (Tpl);\r
+ \r
StatusCodeData = NULL;\r
- gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_STATUS_CODE_DATA) + ExtendedDataSize, (VOID **)&StatusCodeData);\r
+ if (Tpl <= TPL_NOTIFY) {\r
+ //\r
+ // Allocate space for the Status Code Header and its buffer\r
+ //\r
+ gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_STATUS_CODE_DATA) + ExtendedDataSize, (VOID **)&StatusCodeData);\r
+ }\r
+\r
if (StatusCodeData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ //\r
+ // If a buffer could not be allocated, then see if the local variable Buffer can be used\r
+ //\r
+ if (ExtendedDataSize > (MAX_EXTENDED_DATA_SIZE - sizeof (EFI_STATUS_CODE_DATA))) {\r
+ //\r
+ // The local variable Buffer not large enough to hold the extended data associated\r
+ // with the status code being reported.\r
+ //\r
+ DEBUG ((EFI_D_ERROR, "Status code extended data is too large to be reported!\n"));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ StatusCodeData = (EFI_STATUS_CODE_DATA *)Buffer;\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