SmmRuntimeDxeSupport.c revision e5516b494a21cc8ca59dec0a2754f1c1ed31bb7e
1/** @file
2  Report Status Code Library for DXE Phase.
3
4  Copyright (c) 2006 - 2007, Intel Corporation<BR>
5  All rights reserved. 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 "ReportStatusCodeLibInternal.h"
16
17//
18// Resources need by SMM runtime instance
19//
20#include <Library/OemHookStatusCodeLib.h>
21#include <Protocol/SmmBase.h>
22
23STATIC
24EFI_EVENT             mVirtualAddressChangeEvent;
25
26STATIC
27EFI_EVENT             mExitBootServicesEvent;
28
29STATIC
30EFI_STATUS_CODE_DATA  *mStatusCodeData;
31
32STATIC
33EFI_SMM_BASE_PROTOCOL *mSmmBase;
34
35STATIC
36BOOLEAN               mHaveExitedBootServices = FALSE;
37
38/**
39  Locatet he report status code service.
40
41  @return     EFI_REPORT_STATUS_CODE    function point to
42              ReportStatusCode.
43**/
44EFI_REPORT_STATUS_CODE
45InternalGetReportStatusCode (
46  VOID
47  )
48{
49  EFI_STATUS_CODE_PROTOCOL  *StatusCodeProtocol;
50  BOOLEAN                   InSmm;
51  EFI_STATUS                Status;
52
53  if (mSmmBase) {
54    mSmmBase->InSmm (mSmmBase, &InSmm);
55    if (InSmm) {
56      return (EFI_REPORT_STATUS_CODE) OemHookStatusCodeReport;
57    }
58  }
59  if (gRT->Hdr.Revision < 0x20000) {
60    return ((FRAMEWORK_EFI_RUNTIME_SERVICES*)gRT)->ReportStatusCode;
61  } else if (!mHaveExitedBootServices) {
62    Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol);
63    if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) {
64      return StatusCodeProtocol->ReportStatusCode;
65    }
66  }
67
68  return NULL;
69}
70
71
72/**
73  Fixup internal report status code protocol interface.
74
75  @param[in]    Event   The Event that is being processed
76  @param[in]    Context Event Context
77**/
78STATIC
79VOID
80EFIAPI
81ReportStatusCodeLibVirtualAddressChange (
82  IN EFI_EVENT        Event,
83  IN VOID             *Context
84  )
85{
86  if (NULL != mReportStatusCode) {
87    gRT->ConvertPointer (0, (VOID **) &mReportStatusCode);
88  }
89  if (NULL != mSmmBase) {
90    gRT->ConvertPointer (0, (VOID **) &mSmmBase);
91  }
92  gRT->ConvertPointer (0, (VOID **) &mStatusCodeData);
93  gRT->ConvertPointer (0, (VOID **) &gRT);
94}
95
96/**
97  Updatet the In Runtime Indicator.
98
99  @param[in]    Event   The Event that is being processed
100  @param[in]    Context Event Context
101**/
102STATIC
103VOID
104EFIAPI
105ReportStatusCodeLibExitBootServices (
106  IN EFI_EVENT        Event,
107  IN VOID             *Context
108  )
109{
110  mHaveExitedBootServices = TRUE;
111}
112
113/**
114  Intialize Report Status Code Lib.
115
116  @param[in]  ImageHandle   The firmware allocated handle for the EFI image.
117  @param[in]  SystemTable   A pointer to the EFI System Table.
118
119  @return     EFI_STATUS    always returns EFI_SUCCESS.
120**/
121EFI_STATUS
122EFIAPI
123ReportStatusCodeLibConstruct (
124  IN EFI_HANDLE           ImageHandle,
125  IN EFI_SYSTEM_TABLE     *SystemTable
126  )
127{
128  EFI_STATUS    Status;
129  BOOLEAN       InSmm;
130
131  //
132  // SMM driver depends on the SMM BASE protocol.
133  // the SMM driver must be success to locate protocol.
134  //
135  ASSERT (gBS != NULL);
136  Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase);
137  if (!EFI_ERROR (Status)) {
138    mSmmBase->InSmm (mSmmBase, &InSmm);
139    if (InSmm) {
140      Status = mSmmBase->SmmAllocatePool (
141                           mSmmBase,
142                           EfiRuntimeServicesData,
143                           sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE,
144                           (VOID **) &mStatusCodeData
145                           );
146      ASSERT_EFI_ERROR (Status);
147      OemHookStatusCodeInitialize ();
148      return EFI_SUCCESS;
149    }
150  }
151
152  gBS->AllocatePool (EfiRuntimeServicesData, sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE, (VOID **)&mStatusCodeData);
153  ASSERT (NULL != mStatusCodeData);
154  //
155  // Cache the report status code service
156  //
157  mReportStatusCode = InternalGetReportStatusCode ();
158
159  //
160  // Register the call back of virtual address change
161  //
162  Status = gBS->CreateEvent (
163                  EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
164                  TPL_NOTIFY,
165                  ReportStatusCodeLibVirtualAddressChange,
166                  NULL,
167                  &mVirtualAddressChangeEvent
168                  );
169  ASSERT_EFI_ERROR (Status);
170
171
172  //
173  // Register the call back of virtual address change
174  //
175  Status = gBS->CreateEvent (
176                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
177                  TPL_NOTIFY,
178                  ReportStatusCodeLibExitBootServices,
179                  NULL,
180                  &mExitBootServicesEvent
181                  );
182  ASSERT_EFI_ERROR (Status);
183
184  return Status;
185}
186
187
188EFI_STATUS
189EFIAPI
190ReportStatusCodeLibDestruct (
191  IN EFI_HANDLE        ImageHandle,
192  IN EFI_SYSTEM_TABLE  *SystemTable
193  )
194{
195  EFI_STATUS  Status;
196
197  //
198  // Close SetVirtualAddressMap () notify function
199  //
200  ASSERT (gBS != NULL);
201  Status = gBS->CloseEvent (mVirtualAddressChangeEvent);
202  ASSERT_EFI_ERROR (Status);
203  Status = gBS->CloseEvent (mExitBootServicesEvent);
204  ASSERT_EFI_ERROR (Status);
205
206  gBS->FreePool (mStatusCodeData);
207
208  return Status;
209}
210
211
212/**
213  Reports a status code with full parameters.
214
215  The function reports a status code.  If ExtendedData is NULL and ExtendedDataSize
216  is 0, then an extended data buffer is not reported.  If ExtendedData is not
217  NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated.
218  ExtendedData is assumed not have the standard status code header, so this function
219  is responsible for allocating a buffer large enough for the standard header and
220  the extended data passed into this function.  The standard header is filled in
221  with a GUID specified by ExtendedDataGuid.  If ExtendedDataGuid is NULL, then a
222  GUID of gEfiStatusCodeSpecificDatauid is used.  The status code is reported with
223  an instance specified by Instance and a caller ID specified by CallerId.  If
224  CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used.
225
226  ReportStatusCodeEx()must actively prevent recursion.  If ReportStatusCodeEx()
227  is called while processing another any other Report Status Code Library function,
228  then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately.
229
230  If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT().
231  If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT().
232
233  @param  Type              Status code type.
234  @param  Value             Status code value.
235  @param  Instance          Status code instance number.
236  @param  CallerId          Pointer to a GUID that identifies the caller of this
237                            function.  If this parameter is NULL, then a caller
238                            ID of gEfiCallerIdGuid is used.
239  @param  ExtendedDataGuid  Pointer to the GUID for the extended data buffer.
240                            If this parameter is NULL, then a the status code
241                            standard header is filled in with
242                            gEfiStatusCodeSpecificDataGuid.
243  @param  ExtendedData      Pointer to the extended data buffer.  This is an
244                            optional parameter that may be NULL.
245  @param  ExtendedDataSize  The size, in bytes, of the extended data buffer.
246
247  @retval  EFI_SUCCESS           The status code was reported.
248  @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate
249                                 the extended data section if it was specified.
250  @retval  EFI_UNSUPPORTED       Report status code is not supported
251
252**/
253EFI_STATUS
254EFIAPI
255InternalReportStatusCodeEx (
256  IN EFI_STATUS_CODE_TYPE   Type,
257  IN EFI_STATUS_CODE_VALUE  Value,
258  IN UINT32                 Instance,
259  IN CONST EFI_GUID         *CallerId          OPTIONAL,
260  IN CONST EFI_GUID         *ExtendedDataGuid  OPTIONAL,
261  IN CONST VOID             *ExtendedData      OPTIONAL,
262  IN UINTN                  ExtendedDataSize
263  )
264{
265  ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0)));
266  ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0)));
267
268  if (ExtendedDataSize > EFI_STATUS_CODE_DATA_MAX_SIZE) {
269    return EFI_OUT_OF_RESOURCES;
270  }
271
272  //
273  // Fill in the extended data header
274  //
275  mStatusCodeData->HeaderSize = sizeof (EFI_STATUS_CODE_DATA);
276  mStatusCodeData->Size = (UINT16)ExtendedDataSize;
277  if (ExtendedDataGuid == NULL) {
278    ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid;
279  }
280  CopyGuid (&mStatusCodeData->Type, ExtendedDataGuid);
281
282  //
283  // Fill in the extended data buffer
284  //
285  CopyMem (mStatusCodeData + 1, ExtendedData, ExtendedDataSize);
286
287  //
288  // Report the status code
289  //
290  if (CallerId == NULL) {
291    CallerId = &gEfiCallerIdGuid;
292  }
293  return  InternalReportStatusCode (Type, Value, Instance, CallerId, mStatusCodeData);
294}
295