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