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