Home | History | Annotate | Download | only in DxeCoreReportStatusCodeLibFromHob
      1 /** @file
      2   Report Status Code Library for DXE Phase.
      3 
      4   Copyright (c) 2009, 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 "ReportStatusCodeLibInternal.h"
     16 
     17 /**
     18   Internal worker function that reports a status code through the Status Code Protocol
     19 
     20   This function checks to see if a Status Code Protocol is present in the handle
     21   database.  If a Status Code Protocol is not present, then EFI_UNSUPPORTED is
     22   returned.  If a Status Code Protocol is present, then it is cached in gStatusCode,
     23   and the ReportStatusCode() service of the Status Code Protocol is called passing in
     24   Type, Value, Instance, CallerId, and Data.  The result of this call is returned.
     25 
     26   @param  Type              Status code type.
     27   @param  Value             Status code value.
     28   @param  Instance          Status code instance number.
     29   @param  CallerId          Pointer to a GUID that identifies the caller of this
     30                             function.  This is an optional parameter that may be
     31                             NULL.
     32   @param  Data              Pointer to the extended data buffer.  This is an
     33                             optional parameter that may be NULL.
     34 
     35   @retval  EFI_SUCCESS           The status code was reported.
     36   @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to report the status code.
     37   @retval  EFI_UNSUPPORTED       Status Code Protocol is not available.
     38 
     39 **/
     40 EFI_STATUS
     41 InternalReportStatusCode (
     42   IN EFI_STATUS_CODE_TYPE     Type,
     43   IN EFI_STATUS_CODE_VALUE    Value,
     44   IN UINT32                   Instance,
     45   IN CONST EFI_GUID           *CallerId OPTIONAL,
     46   IN EFI_STATUS_CODE_DATA     *Data     OPTIONAL
     47   )
     48 {
     49   //
     50   // A Status Code Protocol is present in the handle database, so pass in all the
     51   // parameters to the ReportStatusCode() service of the Status Code Protocol
     52   //
     53   return (*mStatusProtocol.ReportStatusCode) (Type, Value, Instance, (EFI_GUID *) CallerId, Data);
     54 }
     55 
     56 
     57 /**
     58   Computes and returns the size, in bytes, of a device path.
     59 
     60   @param  DevicePath  A pointer to a device path.
     61 
     62   @return  The size, in bytes, of DevicePath.
     63 
     64 **/
     65 UINTN
     66 InternalReportStatusCodeDevicePathSize (
     67   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
     68   )
     69 {
     70   CONST EFI_DEVICE_PATH_PROTOCOL  *Start;
     71 
     72   //
     73   // Search for the end of the device path structure
     74   //
     75   Start = DevicePath;
     76   while (!IsDevicePathEnd (DevicePath)) {
     77     DevicePath = NextDevicePathNode (DevicePath);
     78   }
     79 
     80   //
     81   // Subtract the start node from the end node and add in the size of the end node
     82   //
     83   return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath);
     84 }
     85 
     86 
     87 /**
     88   Converts a status code to an 8-bit POST code value.
     89 
     90   Converts the status code specified by CodeType and Value to an 8-bit POST code
     91   and returns the 8-bit POST code in PostCode.  If CodeType is an
     92   EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode
     93   are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits
     94   24..26 of Value., and TRUE is returned.  Otherwise, FALSE is returned.
     95 
     96   If PostCode is NULL, then ASSERT().
     97 
     98   @param  CodeType  The type of status code being converted.
     99   @param  Value     The status code value being converted.
    100   @param  PostCode  A pointer to the 8-bit POST code value to return.
    101 
    102   @retval  TRUE   The status code specified by CodeType and Value was converted
    103                   to an 8-bit POST code and returned in  PostCode.
    104   @retval  FALSE  The status code specified by CodeType and Value could not be
    105                   converted to an 8-bit POST code value.
    106 
    107 **/
    108 BOOLEAN
    109 EFIAPI
    110 CodeTypeToPostCode (
    111   IN  EFI_STATUS_CODE_TYPE   CodeType,
    112   IN  EFI_STATUS_CODE_VALUE  Value,
    113   OUT UINT8                  *PostCode
    114   )
    115 {
    116   //
    117   // If PostCode is NULL, then ASSERT()
    118   //
    119   ASSERT (PostCode != NULL);
    120 
    121   //
    122   // Convert Value to an 8 bit post code
    123   //
    124   if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ||
    125       ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE)       ) {
    126     *PostCode  = (UINT8) ((((Value & EFI_STATUS_CODE_CLASS_MASK) >> 24) << 5) |
    127                           (((Value & EFI_STATUS_CODE_SUBCLASS_MASK) >> 16) & 0x1f));
    128     return TRUE;
    129   }
    130   return FALSE;
    131 }
    132 
    133 
    134 /**
    135   Extracts ASSERT() information from a status code structure.
    136 
    137   Converts the status code specified by CodeType, Value, and Data to the ASSERT()
    138   arguments specified by Filename, Description, and LineNumber.  If CodeType is
    139   an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and
    140   Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract
    141   Filename, Description, and LineNumber from the optional data area of the
    142   status code buffer specified by Data.  The optional data area of Data contains
    143   a Null-terminated ASCII string for the FileName, followed by a Null-terminated
    144   ASCII string for the Description, followed by a 32-bit LineNumber.  If the
    145   ASSERT() information could be extracted from Data, then return TRUE.
    146   Otherwise, FALSE is returned.
    147 
    148   If Data is NULL, then ASSERT().
    149   If Filename is NULL, then ASSERT().
    150   If Description is NULL, then ASSERT().
    151   If LineNumber is NULL, then ASSERT().
    152 
    153   @param  CodeType     The type of status code being converted.
    154   @param  Value        The status code value being converted.
    155   @param  Data         Pointer to status code data buffer.
    156   @param  Filename     Pointer to the source file name that generated the ASSERT().
    157   @param  Description  Pointer to the description of the ASSERT().
    158   @param  LineNumber   Pointer to source line number that generated the ASSERT().
    159 
    160   @retval  TRUE   The status code specified by CodeType, Value, and Data was
    161                   converted ASSERT() arguments specified by Filename, Description,
    162                   and LineNumber.
    163   @retval  FALSE  The status code specified by CodeType, Value, and Data could
    164                   not be converted to ASSERT() arguments.
    165 
    166 **/
    167 BOOLEAN
    168 EFIAPI
    169 ReportStatusCodeExtractAssertInfo (
    170   IN EFI_STATUS_CODE_TYPE        CodeType,
    171   IN EFI_STATUS_CODE_VALUE       Value,
    172   IN CONST EFI_STATUS_CODE_DATA  *Data,
    173   OUT CHAR8                      **Filename,
    174   OUT CHAR8                      **Description,
    175   OUT UINT32                     *LineNumber
    176   )
    177 {
    178   EFI_DEBUG_ASSERT_DATA  *AssertData;
    179 
    180   ASSERT (Data        != NULL);
    181   ASSERT (Filename    != NULL);
    182   ASSERT (Description != NULL);
    183   ASSERT (LineNumber  != NULL);
    184 
    185   if (((CodeType & EFI_STATUS_CODE_TYPE_MASK)      == EFI_ERROR_CODE) &&
    186       ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK)  == EFI_ERROR_UNRECOVERED) &&
    187       ((Value    & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) {
    188     AssertData   = (EFI_DEBUG_ASSERT_DATA *)(Data + 1);
    189     *Filename    = (CHAR8 *)(AssertData + 1);
    190     *Description = *Filename + AsciiStrLen (*Filename) + 1;
    191     *LineNumber  = AssertData->LineNumber;
    192     return TRUE;
    193   }
    194   return FALSE;
    195 }
    196 
    197 
    198 /**
    199   Extracts DEBUG() information from a status code structure.
    200 
    201   Converts the status code specified by Data to the DEBUG() arguments specified
    202   by ErrorLevel, Marker, and Format.  If type GUID in Data is
    203   EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and
    204   Format from the optional data area of the status code buffer specified by Data.
    205   The optional data area of Data contains a 32-bit ErrorLevel followed by Marker
    206   which is 12 UINTN parameters, followed by a Null-terminated ASCII string for
    207   the Format.  If the DEBUG() information could be extracted from Data, then
    208   return TRUE.  Otherwise, FALSE is returned.
    209 
    210   If Data is NULL, then ASSERT().
    211   If ErrorLevel is NULL, then ASSERT().
    212   If Marker is NULL, then ASSERT().
    213   If Format is NULL, then ASSERT().
    214 
    215   @param  Data        Pointer to status code data buffer.
    216   @param  ErrorLevel  Pointer to error level mask for a debug message.
    217   @param  Marker      Pointer to the variable argument list associated with Format.
    218   @param  Format      Pointer to a Null-terminated ASCII format string of a
    219                       debug message.
    220 
    221   @retval  TRUE   The status code specified by Data was converted DEBUG() arguments
    222                   specified by ErrorLevel, Marker, and Format.
    223   @retval  FALSE  The status code specified by Data could not be converted to
    224                   DEBUG() arguments.
    225 
    226 **/
    227 BOOLEAN
    228 EFIAPI
    229 ReportStatusCodeExtractDebugInfo (
    230   IN CONST EFI_STATUS_CODE_DATA  *Data,
    231   OUT UINT32                     *ErrorLevel,
    232   OUT BASE_LIST                  *Marker,
    233   OUT CHAR8                      **Format
    234   )
    235 {
    236   EFI_DEBUG_INFO  *DebugInfo;
    237 
    238   ASSERT (Data          != NULL);
    239   ASSERT (ErrorLevel    != NULL);
    240   ASSERT (Marker     != NULL);
    241   ASSERT (Format     != NULL);
    242 
    243   //
    244   // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE
    245   //
    246   if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) {
    247     return FALSE;
    248   }
    249 
    250   //
    251   // Retrieve the debug information from the status code record
    252   //
    253   DebugInfo = (EFI_DEBUG_INFO *)(Data + 1);
    254 
    255   *ErrorLevel = DebugInfo->ErrorLevel;
    256 
    257   //
    258   // The first 12 * UINTN bytes of the string are really an
    259   // argument stack to support varargs on the Format string.
    260   //
    261   *Marker = (BASE_LIST) (DebugInfo + 1);
    262   *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12);
    263 
    264   return TRUE;
    265 }
    266 
    267 
    268 /**
    269   Reports a status code.
    270 
    271   Reports the status code specified by the parameters Type and Value.  Status
    272   code also require an instance, caller ID, and extended data.  This function
    273   passed in a zero instance, NULL extended data, and a caller ID of
    274   gEfiCallerIdGuid, which is the GUID for the module.
    275 
    276   ReportStatusCode()must actively prevent recusrsion.  If ReportStatusCode()
    277   is called while processing another any other Report Status Code Library function,
    278   then ReportStatusCode() must return immediately.
    279 
    280   @param  Type   Status code type.
    281   @param  Value  Status code value.
    282 
    283   @retval  EFI_SUCCESS       The status code was reported.
    284   @retval  EFI_DEVICE_ERROR  There status code could not be reported due to a
    285                              device error.
    286   @retval  EFI_UNSUPPORTED   Report status code is not supported
    287 
    288 **/
    289 EFI_STATUS
    290 EFIAPI
    291 ReportStatusCode (
    292   IN EFI_STATUS_CODE_TYPE   Type,
    293   IN EFI_STATUS_CODE_VALUE  Value
    294   )
    295 {
    296   return InternalReportStatusCode (Type, Value, 0, &gEfiCallerIdGuid, NULL);
    297 }
    298 
    299 
    300 /**
    301   Reports a status code with a Device Path Protocol as the extended data.
    302 
    303   Allocates and fills in the extended data section of a status code with the
    304   Device Path Protocol specified by DevicePath.  This function is responsible
    305   for allocating a buffer large enough for the standard header and the device
    306   path.  The standard header is filled in with a GUID of
    307   gEfiStatusCodeSpecificDataGuid.  The status code is reported with a zero
    308   instance and a caller ID of gEfiCallerIdGuid.
    309 
    310   ReportStatusCodeWithDevicePath()must actively prevent recursion.  If
    311   ReportStatusCodeWithDevicePath() is called while processing another any other
    312   Report Status Code Library function, then ReportStatusCodeWithDevicePath()
    313   must return EFI_DEVICE_ERROR immediately.
    314 
    315   If DevicePath is NULL, then ASSERT().
    316 
    317   @param  Type        Status code type.
    318   @param  Value       Status code value.
    319   @param  DevicePath  Pointer to the Device Path Protocol to be reported.
    320 
    321   @retval  EFI_SUCCESS           The status code was reported with the extended
    322                                  data specified by DevicePath.
    323   @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate the
    324                                  extended data section.
    325   @retval  EFI_UNSUPPORTED       Report status code is not supported
    326 
    327 **/
    328 EFI_STATUS
    329 EFIAPI
    330 ReportStatusCodeWithDevicePath (
    331   IN EFI_STATUS_CODE_TYPE            Type,
    332   IN EFI_STATUS_CODE_VALUE           Value,
    333   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
    334   )
    335 {
    336   ASSERT (DevicePath != NULL);
    337   return ReportStatusCodeWithExtendedData (
    338            Type,
    339            Value,
    340            (VOID *)DevicePath,
    341            InternalReportStatusCodeDevicePathSize (DevicePath)
    342            );
    343 }
    344 
    345 
    346 /**
    347   Reports a status code with an extended data buffer.
    348 
    349   Allocates and fills in the extended data section of a status code with the
    350   extended data specified by ExtendedData and ExtendedDataSize.  ExtendedData
    351   is assumed to be one of the data structures specified in Related Definitions.
    352   These data structure do not have the standard header, so this function is
    353   responsible for allocating a buffer large enough for the standard header and
    354   the extended data passed into this function.  The standard header is filled
    355   in with a GUID of  gEfiStatusCodeSpecificDataGuid.  The status code is reported
    356   with a zero instance and a caller ID of gEfiCallerIdGuid.
    357 
    358   ReportStatusCodeWithExtendedData()must actively prevent recursion.  If
    359   ReportStatusCodeWithExtendedData() is called while processing another any other
    360   Report Status Code Library function, then ReportStatusCodeWithExtendedData()
    361   must return EFI_DEVICE_ERROR immediately.
    362 
    363   If ExtendedData is NULL, then ASSERT().
    364   If ExtendedDataSize is 0, then ASSERT().
    365 
    366   @param  Type              Status code type.
    367   @param  Value             Status code value.
    368   @param  ExtendedData      Pointer to the extended data buffer to be reported.
    369   @param  ExtendedDataSize  The size, in bytes, of the extended data buffer to
    370                             be reported.
    371 
    372   @retval  EFI_SUCCESS           The status code was reported with the extended
    373                                  data specified by ExtendedData and ExtendedDataSize.
    374   @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate the
    375                                  extended data section.
    376   @retval  EFI_UNSUPPORTED       Report status code is not supported
    377 
    378 **/
    379 EFI_STATUS
    380 EFIAPI
    381 ReportStatusCodeWithExtendedData (
    382   IN EFI_STATUS_CODE_TYPE   Type,
    383   IN EFI_STATUS_CODE_VALUE  Value,
    384   IN CONST VOID             *ExtendedData,
    385   IN UINTN                  ExtendedDataSize
    386   )
    387 {
    388   ASSERT (ExtendedData     != NULL);
    389   ASSERT (ExtendedDataSize != 0);
    390   return ReportStatusCodeEx (
    391            Type,
    392            Value,
    393            0,
    394            NULL,
    395            NULL,
    396            ExtendedData,
    397            ExtendedDataSize
    398            );
    399 }
    400 
    401 
    402 /**
    403   Reports a status code with full parameters.
    404 
    405   The function reports a status code.  If ExtendedData is NULL and ExtendedDataSize
    406   is 0, then an extended data buffer is not reported.  If ExtendedData is not
    407   NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated.
    408   ExtendedData is assumed not have the standard status code header, so this function
    409   is responsible for allocating a buffer large enough for the standard header and
    410   the extended data passed into this function.  The standard header is filled in
    411   with a GUID specified by ExtendedDataGuid.  If ExtendedDataGuid is NULL, then a
    412   GUID of gEfiStatusCodeSpecificDataGuid is used.  The status code is reported with
    413   an instance specified by Instance and a caller ID specified by CallerId.  If
    414   CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used.
    415 
    416   ReportStatusCodeEx()must actively prevent recursion. If
    417   ReportStatusCodeEx() is called while processing another any
    418   other Report Status Code Library function, then
    419   ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately.
    420 
    421   If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT().
    422   If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT().
    423 
    424   @param  Type              Status code type.
    425   @param  Value             Status code value.
    426   @param  Instance          Status code instance number.
    427   @param  CallerId          Pointer to a GUID that identifies the caller of this
    428                             function.  If this parameter is NULL, then a caller
    429                             ID of gEfiCallerIdGuid is used.
    430   @param  ExtendedDataGuid  Pointer to the GUID for the extended data buffer.
    431                             If this parameter is NULL, then a the status code
    432                             standard header is filled in with
    433                             gEfiStatusCodeSpecificDataGuid.
    434   @param  ExtendedData      Pointer to the extended data buffer.  This is an
    435                             optional parameter that may be NULL.
    436   @param  ExtendedDataSize  The size, in bytes, of the extended data buffer.
    437 
    438   @retval  EFI_SUCCESS           The status code was reported.
    439   @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate
    440                                  the extended data section if it was specified.
    441   @retval  EFI_UNSUPPORTED       Report status code is not supported
    442 
    443 **/
    444 EFI_STATUS
    445 EFIAPI
    446 ReportStatusCodeEx (
    447   IN EFI_STATUS_CODE_TYPE   Type,
    448   IN EFI_STATUS_CODE_VALUE  Value,
    449   IN UINT32                 Instance,
    450   IN CONST EFI_GUID         *CallerId          OPTIONAL,
    451   IN CONST EFI_GUID         *ExtendedDataGuid  OPTIONAL,
    452   IN CONST VOID             *ExtendedData      OPTIONAL,
    453   IN UINTN                  ExtendedDataSize
    454   )
    455 {
    456   EFI_STATUS  Status;
    457 
    458   Status = InternalReportStatusCodeEx (
    459              Type,
    460              Value,
    461              Instance,
    462              CallerId,
    463              ExtendedDataGuid,
    464              ExtendedData,
    465              ExtendedDataSize
    466              );
    467 
    468   return Status;
    469 }
    470 
    471 
    472 /**
    473   Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled
    474 
    475   This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED
    476   bit of PcdReportStatusCodeProperyMask is set.  Otherwise FALSE is returned.
    477 
    478   @retval  TRUE   The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of
    479                   PcdReportStatusCodeProperyMask is set.
    480   @retval  FALSE  The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of
    481                   PcdReportStatusCodeProperyMask is clear.
    482 
    483 **/
    484 BOOLEAN
    485 EFIAPI
    486 ReportProgressCodeEnabled (
    487   VOID
    488   )
    489 {
    490   return (BOOLEAN) ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED) != 0);
    491 }
    492 
    493 
    494 /**
    495   Returns TRUE if status codes of type EFI_ERROR_CODE are enabled
    496 
    497   This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED
    498   bit of PcdReportStatusCodeProperyMask is set.  Otherwise FALSE is returned.
    499 
    500   @retval  TRUE   The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of
    501                   PcdReportStatusCodeProperyMask is set.
    502   @retval  FALSE  The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of
    503                   PcdReportStatusCodeProperyMask is clear.
    504 
    505 **/
    506 BOOLEAN
    507 EFIAPI
    508 ReportErrorCodeEnabled (
    509   VOID
    510   )
    511 {
    512   return (BOOLEAN) ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED) != 0);
    513 }
    514 
    515 
    516 /**
    517   Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled
    518 
    519   This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED
    520   bit of PcdReportStatusCodeProperyMask is set.  Otherwise FALSE is returned.
    521 
    522   @retval  TRUE   The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of
    523                   PcdReportStatusCodeProperyMask is set.
    524   @retval  FALSE  The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of
    525                   PcdReportStatusCodeProperyMask is clear.
    526 
    527 **/
    528 BOOLEAN
    529 EFIAPI
    530 ReportDebugCodeEnabled (
    531   VOID
    532   )
    533 {
    534   return (BOOLEAN) ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0);
    535 }
    536