Home | History | Annotate | Download | only in EfiCommonLib
      1 /*++
      2 
      3 Copyright (c) 2004, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   ReportStatusCode.c
     15 
     16 Abstract:
     17 
     18   Worker functions for ReportStatusCode
     19 
     20 --*/
     21 
     22 #include "TianoCommon.h"
     23 #include "EfiCommonLib.h"
     24 #include EFI_GUID_DEFINITION (StatusCodeCallerId)
     25 #include EFI_GUID_DEFINITION (StatusCodeDataTypeId)
     26 
     27 
     28 VOID *
     29 EfiConstructStatusCodeData (
     30   IN  UINT16                    DataSize,
     31   IN  EFI_GUID                  *TypeGuid,
     32   IN OUT  EFI_STATUS_CODE_DATA  *Data
     33   )
     34 /*++
     35 
     36 Routine Description:
     37 
     38   Construct stanader header for optional data passed into ReportStatusCode
     39 
     40 Arguments:
     41 
     42   DataSize - Size of optional data. Does not include EFI_STATUS_CODE_DATA header
     43   TypeGuid - GUID to place in EFI_STATUS_CODE_DATA
     44   Data     - Buffer to use.
     45 
     46 Returns:
     47 
     48   Return pointer to Data buffer pointing past the end of EFI_STATUS_CODE_DATA
     49 
     50 --*/
     51 {
     52   Data->HeaderSize = (UINT16) sizeof (EFI_STATUS_CODE_DATA);
     53   Data->Size = (UINT16)(DataSize - sizeof (EFI_STATUS_CODE_DATA));
     54   EfiCommonLibCopyMem (&Data->Type, TypeGuid, sizeof (EFI_GUID));
     55 
     56   return (VOID *)(Data + 1);
     57 }
     58 
     59 EFI_STATUS
     60 EfiDebugVPrintWorker (
     61   IN  UINTN                   ErrorLevel,
     62   IN  CHAR8                   *Format,
     63   IN  VA_LIST                 Marker,
     64   IN  UINTN                   BufferSize,
     65   IN OUT VOID                 *Buffer
     66   )
     67 /*++
     68 
     69 Routine Description:
     70 
     71   Worker function for DEBUG(). If Error Logging hub is loaded log ASSERT
     72   information. If Error Logging hub is not loaded do nothing.
     73 
     74   The Format string might be truncated to fit into the status code struture
     75   which has the max size of EFI_STATUS_CODE_DATA_MAX_SIZE.
     76 
     77   We use UINT64 buffers due to IPF alignment concerns.
     78 
     79 Arguments:
     80 
     81   ErrorLevel - If error level is set do the debug print.
     82 
     83   Format     - String to use for the print, followed by Print arguments.
     84 
     85   Marker     - VarArgs
     86 
     87   BufferSize - Size of Buffer.
     88 
     89   Buffer     - Caller allocated buffer, contains ReportStatusCode extended data
     90 
     91 Returns:
     92 
     93   Status code
     94 
     95   EFI_SUCCESS             - Successfully printed
     96 
     97 --*/
     98 {
     99   UINTN                   Index;
    100   UINTN                   FormatStrLen;
    101   UINTN                   RemainingStrLen;
    102   UINT64                  *Ptr;
    103   EFI_DEBUG_INFO          *EfiDebug;
    104 
    105 
    106   //
    107   // Build the type specific EFI_STATUS_CODE_DATA in order
    108   //
    109 
    110   //
    111   // Fill in EFI_STATUS_CODE_DATA to Buffer.
    112   //
    113   EfiDebug = (EFI_DEBUG_INFO *)EfiConstructStatusCodeData (
    114                                 (UINT16)BufferSize,
    115                                 &gEfiStatusCodeDataTypeDebugGuid,
    116                                 Buffer
    117                                 );
    118 
    119   //
    120   // Then EFI_DEBUG_INFO
    121   //
    122   EfiDebug->ErrorLevel = (UINT32)ErrorLevel;
    123 
    124   //
    125   // 12 * sizeof (UINT64) byte mini Var Arg stack.
    126   // That is followed by the format string.
    127   //
    128   for (Index = 0, Ptr = (UINT64 *)(EfiDebug + 1); Index < 12; Index++, Ptr++) {
    129     *Ptr = VA_ARG (Marker, UINT64);
    130   }
    131 
    132   //
    133   // Place Ascii Format string at the end
    134   // Truncate it to fit into the status code structure
    135   //
    136   FormatStrLen    = EfiAsciiStrLen (Format);
    137   RemainingStrLen = EFI_STATUS_CODE_DATA_MAX_SIZE
    138     - sizeof (EFI_STATUS_CODE_DATA)
    139     - sizeof (EFI_DEBUG_INFO)
    140     - 12 * sizeof (UINT64) - 1;
    141   if (FormatStrLen > RemainingStrLen) {
    142     FormatStrLen = RemainingStrLen;
    143   }
    144   EfiCommonLibCopyMem (Ptr, Format, FormatStrLen);
    145   *((CHAR8 *) Ptr + FormatStrLen) = '\0';
    146 
    147   return EFI_SUCCESS;
    148 }
    149 
    150 
    151 
    152 EFI_STATUS
    153 EfiDebugAssertWorker (
    154   IN CHAR8                    *Filename,
    155   IN INTN                     LineNumber,
    156   IN CHAR8                    *Description,
    157   IN UINTN                    BufferSize,
    158   IN OUT VOID                 *Buffer
    159   )
    160 /*++
    161 
    162 Routine Description:
    163 
    164   Worker function for ASSERT (). If Error Logging hub is loaded log ASSERT
    165   information. If Error Logging hub is not loaded DEADLOOP ().
    166 
    167   We use UINT64 buffers due to IPF alignment concerns.
    168 
    169 Arguments:
    170 
    171   Filename    - File name of failing routine.
    172 
    173   LineNumber  - Line number of failing ASSERT().
    174 
    175   Description - Description, usually the assertion,
    176 
    177   BufferSize - Size of Buffer.
    178 
    179   Buffer     - Caller allocated buffer, contains ReportStatusCode extendecd data
    180 
    181 Returns:
    182 
    183   Status code
    184 
    185   EFI_BUFFER_TOO_SMALL      - Buffer not large enough
    186 
    187   EFI_SUCCESS               - Function successfully done.
    188 
    189 --*/
    190 {
    191   EFI_DEBUG_ASSERT_DATA   *AssertData;
    192   UINTN                   TotalSize;
    193   CHAR8                   *EndOfStr;
    194 
    195   //
    196   // Make sure it will all fit in the passed in buffer
    197   //
    198   TotalSize = sizeof (EFI_STATUS_CODE_DATA) + sizeof (EFI_DEBUG_ASSERT_DATA);
    199   TotalSize += EfiAsciiStrLen (Filename);
    200   TotalSize += EfiAsciiStrLen (Description);
    201   if (TotalSize > BufferSize) {
    202     return EFI_BUFFER_TOO_SMALL;
    203   }
    204 
    205   //
    206   // Fill in EFI_STATUS_CODE_DATA
    207   //
    208   AssertData =  (EFI_DEBUG_ASSERT_DATA *)
    209                 EfiConstructStatusCodeData (
    210                   (UINT16)(TotalSize - sizeof (EFI_STATUS_CODE_DATA)),
    211                   &gEfiStatusCodeDataTypeAssertGuid,
    212                   Buffer
    213                   );
    214 
    215   //
    216   // Fill in EFI_DEBUG_ASSERT_DATA
    217   //
    218   AssertData->LineNumber = (UINT32)LineNumber;
    219 
    220   //
    221   // Copy Ascii FileName including NULL.
    222   //
    223   EndOfStr = EfiAsciiStrCpy ((CHAR8 *)(AssertData + 1), Filename);
    224 
    225   //
    226   // Copy Ascii Description
    227   //
    228   EfiAsciiStrCpy (EndOfStr, Description);
    229   return EFI_SUCCESS;
    230 }
    231 
    232 
    233 
    234 BOOLEAN
    235 ReportStatusCodeExtractAssertInfo (
    236   IN EFI_STATUS_CODE_TYPE     CodeType,
    237   IN EFI_STATUS_CODE_VALUE    Value,
    238   IN EFI_STATUS_CODE_DATA     *Data,
    239   OUT CHAR8                   **Filename,
    240   OUT CHAR8                   **Description,
    241   OUT UINT32                  *LineNumber
    242   )
    243 /*++
    244 
    245 Routine Description:
    246 
    247   Extract assert information from status code data.
    248 
    249 Arguments:
    250 
    251   CodeType    - Code type
    252   Value       - Code value
    253   Data        - Optional data associated with this status code.
    254   Filename    - Filename extracted from Data
    255   Description - Description extracted from Data
    256   LineNumber  - Line number extracted from Data
    257 
    258 Returns:
    259 
    260   TRUE      - Successfully extracted
    261 
    262   FALSE     - Extraction failed
    263 
    264 --*/
    265 {
    266   EFI_DEBUG_ASSERT_DATA   *AssertData;
    267 
    268   if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) &&
    269         ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED)) {
    270     //
    271     // Assume if we have an uncontained unrecoverable error that the data hub
    272     // may not work. So we will print out data here. If we had an IPMI controller,
    273     // or error log we could wack the hardware here.
    274     //
    275     if ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE && (Data != NULL)) {
    276       //
    277       // ASSERT (Expresion) -
    278       // ExtendedData == FileName
    279       // Instance     == Line Nuber
    280       // NULL         == String of Expresion
    281       //
    282       AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1);
    283       *Filename = (CHAR8 *)(AssertData + 1);
    284       *Description = *Filename + EfiAsciiStrLen (*Filename) + 1;
    285       *LineNumber = AssertData->LineNumber;
    286       return TRUE;
    287     }
    288   }
    289   return FALSE;
    290 }
    291 
    292 
    293 BOOLEAN
    294 ReportStatusCodeExtractDebugInfo (
    295   IN EFI_STATUS_CODE_DATA     *Data,
    296   OUT UINT32                  *ErrorLevel,
    297   OUT VA_LIST                 *Marker,
    298   OUT CHAR8                   **Format
    299   )
    300 /*++
    301 
    302 Routine Description:
    303 
    304   Extract debug information from status code data.
    305 
    306 Arguments:
    307 
    308   Data        - Optional data associated with status code.
    309   ErrorLevel  - Error level extracted from Data
    310   Marker      - VA_LIST extracted from Data
    311   Format      - Format string extracted from Data
    312 
    313 Returns:
    314 
    315   TRUE      - Successfully extracted
    316 
    317   FALSE     - Extraction failed
    318 
    319 --*/
    320 {
    321   EFI_DEBUG_INFO      *DebugInfo;
    322 
    323   if ((Data == NULL) || (!EfiCompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid))) {
    324     return FALSE;
    325   }
    326 
    327   DebugInfo = (EFI_DEBUG_INFO *)(Data + 1);
    328 
    329   *ErrorLevel = DebugInfo->ErrorLevel;
    330 
    331   //
    332   // The first 12 * UINTN bytes of the string are really an
    333   // arguement stack to support varargs on the Format string.
    334   //
    335 #if (defined (EFIARM) || defined (EFIAARCH64) || defined (__APPLE__) || defined (__GNUC__))
    336   // It is not legal C code to cast VA_LIST to a pointer. VA_LIST can
    337   // be a structure.
    338   return FALSE;
    339 #else
    340   *Marker = (VA_LIST) (DebugInfo + 1);
    341   *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12);
    342   return TRUE;
    343 #endif
    344 }
    345