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