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