1/** @file
2  Report status code lib on top of either SerialLib and/or EFI Serial Protocol.
3  Based on PcdStatusCodeUseEfiSerial & PcdStatusCodeUseHardSerial settings
4
5  There is just a single runtime memory buffer that contans all the data.
6
7  Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
8  Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
9  This program and the accompanying materials
10  are licensed and made available under the terms and conditions of the BSD License
11  which accompanies this distribution.  The full text of the license may be found at
12  http://opensource.org/licenses/bsd-license.php
13
14  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17
18**/
19
20//////////#include "DxeStatusCode.h"
21
22
23EFI_SERIAL_IO_PROTOCOL *mSerialIoProtocol = NULL;
24
25
26EFI_STATUS
27LibReportStatusCode (
28  IN EFI_STATUS_CODE_TYPE     CodeType,
29  IN EFI_STATUS_CODE_VALUE    Value,
30  IN UINT32                   Instance,
31  IN EFI_GUID                 *CallerId,
32  IN EFI_STATUS_CODE_DATA     *Data OPTIONAL
33  )
34{
35  CHAR8           *Filename;
36  CHAR8           *Description;
37  CHAR8           *Format;
38  CHAR8           Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
39  UINT32          ErrorLevel;
40  UINT32          LineNumber;
41  UINTN           CharCount;
42  VA_LIST         Marker;
43  EFI_DEBUG_INFO  *DebugInfo;
44  EFI_TPL         CurrentTpl;
45
46
47  if (FeaturePcdGet (PcdStatusCodeUseEfiSerial)) {
48    if (EfiAtRuntime ()) {
49      return EFI_DEVICE_ERROR;
50    }
51    CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
52    gBS->RestoreTPL (CurrentTpl);
53
54    if (CurrentTpl > EFI_TPL_CALLBACK ) {
55      return EFI_DEVICE_ERROR;
56    }
57  }
58
59  Buffer[0] = '\0';
60
61  if (Data != NULL &&
62      ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
63    //
64    // Print ASSERT() information into output buffer.
65    //
66    CharCount = AsciiSPrint (
67                  Buffer,
68                  EFI_STATUS_CODE_DATA_MAX_SIZE,
69                  "\n\rDXE_ASSERT!: %a (%d): %a\n\r",
70                  Filename,
71                  LineNumber,
72                  Description
73                  );
74  } else if (Data != NULL &&
75             ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
76    //
77    // Print DEBUG() information into output buffer.
78    //
79    CharCount = AsciiVSPrint (
80                  Buffer,
81                  EFI_STATUS_CODE_DATA_MAX_SIZE,
82                  Format,
83                  Marker
84                  );
85  } else if (Data != NULL &&
86             CompareGuid (&Data->Type, &gEfiStatusCodeSpecificDataGuid) &&
87             (CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
88    //
89    // Print specific data into output buffer.
90    //
91    DebugInfo = (EFI_DEBUG_INFO *) (Data + 1);
92    Marker    = (VA_LIST) (DebugInfo + 1);
93    Format    = (CHAR8 *) (((UINT64 *) (DebugInfo + 1)) + 12);
94
95    CharCount = AsciiVSPrint (Buffer, EFI_STATUS_CODE_DATA_MAX_SIZE, Format, Marker);
96  } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {
97    //
98    // Print ERROR information into output buffer.
99    //
100    CharCount = AsciiSPrint (
101                  Buffer,
102                  EFI_STATUS_CODE_DATA_MAX_SIZE,
103                  "ERROR: C%x:V%x I%x",
104                  CodeType,
105                  Value,
106                  Instance
107                  );
108
109    //
110    // Make sure we don't try to print values that weren't
111    // intended to be printed, especially NULL GUID pointers.
112    //
113
114    if (CallerId != NULL) {
115      CharCount += AsciiSPrint (
116                     &Buffer[CharCount - 1],
117                     (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
118                     " %g",
119                     CallerId
120                     );
121    }
122
123    if (Data != NULL) {
124      CharCount += AsciiSPrint (
125                     &Buffer[CharCount - 1],
126                     (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
127                     " %x",
128                     Data
129                     );
130    }
131
132    CharCount += AsciiSPrint (
133                   &Buffer[CharCount - 1],
134                   (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
135                   "\n\r"
136                   );
137  } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {
138    CharCount = AsciiSPrint (
139                  Buffer,
140                  EFI_STATUS_CODE_DATA_MAX_SIZE,
141                  "PROGRESS CODE: V%x I%x\n\r",
142                  Value,
143                  Instance
144                  );
145  } else {
146    CharCount = AsciiSPrint (
147                  Buffer,
148                  EFI_STATUS_CODE_DATA_MAX_SIZE,
149                  "Undefined: C%x:V%x I%x\n\r",
150                  CodeType,
151                  Value,
152                  Instance
153                  );
154  }
155
156
157  if (FeaturePcdGet (PcdStatusCodeUseHardSerial)) {
158    //
159    // Callout to SerialPort Lib function to do print.
160    //
161    SerialPortWrite ((UINT8 *) Buffer, CharCount);
162  }
163  if (FeaturePcdGet (PcdStatusCodeUseEfiSerial)) {
164    if (mSerialIoProtocol == NULL) {
165      gBS->LocateProtocol (&gEfiSerialIoProtocolGuid, NULL, (VOID **) &mSerialIoProtocol);
166    }
167
168    if (mSerialIoProtocol == NULL) {
169      mSerialIoProtocol->Write (
170        mSerialIoProtocol,
171        &CharCount,
172        Buffer
173        );
174    }
175  }
176
177  return EFI_SUCCESS;
178}
179
180
181VOID
182LibReportStatusCodeVirtualAddressChangeEvent (
183  VOID
184  )
185{
186  return;
187}
188
189VOID
190LibReportStatusCodeInitialize (
191  VOID
192  )
193{
194  return;
195}
196
197
198
199