]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
MdeModulePkg: Connect VariablePolicy business logic to VariableServices
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / VariablePolicySmmDxe.c
CommitLineData
b6490426
BB
1/** @file -- VariablePolicySmmDxe.c\r
2This protocol allows communication with Variable Policy Engine.\r
3\r
4Copyright (c) Microsoft Corporation.\r
5SPDX-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
24EDKII_VARIABLE_POLICY_PROTOCOL mVariablePolicyProtocol;\r
25EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication;\r
26\r
27VOID *mMmCommunicationBuffer;\r
28UINTN mMmCommunicationBufferSize;\r
29EFI_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
40STATIC\r
41EFI_STATUS\r
42InternalMmCommunicate (\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
66STATIC\r
67EFI_STATUS\r
68EFIAPI\r
69ProtocolDisableVariablePolicy (\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
116STATIC\r
117EFI_STATUS\r
118EFIAPI\r
119ProtocolIsVariablePolicyEnabled (\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
175STATIC\r
176EFI_STATUS\r
177EFIAPI\r
178ProtocolRegisterVariablePolicy (\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
243STATIC\r
244EFI_STATUS\r
245DumpVariablePolicyHelper (\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
306STATIC\r
307EFI_STATUS\r
308EFIAPI\r
309ProtocolDumpVariablePolicy (\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
379STATIC\r
380EFI_STATUS\r
381EFIAPI\r
382ProtocolLockVariablePolicy (\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
424STATIC\r
425EFI_STATUS\r
426InitMmCommonCommBuffer (\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
460STATIC\r
461VOID\r
462EFIAPI\r
463VariablePolicyVirtualAddressCallback (\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
483EFI_STATUS\r
484EFIAPI\r
485VariablePolicySmmDxeMain (\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
559Exit:\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