]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
MdeModulePkg/Variable: Consolidate common parsing functions
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / VariableSmm.c
CommitLineData
8a2d4996 1/** @file\r
fa0737a8
SZ
2 The sample implementation for SMM variable protocol. And this driver\r
3 implements an SMI handler to communicate with the DXE runtime driver\r
8a2d4996 4 to provide variable services.\r
5\r
2445a70e 6 Caution: This module requires additional review when modified.\r
7 This driver will have external input - variable data and communicate buffer in SMM mode.\r
8 This external input must be validated carefully to avoid security issue like\r
9 buffer overflow, integer overflow.\r
10\r
11 SmmVariableHandler() will receive untrusted input and do basic validation.\r
12\r
fa0737a8
SZ
13 Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),\r
14 VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),\r
2445a70e 15 SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
16\r
904e0ca9 17Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>\r
a855f63e 18Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>\r
9d510e61 19SPDX-License-Identifier: BSD-2-Clause-Patent\r
8a2d4996 20\r
21**/\r
fa0737a8 22\r
d00ed85e 23#include <Protocol/SmmVariable.h>\r
24#include <Protocol/SmmFirmwareVolumeBlock.h>\r
8a2d4996 25#include <Protocol/SmmFaultTolerantWrite.h>\r
a855f63e 26#include <Protocol/MmEndOfDxe.h>\r
efb01a10 27#include <Protocol/SmmVarCheck.h>\r
2445a70e 28\r
a855f63e 29#include <Library/MmServicesTableLib.h>\r
8a2d4996 30\r
d00ed85e 31#include <Guid/SmmVariableCommon.h>\r
8a2d4996 32#include "Variable.h"\r
20a27a64 33#include "VariableParsing.h"\r
8a2d4996 34\r
8a2d4996 35BOOLEAN mAtRuntime = FALSE;\r
5e5bb2a9
SZ
36UINT8 *mVariableBufferPayload = NULL;\r
37UINTN mVariableBufferPayloadSize;\r
ff843847 38\r
fa0737a8
SZ
39/**\r
40 SecureBoot Hook for SetVariable.\r
41\r
42 @param[in] VariableName Name of Variable to be found.\r
43 @param[in] VendorGuid Variable vendor GUID.\r
44\r
45**/\r
46VOID\r
47EFIAPI\r
48SecureBootHook (\r
49 IN CHAR16 *VariableName,\r
50 IN EFI_GUID *VendorGuid\r
51 )\r
52{\r
53 return ;\r
54}\r
55\r
ff843847
RN
56/**\r
57\r
58 This code sets variable in storage blocks (Volatile or Non-Volatile).\r
59\r
60 @param VariableName Name of Variable to be found.\r
61 @param VendorGuid Variable vendor GUID.\r
62 @param Attributes Attribute value of the variable found\r
63 @param DataSize Size of Data found. If size is less than the\r
64 data, this value contains the required size.\r
65 @param Data Data pointer.\r
66\r
67 @return EFI_INVALID_PARAMETER Invalid parameter.\r
68 @return EFI_SUCCESS Set successfully.\r
69 @return EFI_OUT_OF_RESOURCES Resource not enough to set variable.\r
70 @return EFI_NOT_FOUND Not found.\r
71 @return EFI_WRITE_PROTECTED Variable is read-only.\r
72\r
73**/\r
74EFI_STATUS\r
75EFIAPI\r
76SmmVariableSetVariable (\r
77 IN CHAR16 *VariableName,\r
78 IN EFI_GUID *VendorGuid,\r
79 IN UINT32 Attributes,\r
80 IN UINTN DataSize,\r
81 IN VOID *Data\r
82 )\r
83{\r
84 EFI_STATUS Status;\r
85\r
86 //\r
87 // Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL.\r
88 //\r
8021f4c7 89 mRequestSource = VarCheckFromTrusted;\r
ff843847
RN
90 Status = VariableServiceSetVariable (\r
91 VariableName,\r
92 VendorGuid,\r
93 Attributes,\r
94 DataSize,\r
95 Data\r
96 );\r
8021f4c7 97 mRequestSource = VarCheckFromUntrusted;\r
ff843847
RN
98 return Status;\r
99}\r
5e5bb2a9 100\r
8a2d4996 101EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = {\r
102 VariableServiceGetVariable,\r
103 VariableServiceGetNextVariableName,\r
ff843847 104 SmmVariableSetVariable,\r
8a2d4996 105 VariableServiceQueryVariableInfo\r
106};\r
107\r
efb01a10
SZ
108EDKII_SMM_VAR_CHECK_PROTOCOL mSmmVarCheck = { VarCheckRegisterSetVariableCheckHandler,\r
109 VarCheckVariablePropertySet,\r
110 VarCheckVariablePropertyGet };\r
111\r
8a2d4996 112/**\r
113 Return TRUE if ExitBootServices () has been called.\r
fa0737a8 114\r
8a2d4996 115 @retval TRUE If ExitBootServices () has been called.\r
116**/\r
117BOOLEAN\r
118AtRuntime (\r
119 VOID\r
120 )\r
121{\r
122 return mAtRuntime;\r
123}\r
124\r
125/**\r
126 Initializes a basic mutual exclusion lock.\r
127\r
fa0737a8
SZ
128 This function initializes a basic mutual exclusion lock to the released state\r
129 and returns the lock. Each lock provides mutual exclusion access at its task\r
8a2d4996 130 priority level. Since there is no preemption or multiprocessor support in EFI,\r
131 acquiring the lock only consists of raising to the locks TPL.\r
132 If Lock is NULL, then ASSERT().\r
133 If Priority is not a valid TPL value, then ASSERT().\r
134\r
135 @param Lock A pointer to the lock data structure to initialize.\r
136 @param Priority EFI TPL is associated with the lock.\r
137\r
138 @return The lock.\r
139\r
140**/\r
141EFI_LOCK *\r
142InitializeLock (\r
143 IN OUT EFI_LOCK *Lock,\r
144 IN EFI_TPL Priority\r
145 )\r
146{\r
147 return Lock;\r
148}\r
149\r
150/**\r
151 Acquires lock only at boot time. Simply returns at runtime.\r
152\r
153 This is a temperary function that will be removed when\r
154 EfiAcquireLock() in UefiLib can handle the call in UEFI\r
155 Runtimer driver in RT phase.\r
156 It calls EfiAcquireLock() at boot time, and simply returns\r
157 at runtime.\r
158\r
159 @param Lock A pointer to the lock to acquire.\r
160\r
161**/\r
162VOID\r
163AcquireLockOnlyAtBootTime (\r
164 IN EFI_LOCK *Lock\r
165 )\r
166{\r
167\r
168}\r
169\r
170\r
171/**\r
172 Releases lock only at boot time. Simply returns at runtime.\r
173\r
174 This is a temperary function which will be removed when\r
175 EfiReleaseLock() in UefiLib can handle the call in UEFI\r
176 Runtimer driver in RT phase.\r
177 It calls EfiReleaseLock() at boot time and simply returns\r
178 at runtime.\r
179\r
180 @param Lock A pointer to the lock to release.\r
181\r
182**/\r
183VOID\r
184ReleaseLockOnlyAtBootTime (\r
185 IN EFI_LOCK *Lock\r
186 )\r
187{\r
188\r
189}\r
190\r
191/**\r
0a18956d 192 Retrieve the SMM Fault Tolerent Write protocol interface.\r
8a2d4996 193\r
194 @param[out] FtwProtocol The interface of SMM Ftw protocol\r
195\r
196 @retval EFI_SUCCESS The SMM FTW protocol instance was found and returned in FtwProtocol.\r
197 @retval EFI_NOT_FOUND The SMM FTW protocol instance was not found.\r
198 @retval EFI_INVALID_PARAMETER SarProtocol is NULL.\r
199\r
200**/\r
201EFI_STATUS\r
202GetFtwProtocol (\r
203 OUT VOID **FtwProtocol\r
204 )\r
205{\r
206 EFI_STATUS Status;\r
207\r
208 //\r
209 // Locate Smm Fault Tolerent Write protocol\r
210 //\r
a855f63e 211 Status = gMmst->MmLocateProtocol (\r
fa0737a8
SZ
212 &gEfiSmmFaultTolerantWriteProtocolGuid,\r
213 NULL,\r
8a2d4996 214 FtwProtocol\r
215 );\r
216 return Status;\r
217}\r
218\r
219\r
220/**\r
0a18956d 221 Retrieve the SMM FVB protocol interface by HANDLE.\r
8a2d4996 222\r
223 @param[in] FvBlockHandle The handle of SMM FVB protocol that provides services for\r
224 reading, writing, and erasing the target block.\r
225 @param[out] FvBlock The interface of SMM FVB protocol\r
226\r
227 @retval EFI_SUCCESS The interface information for the specified protocol was returned.\r
228 @retval EFI_UNSUPPORTED The device does not support the SMM FVB protocol.\r
229 @retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.\r
230\r
231**/\r
232EFI_STATUS\r
233GetFvbByHandle (\r
234 IN EFI_HANDLE FvBlockHandle,\r
235 OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock\r
236 )\r
237{\r
238 //\r
239 // To get the SMM FVB protocol interface on the handle\r
240 //\r
a855f63e 241 return gMmst->MmHandleProtocol (\r
8a2d4996 242 FvBlockHandle,\r
243 &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
244 (VOID **) FvBlock\r
245 );\r
246}\r
247\r
248\r
249/**\r
250 Function returns an array of handles that support the SMM FVB protocol\r
fa0737a8 251 in a buffer allocated from pool.\r
8a2d4996 252\r
253 @param[out] NumberHandles The number of handles returned in Buffer.\r
254 @param[out] Buffer A pointer to the buffer to return the requested\r
255 array of handles that support SMM FVB protocol.\r
256\r
257 @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of\r
258 handles in Buffer was returned in NumberHandles.\r
259 @retval EFI_NOT_FOUND No SMM FVB handle was found.\r
260 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.\r
261 @retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.\r
262\r
263**/\r
264EFI_STATUS\r
265GetFvbCountAndBuffer (\r
266 OUT UINTN *NumberHandles,\r
267 OUT EFI_HANDLE **Buffer\r
268 )\r
269{\r
270 EFI_STATUS Status;\r
271 UINTN BufferSize;\r
272\r
273 if ((NumberHandles == NULL) || (Buffer == NULL)) {\r
274 return EFI_INVALID_PARAMETER;\r
275 }\r
276\r
277 BufferSize = 0;\r
278 *NumberHandles = 0;\r
279 *Buffer = NULL;\r
a855f63e 280 Status = gMmst->MmLocateHandle (\r
8a2d4996 281 ByProtocol,\r
282 &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
283 NULL,\r
284 &BufferSize,\r
285 *Buffer\r
286 );\r
287 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
288 return EFI_NOT_FOUND;\r
289 }\r
290\r
291 *Buffer = AllocatePool (BufferSize);\r
292 if (*Buffer == NULL) {\r
293 return EFI_OUT_OF_RESOURCES;\r
294 }\r
295\r
a855f63e 296 Status = gMmst->MmLocateHandle (\r
8a2d4996 297 ByProtocol,\r
298 &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
299 NULL,\r
300 &BufferSize,\r
301 *Buffer\r
302 );\r
303\r
304 *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
305 if (EFI_ERROR(Status)) {\r
306 *NumberHandles = 0;\r
5e5bb2a9
SZ
307 FreePool (*Buffer);\r
308 *Buffer = NULL;\r
8a2d4996 309 }\r
310\r
311 return Status;\r
312}\r
313\r
314\r
315/**\r
316 Get the variable statistics information from the information buffer pointed by gVariableInfo.\r
317\r
2445a70e 318 Caution: This function may be invoked at SMM runtime.\r
319 InfoEntry and InfoSize are external input. Care must be taken to make sure not security issue at runtime.\r
320\r
321 @param[in, out] InfoEntry A pointer to the buffer of variable information entry.\r
fa0737a8 322 On input, point to the variable information returned last time. if\r
2445a70e 323 InfoEntry->VendorGuid is zero, return the first information.\r
324 On output, point to the next variable information.\r
325 @param[in, out] InfoSize On input, the size of the variable information buffer.\r
326 On output, the returned variable information size.\r
8a2d4996 327\r
fa0737a8
SZ
328 @retval EFI_SUCCESS The variable information is found and returned successfully.\r
329 @retval EFI_UNSUPPORTED No variable inoformation exists in variable driver. The\r
330 PcdVariableCollectStatistics should be set TRUE to support it.\r
331 @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the next variable information.\r
332 @retval EFI_INVALID_PARAMETER Input parameter is invalid.\r
8a2d4996 333\r
334**/\r
335EFI_STATUS\r
336SmmVariableGetStatistics (\r
d00ed85e 337 IN OUT VARIABLE_INFO_ENTRY *InfoEntry,\r
8a2d4996 338 IN OUT UINTN *InfoSize\r
339 )\r
340{\r
d00ed85e 341 VARIABLE_INFO_ENTRY *VariableInfo;\r
d5aef955 342 UINTN NameSize;\r
8a2d4996 343 UINTN StatisticsInfoSize;\r
344 CHAR16 *InfoName;\r
d5aef955 345 UINTN InfoNameMaxSize;\r
5e5bb2a9
SZ
346 EFI_GUID VendorGuid;\r
347\r
fa0737a8
SZ
348 if (InfoEntry == NULL) {\r
349 return EFI_INVALID_PARAMETER;\r
350 }\r
351\r
352 VariableInfo = gVariableInfo;\r
8a2d4996 353 if (VariableInfo == NULL) {\r
354 return EFI_UNSUPPORTED;\r
355 }\r
356\r
d5aef955 357 StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY);\r
eb96e4f2 358 if (*InfoSize < StatisticsInfoSize) {\r
8a2d4996 359 *InfoSize = StatisticsInfoSize;\r
360 return EFI_BUFFER_TOO_SMALL;\r
361 }\r
362 InfoName = (CHAR16 *)(InfoEntry + 1);\r
d5aef955 363 InfoNameMaxSize = (*InfoSize - sizeof (VARIABLE_INFO_ENTRY));\r
8a2d4996 364\r
5e5bb2a9
SZ
365 CopyGuid (&VendorGuid, &InfoEntry->VendorGuid);\r
366\r
39cde03c 367 if (IsZeroGuid (&VendorGuid)) {\r
8a2d4996 368 //\r
369 // Return the first variable info\r
370 //\r
d5aef955
SZ
371 NameSize = StrSize (VariableInfo->Name);\r
372 StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + NameSize;\r
373 if (*InfoSize < StatisticsInfoSize) {\r
374 *InfoSize = StatisticsInfoSize;\r
375 return EFI_BUFFER_TOO_SMALL;\r
376 }\r
d00ed85e 377 CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
d5aef955 378 CopyMem (InfoName, VariableInfo->Name, NameSize);\r
8a2d4996 379 *InfoSize = StatisticsInfoSize;\r
380 return EFI_SUCCESS;\r
381 }\r
382\r
383 //\r
384 // Get the next variable info\r
385 //\r
386 while (VariableInfo != NULL) {\r
5e5bb2a9 387 if (CompareGuid (&VariableInfo->VendorGuid, &VendorGuid)) {\r
d5aef955
SZ
388 NameSize = StrSize (VariableInfo->Name);\r
389 if (NameSize <= InfoNameMaxSize) {\r
390 if (CompareMem (VariableInfo->Name, InfoName, NameSize) == 0) {\r
8a2d4996 391 //\r
392 // Find the match one\r
393 //\r
394 VariableInfo = VariableInfo->Next;\r
395 break;\r
396 }\r
397 }\r
398 }\r
399 VariableInfo = VariableInfo->Next;\r
400 };\r
fa0737a8 401\r
8a2d4996 402 if (VariableInfo == NULL) {\r
403 *InfoSize = 0;\r
404 return EFI_SUCCESS;\r
405 }\r
406\r
407 //\r
408 // Output the new variable info\r
409 //\r
d5aef955
SZ
410 NameSize = StrSize (VariableInfo->Name);\r
411 StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + NameSize;\r
8a2d4996 412 if (*InfoSize < StatisticsInfoSize) {\r
413 *InfoSize = StatisticsInfoSize;\r
414 return EFI_BUFFER_TOO_SMALL;\r
415 }\r
416\r
d00ed85e 417 CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
d5aef955 418 CopyMem (InfoName, VariableInfo->Name, NameSize);\r
8a2d4996 419 *InfoSize = StatisticsInfoSize;\r
fa0737a8 420\r
8a2d4996 421 return EFI_SUCCESS;\r
422}\r
423\r
424\r
425/**\r
426 Communication service SMI Handler entry.\r
427\r
428 This SMI handler provides services for the variable wrapper driver.\r
429\r
2445a70e 430 Caution: This function may receive untrusted input.\r
431 This variable data and communicate buffer are external input, so this function will do basic validation.\r
fa0737a8
SZ
432 Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),\r
433 VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),\r
2445a70e 434 SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
435\r
8a2d4996 436 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
437 @param[in] RegisterContext Points to an optional handler context which was specified when the\r
438 handler was registered.\r
439 @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
440 be conveyed from a non-SMM environment into an SMM environment.\r
441 @param[in, out] CommBufferSize The size of the CommBuffer.\r
442\r
fa0737a8 443 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers\r
8a2d4996 444 should still be called.\r
fa0737a8 445 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should\r
8a2d4996 446 still be called.\r
fa0737a8 447 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still\r
8a2d4996 448 be called.\r
449 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
450**/\r
451EFI_STATUS\r
452EFIAPI\r
453SmmVariableHandler (\r
454 IN EFI_HANDLE DispatchHandle,\r
455 IN CONST VOID *RegisterContext,\r
456 IN OUT VOID *CommBuffer,\r
457 IN OUT UINTN *CommBufferSize\r
458 )\r
459{\r
460 EFI_STATUS Status;\r
461 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
462 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
463 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;\r
464 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;\r
fa0737a8 465 SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *GetPayloadSize;\r
d00ed85e 466 VARIABLE_INFO_ENTRY *VariableInfo;\r
ff843847 467 SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;\r
efb01a10 468 SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
8a2d4996 469 UINTN InfoSize;\r
9d00d20e 470 UINTN NameBufferSize;\r
5e5bb2a9 471 UINTN CommBufferPayloadSize;\r
164a9b67 472 UINTN TempCommBufferSize;\r
8a2d4996 473\r
2445a70e 474 //\r
475 // If input is invalid, stop processing this SMI\r
476 //\r
477 if (CommBuffer == NULL || CommBufferSize == NULL) {\r
478 return EFI_SUCCESS;\r
479 }\r
480\r
164a9b67
SZ
481 TempCommBufferSize = *CommBufferSize;\r
482\r
483 if (TempCommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {\r
5e5bb2a9
SZ
484 DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n"));\r
485 return EFI_SUCCESS;\r
486 }\r
164a9b67 487 CommBufferPayloadSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
5e5bb2a9
SZ
488 if (CommBufferPayloadSize > mVariableBufferPayloadSize) {\r
489 DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));\r
2445a70e 490 return EFI_SUCCESS;\r
491 }\r
492\r
a855f63e 493 if (!VariableSmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
5e5bb2a9 494 DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
2445a70e 495 return EFI_SUCCESS;\r
496 }\r
8a2d4996 497\r
498 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer;\r
499 switch (SmmVariableFunctionHeader->Function) {\r
500 case SMM_VARIABLE_FUNCTION_GET_VARIABLE:\r
5e5bb2a9
SZ
501 if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
502 DEBUG ((EFI_D_ERROR, "GetVariable: SMM communication buffer size invalid!\n"));\r
503 return EFI_SUCCESS;\r
504 }\r
505 //\r
506 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
507 //\r
508 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
509 SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;\r
9d00d20e
SZ
510 if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
511 ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {\r
512 //\r
513 // Prevent InfoSize overflow happen\r
514 //\r
515 Status = EFI_ACCESS_DENIED;\r
516 goto EXIT;\r
517 }\r
fa0737a8 518 InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
2445a70e 519 + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;\r
520\r
521 //\r
522 // SMRAM range check already covered before\r
523 //\r
5e5bb2a9
SZ
524 if (InfoSize > CommBufferPayloadSize) {\r
525 DEBUG ((EFI_D_ERROR, "GetVariable: Data size exceed communication buffer size limit!\n"));\r
2445a70e 526 Status = EFI_ACCESS_DENIED;\r
527 goto EXIT;\r
528 }\r
529\r
e83d841f 530 //\r
49395ea0
HW
531 // The VariableSpeculationBarrier() call here is to ensure the previous\r
532 // range/content checks for the CommBuffer have been completed before the\r
533 // subsequent consumption of the CommBuffer content.\r
e83d841f 534 //\r
49395ea0 535 VariableSpeculationBarrier ();\r
9d00d20e
SZ
536 if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
537 //\r
538 // Make sure VariableName is A Null-terminated string.\r
539 //\r
540 Status = EFI_ACCESS_DENIED;\r
541 goto EXIT;\r
542 }\r
543\r
8a2d4996 544 Status = VariableServiceGetVariable (\r
545 SmmVariableHeader->Name,\r
546 &SmmVariableHeader->Guid,\r
547 &SmmVariableHeader->Attributes,\r
548 &SmmVariableHeader->DataSize,\r
549 (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize\r
550 );\r
5e5bb2a9 551 CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);\r
8a2d4996 552 break;\r
fa0737a8 553\r
8a2d4996 554 case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:\r
5e5bb2a9
SZ
555 if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
556 DEBUG ((EFI_D_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));\r
557 return EFI_SUCCESS;\r
558 }\r
559 //\r
560 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
561 //\r
562 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
563 GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) mVariableBufferPayload;\r
9d00d20e
SZ
564 if ((UINTN)(~0) - GetNextVariableName->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
565 //\r
566 // Prevent InfoSize overflow happen\r
567 //\r
568 Status = EFI_ACCESS_DENIED;\r
569 goto EXIT;\r
570 }\r
2445a70e 571 InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + GetNextVariableName->NameSize;\r
572\r
573 //\r
574 // SMRAM range check already covered before\r
575 //\r
5e5bb2a9
SZ
576 if (InfoSize > CommBufferPayloadSize) {\r
577 DEBUG ((EFI_D_ERROR, "GetNextVariableName: Data size exceed communication buffer size limit!\n"));\r
2445a70e 578 Status = EFI_ACCESS_DENIED;\r
579 goto EXIT;\r
580 }\r
581\r
5e5bb2a9 582 NameBufferSize = CommBufferPayloadSize - OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
9d00d20e
SZ
583 if (NameBufferSize < sizeof (CHAR16) || GetNextVariableName->Name[NameBufferSize/sizeof (CHAR16) - 1] != L'\0') {\r
584 //\r
585 // Make sure input VariableName is A Null-terminated string.\r
586 //\r
587 Status = EFI_ACCESS_DENIED;\r
588 goto EXIT;\r
589 }\r
590\r
8a2d4996 591 Status = VariableServiceGetNextVariableName (\r
592 &GetNextVariableName->NameSize,\r
593 GetNextVariableName->Name,\r
594 &GetNextVariableName->Guid\r
595 );\r
5e5bb2a9 596 CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);\r
8a2d4996 597 break;\r
fa0737a8 598\r
8a2d4996 599 case SMM_VARIABLE_FUNCTION_SET_VARIABLE:\r
5e5bb2a9
SZ
600 if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
601 DEBUG ((EFI_D_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));\r
602 return EFI_SUCCESS;\r
603 }\r
604 //\r
605 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
606 //\r
607 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
608 SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;\r
9d00d20e
SZ
609 if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
610 ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {\r
611 //\r
612 // Prevent InfoSize overflow happen\r
613 //\r
614 Status = EFI_ACCESS_DENIED;\r
615 goto EXIT;\r
616 }\r
d17c4eac 617 InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
618 + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;\r
619\r
620 //\r
621 // SMRAM range check already covered before\r
622 // Data buffer should not contain SMM range\r
623 //\r
5e5bb2a9
SZ
624 if (InfoSize > CommBufferPayloadSize) {\r
625 DEBUG ((EFI_D_ERROR, "SetVariable: Data size exceed communication buffer size limit!\n"));\r
d17c4eac 626 Status = EFI_ACCESS_DENIED;\r
627 goto EXIT;\r
628 }\r
629\r
e83d841f 630 //\r
49395ea0
HW
631 // The VariableSpeculationBarrier() call here is to ensure the previous\r
632 // range/content checks for the CommBuffer have been completed before the\r
633 // subsequent consumption of the CommBuffer content.\r
e83d841f 634 //\r
49395ea0 635 VariableSpeculationBarrier ();\r
9d00d20e
SZ
636 if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
637 //\r
638 // Make sure VariableName is A Null-terminated string.\r
639 //\r
640 Status = EFI_ACCESS_DENIED;\r
641 goto EXIT;\r
642 }\r
643\r
8a2d4996 644 Status = VariableServiceSetVariable (\r
645 SmmVariableHeader->Name,\r
646 &SmmVariableHeader->Guid,\r
647 SmmVariableHeader->Attributes,\r
648 SmmVariableHeader->DataSize,\r
649 (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize\r
650 );\r
651 break;\r
fa0737a8 652\r
8a2d4996 653 case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:\r
5e5bb2a9
SZ
654 if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {\r
655 DEBUG ((EFI_D_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));\r
656 return EFI_SUCCESS;\r
2445a70e 657 }\r
5e5bb2a9 658 QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data;\r
2445a70e 659\r
8a2d4996 660 Status = VariableServiceQueryVariableInfo (\r
661 QueryVariableInfo->Attributes,\r
662 &QueryVariableInfo->MaximumVariableStorageSize,\r
663 &QueryVariableInfo->RemainingVariableStorageSize,\r
664 &QueryVariableInfo->MaximumVariableSize\r
665 );\r
666 break;\r
667\r
fa0737a8
SZ
668 case SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE:\r
669 if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE)) {\r
670 DEBUG ((EFI_D_ERROR, "GetPayloadSize: SMM communication buffer size invalid!\n"));\r
671 return EFI_SUCCESS;\r
672 }\r
673 GetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *) SmmVariableFunctionHeader->Data;\r
674 GetPayloadSize->VariablePayloadSize = mVariableBufferPayloadSize;\r
675 Status = EFI_SUCCESS;\r
676 break;\r
677\r
8a2d4996 678 case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:\r
876ac395 679 if (AtRuntime()) {\r
680 Status = EFI_UNSUPPORTED;\r
681 break;\r
682 }\r
8021f4c7 683 if (!mEndOfDxe) {\r
f1304280 684 MorLockInitAtEndOfDxe ();\r
8021f4c7
SZ
685 mEndOfDxe = TRUE;\r
686 VarCheckLibInitializeAtEndOfDxe (NULL);\r
687 //\r
688 // The initialization for variable quota.\r
689 //\r
690 InitializeVariableQuota ();\r
691 }\r
8a2d4996 692 ReclaimForOS ();\r
693 Status = EFI_SUCCESS;\r
694 break;\r
fa0737a8 695\r
8a2d4996 696 case SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE:\r
697 mAtRuntime = TRUE;\r
698 Status = EFI_SUCCESS;\r
699 break;\r
700\r
701 case SMM_VARIABLE_FUNCTION_GET_STATISTICS:\r
d00ed85e 702 VariableInfo = (VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data;\r
164a9b67 703 InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
2445a70e 704\r
705 //\r
fa0737a8
SZ
706 // Do not need to check SmmVariableFunctionHeader->Data in SMRAM here.\r
707 // It is covered by previous CommBuffer check\r
2445a70e 708 //\r
fa0737a8 709\r
62016c1e
SZ
710 //\r
711 // Do not need to check CommBufferSize buffer as it should point to SMRAM\r
712 // that was used by SMM core to cache CommSize from SmmCommunication protocol.\r
713 //\r
2445a70e 714\r
8a2d4996 715 Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);\r
3f5c168f 716 *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
8a2d4996 717 break;\r
718\r
ff843847 719 case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:\r
51547bb8 720 if (mEndOfDxe) {\r
ff843847 721 Status = EFI_ACCESS_DENIED;\r
51547bb8
RN
722 } else {\r
723 VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data;\r
724 Status = VariableLockRequestToLock (\r
725 NULL,\r
726 VariableToLock->Name,\r
727 &VariableToLock->Guid\r
728 );\r
ff843847 729 }\r
ff843847 730 break;\r
efb01a10
SZ
731 case SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET:\r
732 if (mEndOfDxe) {\r
733 Status = EFI_ACCESS_DENIED;\r
734 } else {\r
735 CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *) SmmVariableFunctionHeader->Data;\r
736 Status = VarCheckVariablePropertySet (\r
737 CommVariableProperty->Name,\r
738 &CommVariableProperty->Guid,\r
739 &CommVariableProperty->VariableProperty\r
740 );\r
741 }\r
742 break;\r
743 case SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET:\r
744 if (CommBufferPayloadSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
745 DEBUG ((EFI_D_ERROR, "VarCheckVariablePropertyGet: SMM communication buffer size invalid!\n"));\r
746 return EFI_SUCCESS;\r
747 }\r
748 //\r
749 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
750 //\r
751 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
752 CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *) mVariableBufferPayload;\r
753 if ((UINTN) (~0) - CommVariableProperty->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
754 //\r
755 // Prevent InfoSize overflow happen\r
756 //\r
757 Status = EFI_ACCESS_DENIED;\r
758 goto EXIT;\r
759 }\r
760 InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + CommVariableProperty->NameSize;\r
761\r
762 //\r
763 // SMRAM range check already covered before\r
764 //\r
765 if (InfoSize > CommBufferPayloadSize) {\r
766 DEBUG ((EFI_D_ERROR, "VarCheckVariablePropertyGet: Data size exceed communication buffer size limit!\n"));\r
767 Status = EFI_ACCESS_DENIED;\r
768 goto EXIT;\r
769 }\r
770\r
e83d841f 771 //\r
49395ea0
HW
772 // The VariableSpeculationBarrier() call here is to ensure the previous\r
773 // range/content checks for the CommBuffer have been completed before the\r
774 // subsequent consumption of the CommBuffer content.\r
e83d841f 775 //\r
49395ea0 776 VariableSpeculationBarrier ();\r
efb01a10
SZ
777 if (CommVariableProperty->NameSize < sizeof (CHAR16) || CommVariableProperty->Name[CommVariableProperty->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
778 //\r
779 // Make sure VariableName is A Null-terminated string.\r
780 //\r
781 Status = EFI_ACCESS_DENIED;\r
782 goto EXIT;\r
783 }\r
784\r
785 Status = VarCheckVariablePropertyGet (\r
786 CommVariableProperty->Name,\r
787 &CommVariableProperty->Guid,\r
788 &CommVariableProperty->VariableProperty\r
789 );\r
790 CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);\r
791 break;\r
ff843847 792\r
8a2d4996 793 default:\r
8a2d4996 794 Status = EFI_UNSUPPORTED;\r
795 }\r
796\r
2445a70e 797EXIT:\r
798\r
8a2d4996 799 SmmVariableFunctionHeader->ReturnStatus = Status;\r
800\r
801 return EFI_SUCCESS;\r
802}\r
803\r
ff843847
RN
804/**\r
805 SMM END_OF_DXE protocol notification event handler.\r
806\r
807 @param Protocol Points to the protocol's unique identifier\r
808 @param Interface Points to the interface instance\r
809 @param Handle The handle on which the interface was installed\r
810\r
811 @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully\r
812\r
813**/\r
814EFI_STATUS\r
815EFIAPI\r
816SmmEndOfDxeCallback (\r
817 IN CONST EFI_GUID *Protocol,\r
818 IN VOID *Interface,\r
819 IN EFI_HANDLE Handle\r
820 )\r
821{\r
8021f4c7 822 DEBUG ((EFI_D_INFO, "[Variable]SMM_END_OF_DXE is signaled\n"));\r
f1304280 823 MorLockInitAtEndOfDxe ();\r
ff843847 824 mEndOfDxe = TRUE;\r
8021f4c7 825 VarCheckLibInitializeAtEndOfDxe (NULL);\r
4edb1866
SZ
826 //\r
827 // The initialization for variable quota.\r
828 //\r
829 InitializeVariableQuota ();\r
0fb5e515
SZ
830 if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) {\r
831 ReclaimForOS ();\r
832 }\r
8021f4c7 833\r
ff843847
RN
834 return EFI_SUCCESS;\r
835}\r
8a2d4996 836\r
b59fd889
SZ
837/**\r
838 Initializes variable write service for SMM.\r
839\r
840**/\r
841VOID\r
842VariableWriteServiceInitializeSmm (\r
843 VOID\r
844 )\r
845{\r
846 EFI_STATUS Status;\r
847\r
848 Status = VariableWriteServiceInitialize ();\r
849 if (EFI_ERROR (Status)) {\r
850 DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));\r
851 }\r
852\r
853 //\r
854 // Notify the variable wrapper driver the variable write service is ready\r
855 //\r
856 VariableNotifySmmWriteReady ();\r
857}\r
858\r
8a2d4996 859/**\r
860 SMM Fault Tolerant Write protocol notification event handler.\r
861\r
fa0737a8 862 Non-Volatile variable write may needs FTW protocol to reclaim when\r
8a2d4996 863 writting variable.\r
fa0737a8 864\r
8a2d4996 865 @param Protocol Points to the protocol's unique identifier\r
866 @param Interface Points to the interface instance\r
867 @param Handle The handle on which the interface was installed\r
868\r
869 @retval EFI_SUCCESS SmmEventCallback runs successfully\r
870 @retval EFI_NOT_FOUND The Fvb protocol for variable is not found.\r
fa0737a8 871\r
8a2d4996 872 **/\r
873EFI_STATUS\r
874EFIAPI\r
875SmmFtwNotificationEvent (\r
876 IN CONST EFI_GUID *Protocol,\r
877 IN VOID *Interface,\r
878 IN EFI_HANDLE Handle\r
879 )\r
880{\r
881 EFI_STATUS Status;\r
904e0ca9 882 EFI_PHYSICAL_ADDRESS VariableStoreBase;\r
8a2d4996 883 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
884 EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;\r
885 EFI_PHYSICAL_ADDRESS NvStorageVariableBase;\r
2c4b18e0 886 UINTN FtwMaxBlockSize;\r
fa0737a8 887\r
8a2d4996 888 if (mVariableModuleGlobal->FvbInstance != NULL) {\r
889 return EFI_SUCCESS;\r
890 }\r
891\r
892 //\r
893 // Ensure SMM FTW protocol is installed.\r
894 //\r
5c7fa429 895 Status = GetFtwProtocol ((VOID **)&FtwProtocol);\r
8a2d4996 896 if (EFI_ERROR (Status)) {\r
897 return Status;\r
898 }\r
899\r
2c4b18e0
SZ
900 Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);\r
901 if (!EFI_ERROR (Status)) {\r
902 ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);\r
903 }\r
904\r
904e0ca9
SZ
905 NvStorageVariableBase = NV_STORAGE_VARIABLE_BASE;\r
906 VariableStoreBase = NvStorageVariableBase + mNvFvHeaderCache->HeaderLength;\r
907\r
908 //\r
909 // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.\r
910 //\r
911 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
912\r
8a2d4996 913 //\r
914 // Find the proper FVB protocol for variable.\r
915 //\r
8a2d4996 916 Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);\r
917 if (EFI_ERROR (Status)) {\r
918 return EFI_NOT_FOUND;\r
919 }\r
920\r
921 mVariableModuleGlobal->FvbInstance = FvbProtocol;\r
fa0737a8 922\r
8a2d4996 923 //\r
b59fd889 924 // Initializes variable write service after FTW was ready.\r
8a2d4996 925 //\r
b59fd889 926 VariableWriteServiceInitializeSmm ();\r
fa0737a8 927\r
8a2d4996 928 return EFI_SUCCESS;\r
929}\r
930\r
931\r
932/**\r
933 Variable Driver main entry point. The Variable driver places the 4 EFI\r
fa0737a8 934 runtime services in the EFI System Table and installs arch protocols\r
d00ed85e 935 for variable read and write services being available. It also registers\r
8a2d4996 936 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
937\r
8a2d4996 938 @retval EFI_SUCCESS Variable service successfully initialized.\r
939\r
940**/\r
941EFI_STATUS\r
942EFIAPI\r
a855f63e
AB
943MmVariableServiceInitialize (\r
944 VOID\r
8a2d4996 945 )\r
946{\r
947 EFI_STATUS Status;\r
948 EFI_HANDLE VariableHandle;\r
949 VOID *SmmFtwRegistration;\r
ff843847 950 VOID *SmmEndOfDxeRegistration;\r
2445a70e 951\r
8a2d4996 952 //\r
953 // Variable initialize.\r
954 //\r
955 Status = VariableCommonInitialize ();\r
956 ASSERT_EFI_ERROR (Status);\r
957\r
958 //\r
959 // Install the Smm Variable Protocol on a new handle.\r
960 //\r
961 VariableHandle = NULL;\r
a855f63e 962 Status = gMmst->MmInstallProtocolInterface (\r
8a2d4996 963 &VariableHandle,\r
964 &gEfiSmmVariableProtocolGuid,\r
965 EFI_NATIVE_INTERFACE,\r
966 &gSmmVariable\r
967 );\r
968 ASSERT_EFI_ERROR (Status);\r
969\r
a855f63e 970 Status = gMmst->MmInstallProtocolInterface (\r
efb01a10
SZ
971 &VariableHandle,\r
972 &gEdkiiSmmVarCheckProtocolGuid,\r
973 EFI_NATIVE_INTERFACE,\r
974 &mSmmVarCheck\r
975 );\r
976 ASSERT_EFI_ERROR (Status);\r
977\r
9b4a2032 978 mVariableBufferPayloadSize = GetMaxVariableSize () +\r
fa0737a8 979 OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - GetVariableHeaderSize ();\r
5e5bb2a9 980\r
a855f63e 981 Status = gMmst->MmAllocatePool (\r
5e5bb2a9
SZ
982 EfiRuntimeServicesData,\r
983 mVariableBufferPayloadSize,\r
984 (VOID **)&mVariableBufferPayload\r
985 );\r
986 ASSERT_EFI_ERROR (Status);\r
987\r
8a2d4996 988 ///\r
989 /// Register SMM variable SMI handler\r
990 ///\r
991 VariableHandle = NULL;\r
a855f63e 992 Status = gMmst->MmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);\r
8a2d4996 993 ASSERT_EFI_ERROR (Status);\r
fa0737a8 994\r
8a2d4996 995 //\r
996 // Notify the variable wrapper driver the variable service is ready\r
997 //\r
a855f63e 998 VariableNotifySmmReady ();\r
fa0737a8 999\r
ff843847
RN
1000 //\r
1001 // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.\r
1002 //\r
a855f63e
AB
1003 Status = gMmst->MmRegisterProtocolNotify (\r
1004 &gEfiMmEndOfDxeProtocolGuid,\r
ff843847
RN
1005 SmmEndOfDxeCallback,\r
1006 &SmmEndOfDxeRegistration\r
1007 );\r
1008 ASSERT_EFI_ERROR (Status);\r
1009\r
7cd69959
SZ
1010 if (!PcdGetBool (PcdEmuVariableNvModeEnable)) {\r
1011 //\r
1012 // Register FtwNotificationEvent () notify function.\r
1013 //\r
1014 Status = gMmst->MmRegisterProtocolNotify (\r
1015 &gEfiSmmFaultTolerantWriteProtocolGuid,\r
1016 SmmFtwNotificationEvent,\r
1017 &SmmFtwRegistration\r
1018 );\r
1019 ASSERT_EFI_ERROR (Status);\r
1020\r
1021 SmmFtwNotificationEvent (NULL, NULL, NULL);\r
1022 } else {\r
1023 //\r
1024 // Emulated non-volatile variable mode does not depend on FVB and FTW.\r
1025 //\r
1026 VariableWriteServiceInitializeSmm ();\r
1027 }\r
fa0737a8 1028\r
8a2d4996 1029 return EFI_SUCCESS;\r
1030}\r
1031\r
1032\r