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