]>
Commit | Line | Data |
---|---|---|
b6490426 BB |
1 | /** @file -- VariablePolicySmmDxe.c\r |
2 | This protocol allows communication with Variable Policy Engine.\r | |
3 | \r | |
4 | Copyright (c) Microsoft Corporation.\r | |
5 | SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
6 | \r | |
7 | **/\r | |
8 | \r | |
9 | #include <Library/BaseLib.h>\r | |
10 | #include <Library/UefiLib.h>\r | |
11 | #include <Library/DebugLib.h>\r | |
12 | #include <Library/SafeIntLib.h>\r | |
13 | #include <Library/UefiBootServicesTableLib.h>\r | |
14 | #include <Library/BaseMemoryLib.h>\r | |
15 | #include <Library/MemoryAllocationLib.h>\r | |
16 | \r | |
17 | #include <Protocol/VariablePolicy.h>\r | |
18 | #include <Protocol/MmCommunication2.h>\r | |
19 | \r | |
20 | #include <Guid/VarCheckPolicyMmi.h>\r | |
21 | \r | |
22 | #include "Variable.h"\r | |
23 | \r | |
24 | EDKII_VARIABLE_POLICY_PROTOCOL mVariablePolicyProtocol;\r | |
25 | EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication;\r | |
26 | \r | |
27 | VOID *mMmCommunicationBuffer;\r | |
28 | UINTN mMmCommunicationBufferSize;\r | |
29 | EFI_LOCK mMmCommunicationLock;\r | |
30 | \r | |
31 | /**\r | |
32 | Internal helper function to consolidate communication method.\r | |
33 | \r | |
34 | @param[in,out] CommBuffer\r | |
35 | @param[in,out] CommSize Size of the CommBuffer.\r | |
36 | \r | |
37 | @retval EFI_STATUS Result from communication method.\r | |
38 | \r | |
39 | **/\r | |
40 | STATIC\r | |
41 | EFI_STATUS\r | |
42 | InternalMmCommunicate (\r | |
43 | IN OUT VOID *CommBuffer,\r | |
44 | IN OUT UINTN *CommSize\r | |
45 | )\r | |
46 | {\r | |
47 | EFI_STATUS Status;\r | |
48 | if (CommBuffer == NULL || CommSize == NULL) {\r | |
49 | return EFI_INVALID_PARAMETER;\r | |
50 | }\r | |
51 | Status = mMmCommunication->Communicate (mMmCommunication, CommBuffer, CommBuffer, CommSize);\r | |
52 | return Status;\r | |
53 | }\r | |
54 | \r | |
55 | \r | |
56 | /**\r | |
57 | This API function disables the variable policy enforcement. If it's\r | |
58 | already been called once, will return EFI_ALREADY_STARTED.\r | |
59 | \r | |
60 | @retval EFI_SUCCESS\r | |
61 | @retval EFI_ALREADY_STARTED Has already been called once this boot.\r | |
62 | @retval EFI_WRITE_PROTECTED Interface has been locked until reboot.\r | |
63 | @retval EFI_WRITE_PROTECTED Interface option is disabled by platform PCD.\r | |
64 | \r | |
65 | **/\r | |
66 | STATIC\r | |
67 | EFI_STATUS\r | |
68 | EFIAPI\r | |
69 | ProtocolDisableVariablePolicy (\r | |
70 | VOID\r | |
71 | )\r | |
72 | {\r | |
73 | EFI_STATUS Status;\r | |
74 | EFI_MM_COMMUNICATE_HEADER *CommHeader;\r | |
75 | VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;\r | |
76 | UINTN BufferSize;\r | |
77 | \r | |
78 | // Check the PCD for convenience.\r | |
79 | // This would also be rejected by the lib, but why go to MM if we don't have to?\r | |
80 | if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {\r | |
81 | return EFI_WRITE_PROTECTED;\r | |
82 | }\r | |
83 | \r | |
84 | AcquireLockOnlyAtBootTime (&mMmCommunicationLock);\r | |
85 | \r | |
86 | // Set up the MM communication.\r | |
87 | BufferSize = mMmCommunicationBufferSize;\r | |
88 | CommHeader = mMmCommunicationBuffer;\r | |
89 | PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;\r | |
90 | CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );\r | |
91 | CommHeader->MessageLength = BufferSize;\r | |
92 | PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG;\r | |
93 | PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION;\r | |
94 | PolicyHeader->Command = VAR_CHECK_POLICY_COMMAND_DISABLE;\r | |
95 | \r | |
96 | Status = InternalMmCommunicate (CommHeader, &BufferSize);\r | |
97 | DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));\r | |
98 | \r | |
99 | ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);\r | |
100 | \r | |
101 | return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;\r | |
102 | }\r | |
103 | \r | |
104 | \r | |
105 | /**\r | |
106 | This API function returns whether or not the policy engine is\r | |
107 | currently being enforced.\r | |
108 | \r | |
109 | @param[out] State Pointer to a return value for whether the policy enforcement\r | |
110 | is currently enabled.\r | |
111 | \r | |
112 | @retval EFI_SUCCESS\r | |
113 | @retval Others An error has prevented this command from completing.\r | |
114 | \r | |
115 | **/\r | |
116 | STATIC\r | |
117 | EFI_STATUS\r | |
118 | EFIAPI\r | |
119 | ProtocolIsVariablePolicyEnabled (\r | |
120 | OUT BOOLEAN *State\r | |
121 | )\r | |
122 | {\r | |
123 | EFI_STATUS Status;\r | |
124 | EFI_MM_COMMUNICATE_HEADER *CommHeader;\r | |
125 | VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;\r | |
126 | VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS *CommandParams;\r | |
127 | UINTN BufferSize;\r | |
128 | \r | |
129 | if (State == NULL) {\r | |
130 | return EFI_INVALID_PARAMETER;\r | |
131 | }\r | |
132 | \r | |
133 | AcquireLockOnlyAtBootTime (&mMmCommunicationLock);\r | |
134 | \r | |
135 | // Set up the MM communication.\r | |
136 | BufferSize = mMmCommunicationBufferSize;\r | |
137 | CommHeader = mMmCommunicationBuffer;\r | |
138 | PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;\r | |
139 | CommandParams = (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS*)(PolicyHeader + 1);\r | |
140 | CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );\r | |
141 | CommHeader->MessageLength = BufferSize;\r | |
142 | PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG;\r | |
143 | PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION;\r | |
144 | PolicyHeader->Command = VAR_CHECK_POLICY_COMMAND_IS_ENABLED;\r | |
145 | \r | |
146 | Status = InternalMmCommunicate (CommHeader, &BufferSize);\r | |
147 | DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));\r | |
148 | \r | |
149 | if (!EFI_ERROR( Status )) {\r | |
150 | Status = PolicyHeader->Result;\r | |
151 | *State = CommandParams->State;\r | |
152 | }\r | |
153 | \r | |
154 | ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);\r | |
155 | \r | |
156 | return Status;\r | |
157 | }\r | |
158 | \r | |
159 | \r | |
160 | /**\r | |
161 | This API function validates and registers a new policy with\r | |
162 | the policy enforcement engine.\r | |
163 | \r | |
164 | @param[in] NewPolicy Pointer to the incoming policy structure.\r | |
165 | \r | |
166 | @retval EFI_SUCCESS\r | |
167 | @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally inconsistent.\r | |
168 | @retval EFI_ALREADY_STARTED An identical matching policy already exists.\r | |
169 | @retval EFI_WRITE_PROTECTED The interface has been locked until the next reboot.\r | |
170 | @retval EFI_UNSUPPORTED Policy enforcement has been disabled. No reason to add more policies.\r | |
171 | @retval EFI_ABORTED A calculation error has prevented this function from completing.\r | |
172 | @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any more policies.\r | |
173 | \r | |
174 | **/\r | |
175 | STATIC\r | |
176 | EFI_STATUS\r | |
177 | EFIAPI\r | |
178 | ProtocolRegisterVariablePolicy (\r | |
179 | IN CONST VARIABLE_POLICY_ENTRY *NewPolicy\r | |
180 | )\r | |
181 | {\r | |
182 | EFI_STATUS Status;\r | |
183 | EFI_MM_COMMUNICATE_HEADER *CommHeader;\r | |
184 | VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;\r | |
185 | VOID *PolicyBuffer;\r | |
186 | UINTN BufferSize;\r | |
187 | UINTN RequiredSize;\r | |
188 | \r | |
189 | if (NewPolicy == NULL) {\r | |
190 | return EFI_INVALID_PARAMETER;\r | |
191 | }\r | |
192 | \r | |
193 | // First, make sure that the required size does not exceed the capabilities\r | |
194 | // of the MmCommunication buffer.\r | |
195 | RequiredSize = OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + sizeof(VAR_CHECK_POLICY_COMM_HEADER);\r | |
196 | Status = SafeUintnAdd( RequiredSize, NewPolicy->Size, &RequiredSize );\r | |
197 | if (EFI_ERROR( Status ) || RequiredSize > mMmCommunicationBufferSize) {\r | |
198 | DEBUG(( DEBUG_ERROR, "%a - Policy too large for buffer! %r, %d > %d \n", __FUNCTION__,\r | |
199 | Status, RequiredSize, mMmCommunicationBufferSize ));\r | |
200 | return EFI_OUT_OF_RESOURCES;\r | |
201 | }\r | |
202 | \r | |
203 | AcquireLockOnlyAtBootTime (&mMmCommunicationLock);\r | |
204 | \r | |
205 | // Set up the MM communication.\r | |
206 | BufferSize = mMmCommunicationBufferSize;\r | |
207 | CommHeader = mMmCommunicationBuffer;\r | |
208 | PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;\r | |
209 | PolicyBuffer = (VOID*)(PolicyHeader + 1);\r | |
210 | CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );\r | |
211 | CommHeader->MessageLength = BufferSize;\r | |
212 | PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG;\r | |
213 | PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION;\r | |
214 | PolicyHeader->Command = VAR_CHECK_POLICY_COMMAND_REGISTER;\r | |
215 | \r | |
216 | // Copy the policy into place. This copy is safe because we've already tested above.\r | |
217 | CopyMem( PolicyBuffer, NewPolicy, NewPolicy->Size );\r | |
218 | \r | |
219 | Status = InternalMmCommunicate (CommHeader, &BufferSize);\r | |
220 | DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));\r | |
221 | \r | |
222 | ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);\r | |
223 | \r | |
224 | return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;\r | |
225 | }\r | |
226 | \r | |
227 | \r | |
228 | /**\r | |
229 | This helper function takes care of the overhead of formatting, sending, and interpreting\r | |
230 | the results for a single DumpVariablePolicy request.\r | |
231 | \r | |
232 | @param[in] PageRequested The page of the paginated results from MM. 0 for metadata.\r | |
233 | @param[out] TotalSize The total size of the entire buffer. Returned as part of metadata.\r | |
234 | @param[out] PageSize The size of the current page being returned. Not valid as part of metadata.\r | |
235 | @param[out] HasMore A flag indicating whether there are more pages after this one.\r | |
236 | @param[out] Buffer The start of the current page from MM.\r | |
237 | \r | |
238 | @retval EFI_SUCCESS Output params have been updated (either metadata or dump page).\r | |
239 | @retval EFI_INVALID_PARAMETER One of the output params is NULL.\r | |
240 | @retval Others Response from MM handler.\r | |
241 | \r | |
242 | **/\r | |
243 | STATIC\r | |
244 | EFI_STATUS\r | |
245 | DumpVariablePolicyHelper (\r | |
246 | IN UINT32 PageRequested,\r | |
247 | OUT UINT32 *TotalSize,\r | |
248 | OUT UINT32 *PageSize,\r | |
249 | OUT BOOLEAN *HasMore,\r | |
250 | OUT UINT8 **Buffer\r | |
251 | )\r | |
252 | {\r | |
253 | EFI_STATUS Status;\r | |
254 | EFI_MM_COMMUNICATE_HEADER *CommHeader;\r | |
255 | VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;\r | |
256 | VAR_CHECK_POLICY_COMM_DUMP_PARAMS *CommandParams;\r | |
257 | UINTN BufferSize;\r | |
258 | \r | |
259 | if (TotalSize == NULL || PageSize == NULL || HasMore == NULL || Buffer == NULL) {\r | |
260 | return EFI_INVALID_PARAMETER;\r | |
261 | }\r | |
262 | \r | |
263 | // Set up the MM communication.\r | |
264 | BufferSize = mMmCommunicationBufferSize;\r | |
265 | CommHeader = mMmCommunicationBuffer;\r | |
266 | PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;\r | |
267 | CommandParams = (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(PolicyHeader + 1);\r | |
268 | CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );\r | |
269 | CommHeader->MessageLength = BufferSize;\r | |
270 | PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG;\r | |
271 | PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION;\r | |
272 | PolicyHeader->Command = VAR_CHECK_POLICY_COMMAND_DUMP;\r | |
273 | \r | |
274 | CommandParams->PageRequested = PageRequested;\r | |
275 | \r | |
276 | Status = InternalMmCommunicate (CommHeader, &BufferSize);\r | |
277 | DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));\r | |
278 | \r | |
279 | if (!EFI_ERROR( Status )) {\r | |
280 | Status = PolicyHeader->Result;\r | |
281 | *TotalSize = CommandParams->TotalSize;\r | |
282 | *PageSize = CommandParams->PageSize;\r | |
283 | *HasMore = CommandParams->HasMore;\r | |
284 | *Buffer = (UINT8*)(CommandParams + 1);\r | |
285 | }\r | |
286 | \r | |
287 | return Status;\r | |
288 | }\r | |
289 | \r | |
290 | \r | |
291 | /**\r | |
292 | This API function will dump the entire contents of the variable policy table.\r | |
293 | \r | |
294 | Similar to GetVariable, the first call can be made with a 0 size and it will return\r | |
295 | the size of the buffer required to hold the entire table.\r | |
296 | \r | |
297 | @param[out] Policy Pointer to the policy buffer. Can be NULL if Size is 0.\r | |
298 | @param[in,out] Size On input, the size of the output buffer. On output, the size\r | |
299 | of the data returned.\r | |
300 | \r | |
301 | @retval EFI_SUCCESS Policy data is in the output buffer and Size has been updated.\r | |
302 | @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero and Policy is NULL.\r | |
303 | @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold policy. Size updated with required size.\r | |
304 | \r | |
305 | **/\r | |
306 | STATIC\r | |
307 | EFI_STATUS\r | |
308 | EFIAPI\r | |
309 | ProtocolDumpVariablePolicy (\r | |
310 | OUT UINT8 *Policy OPTIONAL,\r | |
311 | IN OUT UINT32 *Size\r | |
312 | )\r | |
313 | {\r | |
314 | EFI_STATUS Status;\r | |
315 | UINT8 *Source;\r | |
316 | UINT8 *Destination;\r | |
317 | UINT32 PolicySize;\r | |
318 | UINT32 PageSize;\r | |
319 | BOOLEAN HasMore;\r | |
320 | UINT32 PageIndex;\r | |
321 | \r | |
322 | if (Size == NULL || (*Size > 0 && Policy == NULL)) {\r | |
323 | return EFI_INVALID_PARAMETER;\r | |
324 | }\r | |
325 | \r | |
326 | AcquireLockOnlyAtBootTime (&mMmCommunicationLock);\r | |
327 | \r | |
328 | // Repeat this whole process until we either have a failure case or get the entire buffer.\r | |
329 | do {\r | |
330 | // First, we must check the zero page to determine the buffer size and\r | |
331 | // reset the internal state.\r | |
332 | PolicySize = 0;\r | |
333 | PageSize = 0;\r | |
334 | HasMore = FALSE;\r | |
335 | Status = DumpVariablePolicyHelper (0, &PolicySize, &PageSize, &HasMore, &Source);\r | |
336 | if (EFI_ERROR (Status)) {\r | |
337 | break;\r | |
338 | }\r | |
339 | \r | |
340 | // If we're good, we can at least check the required size now.\r | |
341 | if (*Size < PolicySize) {\r | |
342 | *Size = PolicySize;\r | |
343 | Status = EFI_BUFFER_TOO_SMALL;\r | |
344 | break;\r | |
345 | }\r | |
346 | \r | |
347 | // On further thought, let's update the size either way.\r | |
348 | *Size = PolicySize;\r | |
349 | // And get ready to ROCK.\r | |
350 | Destination = Policy;\r | |
351 | \r | |
352 | // Keep looping and copying until we're either done or freak out.\r | |
353 | for (PageIndex = 1; !EFI_ERROR (Status) && HasMore && PageIndex < MAX_UINT32; PageIndex++) {\r | |
354 | Status = DumpVariablePolicyHelper (PageIndex, &PolicySize, &PageSize, &HasMore, &Source);\r | |
355 | if (!EFI_ERROR (Status)) {\r | |
356 | CopyMem (Destination, Source, PageSize);\r | |
357 | Destination += PageSize;\r | |
358 | }\r | |
359 | }\r | |
360 | \r | |
361 | // Next, we check to see whether\r | |
362 | } while (Status == EFI_TIMEOUT);\r | |
363 | \r | |
364 | ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);\r | |
365 | \r | |
366 | // There's currently no use for this, but it shouldn't be hard to implement.\r | |
367 | return Status;\r | |
368 | }\r | |
369 | \r | |
370 | \r | |
371 | /**\r | |
372 | This API function locks the interface so that no more policy updates\r | |
373 | can be performed or changes made to the enforcement until the next boot.\r | |
374 | \r | |
375 | @retval EFI_SUCCESS\r | |
376 | @retval Others An error has prevented this command from completing.\r | |
377 | \r | |
378 | **/\r | |
379 | STATIC\r | |
380 | EFI_STATUS\r | |
381 | EFIAPI\r | |
382 | ProtocolLockVariablePolicy (\r | |
383 | VOID\r | |
384 | )\r | |
385 | {\r | |
386 | EFI_STATUS Status;\r | |
387 | EFI_MM_COMMUNICATE_HEADER *CommHeader;\r | |
388 | VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;\r | |
389 | UINTN BufferSize;\r | |
390 | \r | |
391 | AcquireLockOnlyAtBootTime (&mMmCommunicationLock);\r | |
392 | \r | |
393 | // Set up the MM communication.\r | |
394 | BufferSize = mMmCommunicationBufferSize;\r | |
395 | CommHeader = mMmCommunicationBuffer;\r | |
396 | PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;\r | |
397 | CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );\r | |
398 | CommHeader->MessageLength = BufferSize;\r | |
399 | PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG;\r | |
400 | PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION;\r | |
401 | PolicyHeader->Command = VAR_CHECK_POLICY_COMMAND_LOCK;\r | |
402 | \r | |
403 | Status = InternalMmCommunicate (CommHeader, &BufferSize);\r | |
404 | DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));\r | |
405 | \r | |
406 | ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);\r | |
407 | \r | |
408 | return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;\r | |
409 | }\r | |
410 | \r | |
411 | \r | |
412 | /**\r | |
413 | This helper function locates the shared comm buffer and assigns it to input pointers.\r | |
414 | \r | |
415 | @param[in,out] BufferSize On input, the minimum buffer size required INCLUDING the MM communicate header.\r | |
416 | On output, the size of the matching buffer found.\r | |
417 | @param[out] LocatedBuffer A pointer to the matching buffer.\r | |
418 | \r | |
419 | @retval EFI_SUCCESS\r | |
420 | @retval EFI_INVALID_PARAMETER One of the output pointers was NULL.\r | |
421 | @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate a comm buffer.\r | |
422 | \r | |
423 | **/\r | |
424 | STATIC\r | |
425 | EFI_STATUS\r | |
426 | InitMmCommonCommBuffer (\r | |
427 | IN OUT UINTN *BufferSize,\r | |
428 | OUT VOID **LocatedBuffer\r | |
429 | )\r | |
430 | {\r | |
431 | EFI_STATUS Status;\r | |
432 | \r | |
433 | Status = EFI_SUCCESS;\r | |
434 | \r | |
435 | // Make sure that we're working with good pointers.\r | |
436 | if (BufferSize == NULL || LocatedBuffer == NULL) {\r | |
437 | return EFI_INVALID_PARAMETER;\r | |
438 | }\r | |
439 | \r | |
440 | // Allocate the runtime memory for the comm buffer.\r | |
441 | *LocatedBuffer = AllocateRuntimePool (*BufferSize);\r | |
442 | if (*LocatedBuffer == NULL) {\r | |
443 | Status = EFI_OUT_OF_RESOURCES;\r | |
444 | *BufferSize = 0;\r | |
445 | }\r | |
446 | \r | |
447 | EfiInitializeLock (&mMmCommunicationLock, TPL_NOTIFY);\r | |
448 | \r | |
449 | return Status;\r | |
450 | }\r | |
451 | \r | |
452 | \r | |
453 | /**\r | |
454 | Convert internal pointer addresses to virtual addresses.\r | |
455 | \r | |
456 | @param[in] Event Event whose notification function is being invoked.\r | |
457 | @param[in] Context The pointer to the notification function's context, which\r | |
458 | is implementation-dependent.\r | |
459 | **/\r | |
460 | STATIC\r | |
461 | VOID\r | |
462 | EFIAPI\r | |
463 | VariablePolicyVirtualAddressCallback (\r | |
464 | IN EFI_EVENT Event,\r | |
465 | IN VOID *Context\r | |
466 | )\r | |
467 | {\r | |
468 | EfiConvertPointer (0, (VOID **)&mMmCommunication);\r | |
469 | EfiConvertPointer (0, (VOID **)&mMmCommunicationBuffer);\r | |
470 | }\r | |
471 | \r | |
472 | \r | |
473 | /**\r | |
474 | The driver's entry point.\r | |
475 | \r | |
476 | @param[in] ImageHandle The firmware allocated handle for the EFI image.\r | |
477 | @param[in] SystemTable A pointer to the EFI System Table.\r | |
478 | \r | |
479 | @retval EFI_SUCCESS The entry point executed successfully.\r | |
480 | @retval other Some error occured when executing this entry point.\r | |
481 | \r | |
482 | **/\r | |
483 | EFI_STATUS\r | |
484 | EFIAPI\r | |
485 | VariablePolicySmmDxeMain (\r | |
486 | IN EFI_HANDLE ImageHandle,\r | |
487 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
488 | )\r | |
489 | {\r | |
490 | EFI_STATUS Status;\r | |
491 | BOOLEAN ProtocolInstalled;\r | |
492 | BOOLEAN VirtualAddressChangeRegistered;\r | |
493 | EFI_EVENT VirtualAddressChangeEvent;\r | |
494 | \r | |
495 | Status = EFI_SUCCESS;\r | |
496 | ProtocolInstalled = FALSE;\r | |
497 | VirtualAddressChangeRegistered = FALSE;\r | |
498 | \r | |
499 | // Update the minimum buffer size.\r | |
500 | mMmCommunicationBufferSize = VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE;\r | |
501 | // Locate the shared comm buffer to use for sending MM commands.\r | |
502 | Status = InitMmCommonCommBuffer( &mMmCommunicationBufferSize, &mMmCommunicationBuffer );\r | |
503 | if (EFI_ERROR( Status )) {\r | |
504 | DEBUG((DEBUG_ERROR, "%a - Failed to locate a viable MM comm buffer! %r\n", __FUNCTION__, Status));\r | |
505 | ASSERT_EFI_ERROR( Status );\r | |
506 | return Status;\r | |
507 | }\r | |
508 | \r | |
509 | // Locate the MmCommunication protocol.\r | |
510 | Status = gBS->LocateProtocol( &gEfiMmCommunication2ProtocolGuid, NULL, (VOID**)&mMmCommunication );\r | |
511 | if (EFI_ERROR( Status )) {\r | |
512 | DEBUG((DEBUG_ERROR, "%a - Failed to locate MmCommunication protocol! %r\n", __FUNCTION__, Status));\r | |
513 | ASSERT_EFI_ERROR( Status );\r | |
514 | return Status;\r | |
515 | }\r | |
516 | \r | |
517 | // Configure the VariablePolicy protocol structure.\r | |
518 | mVariablePolicyProtocol.Revision = EDKII_VARIABLE_POLICY_PROTOCOL_REVISION;\r | |
519 | mVariablePolicyProtocol.DisableVariablePolicy = ProtocolDisableVariablePolicy;\r | |
520 | mVariablePolicyProtocol.IsVariablePolicyEnabled = ProtocolIsVariablePolicyEnabled;\r | |
521 | mVariablePolicyProtocol.RegisterVariablePolicy = ProtocolRegisterVariablePolicy;\r | |
522 | mVariablePolicyProtocol.DumpVariablePolicy = ProtocolDumpVariablePolicy;\r | |
523 | mVariablePolicyProtocol.LockVariablePolicy = ProtocolLockVariablePolicy;\r | |
524 | \r | |
525 | // Register all the protocols and return the status.\r | |
526 | Status = gBS->InstallMultipleProtocolInterfaces( &ImageHandle,\r | |
527 | &gEdkiiVariablePolicyProtocolGuid, &mVariablePolicyProtocol,\r | |
528 | NULL );\r | |
529 | if (EFI_ERROR( Status )) {\r | |
530 | DEBUG(( DEBUG_ERROR, "%a - Failed to install protocol! %r\n", __FUNCTION__, Status ));\r | |
531 | goto Exit;\r | |
532 | }\r | |
533 | else {\r | |
534 | ProtocolInstalled = TRUE;\r | |
535 | }\r | |
536 | \r | |
537 | // Normally, we might want to register a callback\r | |
538 | // to lock the interface, but this is integrated\r | |
539 | // into the existing callbacks in VaraiableSmm.c\r | |
540 | // and VariableDxe.c.\r | |
541 | \r | |
542 | //\r | |
543 | // Register a VirtualAddressChange callback for the MmComm protocol and Comm buffer.\r | |
544 | Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,\r | |
545 | TPL_NOTIFY,\r | |
546 | VariablePolicyVirtualAddressCallback,\r | |
547 | NULL,\r | |
548 | &gEfiEventVirtualAddressChangeGuid,\r | |
549 | &VirtualAddressChangeEvent);\r | |
550 | if (EFI_ERROR( Status )) {\r | |
551 | DEBUG(( DEBUG_ERROR, "%a - Failed to create VirtualAddressChange event! %r\n", __FUNCTION__, Status ));\r | |
552 | goto Exit;\r | |
553 | }\r | |
554 | else {\r | |
555 | VirtualAddressChangeRegistered = TRUE;\r | |
556 | }\r | |
557 | \r | |
558 | \r | |
559 | Exit:\r | |
560 | //\r | |
561 | // If we're about to return a failed status (and unload this driver), we must first undo anything that\r | |
562 | // has been successfully done.\r | |
563 | if (EFI_ERROR( Status )) {\r | |
564 | if (ProtocolInstalled) {\r | |
565 | gBS->UninstallProtocolInterface( &ImageHandle, &gEdkiiVariablePolicyProtocolGuid, &mVariablePolicyProtocol );\r | |
566 | }\r | |
567 | if (VirtualAddressChangeRegistered) {\r | |
568 | gBS->CloseEvent( VirtualAddressChangeEvent );\r | |
569 | }\r | |
570 | }\r | |
571 | \r | |
572 | return Status;\r | |
573 | }\r |