1/** @file
2  Serial I/O status code reporting worker.
3
4  Copyright (c) 2009 - 2014, 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 "StatusCodeHandlerSmm.h"
16
17/**
18  Convert status code value and extended data to readable ASCII string, send string to serial I/O device.
19
20  @param  CodeType         Indicates the type of status code being reported.
21  @param  Value            Describes the current status of a hardware or software entity.
22                           This included information about the class and subclass that is used to
23                           classify the entity as well as an operation.
24  @param  Instance         The enumeration of a hardware or software entity within
25                           the system. Valid instance numbers start with 1.
26  @param  CallerId         This optional parameter may be used to identify the caller.
27                           This parameter allows the status code driver to apply different rules to
28                           different callers.
29  @param  Data             This optional parameter may be used to pass additional data.
30
31  @retval EFI_SUCCESS      Status code reported to serial I/O successfully.
32  @retval EFI_DEVICE_ERROR EFI serial device cannot work after ExitBootService() is called.
33  @retval EFI_DEVICE_ERROR EFI serial device cannot work with TPL higher than TPL_CALLBACK.
34
35**/
36EFI_STATUS
37EFIAPI
38SerialStatusCodeReportWorker (
39  IN EFI_STATUS_CODE_TYPE     CodeType,
40  IN EFI_STATUS_CODE_VALUE    Value,
41  IN UINT32                   Instance,
42  IN EFI_GUID                 *CallerId,
43  IN EFI_STATUS_CODE_DATA     *Data OPTIONAL
44  )
45{
46  CHAR8           *Filename;
47  CHAR8           *Description;
48  CHAR8           *Format;
49  CHAR8           Buffer[MAX_DEBUG_MESSAGE_LENGTH];
50  UINT32          ErrorLevel;
51  UINT32          LineNumber;
52  UINTN           CharCount;
53  BASE_LIST       Marker;
54
55  Buffer[0] = '\0';
56
57  if (Data != NULL &&
58      ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
59    //
60    // Print ASSERT() information into output buffer.
61    //
62    CharCount = AsciiSPrint (
63                  Buffer,
64                  sizeof (Buffer),
65                  "\n\rDXE_ASSERT!: %a (%d): %a\n\r",
66                  Filename,
67                  LineNumber,
68                  Description
69                  );
70  } else if (Data != NULL &&
71             ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
72    //
73    // Print DEBUG() information into output buffer.
74    //
75    CharCount = AsciiBSPrint (
76                  Buffer,
77                  sizeof (Buffer),
78                  Format,
79                  Marker
80                  );
81  } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {
82    //
83    // Print ERROR information into output buffer.
84    //
85    CharCount = AsciiSPrint (
86                  Buffer,
87                  sizeof (Buffer),
88                  "ERROR: C%08x:V%08x I%x",
89                  CodeType,
90                  Value,
91                  Instance
92                  );
93    ASSERT (CharCount > 0);
94
95    if (CallerId != NULL) {
96      CharCount += AsciiSPrint (
97                     &Buffer[CharCount],
98                     (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)),
99                     " %g",
100                     CallerId
101                     );
102    }
103
104    if (Data != NULL) {
105      CharCount += AsciiSPrint (
106                     &Buffer[CharCount],
107                     (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)),
108                     " %x",
109                     Data
110                     );
111    }
112
113    CharCount += AsciiSPrint (
114                   &Buffer[CharCount],
115                   (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)),
116                   "\n\r"
117                   );
118  } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {
119    //
120    // Print PROGRESS information into output buffer.
121    //
122    CharCount = AsciiSPrint (
123                  Buffer,
124                  sizeof (Buffer),
125                  "PROGRESS CODE: V%08x I%x\n\r",
126                  Value,
127                  Instance
128                  );
129  } else if (Data != NULL &&
130             CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeStringGuid) &&
131             ((EFI_STATUS_CODE_STRING_DATA *) Data)->StringType == EfiStringAscii) {
132    //
133    // EFI_STATUS_CODE_STRING_DATA
134    //
135    CharCount = AsciiSPrint (
136                  Buffer,
137                  sizeof (Buffer),
138                  "%a\n\r",
139                  ((EFI_STATUS_CODE_STRING_DATA *) Data)->String.Ascii
140                  );
141  } else {
142    //
143    // Code type is not defined.
144    //
145    CharCount = AsciiSPrint (
146                  Buffer,
147                  sizeof (Buffer),
148                  "Undefined: C%08x:V%08x I%x\n\r",
149                  CodeType,
150                  Value,
151                  Instance
152                  );
153  }
154
155  //
156  // Call SerialPort Lib function to do print.
157  //
158  SerialPortWrite ((UINT8 *) Buffer, CharCount);
159
160  return EFI_SUCCESS;
161}
162
163