]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / VariableSmmRuntimeDxe.c
CommitLineData
8a2d4996 1/** @file\r
8a2d4996 2 Implement all four UEFI Runtime Variable services for the nonvolatile\r
3 and volatile storage space and install variable architecture protocol\r
4 based on SMM variable module.\r
5\r
18a7dbbc
SZ
6 Caution: This module requires additional review when modified.\r
7 This driver will have external input - variable data.\r
8 This external input must be validated carefully to avoid security issue like\r
9 buffer overflow, integer overflow.\r
10\r
11 RuntimeServiceGetVariable() and RuntimeServiceSetVariable() are external API\r
12 to receive data buffer. The size should be checked carefully.\r
13\r
14 InitCommunicateBuffer() is really function to check the variable data size.\r
15\r
aab3b9b9 16Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>\r
edf88807 17Copyright (c) Microsoft Corporation.<BR>\r
9d510e61 18SPDX-License-Identifier: BSD-2-Clause-Patent\r
8a2d4996 19\r
20**/\r
d00ed85e 21#include <PiDxe.h>\r
8a2d4996 22#include <Protocol/VariableWrite.h>\r
23#include <Protocol/Variable.h>\r
be4e0cfb 24#include <Protocol/MmCommunication2.h>\r
d00ed85e 25#include <Protocol/SmmVariable.h>\r
ff843847 26#include <Protocol/VariableLock.h>\r
efb01a10 27#include <Protocol/VarCheck.h>\r
8a2d4996 28\r
29#include <Library/UefiBootServicesTableLib.h>\r
30#include <Library/UefiRuntimeServicesTableLib.h>\r
31#include <Library/MemoryAllocationLib.h>\r
32#include <Library/UefiDriverEntryPoint.h>\r
33#include <Library/UefiRuntimeLib.h>\r
34#include <Library/BaseMemoryLib.h>\r
35#include <Library/DebugLib.h>\r
8a2d4996 36#include <Library/UefiLib.h>\r
37#include <Library/BaseLib.h>\r
f463dbad 38#include <Library/MmUnblockMemoryLib.h>\r
8a2d4996 39\r
40#include <Guid/EventGroup.h>\r
d00ed85e 41#include <Guid/SmmVariableCommon.h>\r
8a2d4996 42\r
00663d04 43#include "PrivilegePolymorphic.h"\r
aab3b9b9 44#include "VariableParsing.h"\r
00663d04 45\r
1436aea4
MK
46EFI_HANDLE mHandle = NULL;\r
47EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;\r
48EFI_EVENT mVirtualAddressChangeEvent = NULL;\r
49EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication2 = NULL;\r
50UINT8 *mVariableBuffer = NULL;\r
51UINT8 *mVariableBufferPhysical = NULL;\r
52VARIABLE_INFO_ENTRY *mVariableInfo = NULL;\r
53VARIABLE_STORE_HEADER *mVariableRuntimeHobCacheBuffer = NULL;\r
54VARIABLE_STORE_HEADER *mVariableRuntimeNvCacheBuffer = NULL;\r
55VARIABLE_STORE_HEADER *mVariableRuntimeVolatileCacheBuffer = NULL;\r
56UINTN mVariableBufferSize;\r
57UINTN mVariableRuntimeHobCacheBufferSize;\r
58UINTN mVariableRuntimeNvCacheBufferSize;\r
59UINTN mVariableRuntimeVolatileCacheBufferSize;\r
60UINTN mVariableBufferPayloadSize;\r
61BOOLEAN mVariableRuntimeCachePendingUpdate;\r
62BOOLEAN mVariableRuntimeCacheReadLock;\r
63BOOLEAN mVariableAuthFormat;\r
64BOOLEAN mHobFlushComplete;\r
65EFI_LOCK mVariableServicesLock;\r
66EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;\r
67EDKII_VAR_CHECK_PROTOCOL mVarCheck;\r
8a2d4996 68\r
b6490426
BB
69/**\r
70 The logic to initialize the VariablePolicy engine is in its own file.\r
71\r
72**/\r
73EFI_STATUS\r
74EFIAPI\r
75VariablePolicySmmDxeMain (\r
1436aea4
MK
76 IN EFI_HANDLE ImageHandle,\r
77 IN EFI_SYSTEM_TABLE *SystemTable\r
b6490426
BB
78 );\r
79\r
dc9bd6ed
ZC
80/**\r
81 Some Secure Boot Policy Variable may update following other variable changes(SecureBoot follows PK change, etc).\r
82 Record their initial State when variable write service is ready.\r
83\r
84**/\r
85VOID\r
86EFIAPI\r
1436aea4 87RecordSecureBootPolicyVarData (\r
dc9bd6ed
ZC
88 VOID\r
89 );\r
90\r
6ed1ec59
SZ
91/**\r
92 Acquires lock only at boot time. Simply returns at runtime.\r
93\r
94 This is a temperary function that will be removed when\r
95 EfiAcquireLock() in UefiLib can handle the call in UEFI\r
96 Runtimer driver in RT phase.\r
97 It calls EfiAcquireLock() at boot time, and simply returns\r
98 at runtime.\r
99\r
100 @param Lock A pointer to the lock to acquire.\r
101\r
102**/\r
103VOID\r
104AcquireLockOnlyAtBootTime (\r
1436aea4 105 IN EFI_LOCK *Lock\r
6ed1ec59
SZ
106 )\r
107{\r
108 if (!EfiAtRuntime ()) {\r
109 EfiAcquireLock (Lock);\r
110 }\r
111}\r
112\r
113/**\r
114 Releases lock only at boot time. Simply returns at runtime.\r
115\r
116 This is a temperary function which will be removed when\r
117 EfiReleaseLock() in UefiLib can handle the call in UEFI\r
118 Runtimer driver in RT phase.\r
119 It calls EfiReleaseLock() at boot time and simply returns\r
120 at runtime.\r
121\r
122 @param Lock A pointer to the lock to release.\r
123\r
124**/\r
125VOID\r
126ReleaseLockOnlyAtBootTime (\r
1436aea4 127 IN EFI_LOCK *Lock\r
6ed1ec59
SZ
128 )\r
129{\r
130 if (!EfiAtRuntime ()) {\r
131 EfiReleaseLock (Lock);\r
132 }\r
133}\r
8a2d4996 134\r
aab3b9b9
MK
135/**\r
136 Return TRUE if ExitBootServices () has been called.\r
137\r
138 @retval TRUE If ExitBootServices () has been called. FALSE if ExitBootServices () has not been called.\r
139**/\r
140BOOLEAN\r
141AtRuntime (\r
142 VOID\r
143 )\r
144{\r
145 return EfiAtRuntime ();\r
146}\r
147\r
148/**\r
149 Initialize the variable cache buffer as an empty variable store.\r
150\r
151 @param[out] VariableCacheBuffer A pointer to pointer of a cache variable store.\r
152 @param[in,out] TotalVariableCacheSize On input, the minimum size needed for the UEFI variable store cache\r
153 buffer that is allocated. On output, the actual size of the buffer allocated.\r
154 If TotalVariableCacheSize is zero, a buffer will not be allocated and the\r
155 function will return with EFI_SUCCESS.\r
156\r
157 @retval EFI_SUCCESS The variable cache was allocated and initialized successfully.\r
158 @retval EFI_INVALID_PARAMETER A given pointer is NULL or an invalid variable store size was specified.\r
159 @retval EFI_OUT_OF_RESOURCES Insufficient resources are available to allocate the variable store cache buffer.\r
160\r
161**/\r
162EFI_STATUS\r
163InitVariableCache (\r
1436aea4
MK
164 OUT VARIABLE_STORE_HEADER **VariableCacheBuffer,\r
165 IN OUT UINTN *TotalVariableCacheSize\r
aab3b9b9
MK
166 )\r
167{\r
1436aea4
MK
168 VARIABLE_STORE_HEADER *VariableCacheStorePtr;\r
169 EFI_STATUS Status;\r
aab3b9b9
MK
170\r
171 if (TotalVariableCacheSize == NULL) {\r
172 return EFI_INVALID_PARAMETER;\r
173 }\r
1436aea4 174\r
aab3b9b9
MK
175 if (*TotalVariableCacheSize == 0) {\r
176 return EFI_SUCCESS;\r
177 }\r
1436aea4
MK
178\r
179 if ((VariableCacheBuffer == NULL) || (*TotalVariableCacheSize < sizeof (VARIABLE_STORE_HEADER))) {\r
aab3b9b9
MK
180 return EFI_INVALID_PARAMETER;\r
181 }\r
1436aea4 182\r
aab3b9b9
MK
183 *TotalVariableCacheSize = ALIGN_VALUE (*TotalVariableCacheSize, sizeof (UINT32));\r
184\r
185 //\r
186 // Allocate NV Storage Cache and initialize it to all 1's (like an erased FV)\r
187 //\r
1436aea4
MK
188 *VariableCacheBuffer = (VARIABLE_STORE_HEADER *)AllocateRuntimePages (\r
189 EFI_SIZE_TO_PAGES (*TotalVariableCacheSize)\r
190 );\r
aab3b9b9
MK
191 if (*VariableCacheBuffer == NULL) {\r
192 return EFI_OUT_OF_RESOURCES;\r
193 }\r
f463dbad
KQ
194\r
195 //\r
196 // Request to unblock the newly allocated cache region to be accessible from inside MM\r
197 //\r
198 Status = MmUnblockMemoryRequest (\r
1436aea4
MK
199 (EFI_PHYSICAL_ADDRESS)(UINTN)*VariableCacheBuffer,\r
200 EFI_SIZE_TO_PAGES (*TotalVariableCacheSize)\r
201 );\r
202 if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) {\r
f463dbad
KQ
203 return Status;\r
204 }\r
205\r
aab3b9b9 206 VariableCacheStorePtr = *VariableCacheBuffer;\r
1436aea4 207 SetMem32 ((VOID *)VariableCacheStorePtr, *TotalVariableCacheSize, (UINT32)0xFFFFFFFF);\r
aab3b9b9 208\r
1436aea4
MK
209 ZeroMem ((VOID *)VariableCacheStorePtr, sizeof (VARIABLE_STORE_HEADER));\r
210 VariableCacheStorePtr->Size = (UINT32)*TotalVariableCacheSize;\r
211 VariableCacheStorePtr->Format = VARIABLE_STORE_FORMATTED;\r
212 VariableCacheStorePtr->State = VARIABLE_STORE_HEALTHY;\r
aab3b9b9
MK
213\r
214 return EFI_SUCCESS;\r
215}\r
216\r
8a2d4996 217/**\r
218 Initialize the communicate buffer using DataSize and Function.\r
219\r
220 The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +\r
221 DataSize.\r
222\r
18a7dbbc
SZ
223 Caution: This function may receive untrusted input.\r
224 The data size external input, so this function will validate it carefully to avoid buffer overflow.\r
225\r
8a2d4996 226 @param[out] DataPtr Points to the data in the communicate buffer.\r
227 @param[in] DataSize The data size to send to SMM.\r
228 @param[in] Function The function number to initialize the communicate header.\r
fa0737a8 229\r
8a2d4996 230 @retval EFI_INVALID_PARAMETER The data size is too big.\r
231 @retval EFI_SUCCESS Find the specified variable.\r
232\r
233**/\r
234EFI_STATUS\r
235InitCommunicateBuffer (\r
1436aea4
MK
236 OUT VOID **DataPtr OPTIONAL,\r
237 IN UINTN DataSize,\r
238 IN UINTN Function\r
8a2d4996 239 )\r
240{\r
1436aea4
MK
241 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
242 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
8a2d4996 243\r
8a2d4996 244 if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {\r
245 return EFI_INVALID_PARAMETER;\r
246 }\r
247\r
1436aea4 248 SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mVariableBuffer;\r
8a2d4996 249 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
250 SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
fa0737a8 251\r
1436aea4 252 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;\r
8a2d4996 253 SmmVariableFunctionHeader->Function = Function;\r
254 if (DataPtr != NULL) {\r
255 *DataPtr = SmmVariableFunctionHeader->Data;\r
256 }\r
257\r
258 return EFI_SUCCESS;\r
259}\r
260\r
8a2d4996 261/**\r
262 Send the data in communicate buffer to SMM.\r
263\r
264 @param[in] DataSize This size of the function header and the data.\r
265\r
32732a33 266 @retval EFI_SUCCESS Success is returned from the functin in SMM.\r
fa0737a8
SZ
267 @retval Others Failure is returned from the function in SMM.\r
268\r
8a2d4996 269**/\r
270EFI_STATUS\r
271SendCommunicateBuffer (\r
1436aea4 272 IN UINTN DataSize\r
8a2d4996 273 )\r
274{\r
1436aea4
MK
275 EFI_STATUS Status;\r
276 UINTN CommSize;\r
277 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
278 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
fa0737a8 279\r
8a2d4996 280 CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
1436aea4
MK
281 Status = mMmCommunication2->Communicate (\r
282 mMmCommunication2,\r
283 mVariableBufferPhysical,\r
284 mVariableBuffer,\r
285 &CommSize\r
286 );\r
8a2d4996 287 ASSERT_EFI_ERROR (Status);\r
288\r
1436aea4 289 SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mVariableBuffer;\r
8a2d4996 290 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;\r
1436aea4 291 return SmmVariableFunctionHeader->ReturnStatus;\r
8a2d4996 292}\r
293\r
ff843847
RN
294/**\r
295 Mark a variable that will become read-only after leaving the DXE phase of execution.\r
296\r
297 @param[in] This The VARIABLE_LOCK_PROTOCOL instance.\r
298 @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.\r
299 @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.\r
300\r
301 @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked\r
302 as pending to be read-only.\r
303 @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.\r
304 Or VariableName is an empty string.\r
305 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
306 already been signaled.\r
307 @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.\r
308**/\r
309EFI_STATUS\r
310EFIAPI\r
311VariableLockRequestToLock (\r
1436aea4
MK
312 IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,\r
313 IN CHAR16 *VariableName,\r
314 IN EFI_GUID *VendorGuid\r
ff843847
RN
315 )\r
316{\r
1436aea4
MK
317 EFI_STATUS Status;\r
318 UINTN VariableNameSize;\r
319 UINTN PayloadSize;\r
320 SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;\r
ff843847 321\r
1436aea4 322 if ((VariableName == NULL) || (VariableName[0] == 0) || (VendorGuid == NULL)) {\r
ff843847
RN
323 return EFI_INVALID_PARAMETER;\r
324 }\r
325\r
51547bb8 326 VariableNameSize = StrSize (VariableName);\r
4e1005ec 327 VariableToLock = NULL;\r
51547bb8
RN
328\r
329 //\r
330 // If VariableName exceeds SMM payload limit. Return failure\r
331 //\r
332 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {\r
333 return EFI_INVALID_PARAMETER;\r
334 }\r
335\r
1436aea4 336 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
ff843847
RN
337\r
338 //\r
339 // Init the communicate buffer. The buffer data size is:\r
340 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
341 //\r
51547bb8 342 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize;\r
1436aea4 343 Status = InitCommunicateBuffer ((VOID **)&VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE);\r
ff843847
RN
344 if (EFI_ERROR (Status)) {\r
345 goto Done;\r
346 }\r
1436aea4 347\r
ff843847
RN
348 ASSERT (VariableToLock != NULL);\r
349\r
350 CopyGuid (&VariableToLock->Guid, VendorGuid);\r
51547bb8 351 VariableToLock->NameSize = VariableNameSize;\r
ff843847
RN
352 CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize);\r
353\r
354 //\r
355 // Send data to SMM.\r
356 //\r
357 Status = SendCommunicateBuffer (PayloadSize);\r
358\r
359Done:\r
360 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
361 return Status;\r
362}\r
8a2d4996 363\r
efb01a10
SZ
364/**\r
365 Register SetVariable check handler.\r
366\r
367 @param[in] Handler Pointer to check handler.\r
368\r
369 @retval EFI_SUCCESS The SetVariable check handler was registered successfully.\r
370 @retval EFI_INVALID_PARAMETER Handler is NULL.\r
371 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
372 already been signaled.\r
373 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the SetVariable check handler register request.\r
374 @retval EFI_UNSUPPORTED This interface is not implemented.\r
375 For example, it is unsupported in VarCheck protocol if both VarCheck and SmmVarCheck protocols are present.\r
376\r
377**/\r
378EFI_STATUS\r
379EFIAPI\r
380VarCheckRegisterSetVariableCheckHandler (\r
1436aea4 381 IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler\r
efb01a10
SZ
382 )\r
383{\r
384 return EFI_UNSUPPORTED;\r
385}\r
386\r
387/**\r
388 Variable property set.\r
389\r
390 @param[in] Name Pointer to the variable name.\r
391 @param[in] Guid Pointer to the vendor GUID.\r
392 @param[in] VariableProperty Pointer to the input variable property.\r
393\r
394 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was set successfully.\r
395 @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string,\r
396 or the fields of VariableProperty are not valid.\r
397 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
398 already been signaled.\r
399 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the variable property set request.\r
400\r
401**/\r
402EFI_STATUS\r
403EFIAPI\r
404VarCheckVariablePropertySet (\r
1436aea4
MK
405 IN CHAR16 *Name,\r
406 IN EFI_GUID *Guid,\r
407 IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty\r
efb01a10
SZ
408 )\r
409{\r
1436aea4
MK
410 EFI_STATUS Status;\r
411 UINTN VariableNameSize;\r
412 UINTN PayloadSize;\r
413 SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
efb01a10 414\r
1436aea4 415 if ((Name == NULL) || (Name[0] == 0) || (Guid == NULL)) {\r
efb01a10
SZ
416 return EFI_INVALID_PARAMETER;\r
417 }\r
418\r
419 if (VariableProperty == NULL) {\r
420 return EFI_INVALID_PARAMETER;\r
421 }\r
422\r
423 if (VariableProperty->Revision != VAR_CHECK_VARIABLE_PROPERTY_REVISION) {\r
424 return EFI_INVALID_PARAMETER;\r
425 }\r
426\r
1436aea4 427 VariableNameSize = StrSize (Name);\r
efb01a10
SZ
428 CommVariableProperty = NULL;\r
429\r
430 //\r
431 // If VariableName exceeds SMM payload limit. Return failure\r
432 //\r
433 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
434 return EFI_INVALID_PARAMETER;\r
435 }\r
436\r
437 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
438\r
439 //\r
440 // Init the communicate buffer. The buffer data size is:\r
441 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
442 //\r
443 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + VariableNameSize;\r
1436aea4 444 Status = InitCommunicateBuffer ((VOID **)&CommVariableProperty, PayloadSize, SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET);\r
efb01a10
SZ
445 if (EFI_ERROR (Status)) {\r
446 goto Done;\r
447 }\r
1436aea4 448\r
efb01a10
SZ
449 ASSERT (CommVariableProperty != NULL);\r
450\r
451 CopyGuid (&CommVariableProperty->Guid, Guid);\r
452 CopyMem (&CommVariableProperty->VariableProperty, VariableProperty, sizeof (*VariableProperty));\r
453 CommVariableProperty->NameSize = VariableNameSize;\r
454 CopyMem (CommVariableProperty->Name, Name, CommVariableProperty->NameSize);\r
455\r
456 //\r
457 // Send data to SMM.\r
458 //\r
459 Status = SendCommunicateBuffer (PayloadSize);\r
460\r
461Done:\r
462 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
463 return Status;\r
464}\r
465\r
466/**\r
467 Variable property get.\r
468\r
469 @param[in] Name Pointer to the variable name.\r
470 @param[in] Guid Pointer to the vendor GUID.\r
471 @param[out] VariableProperty Pointer to the output variable property.\r
472\r
473 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was got successfully.\r
474 @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string.\r
475 @retval EFI_NOT_FOUND The property of variable specified by the Name and Guid was not found.\r
476\r
477**/\r
478EFI_STATUS\r
479EFIAPI\r
480VarCheckVariablePropertyGet (\r
1436aea4
MK
481 IN CHAR16 *Name,\r
482 IN EFI_GUID *Guid,\r
483 OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty\r
efb01a10
SZ
484 )\r
485{\r
1436aea4
MK
486 EFI_STATUS Status;\r
487 UINTN VariableNameSize;\r
488 UINTN PayloadSize;\r
489 SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
efb01a10 490\r
1436aea4 491 if ((Name == NULL) || (Name[0] == 0) || (Guid == NULL)) {\r
efb01a10
SZ
492 return EFI_INVALID_PARAMETER;\r
493 }\r
494\r
495 if (VariableProperty == NULL) {\r
496 return EFI_INVALID_PARAMETER;\r
497 }\r
498\r
1436aea4 499 VariableNameSize = StrSize (Name);\r
efb01a10
SZ
500 CommVariableProperty = NULL;\r
501\r
502 //\r
503 // If VariableName exceeds SMM payload limit. Return failure\r
504 //\r
505 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
506 return EFI_INVALID_PARAMETER;\r
507 }\r
508\r
509 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
510\r
511 //\r
512 // Init the communicate buffer. The buffer data size is:\r
513 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
514 //\r
515 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + VariableNameSize;\r
1436aea4 516 Status = InitCommunicateBuffer ((VOID **)&CommVariableProperty, PayloadSize, SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET);\r
efb01a10
SZ
517 if (EFI_ERROR (Status)) {\r
518 goto Done;\r
519 }\r
1436aea4 520\r
efb01a10
SZ
521 ASSERT (CommVariableProperty != NULL);\r
522\r
523 CopyGuid (&CommVariableProperty->Guid, Guid);\r
524 CommVariableProperty->NameSize = VariableNameSize;\r
525 CopyMem (CommVariableProperty->Name, Name, CommVariableProperty->NameSize);\r
526\r
527 //\r
528 // Send data to SMM.\r
529 //\r
530 Status = SendCommunicateBuffer (PayloadSize);\r
531 if (Status == EFI_SUCCESS) {\r
532 CopyMem (VariableProperty, &CommVariableProperty->VariableProperty, sizeof (*VariableProperty));\r
533 }\r
534\r
535Done:\r
536 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
537 return Status;\r
538}\r
539\r
8a2d4996 540/**\r
aab3b9b9
MK
541 Signals SMM to synchronize any pending variable updates with the runtime cache(s).\r
542\r
543**/\r
544VOID\r
545SyncRuntimeCache (\r
546 VOID\r
547 )\r
548{\r
549 //\r
550 // Init the communicate buffer. The buffer data size is:\r
551 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
552 //\r
553 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_SYNC_RUNTIME_CACHE);\r
554\r
555 //\r
556 // Send data to SMM.\r
557 //\r
558 SendCommunicateBuffer (0);\r
559}\r
560\r
561/**\r
562 Check whether a SMI must be triggered to retrieve pending cache updates.\r
563\r
564 If the variable HOB was finished being flushed since the last check for a runtime cache update, this function\r
565 will prevent the HOB cache from being used for future runtime cache hits.\r
566\r
567**/\r
568VOID\r
569CheckForRuntimeCacheSync (\r
570 VOID\r
571 )\r
572{\r
573 if (mVariableRuntimeCachePendingUpdate) {\r
574 SyncRuntimeCache ();\r
575 }\r
1436aea4 576\r
aab3b9b9
MK
577 ASSERT (!mVariableRuntimeCachePendingUpdate);\r
578\r
579 //\r
580 // The HOB variable data may have finished being flushed in the runtime cache sync update\r
581 //\r
1436aea4 582 if (mHobFlushComplete && (mVariableRuntimeHobCacheBuffer != NULL)) {\r
aab3b9b9
MK
583 if (!EfiAtRuntime ()) {\r
584 FreePages (mVariableRuntimeHobCacheBuffer, EFI_SIZE_TO_PAGES (mVariableRuntimeHobCacheBufferSize));\r
585 }\r
1436aea4 586\r
aab3b9b9
MK
587 mVariableRuntimeHobCacheBuffer = NULL;\r
588 }\r
589}\r
590\r
591/**\r
592 Finds the given variable in a runtime cache variable store.\r
8a2d4996 593\r
18a7dbbc
SZ
594 Caution: This function may receive untrusted input.\r
595 The data size is external input, so this function will validate it carefully to avoid buffer overflow.\r
596\r
8a2d4996 597 @param[in] VariableName Name of Variable to be found.\r
598 @param[in] VendorGuid Variable vendor GUID.\r
599 @param[out] Attributes Attribute value of the variable found.\r
600 @param[in, out] DataSize Size of Data found. If size is less than the\r
601 data, this value contains the required size.\r
602 @param[out] Data Data pointer.\r
fa0737a8 603\r
aab3b9b9 604 @retval EFI_SUCCESS Found the specified variable.\r
8a2d4996 605 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
aab3b9b9 606 @retval EFI_NOT_FOUND The specified variable could not be found.\r
8a2d4996 607\r
608**/\r
609EFI_STATUS\r
aab3b9b9 610FindVariableInRuntimeCache (\r
1436aea4
MK
611 IN CHAR16 *VariableName,\r
612 IN EFI_GUID *VendorGuid,\r
613 OUT UINT32 *Attributes OPTIONAL,\r
614 IN OUT UINTN *DataSize,\r
615 OUT VOID *Data OPTIONAL\r
aab3b9b9
MK
616 )\r
617{\r
618 EFI_STATUS Status;\r
619 UINTN TempDataSize;\r
620 VARIABLE_POINTER_TRACK RtPtrTrack;\r
621 VARIABLE_STORE_TYPE StoreType;\r
622 VARIABLE_STORE_HEADER *VariableStoreList[VariableStoreTypeMax];\r
623\r
624 Status = EFI_NOT_FOUND;\r
625\r
1436aea4 626 if ((VariableName == NULL) || (VendorGuid == NULL) || (DataSize == NULL)) {\r
aab3b9b9
MK
627 return EFI_INVALID_PARAMETER;\r
628 }\r
629\r
bd85bf54
MK
630 ZeroMem (&RtPtrTrack, sizeof (RtPtrTrack));\r
631\r
aab3b9b9
MK
632 //\r
633 // The UEFI specification restricts Runtime Services callers from invoking the same or certain other Runtime Service\r
634 // functions prior to completion and return from a previous Runtime Service call. These restrictions prevent\r
635 // a GetVariable () or GetNextVariable () call from being issued until a prior call has returned. The runtime\r
636 // cache read lock should always be free when entering this function.\r
637 //\r
638 ASSERT (!mVariableRuntimeCacheReadLock);\r
639\r
640 mVariableRuntimeCacheReadLock = TRUE;\r
641 CheckForRuntimeCacheSync ();\r
642\r
643 if (!mVariableRuntimeCachePendingUpdate) {\r
644 //\r
645 // 0: Volatile, 1: HOB, 2: Non-Volatile.\r
646 // The index and attributes mapping must be kept in this order as FindVariable\r
647 // makes use of this mapping to implement search algorithm.\r
648 //\r
649 VariableStoreList[VariableStoreTypeVolatile] = mVariableRuntimeVolatileCacheBuffer;\r
650 VariableStoreList[VariableStoreTypeHob] = mVariableRuntimeHobCacheBuffer;\r
651 VariableStoreList[VariableStoreTypeNv] = mVariableRuntimeNvCacheBuffer;\r
652\r
1436aea4 653 for (StoreType = (VARIABLE_STORE_TYPE)0; StoreType < VariableStoreTypeMax; StoreType++) {\r
aab3b9b9
MK
654 if (VariableStoreList[StoreType] == NULL) {\r
655 continue;\r
656 }\r
657\r
658 RtPtrTrack.StartPtr = GetStartPointer (VariableStoreList[StoreType]);\r
1436aea4
MK
659 RtPtrTrack.EndPtr = GetEndPointer (VariableStoreList[StoreType]);\r
660 RtPtrTrack.Volatile = (BOOLEAN)(StoreType == VariableStoreTypeVolatile);\r
aab3b9b9
MK
661\r
662 Status = FindVariableEx (VariableName, VendorGuid, FALSE, &RtPtrTrack, mVariableAuthFormat);\r
663 if (!EFI_ERROR (Status)) {\r
664 break;\r
665 }\r
666 }\r
667\r
668 if (!EFI_ERROR (Status)) {\r
669 //\r
670 // Get data size\r
671 //\r
672 TempDataSize = DataSizeOfVariable (RtPtrTrack.CurrPtr, mVariableAuthFormat);\r
673 ASSERT (TempDataSize != 0);\r
674\r
675 if (*DataSize >= TempDataSize) {\r
676 if (Data == NULL) {\r
677 Status = EFI_INVALID_PARAMETER;\r
678 goto Done;\r
679 }\r
680\r
681 CopyMem (Data, GetVariableDataPtr (RtPtrTrack.CurrPtr, mVariableAuthFormat), TempDataSize);\r
aab3b9b9
MK
682 *DataSize = TempDataSize;\r
683\r
684 UpdateVariableInfo (VariableName, VendorGuid, RtPtrTrack.Volatile, TRUE, FALSE, FALSE, TRUE, &mVariableInfo);\r
685\r
686 Status = EFI_SUCCESS;\r
687 goto Done;\r
688 } else {\r
689 *DataSize = TempDataSize;\r
1436aea4 690 Status = EFI_BUFFER_TOO_SMALL;\r
aab3b9b9
MK
691 goto Done;\r
692 }\r
693 }\r
694 }\r
695\r
696Done:\r
1436aea4
MK
697 if ((Status == EFI_SUCCESS) || (Status == EFI_BUFFER_TOO_SMALL)) {\r
698 if ((Attributes != NULL) && (RtPtrTrack.CurrPtr != NULL)) {\r
edf88807
MK
699 *Attributes = RtPtrTrack.CurrPtr->Attributes;\r
700 }\r
701 }\r
1436aea4 702\r
aab3b9b9
MK
703 mVariableRuntimeCacheReadLock = FALSE;\r
704\r
705 return Status;\r
706}\r
707\r
708/**\r
709 Finds the given variable in a variable store in SMM.\r
710\r
711 Caution: This function may receive untrusted input.\r
712 The data size is external input, so this function will validate it carefully to avoid buffer overflow.\r
713\r
714 @param[in] VariableName Name of Variable to be found.\r
715 @param[in] VendorGuid Variable vendor GUID.\r
716 @param[out] Attributes Attribute value of the variable found.\r
717 @param[in, out] DataSize Size of Data found. If size is less than the\r
718 data, this value contains the required size.\r
719 @param[out] Data Data pointer.\r
720\r
721 @retval EFI_SUCCESS Found the specified variable.\r
722 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
723 @retval EFI_NOT_FOUND The specified variable could not be found.\r
724\r
725**/\r
726EFI_STATUS\r
727FindVariableInSmm (\r
1436aea4
MK
728 IN CHAR16 *VariableName,\r
729 IN EFI_GUID *VendorGuid,\r
730 OUT UINT32 *Attributes OPTIONAL,\r
731 IN OUT UINTN *DataSize,\r
732 OUT VOID *Data OPTIONAL\r
8a2d4996 733 )\r
734{\r
735 EFI_STATUS Status;\r
736 UINTN PayloadSize;\r
737 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
3a146f2a 738 UINTN TempDataSize;\r
9d00d20e 739 UINTN VariableNameSize;\r
8a2d4996 740\r
1436aea4 741 if ((VariableName == NULL) || (VendorGuid == NULL) || (DataSize == NULL)) {\r
8a2d4996 742 return EFI_INVALID_PARAMETER;\r
743 }\r
744\r
1436aea4
MK
745 TempDataSize = *DataSize;\r
746 VariableNameSize = StrSize (VariableName);\r
747 SmmVariableHeader = NULL;\r
3a146f2a 748\r
749 //\r
750 // If VariableName exceeds SMM payload limit. Return failure\r
751 //\r
5e5bb2a9 752 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
3588bb35
SZ
753 return EFI_INVALID_PARAMETER;\r
754 }\r
755\r
8a2d4996 756 //\r
757 // Init the communicate buffer. The buffer data size is:\r
6ed1ec59 758 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
8a2d4996 759 //\r
5e5bb2a9 760 if (TempDataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize) {\r
3a146f2a 761 //\r
762 // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size\r
763 //\r
5e5bb2a9 764 TempDataSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize;\r
3a146f2a 765 }\r
1436aea4 766\r
9d00d20e 767 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + TempDataSize;\r
3a146f2a 768\r
1436aea4 769 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);\r
8a2d4996 770 if (EFI_ERROR (Status)) {\r
6ed1ec59 771 goto Done;\r
8a2d4996 772 }\r
1436aea4 773\r
8a2d4996 774 ASSERT (SmmVariableHeader != NULL);\r
775\r
776 CopyGuid (&SmmVariableHeader->Guid, VendorGuid);\r
1436aea4
MK
777 SmmVariableHeader->DataSize = TempDataSize;\r
778 SmmVariableHeader->NameSize = VariableNameSize;\r
8a2d4996 779 if (Attributes == NULL) {\r
780 SmmVariableHeader->Attributes = 0;\r
781 } else {\r
782 SmmVariableHeader->Attributes = *Attributes;\r
783 }\r
1436aea4 784\r
8a2d4996 785 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);\r
786\r
787 //\r
788 // Send data to SMM.\r
789 //\r
790 Status = SendCommunicateBuffer (PayloadSize);\r
791\r
792 //\r
793 // Get data from SMM.\r
794 //\r
1436aea4 795 if ((Status == EFI_SUCCESS) || (Status == EFI_BUFFER_TOO_SMALL)) {\r
3a146f2a 796 //\r
797 // SMM CommBuffer DataSize can be a trimed value\r
798 // Only update DataSize when needed\r
799 //\r
800 *DataSize = SmmVariableHeader->DataSize;\r
801 }\r
1436aea4 802\r
8a2d4996 803 if (Attributes != NULL) {\r
804 *Attributes = SmmVariableHeader->Attributes;\r
805 }\r
806\r
807 if (EFI_ERROR (Status)) {\r
6ed1ec59 808 goto Done;\r
8a2d4996 809 }\r
810\r
82e47eb2
SZ
811 if (Data != NULL) {\r
812 CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);\r
813 } else {\r
814 Status = EFI_INVALID_PARAMETER;\r
815 }\r
8a2d4996 816\r
6ed1ec59 817Done:\r
8a2d4996 818 return Status;\r
819}\r
820\r
aab3b9b9
MK
821/**\r
822 This code finds variable in storage blocks (Volatile or Non-Volatile).\r
823\r
824 Caution: This function may receive untrusted input.\r
825 The data size is external input, so this function will validate it carefully to avoid buffer overflow.\r
826\r
827 @param[in] VariableName Name of Variable to be found.\r
828 @param[in] VendorGuid Variable vendor GUID.\r
829 @param[out] Attributes Attribute value of the variable found.\r
830 @param[in, out] DataSize Size of Data found. If size is less than the\r
831 data, this value contains the required size.\r
832 @param[out] Data Data pointer.\r
833\r
834 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
835 @retval EFI_SUCCESS Find the specified variable.\r
836 @retval EFI_NOT_FOUND Not found.\r
837 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
838\r
839**/\r
840EFI_STATUS\r
841EFIAPI\r
842RuntimeServiceGetVariable (\r
1436aea4
MK
843 IN CHAR16 *VariableName,\r
844 IN EFI_GUID *VendorGuid,\r
845 OUT UINT32 *Attributes OPTIONAL,\r
846 IN OUT UINTN *DataSize,\r
847 OUT VOID *Data\r
aab3b9b9
MK
848 )\r
849{\r
1436aea4 850 EFI_STATUS Status;\r
aab3b9b9 851\r
1436aea4 852 if ((VariableName == NULL) || (VendorGuid == NULL) || (DataSize == NULL)) {\r
aab3b9b9
MK
853 return EFI_INVALID_PARAMETER;\r
854 }\r
1436aea4 855\r
aab3b9b9
MK
856 if (VariableName[0] == 0) {\r
857 return EFI_NOT_FOUND;\r
858 }\r
859\r
860 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
861 if (FeaturePcdGet (PcdEnableVariableRuntimeCache)) {\r
862 Status = FindVariableInRuntimeCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
863 } else {\r
864 Status = FindVariableInSmm (VariableName, VendorGuid, Attributes, DataSize, Data);\r
865 }\r
1436aea4 866\r
aab3b9b9
MK
867 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
868\r
869 return Status;\r
870}\r
8a2d4996 871\r
872/**\r
6f9838f3 873 Finds the next available variable in a runtime cache variable store.\r
8a2d4996 874\r
875 @param[in, out] VariableNameSize Size of the variable name.\r
876 @param[in, out] VariableName Pointer to variable name.\r
877 @param[in, out] VendorGuid Variable Vendor Guid.\r
878\r
879 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
880 @retval EFI_SUCCESS Find the specified variable.\r
881 @retval EFI_NOT_FOUND Not found.\r
882 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
883\r
884**/\r
885EFI_STATUS\r
6f9838f3 886GetNextVariableNameInRuntimeCache (\r
1436aea4
MK
887 IN OUT UINTN *VariableNameSize,\r
888 IN OUT CHAR16 *VariableName,\r
889 IN OUT EFI_GUID *VendorGuid\r
6f9838f3
MK
890 )\r
891{\r
1436aea4
MK
892 EFI_STATUS Status;\r
893 UINTN VarNameSize;\r
894 VARIABLE_HEADER *VariablePtr;\r
895 VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];\r
6f9838f3
MK
896\r
897 Status = EFI_NOT_FOUND;\r
898\r
899 //\r
900 // The UEFI specification restricts Runtime Services callers from invoking the same or certain other Runtime Service\r
901 // functions prior to completion and return from a previous Runtime Service call. These restrictions prevent\r
902 // a GetVariable () or GetNextVariable () call from being issued until a prior call has returned. The runtime\r
903 // cache read lock should always be free when entering this function.\r
904 //\r
905 ASSERT (!mVariableRuntimeCacheReadLock);\r
906\r
907 CheckForRuntimeCacheSync ();\r
908\r
909 mVariableRuntimeCacheReadLock = TRUE;\r
910 if (!mVariableRuntimeCachePendingUpdate) {\r
911 //\r
912 // 0: Volatile, 1: HOB, 2: Non-Volatile.\r
913 // The index and attributes mapping must be kept in this order as FindVariable\r
914 // makes use of this mapping to implement search algorithm.\r
915 //\r
916 VariableStoreHeader[VariableStoreTypeVolatile] = mVariableRuntimeVolatileCacheBuffer;\r
917 VariableStoreHeader[VariableStoreTypeHob] = mVariableRuntimeHobCacheBuffer;\r
918 VariableStoreHeader[VariableStoreTypeNv] = mVariableRuntimeNvCacheBuffer;\r
919\r
920 Status = VariableServiceGetNextVariableInternal (\r
921 VariableName,\r
922 VendorGuid,\r
923 VariableStoreHeader,\r
924 &VariablePtr,\r
925 mVariableAuthFormat\r
926 );\r
927 if (!EFI_ERROR (Status)) {\r
928 VarNameSize = NameSizeOfVariable (VariablePtr, mVariableAuthFormat);\r
929 ASSERT (VarNameSize != 0);\r
930 if (VarNameSize <= *VariableNameSize) {\r
931 CopyMem (VariableName, GetVariableNamePtr (VariablePtr, mVariableAuthFormat), VarNameSize);\r
932 CopyMem (VendorGuid, GetVendorGuidPtr (VariablePtr, mVariableAuthFormat), sizeof (EFI_GUID));\r
933 Status = EFI_SUCCESS;\r
934 } else {\r
935 Status = EFI_BUFFER_TOO_SMALL;\r
936 }\r
937\r
938 *VariableNameSize = VarNameSize;\r
939 }\r
940 }\r
1436aea4 941\r
6f9838f3
MK
942 mVariableRuntimeCacheReadLock = FALSE;\r
943\r
944 return Status;\r
945}\r
946\r
947/**\r
948 Finds the next available variable in a SMM variable store.\r
949\r
950 @param[in, out] VariableNameSize Size of the variable name.\r
951 @param[in, out] VariableName Pointer to variable name.\r
952 @param[in, out] VendorGuid Variable Vendor Guid.\r
953\r
954 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
955 @retval EFI_SUCCESS Find the specified variable.\r
956 @retval EFI_NOT_FOUND Not found.\r
957 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
958\r
959**/\r
960EFI_STATUS\r
961GetNextVariableNameInSmm (\r
1436aea4
MK
962 IN OUT UINTN *VariableNameSize,\r
963 IN OUT CHAR16 *VariableName,\r
964 IN OUT EFI_GUID *VendorGuid\r
8a2d4996 965 )\r
966{\r
1436aea4
MK
967 EFI_STATUS Status;\r
968 UINTN PayloadSize;\r
969 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;\r
970 UINTN OutVariableNameSize;\r
971 UINTN InVariableNameSize;\r
972\r
973 OutVariableNameSize = *VariableNameSize;\r
974 InVariableNameSize = StrSize (VariableName);\r
4e1005ec 975 SmmGetNextVariableName = NULL;\r
0c55190f 976\r
977 //\r
978 // If input string exceeds SMM payload limit. Return failure\r
979 //\r
5e5bb2a9 980 if (InVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
3588bb35
SZ
981 return EFI_INVALID_PARAMETER;\r
982 }\r
983\r
8a2d4996 984 //\r
985 // Init the communicate buffer. The buffer data size is:\r
986 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
987 //\r
5e5bb2a9 988 if (OutVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
0c55190f 989 //\r
990 // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size\r
991 //\r
5e5bb2a9 992 OutVariableNameSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
0c55190f 993 }\r
1436aea4 994\r
0c55190f 995 //\r
996 // Payload should be Guid + NameSize + MAX of Input & Output buffer\r
997 //\r
9d00d20e 998 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize);\r
0c55190f 999\r
5c7fa429 1000 Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);\r
8a2d4996 1001 if (EFI_ERROR (Status)) {\r
6ed1ec59 1002 goto Done;\r
8a2d4996 1003 }\r
1436aea4 1004\r
8a2d4996 1005 ASSERT (SmmGetNextVariableName != NULL);\r
1006\r
0c55190f 1007 //\r
1008 // SMM comm buffer->NameSize is buffer size for return string\r
1009 //\r
9d00d20e 1010 SmmGetNextVariableName->NameSize = OutVariableNameSize;\r
0c55190f 1011\r
8a2d4996 1012 CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);\r
0c55190f 1013 //\r
1014 // Copy whole string\r
1015 //\r
9d00d20e
SZ
1016 CopyMem (SmmGetNextVariableName->Name, VariableName, InVariableNameSize);\r
1017 if (OutVariableNameSize > InVariableNameSize) {\r
1436aea4 1018 ZeroMem ((UINT8 *)SmmGetNextVariableName->Name + InVariableNameSize, OutVariableNameSize - InVariableNameSize);\r
9d00d20e 1019 }\r
8a2d4996 1020\r
1021 //\r
1022 // Send data to SMM\r
1023 //\r
1024 Status = SendCommunicateBuffer (PayloadSize);\r
1025\r
1026 //\r
1027 // Get data from SMM.\r
1028 //\r
1436aea4 1029 if ((Status == EFI_SUCCESS) || (Status == EFI_BUFFER_TOO_SMALL)) {\r
9d00d20e
SZ
1030 //\r
1031 // SMM CommBuffer NameSize can be a trimed value\r
1032 // Only update VariableNameSize when needed\r
1033 //\r
1034 *VariableNameSize = SmmGetNextVariableName->NameSize;\r
1035 }\r
1436aea4 1036\r
8a2d4996 1037 if (EFI_ERROR (Status)) {\r
6ed1ec59 1038 goto Done;\r
8a2d4996 1039 }\r
fa0737a8 1040\r
8a2d4996 1041 CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid);\r
fa0737a8 1042 CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);\r
8a2d4996 1043\r
6ed1ec59 1044Done:\r
6f9838f3
MK
1045 return Status;\r
1046}\r
1047\r
1048/**\r
1049 This code Finds the Next available variable.\r
1050\r
1051 @param[in, out] VariableNameSize Size of the variable name.\r
1052 @param[in, out] VariableName Pointer to variable name.\r
1053 @param[in, out] VendorGuid Variable Vendor Guid.\r
1054\r
1055 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1056 @retval EFI_SUCCESS Find the specified variable.\r
1057 @retval EFI_NOT_FOUND Not found.\r
1058 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
1059\r
1060**/\r
1061EFI_STATUS\r
1062EFIAPI\r
1063RuntimeServiceGetNextVariableName (\r
1436aea4
MK
1064 IN OUT UINTN *VariableNameSize,\r
1065 IN OUT CHAR16 *VariableName,\r
1066 IN OUT EFI_GUID *VendorGuid\r
6f9838f3
MK
1067 )\r
1068{\r
1436aea4
MK
1069 EFI_STATUS Status;\r
1070 UINTN MaxLen;\r
6f9838f3
MK
1071\r
1072 Status = EFI_NOT_FOUND;\r
1073\r
1436aea4 1074 if ((VariableNameSize == NULL) || (VariableName == NULL) || (VendorGuid == NULL)) {\r
6f9838f3
MK
1075 return EFI_INVALID_PARAMETER;\r
1076 }\r
1077\r
1078 //\r
1079 // Calculate the possible maximum length of name string, including the Null terminator.\r
1080 //\r
1081 MaxLen = *VariableNameSize / sizeof (CHAR16);\r
1082 if ((MaxLen == 0) || (StrnLenS (VariableName, MaxLen) == MaxLen)) {\r
1083 //\r
1084 // Null-terminator is not found in the first VariableNameSize bytes of the input VariableName buffer,\r
1085 // follow spec to return EFI_INVALID_PARAMETER.\r
1086 //\r
1087 return EFI_INVALID_PARAMETER;\r
1088 }\r
1089\r
1090 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
1091 if (FeaturePcdGet (PcdEnableVariableRuntimeCache)) {\r
1092 Status = GetNextVariableNameInRuntimeCache (VariableNameSize, VariableName, VendorGuid);\r
1093 } else {\r
1094 Status = GetNextVariableNameInSmm (VariableNameSize, VariableName, VendorGuid);\r
1095 }\r
1436aea4 1096\r
6ed1ec59 1097 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
6f9838f3 1098\r
8a2d4996 1099 return Status;\r
1100}\r
1101\r
1102/**\r
1103 This code sets variable in storage blocks (Volatile or Non-Volatile).\r
1104\r
18a7dbbc
SZ
1105 Caution: This function may receive untrusted input.\r
1106 The data size and data are external input, so this function will validate it carefully to avoid buffer overflow.\r
1107\r
8a2d4996 1108 @param[in] VariableName Name of Variable to be found.\r
1109 @param[in] VendorGuid Variable vendor GUID.\r
1110 @param[in] Attributes Attribute value of the variable found\r
1111 @param[in] DataSize Size of Data found. If size is less than the\r
1112 data, this value contains the required size.\r
1113 @param[in] Data Data pointer.\r
1114\r
1115 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1116 @retval EFI_SUCCESS Set successfully.\r
1117 @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.\r
1118 @retval EFI_NOT_FOUND Not found.\r
1119 @retval EFI_WRITE_PROTECTED Variable is read-only.\r
1120\r
1121**/\r
1122EFI_STATUS\r
1123EFIAPI\r
1124RuntimeServiceSetVariable (\r
1436aea4
MK
1125 IN CHAR16 *VariableName,\r
1126 IN EFI_GUID *VendorGuid,\r
1127 IN UINT32 Attributes,\r
1128 IN UINTN DataSize,\r
1129 IN VOID *Data\r
8a2d4996 1130 )\r
1131{\r
1132 EFI_STATUS Status;\r
fa0737a8 1133 UINTN PayloadSize;\r
8a2d4996 1134 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
9d00d20e 1135 UINTN VariableNameSize;\r
fa0737a8 1136\r
8a2d4996 1137 //\r
1138 // Check input parameters.\r
1139 //\r
1436aea4 1140 if ((VariableName == NULL) || (VariableName[0] == 0) || (VendorGuid == NULL)) {\r
8a2d4996 1141 return EFI_INVALID_PARAMETER;\r
fa0737a8 1142 }\r
8a2d4996 1143\r
1436aea4 1144 if ((DataSize != 0) && (Data == NULL)) {\r
8a2d4996 1145 return EFI_INVALID_PARAMETER;\r
1146 }\r
6ed1ec59 1147\r
1436aea4
MK
1148 VariableNameSize = StrSize (VariableName);\r
1149 SmmVariableHeader = NULL;\r
3588bb35 1150\r
5e5bb2a9
SZ
1151 //\r
1152 // If VariableName or DataSize exceeds SMM payload limit. Return failure\r
1153 //\r
1154 if ((VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
1436aea4
MK
1155 (DataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize))\r
1156 {\r
56251c66 1157 return EFI_INVALID_PARAMETER;\r
1158 }\r
1159\r
1436aea4 1160 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
fa0737a8 1161\r
8a2d4996 1162 //\r
1163 // Init the communicate buffer. The buffer data size is:\r
1164 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
1165 //\r
9d00d20e 1166 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + DataSize;\r
1436aea4 1167 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);\r
8a2d4996 1168 if (EFI_ERROR (Status)) {\r
6ed1ec59 1169 goto Done;\r
8a2d4996 1170 }\r
1436aea4 1171\r
8a2d4996 1172 ASSERT (SmmVariableHeader != NULL);\r
1173\r
1436aea4 1174 CopyGuid ((EFI_GUID *)&SmmVariableHeader->Guid, VendorGuid);\r
8a2d4996 1175 SmmVariableHeader->DataSize = DataSize;\r
9d00d20e 1176 SmmVariableHeader->NameSize = VariableNameSize;\r
8a2d4996 1177 SmmVariableHeader->Attributes = Attributes;\r
1178 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);\r
1436aea4 1179 CopyMem ((UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, Data, DataSize);\r
8a2d4996 1180\r
1181 //\r
1182 // Send data to SMM.\r
1183 //\r
1184 Status = SendCommunicateBuffer (PayloadSize);\r
6ed1ec59
SZ
1185\r
1186Done:\r
1187 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
fa0737a8
SZ
1188\r
1189 if (!EfiAtRuntime ()) {\r
1190 if (!EFI_ERROR (Status)) {\r
1191 SecureBootHook (\r
1192 VariableName,\r
1193 VendorGuid\r
1194 );\r
1195 }\r
1196 }\r
1436aea4 1197\r
8a2d4996 1198 return Status;\r
1199}\r
1200\r
8a2d4996 1201/**\r
1202 This code returns information about the EFI variables.\r
1203\r
1204 @param[in] Attributes Attributes bitmask to specify the type of variables\r
1205 on which to return information.\r
1206 @param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available\r
1207 for the EFI variables associated with the attributes specified.\r
1208 @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available\r
1209 for EFI variables associated with the attributes specified.\r
1210 @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables\r
1211 associated with the attributes specified.\r
1212\r
1213 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.\r
1214 @retval EFI_SUCCESS Query successfully.\r
1215 @retval EFI_UNSUPPORTED The attribute is not supported on this platform.\r
1216\r
1217**/\r
1218EFI_STATUS\r
1219EFIAPI\r
1220RuntimeServiceQueryVariableInfo (\r
1436aea4
MK
1221 IN UINT32 Attributes,\r
1222 OUT UINT64 *MaximumVariableStorageSize,\r
1223 OUT UINT64 *RemainingVariableStorageSize,\r
1224 OUT UINT64 *MaximumVariableSize\r
8a2d4996 1225 )\r
1226{\r
1436aea4
MK
1227 EFI_STATUS Status;\r
1228 UINTN PayloadSize;\r
1229 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo;\r
8a2d4996 1230\r
4e1005ec
ED
1231 SmmQueryVariableInfo = NULL;\r
1232\r
1436aea4 1233 if ((MaximumVariableStorageSize == NULL) || (RemainingVariableStorageSize == NULL) || (MaximumVariableSize == NULL) || (Attributes == 0)) {\r
8a2d4996 1234 return EFI_INVALID_PARAMETER;\r
1235 }\r
6ed1ec59 1236\r
1436aea4 1237 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
6ed1ec59 1238\r
8a2d4996 1239 //\r
1240 // Init the communicate buffer. The buffer data size is:\r
1241 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;\r
1242 //\r
d00ed85e 1243 PayloadSize = sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO);\r
1436aea4 1244 Status = InitCommunicateBuffer ((VOID **)&SmmQueryVariableInfo, PayloadSize, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO);\r
8a2d4996 1245 if (EFI_ERROR (Status)) {\r
6ed1ec59 1246 goto Done;\r
8a2d4996 1247 }\r
1436aea4 1248\r
8a2d4996 1249 ASSERT (SmmQueryVariableInfo != NULL);\r
1250\r
1436aea4 1251 SmmQueryVariableInfo->Attributes = Attributes;\r
8a2d4996 1252\r
1253 //\r
1254 // Send data to SMM.\r
1255 //\r
1256 Status = SendCommunicateBuffer (PayloadSize);\r
1257 if (EFI_ERROR (Status)) {\r
6ed1ec59 1258 goto Done;\r
8a2d4996 1259 }\r
1260\r
1261 //\r
1262 // Get data from SMM.\r
1263 //\r
1264 *MaximumVariableSize = SmmQueryVariableInfo->MaximumVariableSize;\r
1265 *MaximumVariableStorageSize = SmmQueryVariableInfo->MaximumVariableStorageSize;\r
fa0737a8 1266 *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;\r
6ed1ec59
SZ
1267\r
1268Done:\r
1269 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
aab9212f 1270 return Status;\r
8a2d4996 1271}\r
1272\r
8a2d4996 1273/**\r
1274 Exit Boot Services Event notification handler.\r
1275\r
1276 Notify SMM variable driver about the event.\r
1277\r
1278 @param[in] Event Event whose notification function is being invoked.\r
1279 @param[in] Context Pointer to the notification function's context.\r
1280\r
1281**/\r
1282VOID\r
1283EFIAPI\r
1284OnExitBootServices (\r
1436aea4
MK
1285 IN EFI_EVENT Event,\r
1286 IN VOID *Context\r
8a2d4996 1287 )\r
1288{\r
1289 //\r
1290 // Init the communicate buffer. The buffer data size is:\r
1291 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
1292 //\r
fa0737a8 1293 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE);\r
8a2d4996 1294\r
1295 //\r
1296 // Send data to SMM.\r
1297 //\r
1298 SendCommunicateBuffer (0);\r
1299}\r
1300\r
8a2d4996 1301/**\r
1302 On Ready To Boot Services Event notification handler.\r
1303\r
1304 Notify SMM variable driver about the event.\r
1305\r
1306 @param[in] Event Event whose notification function is being invoked\r
1307 @param[in] Context Pointer to the notification function's context\r
1308\r
1309**/\r
1310VOID\r
1311EFIAPI\r
1312OnReadyToBoot (\r
1436aea4
MK
1313 IN EFI_EVENT Event,\r
1314 IN VOID *Context\r
8a2d4996 1315 )\r
1316{\r
1317 //\r
1318 // Init the communicate buffer. The buffer data size is:\r
1319 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
1320 //\r
1321 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT);\r
fa0737a8 1322\r
8a2d4996 1323 //\r
1324 // Send data to SMM.\r
1325 //\r
1326 SendCommunicateBuffer (0);\r
fa0737a8 1327\r
aab3b9b9
MK
1328 //\r
1329 // Install the system configuration table for variable info data captured\r
1330 //\r
1331 if (FeaturePcdGet (PcdEnableVariableRuntimeCache) && FeaturePcdGet (PcdVariableCollectStatistics)) {\r
1332 if (mVariableAuthFormat) {\r
1333 gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, mVariableInfo);\r
1334 } else {\r
1335 gBS->InstallConfigurationTable (&gEfiVariableGuid, mVariableInfo);\r
1336 }\r
1337 }\r
1338\r
fa0737a8 1339 gBS->CloseEvent (Event);\r
8a2d4996 1340}\r
1341\r
8a2d4996 1342/**\r
1343 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.\r
1344\r
1345 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
1346 It convers pointer to new virtual address.\r
1347\r
1348 @param[in] Event Event whose notification function is being invoked.\r
1349 @param[in] Context Pointer to the notification function's context.\r
1350\r
1351**/\r
1352VOID\r
1353EFIAPI\r
1354VariableAddressChangeEvent (\r
1436aea4
MK
1355 IN EFI_EVENT Event,\r
1356 IN VOID *Context\r
8a2d4996 1357 )\r
1358{\r
1436aea4
MK
1359 EfiConvertPointer (0x0, (VOID **)&mVariableBuffer);\r
1360 EfiConvertPointer (0x0, (VOID **)&mMmCommunication2);\r
1361 EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mVariableRuntimeHobCacheBuffer);\r
1362 EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mVariableRuntimeNvCacheBuffer);\r
1363 EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mVariableRuntimeVolatileCacheBuffer);\r
8a2d4996 1364}\r
1365\r
fa0737a8
SZ
1366/**\r
1367 This code gets variable payload size.\r
1368\r
1369 @param[out] VariablePayloadSize Output pointer to variable payload size.\r
1370\r
1371 @retval EFI_SUCCESS Get successfully.\r
1372 @retval Others Get unsuccessfully.\r
1373\r
1374**/\r
1375EFI_STATUS\r
1376EFIAPI\r
1377GetVariablePayloadSize (\r
1436aea4 1378 OUT UINTN *VariablePayloadSize\r
fa0737a8
SZ
1379 )\r
1380{\r
1436aea4
MK
1381 EFI_STATUS Status;\r
1382 SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *SmmGetPayloadSize;\r
1383 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
1384 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
1385 UINTN CommSize;\r
1386 UINT8 *CommBuffer;\r
fa0737a8
SZ
1387\r
1388 SmmGetPayloadSize = NULL;\r
1436aea4 1389 CommBuffer = NULL;\r
fa0737a8 1390\r
1436aea4 1391 if (VariablePayloadSize == NULL) {\r
fa0737a8
SZ
1392 return EFI_INVALID_PARAMETER;\r
1393 }\r
1394\r
1436aea4 1395 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
fa0737a8
SZ
1396\r
1397 //\r
1398 // Init the communicate buffer. The buffer data size is:\r
1399 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
1400 //\r
1436aea4 1401 CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
fa0737a8
SZ
1402 CommBuffer = AllocateZeroPool (CommSize);\r
1403 if (CommBuffer == NULL) {\r
1404 Status = EFI_OUT_OF_RESOURCES;\r
1405 goto Done;\r
1406 }\r
1407\r
1436aea4 1408 SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;\r
fa0737a8
SZ
1409 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
1410 SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
1411\r
1436aea4 1412 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;\r
fa0737a8 1413 SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE;\r
1436aea4 1414 SmmGetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *)SmmVariableFunctionHeader->Data;\r
fa0737a8
SZ
1415\r
1416 //\r
1417 // Send data to SMM.\r
1418 //\r
be4e0cfb 1419 Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);\r
fa0737a8
SZ
1420 ASSERT_EFI_ERROR (Status);\r
1421\r
1422 Status = SmmVariableFunctionHeader->ReturnStatus;\r
1423 if (EFI_ERROR (Status)) {\r
1424 goto Done;\r
1425 }\r
1426\r
1427 //\r
1428 // Get data from SMM.\r
1429 //\r
1430 *VariablePayloadSize = SmmGetPayloadSize->VariablePayloadSize;\r
1431\r
1432Done:\r
1433 if (CommBuffer != NULL) {\r
1434 FreePool (CommBuffer);\r
1435 }\r
1436aea4 1436\r
fa0737a8
SZ
1437 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
1438 return Status;\r
1439}\r
8a2d4996 1440\r
aab3b9b9
MK
1441/**\r
1442 This code gets information needed from SMM for runtime cache initialization.\r
1443\r
1444 @param[out] TotalHobStorageSize Output pointer for the total HOB storage size in bytes.\r
1445 @param[out] TotalNvStorageSize Output pointer for the total non-volatile storage size in bytes.\r
1446 @param[out] TotalVolatileStorageSize Output pointer for the total volatile storage size in bytes.\r
1447 @param[out] AuthenticatedVariableUsage Output pointer that indicates if authenticated variables are to be used.\r
1448\r
1449 @retval EFI_SUCCESS Retrieved the size successfully.\r
1450 @retval EFI_INVALID_PARAMETER TotalNvStorageSize parameter is NULL.\r
1451 @retval EFI_OUT_OF_RESOURCES The memory resources needed for a CommBuffer are not available.\r
1452 @retval Others Could not retrieve the size successfully.\r
1453\r
1454**/\r
1455EFI_STATUS\r
1456GetRuntimeCacheInfo (\r
1436aea4
MK
1457 OUT UINTN *TotalHobStorageSize,\r
1458 OUT UINTN *TotalNvStorageSize,\r
1459 OUT UINTN *TotalVolatileStorageSize,\r
1460 OUT BOOLEAN *AuthenticatedVariableUsage\r
aab3b9b9
MK
1461 )\r
1462{\r
1436aea4
MK
1463 EFI_STATUS Status;\r
1464 SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *SmmGetRuntimeCacheInfo;\r
1465 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
1466 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
1467 UINTN CommSize;\r
1468 UINT8 *CommBuffer;\r
aab3b9b9
MK
1469\r
1470 SmmGetRuntimeCacheInfo = NULL;\r
1436aea4 1471 CommBuffer = mVariableBuffer;\r
aab3b9b9 1472\r
1436aea4 1473 if ((TotalHobStorageSize == NULL) || (TotalNvStorageSize == NULL) || (TotalVolatileStorageSize == NULL) || (AuthenticatedVariableUsage == NULL)) {\r
aab3b9b9
MK
1474 return EFI_INVALID_PARAMETER;\r
1475 }\r
1476\r
1477 if (CommBuffer == NULL) {\r
1478 return EFI_OUT_OF_RESOURCES;\r
1479 }\r
1480\r
1481 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
1482\r
1483 CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO);\r
1484 ZeroMem (CommBuffer, CommSize);\r
1485\r
1436aea4 1486 SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;\r
aab3b9b9
MK
1487 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
1488 SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO);\r
1489\r
1436aea4 1490 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;\r
aab3b9b9 1491 SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO;\r
1436aea4 1492 SmmGetRuntimeCacheInfo = (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *)SmmVariableFunctionHeader->Data;\r
aab3b9b9
MK
1493\r
1494 //\r
1495 // Send data to SMM.\r
1496 //\r
be4e0cfb 1497 Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);\r
aab3b9b9
MK
1498 ASSERT_EFI_ERROR (Status);\r
1499 if (CommSize <= SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {\r
1500 Status = EFI_BAD_BUFFER_SIZE;\r
1501 goto Done;\r
1502 }\r
1503\r
1504 Status = SmmVariableFunctionHeader->ReturnStatus;\r
1505 if (EFI_ERROR (Status)) {\r
1506 goto Done;\r
1507 }\r
1508\r
1509 //\r
1510 // Get data from SMM.\r
1511 //\r
1436aea4
MK
1512 *TotalHobStorageSize = SmmGetRuntimeCacheInfo->TotalHobStorageSize;\r
1513 *TotalNvStorageSize = SmmGetRuntimeCacheInfo->TotalNvStorageSize;\r
1514 *TotalVolatileStorageSize = SmmGetRuntimeCacheInfo->TotalVolatileStorageSize;\r
aab3b9b9
MK
1515 *AuthenticatedVariableUsage = SmmGetRuntimeCacheInfo->AuthenticatedVariableUsage;\r
1516\r
1517Done:\r
1518 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
1519 return Status;\r
1520}\r
1521\r
1522/**\r
1523 Sends the runtime variable cache context information to SMM.\r
1524\r
1525 @retval EFI_SUCCESS Retrieved the size successfully.\r
1526 @retval EFI_INVALID_PARAMETER TotalNvStorageSize parameter is NULL.\r
1527 @retval EFI_OUT_OF_RESOURCES The memory resources needed for a CommBuffer are not available.\r
1528 @retval Others Could not retrieve the size successfully.;\r
1529\r
1530**/\r
1531EFI_STATUS\r
1532SendRuntimeVariableCacheContextToSmm (\r
1533 VOID\r
1534 )\r
1535{\r
1436aea4
MK
1536 EFI_STATUS Status;\r
1537 SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *SmmRuntimeVarCacheContext;\r
1538 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
1539 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
1540 UINTN CommSize;\r
1541 UINT8 *CommBuffer;\r
aab3b9b9
MK
1542\r
1543 SmmRuntimeVarCacheContext = NULL;\r
1436aea4 1544 CommBuffer = mVariableBuffer;\r
aab3b9b9
MK
1545\r
1546 if (CommBuffer == NULL) {\r
1547 return EFI_OUT_OF_RESOURCES;\r
1548 }\r
1549\r
1550 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
1551\r
1552 //\r
1553 // Init the communicate buffer. The buffer data size is:\r
1554 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);\r
1555 //\r
1556 CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);\r
1557 ZeroMem (CommBuffer, CommSize);\r
1558\r
1436aea4 1559 SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;\r
aab3b9b9
MK
1560 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
1561 SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);\r
1562\r
1436aea4 1563 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;\r
aab3b9b9 1564 SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT;\r
1436aea4 1565 SmmRuntimeVarCacheContext = (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *)SmmVariableFunctionHeader->Data;\r
aab3b9b9 1566\r
1436aea4 1567 SmmRuntimeVarCacheContext->RuntimeHobCache = mVariableRuntimeHobCacheBuffer;\r
aab3b9b9 1568 SmmRuntimeVarCacheContext->RuntimeVolatileCache = mVariableRuntimeVolatileCacheBuffer;\r
1436aea4
MK
1569 SmmRuntimeVarCacheContext->RuntimeNvCache = mVariableRuntimeNvCacheBuffer;\r
1570 SmmRuntimeVarCacheContext->PendingUpdate = &mVariableRuntimeCachePendingUpdate;\r
1571 SmmRuntimeVarCacheContext->ReadLock = &mVariableRuntimeCacheReadLock;\r
1572 SmmRuntimeVarCacheContext->HobFlushComplete = &mHobFlushComplete;\r
aab3b9b9 1573\r
f463dbad
KQ
1574 //\r
1575 // Request to unblock this region to be accessible from inside MM environment\r
1576 // These fields "should" be all on the same page, but just to be on the safe side...\r
1577 //\r
1578 Status = MmUnblockMemoryRequest (\r
1436aea4
MK
1579 (EFI_PHYSICAL_ADDRESS)ALIGN_VALUE ((UINTN)SmmRuntimeVarCacheContext->PendingUpdate - EFI_PAGE_SIZE + 1, EFI_PAGE_SIZE),\r
1580 EFI_SIZE_TO_PAGES (sizeof (mVariableRuntimeCachePendingUpdate))\r
1581 );\r
1582 if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) {\r
f463dbad
KQ
1583 goto Done;\r
1584 }\r
1585\r
1586 Status = MmUnblockMemoryRequest (\r
1436aea4
MK
1587 (EFI_PHYSICAL_ADDRESS)ALIGN_VALUE ((UINTN)SmmRuntimeVarCacheContext->ReadLock - EFI_PAGE_SIZE + 1, EFI_PAGE_SIZE),\r
1588 EFI_SIZE_TO_PAGES (sizeof (mVariableRuntimeCacheReadLock))\r
1589 );\r
1590 if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) {\r
f463dbad
KQ
1591 goto Done;\r
1592 }\r
1593\r
1594 Status = MmUnblockMemoryRequest (\r
1436aea4
MK
1595 (EFI_PHYSICAL_ADDRESS)ALIGN_VALUE ((UINTN)SmmRuntimeVarCacheContext->HobFlushComplete - EFI_PAGE_SIZE + 1, EFI_PAGE_SIZE),\r
1596 EFI_SIZE_TO_PAGES (sizeof (mHobFlushComplete))\r
1597 );\r
1598 if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) {\r
f463dbad
KQ
1599 goto Done;\r
1600 }\r
1601\r
aab3b9b9
MK
1602 //\r
1603 // Send data to SMM.\r
1604 //\r
be4e0cfb 1605 Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);\r
aab3b9b9
MK
1606 ASSERT_EFI_ERROR (Status);\r
1607 if (CommSize <= SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {\r
1608 Status = EFI_BAD_BUFFER_SIZE;\r
1609 goto Done;\r
1610 }\r
1611\r
1612 Status = SmmVariableFunctionHeader->ReturnStatus;\r
1613 if (EFI_ERROR (Status)) {\r
1614 goto Done;\r
1615 }\r
1616\r
1617Done:\r
1618 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
1619 return Status;\r
1620}\r
1621\r
8a2d4996 1622/**\r
1623 Initialize variable service and install Variable Architectural protocol.\r
1624\r
1625 @param[in] Event Event whose notification function is being invoked.\r
1626 @param[in] Context Pointer to the notification function's context.\r
fa0737a8 1627\r
8a2d4996 1628**/\r
1629VOID\r
1630EFIAPI\r
1631SmmVariableReady (\r
1436aea4
MK
1632 IN EFI_EVENT Event,\r
1633 IN VOID *Context\r
8a2d4996 1634 )\r
1635{\r
1436aea4 1636 EFI_STATUS Status;\r
8a2d4996 1637\r
1436aea4 1638 Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);\r
8a2d4996 1639 if (EFI_ERROR (Status)) {\r
1640 return;\r
1641 }\r
fa0737a8 1642\r
1436aea4 1643 Status = gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid, NULL, (VOID **)&mMmCommunication2);\r
8a2d4996 1644 ASSERT_EFI_ERROR (Status);\r
fa0737a8 1645\r
8a2d4996 1646 //\r
5e5bb2a9 1647 // Allocate memory for variable communicate buffer.\r
8a2d4996 1648 //\r
fa0737a8
SZ
1649 Status = GetVariablePayloadSize (&mVariableBufferPayloadSize);\r
1650 ASSERT_EFI_ERROR (Status);\r
1436aea4
MK
1651 mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + mVariableBufferPayloadSize;\r
1652 mVariableBuffer = AllocateRuntimePool (mVariableBufferSize);\r
8a2d4996 1653 ASSERT (mVariableBuffer != NULL);\r
1654\r
1655 //\r
1656 // Save the buffer physical address used for SMM conmunication.\r
1657 //\r
1658 mVariableBufferPhysical = mVariableBuffer;\r
1659\r
aab3b9b9
MK
1660 if (FeaturePcdGet (PcdEnableVariableRuntimeCache)) {\r
1661 DEBUG ((DEBUG_INFO, "Variable driver runtime cache is enabled.\n"));\r
1662 //\r
1663 // Allocate runtime variable cache memory buffers.\r
1664 //\r
1665 Status = GetRuntimeCacheInfo (\r
1666 &mVariableRuntimeHobCacheBufferSize,\r
1667 &mVariableRuntimeNvCacheBufferSize,\r
1668 &mVariableRuntimeVolatileCacheBufferSize,\r
1669 &mVariableAuthFormat\r
1670 );\r
1671 if (!EFI_ERROR (Status)) {\r
1672 Status = InitVariableCache (&mVariableRuntimeHobCacheBuffer, &mVariableRuntimeHobCacheBufferSize);\r
1673 if (!EFI_ERROR (Status)) {\r
1674 Status = InitVariableCache (&mVariableRuntimeNvCacheBuffer, &mVariableRuntimeNvCacheBufferSize);\r
1675 if (!EFI_ERROR (Status)) {\r
1676 Status = InitVariableCache (&mVariableRuntimeVolatileCacheBuffer, &mVariableRuntimeVolatileCacheBufferSize);\r
1677 if (!EFI_ERROR (Status)) {\r
1678 Status = SendRuntimeVariableCacheContextToSmm ();\r
1679 if (!EFI_ERROR (Status)) {\r
1680 SyncRuntimeCache ();\r
1681 }\r
1682 }\r
1683 }\r
1684 }\r
1436aea4 1685\r
aab3b9b9 1686 if (EFI_ERROR (Status)) {\r
1436aea4
MK
1687 mVariableRuntimeHobCacheBuffer = NULL;\r
1688 mVariableRuntimeNvCacheBuffer = NULL;\r
aab3b9b9
MK
1689 mVariableRuntimeVolatileCacheBuffer = NULL;\r
1690 }\r
1691 }\r
1436aea4 1692\r
aab3b9b9
MK
1693 ASSERT_EFI_ERROR (Status);\r
1694 } else {\r
1695 DEBUG ((DEBUG_INFO, "Variable driver runtime cache is disabled.\n"));\r
1696 }\r
1697\r
8a2d4996 1698 gRT->GetVariable = RuntimeServiceGetVariable;\r
1699 gRT->GetNextVariableName = RuntimeServiceGetNextVariableName;\r
1700 gRT->SetVariable = RuntimeServiceSetVariable;\r
1701 gRT->QueryVariableInfo = RuntimeServiceQueryVariableInfo;\r
fa0737a8 1702\r
8a2d4996 1703 //\r
1704 // Install the Variable Architectural Protocol on a new handle.\r
1705 //\r
1706 Status = gBS->InstallProtocolInterface (\r
1707 &mHandle,\r
fa0737a8 1708 &gEfiVariableArchProtocolGuid,\r
8a2d4996 1709 EFI_NATIVE_INTERFACE,\r
1710 NULL\r
1711 );\r
1712 ASSERT_EFI_ERROR (Status);\r
aa2868b3
SZ
1713\r
1714 mVariableLock.RequestToLock = VariableLockRequestToLock;\r
1436aea4
MK
1715 Status = gBS->InstallMultipleProtocolInterfaces (\r
1716 &mHandle,\r
1717 &gEdkiiVariableLockProtocolGuid,\r
1718 &mVariableLock,\r
1719 NULL\r
1720 );\r
aa2868b3
SZ
1721 ASSERT_EFI_ERROR (Status);\r
1722\r
1723 mVarCheck.RegisterSetVariableCheckHandler = VarCheckRegisterSetVariableCheckHandler;\r
1436aea4
MK
1724 mVarCheck.VariablePropertySet = VarCheckVariablePropertySet;\r
1725 mVarCheck.VariablePropertyGet = VarCheckVariablePropertyGet;\r
1726 Status = gBS->InstallMultipleProtocolInterfaces (\r
1727 &mHandle,\r
1728 &gEdkiiVarCheckProtocolGuid,\r
1729 &mVarCheck,\r
1730 NULL\r
1731 );\r
aa2868b3 1732 ASSERT_EFI_ERROR (Status);\r
fa0737a8
SZ
1733\r
1734 gBS->CloseEvent (Event);\r
8a2d4996 1735}\r
1736\r
8a2d4996 1737/**\r
1738 SMM Non-Volatile variable write service is ready notify event handler.\r
1739\r
1740 @param[in] Event Event whose notification function is being invoked.\r
1741 @param[in] Context Pointer to the notification function's context.\r
fa0737a8 1742\r
8a2d4996 1743**/\r
1744VOID\r
1745EFIAPI\r
1746SmmVariableWriteReady (\r
1436aea4
MK
1747 IN EFI_EVENT Event,\r
1748 IN VOID *Context\r
8a2d4996 1749 )\r
1750{\r
1436aea4
MK
1751 EFI_STATUS Status;\r
1752 VOID *ProtocolOps;\r
8a2d4996 1753\r
1754 //\r
1755 // Check whether the protocol is installed or not.\r
1756 //\r
1436aea4 1757 Status = gBS->LocateProtocol (&gSmmVariableWriteGuid, NULL, (VOID **)&ProtocolOps);\r
8a2d4996 1758 if (EFI_ERROR (Status)) {\r
1759 return;\r
1760 }\r
fa0737a8 1761\r
dc9bd6ed
ZC
1762 //\r
1763 // Some Secure Boot Policy Var (SecureBoot, etc) updates following other\r
1764 // Secure Boot Policy Variable change. Record their initial value.\r
1765 //\r
1436aea4 1766 RecordSecureBootPolicyVarData ();\r
dc9bd6ed 1767\r
8a2d4996 1768 Status = gBS->InstallProtocolInterface (\r
1769 &mHandle,\r
fa0737a8 1770 &gEfiVariableWriteArchProtocolGuid,\r
8a2d4996 1771 EFI_NATIVE_INTERFACE,\r
1772 NULL\r
1773 );\r
fa0737a8
SZ
1774 ASSERT_EFI_ERROR (Status);\r
1775\r
1776 gBS->CloseEvent (Event);\r
8a2d4996 1777}\r
1778\r
8a2d4996 1779/**\r
1780 Variable Driver main entry point. The Variable driver places the 4 EFI\r
fa0737a8 1781 runtime services in the EFI System Table and installs arch protocols\r
d00ed85e 1782 for variable read and write services being available. It also registers\r
8a2d4996 1783 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
1784\r
fa0737a8 1785 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
8a2d4996 1786 @param[in] SystemTable A pointer to the EFI System Table.\r
fa0737a8 1787\r
8a2d4996 1788 @retval EFI_SUCCESS Variable service successfully initialized.\r
1789\r
1790**/\r
1791EFI_STATUS\r
1792EFIAPI\r
1793VariableSmmRuntimeInitialize (\r
1436aea4
MK
1794 IN EFI_HANDLE ImageHandle,\r
1795 IN EFI_SYSTEM_TABLE *SystemTable\r
8a2d4996 1796 )\r
1797{\r
1436aea4
MK
1798 VOID *SmmVariableRegistration;\r
1799 VOID *SmmVariableWriteRegistration;\r
1800 EFI_EVENT OnReadyToBootEvent;\r
1801 EFI_EVENT ExitBootServiceEvent;\r
1802 EFI_EVENT LegacyBootEvent;\r
6ed1ec59
SZ
1803\r
1804 EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);\r
1805\r
8a2d4996 1806 //\r
1807 // Smm variable service is ready\r
1808 //\r
1809 EfiCreateProtocolNotifyEvent (\r
fa0737a8
SZ
1810 &gEfiSmmVariableProtocolGuid,\r
1811 TPL_CALLBACK,\r
1812 SmmVariableReady,\r
1813 NULL,\r
8a2d4996 1814 &SmmVariableRegistration\r
1815 );\r
1816\r
1817 //\r
1818 // Smm Non-Volatile variable write service is ready\r
1819 //\r
1820 EfiCreateProtocolNotifyEvent (\r
fa0737a8
SZ
1821 &gSmmVariableWriteGuid,\r
1822 TPL_CALLBACK,\r
1823 SmmVariableWriteReady,\r
1824 NULL,\r
8a2d4996 1825 &SmmVariableWriteRegistration\r
1826 );\r
1827\r
1828 //\r
1829 // Register the event to reclaim variable for OS usage.\r
1830 //\r
1831 EfiCreateEventReadyToBootEx (\r
fa0737a8
SZ
1832 TPL_NOTIFY,\r
1833 OnReadyToBoot,\r
1834 NULL,\r
8a2d4996 1835 &OnReadyToBootEvent\r
fa0737a8 1836 );\r
8a2d4996 1837\r
1838 //\r
1839 // Register the event to inform SMM variable that it is at runtime.\r
1840 //\r
1841 gBS->CreateEventEx (\r
1842 EVT_NOTIFY_SIGNAL,\r
1843 TPL_NOTIFY,\r
1844 OnExitBootServices,\r
1845 NULL,\r
1846 &gEfiEventExitBootServicesGuid,\r
1847 &ExitBootServiceEvent\r
fa0737a8 1848 );\r
8a2d4996 1849\r
d3460bcb
SZ
1850 //\r
1851 // Register the event to inform SMM variable that it is at runtime for legacy boot.\r
1852 // Reuse OnExitBootServices() here.\r
1853 //\r
1436aea4 1854 EfiCreateEventLegacyBootEx (\r
d3460bcb
SZ
1855 TPL_NOTIFY,\r
1856 OnExitBootServices,\r
1857 NULL,\r
1858 &LegacyBootEvent\r
1859 );\r
1860\r
8a2d4996 1861 //\r
1862 // Register the event to convert the pointer for runtime.\r
1863 //\r
1864 gBS->CreateEventEx (\r
1865 EVT_NOTIFY_SIGNAL,\r
1866 TPL_NOTIFY,\r
1867 VariableAddressChangeEvent,\r
1868 NULL,\r
1869 &gEfiEventVirtualAddressChangeGuid,\r
1870 &mVirtualAddressChangeEvent\r
1871 );\r
fa0737a8 1872\r
b6490426
BB
1873 // Initialize the VariablePolicy protocol and engine.\r
1874 VariablePolicySmmDxeMain (ImageHandle, SystemTable);\r
1875\r
8a2d4996 1876 return EFI_SUCCESS;\r
1877}\r