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