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