]>
Commit | Line | Data |
---|---|---|
e5516b49 | 1 | /** @file\r |
29f766e4 | 2 | Library constructor & destructor, event handlers, and other internal worker functions.\r |
e5516b49 | 3 | \r |
29f766e4 | 4 | Copyright (c) 2006 - 2009, Intel Corporation<BR>\r |
e5516b49 | 5 | All rights reserved. This program and the accompanying materials\r |
6 | are licensed and made available under the terms and conditions of the BSD License\r | |
7 | which accompanies this distribution. The full text of the license may be found at\r | |
8 | http://opensource.org/licenses/bsd-license.php\r | |
9 | \r | |
10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
12 | \r | |
13 | **/\r | |
14 | \r | |
15 | #include "ReportStatusCodeLibInternal.h"\r | |
16 | \r | |
29f766e4 | 17 | EFI_EVENT mVirtualAddressChangeEvent;\r |
18 | EFI_EVENT mExitBootServicesEvent;\r | |
19 | EFI_STATUS_CODE_DATA *mStatusCodeData;\r | |
20 | BOOLEAN mInSmm;\r | |
21 | EFI_SMM_BASE_PROTOCOL *mSmmBase;\r | |
22 | EFI_RUNTIME_SERVICES *mInternalRT;\r | |
23 | BOOLEAN mHaveExitedBootServices = FALSE;\r | |
24 | EFI_REPORT_STATUS_CODE mReportStatusCode = NULL;\r | |
e5516b49 | 25 | \r |
29f766e4 | 26 | /**\r |
27 | Locate the report status code service.\r | |
b13b4473 | 28 | \r |
29f766e4 | 29 | In SMM, it retrieves OemHookStatusCodeReport() from customized OEM Hook Status Code Lib.\r |
30 | Otherwise, it first tries to retrieve ReportStatusCode() in Runtime Services Table.\r | |
31 | If not found, it then tries to retrieve ReportStatusCode() API of Report Status Code Protocol.\r | |
e5516b49 | 32 | \r |
29f766e4 | 33 | @return Function pointer to the report status code service.\r |
34 | NULL is returned if no status code service is available.\r | |
e5516b49 | 35 | \r |
e5516b49 | 36 | **/\r |
37 | EFI_REPORT_STATUS_CODE\r | |
38 | InternalGetReportStatusCode (\r | |
39 | VOID\r | |
40 | )\r | |
41 | {\r | |
42 | EFI_STATUS_CODE_PROTOCOL *StatusCodeProtocol;\r | |
e5516b49 | 43 | EFI_STATUS Status;\r |
44 | \r | |
404d4e5c | 45 | if (mInSmm) {\r |
46 | return (EFI_REPORT_STATUS_CODE) OemHookStatusCodeReport;\r | |
29f766e4 | 47 | } else if (mInternalRT != NULL && mInternalRT->Hdr.Revision < 0x20000) {\r |
48 | return ((FRAMEWORK_EFI_RUNTIME_SERVICES*)mInternalRT)->ReportStatusCode;\r | |
e5516b49 | 49 | } else if (!mHaveExitedBootServices) {\r |
9556741c | 50 | //\r |
51 | // Check gBS just in case. ReportStatusCode is called before gBS is initialized.\r | |
52 | //\r | |
53 | if (gBS != NULL) {\r | |
54 | Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol);\r | |
55 | if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) {\r | |
56 | return StatusCodeProtocol->ReportStatusCode;\r | |
57 | }\r | |
e5516b49 | 58 | }\r |
59 | }\r | |
60 | \r | |
61 | return NULL;\r | |
62 | }\r | |
63 | \r | |
29f766e4 | 64 | /**\r |
65 | Internal worker function that reports a status code through the status code service.\r | |
66 | \r | |
67 | If status code service is not cached, then this function checks if status code service is\r | |
68 | available in system. If status code service is not available, then EFI_UNSUPPORTED is\r | |
69 | returned. If status code service is present, then it is cached in mReportStatusCode.\r | |
70 | Finally this function reports status code through the status code service.\r | |
71 | \r | |
72 | @param Type Status code type.\r | |
73 | @param Value Status code value.\r | |
74 | @param Instance Status code instance number.\r | |
75 | @param CallerId Pointer to a GUID that identifies the caller of this\r | |
76 | function. This is an optional parameter that may be\r | |
77 | NULL.\r | |
78 | @param Data Pointer to the extended data buffer. This is an\r | |
79 | optional parameter that may be NULL.\r | |
80 | \r | |
81 | @retval EFI_SUCCESS The status code was reported.\r | |
82 | @retval EFI_UNSUPPORTED Status code service is not available.\r | |
83 | @retval EFI_UNSUPPORTED Status code type is not supported.\r | |
84 | \r | |
85 | **/\r | |
86 | EFI_STATUS\r | |
87 | InternalReportStatusCode (\r | |
88 | IN EFI_STATUS_CODE_TYPE Type,\r | |
89 | IN EFI_STATUS_CODE_VALUE Value,\r | |
90 | IN UINT32 Instance,\r | |
91 | IN CONST EFI_GUID *CallerId OPTIONAL,\r | |
92 | IN EFI_STATUS_CODE_DATA *Data OPTIONAL\r | |
93 | )\r | |
94 | {\r | |
95 | if ((ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ||\r | |
96 | (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ||\r | |
97 | (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE)) {\r | |
98 | //\r | |
99 | // If mReportStatusCode is NULL, then check if status code service is available in system.\r | |
100 | //\r | |
101 | if (mReportStatusCode == NULL) {\r | |
102 | mReportStatusCode = InternalGetReportStatusCode ();\r | |
103 | if (mReportStatusCode == NULL) {\r | |
104 | return EFI_UNSUPPORTED;\r | |
105 | }\r | |
106 | }\r | |
107 | \r | |
108 | //\r | |
109 | // A status code service is present in system, so pass in all the parameters to the service.\r | |
110 | //\r | |
111 | return (*mReportStatusCode) (Type, Value, Instance, (EFI_GUID *)CallerId, Data);\r | |
112 | }\r | |
113 | \r | |
114 | return EFI_UNSUPPORTED;\r | |
115 | }\r | |
e5516b49 | 116 | \r |
117 | /**\r | |
29f766e4 | 118 | Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.\r |
119 | \r | |
120 | @param Event Event whose notification function is being invoked.\r | |
121 | @param Context Pointer to the notification function's context\r | |
e5516b49 | 122 | \r |
e5516b49 | 123 | **/\r |
e5516b49 | 124 | VOID\r |
125 | EFIAPI\r | |
126 | ReportStatusCodeLibVirtualAddressChange (\r | |
127 | IN EFI_EVENT Event,\r | |
128 | IN VOID *Context\r | |
129 | )\r | |
130 | {\r | |
29f766e4 | 131 | if (mReportStatusCode != NULL) {\r |
132 | mInternalRT->ConvertPointer (0, (VOID **) &mReportStatusCode);\r | |
e5516b49 | 133 | }\r |
29f766e4 | 134 | mInternalRT->ConvertPointer (0, (VOID **) &mStatusCodeData);\r |
135 | mInternalRT->ConvertPointer (0, (VOID **) &mInternalRT);\r | |
e5516b49 | 136 | }\r |
137 | \r | |
138 | /**\r | |
29f766e4 | 139 | Notification function of EVT_SIGNAL_EXIT_BOOT_SERVICES.\r |
140 | \r | |
141 | @param Event Event whose notification function is being invoked.\r | |
142 | @param Context Pointer to the notification function's context\r | |
e5516b49 | 143 | \r |
e5516b49 | 144 | **/\r |
e5516b49 | 145 | VOID\r |
146 | EFIAPI\r | |
147 | ReportStatusCodeLibExitBootServices (\r | |
148 | IN EFI_EVENT Event,\r | |
149 | IN VOID *Context\r | |
150 | )\r | |
151 | {\r | |
152 | mHaveExitedBootServices = TRUE;\r | |
153 | }\r | |
154 | \r | |
155 | /**\r | |
29f766e4 | 156 | The constructor function of SMM Runtime DXE Report Status Code Lib.\r |
e5516b49 | 157 | \r |
29f766e4 | 158 | This function allocates memory for extended status code data, caches\r |
159 | the report status code service, and registers events.\r | |
160 | \r | |
161 | @param ImageHandle The firmware allocated handle for the EFI image.\r | |
162 | @param SystemTable A pointer to the EFI System Table.\r | |
163 | \r | |
164 | @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r | |
e5516b49 | 165 | \r |
e5516b49 | 166 | **/\r |
167 | EFI_STATUS\r | |
168 | EFIAPI\r | |
169 | ReportStatusCodeLibConstruct (\r | |
170 | IN EFI_HANDLE ImageHandle,\r | |
171 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
172 | )\r | |
173 | {\r | |
29f766e4 | 174 | EFI_STATUS Status;\r |
e5516b49 | 175 | \r |
176 | //\r | |
29f766e4 | 177 | // If in SMM mode, then allocates memory from SMRAM for extended status code data.\r |
178 | //\r | |
9556741c | 179 | Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase);\r |
e5516b49 | 180 | if (!EFI_ERROR (Status)) {\r |
c0522bd7 | 181 | mSmmBase->InSmm (mSmmBase, &mInSmm);\r |
404d4e5c | 182 | if (mInSmm) {\r |
c0522bd7 | 183 | Status = mSmmBase->SmmAllocatePool (\r |
184 | mSmmBase,\r | |
e5516b49 | 185 | EfiRuntimeServicesData, \r |
186 | sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE, \r | |
187 | (VOID **) &mStatusCodeData\r | |
188 | );\r | |
189 | ASSERT_EFI_ERROR (Status);\r | |
190 | OemHookStatusCodeInitialize ();\r | |
191 | return EFI_SUCCESS;\r | |
192 | }\r | |
193 | }\r | |
194 | \r | |
29f766e4 | 195 | \r |
b13b4473 | 196 | //\r |
29f766e4 | 197 | // If not in SMM mode, then allocate runtime memory for extended status code data.\r |
198 | //\r | |
199 | // Library should not use the gRT directly, for it may be converted by other library instance.\r | |
b13b4473 | 200 | // \r |
29f766e4 | 201 | mInternalRT = gRT;\r |
202 | mInSmm = FALSE;\r | |
b13b4473 | 203 | \r |
29f766e4 | 204 | mStatusCodeData = AllocateRuntimePool (sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE);\r |
205 | ASSERT (mStatusCodeData != NULL);\r | |
e5516b49 | 206 | //\r |
207 | // Cache the report status code service\r | |
208 | // \r | |
209 | mReportStatusCode = InternalGetReportStatusCode ();\r | |
210 | \r | |
211 | //\r | |
29f766e4 | 212 | // Register notify function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE\r |
e5516b49 | 213 | // \r |
6a27a4eb | 214 | Status = gBS->CreateEventEx (\r |
215 | EVT_NOTIFY_SIGNAL,\r | |
e5516b49 | 216 | TPL_NOTIFY,\r |
217 | ReportStatusCodeLibVirtualAddressChange,\r | |
218 | NULL,\r | |
6a27a4eb | 219 | &gEfiEventVirtualAddressChangeGuid,\r |
e5516b49 | 220 | &mVirtualAddressChangeEvent\r |
221 | );\r | |
222 | ASSERT_EFI_ERROR (Status);\r | |
223 | \r | |
e5516b49 | 224 | //\r |
29f766e4 | 225 | // Register notify function for EVT_SIGNAL_EXIT_BOOT_SERVICES\r |
e5516b49 | 226 | // \r |
6a27a4eb | 227 | Status = gBS->CreateEventEx (\r |
228 | EVT_NOTIFY_SIGNAL,\r | |
e5516b49 | 229 | TPL_NOTIFY,\r |
230 | ReportStatusCodeLibExitBootServices,\r | |
231 | NULL,\r | |
6a27a4eb | 232 | &gEfiEventExitBootServicesGuid,\r |
e5516b49 | 233 | &mExitBootServicesEvent\r |
234 | );\r | |
235 | ASSERT_EFI_ERROR (Status);\r | |
236 | \r | |
29f766e4 | 237 | return EFI_SUCCESS;\r |
e5516b49 | 238 | }\r |
239 | \r | |
ed7752ec | 240 | /**\r |
29f766e4 | 241 | The destructor function of SMM Runtime DXE Report Status Code Lib.\r |
242 | \r | |
243 | The destructor function frees memory allocated by constructor, and closes related events.\r | |
244 | It will ASSERT() if that related operation fails and it will always return EFI_SUCCESS. \r | |
245 | \r | |
246 | @param ImageHandle The firmware allocated handle for the EFI image.\r | |
247 | @param SystemTable A pointer to the EFI System Table.\r | |
ed7752ec | 248 | \r |
29f766e4 | 249 | @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r |
250 | \r | |
ed7752ec | 251 | **/\r |
e5516b49 | 252 | EFI_STATUS\r |
253 | EFIAPI\r | |
254 | ReportStatusCodeLibDestruct (\r | |
255 | IN EFI_HANDLE ImageHandle,\r | |
256 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
257 | )\r | |
258 | {\r | |
259 | EFI_STATUS Status;\r | |
260 | \r | |
c0522bd7 | 261 | if (!mInSmm) {\r |
9556741c | 262 | ASSERT (gBS != NULL);\r |
263 | Status = gBS->CloseEvent (mVirtualAddressChangeEvent);\r | |
c0522bd7 | 264 | ASSERT_EFI_ERROR (Status);\r |
9556741c | 265 | Status = gBS->CloseEvent (mExitBootServicesEvent);\r |
c0522bd7 | 266 | ASSERT_EFI_ERROR (Status);\r |
267 | \r | |
29f766e4 | 268 | FreePool (mStatusCodeData);\r |
c0522bd7 | 269 | } else {\r |
270 | mSmmBase->SmmFreePool (mSmmBase, mStatusCodeData);\r | |
271 | }\r | |
e5516b49 | 272 | \r |
c0522bd7 | 273 | return EFI_SUCCESS;\r |
e5516b49 | 274 | }\r |
275 | \r |