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