EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

MdeModulePkg/Universal/Variable/Pei/Variable.c

Go to the documentation of this file.
00001 
00019 #include "Variable.h"
00020 
00021 //
00022 // Module globals
00023 //
00024 EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi = {
00025   PeiGetVariable,
00026   PeiGetNextVariableName
00027 };
00028 
00029 EFI_PEI_PPI_DESCRIPTOR     mPpiListVariable = {
00030   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
00031   &gEfiPeiReadOnlyVariable2PpiGuid,
00032   &mVariablePpi
00033 };
00034 
00035 
00046 EFI_STATUS
00047 EFIAPI
00048 PeimInitializeVariableServices (
00049   IN       EFI_PEI_FILE_HANDLE       FileHandle,
00050   IN CONST EFI_PEI_SERVICES          **PeiServices
00051   )
00052 {
00053   return PeiServicesInstallPpi (&mPpiListVariable);
00054 }
00055 
00065 VARIABLE_HEADER *
00066 GetStartPointer (
00067   IN VARIABLE_STORE_HEADER       *VarStoreHeader
00068   )
00069 {
00070   //
00071   // The end of variable store
00072   //
00073   return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
00074 }
00075 
00076 
00085 VARIABLE_HEADER *
00086 GetEndPointer (
00087   IN VARIABLE_STORE_HEADER       *VarStoreHeader
00088   )
00089 {
00090   //
00091   // The end of variable store
00092   //
00093   return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
00094 }
00095 
00096 
00106 BOOLEAN
00107 IsValidVariableHeader (
00108   IN  VARIABLE_HEADER   *Variable
00109   )
00110 {
00111   if (Variable == NULL || Variable->StartId != VARIABLE_DATA ) {
00112     return FALSE;
00113   }
00114 
00115   return TRUE;
00116 }
00117 
00118 
00127 UINTN
00128 NameSizeOfVariable (
00129   IN  VARIABLE_HEADER   *Variable
00130   )
00131 {
00132   if (Variable->State    == (UINT8) (-1) ||
00133       Variable->DataSize == (UINT32) (-1) ||
00134       Variable->NameSize == (UINT32) (-1) ||
00135       Variable->Attributes == (UINT32) (-1)) {
00136     return 0;
00137   }
00138   return (UINTN) Variable->NameSize;
00139 }
00140 
00141 
00150 UINTN
00151 DataSizeOfVariable (
00152   IN  VARIABLE_HEADER   *Variable
00153   )
00154 {
00155   if (Variable->State    == (UINT8)  (-1) ||
00156       Variable->DataSize == (UINT32) (-1) ||
00157       Variable->NameSize == (UINT32) (-1) ||
00158       Variable->Attributes == (UINT32) (-1)) {
00159     return 0;
00160   }
00161   return (UINTN) Variable->DataSize;
00162 }
00163 
00172 CHAR16 *
00173 GetVariableNamePtr (
00174   IN  VARIABLE_HEADER   *Variable
00175   )
00176 {
00177 
00178   return (CHAR16 *) (Variable + 1);
00179 }
00180 
00181 
00190 UINT8 *
00191 GetVariableDataPtr (
00192   IN  VARIABLE_HEADER   *Variable
00193   )
00194 {
00195   UINTN Value;
00196   
00197   //
00198   // Be careful about pad size for alignment
00199   //
00200   Value =  (UINTN) GetVariableNamePtr (Variable);
00201   Value += NameSizeOfVariable (Variable);
00202   Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
00203 
00204   return (UINT8 *) Value;
00205 }
00206 
00207 
00216 VARIABLE_HEADER *
00217 GetNextVariablePtr (
00218   IN  VARIABLE_HEADER   *Variable
00219   )
00220 {
00221   UINTN Value;
00222 
00223   if (!IsValidVariableHeader (Variable)) {
00224     return NULL;
00225   }
00226 
00227   Value =  (UINTN) GetVariableDataPtr (Variable);
00228   Value += DataSizeOfVariable (Variable);
00229   Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
00230 
00231   //
00232   // Be careful about pad size for alignment
00233   //
00234   return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
00235 }
00236 
00247 VARIABLE_STORE_STATUS
00248 GetVariableStoreStatus (
00249   IN VARIABLE_STORE_HEADER *VarStoreHeader
00250   )
00251 {
00252         
00253   if (CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid) &&
00254       VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
00255       VarStoreHeader->State == VARIABLE_STORE_HEALTHY
00256       ) {
00257 
00258     return EfiValid;
00259   }
00260 
00261   if (((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff &&
00262       ((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff &&
00263       ((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff &&
00264       ((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff &&
00265       VarStoreHeader->Size == 0xffffffff &&
00266       VarStoreHeader->Format == 0xff &&
00267       VarStoreHeader->State == 0xff
00268       ) {
00269 
00270     return EfiRaw;
00271   } else {
00272     return EfiInvalid;
00273   }
00274 }
00275 
00276 
00289 EFI_STATUS
00290 CompareWithValidVariable (
00291   IN  VARIABLE_HEADER               *Variable,
00292   IN  CONST CHAR16                  *VariableName,
00293   IN  CONST EFI_GUID                *VendorGuid,
00294   OUT VARIABLE_POINTER_TRACK        *PtrTrack
00295   )
00296 {
00297   VOID  *Point;
00298 
00299   if (VariableName[0] == 0) {
00300     PtrTrack->CurrPtr = Variable;
00301     return EFI_SUCCESS;
00302   } else {
00303     //
00304     // Don't use CompareGuid function here for performance reasons.
00305     // Instead we compare the GUID a UINT32 at a time and branch
00306     // on the first failed comparison.
00307     //
00308     if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&
00309         (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&
00310         (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&
00311         (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])
00312         ) {
00313       ASSERT (NameSizeOfVariable (Variable) != 0);
00314       Point = (VOID *) GetVariableNamePtr (Variable);
00315       if (CompareMem (VariableName, Point, NameSizeOfVariable (Variable)) == 0) {
00316         PtrTrack->CurrPtr = Variable;
00317         return EFI_SUCCESS;
00318       }
00319     }
00320   }
00321 
00322   return EFI_NOT_FOUND;
00323 }
00324 
00333 VARIABLE_STORE_HEADER *
00334 GetVariableStore (
00335   IN VARIABLE_STORE_TYPE         Type,
00336   OUT VARIABLE_INDEX_TABLE       **IndexTable  OPTIONAL
00337   )
00338 {
00339   EFI_HOB_GUID_TYPE           *GuidHob;
00340   EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
00341   VARIABLE_STORE_HEADER       *VariableStoreHeader;
00342 
00343   if (IndexTable != NULL) {
00344     *IndexTable       = NULL;
00345   }
00346   VariableStoreHeader = NULL;
00347   switch (Type) {
00348     case VariableStoreTypeHob:
00349       GuidHob     = GetFirstGuidHob (&gEfiVariableGuid);
00350       if (GuidHob != NULL) {
00351         VariableStoreHeader = (VARIABLE_STORE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
00352       }
00353       break;
00354 
00355     case VariableStoreTypeNv:
00356       if (GetBootModeHob () != BOOT_IN_RECOVERY_MODE) {
00357         //
00358         // The content of NV storage for variable is not reliable in recovery boot mode.
00359         //
00360         FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ? 
00361                                                            PcdGet64 (PcdFlashNvStorageVariableBase64) : 
00362                                                            PcdGet32 (PcdFlashNvStorageVariableBase)
00363                                                           );
00364         VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);
00365 
00366         if (IndexTable != NULL) {
00367           GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
00368           if (GuidHob != NULL) {
00369             *IndexTable = GET_GUID_HOB_DATA (GuidHob);
00370           } else {
00371             //
00372             // If it's the first time to access variable region in flash, create a guid hob to record
00373             // VAR_ADDED type variable info.
00374             // Note that as the resource of PEI phase is limited, only store the limited number of 
00375             // VAR_ADDED type variables to reduce access time.
00376             //
00377             *IndexTable = BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
00378             (*IndexTable)->Length      = 0;
00379             (*IndexTable)->StartPtr    = GetStartPointer (VariableStoreHeader);
00380             (*IndexTable)->EndPtr      = GetEndPointer   (VariableStoreHeader);
00381             (*IndexTable)->GoneThrough = 0;
00382           }
00383         }
00384       }
00385       break;
00386 
00387     default:
00388       ASSERT (FALSE);
00389       break;
00390   }
00391 
00392   return VariableStoreHeader;
00393 }
00394 
00409 EFI_STATUS
00410 FindVariableEx (
00411   IN VARIABLE_STORE_HEADER       *VariableStoreHeader,
00412   IN VARIABLE_INDEX_TABLE        *IndexTable,
00413   IN CONST CHAR16                *VariableName,
00414   IN CONST EFI_GUID              *VendorGuid,
00415   OUT VARIABLE_POINTER_TRACK     *PtrTrack
00416   )
00417 {
00418   VARIABLE_HEADER         *Variable;
00419   VARIABLE_HEADER         *LastVariable;
00420   VARIABLE_HEADER         *MaxIndex;
00421   UINTN                   Index;
00422   UINTN                   Offset;
00423   BOOLEAN                 StopRecord;
00424 
00425   if (VariableStoreHeader == NULL) {
00426     return EFI_INVALID_PARAMETER;
00427   }
00428 
00429   if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
00430     return EFI_UNSUPPORTED;
00431   }
00432 
00433   if (~VariableStoreHeader->Size == 0) {
00434     return EFI_NOT_FOUND;
00435   }
00436 
00437   PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);
00438   PtrTrack->EndPtr   = GetEndPointer   (VariableStoreHeader);
00439 
00440   //
00441   // No Variable Address equals zero, so 0 as initial value is safe.
00442   //
00443   MaxIndex   = NULL;
00444 
00445   if (IndexTable != NULL) {
00446     //
00447     // traverse the variable index table to look for varible.
00448     // The IndexTable->Index[Index] records the distance of two neighbouring VAR_ADDED type variables.
00449     //
00450     for (Offset = 0, Index = 0; Index < IndexTable->Length; Index++) {
00451       ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]));
00452       Offset   += IndexTable->Index[Index];
00453       MaxIndex  = (VARIABLE_HEADER *) ((UINT8 *) IndexTable->StartPtr + Offset);
00454       if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
00455         return EFI_SUCCESS;
00456       }
00457     }
00458 
00459     if (IndexTable->GoneThrough != 0) {
00460       //
00461       // If the table has all the existing variables indexed and we still cannot find it.
00462       //
00463       return EFI_NOT_FOUND;
00464     }
00465   }
00466 
00467   if (MaxIndex != NULL) {
00468     //
00469     // HOB exists but the variable cannot be found in HOB
00470     // If not found in HOB, then let's start from the MaxIndex we've found.
00471     //
00472     Variable     = GetNextVariablePtr (MaxIndex);
00473     LastVariable = MaxIndex;
00474   } else {
00475     //
00476     // Start Pointers for the variable.
00477     // Actual Data Pointer where data can be written.
00478     //
00479     Variable     = PtrTrack->StartPtr;
00480     LastVariable = PtrTrack->StartPtr;
00481   }
00482 
00483   //
00484   // Find the variable by walk through non-volatile variable store
00485   //
00486   StopRecord = FALSE;
00487   while ((Variable < PtrTrack->EndPtr) && IsValidVariableHeader (Variable)) {
00488     if (Variable->State == VAR_ADDED) {
00489       //
00490       // Record Variable in VariableIndex HOB
00491       //
00492       if ((IndexTable != NULL) && !StopRecord) {
00493         Offset = (UINTN) Variable - (UINTN) LastVariable;
00494         if ((Offset > 0x0FFFF) || (IndexTable->Length == sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]))) {
00495           //
00496           // Stop to record if the distance of two neighbouring VAR_ADDED variable is larger than the allowable scope(UINT16),
00497           // or the record buffer is full.
00498           //
00499           StopRecord = TRUE;
00500         } else {
00501           IndexTable->Index[IndexTable->Length++] = (UINT16) Offset;
00502           LastVariable = Variable;
00503         }
00504       }
00505 
00506       if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
00507         return EFI_SUCCESS;
00508       }
00509     }
00510 
00511     Variable = GetNextVariablePtr (Variable);
00512   }
00513   //
00514   // If gone through the VariableStore, that means we never find in Firmware any more.
00515   //
00516   if ((IndexTable != NULL) && !StopRecord) {
00517     IndexTable->GoneThrough = 1;
00518   }
00519 
00520   PtrTrack->CurrPtr = NULL;
00521 
00522   return EFI_NOT_FOUND;
00523 }
00524 
00536 EFI_STATUS
00537 FindVariable (
00538   IN CONST  CHAR16            *VariableName,
00539   IN CONST  EFI_GUID          *VendorGuid,
00540   OUT VARIABLE_POINTER_TRACK  *PtrTrack
00541   )
00542 {
00543   EFI_STATUS                  Status;
00544   VARIABLE_STORE_HEADER       *VariableStoreHeader;
00545   VARIABLE_INDEX_TABLE        *IndexTable;
00546   VARIABLE_STORE_TYPE         Type;
00547 
00548   if (VariableName[0] != 0 && VendorGuid == NULL) {
00549     return EFI_INVALID_PARAMETER;
00550   }
00551 
00552   for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
00553     VariableStoreHeader = GetVariableStore (Type, &IndexTable);
00554     Status = FindVariableEx (
00555                VariableStoreHeader,
00556                IndexTable,
00557                VariableName,
00558                VendorGuid, 
00559                PtrTrack
00560                );
00561     if (!EFI_ERROR (Status)) {
00562       return Status;
00563     }
00564   }
00565 
00566   return EFI_NOT_FOUND;
00567 }
00568 
00595 EFI_STATUS
00596 EFIAPI
00597 PeiGetVariable (
00598   IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
00599   IN CONST  CHAR16                          *VariableName,
00600   IN CONST  EFI_GUID                        *VariableGuid,
00601   OUT       UINT32                          *Attributes,
00602   IN OUT    UINTN                           *DataSize,
00603   OUT       VOID                            *Data
00604   )
00605 {
00606   VARIABLE_POINTER_TRACK  Variable;
00607   UINTN                   VarDataSize;
00608   EFI_STATUS              Status;
00609 
00610   if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {
00611     return EFI_INVALID_PARAMETER;
00612   }
00613 
00614   //
00615   // Find existing variable
00616   //
00617   Status = FindVariable (VariableName, VariableGuid, &Variable);
00618   if (EFI_ERROR (Status)) {
00619     return Status;
00620   }
00621   //
00622   // Get data size
00623   //
00624   VarDataSize = DataSizeOfVariable (Variable.CurrPtr);
00625   if (*DataSize >= VarDataSize) {
00626     if (Data == NULL) {
00627       return EFI_INVALID_PARAMETER;
00628     }
00629 
00630     CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);
00631 
00632     if (Attributes != NULL) {
00633       *Attributes = Variable.CurrPtr->Attributes;
00634     }
00635 
00636     *DataSize = VarDataSize;
00637     return EFI_SUCCESS;
00638   } else {
00639     *DataSize = VarDataSize;
00640     return EFI_BUFFER_TOO_SMALL;
00641   }
00642 }
00643 
00673 EFI_STATUS
00674 EFIAPI
00675 PeiGetNextVariableName (
00676   IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
00677   IN OUT UINTN                              *VariableNameSize,
00678   IN OUT CHAR16                             *VariableName,
00679   IN OUT EFI_GUID                           *VariableGuid
00680   )
00681 {
00682   VARIABLE_STORE_TYPE     Type;
00683   VARIABLE_POINTER_TRACK  Variable;
00684   VARIABLE_POINTER_TRACK  VariableInHob;
00685   UINTN                   VarNameSize;
00686   EFI_STATUS              Status;
00687   VARIABLE_STORE_HEADER   *VariableStoreHeader[VariableStoreTypeMax];
00688 
00689   if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {
00690     return EFI_INVALID_PARAMETER;
00691   }
00692 
00693   Status = FindVariable (VariableName, VariableGuid, &Variable);
00694   if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
00695     return Status;
00696   }
00697 
00698   if (VariableName[0] != 0) {
00699     //
00700     // If variable name is not NULL, get next variable
00701     //
00702     Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
00703   }
00704 
00705   VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, NULL);
00706   VariableStoreHeader[VariableStoreTypeNv]  = GetVariableStore (VariableStoreTypeNv, NULL);
00707 
00708   while (TRUE) {
00709     //
00710     // Switch from HOB to Non-Volatile.
00711     //
00712     while ((Variable.CurrPtr >= Variable.EndPtr) ||
00713            (Variable.CurrPtr == NULL)            ||
00714            !IsValidVariableHeader (Variable.CurrPtr)
00715           ) {
00716       //
00717       // Find current storage index
00718       //
00719       for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
00720         if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {
00721           break;
00722         }
00723       }
00724       ASSERT (Type < VariableStoreTypeMax);
00725       //
00726       // Switch to next storage
00727       //
00728       for (Type++; Type < VariableStoreTypeMax; Type++) {
00729         if (VariableStoreHeader[Type] != NULL) {
00730           break;
00731         }
00732       }
00733       //
00734       // Capture the case that 
00735       // 1. current storage is the last one, or
00736       // 2. no further storage
00737       //
00738       if (Type == VariableStoreTypeMax) {
00739         return EFI_NOT_FOUND;
00740       }
00741       Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);
00742       Variable.EndPtr   = GetEndPointer   (VariableStoreHeader[Type]);
00743       Variable.CurrPtr  = Variable.StartPtr;
00744     }
00745 
00746     if (Variable.CurrPtr->State == VAR_ADDED) {
00747 
00748       //
00749       // Don't return NV variable when HOB overrides it
00750       //
00751       if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) &&
00752           (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))
00753          ) {
00754         Status = FindVariableEx (
00755                    VariableStoreHeader[VariableStoreTypeHob],
00756                    NULL,
00757                    GetVariableNamePtr (Variable.CurrPtr),
00758                    &Variable.CurrPtr->VendorGuid, 
00759                    &VariableInHob
00760                    );
00761         if (!EFI_ERROR (Status)) {
00762           Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
00763           continue;
00764         }
00765       }
00766 
00767       VarNameSize = NameSizeOfVariable (Variable.CurrPtr);
00768       ASSERT (VarNameSize != 0);
00769 
00770       if (VarNameSize <= *VariableNameSize) {
00771         CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);
00772 
00773         CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
00774 
00775         Status = EFI_SUCCESS;
00776       } else {
00777         Status = EFI_BUFFER_TOO_SMALL;
00778       }
00779 
00780       *VariableNameSize = VarNameSize;
00781       //
00782       // Variable is found
00783       //
00784       return Status;
00785     } else {
00786       Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
00787     }
00788   }
00789 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines