]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeSupport.c
882cad677f6a99a0589e7082640f1dbcf985ecbd
[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 STATIC
36 EFI_RUNTIME_SERVICES *mRT;
37
38 STATIC
39 EFI_BOOT_SERVICES *mBS;
40
41 STATIC
42 BOOLEAN mHaveExitedBootServices = FALSE;
43
44 /**
45 Locatet he report status code service.
46
47 @return EFI_REPORT_STATUS_CODE function point to
48 ReportStatusCode.
49 **/
50 EFI_REPORT_STATUS_CODE
51 InternalGetReportStatusCode (
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 **/
79 STATIC
80 VOID
81 EFIAPI
82 ReportStatusCodeLibVirtualAddressChange (
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 **/
100 STATIC
101 VOID
102 EFIAPI
103 ReportStatusCodeLibExitBootServices (
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 **/
119 EFI_STATUS
120 EFIAPI
121 ReportStatusCodeLibConstruct (
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
195 EFI_STATUS
196 EFIAPI
197 ReportStatusCodeLibDestruct (
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 **/
260 EFI_STATUS
261 EFIAPI
262 InternalReportStatusCodeEx (
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 }