PageRenderTime 37ms CodeModel.GetById 8ms RepoModel.GetById 1ms app.codeStats 0ms

/EmbeddedPkg/Library/PrePiLib/ReportStatusCode.c

https://bitbucket.org/incubaid/edk2
C | 327 lines | 177 code | 46 blank | 104 comment | 33 complexity | fb31de8f836422b4cfbdc3734726b25f MD5 | raw file
  1. /** @file
  2. Library that helps implement monolithic PEI
  3. Copyright (c) 2008 - 2009, Apple Inc. 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. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  10. **/
  11. #include <PrePi.h>
  12. #include <Library/ReportStatusCodeLib.h>
  13. #include <Library/SerialPortLib.h>
  14. #include <Library/PrintLib.h>
  15. #include <Protocol/StatusCode.h>
  16. #include <Guid/StatusCodeDataTypeId.h>
  17. #include <Guid/StatusCodeDataTypeDebug.h>
  18. #include <FrameworkPei.h>
  19. #define EFI_STATUS_CODE_DATA_MAX_SIZE 200
  20. EFI_STATUS
  21. EFIAPI
  22. SerialReportStatusCode (
  23. IN EFI_STATUS_CODE_TYPE CodeType,
  24. IN EFI_STATUS_CODE_VALUE Value,
  25. IN UINT32 Instance,
  26. IN CONST EFI_GUID *CallerId,
  27. IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
  28. );
  29. EFI_STATUS_CODE_PROTOCOL gStatusCode = {
  30. (EFI_REPORT_STATUS_CODE)SerialReportStatusCode
  31. };
  32. /**
  33. Extracts ASSERT() information from a status code structure.
  34. Converts the status code specified by CodeType, Value, and Data to the ASSERT()
  35. arguments specified by Filename, Description, and LineNumber. If CodeType is
  36. an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and
  37. Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract
  38. Filename, Description, and LineNumber from the optional data area of the
  39. status code buffer specified by Data. The optional data area of Data contains
  40. a Null-terminated ASCII string for the FileName, followed by a Null-terminated
  41. ASCII string for the Description, followed by a 32-bit LineNumber. If the
  42. ASSERT() information could be extracted from Data, then return TRUE.
  43. Otherwise, FALSE is returned.
  44. If Data is NULL, then ASSERT().
  45. If Filename is NULL, then ASSERT().
  46. If Description is NULL, then ASSERT().
  47. If LineNumber is NULL, then ASSERT().
  48. @param CodeType The type of status code being converted.
  49. @param Value The status code value being converted.
  50. @param Data Pointer to status code data buffer.
  51. @param Filename Pointer to the source file name that generated the ASSERT().
  52. @param Description Pointer to the description of the ASSERT().
  53. @param LineNumber Pointer to source line number that generated the ASSERT().
  54. @retval TRUE The status code specified by CodeType, Value, and Data was
  55. converted ASSERT() arguments specified by Filename, Description,
  56. and LineNumber.
  57. @retval FALSE The status code specified by CodeType, Value, and Data could
  58. not be converted to ASSERT() arguments.
  59. **/
  60. BOOLEAN
  61. EFIAPI
  62. ReportStatusCodeExtractAssertInfo (
  63. IN EFI_STATUS_CODE_TYPE CodeType,
  64. IN EFI_STATUS_CODE_VALUE Value,
  65. IN CONST EFI_STATUS_CODE_DATA *Data,
  66. OUT CHAR8 **Filename,
  67. OUT CHAR8 **Description,
  68. OUT UINT32 *LineNumber
  69. )
  70. {
  71. EFI_DEBUG_ASSERT_DATA *AssertData;
  72. ASSERT (Data != NULL);
  73. ASSERT (Filename != NULL);
  74. ASSERT (Description != NULL);
  75. ASSERT (LineNumber != NULL);
  76. if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) &&
  77. ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) &&
  78. ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) {
  79. AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1);
  80. *Filename = (CHAR8 *)(AssertData + 1);
  81. *Description = *Filename + AsciiStrLen (*Filename) + 1;
  82. *LineNumber = AssertData->LineNumber;
  83. return TRUE;
  84. }
  85. return FALSE;
  86. }
  87. /**
  88. Extracts DEBUG() information from a status code structure.
  89. Converts the status code specified by Data to the DEBUG() arguments specified
  90. by ErrorLevel, Marker, and Format. If type GUID in Data is
  91. EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and
  92. Format from the optional data area of the status code buffer specified by Data.
  93. The optional data area of Data contains a 32-bit ErrorLevel followed by Marker
  94. which is 12 UINTN parameters, followed by a Null-terminated ASCII string for
  95. the Format. If the DEBUG() information could be extracted from Data, then
  96. return TRUE. Otherwise, FALSE is returned.
  97. If Data is NULL, then ASSERT().
  98. If ErrorLevel is NULL, then ASSERT().
  99. If Marker is NULL, then ASSERT().
  100. If Format is NULL, then ASSERT().
  101. @param Data Pointer to status code data buffer.
  102. @param ErrorLevel Pointer to error level mask for a debug message.
  103. @param Marker Pointer to the variable argument list associated with Format.
  104. @param Format Pointer to a Null-terminated ASCII format string of a
  105. debug message.
  106. @retval TRUE The status code specified by Data was converted DEBUG() arguments
  107. specified by ErrorLevel, Marker, and Format.
  108. @retval FALSE The status code specified by Data could not be converted to
  109. DEBUG() arguments.
  110. **/
  111. BOOLEAN
  112. EFIAPI
  113. ReportStatusCodeExtractDebugInfo (
  114. IN CONST EFI_STATUS_CODE_DATA *Data,
  115. OUT UINT32 *ErrorLevel,
  116. OUT BASE_LIST *Marker,
  117. OUT CHAR8 **Format
  118. )
  119. {
  120. EFI_DEBUG_INFO *DebugInfo;
  121. ASSERT (Data != NULL);
  122. ASSERT (ErrorLevel != NULL);
  123. ASSERT (Marker != NULL);
  124. ASSERT (Format != NULL);
  125. //
  126. // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE
  127. //
  128. if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) {
  129. return FALSE;
  130. }
  131. //
  132. // Retrieve the debug information from the status code record
  133. //
  134. DebugInfo = (EFI_DEBUG_INFO *)(Data + 1);
  135. *ErrorLevel = DebugInfo->ErrorLevel;
  136. //
  137. // The first 12 * UINTN bytes of the string are really an
  138. // argument stack to support varargs on the Format string.
  139. //
  140. *Marker = (BASE_LIST) (DebugInfo + 1);
  141. *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12);
  142. return TRUE;
  143. }
  144. EFI_STATUS
  145. EFIAPI
  146. SerialReportStatusCode (
  147. IN EFI_STATUS_CODE_TYPE CodeType,
  148. IN EFI_STATUS_CODE_VALUE Value,
  149. IN UINT32 Instance,
  150. IN CONST EFI_GUID *CallerId,
  151. IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
  152. )
  153. {
  154. CHAR8 *Filename;
  155. CHAR8 *Description;
  156. CHAR8 *Format;
  157. CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
  158. UINT32 ErrorLevel;
  159. UINT32 LineNumber;
  160. UINTN CharCount;
  161. BASE_LIST Marker;
  162. EFI_DEBUG_INFO *DebugInfo;
  163. Buffer[0] = '\0';
  164. if (Data != NULL &&
  165. ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
  166. //
  167. // Print ASSERT() information into output buffer.
  168. //
  169. CharCount = AsciiSPrint (
  170. Buffer,
  171. EFI_STATUS_CODE_DATA_MAX_SIZE,
  172. "\n\rASSERT!: %a (%d): %a\n\r",
  173. Filename,
  174. LineNumber,
  175. Description
  176. );
  177. //
  178. // Callout to standard output.
  179. //
  180. SerialPortWrite ((UINT8 *)Buffer, CharCount);
  181. return EFI_SUCCESS;
  182. } else if (Data != NULL &&
  183. ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
  184. //
  185. // Print DEBUG() information into output buffer.
  186. //
  187. CharCount = AsciiBSPrint (
  188. Buffer,
  189. EFI_STATUS_CODE_DATA_MAX_SIZE,
  190. Format,
  191. Marker
  192. );
  193. } else if (Data != NULL &&
  194. CompareGuid (&Data->Type, &gEfiStatusCodeSpecificDataGuid) &&
  195. (CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
  196. //
  197. // Print specific data into output buffer.
  198. //
  199. DebugInfo = (EFI_DEBUG_INFO *) (Data + 1);
  200. Marker = (BASE_LIST) (DebugInfo + 1);
  201. Format = (CHAR8 *) (((UINT64 *) (DebugInfo + 1)) + 12);
  202. CharCount = AsciiBSPrint (Buffer, EFI_STATUS_CODE_DATA_MAX_SIZE, Format, Marker);
  203. } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {
  204. //
  205. // Print ERROR information into output buffer.
  206. //
  207. CharCount = AsciiSPrint (
  208. Buffer,
  209. EFI_STATUS_CODE_DATA_MAX_SIZE,
  210. "ERROR: C%x:V%x I%x",
  211. CodeType,
  212. Value,
  213. Instance
  214. );
  215. //
  216. // Make sure we don't try to print values that weren't intended to be printed, especially NULL GUID pointers.
  217. //
  218. if (CallerId != NULL) {
  219. CharCount += AsciiSPrint (
  220. &Buffer[CharCount - 1],
  221. (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
  222. " %g",
  223. CallerId
  224. );
  225. }
  226. if (Data != NULL) {
  227. CharCount += AsciiSPrint (
  228. &Buffer[CharCount - 1],
  229. (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
  230. " %x",
  231. Data
  232. );
  233. }
  234. CharCount += AsciiSPrint (
  235. &Buffer[CharCount - 1],
  236. (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
  237. "\n\r"
  238. );
  239. } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {
  240. CharCount = AsciiSPrint (
  241. Buffer,
  242. EFI_STATUS_CODE_DATA_MAX_SIZE,
  243. "PROGRESS CODE: V%x I%x\n\r",
  244. Value,
  245. Instance
  246. );
  247. } else {
  248. CharCount = AsciiSPrint (
  249. Buffer,
  250. EFI_STATUS_CODE_DATA_MAX_SIZE,
  251. "Undefined: C%x:V%x I%x\n\r",
  252. CodeType,
  253. Value,
  254. Instance
  255. );
  256. }
  257. SerialPortWrite ((UINT8 *)Buffer, CharCount);
  258. return EFI_SUCCESS;
  259. }
  260. VOID
  261. EFIAPI
  262. AddDxeCoreReportStatusCodeCallback (
  263. VOID
  264. )
  265. {
  266. BuildGuidDataHob (&gEfiStatusCodeRuntimeProtocolGuid, &gStatusCode, sizeof(VOID *));
  267. }