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