• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   API implementation for instance of Report Status Code Library.
3 
4   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include <Library/ReportStatusCodeLib.h>
16 #include <Library/BaseLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/DevicePathLib.h>
22 #include <Library/UefiRuntimeLib.h>
23 
24 #include <Protocol/StatusCode.h>
25 
26 #include <Guid/StatusCodeDataTypeId.h>
27 #include <Guid/StatusCodeDataTypeDebug.h>
28 #include <Guid/EventGroup.h>
29 
30 
31 //
32 // Define the maximum extended data size that is supported when a status code is reported.
33 //
34 #define MAX_EXTENDED_DATA_SIZE  0x200
35 
36 EFI_STATUS_CODE_PROTOCOL  *mReportStatusCodeLibStatusCodeProtocol = NULL;
37 EFI_EVENT                 mReportStatusCodeLibVirtualAddressChangeEvent;
38 EFI_EVENT                 mReportStatusCodeLibExitBootServicesEvent;
39 BOOLEAN                   mHaveExitedBootServices = FALSE;
40 
41 /**
42   Locate the report status code service.
43 
44   Retrieve ReportStatusCode() API of Report Status Code Protocol.
45 
46 **/
47 VOID
InternalGetReportStatusCode(VOID)48 InternalGetReportStatusCode (
49   VOID
50   )
51 {
52   EFI_STATUS  Status;
53 
54   if (mReportStatusCodeLibStatusCodeProtocol != NULL) {
55     return;
56   }
57 
58   if (mHaveExitedBootServices) {
59     return;
60   }
61 
62   //
63   // Check gBS just in case ReportStatusCode is called before gBS is initialized.
64   //
65   if (gBS != NULL && gBS->LocateProtocol != NULL) {
66     Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**) &mReportStatusCodeLibStatusCodeProtocol);
67     if (EFI_ERROR (Status)) {
68       mReportStatusCodeLibStatusCodeProtocol = NULL;
69     }
70   }
71 }
72 
73 /**
74   Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
75 
76   @param  Event        Event whose notification function is being invoked.
77   @param  Context      Pointer to the notification function's context
78 
79 **/
80 VOID
81 EFIAPI
ReportStatusCodeLibVirtualAddressChange(IN EFI_EVENT Event,IN VOID * Context)82 ReportStatusCodeLibVirtualAddressChange (
83   IN EFI_EVENT        Event,
84   IN VOID             *Context
85   )
86 {
87   if (mReportStatusCodeLibStatusCodeProtocol == NULL) {
88     return;
89   }
90   EfiConvertPointer (0, (VOID **) &mReportStatusCodeLibStatusCodeProtocol);
91 }
92 
93 /**
94   Notification function of EVT_SIGNAL_EXIT_BOOT_SERVICES.
95 
96   @param  Event        Event whose notification function is being invoked.
97   @param  Context      Pointer to the notification function's context
98 
99 **/
100 VOID
101 EFIAPI
ReportStatusCodeLibExitBootServices(IN EFI_EVENT Event,IN VOID * Context)102 ReportStatusCodeLibExitBootServices (
103   IN EFI_EVENT        Event,
104   IN VOID             *Context
105   )
106 {
107   //
108   // Locate the report status code service before enter runtime.
109   //
110   InternalGetReportStatusCode ();
111 
112   mHaveExitedBootServices = TRUE;
113 }
114 
115 /**
116   The constructor function of Runtime DXE Report Status Code Lib.
117 
118   This function allocates memory for extended status code data, caches
119   the report status code service, and registers events.
120 
121   @param  ImageHandle   The firmware allocated handle for the EFI image.
122   @param  SystemTable   A pointer to the EFI System Table.
123 
124   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
125 
126 **/
127 EFI_STATUS
128 EFIAPI
ReportStatusCodeLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)129 ReportStatusCodeLibConstructor (
130   IN EFI_HANDLE           ImageHandle,
131   IN EFI_SYSTEM_TABLE     *SystemTable
132   )
133 {
134   EFI_STATUS  Status;
135 
136   //
137   // Cache the report status code service
138   //
139   InternalGetReportStatusCode ();
140 
141   //
142   // Register notify function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
143   //
144   Status = gBS->CreateEventEx (
145                   EVT_NOTIFY_SIGNAL,
146                   TPL_NOTIFY,
147                   ReportStatusCodeLibVirtualAddressChange,
148                   NULL,
149                   &gEfiEventVirtualAddressChangeGuid,
150                   &mReportStatusCodeLibVirtualAddressChangeEvent
151                   );
152   ASSERT_EFI_ERROR (Status);
153 
154   //
155   // Register notify function for EVT_SIGNAL_EXIT_BOOT_SERVICES
156   //
157   Status = gBS->CreateEventEx (
158                   EVT_NOTIFY_SIGNAL,
159                   TPL_NOTIFY,
160                   ReportStatusCodeLibExitBootServices,
161                   NULL,
162                   &gEfiEventExitBootServicesGuid,
163                   &mReportStatusCodeLibExitBootServicesEvent
164                   );
165   ASSERT_EFI_ERROR (Status);
166 
167   return EFI_SUCCESS;
168 }
169 
170 /**
171   The destructor function of Runtime DXE Report Status Code Lib.
172 
173   The destructor function frees memory allocated by constructor, and closes related events.
174   It will ASSERT() if that related operation fails and it will always return EFI_SUCCESS.
175 
176   @param  ImageHandle   The firmware allocated handle for the EFI image.
177   @param  SystemTable   A pointer to the EFI System Table.
178 
179   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
180 
181 **/
182 EFI_STATUS
183 EFIAPI
ReportStatusCodeLibDestructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)184 ReportStatusCodeLibDestructor (
185   IN EFI_HANDLE        ImageHandle,
186   IN EFI_SYSTEM_TABLE  *SystemTable
187   )
188 {
189   EFI_STATUS  Status;
190 
191   ASSERT (gBS != NULL);
192   Status = gBS->CloseEvent (mReportStatusCodeLibVirtualAddressChangeEvent);
193   ASSERT_EFI_ERROR (Status);
194 
195   Status = gBS->CloseEvent (mReportStatusCodeLibExitBootServicesEvent);
196   ASSERT_EFI_ERROR (Status);
197 
198   return EFI_SUCCESS;
199 }
200 
201 /**
202   Internal worker function that reports a status code through the Report Status Code Protocol.
203 
204   If status code service is not cached, then this function checks if Report Status Code
205   Protocol is available in system.  If Report Status Code Protocol is not available, then
206   EFI_UNSUPPORTED is returned.  If Report Status Code Protocol is present, then it is
207   cached in mReportStatusCodeLibStatusCodeProtocol. Finally this function reports status
208   code through the Report Status Code Protocol.
209 
210   @param  Type              Status code type.
211   @param  Value             Status code value.
212   @param  Instance          Status code instance number.
213   @param  CallerId          Pointer to a GUID that identifies the caller of this
214                             function.  This is an optional parameter that may be
215                             NULL.
216   @param  Data              Pointer to the extended data buffer.  This is an
217                             optional parameter that may be NULL.
218 
219   @retval EFI_SUCCESS       The status code was reported.
220   @retval EFI_UNSUPPORTED   Report Status Code Protocol is not available.
221   @retval EFI_UNSUPPORTED   Status code type is not supported.
222 
223 **/
224 EFI_STATUS
InternalReportStatusCode(IN EFI_STATUS_CODE_TYPE Type,IN EFI_STATUS_CODE_VALUE Value,IN UINT32 Instance,IN CONST EFI_GUID * CallerId OPTIONAL,IN EFI_STATUS_CODE_DATA * Data OPTIONAL)225 InternalReportStatusCode (
226   IN EFI_STATUS_CODE_TYPE     Type,
227   IN EFI_STATUS_CODE_VALUE    Value,
228   IN UINT32                   Instance,
229   IN CONST EFI_GUID           *CallerId OPTIONAL,
230   IN EFI_STATUS_CODE_DATA     *Data     OPTIONAL
231   )
232 {
233   if ((ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ||
234       (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ||
235       (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE)) {
236     //
237     // If mReportStatusCodeLibStatusCodeProtocol is NULL, then check if Report Status Code Protocol is available in system.
238     //
239     InternalGetReportStatusCode ();
240     if (mReportStatusCodeLibStatusCodeProtocol == NULL) {
241       return EFI_UNSUPPORTED;
242     }
243 
244     //
245     // A Report Status Code Protocol is present in system, so pass in all the parameters to the service.
246     //
247     return mReportStatusCodeLibStatusCodeProtocol->ReportStatusCode (Type, Value, Instance, (EFI_GUID *)CallerId, Data);
248   }
249 
250   return EFI_UNSUPPORTED;
251 }
252 
253 
254 /**
255   Converts a status code to an 8-bit POST code value.
256 
257   Converts the status code specified by CodeType and Value to an 8-bit POST code
258   and returns the 8-bit POST code in PostCode.  If CodeType is an
259   EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode
260   are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits
261   24..26 of Value., and TRUE is returned.  Otherwise, FALSE is returned.
262 
263   If PostCode is NULL, then ASSERT().
264 
265   @param  CodeType  The type of status code being converted.
266   @param  Value     The status code value being converted.
267   @param  PostCode  A pointer to the 8-bit POST code value to return.
268 
269   @retval  TRUE   The status code specified by CodeType and Value was converted
270                   to an 8-bit POST code and returned in  PostCode.
271   @retval  FALSE  The status code specified by CodeType and Value could not be
272                   converted to an 8-bit POST code value.
273 
274 **/
275 BOOLEAN
276 EFIAPI
CodeTypeToPostCode(IN EFI_STATUS_CODE_TYPE CodeType,IN EFI_STATUS_CODE_VALUE Value,OUT UINT8 * PostCode)277 CodeTypeToPostCode (
278   IN  EFI_STATUS_CODE_TYPE   CodeType,
279   IN  EFI_STATUS_CODE_VALUE  Value,
280   OUT UINT8                  *PostCode
281   )
282 {
283   //
284   // If PostCode is NULL, then ASSERT()
285   //
286   ASSERT (PostCode != NULL);
287 
288   //
289   // Convert Value to an 8 bit post code
290   //
291   if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ||
292       ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE)       ) {
293     *PostCode  = (UINT8) ((((Value & EFI_STATUS_CODE_CLASS_MASK) >> 24) << 5) |
294                           (((Value & EFI_STATUS_CODE_SUBCLASS_MASK) >> 16) & 0x1f));
295     return TRUE;
296   }
297   return FALSE;
298 }
299 
300 
301 /**
302   Extracts ASSERT() information from a status code structure.
303 
304   Converts the status code specified by CodeType, Value, and Data to the ASSERT()
305   arguments specified by Filename, Description, and LineNumber.  If CodeType is
306   an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and
307   Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract
308   Filename, Description, and LineNumber from the optional data area of the
309   status code buffer specified by Data.  The optional data area of Data contains
310   a Null-terminated ASCII string for the FileName, followed by a Null-terminated
311   ASCII string for the Description, followed by a 32-bit LineNumber.  If the
312   ASSERT() information could be extracted from Data, then return TRUE.
313   Otherwise, FALSE is returned.
314 
315   If Data is NULL, then ASSERT().
316   If Filename is NULL, then ASSERT().
317   If Description is NULL, then ASSERT().
318   If LineNumber is NULL, then ASSERT().
319 
320   @param  CodeType     The type of status code being converted.
321   @param  Value        The status code value being converted.
322   @param  Data         Pointer to status code data buffer.
323   @param  Filename     Pointer to the source file name that generated the ASSERT().
324   @param  Description  Pointer to the description of the ASSERT().
325   @param  LineNumber   Pointer to source line number that generated the ASSERT().
326 
327   @retval  TRUE   The status code specified by CodeType, Value, and Data was
328                   converted ASSERT() arguments specified by Filename, Description,
329                   and LineNumber.
330   @retval  FALSE  The status code specified by CodeType, Value, and Data could
331                   not be converted to ASSERT() arguments.
332 
333 **/
334 BOOLEAN
335 EFIAPI
ReportStatusCodeExtractAssertInfo(IN EFI_STATUS_CODE_TYPE CodeType,IN EFI_STATUS_CODE_VALUE Value,IN CONST EFI_STATUS_CODE_DATA * Data,OUT CHAR8 ** Filename,OUT CHAR8 ** Description,OUT UINT32 * LineNumber)336 ReportStatusCodeExtractAssertInfo (
337   IN EFI_STATUS_CODE_TYPE        CodeType,
338   IN EFI_STATUS_CODE_VALUE       Value,
339   IN CONST EFI_STATUS_CODE_DATA  *Data,
340   OUT CHAR8                      **Filename,
341   OUT CHAR8                      **Description,
342   OUT UINT32                     *LineNumber
343   )
344 {
345   EFI_DEBUG_ASSERT_DATA  *AssertData;
346 
347   ASSERT (Data        != NULL);
348   ASSERT (Filename    != NULL);
349   ASSERT (Description != NULL);
350   ASSERT (LineNumber  != NULL);
351 
352   if (((CodeType & EFI_STATUS_CODE_TYPE_MASK)      == EFI_ERROR_CODE) &&
353       ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK)  == EFI_ERROR_UNRECOVERED) &&
354       ((Value    & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) {
355     AssertData   = (EFI_DEBUG_ASSERT_DATA *)(Data + 1);
356     *Filename    = (CHAR8 *)(AssertData + 1);
357     *Description = *Filename + AsciiStrLen (*Filename) + 1;
358     *LineNumber  = AssertData->LineNumber;
359     return TRUE;
360   }
361   return FALSE;
362 }
363 
364 
365 /**
366   Extracts DEBUG() information from a status code structure.
367 
368   Converts the status code specified by Data to the DEBUG() arguments specified
369   by ErrorLevel, Marker, and Format.  If type GUID in Data is
370   EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and
371   Format from the optional data area of the status code buffer specified by Data.
372   The optional data area of Data contains a 32-bit ErrorLevel followed by Marker
373   which is 12 UINTN parameters, followed by a Null-terminated ASCII string for
374   the Format.  If the DEBUG() information could be extracted from Data, then
375   return TRUE.  Otherwise, FALSE is returned.
376 
377   If Data is NULL, then ASSERT().
378   If ErrorLevel is NULL, then ASSERT().
379   If Marker is NULL, then ASSERT().
380   If Format is NULL, then ASSERT().
381 
382   @param  Data        Pointer to status code data buffer.
383   @param  ErrorLevel  Pointer to error level mask for a debug message.
384   @param  Marker      Pointer to the variable argument list associated with Format.
385   @param  Format      Pointer to a Null-terminated ASCII format string of a
386                       debug message.
387 
388   @retval  TRUE   The status code specified by Data was converted DEBUG() arguments
389                   specified by ErrorLevel, Marker, and Format.
390   @retval  FALSE  The status code specified by Data could not be converted to
391                   DEBUG() arguments.
392 
393 **/
394 BOOLEAN
395 EFIAPI
ReportStatusCodeExtractDebugInfo(IN CONST EFI_STATUS_CODE_DATA * Data,OUT UINT32 * ErrorLevel,OUT BASE_LIST * Marker,OUT CHAR8 ** Format)396 ReportStatusCodeExtractDebugInfo (
397   IN CONST EFI_STATUS_CODE_DATA  *Data,
398   OUT UINT32                     *ErrorLevel,
399   OUT BASE_LIST                  *Marker,
400   OUT CHAR8                      **Format
401   )
402 {
403   EFI_DEBUG_INFO  *DebugInfo;
404 
405   ASSERT (Data       != NULL);
406   ASSERT (ErrorLevel != NULL);
407   ASSERT (Marker     != NULL);
408   ASSERT (Format     != NULL);
409 
410   //
411   // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE
412   //
413   if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) {
414     return FALSE;
415   }
416 
417   //
418   // Retrieve the debug information from the status code record
419   //
420   DebugInfo = (EFI_DEBUG_INFO *)(Data + 1);
421 
422   *ErrorLevel = DebugInfo->ErrorLevel;
423 
424   //
425   // The first 12 * sizeof (UINT64) bytes following EFI_DEBUG_INFO are for variable arguments
426   // of format in DEBUG string. Its address is returned in Marker and has to be 64-bit aligned.
427   // It must be noticed that EFI_DEBUG_INFO follows EFI_STATUS_CODE_DATA, whose size is
428   // 20 bytes. The size of EFI_DEBUG_INFO is 4 bytes, so we can ensure that Marker
429   // returned is 64-bit aligned.
430   // 64-bit aligned is a must, otherwise retrieving 64-bit parameter from BASE_LIST will
431   // cause unalignment exception.
432   //
433   *Marker = (BASE_LIST) (DebugInfo + 1);
434   *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12);
435 
436   return TRUE;
437 }
438 
439 
440 /**
441   Reports a status code.
442 
443   Reports the status code specified by the parameters Type and Value.  Status
444   code also require an instance, caller ID, and extended data.  This function
445   passed in a zero instance, NULL extended data, and a caller ID of
446   gEfiCallerIdGuid, which is the GUID for the module.
447 
448   ReportStatusCode()must actively prevent recusrsion.  If ReportStatusCode()
449   is called while processing another any other Report Status Code Library function,
450   then ReportStatusCode() must return immediately.
451 
452   @param  Type   Status code type.
453   @param  Value  Status code value.
454 
455   @retval  EFI_SUCCESS       The status code was reported.
456   @retval  EFI_DEVICE_ERROR  There status code could not be reported due to a
457                              device error.
458   @retval  EFI_UNSUPPORTED   Report status code is not supported
459 
460 **/
461 EFI_STATUS
462 EFIAPI
ReportStatusCode(IN EFI_STATUS_CODE_TYPE Type,IN EFI_STATUS_CODE_VALUE Value)463 ReportStatusCode (
464   IN EFI_STATUS_CODE_TYPE   Type,
465   IN EFI_STATUS_CODE_VALUE  Value
466   )
467 {
468   return InternalReportStatusCode (Type, Value, 0, &gEfiCallerIdGuid, NULL);
469 }
470 
471 
472 /**
473   Reports a status code with a Device Path Protocol as the extended data.
474 
475   Allocates and fills in the extended data section of a status code with the
476   Device Path Protocol specified by DevicePath.  This function is responsible
477   for allocating a buffer large enough for the standard header and the device
478   path.  The standard header is filled in with a GUID of
479   gEfiStatusCodeSpecificDataGuid.  The status code is reported with a zero
480   instance and a caller ID of gEfiCallerIdGuid.
481 
482   ReportStatusCodeWithDevicePath()must actively prevent recursion.  If
483   ReportStatusCodeWithDevicePath() is called while processing another any other
484   Report Status Code Library function, then ReportStatusCodeWithDevicePath()
485   must return EFI_DEVICE_ERROR immediately.
486 
487   If DevicePath is NULL, then ASSERT().
488 
489   @param  Type        Status code type.
490   @param  Value       Status code value.
491   @param  DevicePath  Pointer to the Device Path Protocol to be reported.
492 
493   @retval  EFI_SUCCESS           The status code was reported with the extended
494                                  data specified by DevicePath.
495   @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate the
496                                  extended data section.
497   @retval  EFI_UNSUPPORTED       Report status code is not supported
498 
499 **/
500 EFI_STATUS
501 EFIAPI
ReportStatusCodeWithDevicePath(IN EFI_STATUS_CODE_TYPE Type,IN EFI_STATUS_CODE_VALUE Value,IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath)502 ReportStatusCodeWithDevicePath (
503   IN EFI_STATUS_CODE_TYPE            Type,
504   IN EFI_STATUS_CODE_VALUE           Value,
505   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
506   )
507 {
508   ASSERT (DevicePath != NULL);
509   return ReportStatusCodeWithExtendedData (
510            Type,
511            Value,
512            (VOID *)DevicePath,
513            GetDevicePathSize (DevicePath)
514            );
515 }
516 
517 
518 /**
519   Reports a status code with an extended data buffer.
520 
521   Allocates and fills in the extended data section of a status code with the
522   extended data specified by ExtendedData and ExtendedDataSize.  ExtendedData
523   is assumed to be one of the data structures specified in Related Definitions.
524   These data structure do not have the standard header, so this function is
525   responsible for allocating a buffer large enough for the standard header and
526   the extended data passed into this function.  The standard header is filled
527   in with a GUID of  gEfiStatusCodeSpecificDataGuid.  The status code is reported
528   with a zero instance and a caller ID of gEfiCallerIdGuid.
529 
530   ReportStatusCodeWithExtendedData()must actively prevent recursion.  If
531   ReportStatusCodeWithExtendedData() is called while processing another any other
532   Report Status Code Library function, then ReportStatusCodeWithExtendedData()
533   must return EFI_DEVICE_ERROR immediately.
534 
535   If ExtendedData is NULL, then ASSERT().
536   If ExtendedDataSize is 0, then ASSERT().
537 
538   @param  Type              Status code type.
539   @param  Value             Status code value.
540   @param  ExtendedData      Pointer to the extended data buffer to be reported.
541   @param  ExtendedDataSize  The size, in bytes, of the extended data buffer to
542                             be reported.
543 
544   @retval  EFI_SUCCESS           The status code was reported with the extended
545                                  data specified by ExtendedData and ExtendedDataSize.
546   @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate the
547                                  extended data section.
548   @retval  EFI_UNSUPPORTED       Report status code is not supported
549 
550 **/
551 EFI_STATUS
552 EFIAPI
ReportStatusCodeWithExtendedData(IN EFI_STATUS_CODE_TYPE Type,IN EFI_STATUS_CODE_VALUE Value,IN CONST VOID * ExtendedData,IN UINTN ExtendedDataSize)553 ReportStatusCodeWithExtendedData (
554   IN EFI_STATUS_CODE_TYPE   Type,
555   IN EFI_STATUS_CODE_VALUE  Value,
556   IN CONST VOID             *ExtendedData,
557   IN UINTN                  ExtendedDataSize
558   )
559 {
560   ASSERT (ExtendedData     != NULL);
561   ASSERT (ExtendedDataSize != 0);
562   return ReportStatusCodeEx (
563            Type,
564            Value,
565            0,
566            NULL,
567            NULL,
568            ExtendedData,
569            ExtendedDataSize
570            );
571 }
572 
573 
574 /**
575   Reports a status code with full parameters.
576 
577   The function reports a status code.  If ExtendedData is NULL and ExtendedDataSize
578   is 0, then an extended data buffer is not reported.  If ExtendedData is not
579   NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated.
580   ExtendedData is assumed not have the standard status code header, so this function
581   is responsible for allocating a buffer large enough for the standard header and
582   the extended data passed into this function.  The standard header is filled in
583   with a GUID specified by ExtendedDataGuid.  If ExtendedDataGuid is NULL, then a
584   GUID of gEfiStatusCodeSpecificDataGuid is used.  The status code is reported with
585   an instance specified by Instance and a caller ID specified by CallerId.  If
586   CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used.
587 
588   ReportStatusCodeEx()must actively prevent recursion. If
589   ReportStatusCodeEx() is called while processing another any
590   other Report Status Code Library function, then
591   ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately.
592 
593   If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT().
594   If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT().
595 
596   @param  Type              Status code type.
597   @param  Value             Status code value.
598   @param  Instance          Status code instance number.
599   @param  CallerId          Pointer to a GUID that identifies the caller of this
600                             function.  If this parameter is NULL, then a caller
601                             ID of gEfiCallerIdGuid is used.
602   @param  ExtendedDataGuid  Pointer to the GUID for the extended data buffer.
603                             If this parameter is NULL, then a the status code
604                             standard header is filled in with
605                             gEfiStatusCodeSpecificDataGuid.
606   @param  ExtendedData      Pointer to the extended data buffer.  This is an
607                             optional parameter that may be NULL.
608   @param  ExtendedDataSize  The size, in bytes, of the extended data buffer.
609 
610   @retval  EFI_SUCCESS           The status code was reported.
611   @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate
612                                  the extended data section if it was specified.
613   @retval  EFI_UNSUPPORTED       Report status code is not supported
614 
615 **/
616 EFI_STATUS
617 EFIAPI
ReportStatusCodeEx(IN EFI_STATUS_CODE_TYPE Type,IN EFI_STATUS_CODE_VALUE Value,IN UINT32 Instance,IN CONST EFI_GUID * CallerId OPTIONAL,IN CONST EFI_GUID * ExtendedDataGuid OPTIONAL,IN CONST VOID * ExtendedData OPTIONAL,IN UINTN ExtendedDataSize)618 ReportStatusCodeEx (
619   IN EFI_STATUS_CODE_TYPE   Type,
620   IN EFI_STATUS_CODE_VALUE  Value,
621   IN UINT32                 Instance,
622   IN CONST EFI_GUID         *CallerId          OPTIONAL,
623   IN CONST EFI_GUID         *ExtendedDataGuid  OPTIONAL,
624   IN CONST VOID             *ExtendedData      OPTIONAL,
625   IN UINTN                  ExtendedDataSize
626   )
627 {
628   EFI_STATUS            Status;
629   EFI_STATUS_CODE_DATA  *StatusCodeData;
630   UINT64                StatusCodeBuffer[(MAX_EXTENDED_DATA_SIZE / sizeof (UINT64)) + 1];
631 
632   ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0)));
633   ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0)));
634 
635   if (mHaveExitedBootServices) {
636     if (sizeof (EFI_STATUS_CODE_DATA) + ExtendedDataSize > MAX_EXTENDED_DATA_SIZE) {
637       return EFI_OUT_OF_RESOURCES;
638     }
639     StatusCodeData = (EFI_STATUS_CODE_DATA *) StatusCodeBuffer;
640   } else  {
641     if (gBS == NULL || gBS->AllocatePool == NULL || gBS->FreePool == NULL) {
642       return EFI_UNSUPPORTED;
643     }
644 
645     //
646     // Allocate space for the Status Code Header and its buffer
647     //
648     StatusCodeData = NULL;
649     gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_STATUS_CODE_DATA) + ExtendedDataSize, (VOID **)&StatusCodeData);
650     if (StatusCodeData == NULL) {
651       return EFI_OUT_OF_RESOURCES;
652     }
653   }
654 
655   //
656   // Fill in the extended data header
657   //
658   StatusCodeData->HeaderSize = (UINT16) sizeof (EFI_STATUS_CODE_DATA);
659   StatusCodeData->Size = (UINT16) ExtendedDataSize;
660   if (ExtendedDataGuid == NULL) {
661     ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid;
662   }
663   CopyGuid (&StatusCodeData->Type, ExtendedDataGuid);
664 
665   //
666   // Fill in the extended data buffer
667   //
668   if (ExtendedData != NULL) {
669     CopyMem (StatusCodeData + 1, ExtendedData, ExtendedDataSize);
670   }
671 
672   //
673   // Report the status code
674   //
675   if (CallerId == NULL) {
676     CallerId = &gEfiCallerIdGuid;
677   }
678   Status = InternalReportStatusCode (Type, Value, Instance, CallerId, StatusCodeData);
679 
680   //
681   // Free the allocated buffer
682   //
683   if (!mHaveExitedBootServices) {
684     gBS->FreePool (StatusCodeData);
685   }
686 
687   return Status;
688 }
689 
690 
691 /**
692   Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled
693 
694   This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED
695   bit of PcdReportStatusCodeProperyMask is set.  Otherwise FALSE is returned.
696 
697   @retval  TRUE   The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of
698                   PcdReportStatusCodeProperyMask is set.
699   @retval  FALSE  The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of
700                   PcdReportStatusCodeProperyMask is clear.
701 
702 **/
703 BOOLEAN
704 EFIAPI
ReportProgressCodeEnabled(VOID)705 ReportProgressCodeEnabled (
706   VOID
707   )
708 {
709   return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED) != 0);
710 }
711 
712 
713 /**
714   Returns TRUE if status codes of type EFI_ERROR_CODE are enabled
715 
716   This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED
717   bit of PcdReportStatusCodeProperyMask is set.  Otherwise FALSE is returned.
718 
719   @retval  TRUE   The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of
720                   PcdReportStatusCodeProperyMask is set.
721   @retval  FALSE  The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of
722                   PcdReportStatusCodeProperyMask is clear.
723 
724 **/
725 BOOLEAN
726 EFIAPI
ReportErrorCodeEnabled(VOID)727 ReportErrorCodeEnabled (
728   VOID
729   )
730 {
731   return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED) != 0);
732 }
733 
734 
735 /**
736   Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled
737 
738   This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED
739   bit of PcdReportStatusCodeProperyMask is set.  Otherwise FALSE is returned.
740 
741   @retval  TRUE   The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of
742                   PcdReportStatusCodeProperyMask is set.
743   @retval  FALSE  The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of
744                   PcdReportStatusCodeProperyMask is clear.
745 
746 **/
747 BOOLEAN
748 EFIAPI
ReportDebugCodeEnabled(VOID)749 ReportDebugCodeEnabled (
750   VOID
751   )
752 {
753   return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0);
754 }
755