]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/SmmRuntimeDxeReportStatusCodeLib/SmmRuntimeDxeSupport.c
70ae09228db427b22b7542d2e9c54905e2547812
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / EdkIIGlueLib / Library / SmmRuntimeDxeReportStatusCodeLib / SmmRuntimeDxeSupport.c
1 /*++
2
3 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12
13 Module Name:
14
15 SmmRuntimeDxeSupport.c
16
17 Abstract:
18
19 Report Status Code Library for DXE Phase.
20
21 --*/
22
23 #include "ReportStatusCodeLibInternal.h"
24 #include EFI_PROTOCOL_DEFINITION (SmmStatusCode)
25
26 EFI_EVENT mVirtualAddressChangeEvent;
27
28 EFI_EVENT mExitBootServicesEvent;
29
30 EFI_STATUS_CODE_DATA *mStatusCodeData;
31
32 BOOLEAN mInSmm;
33
34 EFI_SMM_BASE_PROTOCOL *mSmmBase;
35
36 EFI_RUNTIME_SERVICES *mRTSmmRuntimeDxeReportStatusCodeLib;
37
38 BOOLEAN mHaveExitedBootServices = FALSE;
39
40 EFI_SMM_STATUS_CODE_PROTOCOL *mSmmStatusCode;
41
42 VOID
43 SmmStatusCodeInitialize (
44 VOID
45 )
46 {
47 EFI_STATUS Status;
48
49 Status = gBS->LocateProtocol (&gEfiSmmStatusCodeProtocolGuid, NULL, (VOID **) &mSmmStatusCode);
50 if (EFI_ERROR (Status)) {
51 mSmmStatusCode = NULL;
52 }
53 }
54
55 EFI_STATUS
56 SmmStatusCodeReport (
57 IN EFI_STATUS_CODE_TYPE Type,
58 IN EFI_STATUS_CODE_VALUE Value,
59 IN UINT32 Instance,
60 IN EFI_GUID *CallerId OPTIONAL,
61 IN EFI_STATUS_CODE_DATA *Data OPTIONAL
62 )
63 {
64 if (mSmmStatusCode != NULL) {
65 (mSmmStatusCode->ReportStatusCode) (mSmmStatusCode, Type, Value, Instance, CallerId, Data);
66 }
67 return EFI_SUCCESS;
68 }
69
70 /**
71 Locate he report status code service.
72
73 @return EFI_REPORT_STATUS_CODE function point to
74 ReportStatusCode.
75 **/
76 EFI_REPORT_STATUS_CODE
77 InternalGetReportStatusCode (
78 VOID
79 )
80 {
81 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
82 EFI_STATUS_CODE_PROTOCOL *StatusCodeProtocol;
83 EFI_STATUS Status;
84 #endif
85
86 if (mInSmm) {
87 return (EFI_REPORT_STATUS_CODE) SmmStatusCodeReport;
88 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
89 } else if (!mHaveExitedBootServices) {
90 //
91 // Check gBS just in case. ReportStatusCode is called before gBS is initialized.
92 //
93 if (gBS != NULL) {
94 Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol);
95 if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) {
96 return StatusCodeProtocol->ReportStatusCode;
97 }
98 }
99 }
100 #elif (TIANO_RELEASE_VERSION != 0)
101 } else if (mRTSmmRuntimeDxeReportStatusCodeLib != NULL) {
102 return mRTSmmRuntimeDxeReportStatusCodeLib->ReportStatusCode;
103 }
104 #endif
105
106 return NULL;
107 }
108
109
110 /**
111 Fixup internal report status code protocol interface.
112
113 @param[in] Event The Event that is being processed
114 @param[in] Context Event Context
115 **/
116 VOID
117 EFIAPI
118 ReportStatusCodeLibVirtualAddressChange (
119 IN EFI_EVENT Event,
120 IN VOID *Context
121 )
122 {
123 if (NULL != mReportStatusCode) {
124 mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &mReportStatusCode);
125 }
126 mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &mStatusCodeData);
127 mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &mRTSmmRuntimeDxeReportStatusCodeLib);
128 }
129
130 /**
131 Update the In Runtime Indicator.
132
133 @param[in] Event The Event that is being processed
134 @param[in] Context Event Context
135 **/
136 VOID
137 EFIAPI
138 ReportStatusCodeLibExitBootServices (
139 IN EFI_EVENT Event,
140 IN VOID *Context
141 )
142 {
143 //
144 // If mReportStatusCode is NULL, then see if a Status Code Protocol instance is present
145 // in the handle database.
146 //
147 if (mReportStatusCode == NULL) {
148 mReportStatusCode = InternalGetReportStatusCode ();
149 }
150
151 mHaveExitedBootServices = TRUE;
152 }
153
154 /**
155 Intialize Report Status Code Lib.
156
157 @param[in] ImageHandle The firmware allocated handle for the EFI image.
158 @param[in] SystemTable A pointer to the EFI System Table.
159
160 @return EFI_STATUS always returns EFI_SUCCESS.
161 **/
162 EFI_STATUS
163 EFIAPI
164 ReportStatusCodeLibConstruct (
165 IN EFI_HANDLE ImageHandle,
166 IN EFI_SYSTEM_TABLE *SystemTable
167 )
168 {
169 EFI_STATUS Status;
170
171 //
172 // SMM driver depends on the SMM BASE protocol.
173 // the SMM driver must be success to locate protocol.
174 //
175 Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase);
176 if (!EFI_ERROR (Status)) {
177 mSmmBase->InSmm (mSmmBase, &mInSmm);
178 if (mInSmm) {
179 Status = mSmmBase->SmmAllocatePool (
180 mSmmBase,
181 EfiRuntimeServicesData,
182 sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE,
183 (VOID **) &mStatusCodeData
184 );
185 ASSERT_EFI_ERROR (Status);
186 SmmStatusCodeInitialize ();
187 return EFI_SUCCESS;
188 }
189 }
190
191 //
192 // Library should not use the gRT directly, since it
193 // may be converted by other library instance.
194 //
195 mRTSmmRuntimeDxeReportStatusCodeLib = gRT;
196 mInSmm = FALSE;
197
198 (gBS->AllocatePool) (EfiRuntimeServicesData, sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE, (VOID **)&mStatusCodeData);
199 ASSERT (NULL != mStatusCodeData);
200 //
201 // Cache the report status code service
202 //
203 mReportStatusCode = InternalGetReportStatusCode ();
204
205 //
206 // Register the call back of virtual address change
207 //
208 Status = gBS->CreateEvent (
209 EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
210 TPL_NOTIFY,
211 ReportStatusCodeLibVirtualAddressChange,
212 NULL,
213 &mVirtualAddressChangeEvent
214 );
215 ASSERT_EFI_ERROR (Status);
216
217
218 //
219 // Register the call back of exit boot services
220 //
221 Status = gBS->CreateEvent (
222 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
223 TPL_NOTIFY,
224 ReportStatusCodeLibExitBootServices,
225 NULL,
226 &mExitBootServicesEvent
227 );
228 ASSERT_EFI_ERROR (Status);
229
230 return Status;
231 }
232
233 /**
234 Desctructor of library will close events.
235
236 @param ImageHandle callder module's image handle
237 @param SystemTable pointer to EFI system table.
238 @return the status of close event.
239 **/
240 EFI_STATUS
241 EFIAPI
242 ReportStatusCodeLibDestruct (
243 IN EFI_HANDLE ImageHandle,
244 IN EFI_SYSTEM_TABLE *SystemTable
245 )
246 {
247 EFI_STATUS Status;
248
249 if (!mInSmm) {
250 //
251 // Close SetVirtualAddressMap () notify function
252 //
253 ASSERT (gBS != NULL);
254 Status = gBS->CloseEvent (mVirtualAddressChangeEvent);
255 ASSERT_EFI_ERROR (Status);
256 Status = gBS->CloseEvent (mExitBootServicesEvent);
257 ASSERT_EFI_ERROR (Status);
258
259 (gBS->FreePool) (mStatusCodeData);
260 } else {
261 mSmmBase->SmmFreePool (mSmmBase, mStatusCodeData);
262 }
263
264 return EFI_SUCCESS;
265 }
266
267 /**
268 Reports a status code with full parameters.
269
270 The function reports a status code. If ExtendedData is NULL and ExtendedDataSize
271 is 0, then an extended data buffer is not reported. If ExtendedData is not
272 NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated.
273 ExtendedData is assumed not have the standard status code header, so this function
274 is responsible for allocating a buffer large enough for the standard header and
275 the extended data passed into this function. The standard header is filled in
276 with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a
277 GUID of gEfiStatusCodeSpecificDatauid is used. The status code is reported with
278 an instance specified by Instance and a caller ID specified by CallerId. If
279 CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used.
280
281 ReportStatusCodeEx()must actively prevent recursion. If ReportStatusCodeEx()
282 is called while processing another any other Report Status Code Library function,
283 then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately.
284
285 If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT().
286 If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT().
287
288 @param Type Status code type.
289 @param Value Status code value.
290 @param Instance Status code instance number.
291 @param CallerId Pointer to a GUID that identifies the caller of this
292 function. If this parameter is NULL, then a caller
293 ID of gEfiCallerIdGuid is used.
294 @param ExtendedDataGuid Pointer to the GUID for the extended data buffer.
295 If this parameter is NULL, then a the status code
296 standard header is filled in with
297 gEfiStatusCodeSpecificDataGuid.
298 @param ExtendedData Pointer to the extended data buffer. This is an
299 optional parameter that may be NULL.
300 @param ExtendedDataSize The size, in bytes, of the extended data buffer.
301
302 @retval EFI_SUCCESS The status code was reported.
303 @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate
304 the extended data section if it was specified.
305 @retval EFI_UNSUPPORTED Report status code is not supported
306
307 **/
308 EFI_STATUS
309 EFIAPI
310 InternalReportStatusCodeEx (
311 IN EFI_STATUS_CODE_TYPE Type,
312 IN EFI_STATUS_CODE_VALUE Value,
313 IN UINT32 Instance,
314 IN CONST EFI_GUID *CallerId OPTIONAL,
315 IN CONST EFI_GUID *ExtendedDataGuid OPTIONAL,
316 IN CONST VOID *ExtendedData OPTIONAL,
317 IN UINTN ExtendedDataSize
318 )
319 {
320 ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0)));
321 ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0)));
322
323 if (ExtendedDataSize > EFI_STATUS_CODE_DATA_MAX_SIZE) {
324 return EFI_OUT_OF_RESOURCES;
325 }
326
327 //
328 // Fill in the extended data header
329 //
330 mStatusCodeData->HeaderSize = (UINT16) sizeof (EFI_STATUS_CODE_DATA);
331 mStatusCodeData->Size = (UINT16)ExtendedDataSize;
332 if (ExtendedDataGuid == NULL) {
333 ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid;
334 }
335 CopyGuid (&mStatusCodeData->Type, ExtendedDataGuid);
336
337 //
338 // Fill in the extended data buffer
339 //
340 CopyMem (mStatusCodeData + 1, ExtendedData, ExtendedDataSize);
341
342 //
343 // Report the status code
344 //
345 if (CallerId == NULL) {
346 CallerId = &gEfiCallerIdGuid;
347 }
348 return InternalReportStatusCode (Type, Value, Instance, CallerId, mStatusCodeData);
349 }
350