1 /** @file
2   OEM hook status code library functions with no library constructor/destructor
3 
4   Copyright (c) 2006 - 2013, 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   Module Name:  Nt32OemHookStatusCodeLib.c
14 
15 **/
16 
17 //
18 // The package level header files this module uses
19 //
20 #include <WinNtPeim.h>
21 
22 //
23 // The protocols, PPI and GUID defintions for this module
24 //
25 #include <Guid/StatusCodeDataTypeId.h>
26 #include <Guid/StatusCodeDataTypeDebug.h>
27 #include <Ppi/NtThunk.h>
28 //
29 // The Library classes this module consumes
30 //
31 #include <Library/OemHookStatusCodeLib.h>
32 #include <Library/DebugLib.h>
33 #include <Library/PrintLib.h>
34 #include <Library/BaseMemoryLib.h>
35 #include <Library/ReportStatusCodeLib.h>
36 #include <Library/PeiServicesLib.h>
37 
38 //
39 // Cache of WinNtThunk protocol
40 //
41 EFI_WIN_NT_THUNK_PROTOCOL   *mWinNt;
42 
43 //
44 // Cache of standard output handle .
45 //
46 HANDLE                      mStdOut;
47 
48 /**
49 
50   Initialize OEM status code device .
51 
52   @return    Always return EFI_SUCCESS.
53 
54 **/
55 EFI_STATUS
56 EFIAPI
OemHookStatusCodeInitialize(VOID)57 OemHookStatusCodeInitialize (
58   VOID
59   )
60 {
61   PEI_NT_THUNK_PPI  *NtThunkPpi;
62   EFI_STATUS        Status;
63 
64 
65   //
66   // Locate NtThunkPpi for retrieving standard output handle
67   //
68   Status = PeiServicesLocatePpi (
69               &gPeiNtThunkPpiGuid,
70               0,
71               NULL,
72               (VOID **) &NtThunkPpi
73               );
74 
75   ASSERT_EFI_ERROR (Status);
76 
77   mWinNt  = (EFI_WIN_NT_THUNK_PROTOCOL *) NtThunkPpi->NtThunk ();
78 
79 
80   //
81   // Cache standard output handle.
82   //
83   mStdOut = mWinNt->GetStdHandle (STD_OUTPUT_HANDLE);
84 
85   return EFI_SUCCESS;
86 }
87 
88 /**
89   Report status code to OEM device.
90 
91   @param  CodeType      Indicates the type of status code being reported.  Type EFI_STATUS_CODE_TYPE is defined in "Related Definitions" below.
92 
93   @param  Value         Describes the current status of a hardware or software entity.
94                         This included information about the class and subclass that is used to classify the entity
95                         as well as an operation.  For progress codes, the operation is the current activity.
96                         For error codes, it is the exception.  For debug codes, it is not defined at this time.
97                         Type EFI_STATUS_CODE_VALUE is defined in "Related Definitions" below.
98                         Specific values are discussed in the Intel? Platform Innovation Framework for EFI Status Code Specification.
99 
100   @param  Instance      The enumeration of a hardware or software entity within the system.
101                         A system may contain multiple entities that match a class/subclass pairing.
102                         The instance differentiates between them.  An instance of 0 indicates that instance information is unavailable,
103                         not meaningful, or not relevant.  Valid instance numbers start with 1.
104 
105 
106   @param  CallerId      This optional parameter may be used to identify the caller.
107                         This parameter allows the status code driver to apply different rules to different callers.
108                         Type EFI_GUID is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
109 
110 
111   @param  Data          This optional parameter may be used to pass additional data
112 
113   @return               The function always return EFI_SUCCESS.
114 
115 **/
116 EFI_STATUS
117 EFIAPI
OemHookStatusCodeReport(IN EFI_STATUS_CODE_TYPE CodeType,IN EFI_STATUS_CODE_VALUE Value,IN UINT32 Instance,IN EFI_GUID * CallerId,OPTIONAL IN EFI_STATUS_CODE_DATA * Data OPTIONAL)118 OemHookStatusCodeReport (
119   IN EFI_STATUS_CODE_TYPE     CodeType,
120   IN EFI_STATUS_CODE_VALUE    Value,
121   IN UINT32                   Instance,
122   IN EFI_GUID                 *CallerId, OPTIONAL
123   IN EFI_STATUS_CODE_DATA     *Data      OPTIONAL
124   )
125 {
126   CHAR8           *Filename;
127   CHAR8           *Description;
128   CHAR8           *Format;
129   CHAR8           Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
130   UINT32          ErrorLevel;
131   UINT32          LineNumber;
132   UINTN           CharCount;
133   BASE_LIST       Marker;
134 
135   Buffer[0] = '\0';
136 
137   if (Data != NULL &&
138       ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
139     //
140     // Print ASSERT() information into output buffer.
141     //
142     CharCount = AsciiSPrint (
143                   Buffer,
144                   sizeof (Buffer),
145                   "\n\rASSERT!: %a (%d): %a\n\r",
146                   Filename,
147                   LineNumber,
148                   Description
149                   );
150 
151     //
152     // Callout to standard output.
153     //
154     mWinNt->WriteFile (
155               mStdOut,
156               Buffer,
157               (DWORD)CharCount,
158               (LPDWORD)&CharCount,
159               NULL
160               );
161 
162     return EFI_SUCCESS;
163 
164   } else if (Data != NULL &&
165              ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
166     //
167     // Print DEBUG() information into output buffer.
168     //
169     CharCount = AsciiBSPrint (
170                   Buffer,
171                   sizeof (Buffer),
172                   Format,
173                   Marker
174                   );
175   } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {
176     //
177     // Print ERROR information into output buffer.
178     //
179     CharCount = AsciiSPrint (
180                   Buffer,
181                   sizeof (Buffer),
182                   "ERROR: C%x:V%x I%x",
183                   CodeType,
184                   Value,
185                   Instance
186                   );
187 
188     //
189     // Make sure we don't try to print values that weren't intended to be printed, especially NULL GUID pointers.
190     //
191 
192     if (CallerId != NULL) {
193       CharCount += AsciiSPrint (
194                      &Buffer[CharCount - 1],
195                      (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)),
196                      " %g",
197                      CallerId
198                      );
199     }
200 
201     if (Data != NULL) {
202       CharCount += AsciiSPrint (
203                      &Buffer[CharCount - 1],
204                      (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)),
205                      " %p",
206                      Data
207                      );
208     }
209 
210     CharCount += AsciiSPrint (
211                    &Buffer[CharCount - 1],
212                    (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)),
213                    "\n\r"
214                    );
215   } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {
216     CharCount = AsciiSPrint (
217                   Buffer,
218                   sizeof (Buffer),
219                   "PROGRESS CODE: V%x I%x\n\r",
220                   Value,
221                   Instance
222                   );
223   } else {
224     CharCount = AsciiSPrint (
225                   Buffer,
226                   sizeof (Buffer),
227                   "Undefined: C%x:V%x I%x\n\r",
228                   CodeType,
229                   Value,
230                   Instance
231                   );
232   }
233 
234   //
235   // Callout to standard output.
236   //
237   mWinNt->WriteFile (
238             mStdOut,
239             Buffer,
240             (DWORD)CharCount,
241             (LPDWORD)&CharCount,
242             NULL
243             );
244 
245   return EFI_SUCCESS;
246 }
247 
248