TianoCore EDK2 master
Loading...
Searching...
No Matches
VariableSmmRuntimeDxe.c
Go to the documentation of this file.
1
21#include <PiDxe.h>
23#include <Protocol/Variable.h>
27#include <Protocol/VarCheck.h>
28
35#include <Library/DebugLib.h>
36#include <Library/UefiLib.h>
37#include <Library/BaseLib.h>
38#include <Library/HobLib.h>
39
40#include <Guid/EventGroup.h>
43
45#include "VariableParsing.h"
46
48EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;
49EFI_EVENT mVirtualAddressChangeEvent = NULL;
50EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication2 = NULL;
51UINT8 *mVariableBuffer = NULL;
52UINT8 *mVariableBufferPhysical = NULL;
53VARIABLE_INFO_ENTRY *mVariableInfo = NULL;
54UINTN mVariableBufferSize;
55UINTN mVariableBufferPayloadSize;
56BOOLEAN mVariableAuthFormat;
57EFI_LOCK mVariableServicesLock;
60VARIABLE_RUNTIME_CACHE_INFO mVariableRtCacheInfo;
61BOOLEAN mIsRuntimeCacheEnabled = FALSE;
62
68EFIAPI
70 IN EFI_HANDLE ImageHandle,
71 IN EFI_SYSTEM_TABLE *SystemTable
72 );
73
79VOID
80EFIAPI
82 VOID
83 );
84
97VOID
100 )
101{
102 if (!EfiAtRuntime ()) {
104 }
105}
106
119VOID
122 )
123{
124 if (!EfiAtRuntime ()) {
126 }
127}
128
134BOOLEAN
136 VOID
137 )
138{
139 return EfiAtRuntime ();
140}
141
161 OUT VOID **DataPtr OPTIONAL,
162 IN UINTN DataSize,
163 IN UINTN Function
164 )
165{
166 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
167 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
168
169 if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {
170 return EFI_INVALID_PARAMETER;
171 }
172
173 SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mVariableBuffer;
174 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
175 SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
176
177 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
178 SmmVariableFunctionHeader->Function = Function;
179 if (DataPtr != NULL) {
180 *DataPtr = SmmVariableFunctionHeader->Data;
181 }
182
183 return EFI_SUCCESS;
184}
185
197 IN UINTN DataSize
198 )
199{
200 EFI_STATUS Status;
201 UINTN CommSize;
202 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
203 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
204
206 Status = mMmCommunication2->Communicate (
207 mMmCommunication2,
208 mVariableBufferPhysical,
209 mVariableBuffer,
210 &CommSize
211 );
212 ASSERT_EFI_ERROR (Status);
213
214 SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mVariableBuffer;
215 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
216 return SmmVariableFunctionHeader->ReturnStatus;
217}
218
235EFIAPI
238 IN CHAR16 *VariableName,
239 IN EFI_GUID *VendorGuid
240 )
241{
242 EFI_STATUS Status;
243 UINTN VariableNameSize;
244 UINTN PayloadSize;
246
247 if ((VariableName == NULL) || (VariableName[0] == 0) || (VendorGuid == NULL)) {
248 return EFI_INVALID_PARAMETER;
249 }
250
251 VariableNameSize = StrSize (VariableName);
252 VariableToLock = NULL;
253
254 //
255 // If VariableName exceeds SMM payload limit. Return failure
256 //
257 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {
258 return EFI_INVALID_PARAMETER;
259 }
260
261 AcquireLockOnlyAtBootTime (&mVariableServicesLock);
262
263 //
264 // Init the communicate buffer. The buffer data size is:
265 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
266 //
267 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize;
268 Status = InitCommunicateBuffer ((VOID **)&VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE);
269 if (EFI_ERROR (Status)) {
270 goto Done;
271 }
272
273 ASSERT (VariableToLock != NULL);
274
275 CopyGuid (&VariableToLock->Guid, VendorGuid);
276 VariableToLock->NameSize = VariableNameSize;
277 CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize);
278
279 //
280 // Send data to SMM.
281 //
282 Status = SendCommunicateBuffer (PayloadSize);
283
284Done:
285 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
286 return Status;
287}
288
304EFIAPI
306 IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler
307 )
308{
309 return EFI_UNSUPPORTED;
310}
311
328EFIAPI
330 IN CHAR16 *Name,
331 IN EFI_GUID *Guid,
332 IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty
333 )
334{
335 EFI_STATUS Status;
336 UINTN VariableNameSize;
337 UINTN PayloadSize;
339
340 if ((Name == NULL) || (Name[0] == 0) || (Guid == NULL)) {
341 return EFI_INVALID_PARAMETER;
342 }
343
344 if (VariableProperty == NULL) {
345 return EFI_INVALID_PARAMETER;
346 }
347
348 if (VariableProperty->Revision != VAR_CHECK_VARIABLE_PROPERTY_REVISION) {
349 return EFI_INVALID_PARAMETER;
350 }
351
352 VariableNameSize = StrSize (Name);
353 CommVariableProperty = NULL;
354
355 //
356 // If VariableName exceeds SMM payload limit. Return failure
357 //
358 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {
359 return EFI_INVALID_PARAMETER;
360 }
361
362 AcquireLockOnlyAtBootTime (&mVariableServicesLock);
363
364 //
365 // Init the communicate buffer. The buffer data size is:
366 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
367 //
368 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + VariableNameSize;
369 Status = InitCommunicateBuffer ((VOID **)&CommVariableProperty, PayloadSize, SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET);
370 if (EFI_ERROR (Status)) {
371 goto Done;
372 }
373
374 ASSERT (CommVariableProperty != NULL);
375
376 CopyGuid (&CommVariableProperty->Guid, Guid);
377 CopyMem (&CommVariableProperty->VariableProperty, VariableProperty, sizeof (*VariableProperty));
378 CommVariableProperty->NameSize = VariableNameSize;
379 CopyMem (CommVariableProperty->Name, Name, CommVariableProperty->NameSize);
380
381 //
382 // Send data to SMM.
383 //
384 Status = SendCommunicateBuffer (PayloadSize);
385
386Done:
387 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
388 return Status;
389}
390
404EFIAPI
406 IN CHAR16 *Name,
407 IN EFI_GUID *Guid,
408 OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty
409 )
410{
411 EFI_STATUS Status;
412 UINTN VariableNameSize;
413 UINTN PayloadSize;
415
416 if ((Name == NULL) || (Name[0] == 0) || (Guid == NULL)) {
417 return EFI_INVALID_PARAMETER;
418 }
419
420 if (VariableProperty == NULL) {
421 return EFI_INVALID_PARAMETER;
422 }
423
424 VariableNameSize = StrSize (Name);
425 CommVariableProperty = NULL;
426
427 //
428 // If VariableName exceeds SMM payload limit. Return failure
429 //
430 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {
431 return EFI_INVALID_PARAMETER;
432 }
433
434 AcquireLockOnlyAtBootTime (&mVariableServicesLock);
435
436 //
437 // Init the communicate buffer. The buffer data size is:
438 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
439 //
440 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + VariableNameSize;
441 Status = InitCommunicateBuffer ((VOID **)&CommVariableProperty, PayloadSize, SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET);
442 if (EFI_ERROR (Status)) {
443 goto Done;
444 }
445
446 ASSERT (CommVariableProperty != NULL);
447
448 CopyGuid (&CommVariableProperty->Guid, Guid);
449 CommVariableProperty->NameSize = VariableNameSize;
450 CopyMem (CommVariableProperty->Name, Name, CommVariableProperty->NameSize);
451
452 //
453 // Send data to SMM.
454 //
455 Status = SendCommunicateBuffer (PayloadSize);
456 if (Status == EFI_SUCCESS) {
457 CopyMem (VariableProperty, &CommVariableProperty->VariableProperty, sizeof (*VariableProperty));
458 }
459
460Done:
461 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
462 return Status;
463}
464
469VOID
471 VOID
472 )
473{
474 //
475 // Init the communicate buffer. The buffer data size is:
476 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
477 //
478 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_SYNC_RUNTIME_CACHE);
479
480 //
481 // Send data to SMM.
482 //
484}
485
493VOID
495 VOID
496 )
497{
498 CACHE_INFO_FLAG *CacheInfoFlag;
499
500 CacheInfoFlag = (CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer;
501
502 if (CacheInfoFlag->PendingUpdate) {
504 }
505
506 ASSERT (!(CacheInfoFlag->PendingUpdate));
507
508 //
509 // The HOB variable data may have finished being flushed in the runtime cache sync update
510 //
511 if ((CacheInfoFlag->HobFlushComplete) && (mVariableRtCacheInfo.RuntimeHobCacheBuffer != 0)) {
512 mVariableRtCacheInfo.RuntimeHobCacheBuffer = 0;
513 }
514}
515
536 IN CHAR16 *VariableName,
537 IN EFI_GUID *VendorGuid,
538 OUT UINT32 *Attributes OPTIONAL,
539 IN OUT UINTN *DataSize,
540 OUT VOID *Data OPTIONAL
541 )
542{
543 EFI_STATUS Status;
544 UINTN TempDataSize;
545 VARIABLE_POINTER_TRACK RtPtrTrack;
546 VARIABLE_STORE_TYPE StoreType;
547 VARIABLE_STORE_HEADER *VariableStoreList[VariableStoreTypeMax];
548 CACHE_INFO_FLAG *CacheInfoFlag;
549
550 Status = EFI_NOT_FOUND;
551 CacheInfoFlag = (CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer;
552
553 if ((VariableName == NULL) || (VendorGuid == NULL) || (DataSize == NULL)) {
554 return EFI_INVALID_PARAMETER;
555 }
556
557 ZeroMem (&RtPtrTrack, sizeof (RtPtrTrack));
558
559 //
560 // The UEFI specification restricts Runtime Services callers from invoking the same or certain other Runtime Service
561 // functions prior to completion and return from a previous Runtime Service call. These restrictions prevent
562 // a GetVariable () or GetNextVariable () call from being issued until a prior call has returned. The runtime
563 // cache read lock should always be free when entering this function.
564 //
565 ASSERT (!(CacheInfoFlag->ReadLock));
566
567 CacheInfoFlag->ReadLock = TRUE;
569
570 if (!(CacheInfoFlag->PendingUpdate)) {
571 //
572 // 0: Volatile, 1: HOB, 2: Non-Volatile.
573 // The index and attributes mapping must be kept in this order as FindVariable
574 // makes use of this mapping to implement search algorithm.
575 //
576 VariableStoreList[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer;
577 VariableStoreList[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer;
578 VariableStoreList[VariableStoreTypeNv] = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer;
579
580 for (StoreType = (VARIABLE_STORE_TYPE)0; StoreType < VariableStoreTypeMax; StoreType++) {
581 if (VariableStoreList[StoreType] == NULL) {
582 continue;
583 }
584
585 RtPtrTrack.StartPtr = GetStartPointer (VariableStoreList[StoreType]);
586 RtPtrTrack.EndPtr = GetEndPointer (VariableStoreList[StoreType]);
587 RtPtrTrack.Volatile = (BOOLEAN)(StoreType == VariableStoreTypeVolatile);
588
589 Status = FindVariableEx (VariableName, VendorGuid, FALSE, &RtPtrTrack, mVariableAuthFormat);
590 if (!EFI_ERROR (Status)) {
591 break;
592 }
593 }
594
595 if (!EFI_ERROR (Status)) {
596 //
597 // Get data size
598 //
599 TempDataSize = DataSizeOfVariable (RtPtrTrack.CurrPtr, mVariableAuthFormat);
600 ASSERT (TempDataSize != 0);
601
602 if (*DataSize >= TempDataSize) {
603 if (Data == NULL) {
604 Status = EFI_INVALID_PARAMETER;
605 goto Done;
606 }
607
608 CopyMem (Data, GetVariableDataPtr (RtPtrTrack.CurrPtr, mVariableAuthFormat), TempDataSize);
609 *DataSize = TempDataSize;
610
611 UpdateVariableInfo (VariableName, VendorGuid, RtPtrTrack.Volatile, TRUE, FALSE, FALSE, TRUE, &mVariableInfo);
612
613 Status = EFI_SUCCESS;
614 goto Done;
615 } else {
616 *DataSize = TempDataSize;
617 Status = EFI_BUFFER_TOO_SMALL;
618 goto Done;
619 }
620 }
621 }
622
623Done:
624 if ((Status == EFI_SUCCESS) || (Status == EFI_BUFFER_TOO_SMALL)) {
625 if ((Attributes != NULL) && (RtPtrTrack.CurrPtr != NULL)) {
626 *Attributes = RtPtrTrack.CurrPtr->Attributes;
627 }
628 }
629
630 CacheInfoFlag->ReadLock = FALSE;
631
632 return Status;
633}
634
655 IN CHAR16 *VariableName,
656 IN EFI_GUID *VendorGuid,
657 OUT UINT32 *Attributes OPTIONAL,
658 IN OUT UINTN *DataSize,
659 OUT VOID *Data OPTIONAL
660 )
661{
662 EFI_STATUS Status;
663 UINTN PayloadSize;
665 UINTN TempDataSize;
666 UINTN VariableNameSize;
667
668 if ((VariableName == NULL) || (VendorGuid == NULL) || (DataSize == NULL)) {
669 return EFI_INVALID_PARAMETER;
670 }
671
672 TempDataSize = *DataSize;
673 VariableNameSize = StrSize (VariableName);
674 SmmVariableHeader = NULL;
675
676 //
677 // If VariableName exceeds SMM payload limit. Return failure
678 //
679 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
680 return EFI_INVALID_PARAMETER;
681 }
682
683 //
684 // Init the communicate buffer. The buffer data size is:
685 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
686 //
687 if (TempDataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize) {
688 //
689 // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size
690 //
691 TempDataSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize;
692 }
693
694 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + TempDataSize;
695
696 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
697 if (EFI_ERROR (Status)) {
698 goto Done;
699 }
700
701 ASSERT (SmmVariableHeader != NULL);
702
703 CopyGuid (&SmmVariableHeader->Guid, VendorGuid);
704 SmmVariableHeader->DataSize = TempDataSize;
705 SmmVariableHeader->NameSize = VariableNameSize;
706 if (Attributes == NULL) {
707 SmmVariableHeader->Attributes = 0;
708 } else {
709 SmmVariableHeader->Attributes = *Attributes;
710 }
711
712 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
713
714 //
715 // Send data to SMM.
716 //
717 Status = SendCommunicateBuffer (PayloadSize);
718
719 //
720 // Get data from SMM.
721 //
722 if ((Status == EFI_SUCCESS) || (Status == EFI_BUFFER_TOO_SMALL)) {
723 //
724 // SMM CommBuffer DataSize can be a trimed value
725 // Only update DataSize when needed
726 //
727 *DataSize = SmmVariableHeader->DataSize;
728 }
729
730 if (Attributes != NULL) {
731 *Attributes = SmmVariableHeader->Attributes;
732 }
733
734 if (EFI_ERROR (Status)) {
735 goto Done;
736 }
737
738 if (Data != NULL) {
739 CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);
740 } else {
741 Status = EFI_INVALID_PARAMETER;
742 }
743
744Done:
745 return Status;
746}
747
777EFIAPI
779 IN CHAR16 *VariableName,
780 IN EFI_GUID *VendorGuid,
781 OUT UINT32 *Attributes OPTIONAL,
782 IN OUT UINTN *DataSize,
783 OUT VOID *Data
784 )
785{
786 EFI_STATUS Status;
787
788 if ((VariableName == NULL) || (VendorGuid == NULL) || (DataSize == NULL)) {
789 return EFI_INVALID_PARAMETER;
790 }
791
792 if (VariableName[0] == 0) {
793 return EFI_NOT_FOUND;
794 }
795
796 AcquireLockOnlyAtBootTime (&mVariableServicesLock);
797 if (mIsRuntimeCacheEnabled) {
798 Status = FindVariableInRuntimeCache (VariableName, VendorGuid, Attributes, DataSize, Data);
799 } else {
800 Status = FindVariableInSmm (VariableName, VendorGuid, Attributes, DataSize, Data);
801 }
802
803 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
804
805 return Status;
806}
807
835 IN OUT UINTN *VariableNameSize,
836 IN OUT CHAR16 *VariableName,
837 IN OUT EFI_GUID *VendorGuid
838 )
839{
840 EFI_STATUS Status;
841 UINTN VarNameSize;
842 VARIABLE_HEADER *VariablePtr;
843 VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
844 CACHE_INFO_FLAG *CacheInfoFlag;
845
846 Status = EFI_NOT_FOUND;
847 CacheInfoFlag = (CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer;
848
849 //
850 // The UEFI specification restricts Runtime Services callers from invoking the same or certain other Runtime Service
851 // functions prior to completion and return from a previous Runtime Service call. These restrictions prevent
852 // a GetVariable () or GetNextVariable () call from being issued until a prior call has returned. The runtime
853 // cache read lock should always be free when entering this function.
854 //
855 ASSERT (!(CacheInfoFlag->ReadLock));
856
858
859 CacheInfoFlag->ReadLock = TRUE;
860 if (!(CacheInfoFlag->PendingUpdate)) {
861 //
862 // 0: Volatile, 1: HOB, 2: Non-Volatile.
863 // The index and attributes mapping must be kept in this order as FindVariable
864 // makes use of this mapping to implement search algorithm.
865 //
866 VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer;
867 VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer;
868 VariableStoreHeader[VariableStoreTypeNv] = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer;
869
871 VariableName,
872 VendorGuid,
873 VariableStoreHeader,
874 &VariablePtr,
875 mVariableAuthFormat
876 );
877 if (!EFI_ERROR (Status)) {
878 VarNameSize = NameSizeOfVariable (VariablePtr, mVariableAuthFormat);
879 ASSERT (VarNameSize != 0);
880 if (VarNameSize <= *VariableNameSize) {
881 CopyMem (VariableName, GetVariableNamePtr (VariablePtr, mVariableAuthFormat), VarNameSize);
882 CopyMem (VendorGuid, GetVendorGuidPtr (VariablePtr, mVariableAuthFormat), sizeof (EFI_GUID));
883 Status = EFI_SUCCESS;
884 } else {
885 Status = EFI_BUFFER_TOO_SMALL;
886 }
887
888 *VariableNameSize = VarNameSize;
889 }
890 }
891
892 CacheInfoFlag->ReadLock = FALSE;
893
894 return Status;
895}
896
924 IN OUT UINTN *VariableNameSize,
925 IN OUT CHAR16 *VariableName,
926 IN OUT EFI_GUID *VendorGuid
927 )
928{
929 EFI_STATUS Status;
930 UINTN PayloadSize;
932 UINTN OutVariableNameSize;
933 UINTN InVariableNameSize;
934
935 OutVariableNameSize = *VariableNameSize;
936 InVariableNameSize = StrSize (VariableName);
937 SmmGetNextVariableName = NULL;
938
939 //
940 // If input string exceeds SMM payload limit. Return failure
941 //
942 if (InVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
943 return EFI_INVALID_PARAMETER;
944 }
945
946 //
947 // Init the communicate buffer. The buffer data size is:
948 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
949 //
950 if (OutVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
951 //
952 // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size
953 //
954 OutVariableNameSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);
955 }
956
957 //
958 // Payload should be Guid + NameSize + MAX of Input & Output buffer
959 //
960 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize);
961
962 Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
963 if (EFI_ERROR (Status)) {
964 goto Done;
965 }
966
967 ASSERT (SmmGetNextVariableName != NULL);
968
969 //
970 // SMM comm buffer->NameSize is buffer size for return string
971 //
972 SmmGetNextVariableName->NameSize = OutVariableNameSize;
973
974 CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);
975 //
976 // Copy whole string
977 //
978 CopyMem (SmmGetNextVariableName->Name, VariableName, InVariableNameSize);
979 if (OutVariableNameSize > InVariableNameSize) {
980 ZeroMem ((UINT8 *)SmmGetNextVariableName->Name + InVariableNameSize, OutVariableNameSize - InVariableNameSize);
981 }
982
983 //
984 // Send data to SMM
985 //
986 Status = SendCommunicateBuffer (PayloadSize);
987
988 //
989 // Get data from SMM.
990 //
991 if ((Status == EFI_SUCCESS) || (Status == EFI_BUFFER_TOO_SMALL)) {
992 //
993 // SMM CommBuffer NameSize can be a trimed value
994 // Only update VariableNameSize when needed
995 //
996 *VariableNameSize = SmmGetNextVariableName->NameSize;
997 }
998
999 if (EFI_ERROR (Status)) {
1000 goto Done;
1001 }
1002
1003 CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid);
1004 CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);
1005
1006Done:
1007 return Status;
1008}
1009
1036EFIAPI
1038 IN OUT UINTN *VariableNameSize,
1039 IN OUT CHAR16 *VariableName,
1040 IN OUT EFI_GUID *VendorGuid
1041 )
1042{
1043 EFI_STATUS Status;
1044 UINTN MaxLen;
1045
1046 Status = EFI_NOT_FOUND;
1047
1048 if ((VariableNameSize == NULL) || (VariableName == NULL) || (VendorGuid == NULL)) {
1049 return EFI_INVALID_PARAMETER;
1050 }
1051
1052 //
1053 // Calculate the possible maximum length of name string, including the Null terminator.
1054 //
1055 MaxLen = *VariableNameSize / sizeof (CHAR16);
1056 if ((MaxLen == 0) || (StrnLenS (VariableName, MaxLen) == MaxLen)) {
1057 //
1058 // Null-terminator is not found in the first VariableNameSize bytes of the input VariableName buffer,
1059 // follow spec to return EFI_INVALID_PARAMETER.
1060 //
1061 return EFI_INVALID_PARAMETER;
1062 }
1063
1064 AcquireLockOnlyAtBootTime (&mVariableServicesLock);
1065 if (mIsRuntimeCacheEnabled) {
1066 Status = GetNextVariableNameInRuntimeCache (VariableNameSize, VariableName, VendorGuid);
1067 } else {
1068 Status = GetNextVariableNameInSmm (VariableNameSize, VariableName, VendorGuid);
1069 }
1070
1071 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
1072
1073 return Status;
1074}
1075
1109EFIAPI
1111 IN CHAR16 *VariableName,
1112 IN EFI_GUID *VendorGuid,
1113 IN UINT32 Attributes,
1114 IN UINTN DataSize,
1115 IN VOID *Data
1116 )
1117{
1118 EFI_STATUS Status;
1119 UINTN PayloadSize;
1121 UINTN VariableNameSize;
1122
1123 //
1124 // Check input parameters.
1125 //
1126 if ((VariableName == NULL) || (VariableName[0] == 0) || (VendorGuid == NULL)) {
1127 return EFI_INVALID_PARAMETER;
1128 }
1129
1130 if ((DataSize != 0) && (Data == NULL)) {
1131 return EFI_INVALID_PARAMETER;
1132 }
1133
1134 VariableNameSize = StrSize (VariableName);
1135 SmmVariableHeader = NULL;
1136
1137 //
1138 // If VariableName or DataSize exceeds SMM payload limit. Return failure
1139 //
1140 if ((VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||
1141 (DataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize))
1142 {
1143 return EFI_INVALID_PARAMETER;
1144 }
1145
1146 AcquireLockOnlyAtBootTime (&mVariableServicesLock);
1147
1148 //
1149 // Init the communicate buffer. The buffer data size is:
1150 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
1151 //
1152 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + DataSize;
1153 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);
1154 if (EFI_ERROR (Status)) {
1155 goto Done;
1156 }
1157
1158 ASSERT (SmmVariableHeader != NULL);
1159
1160 CopyGuid ((EFI_GUID *)&SmmVariableHeader->Guid, VendorGuid);
1161 SmmVariableHeader->DataSize = DataSize;
1162 SmmVariableHeader->NameSize = VariableNameSize;
1163 SmmVariableHeader->Attributes = Attributes;
1164 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
1165 CopyMem ((UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, Data, DataSize);
1166
1167 //
1168 // Send data to SMM.
1169 //
1170 Status = SendCommunicateBuffer (PayloadSize);
1171
1172Done:
1173 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
1174
1175 if (!EfiAtRuntime ()) {
1176 if (!EFI_ERROR (Status)) {
1178 VariableName,
1179 VendorGuid
1180 );
1181 }
1182 }
1183
1184 return Status;
1185}
1186
1205EFIAPI
1207 IN UINT32 Attributes,
1208 OUT UINT64 *MaximumVariableStorageSize,
1209 OUT UINT64 *RemainingVariableStorageSize,
1210 OUT UINT64 *MaximumVariableSize
1211 )
1212{
1213 EFI_STATUS Status;
1214 UINTN PayloadSize;
1216
1217 SmmQueryVariableInfo = NULL;
1218
1219 if ((MaximumVariableStorageSize == NULL) || (RemainingVariableStorageSize == NULL) || (MaximumVariableSize == NULL) || (Attributes == 0)) {
1220 return EFI_INVALID_PARAMETER;
1221 }
1222
1223 AcquireLockOnlyAtBootTime (&mVariableServicesLock);
1224
1225 //
1226 // Init the communicate buffer. The buffer data size is:
1227 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;
1228 //
1229 PayloadSize = sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO);
1230 Status = InitCommunicateBuffer ((VOID **)&SmmQueryVariableInfo, PayloadSize, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO);
1231 if (EFI_ERROR (Status)) {
1232 goto Done;
1233 }
1234
1235 ASSERT (SmmQueryVariableInfo != NULL);
1236
1237 SmmQueryVariableInfo->Attributes = Attributes;
1238
1239 //
1240 // Send data to SMM.
1241 //
1242 Status = SendCommunicateBuffer (PayloadSize);
1243 if (EFI_ERROR (Status)) {
1244 goto Done;
1245 }
1246
1247 //
1248 // Get data from SMM.
1249 //
1250 *MaximumVariableSize = SmmQueryVariableInfo->MaximumVariableSize;
1251 *MaximumVariableStorageSize = SmmQueryVariableInfo->MaximumVariableStorageSize;
1252 *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;
1253
1254Done:
1255 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
1256 return Status;
1257}
1258
1268VOID
1269EFIAPI
1271 IN EFI_EVENT Event,
1272 IN VOID *Context
1273 )
1274{
1275 //
1276 // Init the communicate buffer. The buffer data size is:
1277 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
1278 //
1279 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE);
1280
1281 //
1282 // Send data to SMM.
1283 //
1285}
1286
1296VOID
1297EFIAPI
1299 IN EFI_EVENT Event,
1300 IN VOID *Context
1301 )
1302{
1303 //
1304 // Init the communicate buffer. The buffer data size is:
1305 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
1306 //
1307 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT);
1308
1309 //
1310 // Send data to SMM.
1311 //
1313
1314 //
1315 // Install the system configuration table for variable info data captured
1316 //
1317 if (mIsRuntimeCacheEnabled && FeaturePcdGet (PcdVariableCollectStatistics)) {
1318 if (mVariableAuthFormat) {
1319 gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, mVariableInfo);
1320 } else {
1321 gBS->InstallConfigurationTable (&gEfiVariableGuid, mVariableInfo);
1322 }
1323 }
1324
1325 gBS->CloseEvent (Event);
1326}
1327
1338VOID
1339EFIAPI
1341 IN EFI_EVENT Event,
1342 IN VOID *Context
1343 )
1344{
1345 EfiConvertPointer (0x0, (VOID **)&mVariableBuffer);
1346 EfiConvertPointer (0x0, (VOID **)&mMmCommunication2);
1347 EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mVariableRtCacheInfo.CacheInfoFlagBuffer);
1348 EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mVariableRtCacheInfo.RuntimeHobCacheBuffer);
1349 EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mVariableRtCacheInfo.RuntimeNvCacheBuffer);
1350 EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mVariableRtCacheInfo.RuntimeVolatileCacheBuffer);
1351}
1352
1363EFIAPI
1365 OUT UINTN *VariablePayloadSize
1366 )
1367{
1368 EFI_STATUS Status;
1370 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
1371 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
1372 UINTN CommSize;
1373 UINT8 *CommBuffer;
1374
1375 SmmGetPayloadSize = NULL;
1376 CommBuffer = NULL;
1377
1378 if (VariablePayloadSize == NULL) {
1379 return EFI_INVALID_PARAMETER;
1380 }
1381
1382 AcquireLockOnlyAtBootTime (&mVariableServicesLock);
1383
1384 //
1385 // Init the communicate buffer. The buffer data size is:
1386 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
1387 //
1389 CommBuffer = AllocateZeroPool (CommSize);
1390 if (CommBuffer == NULL) {
1391 Status = EFI_OUT_OF_RESOURCES;
1392 goto Done;
1393 }
1394
1395 SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
1396 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
1398
1399 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
1400 SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE;
1401 SmmGetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *)SmmVariableFunctionHeader->Data;
1402
1403 //
1404 // Send data to SMM.
1405 //
1406 Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);
1407 ASSERT_EFI_ERROR (Status);
1408
1409 Status = SmmVariableFunctionHeader->ReturnStatus;
1410 if (EFI_ERROR (Status)) {
1411 goto Done;
1412 }
1413
1414 //
1415 // Get data from SMM.
1416 //
1417 *VariablePayloadSize = SmmGetPayloadSize->VariablePayloadSize;
1418
1419Done:
1420 if (CommBuffer != NULL) {
1421 FreePool (CommBuffer);
1422 }
1423
1424 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
1425 return Status;
1426}
1427
1444 OUT UINTN *TotalHobStorageSize,
1445 OUT UINTN *TotalNvStorageSize,
1446 OUT UINTN *TotalVolatileStorageSize,
1447 OUT BOOLEAN *AuthenticatedVariableUsage
1448 )
1449{
1450 EFI_STATUS Status;
1452 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
1453 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
1454 UINTN CommSize;
1455 UINT8 *CommBuffer;
1456
1457 SmmGetRuntimeCacheInfo = NULL;
1458 CommBuffer = mVariableBuffer;
1459
1460 if ((TotalHobStorageSize == NULL) || (TotalNvStorageSize == NULL) || (TotalVolatileStorageSize == NULL) || (AuthenticatedVariableUsage == NULL)) {
1461 return EFI_INVALID_PARAMETER;
1462 }
1463
1464 if (CommBuffer == NULL) {
1465 return EFI_OUT_OF_RESOURCES;
1466 }
1467
1468 AcquireLockOnlyAtBootTime (&mVariableServicesLock);
1469
1471 ZeroMem (CommBuffer, CommSize);
1472
1473 SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
1474 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
1476
1477 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
1478 SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO;
1479 SmmGetRuntimeCacheInfo = (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *)SmmVariableFunctionHeader->Data;
1480
1481 //
1482 // Send data to SMM.
1483 //
1484 Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);
1485 ASSERT_EFI_ERROR (Status);
1486 if (CommSize <= SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
1487 Status = EFI_BAD_BUFFER_SIZE;
1488 goto Done;
1489 }
1490
1491 Status = SmmVariableFunctionHeader->ReturnStatus;
1492 if (EFI_ERROR (Status)) {
1493 goto Done;
1494 }
1495
1496 //
1497 // Get data from SMM.
1498 //
1499 *TotalHobStorageSize = SmmGetRuntimeCacheInfo->TotalHobStorageSize;
1500 *TotalNvStorageSize = SmmGetRuntimeCacheInfo->TotalNvStorageSize;
1501 *TotalVolatileStorageSize = SmmGetRuntimeCacheInfo->TotalVolatileStorageSize;
1502 *AuthenticatedVariableUsage = SmmGetRuntimeCacheInfo->AuthenticatedVariableUsage;
1503
1504Done:
1505 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
1506 return Status;
1507}
1508
1516VOID
1518 IN VARIABLE_STORE_HEADER *VariableCacheBuffer,
1519 IN UINTN TotalVariableCacheSize
1520 )
1521{
1522 if (TotalVariableCacheSize > 0) {
1523 ASSERT ((VariableCacheBuffer != NULL) && (TotalVariableCacheSize >= sizeof (VARIABLE_STORE_HEADER)));
1524
1525 SetMem32 ((VOID *)VariableCacheBuffer, TotalVariableCacheSize, (UINT32)0xFFFFFFFF);
1526 ZeroMem ((VOID *)VariableCacheBuffer, sizeof (VARIABLE_STORE_HEADER));
1527 VariableCacheBuffer->Size = (UINT32)TotalVariableCacheSize;
1528 VariableCacheBuffer->Format = VARIABLE_STORE_FORMATTED;
1529 VariableCacheBuffer->State = VARIABLE_STORE_HEALTHY;
1530 }
1531}
1532
1544 IN EFI_HOB_GUID_TYPE *RuntimeCacheInfoGuidHob
1545 )
1546{
1547 EFI_STATUS Status;
1548 UINTN ExpectedHobCacheSize;
1549 UINTN ExpectedNvCacheSize;
1550 UINTN ExpectedVolatileCacheSize;
1551 UINTN AllocatedHobCacheSize;
1552 UINTN AllocatedNvCacheSize;
1553 UINTN AllocatedVolatileCacheSize;
1554 VARIABLE_RUNTIME_CACHE_INFO *VariableRuntimeCacheInfo;
1555
1556 //
1557 // Get needed runtime cache buffer size and check if auth variables are to be used from SMM
1558 //
1559 Status = GetRuntimeCacheInfo (
1560 &ExpectedHobCacheSize,
1561 &ExpectedNvCacheSize,
1562 &ExpectedVolatileCacheSize,
1563 &mVariableAuthFormat
1564 );
1565 if (!EFI_ERROR (Status)) {
1566 VariableRuntimeCacheInfo = GET_GUID_HOB_DATA (RuntimeCacheInfoGuidHob);
1567 AllocatedHobCacheSize = EFI_PAGES_TO_SIZE ((UINTN)VariableRuntimeCacheInfo->RuntimeHobCachePages);
1568 AllocatedNvCacheSize = EFI_PAGES_TO_SIZE ((UINTN)VariableRuntimeCacheInfo->RuntimeNvCachePages);
1569 AllocatedVolatileCacheSize = EFI_PAGES_TO_SIZE ((UINTN)VariableRuntimeCacheInfo->RuntimeVolatileCachePages);
1570
1571 ASSERT (
1572 (AllocatedHobCacheSize >= ExpectedHobCacheSize) &&
1573 (AllocatedNvCacheSize >= ExpectedNvCacheSize) &&
1574 (AllocatedVolatileCacheSize >= ExpectedVolatileCacheSize)
1575 );
1576
1577 CopyMem (&mVariableRtCacheInfo, VariableRuntimeCacheInfo, sizeof (VARIABLE_RUNTIME_CACHE_INFO));
1578 InitVariableStoreHeader ((VOID *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer, AllocatedHobCacheSize);
1579 InitVariableStoreHeader ((VOID *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer, AllocatedNvCacheSize);
1580 InitVariableStoreHeader ((VOID *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer, AllocatedVolatileCacheSize);
1581 }
1582
1583 return Status;
1584}
1585
1597 VOID
1598 )
1599{
1600 EFI_STATUS Status;
1602 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
1603 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
1604 UINTN CommSize;
1605 UINT8 *CommBuffer;
1606
1607 SmmRuntimeVarCacheContext = NULL;
1608 CommBuffer = mVariableBuffer;
1609
1610 if (CommBuffer == NULL) {
1611 return EFI_OUT_OF_RESOURCES;
1612 }
1613
1614 AcquireLockOnlyAtBootTime (&mVariableServicesLock);
1615
1616 //
1617 // Init the communicate buffer. The buffer data size is:
1618 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);
1619 //
1621 ZeroMem (CommBuffer, CommSize);
1622
1623 SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
1624 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
1626
1627 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
1628 SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT;
1629 SmmRuntimeVarCacheContext = (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *)SmmVariableFunctionHeader->Data;
1630
1631 SmmRuntimeVarCacheContext->RuntimeHobCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer;
1632 SmmRuntimeVarCacheContext->RuntimeVolatileCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer;
1633 SmmRuntimeVarCacheContext->RuntimeNvCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer;
1634 SmmRuntimeVarCacheContext->PendingUpdate = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->PendingUpdate;
1635 SmmRuntimeVarCacheContext->ReadLock = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->ReadLock;
1636 SmmRuntimeVarCacheContext->HobFlushComplete = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->HobFlushComplete;
1637
1638 //
1639 // Send data to SMM.
1640 //
1641 Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);
1642 ASSERT_EFI_ERROR (Status);
1643 if (CommSize <= SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
1644 Status = EFI_BAD_BUFFER_SIZE;
1645 goto Done;
1646 }
1647
1648 Status = SmmVariableFunctionHeader->ReturnStatus;
1649 if (EFI_ERROR (Status)) {
1650 goto Done;
1651 }
1652
1653Done:
1654 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
1655 return Status;
1656}
1657
1665VOID
1666EFIAPI
1668 IN EFI_EVENT Event,
1669 IN VOID *Context
1670 )
1671{
1672 EFI_STATUS Status;
1673 EFI_HOB_GUID_TYPE *GuidHob;
1674
1675 Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);
1676 if (EFI_ERROR (Status)) {
1677 return;
1678 }
1679
1680 Status = gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid, NULL, (VOID **)&mMmCommunication2);
1681 ASSERT_EFI_ERROR (Status);
1682
1683 //
1684 // Allocate memory for variable communicate buffer.
1685 //
1686 Status = GetVariablePayloadSize (&mVariableBufferPayloadSize);
1687 ASSERT_EFI_ERROR (Status);
1688 mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + mVariableBufferPayloadSize;
1689 mVariableBuffer = AllocateRuntimePool (mVariableBufferSize);
1690 ASSERT (mVariableBuffer != NULL);
1691
1692 //
1693 // Save the buffer physical address used for SMM conmunication.
1694 //
1695 mVariableBufferPhysical = mVariableBuffer;
1696
1697 GuidHob = GetFirstGuidHob (&gEdkiiVariableRuntimeCacheInfoHobGuid);
1698 if (GuidHob != NULL) {
1699 mIsRuntimeCacheEnabled = TRUE;
1700 DEBUG ((DEBUG_INFO, "Variable driver runtime cache is enabled.\n"));
1701
1702 Status = InitVariableCache (GuidHob);
1703 if (!EFI_ERROR (Status)) {
1705 if (!EFI_ERROR (Status)) {
1707 }
1708 }
1709
1710 if (EFI_ERROR (Status)) {
1711 ZeroMem (&mVariableRtCacheInfo, sizeof (VARIABLE_RUNTIME_CACHE_INFO));
1712 }
1713
1714 ASSERT_EFI_ERROR (Status);
1715 } else {
1716 DEBUG ((DEBUG_INFO, "Variable driver runtime cache is disabled.\n"));
1717 }
1718
1719 gRT->GetVariable = RuntimeServiceGetVariable;
1720 gRT->GetNextVariableName = RuntimeServiceGetNextVariableName;
1721 gRT->SetVariable = RuntimeServiceSetVariable;
1722 gRT->QueryVariableInfo = RuntimeServiceQueryVariableInfo;
1723
1724 //
1725 // Install the Variable Architectural Protocol on a new handle.
1726 //
1727 Status = gBS->InstallProtocolInterface (
1728 &mHandle,
1729 &gEfiVariableArchProtocolGuid,
1731 NULL
1732 );
1733 ASSERT_EFI_ERROR (Status);
1734
1735 mVariableLock.RequestToLock = VariableLockRequestToLock;
1736 Status = gBS->InstallMultipleProtocolInterfaces (
1737 &mHandle,
1738 &gEdkiiVariableLockProtocolGuid,
1739 &mVariableLock,
1740 NULL
1741 );
1742 ASSERT_EFI_ERROR (Status);
1743
1744 mVarCheck.RegisterSetVariableCheckHandler = VarCheckRegisterSetVariableCheckHandler;
1745 mVarCheck.VariablePropertySet = VarCheckVariablePropertySet;
1746 mVarCheck.VariablePropertyGet = VarCheckVariablePropertyGet;
1747 Status = gBS->InstallMultipleProtocolInterfaces (
1748 &mHandle,
1749 &gEdkiiVarCheckProtocolGuid,
1750 &mVarCheck,
1751 NULL
1752 );
1753 ASSERT_EFI_ERROR (Status);
1754
1755 gBS->CloseEvent (Event);
1756}
1757
1765VOID
1766EFIAPI
1768 IN EFI_EVENT Event,
1769 IN VOID *Context
1770 )
1771{
1772 EFI_STATUS Status;
1773 VOID *ProtocolOps;
1774
1775 //
1776 // Check whether the protocol is installed or not.
1777 //
1778 Status = gBS->LocateProtocol (&gSmmVariableWriteGuid, NULL, (VOID **)&ProtocolOps);
1779 if (EFI_ERROR (Status)) {
1780 return;
1781 }
1782
1783 //
1784 // Some Secure Boot Policy Var (SecureBoot, etc) updates following other
1785 // Secure Boot Policy Variable change. Record their initial value.
1786 //
1788
1789 Status = gBS->InstallProtocolInterface (
1790 &mHandle,
1791 &gEfiVariableWriteArchProtocolGuid,
1793 NULL
1794 );
1795 ASSERT_EFI_ERROR (Status);
1796
1797 gBS->CloseEvent (Event);
1798}
1799
1813EFIAPI
1815 IN EFI_HANDLE ImageHandle,
1816 IN EFI_SYSTEM_TABLE *SystemTable
1817 )
1818{
1819 VOID *SmmVariableRegistration;
1820 VOID *SmmVariableWriteRegistration;
1821 EFI_EVENT OnReadyToBootEvent;
1822 EFI_EVENT ExitBootServiceEvent;
1823 EFI_EVENT LegacyBootEvent;
1824
1825 EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);
1826
1827 //
1828 // Smm variable service is ready
1829 //
1831 &gEfiSmmVariableProtocolGuid,
1832 TPL_CALLBACK,
1834 NULL,
1835 &SmmVariableRegistration
1836 );
1837
1838 //
1839 // Smm Non-Volatile variable write service is ready
1840 //
1842 &gSmmVariableWriteGuid,
1843 TPL_CALLBACK,
1845 NULL,
1846 &SmmVariableWriteRegistration
1847 );
1848
1849 //
1850 // Register the event to reclaim variable for OS usage.
1851 //
1853 TPL_NOTIFY,
1855 NULL,
1856 &OnReadyToBootEvent
1857 );
1858
1859 //
1860 // Register the event to inform SMM variable that it is at runtime.
1861 //
1862 gBS->CreateEventEx (
1863 EVT_NOTIFY_SIGNAL,
1864 TPL_NOTIFY,
1866 NULL,
1867 &gEfiEventExitBootServicesGuid,
1868 &ExitBootServiceEvent
1869 );
1870
1871 //
1872 // Register the event to inform SMM variable that it is at runtime for legacy boot.
1873 // Reuse OnExitBootServices() here.
1874 //
1876 TPL_NOTIFY,
1878 NULL,
1879 &LegacyBootEvent
1880 );
1881
1882 //
1883 // Register the event to convert the pointer for runtime.
1884 //
1885 gBS->CreateEventEx (
1886 EVT_NOTIFY_SIGNAL,
1887 TPL_NOTIFY,
1889 NULL,
1890 &gEfiEventVirtualAddressChangeGuid,
1891 &mVirtualAddressChangeEvent
1892 );
1893
1894 // Initialize the VariablePolicy protocol and engine.
1895 VariablePolicySmmDxeMain (ImageHandle, SystemTable);
1896
1897 return EFI_SUCCESS;
1898}
UINT64 UINTN
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
UINTN EFIAPI StrnLenS(IN CONST CHAR16 *String, IN UINTN MaxSize)
Definition: SafeString.c:119
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID *EFIAPI SetMem32(OUT VOID *Buffer, IN UINTN Length, IN UINT32 Value)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateRuntimePool(IN UINTN AllocationSize)
EFI_RUNTIME_SERVICES * gRT
VOID EFIAPI SecureBootHook(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid)
Definition: Measurement.c:236
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define MAX(a, b)
Definition: Base.h:992
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
EFI_STATUS EFIAPI Lock(IN EFI_SMM_ACCESS2_PROTOCOL *This)
Definition: SmmAccessDxe.c:133
#define SMM_COMMUNICATE_HEADER_SIZE
#define SMM_VARIABLE_COMMUNICATE_HEADER_SIZE
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiCreateEventLegacyBootEx(IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, IN VOID *NotifyContext OPTIONAL, OUT EFI_EVENT *LegacyBootEvent)
Definition: UefiNotTiano.c:68
VOID EFIAPI EfiReleaseLock(IN EFI_LOCK *Lock)
Definition: UefiLib.c:499
VOID EFIAPI EfiAcquireLock(IN EFI_LOCK *Lock)
Definition: UefiLib.c:434
EFI_LOCK *EFIAPI EfiInitializeLock(IN OUT EFI_LOCK *Lock, IN EFI_TPL Priority)
Definition: UefiLib.c:405
EFI_STATUS EFIAPI EfiCreateEventReadyToBootEx(IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, IN VOID *NotifyContext OPTIONAL, OUT EFI_EVENT *ReadyToBootEvent)
Definition: UefiNotTiano.c:164
EFI_EVENT EFIAPI EfiCreateProtocolNotifyEvent(IN EFI_GUID *ProtocolGuid, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *NotifyContext OPTIONAL, OUT VOID **Registration)
Definition: UefiLib.c:134
BOOLEAN EFIAPI EfiAtRuntime(VOID)
Definition: RuntimeLib.c:167
EFI_STATUS EFIAPI EfiConvertPointer(IN UINTN DebugDisposition, IN OUT VOID **Address)
Definition: RuntimeLib.c:561
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
UINTN NameSizeOfVariable(IN VARIABLE_HEADER *Variable, IN BOOLEAN AuthFlag)
Definition: Variable.c:174
VARIABLE_HEADER * GetStartPointer(IN VARIABLE_STORE_HEADER *VarStoreHeader)
Definition: Variable.c:86
UINT8 * GetVariableDataPtr(IN VARIABLE_HEADER *Variable, IN VARIABLE_HEADER *VariableHeader, IN BOOLEAN AuthFlag)
Definition: Variable.c:300
CHAR16 * GetVariableNamePtr(IN VARIABLE_HEADER *Variable, IN BOOLEAN AuthFlag)
Definition: Variable.c:256
VARIABLE_HEADER * GetEndPointer(IN VARIABLE_STORE_HEADER *VarStoreHeader)
Definition: Variable.c:109
UINTN DataSizeOfVariable(IN VARIABLE_HEADER *Variable, IN BOOLEAN AuthFlag)
Definition: Variable.c:215
EFI_STATUS FindVariableEx(IN VARIABLE_STORE_INFO *StoreInfo, IN CONST CHAR16 *VariableName, IN CONST EFI_GUID *VendorGuid, OUT VARIABLE_POINTER_TRACK *PtrTrack)
Definition: Variable.c:844
EFI_GUID * GetVendorGuidPtr(IN VARIABLE_HEADER *Variable, IN BOOLEAN AuthFlag)
Definition: Variable.c:274
#define VARIABLE_STORE_FORMATTED
EFI_STATUS EFIAPI VariableServiceGetNextVariableInternal(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN VARIABLE_STORE_HEADER **VariableStoreList, OUT VARIABLE_HEADER **VariablePtr, IN BOOLEAN AuthFormat)
VOID UpdateVariableInfo(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN BOOLEAN Volatile, IN BOOLEAN Read, IN BOOLEAN Write, IN BOOLEAN Delete, IN BOOLEAN Cache, IN OUT VARIABLE_INFO_ENTRY **VariableInfo)
EFI_STATUS SendRuntimeVariableCacheContextToSmm(VOID)
EFI_STATUS SendCommunicateBuffer(IN UINTN DataSize)
EFI_STATUS EFIAPI RuntimeServiceSetVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data)
EFI_STATUS GetRuntimeCacheInfo(OUT UINTN *TotalHobStorageSize, OUT UINTN *TotalNvStorageSize, OUT UINTN *TotalVolatileStorageSize, OUT BOOLEAN *AuthenticatedVariableUsage)
EFI_STATUS EFIAPI VariableSmmRuntimeInitialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
VOID SyncRuntimeCache(VOID)
VOID InitVariableStoreHeader(IN VARIABLE_STORE_HEADER *VariableCacheBuffer, IN UINTN TotalVariableCacheSize)
EFI_STATUS EFIAPI VarCheckVariablePropertySet(IN CHAR16 *Name, IN EFI_GUID *Guid, IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty)
VOID CheckForRuntimeCacheSync(VOID)
EFI_STATUS EFIAPI VariablePolicySmmDxeMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS EFIAPI VariableLockRequestToLock(IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This, IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid)
=== CODE UNDER TEST ===========================================================================
BOOLEAN AtRuntime(VOID)
EFI_STATUS EFIAPI VarCheckRegisterSetVariableCheckHandler(IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler)
EFI_STATUS EFIAPI RuntimeServiceQueryVariableInfo(IN UINT32 Attributes, OUT UINT64 *MaximumVariableStorageSize, OUT UINT64 *RemainingVariableStorageSize, OUT UINT64 *MaximumVariableSize)
EFI_STATUS EFIAPI VarCheckVariablePropertyGet(IN CHAR16 *Name, IN EFI_GUID *Guid, OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty)
EFI_STATUS GetNextVariableNameInSmm(IN OUT UINTN *VariableNameSize, IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid)
EFI_STATUS EFIAPI GetVariablePayloadSize(OUT UINTN *VariablePayloadSize)
EFI_STATUS FindVariableInSmm(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT UINT32 *Attributes OPTIONAL, IN OUT UINTN *DataSize, OUT VOID *Data OPTIONAL)
VOID EFIAPI OnReadyToBoot(IN EFI_EVENT Event, IN VOID *Context)
VOID EFIAPI RecordSecureBootPolicyVarData(VOID)
Definition: Measurement.c:347
EFI_STATUS EFIAPI RuntimeServiceGetNextVariableName(IN OUT UINTN *VariableNameSize, IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid)
VOID EFIAPI VariableAddressChangeEvent(IN EFI_EVENT Event, IN VOID *Context)
VOID EFIAPI OnExitBootServices(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS GetNextVariableNameInRuntimeCache(IN OUT UINTN *VariableNameSize, IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid)
VOID ReleaseLockOnlyAtBootTime(IN EFI_LOCK *Lock)
EFI_STATUS InitVariableCache(IN EFI_HOB_GUID_TYPE *RuntimeCacheInfoGuidHob)
VOID EFIAPI SmmVariableReady(IN EFI_EVENT Event, IN VOID *Context)
VOID AcquireLockOnlyAtBootTime(IN EFI_LOCK *Lock)
EFI_STATUS InitCommunicateBuffer(OUT VOID **DataPtr OPTIONAL, IN UINTN DataSize, IN UINTN Function)
VOID EFIAPI SmmVariableWriteReady(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS FindVariableInRuntimeCache(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT UINT32 *Attributes OPTIONAL, IN OUT UINTN *DataSize, OUT VOID *Data OPTIONAL)
EFI_HANDLE mHandle
EFI_STATUS EFIAPI RuntimeServiceGetVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT UINT32 *Attributes OPTIONAL, IN OUT UINTN *DataSize, OUT VOID *Data)
Definition: Base.h:213
EFI_PHYSICAL_ADDRESS RuntimeHobCacheBuffer
EFI_PHYSICAL_ADDRESS RuntimeNvCacheBuffer
EFI_PHYSICAL_ADDRESS RuntimeVolatileCacheBuffer