VirtualBox

Ignore:
Timestamp:
Oct 28, 2015 8:17:18 PM (9 years ago)
Author:
vboxsync
Message:

EFI/Firmware: 'svn merge /vendor/edk2/UDK2010.SR1 /vendor/edk2/current .', reverting and removing files+dirs listed in ReadMe.vbox, resolving conflicts with help from ../UDK2014.SP1/. This is a raw untested merge.

Location:
trunk/src/VBox/Devices/EFI/Firmware
Files:
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/EFI/Firmware

  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/AuthService.c

    r48674 r58459  
    33  service in UEFI2.2.
    44
    5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
     5Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    66This program and the accompanying materials
    77are licensed and made available under the terms and conditions of the BSD License
     
    4848  VARIABLE_HEADER         VariableHeader;
    4949  BOOLEAN                 Valid;
     50
     51  ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));
    5052
    5153  mVariableModuleGlobal->AuthenticatedVariableGuid[Physical] = &gEfiAuthenticatedVariableGuid;
     
    485487
    486488  OldPkList = NULL;
     489  ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));
    487490
    488491  if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
     
    624627
    625628  KekList = NULL;
     629  ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));
    626630
    627631  if (mPlatformMode == USER_MODE) {
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/EsalVariableDxeSal.inf

    r48674 r58459  
    11## @file
    2 #  Component description file for Extended SAL authentication variable
    3 #  service module.
     2#  Provides authenticated variable service for IPF platform
    43#
    5 # Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
     4#  This module installs variable arch protocol and variable write arch protocol to provide
     5#  four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo.
     6#
     7# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    68# This program and the accompanying materials
    79# are licensed and made available under the terms and conditions of the BSD License
     
    1618  INF_VERSION                    = 0x00010005
    1719  BASE_NAME                      = EsalVariableDxeSal
     20  MODULE_UNI_FILE                = EsalVariableDxeSal.uni
    1821  FILE_GUID                      = 14610837-4E97-4427-96E0-21D9B2956996
    1922  MODULE_TYPE                    = DXE_SAL_DRIVER
     
    6164
    6265[Protocols]
    63   gEfiFirmwareVolumeBlockProtocolGuid           # PROTOCOL SOMETIMES_CONSUMED
    64   gEfiFaultTolerantWriteProtocolGuid            # PROTOCOL SOMETIMES_CONSUMED
     66  gEfiFirmwareVolumeBlockProtocolGuid           ## SOMETIMES_CONSUMES
     67  gEfiFaultTolerantWriteProtocolGuid            ## SOMETIMES_CONSUMES
    6568
    6669[Guids]
     70  ## SOMETIMES_CONSUMES   ## Variable:L"PK"
     71  ## CONSUMES             ## Variable:L"SetupMode"
     72  ## PRODUCES             ## Variable:L"SetupMode"
     73  ## CONSUMES             ## Variable:L"SignatureSupport"
     74  ## PRODUCES             ## Variable:L"SignatureSupport"
    6775  gEfiGlobalVariableGuid
     76 
     77  ## PRODUCES             ## GUID # Variable store header
     78  ## CONSUMES             ## GUID # Variable store header
     79  ## SOMETIMES_CONSUMES   ## HOB
     80  ## SOMETIMES_PRODUCES   ## SystemTable
    6881  gEfiAuthenticatedVariableGuid
    69   gEfiEventVirtualAddressChangeGuid
    70   gEfiCertRsa2048Sha256Guid
     82 
     83  gEfiEventVirtualAddressChangeGuid             ## CONSUMES               ## Event
     84  gEfiCertRsa2048Sha256Guid                     ## CONSUMES               ## GUID        # Unique ID for the format of the CertType.
     85
     86  ## SOMETIMES_CONSUMES   ## Variable:L"DB"
     87  ## SOMETIMES_CONSUMES   ## Variable:L"DBX"
    7188  gEfiImageSecurityDatabaseGuid
    7289
    7390[Pcd.common]
    74   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
    75   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
    76   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
    77   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
    78   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
    79   gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
    80 
     91  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize            ## CONSUMES
     92  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase            ## SOMETIMES_CONSUMES
     93  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                       ## CONSUMES
     94  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize          ## CONSUMES
     95  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize                     ## CONSUMES
     96  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                      ## CONSUMES
     97 
    8198[FeaturePcd.common]
    82   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics
     99  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics             ## CONSUMES    # statistic the information of variable.
    83100
    84101[Depex]
    85   gEfiExtendedSalFvBlockServicesProtocolGuid AND gEfiFaultTolerantWriteProtocolGuid
    86  
     102  gEfiExtendedSalFvBlockServicesProtocolGuid AND gEfiFaultTolerantWriteProtocolGuid 
     103
     104[UserExtensions.TianoCore."ExtraFiles"]
     105  EsalVariableDxeSalExtra.uni
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/Variable.c

    r48674 r58459  
    22  The implementation of Extended SAL variable services.
    33
    4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    55This program and the accompanying materials
    66are licensed and made available under the terms and conditions of the BSD License
     
    25922592  }
    25932593
     2594 
     2595  if ((UINTN)(~0) - PayloadSize < StrSize(VariableName)){
     2596    //
     2597    // Prevent whole variable size overflow
     2598    //
     2599    return EFI_INVALID_PARAMETER;
     2600  }
     2601
    25942602  VariableGlobal = &Global->VariableGlobal[VirtualMode];
    25952603  Instance = Global->FvbInstance;
     
    26002608    // in bytes plus the DataSize is limited to maximum size of PcdGet32(PcdMaxHardwareErrorVariableSize) bytes.
    26012609    //
    2602     if ((PayloadSize > PcdGet32(PcdMaxHardwareErrorVariableSize)) ||                                                       
    2603         (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + PayloadSize > PcdGet32(PcdMaxHardwareErrorVariableSize))) {
     2610    if (StrSize (VariableName) + PayloadSize > PcdGet32(PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER)) {
    26042611      return EFI_INVALID_PARAMETER;
    26052612    }
     
    26172624    // Unicode Null in bytes plus the DataSize is limited to maximum size of PcdGet32(PcdMaxVariableSize) bytes.
    26182625    //
    2619     if ((PayloadSize > PcdGet32(PcdMaxVariableSize)) ||
    2620         (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + PayloadSize > PcdGet32(PcdMaxVariableSize))) {
     2626    if (StrSize (VariableName) + PayloadSize > PcdGet32(PcdMaxVariableSize) - sizeof (VARIABLE_HEADER)) {
    26212627      return EFI_INVALID_PARAMETER;
    26222628    } 
     
    32393245  } else {
    32403246    Status = EFI_VOLUME_CORRUPTED;
    3241     DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n"));
     3247    DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n"));
    32423248  }
    32433249
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/Pei/Variable.c

    r48674 r58459  
    44  storage space.
    55
    6 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
     6Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    77This program and the accompanying materials
    88are licensed and made available under the terms and conditions of the BSD License
     
    173173  )
    174174{
    175 
    176175  return (CHAR16 *) (Variable + 1);
    177176}
     
    181180  This code gets the pointer to the variable data.
    182181
    183   @param   Variable  Pointer to the Variable Header.
     182  @param   Variable         Pointer to the Variable Header.
     183  @param   VariableHeader   Pointer to the Variable Header that has consecutive content.
    184184
    185185  @return  A UINT8* pointer to Variable Data.
     
    188188UINT8 *
    189189GetVariableDataPtr (
    190   IN  VARIABLE_HEADER   *Variable
     190  IN  VARIABLE_HEADER   *Variable,
     191  IN  VARIABLE_HEADER   *VariableHeader
    191192  )
    192193{
     
    197198  //
    198199  Value =  (UINTN) GetVariableNamePtr (Variable);
    199   Value += NameSizeOfVariable (Variable);
    200   Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
     200  Value += NameSizeOfVariable (VariableHeader);
     201  Value += GET_PAD_SIZE (NameSizeOfVariable (VariableHeader));
    201202
    202203  return (UINT8 *) Value;
     
    207208  This code gets the pointer to the next variable header.
    208209
    209   @param  Variable  Pointer to the Variable Header.
     210  @param  StoreInfo         Pointer to variable store info structure.
     211  @param  Variable          Pointer to the Variable Header.
     212  @param  VariableHeader    Pointer to the Variable Header that has consecutive content.
    210213
    211214  @return  A VARIABLE_HEADER* pointer to next variable header.
     
    214217VARIABLE_HEADER *
    215218GetNextVariablePtr (
    216   IN  VARIABLE_HEADER   *Variable
    217   )
    218 {
    219   UINTN Value;
    220 
    221   if (!IsValidVariableHeader (Variable)) {
    222     return NULL;
    223   }
    224 
    225   Value =  (UINTN) GetVariableDataPtr (Variable);
    226   Value += DataSizeOfVariable (Variable);
    227   Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
    228 
     219  IN  VARIABLE_STORE_INFO   *StoreInfo,
     220  IN  VARIABLE_HEADER       *Variable,
     221  IN  VARIABLE_HEADER       *VariableHeader
     222  )
     223{
     224  EFI_PHYSICAL_ADDRESS  TargetAddress;
     225  EFI_PHYSICAL_ADDRESS  SpareAddress;
     226  UINTN                 Value;
     227
     228  Value =  (UINTN) GetVariableDataPtr (Variable, VariableHeader);
     229  Value += DataSizeOfVariable (VariableHeader);
     230  Value += GET_PAD_SIZE (DataSizeOfVariable (VariableHeader));
    229231  //
    230232  // Be careful about pad size for alignment
    231233  //
    232   return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
    233 }
    234 
    235 /**
    236   This code gets the pointer to the variable name.
     234  Value = HEADER_ALIGN (Value);
     235
     236  if (StoreInfo->FtwLastWriteData != NULL) {
     237    TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
     238    SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
     239    if (((UINTN) Variable < (UINTN) TargetAddress) && (Value >= (UINTN) TargetAddress)) {
     240      //
     241      // Next variable is in spare block.
     242      //
     243      Value = (UINTN) SpareAddress + (Value - (UINTN) TargetAddress);
     244    }
     245  }
     246
     247  return (VARIABLE_HEADER *) Value;
     248}
     249
     250/**
     251  Get variable store status.
    237252
    238253  @param  VarStoreHeader  Pointer to the Variable Store Header.
     
    248263  )
    249264{
    250        
    251265  if (CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) &&
    252266      VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
     
    272286}
    273287
     288/**
     289  Compare two variable names, one of them may be inconsecutive.
     290
     291  @param StoreInfo      Pointer to variable store info structure.
     292  @param Name1          Pointer to one variable name.
     293  @param Name2          Pointer to another variable name.
     294  @param NameSize       Variable name size.
     295
     296  @retval TRUE          Name1 and Name2 are identical.
     297  @retval FALSE         Name1 and Name2 are not identical.
     298
     299**/
     300BOOLEAN
     301CompareVariableName (
     302  IN VARIABLE_STORE_INFO    *StoreInfo,
     303  IN CONST CHAR16           *Name1,
     304  IN CONST CHAR16           *Name2,
     305  IN UINTN                  NameSize
     306  )
     307{
     308  EFI_PHYSICAL_ADDRESS  TargetAddress;
     309  EFI_PHYSICAL_ADDRESS  SpareAddress;
     310  UINTN                 PartialNameSize;
     311
     312  if (StoreInfo->FtwLastWriteData != NULL) {
     313    TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
     314    SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
     315    if (((UINTN) Name1 < (UINTN) TargetAddress) && (((UINTN) Name1 + NameSize) > (UINTN) TargetAddress)) {
     316      //
     317      // Name1 is inconsecutive.
     318      //
     319      PartialNameSize = (UINTN) TargetAddress - (UINTN) Name1;
     320      //
     321      // Partial content is in NV storage.
     322      //
     323      if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, PartialNameSize) == 0) {
     324        //
     325        // Another partial content is in spare block.
     326        //
     327        if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name2 + PartialNameSize, NameSize - PartialNameSize) == 0) {
     328          return TRUE;
     329        }
     330      }
     331      return FALSE;
     332    } else if (((UINTN) Name2 < (UINTN) TargetAddress) && (((UINTN) Name2 + NameSize) > (UINTN) TargetAddress)) {
     333      //
     334      // Name2 is inconsecutive.
     335      //
     336      PartialNameSize = (UINTN) TargetAddress - (UINTN) Name2;
     337      //
     338      // Partial content is in NV storage.
     339      //
     340      if (CompareMem ((UINT8 *) Name2, (UINT8 *) Name1, PartialNameSize) == 0) {
     341        //
     342        // Another partial content is in spare block.
     343        //
     344        if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name1 + PartialNameSize, NameSize - PartialNameSize) == 0) {
     345          return TRUE;
     346        }
     347      }
     348      return FALSE;
     349    }
     350  }
     351
     352  //
     353  // Both Name1 and Name2 are consecutive.
     354  //
     355  if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, NameSize) == 0) {
     356    return TRUE;
     357  }
     358  return FALSE;
     359}
    274360
    275361/**
    276362  This function compares a variable with variable entries in database.
    277363
     364  @param  StoreInfo     Pointer to variable store info structure.
    278365  @param  Variable      Pointer to the variable in our database
     366  @param  VariableHeader Pointer to the Variable Header that has consecutive content.
    279367  @param  VariableName  Name of the variable to compare to 'Variable'
    280368  @param  VendorGuid    GUID of the variable to compare to 'Variable'
     
    287375EFI_STATUS
    288376CompareWithValidVariable (
     377  IN  VARIABLE_STORE_INFO           *StoreInfo,
    289378  IN  VARIABLE_HEADER               *Variable,
     379  IN  VARIABLE_HEADER               *VariableHeader,
    290380  IN  CONST CHAR16                  *VariableName,
    291381  IN  CONST EFI_GUID                *VendorGuid,
     
    304394    // on the first failed comparison.
    305395    //
    306     if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&
    307         (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&
    308         (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&
    309         (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])
     396    if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &VariableHeader->VendorGuid)[0]) &&
     397        (((INT32 *) VendorGuid)[1] == ((INT32 *) &VariableHeader->VendorGuid)[1]) &&
     398        (((INT32 *) VendorGuid)[2] == ((INT32 *) &VariableHeader->VendorGuid)[2]) &&
     399        (((INT32 *) VendorGuid)[3] == ((INT32 *) &VariableHeader->VendorGuid)[3])
    310400        ) {
    311       ASSERT (NameSizeOfVariable (Variable) != 0);
     401      ASSERT (NameSizeOfVariable (VariableHeader) != 0);
    312402      Point = (VOID *) GetVariableNamePtr (Variable);
    313       if (CompareMem (VariableName, Point, NameSizeOfVariable (Variable)) == 0) {
     403      if (CompareVariableName (StoreInfo, VariableName, Point, NameSizeOfVariable (VariableHeader))) {
    314404        PtrTrack->CurrPtr = Variable;
    315405        return EFI_SUCCESS;
     
    322412
    323413/**
    324   Return the variable store header and the index table based on the Index.
    325 
    326   @param Type      The type of the variable store.
    327   @param IndexTable Return the index table.
     414  Return the variable store header and the store info based on the Index.
     415
     416  @param Type       The type of the variable store.
     417  @param StoreInfo  Return the store info.
    328418
    329419  @return  Pointer to the variable store header.
     
    332422GetVariableStore (
    333423  IN VARIABLE_STORE_TYPE         Type,
    334   OUT VARIABLE_INDEX_TABLE       **IndexTable  OPTIONAL
    335   )
    336 {
    337   EFI_HOB_GUID_TYPE           *GuidHob;
    338   EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
    339   VARIABLE_STORE_HEADER       *VariableStoreHeader;
    340 
    341   if (IndexTable != NULL) {
    342     *IndexTable       = NULL;
    343   }
     424  OUT VARIABLE_STORE_INFO        *StoreInfo
     425  )
     426{
     427  EFI_HOB_GUID_TYPE                     *GuidHob;
     428  EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;
     429  VARIABLE_STORE_HEADER                 *VariableStoreHeader;
     430  EFI_PHYSICAL_ADDRESS                  NvStorageBase;
     431  UINT32                                NvStorageSize;
     432  FAULT_TOLERANT_WRITE_LAST_WRITE_DATA  *FtwLastWriteData;
     433  UINT32                                BackUpOffset;
     434
     435  StoreInfo->IndexTable = NULL;
     436  StoreInfo->FtwLastWriteData = NULL;
    344437  VariableStoreHeader = NULL;
    345438  switch (Type) {
     
    356449        // The content of NV storage for variable is not reliable in recovery boot mode.
    357450        //
    358         FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ?
    359                                                            PcdGet64 (PcdFlashNvStorageVariableBase64) :
    360                                                            PcdGet32 (PcdFlashNvStorageVariableBase)
    361                                                           );
     451
     452        NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
     453        NvStorageBase = (EFI_PHYSICAL_ADDRESS) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ?
     454                                                PcdGet64 (PcdFlashNvStorageVariableBase64) :
     455                                                PcdGet32 (PcdFlashNvStorageVariableBase)
     456                                               );
     457        //
     458        // First let FvHeader point to NV storage base.
     459        //
     460        FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) NvStorageBase;
     461
     462        //
     463        // Check the FTW last write data hob.
     464        //
     465        BackUpOffset = 0;
     466        GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
     467        if (GuidHob != NULL) {
     468          FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);
     469          if (FtwLastWriteData->TargetAddress == NvStorageBase) {
     470            //
     471            // Let FvHeader point to spare block.
     472            //
     473            FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FtwLastWriteData->SpareAddress;
     474            DEBUG ((EFI_D_INFO, "PeiVariable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));
     475          } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) && (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {
     476            StoreInfo->FtwLastWriteData = FtwLastWriteData;
     477            //
     478            // Flash NV storage from the offset is backed up in spare block.
     479            //
     480            BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);
     481            DEBUG ((EFI_D_INFO, "PeiVariable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));
     482            //
     483            // At least one block data in flash NV storage is still valid, so still leave FvHeader point to NV storage base.
     484            //
     485          }
     486        }
    362487
    363488        //
     
    371496        VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);
    372497
    373         if (IndexTable != NULL) {
    374           GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
    375           if (GuidHob != NULL) {
    376             *IndexTable = GET_GUID_HOB_DATA (GuidHob);
    377           } else {
    378             //
    379             // If it's the first time to access variable region in flash, create a guid hob to record
    380             // VAR_ADDED type variable info.
    381             // Note that as the resource of PEI phase is limited, only store the limited number of
    382             // VAR_ADDED type variables to reduce access time.
    383             //
    384             *IndexTable = BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
    385             (*IndexTable)->Length      = 0;
    386             (*IndexTable)->StartPtr    = GetStartPointer (VariableStoreHeader);
    387             (*IndexTable)->EndPtr      = GetEndPointer   (VariableStoreHeader);
    388             (*IndexTable)->GoneThrough = 0;
    389           }
     498        GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
     499        if (GuidHob != NULL) {
     500          StoreInfo->IndexTable = GET_GUID_HOB_DATA (GuidHob);
     501        } else {
     502          //
     503          // If it's the first time to access variable region in flash, create a guid hob to record
     504          // VAR_ADDED type variable info.
     505          // Note that as the resource of PEI phase is limited, only store the limited number of
     506          // VAR_ADDED type variables to reduce access time.
     507          //
     508          StoreInfo->IndexTable = (VARIABLE_INDEX_TABLE *) BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
     509          StoreInfo->IndexTable->Length      = 0;
     510          StoreInfo->IndexTable->StartPtr    = GetStartPointer (VariableStoreHeader);
     511          StoreInfo->IndexTable->EndPtr      = GetEndPointer   (VariableStoreHeader);
     512          StoreInfo->IndexTable->GoneThrough = 0;
    390513        }
    391514      }
     
    397520  }
    398521
     522  StoreInfo->VariableStoreHeader = VariableStoreHeader;
    399523  return VariableStoreHeader;
    400524}
    401525
    402526/**
     527  Get variable header that has consecutive content.
     528
     529  @param StoreInfo      Pointer to variable store info structure.
     530  @param Variable       Pointer to the Variable Header.
     531  @param VariableHeader Pointer to Pointer to the Variable Header that has consecutive content.
     532
     533  @retval TRUE          Variable header is valid.
     534  @retval FALSE         Variable header is not valid.
     535
     536**/
     537BOOLEAN
     538GetVariableHeader (
     539  IN VARIABLE_STORE_INFO    *StoreInfo,
     540  IN VARIABLE_HEADER        *Variable,
     541  OUT VARIABLE_HEADER       **VariableHeader
     542  )
     543{
     544  EFI_PHYSICAL_ADDRESS  TargetAddress;
     545  EFI_PHYSICAL_ADDRESS  SpareAddress;
     546  EFI_HOB_GUID_TYPE     *GuidHob;
     547  UINTN                 PartialHeaderSize;
     548
     549  if (Variable == NULL) {
     550    return FALSE;
     551  }
     552
     553   //
     554   // First assume variable header pointed by Variable is consecutive.
     555   //
     556  *VariableHeader = Variable;
     557
     558  if (StoreInfo->FtwLastWriteData != NULL) {
     559    TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
     560    SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
     561    if (((UINTN) Variable > (UINTN) SpareAddress) &&
     562        (((UINTN) Variable - (UINTN) SpareAddress + (UINTN) TargetAddress) >= (UINTN) GetEndPointer (StoreInfo->VariableStoreHeader))) {
     563      //
     564      // Reach the end of variable store.
     565      //
     566      return FALSE;
     567    }
     568    if (((UINTN) Variable < (UINTN) TargetAddress) && (((UINTN) Variable + sizeof (VARIABLE_HEADER)) > (UINTN) TargetAddress)) {
     569      //
     570      // Variable header pointed by Variable is inconsecutive,
     571      // create a guid hob to combine the two partial variable header content together.
     572      //
     573      GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
     574      if (GuidHob != NULL) {
     575        *VariableHeader = (VARIABLE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
     576      } else {
     577        *VariableHeader = (VARIABLE_HEADER *) BuildGuidHob (&gEfiCallerIdGuid, sizeof (VARIABLE_HEADER));
     578        PartialHeaderSize = (UINTN) TargetAddress - (UINTN) Variable;
     579        //
     580        // Partial content is in NV storage.
     581        //
     582        CopyMem ((UINT8 *) *VariableHeader, (UINT8 *) Variable, PartialHeaderSize);
     583        //
     584        // Another partial content is in spare block.
     585        //
     586        CopyMem ((UINT8 *) *VariableHeader + PartialHeaderSize, (UINT8 *) (UINTN) SpareAddress, sizeof (VARIABLE_HEADER) - PartialHeaderSize);
     587      }
     588    }
     589  } else {
     590    if (Variable >= GetEndPointer (StoreInfo->VariableStoreHeader)) {
     591      //
     592      // Reach the end of variable store.
     593      //
     594      return FALSE;
     595    }
     596  }
     597
     598  return IsValidVariableHeader (*VariableHeader);
     599}
     600
     601/**
     602  Get variable name or data to output buffer.
     603
     604  @param  StoreInfo     Pointer to variable store info structure.
     605  @param  NameOrData    Pointer to the variable name/data that may be inconsecutive.
     606  @param  Size          Variable name/data size.
     607  @param  Buffer        Pointer to output buffer to hold the variable name/data.
     608
     609**/
     610VOID
     611GetVariableNameOrData (
     612  IN VARIABLE_STORE_INFO    *StoreInfo,
     613  IN UINT8                  *NameOrData,
     614  IN UINTN                  Size,
     615  OUT UINT8                 *Buffer
     616  )
     617{
     618  EFI_PHYSICAL_ADDRESS  TargetAddress;
     619  EFI_PHYSICAL_ADDRESS  SpareAddress;
     620  UINTN                 PartialSize;
     621 
     622  if (StoreInfo->FtwLastWriteData != NULL) {
     623    TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
     624    SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
     625    if (((UINTN) NameOrData < (UINTN) TargetAddress) && (((UINTN) NameOrData + Size) > (UINTN) TargetAddress)) {
     626      //
     627      // Variable name/data is inconsecutive.
     628      //
     629      PartialSize = (UINTN) TargetAddress - (UINTN) NameOrData;
     630      //
     631      // Partial content is in NV storage.
     632      //
     633      CopyMem (Buffer, NameOrData, PartialSize);
     634      //
     635      // Another partial content is in spare block.
     636      //
     637      CopyMem (Buffer + PartialSize, (UINT8 *) (UINTN) SpareAddress, Size - PartialSize);
     638      return;
     639    }
     640  }
     641
     642  //
     643  // Variable name/data is consecutive.
     644  //
     645  CopyMem (Buffer, NameOrData, Size);
     646}
     647
     648/**
    403649  Find the variable in the specified variable store.
    404650
    405   @param  VariableStoreHeader Pointer to the variable store header.
    406   @param  IndexTable          Pointer to the index table.
     651  @param  StoreInfo           Pointer to the store info structure.
    407652  @param  VariableName        Name of the variable to be found
    408653  @param  VendorGuid          Vendor GUID to be found.
     
    416661EFI_STATUS
    417662FindVariableEx (
    418   IN VARIABLE_STORE_HEADER       *VariableStoreHeader,
    419   IN VARIABLE_INDEX_TABLE        *IndexTable,
     663  IN VARIABLE_STORE_INFO         *StoreInfo,
    420664  IN CONST CHAR16                *VariableName,
    421665  IN CONST EFI_GUID              *VendorGuid,
     
    429673  UINTN                   Offset;
    430674  BOOLEAN                 StopRecord;
     675  VARIABLE_HEADER         *InDeletedVariable;
     676  VARIABLE_STORE_HEADER   *VariableStoreHeader;
     677  VARIABLE_INDEX_TABLE    *IndexTable;
     678  VARIABLE_HEADER         *VariableHeader;
     679
     680  VariableStoreHeader = StoreInfo->VariableStoreHeader;
    431681
    432682  if (VariableStoreHeader == NULL) {
     
    442692  }
    443693
     694  IndexTable = StoreInfo->IndexTable;
    444695  PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);
    445696  PtrTrack->EndPtr   = GetEndPointer   (VariableStoreHeader);
    446697
     698  InDeletedVariable = NULL;
     699
    447700  //
    448701  // No Variable Address equals zero, so 0 as initial value is safe.
    449702  //
    450703  MaxIndex   = NULL;
     704  VariableHeader = NULL;
    451705
    452706  if (IndexTable != NULL) {
     
    459713      Offset   += IndexTable->Index[Index];
    460714      MaxIndex  = (VARIABLE_HEADER *) ((UINT8 *) IndexTable->StartPtr + Offset);
    461       if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
    462         return EFI_SUCCESS;
     715      GetVariableHeader (StoreInfo, MaxIndex, &VariableHeader);
     716      if (CompareWithValidVariable (StoreInfo, MaxIndex, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
     717        if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     718          InDeletedVariable = PtrTrack->CurrPtr;
     719        } else {
     720          return EFI_SUCCESS;
     721        }
    463722      }
    464723    }
     
    466725    if (IndexTable->GoneThrough != 0) {
    467726      //
    468       // If the table has all the existing variables indexed and we still cannot find it.
    469       //
    470       return EFI_NOT_FOUND;
     727      // If the table has all the existing variables indexed, return.
     728      //
     729      PtrTrack->CurrPtr = InDeletedVariable;
     730      return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
    471731    }
    472732  }
     
    477737    // If not found in HOB, then let's start from the MaxIndex we've found.
    478738    //
    479     Variable     = GetNextVariablePtr (MaxIndex);
     739    Variable     = GetNextVariablePtr (StoreInfo, MaxIndex, VariableHeader);
    480740    LastVariable = MaxIndex;
    481741  } else {
     
    489749
    490750  //
    491   // Find the variable by walk through non-volatile variable store
     751  // Find the variable by walk through variable store
    492752  //
    493753  StopRecord = FALSE;
    494   while ((Variable < PtrTrack->EndPtr) && IsValidVariableHeader (Variable)) {
    495     if (Variable->State == VAR_ADDED) {
     754  while (GetVariableHeader (StoreInfo, Variable, &VariableHeader)) {
     755    if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
    496756      //
    497757      // Record Variable in VariableIndex HOB
     
    511771      }
    512772
    513       if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
    514         return EFI_SUCCESS;
    515       }
    516     }
    517 
    518     Variable = GetNextVariablePtr (Variable);
     773      if (CompareWithValidVariable (StoreInfo, Variable, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
     774        if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     775          InDeletedVariable = PtrTrack->CurrPtr;
     776        } else {
     777          return EFI_SUCCESS;
     778        }
     779      }
     780    }
     781
     782    Variable = GetNextVariablePtr (StoreInfo, Variable, VariableHeader);
    519783  }
    520784  //
     
    525789  }
    526790
    527   PtrTrack->CurrPtr = NULL;
    528 
    529   return EFI_NOT_FOUND;
     791  PtrTrack->CurrPtr = InDeletedVariable;
     792
     793  return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
    530794}
    531795
     
    536800  @param  VendorGuid    Vendor GUID to be found.
    537801  @param  PtrTrack      Variable Track Pointer structure that contains Variable Information.
     802  @param  StoreInfo     Return the store info.
    538803
    539804  @retval  EFI_SUCCESS            Variable found successfully
     
    545810  IN CONST  CHAR16            *VariableName,
    546811  IN CONST  EFI_GUID          *VendorGuid,
    547   OUT VARIABLE_POINTER_TRACK  *PtrTrack
     812  OUT VARIABLE_POINTER_TRACK  *PtrTrack,
     813  OUT VARIABLE_STORE_INFO     *StoreInfo
    548814  )
    549815{
    550816  EFI_STATUS                  Status;
    551   VARIABLE_STORE_HEADER       *VariableStoreHeader;
    552   VARIABLE_INDEX_TABLE        *IndexTable;
    553817  VARIABLE_STORE_TYPE         Type;
    554818
     
    558822
    559823  for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
    560     VariableStoreHeader = GetVariableStore (Type, &IndexTable);
     824    GetVariableStore (Type, StoreInfo);
    561825    Status = FindVariableEx (
    562                VariableStoreHeader,
    563                IndexTable,
     826               StoreInfo,
    564827               VariableName,
    565828               VendorGuid,
     
    614877  UINTN                   VarDataSize;
    615878  EFI_STATUS              Status;
     879  VARIABLE_STORE_INFO     StoreInfo;
     880  VARIABLE_HEADER         *VariableHeader;
    616881
    617882  if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {
     
    619884  }
    620885
     886  VariableHeader = NULL;
     887
    621888  //
    622889  // Find existing variable
    623890  //
    624   Status = FindVariable (VariableName, VariableGuid, &Variable);
     891  Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
    625892  if (EFI_ERROR (Status)) {
    626893    return Status;
    627894  }
     895  GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);
     896
    628897  //
    629898  // Get data size
    630899  //
    631   VarDataSize = DataSizeOfVariable (Variable.CurrPtr);
     900  VarDataSize = DataSizeOfVariable (VariableHeader);
    632901  if (*DataSize >= VarDataSize) {
    633902    if (Data == NULL) {
     
    635904    }
    636905
    637     CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);
     906    GetVariableNameOrData (&StoreInfo, GetVariableDataPtr (Variable.CurrPtr, VariableHeader), VarDataSize, Data);
    638907
    639908    if (Attributes != NULL) {
    640       *Attributes = Variable.CurrPtr->Attributes;
     909      *Attributes = VariableHeader->Attributes;
    641910    }
    642911
     
    690959  VARIABLE_POINTER_TRACK  Variable;
    691960  VARIABLE_POINTER_TRACK  VariableInHob;
     961  VARIABLE_POINTER_TRACK  VariablePtrTrack;
    692962  UINTN                   VarNameSize;
    693963  EFI_STATUS              Status;
    694964  VARIABLE_STORE_HEADER   *VariableStoreHeader[VariableStoreTypeMax];
     965  VARIABLE_HEADER         *VariableHeader;
     966  VARIABLE_STORE_INFO     StoreInfo;
     967  VARIABLE_STORE_INFO     StoreInfoForNv;
     968  VARIABLE_STORE_INFO     StoreInfoForHob;
    695969
    696970  if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {
     
    698972  }
    699973
    700   Status = FindVariable (VariableName, VariableGuid, &Variable);
     974  VariableHeader = NULL;
     975
     976  Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
    701977  if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
    702978    return Status;
     
    707983    // If variable name is not NULL, get next variable
    708984    //
    709     Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
    710   }
    711 
    712   VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, NULL);
    713   VariableStoreHeader[VariableStoreTypeNv]  = GetVariableStore (VariableStoreTypeNv, NULL);
     985    GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);
     986    Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
     987  }
     988
     989  VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, &StoreInfoForHob);
     990  VariableStoreHeader[VariableStoreTypeNv]  = GetVariableStore (VariableStoreTypeNv, &StoreInfoForNv);
    714991
    715992  while (TRUE) {
     
    717994    // Switch from HOB to Non-Volatile.
    718995    //
    719     while ((Variable.CurrPtr >= Variable.EndPtr) ||
    720            (Variable.CurrPtr == NULL)            ||
    721            !IsValidVariableHeader (Variable.CurrPtr)
    722           ) {
     996    while (!GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader)) {
    723997      //
    724998      // Find current storage index
     
    7491023      Variable.EndPtr   = GetEndPointer   (VariableStoreHeader[Type]);
    7501024      Variable.CurrPtr  = Variable.StartPtr;
    751     }
    752 
    753     if (Variable.CurrPtr->State == VAR_ADDED) {
     1025      GetVariableStore (Type, &StoreInfo);
     1026    }
     1027
     1028    if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     1029      if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     1030        //
     1031        // If it is a IN_DELETED_TRANSITION variable,
     1032        // and there is also a same ADDED one at the same time,
     1033        // don't return it.
     1034        //
     1035        Status = FindVariableEx (
     1036                   &StoreInfo,
     1037                   GetVariableNamePtr (Variable.CurrPtr),
     1038                   &VariableHeader->VendorGuid,
     1039                   &VariablePtrTrack
     1040                   );
     1041        if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr != Variable.CurrPtr) {
     1042          Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
     1043          continue;
     1044        }
     1045      }
    7541046
    7551047      //
     
    7601052         ) {
    7611053        Status = FindVariableEx (
    762                    VariableStoreHeader[VariableStoreTypeHob],
    763                    NULL,
     1054                   &StoreInfoForHob,
    7641055                   GetVariableNamePtr (Variable.CurrPtr),
    765                    &Variable.CurrPtr->VendorGuid,
     1056                   &VariableHeader->VendorGuid,
    7661057                   &VariableInHob
    7671058                   );
    7681059        if (!EFI_ERROR (Status)) {
    769           Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
     1060          Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
    7701061          continue;
    7711062        }
    7721063      }
    7731064
    774       VarNameSize = NameSizeOfVariable (Variable.CurrPtr);
     1065      VarNameSize = NameSizeOfVariable (VariableHeader);
    7751066      ASSERT (VarNameSize != 0);
    7761067
    7771068      if (VarNameSize <= *VariableNameSize) {
    778         CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);
    779 
    780         CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
     1069        GetVariableNameOrData (&StoreInfo, (UINT8 *) GetVariableNamePtr (Variable.CurrPtr), VarNameSize, (UINT8 *) VariableName);
     1070
     1071        CopyMem (VariableGuid, &VariableHeader->VendorGuid, sizeof (EFI_GUID));
    7811072
    7821073        Status = EFI_SUCCESS;
     
    7911082      return Status;
    7921083    } else {
    793       Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
    794     }
    795   }
    796 }
     1084      Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
     1085    }
     1086  }
     1087}
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/Pei/Variable.h

    r48674 r58459  
    33  internal structure and functions used by PeiVariable module.
    44
    5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
     5Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
    66This program and the accompanying materials
    77are licensed and made available under the terms and conditions of the BSD License
     
    3131#include <Guid/VariableIndexTable.h>
    3232#include <Guid/SystemNvDataGuid.h>
     33#include <Guid/FaultTolerantWrite.h>
    3334
    3435typedef enum {
     
    3738  VariableStoreTypeMax
    3839} VARIABLE_STORE_TYPE;
     40
     41typedef struct {
     42  VARIABLE_STORE_HEADER                   *VariableStoreHeader;
     43  VARIABLE_INDEX_TABLE                    *IndexTable;
     44  //
     45  // If it is not NULL, it means there may be an inconsecutive variable whose
     46  // partial content is still in NV storage, but another partial content is backed up
     47  // in spare block.
     48  //
     49  FAULT_TOLERANT_WRITE_LAST_WRITE_DATA    *FtwLastWriteData;
     50} VARIABLE_STORE_INFO;
    3951
    4052//
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf

    r48674 r58459  
    11## @file
    2 #  The component description for PEI variable driver.
     2#  Implements ReadOnly Variable Services required by PEIM and installs PEI ReadOnly Varaiable2 PPI
     3#  This module implements ReadOnly Variable Services required by PEIM and installs PEI ReadOnly Varaiable2 PPI.
    34#
    4 # Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
     5# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    56# This program and the accompanying materials
    67# are licensed and made available under the terms and conditions of the BSD License
     
    1415[Defines]
    1516  INF_VERSION                    = 0x00010005
    16   BASE_NAME                      = PeiVariable
     17  BASE_NAME                      = PeiVariableAuth
     18  MODULE_UNI_FILE                = PeiVariableAuth.uni
    1719  FILE_GUID                      = B1F7AF2F-2807-478c-A893-2BF4DDD1F62B
    1820  MODULE_TYPE                    = PEIM
     
    4547
    4648[Guids]
     49  ## CONSUMES             ## GUID # Variable store header
     50  ## SOMETIMES_CONSUMES   ## HOB
    4751  gEfiAuthenticatedVariableGuid
     52  ## SOMETIMES_PRODUCES   ## HOB
     53  ## SOMETIMES_CONSUMES   ## HOB
    4854  gEfiVariableIndexTableGuid
    49   gEfiSystemNvDataFvGuid
     55  gEfiSystemNvDataFvGuid            ## SOMETIMES_CONSUMES   ## GUID
     56  gEdkiiFaultTolerantWriteGuid      ## SOMETIMES_CONSUMES   ## HOB
    5057
    5158[Ppis]
    52   gEfiPeiReadOnlyVariable2PpiGuid                ## SOMETIMES_PRODUCES (Not for boot mode RECOVERY)
     59  gEfiPeiReadOnlyVariable2PpiGuid   ## PRODUCES
    5360
    5461[Pcd]
    55   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase  ## CONSUMES
    56   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64  ## CONSUMES
     62  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase      ## SOMETIMES_CONSUMES
     63  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64    ## CONSUMES
     64  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize      ## CONSUMES
    5765
    5866[Depex]
    59   TRUE
     67  gEdkiiFaultTolerantWriteGuid
    6068
    61 #
    62 #  [BootMode]
    63 #    RECOVERY          ## CONSUMES
    64 #
     69# [BootMode]
     70# RECOVERY_FULL             ## SOMETIMES_CONSUMES
    6571
     72[UserExtensions.TianoCore."ExtraFiles"]
     73  PeiVariableExtra.uni
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c

    r48674 r58459  
    33  service in UEFI2.2.
    44
    5 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
     5  Caution: This module requires additional review when modified.
     6  This driver will have external input - variable data. It may be input in SMM mode.
     7  This external input must be validated carefully to avoid security issue like
     8  buffer overflow, integer overflow.
     9  Variable attribute should also be checked to avoid authentication bypass.
     10     The whole SMM authentication variable design relies on the integrity of flash part and SMM.
     11  which is assumed to be protected by platform.  All variable code and metadata in flash/SMM Memory
     12  may not be modified without authorization. If platform fails to protect these resources,
     13  the authentication service provided in this driver will be broken, and the behavior is undefined.
     14
     15  ProcessVarWithPk(), ProcessVarWithKek() and ProcessVariable() are the function to do
     16  variable authentication.
     17
     18  VerifyTimeBasedPayload() and VerifyCounterBasedPayload() are sub function to do verification.
     19  They will do basic validation for authentication data structure, then call crypto library
     20  to verify the signature.
     21
     22Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    623This program and the accompanying materials
    724are licensed and made available under the terms and conditions of the BSD License
     
    2037/// Global database array for scratch
    2138///
    22 UINT8    mPubKeyStore[MAX_KEYDB_SIZE];
     39UINT8    *mPubKeyStore;
    2340UINT32   mPubKeyNumber;
     41UINT32   mMaxKeyNumber;
     42UINT32   mMaxKeyDbSize;
     43UINT8    *mCertDbStore;
     44UINT32   mMaxCertDbSize;
    2445UINT32   mPlatformMode;
     46UINT8    mVendorKeyState;
     47
    2548EFI_GUID mSignatureSupport[] = {EFI_CERT_SHA1_GUID, EFI_CERT_SHA256_GUID, EFI_CERT_RSA2048_GUID, EFI_CERT_X509_GUID};
    2649//
     
    3255//
    3356VOID  *mHashCtx = NULL;
    34 
    35 //
    36 // Pointer to runtime buffer.
    37 // For "Append" operation to an existing variable, a read/modify/write operation
    38 // is supported by firmware internally. Reserve runtime buffer to cache previous
    39 // variable data in runtime phase because memory allocation is forbidden in virtual mode.
    40 //
    41 VOID  *mStorageArea = NULL;
    4257
    4358//
     
    177192
    178193  //
    179   // Reserved runtime buffer for "Append" operation in virtual mode.
    180   //
    181   mStorageArea  = AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize));
    182   if (mStorageArea == NULL) {
     194  // Reserve runtime buffer for public key database. The size excludes variable header and name size.
     195  //
     196  mMaxKeyDbSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - sizeof (AUTHVAR_KEYDB_NAME);
     197  mMaxKeyNumber = mMaxKeyDbSize / EFI_CERT_TYPE_RSA2048_SIZE;
     198  mPubKeyStore  = AllocateRuntimePool (mMaxKeyDbSize);
     199  if (mPubKeyStore == NULL) {
     200    return EFI_OUT_OF_RESOURCES;
     201  }
     202
     203  //
     204  // Reserve runtime buffer for certificate database. The size excludes variable header and name size.
     205  //
     206  mMaxCertDbSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - sizeof (EFI_CERT_DB_NAME);
     207  mCertDbStore   = AllocateRuntimePool (mMaxCertDbSize);
     208  if (mCertDbStore == NULL) {
    183209    return EFI_OUT_OF_RESOURCES;
    184210  }
     
    230256    Data      = GetVariableDataPtr (Variable.CurrPtr);
    231257    ASSERT ((DataSize != 0) && (Data != NULL));
     258    //
     259    // "AuthVarKeyDatabase" is an internal variable. Its DataSize is always ensured not to exceed mPubKeyStore buffer size(See definition before)
     260    //  Therefore, there is no memory overflow in underlying CopyMem.
     261    //
    232262    CopyMem (mPubKeyStore, (UINT8 *) Data, DataSize);
    233263    mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);
     
    242272 
    243273  //
    244   // Check "SetupMode" variable's existence.
    245   // If it doesn't exist, check PK database's existence to determine the value.
    246   // Then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
    247   //
    248   Status = FindVariable (
     274  // Create "SetupMode" variable with BS+RT attribute set.
     275  //
     276  FindVariable (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     277  if (PkVariable.CurrPtr == NULL) {
     278    mPlatformMode = SETUP_MODE;
     279  } else {
     280    mPlatformMode = USER_MODE;
     281  }
     282  Status = UpdateVariable (
    249283             EFI_SETUP_MODE_NAME,
    250284             &gEfiGlobalVariableGuid,
     285             &mPlatformMode,
     286             sizeof(UINT8),
     287             EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
     288             0,
     289             0,
    251290             &Variable,
    252              &mVariableModuleGlobal->VariableGlobal,
    253              FALSE
     291             NULL
    254292             );
    255 
    256   if (Variable.CurrPtr == NULL) {
    257     if (PkVariable.CurrPtr == NULL) {
    258       mPlatformMode = SETUP_MODE;
    259     } else {
    260       mPlatformMode = USER_MODE;
    261     }
    262 
    263     VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
    264     Status  = UpdateVariable (
    265                 EFI_SETUP_MODE_NAME,
    266                 &gEfiGlobalVariableGuid,
    267                 &mPlatformMode,
    268                 sizeof(UINT8),
    269                 VarAttr,
    270                 0,
    271                 0,
    272                 &Variable,
    273                 NULL
    274                 );
    275     if (EFI_ERROR (Status)) {
    276       return Status;
    277     }
    278   } else {
    279     mPlatformMode = *(GetVariableDataPtr (Variable.CurrPtr));
    280   }
    281   //
    282   // Check "SignatureSupport" variable's existence.
    283   // If it doesn't exist, then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
    284   //
    285   Status = FindVariable (
    286              EFI_SIGNATURE_SUPPORT_NAME,
    287              &gEfiGlobalVariableGuid,
    288              &Variable,
    289              &mVariableModuleGlobal->VariableGlobal,
    290              FALSE
    291              );
    292 
    293   if (Variable.CurrPtr == NULL) {
    294     VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
    295     Status  = UpdateVariable (
    296                 EFI_SIGNATURE_SUPPORT_NAME,
    297                 &gEfiGlobalVariableGuid,
    298                 mSignatureSupport,
    299                 sizeof(mSignatureSupport),
    300                 VarAttr,
    301                 0,
    302                 0,
    303                 &Variable,
    304                 NULL
    305                 );
     293  if (EFI_ERROR (Status)) {
     294    return Status;
     295  }
     296 
     297  //
     298  // Create "SignatureSupport" variable with BS+RT attribute set.
     299  //
     300  FindVariable (EFI_SIGNATURE_SUPPORT_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     301  Status  = UpdateVariable (
     302              EFI_SIGNATURE_SUPPORT_NAME,
     303              &gEfiGlobalVariableGuid,
     304              mSignatureSupport,
     305              sizeof(mSignatureSupport),
     306              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
     307              0,
     308              0,
     309              &Variable,
     310              NULL
     311              );
     312  if (EFI_ERROR (Status)) {
     313    return Status;
    306314  }
    307315
     
    311319  // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.
    312320  //
    313   SecureBootEnable = SECURE_BOOT_MODE_DISABLE;
     321  SecureBootEnable = SECURE_BOOT_DISABLE;
    314322  FindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
    315323  if (Variable.CurrPtr != NULL) {
     
    319327    // "SecureBootEnable" not exist, initialize it in USER_MODE.
    320328    //
    321     SecureBootEnable = SECURE_BOOT_MODE_ENABLE;
     329    SecureBootEnable = SECURE_BOOT_ENABLE;
    322330    Status = UpdateVariable (
    323331               EFI_SECURE_BOOT_ENABLE_NAME,
     
    336344  }
    337345
     346  //
     347  // Create "SecureBoot" variable with BS+RT attribute set.
     348  //
    338349  if (SecureBootEnable == SECURE_BOOT_ENABLE && mPlatformMode == USER_MODE) {
    339350    SecureBootMode = SECURE_BOOT_MODE_ENABLE;
     
    347358             &SecureBootMode,
    348359             sizeof (UINT8),
    349              EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
     360             EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    350361             0,
    351362             0,
     
    362373
    363374  //
    364   // Check "CustomMode" variable's existence.
     375  // Initialize "CustomMode" in STANDARD_SECURE_BOOT_MODE state.
    365376  //
    366377  FindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
    367   if (Variable.CurrPtr != NULL) {
    368     CustomMode = *(GetVariableDataPtr (Variable.CurrPtr));
    369   } else {
    370     //
    371     // "CustomMode" not exist, initialize it in STANDARD_SECURE_BOOT_MODE.
    372     //
    373     CustomMode = STANDARD_SECURE_BOOT_MODE;
    374     Status = UpdateVariable (
    375                EFI_CUSTOM_MODE_NAME,
    376                &gEfiCustomModeEnableGuid,
    377                &CustomMode,
    378                sizeof (UINT8),
    379                EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    380                0,
    381                0,
    382                &Variable,
    383                NULL
    384                );
    385     if (EFI_ERROR (Status)) {
    386       return Status;
    387     }
     378  CustomMode = STANDARD_SECURE_BOOT_MODE;
     379  Status = UpdateVariable (
     380             EFI_CUSTOM_MODE_NAME,
     381             &gEfiCustomModeEnableGuid,
     382             &CustomMode,
     383             sizeof (UINT8),
     384             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
     385             0,
     386             0,
     387             &Variable,
     388             NULL
     389             );
     390  if (EFI_ERROR (Status)) {
     391    return Status;
    388392  }
    389393 
     
    405409  if (Variable.CurrPtr == NULL) {
    406410    VarAttr  = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
    407     ListSize = 0;
     411    ListSize = sizeof (UINT32);
    408412    Status   = UpdateVariable (
    409413                 EFI_CERT_DB_NAME,
     
    417421                 NULL
    418422                 );
    419 
     423    if (EFI_ERROR (Status)) {
     424      return Status;
     425    }
    420426  } 
     427
     428  //
     429  // Check "VendorKeysNv" variable's existence and create "VendorKeys" variable accordingly.
     430  //
     431  FindVariable (EFI_VENDOR_KEYS_NV_VARIABLE_NAME, &gEfiVendorKeysNvGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     432  if (Variable.CurrPtr != NULL) {
     433    mVendorKeyState = *(GetVariableDataPtr (Variable.CurrPtr));
     434  } else {
     435    //
     436    // "VendorKeysNv" not exist, initialize it in VENDOR_KEYS_VALID state.
     437    //
     438    mVendorKeyState = VENDOR_KEYS_VALID;
     439    Status = UpdateVariable (
     440               EFI_VENDOR_KEYS_NV_VARIABLE_NAME,
     441               &gEfiVendorKeysNvGuid,
     442               &mVendorKeyState,
     443               sizeof (UINT8),
     444               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
     445               0,
     446               0,
     447               &Variable,
     448               NULL
     449               );
     450    if (EFI_ERROR (Status)) {
     451      return Status;
     452    }
     453  }
     454
     455  //
     456  // Create "VendorKeys" variable with BS+RT attribute set.
     457  //
     458  FindVariable (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     459  Status = UpdateVariable (
     460             EFI_VENDOR_KEYS_VARIABLE_NAME,
     461             &gEfiGlobalVariableGuid,
     462             &mVendorKeyState,
     463             sizeof (UINT8),
     464             EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
     465             0,
     466             0,
     467             &Variable,
     468             NULL
     469             );
     470  if (EFI_ERROR (Status)) {
     471    return Status;
     472  }
     473
     474  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_VENDOR_KEYS_VARIABLE_NAME, mVendorKeyState));
    421475
    422476  return Status;
     
    427481
    428482  @param[in]  PubKey                  Input pointer to Public Key data
     483  @param[in]  VariableDataEntry       The variable data entry
    429484
    430485  @return                             Index of new added item
     
    433488UINT32
    434489AddPubKeyInStore (
    435   IN  UINT8               *PubKey
     490  IN  UINT8                        *PubKey,
     491  IN  VARIABLE_ENTRY_CONSISTENCY   *VariableDataEntry
    436492  )
    437493{
    438   EFI_STATUS              Status;
    439   BOOLEAN                 IsFound;
    440   UINT32                  Index;
    441   VARIABLE_POINTER_TRACK  Variable;
    442   UINT8                   *Ptr;
     494  EFI_STATUS                       Status;
     495  BOOLEAN                          IsFound;
     496  UINT32                           Index;
     497  VARIABLE_POINTER_TRACK           Variable;
     498  UINT8                            *Ptr;
     499  UINT8                            *Data;
     500  UINTN                            DataSize;
     501  VARIABLE_ENTRY_CONSISTENCY       PublicKeyEntry;
     502  UINT32                           Attributes;
    443503
    444504  if (PubKey == NULL) {
     
    453513             FALSE
    454514             );
    455   ASSERT_EFI_ERROR (Status);
     515  if (EFI_ERROR (Status)) {
     516    DEBUG ((EFI_D_ERROR, "Get public key database variable failure, Status = %r\n", Status));
     517    return 0;
     518  }
     519
    456520  //
    457521  // Check whether the public key entry does exist.
     
    470534    // Add public key in database.
    471535    //
    472     if (mPubKeyNumber == MAX_KEY_NUM) {
     536    if (mPubKeyNumber == mMaxKeyNumber) {
    473537      //
    474       // Notes: Database is full, need enhancement here, currently just return 0.
     538      // Public key dadatase is full, try to reclaim invalid key.
     539      //
     540      if (AtRuntime ()) {
     541        //
     542        // NV storage can't reclaim at runtime.
     543        //
     544        return 0;
     545      }
     546     
     547      Status = Reclaim (
     548                 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
     549                 &mVariableModuleGlobal->NonVolatileLastVariableOffset,
     550                 FALSE,
     551                 NULL,
     552                 NULL,
     553                 0,
     554                 TRUE
     555                 );
     556      if (EFI_ERROR (Status)) {
     557        return 0;
     558      }
     559
     560      Status = FindVariable (
     561                 AUTHVAR_KEYDB_NAME,
     562                 &gEfiAuthenticatedVariableGuid,
     563                 &Variable,
     564                 &mVariableModuleGlobal->VariableGlobal,
     565                 FALSE
     566                 );
     567      if (EFI_ERROR (Status)) {
     568        DEBUG ((EFI_D_ERROR, "Get public key database variable failure, Status = %r\n", Status));
     569        return 0;
     570      }
     571
     572      DataSize  = DataSizeOfVariable (Variable.CurrPtr);
     573      Data      = GetVariableDataPtr (Variable.CurrPtr);
     574      ASSERT ((DataSize != 0) && (Data != NULL));
     575      //
     576      // "AuthVarKeyDatabase" is an internal used variable. Its DataSize is always ensured not to exceed mPubKeyStore buffer size(See definition before)
     577      //  Therefore, there is no memory overflow in underlying CopyMem.
     578      //
     579      CopyMem (mPubKeyStore, (UINT8 *) Data, DataSize);
     580      mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);
     581
     582      if (mPubKeyNumber == mMaxKeyNumber) {
     583        return 0;
     584      }     
     585    }
     586
     587    //
     588    // Check the variable space for both public key and variable data.
     589    //
     590    PublicKeyEntry.VariableSize = (mPubKeyNumber + 1) * EFI_CERT_TYPE_RSA2048_SIZE;
     591    PublicKeyEntry.Guid         = &gEfiAuthenticatedVariableGuid;
     592    PublicKeyEntry.Name         = AUTHVAR_KEYDB_NAME;
     593    Attributes = VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
     594
     595    if (!CheckRemainingSpaceForConsistency (Attributes, &PublicKeyEntry, VariableDataEntry, NULL)) {
     596      //
     597      // No enough variable space.
    475598      //
    476599      return 0;
     
    487610               mPubKeyStore,
    488611               mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE,
    489                EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
     612               Attributes,
    490613               0,
    491614               0,
     
    493616               NULL
    494617               );
    495     ASSERT_EFI_ERROR (Status);
     618    if (EFI_ERROR (Status)) {
     619      DEBUG ((EFI_D_ERROR, "Update public key database variable failure, Status = %r\n", Status));
     620      return 0;
     621    }
    496622  }
    497623
     
    502628  Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256_GUID type.
    503629  Follow the steps in UEFI2.2.
     630
     631  Caution: This function may receive untrusted input.
     632  This function may be invoked in SMM mode, and datasize and data are external input.
     633  This function will do basic validation, before parse the data.
     634  This function will parse the authentication carefully to avoid security issues, like
     635  buffer overflow, integer overflow.
    504636
    505637  @param[in]      Data                    Pointer to data with AuthInfo.
     
    524656  UINT8                           Digest[SHA256_DIGEST_SIZE];
    525657  VOID                            *Rsa;
    526 
     658  UINTN                           PayloadSize;
     659 
     660  PayloadSize = DataSize - AUTHINFO_SIZE;
    527661  Rsa         = NULL;
    528662  CertData    = NULL;
     
    556690    goto Done;
    557691  }
    558   Status  = Sha256Update (mHashCtx, Data + AUTHINFO_SIZE, (UINTN) (DataSize - AUTHINFO_SIZE));
     692  Status  = Sha256Update (mHashCtx, Data + AUTHINFO_SIZE, PayloadSize);
     693  if (!Status) {
     694    goto Done;
     695  }
     696  //
     697  // Hash Size.
     698  //
     699  Status  = Sha256Update (mHashCtx, &PayloadSize, sizeof (UINTN));
    559700  if (!Status) {
    560701    goto Done;
     
    626767  EFI_STATUS              Status;
    627768  VARIABLE_POINTER_TRACK  Variable;
    628   UINT32                  VarAttr;
    629769  UINT8                   SecureBootMode;
    630770  UINT8                   SecureBootEnable;
     
    642782  }
    643783
    644   mPlatformMode  = Mode;
    645   VarAttr        = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
    646   Status         = UpdateVariable (
    647                      EFI_SETUP_MODE_NAME,
    648                      &gEfiGlobalVariableGuid,
    649                      &mPlatformMode,
    650                      sizeof(UINT8),
    651                      VarAttr,
    652                      0,
    653                      0,
    654                      &Variable,
    655                      NULL
    656                      );
    657   if (EFI_ERROR (Status)) {
    658     return Status;
    659   }
     784  //
     785  // Update the value of SetupMode variable by a simple mem copy, this could avoid possible
     786  // variable storage reclaim at runtime.
     787  //
     788  mPlatformMode = (UINT8) Mode;
     789  CopyMem (GetVariableDataPtr (Variable.CurrPtr), &mPlatformMode, sizeof(UINT8));
    660790
    661791  if (AtRuntime ()) {
     
    697827  }
    698828
    699   VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
    700829  Status  = UpdateVariable (
    701830              EFI_SECURE_BOOT_MODE_NAME,
     
    703832              &SecureBootMode,
    704833              sizeof(UINT8),
    705               VarAttr,
     834              EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    706835              0,
    707836              0,
     
    757886
    758887/**
    759   Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK variable.
     888  Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK/db/dbx variable.
    760889
    761890  @param[in]  VariableName                Name of Variable to be check.
     
    781910  UINT32                 SigCount;
    782911  BOOLEAN                IsPk;
     912  VOID                   *RsaContext;
     913  EFI_SIGNATURE_DATA     *CertData;
     914  UINTN                  CertLen;
    783915
    784916  if (DataSize == 0) {
     
    790922  if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0)){
    791923    IsPk = TRUE;
    792   } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) {
     924  } else if ((CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0) ||
     925             (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
     926              (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0 || StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))){
    793927    IsPk = FALSE;
    794928  } else {
     
    799933  SigList  = (EFI_SIGNATURE_LIST *) Data;
    800934  SigDataSize  = DataSize;
     935  RsaContext = NULL;
    801936
    802937  //
     
    830965    }
    831966
     967    if (CompareGuid (&SigList->SignatureType, &gEfiCertX509Guid)) {
     968      //
     969      // Try to retrieve the RSA public key from the X.509 certificate.
     970      // If this operation fails, it's not a valid certificate.
     971      //
     972      RsaContext = RsaNew ();
     973      if (RsaContext == NULL) {
     974        return EFI_INVALID_PARAMETER;
     975      }
     976      CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) + SigList->SignatureHeaderSize);
     977      CertLen = SigList->SignatureSize - sizeof (EFI_GUID);
     978      if (!RsaGetPublicKeyFromX509 (CertData->SignatureData, CertLen, &RsaContext)) {
     979        RsaFree (RsaContext);
     980        return EFI_INVALID_PARAMETER;
     981      }
     982      RsaFree (RsaContext);
     983    }
     984
    832985    if ((SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) % SigList->SignatureSize != 0) {
    833986      return EFI_INVALID_PARAMETER;
     
    8511004
    8521005/**
     1006  Update "VendorKeys" variable to record the out of band secure boot key modification.
     1007
     1008  @return EFI_SUCCESS           Variable is updated successfully.
     1009  @return Others                Failed to update variable.
     1010 
     1011**/
     1012EFI_STATUS
     1013VendorKeyIsModified (
     1014  VOID
     1015  )
     1016{
     1017  EFI_STATUS              Status;
     1018  VARIABLE_POINTER_TRACK  Variable;
     1019
     1020  if (mVendorKeyState == VENDOR_KEYS_MODIFIED) {
     1021    return EFI_SUCCESS;
     1022  }
     1023  mVendorKeyState = VENDOR_KEYS_MODIFIED;
     1024 
     1025  FindVariable (EFI_VENDOR_KEYS_NV_VARIABLE_NAME, &gEfiVendorKeysNvGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     1026  Status = UpdateVariable (
     1027             EFI_VENDOR_KEYS_NV_VARIABLE_NAME,
     1028             &gEfiVendorKeysNvGuid,
     1029             &mVendorKeyState,
     1030             sizeof (UINT8),
     1031             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
     1032             0,
     1033             0,
     1034             &Variable,
     1035             NULL
     1036             );
     1037  if (EFI_ERROR (Status)) {
     1038    return Status;
     1039  }
     1040
     1041  FindVariable (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     1042  return UpdateVariable (
     1043           EFI_VENDOR_KEYS_VARIABLE_NAME,
     1044           &gEfiGlobalVariableGuid,
     1045           &mVendorKeyState,
     1046           sizeof (UINT8),
     1047           EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
     1048           0,
     1049           0,
     1050           &Variable,
     1051           NULL
     1052           );
     1053}
     1054
     1055/**
    8531056  Process variable with platform key for verification.
     1057
     1058  Caution: This function may receive untrusted input.
     1059  This function may be invoked in SMM mode, and datasize and data are external input.
     1060  This function will do basic validation, before parse the data.
     1061  This function will parse the authentication carefully to avoid security issues, like
     1062  buffer overflow, integer overflow.
     1063  This function will check attribute carefully to avoid authentication bypass.
    8541064
    8551065  @param[in]  VariableName                Name of Variable to be found.
     
    8871097      (Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {
    8881098    //
    889     // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute and should be a time-based
     1099    // PK, KEK and db/dbx should set EFI_VARIABLE_NON_VOLATILE attribute and should be a time-based
    8901100    // authenticated variable.
    8911101    //
     
    8931103  }
    8941104
    895   if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) {
    896     //
    897     // Verify against X509 Cert PK.
    898     //
    899     Del    = FALSE;
    900     Status = VerifyTimeBasedPayload (
    901                VariableName,
    902                VendorGuid,
    903                Data,
    904                DataSize,
    905                Variable,
    906                Attributes,
    907                AuthVarTypePk,
    908                &Del
    909                );
    910     if (!EFI_ERROR (Status)) {
    911       //
    912       // If delete PK in user mode, need change to setup mode.
    913       //
    914       if (Del && IsPk) {
    915         Status = UpdatePlatformMode (SETUP_MODE);
    916       }
    917     }
    918     return Status;
    919   } else {
    920     //
    921     // Process PK or KEK in Setup mode or Custom Secure Boot mode.
    922     //
     1105  Del = FALSE;
     1106  if ((InCustomMode() && UserPhysicalPresent()) || (mPlatformMode == SETUP_MODE && !IsPk)) {
    9231107    Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);
    9241108    PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
     1109    if (PayloadSize == 0) {
     1110      Del = TRUE;
     1111    }
    9251112
    9261113    Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize);
     
    9401127               &((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp
    9411128               );
    942 
    943     if (IsPk) {
    944       if (PayloadSize != 0) {
    945         //
    946         // If enroll PK in setup mode, need change to user mode.
    947         //
    948         Status = UpdatePlatformMode (USER_MODE);
    949       } else {
    950         //
    951         // If delete PK in custom mode, need change to setup mode.
    952         //
    953         UpdatePlatformMode (SETUP_MODE);
    954       }
    955     }   
     1129    if (EFI_ERROR(Status)) {
     1130      return Status;
     1131    }
     1132
     1133    if ((mPlatformMode != SETUP_MODE) || IsPk) {
     1134      Status = VendorKeyIsModified ();
     1135    }
     1136  } else if (mPlatformMode == USER_MODE) {
     1137    //
     1138    // Verify against X509 Cert in PK database.
     1139    //
     1140    Status = VerifyTimeBasedPayload (
     1141               VariableName,
     1142               VendorGuid,
     1143               Data,
     1144               DataSize,
     1145               Variable,
     1146               Attributes,
     1147               AuthVarTypePk,
     1148               &Del
     1149               );
     1150  } else {
     1151    //
     1152    // Verify against the certificate in data payload.
     1153    //
     1154    Status = VerifyTimeBasedPayload (
     1155               VariableName,
     1156               VendorGuid,
     1157               Data,
     1158               DataSize,
     1159               Variable,
     1160               Attributes,
     1161               AuthVarTypePayload,
     1162               &Del
     1163               );
     1164  }
     1165
     1166  if (!EFI_ERROR(Status) && IsPk) {
     1167    if (mPlatformMode == SETUP_MODE && !Del) {
     1168      //
     1169      // If enroll PK in setup mode, need change to user mode.
     1170      //
     1171      Status = UpdatePlatformMode (USER_MODE);
     1172    } else if (mPlatformMode == USER_MODE && Del){
     1173      //
     1174      // If delete PK in user mode, need change to setup mode.
     1175      //
     1176      Status = UpdatePlatformMode (SETUP_MODE);
     1177    }
    9561178  }
    9571179
     
    9611183/**
    9621184  Process variable with key exchange key for verification.
     1185
     1186  Caution: This function may receive untrusted input.
     1187  This function may be invoked in SMM mode, and datasize and data are external input.
     1188  This function will do basic validation, before parse the data.
     1189  This function will parse the authentication carefully to avoid security issues, like
     1190  buffer overflow, integer overflow.
     1191  This function will check attribute carefully to avoid authentication bypass.
    9631192
    9641193  @param[in]  VariableName                Name of Variable to be found.
     
    10211250    PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
    10221251
     1252    Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize);
     1253    if (EFI_ERROR (Status)) {
     1254      return Status;
     1255    }
     1256   
    10231257    Status = UpdateVariable (
    10241258               VariableName,
     
    10321266               &((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp
    10331267               );
     1268    if (EFI_ERROR (Status)) {
     1269      return Status;
     1270    }
     1271
     1272    if (mPlatformMode != SETUP_MODE) {
     1273      Status = VendorKeyIsModified ();
     1274    }
    10341275  }
    10351276
     
    10391280/**
    10401281  Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
     1282
     1283  Caution: This function may receive untrusted input.
     1284  This function may be invoked in SMM mode, and datasize and data are external input.
     1285  This function will do basic validation, before parse the data.
     1286  This function will parse the authentication carefully to avoid security issues, like
     1287  buffer overflow, integer overflow.
     1288  This function will check attribute carefully to avoid authentication bypass.
    10411289
    10421290  @param[in]  VariableName                Name of Variable to be found.
     
    10521300  @return EFI_WRITE_PROTECTED             Variable is write-protected and needs authentication with
    10531301                                          EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
     1302  @return EFI_OUT_OF_RESOURCES            The Database to save the public key is full.
    10541303  @return EFI_SECURITY_VIOLATION          The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
    10551304                                          set, but the AuthInfo does NOT pass the validation
     
    10761325  UINT32                          KeyIndex;
    10771326  UINT64                          MonotonicCount;
     1327  VARIABLE_ENTRY_CONSISTENCY      VariableDataEntry;
    10781328
    10791329  KeyIndex    = 0;
     
    10901340  }
    10911341 
     1342  //
     1343  // A time-based authenticated variable and a count-based authenticated variable
     1344  // can't be updated by each other.
     1345  //
     1346  if (Variable->CurrPtr != NULL) {   
     1347    if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) &&
     1348        ((Variable->CurrPtr->Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0)) {
     1349      return EFI_SECURITY_VIOLATION;     
     1350    }
     1351   
     1352    if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) &&
     1353        ((Variable->CurrPtr->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0)) {
     1354      return EFI_SECURITY_VIOLATION;     
     1355    }
     1356  }
     1357   
    10921358  //
    10931359  // Process Time-based Authenticated variable.
     
    11571423  if (!IsFirstTime) {
    11581424    //
    1159     // Check input PubKey.
    1160     //
    1161     if (CompareMem (PubKey, mPubKeyStore + (KeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE, EFI_CERT_TYPE_RSA2048_SIZE) != 0) {
     1425    // 2 cases need to check here
     1426    //   1. Internal PubKey variable. PubKeyIndex is always 0
     1427    //   2. Other counter-based AuthVariable. Check input PubKey.
     1428    //
     1429    if (KeyIndex == 0 || CompareMem (PubKey, mPubKeyStore + (KeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE, EFI_CERT_TYPE_RSA2048_SIZE) != 0) {
    11621430      return EFI_SECURITY_VIOLATION;
    11631431    }
     
    11851453  //
    11861454  if (IsFirstTime && !IsDeletion) {
     1455    VariableDataEntry.VariableSize = DataSize - AUTHINFO_SIZE;
     1456    VariableDataEntry.Guid         = VendorGuid;
     1457    VariableDataEntry.Name         = VariableName;
     1458
    11871459    //
    11881460    // Update public key database variable if need.
    11891461    //
    1190     KeyIndex = AddPubKeyInStore (PubKey);
     1462    KeyIndex = AddPubKeyInStore (PubKey, &VariableDataEntry);
    11911463    if (KeyIndex == 0) {
    1192       return EFI_SECURITY_VIOLATION;
     1464      return EFI_OUT_OF_RESOURCES;
    11931465    }
    11941466  }
     
    12051477  will be ignored.
    12061478
    1207   @param[in, out]  Data            Pointer to original EFI_SIGNATURE_LIST.
    1208   @param[in]       DataSize        Size of Data buffer.
    1209   @param[in]       NewData         Pointer to new EFI_SIGNATURE_LIST to be appended.
    1210   @param[in]       NewDataSize     Size of NewData buffer.
    1211 
    1212   @return Size of the merged buffer.
     1479  @param[in, out]  Data              Pointer to original EFI_SIGNATURE_LIST.
     1480  @param[in]       DataSize          Size of Data buffer.
     1481  @param[in]       FreeBufSize       Size of free data buffer
     1482  @param[in]       NewData           Pointer to new EFI_SIGNATURE_LIST to be appended.
     1483  @param[in]       NewDataSize       Size of NewData buffer.
     1484  @param[out]      MergedBufSize     Size of the merged buffer
     1485
     1486  @return EFI_BUFFER_TOO_SMALL if input Data buffer overflowed
    12131487
    12141488**/
    1215 UINTN
     1489EFI_STATUS
    12161490AppendSignatureList (
    12171491  IN  OUT VOID            *Data,
    12181492  IN  UINTN               DataSize,
     1493  IN  UINTN               FreeBufSize,
    12191494  IN  VOID                *NewData,
    1220   IN  UINTN               NewDataSize
     1495  IN  UINTN               NewDataSize,
     1496  OUT UINTN               *MergedBufSize
    12211497  )
    12221498{
     
    12771553        //
    12781554        if (CopiedCount == 0) {
     1555          if (FreeBufSize < sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize) {
     1556            return EFI_BUFFER_TOO_SMALL;
     1557          }
     1558
    12791559          //
    12801560          // Copy EFI_SIGNATURE_LIST header for only once.
    12811561          //
     1562
    12821563          CopyMem (Tail, NewCertList, sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize);
    12831564          Tail = Tail + sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize;
     1565          FreeBufSize -= sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize;
    12841566        }
    12851567
     1568        if (FreeBufSize < NewCertList->SignatureSize) {
     1569          return EFI_BUFFER_TOO_SMALL;
     1570        }
    12861571        CopyMem (Tail, NewCert, NewCertList->SignatureSize);
    12871572        Tail += NewCertList->SignatureSize;
     1573        FreeBufSize -= NewCertList->SignatureSize;
    12881574        CopiedCount++;
    12891575      }
     
    13051591  }
    13061592
    1307   return (Tail - (UINT8 *) Data);
     1593  *MergedBufSize = (Tail - (UINT8 *) Data);
     1594  return EFI_SUCCESS;
    13081595}
    13091596
     
    13341621    return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);
    13351622  } else if (FirstTime->Minute != SecondTime->Minute) {
    1336     return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);
     1623    return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute);
    13371624  }
    13381625
     
    16201907  //
    16211908  NewCertDbSize = (UINT32) DataSize - CertNodeSize;
    1622   NewCertDb     = AllocateZeroPool (NewCertDbSize);
    1623   if (NewCertDb == NULL) {
    1624     return EFI_OUT_OF_RESOURCES;
    1625   }
     1909  NewCertDb     = (UINT8*) mCertDbStore;
    16261910
    16271911  //
     
    16601944               );
    16611945
    1662   FreePool (NewCertDb);
    16631946  return Status;
    16641947}
     
    17492032  NameSize      = (UINT32) StrLen (VariableName);
    17502033  CertNodeSize  = sizeof (AUTH_CERT_DB_DATA) + (UINT32) CertDataSize + NameSize * sizeof (CHAR16);
    1751   NewCertDbSize = (UINT32) DataSize + CertNodeSize;                 
    1752   NewCertDb     = AllocateZeroPool (NewCertDbSize);
    1753   if (NewCertDb == NULL) {
     2034  NewCertDbSize = (UINT32) DataSize + CertNodeSize;
     2035  if (NewCertDbSize > mMaxCertDbSize) {
    17542036    return EFI_OUT_OF_RESOURCES;
    17552037  }
     2038  NewCertDb     = (UINT8*) mCertDbStore;
    17562039
    17572040  //
     
    18002083               );
    18012084
    1802   FreePool (NewCertDb);
    18032085  return Status;
    18042086}
     
    18062088/**
    18072089  Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
     2090
     2091  Caution: This function may receive untrusted input.
     2092  This function may be invoked in SMM mode, and datasize and data are external input.
     2093  This function will do basic validation, before parse the data.
     2094  This function will parse the authentication carefully to avoid security issues, like
     2095  buffer overflow, integer overflow.
    18082096
    18092097  @param[in]  VariableName                Name of Variable to be found.
     
    18142102  @param[in]  Variable                    The variable information which is used to keep track of variable usage.
    18152103  @param[in]  Attributes                  Attribute value of the variable.
    1816   @param[in]  AuthVarType                 Verify against PK or KEK database or private database.
     2104  @param[in]  AuthVarType                 Verify against PK, KEK database, private database or certificate in data payload.
    18172105  @param[out] VarDel                      Delete the variable or not.
    18182106
     
    18712159  SignerCerts            = NULL;
    18722160  RootCert               = NULL;
     2161  CertsInCertDb          = NULL;
    18732162
    18742163  //
     
    19562245  if (AuthVarType == AuthVarTypePk) {
    19572246    //
    1958     // Get platform key from variable.
     2247    // Verify that the signature has been made with the current Platform Key (no chaining for PK).
     2248    // First, get signer's certificates from SignedData.
     2249    //
     2250    VerifyStatus = Pkcs7GetSigners (
     2251                     SigData,
     2252                     SigDataSize,
     2253                     &SignerCerts,
     2254                     &CertStackSize,
     2255                     &RootCert,
     2256                     &RootCertSize
     2257                     );
     2258    if (!VerifyStatus) {
     2259      goto Exit;
     2260    }
     2261
     2262    //
     2263    // Second, get the current platform key from variable. Check whether it's identical with signer's certificates
     2264    // in SignedData. If not, return error immediately.
    19592265    //
    19602266    Status = FindVariable (
     
    19662272               );
    19672273    if (EFI_ERROR (Status)) {
    1968       return Status;
    1969     }
    1970 
     2274      VerifyStatus = FALSE;
     2275      goto Exit;
     2276    }
    19712277    CertList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (PkVariable.CurrPtr);
    19722278    Cert     = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
    1973     RootCert      = Cert->SignatureData;
    1974     RootCertSize  = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);
    1975 
     2279    if ((RootCertSize != (CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1))) ||
     2280        (CompareMem (Cert->SignatureData, RootCert, RootCertSize) != 0)) {
     2281      VerifyStatus = FALSE;
     2282      goto Exit;
     2283    }
    19762284
    19772285    //
     
    20912399    // Delete signer's certificates when delete the common authenticated variable.
    20922400    //
    2093     if ((PayloadSize == 0) && (Variable->CurrPtr != NULL)) {
     2401    if ((PayloadSize == 0) && (Variable->CurrPtr != NULL) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) {
    20942402      Status = DeleteCertsFromDb (VariableName, VendorGuid);
    20952403      if (EFI_ERROR (Status)) {
     
    20972405        goto Exit;
    20982406      }
    2099     } else if (Variable->CurrPtr == NULL) {
     2407    } else if (Variable->CurrPtr == NULL && PayloadSize != 0) {
    21002408      //
    21012409      // Insert signer's certificates when adding a new common authenticated variable.
     
    21072415      }
    21082416    }
     2417  } else if (AuthVarType == AuthVarTypePayload) {
     2418    CertList = (EFI_SIGNATURE_LIST *) PayloadPtr;
     2419    Cert     = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
     2420    RootCert      = Cert->SignatureData;
     2421    RootCertSize  = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);
     2422   
     2423    // Verify Pkcs7 SignedData via Pkcs7Verify library.
     2424    //
     2425    VerifyStatus = Pkcs7Verify (
     2426                     SigData,
     2427                     SigDataSize,
     2428                     RootCert,
     2429                     RootCertSize,
     2430                     NewData,
     2431                     NewDataSize
     2432                     );
    21092433  } else {
    21102434    return EFI_SECURITY_VIOLATION;
     
    21132437Exit:
    21142438
    2115   if (AuthVarType == AuthVarTypePriv) {
     2439  if (AuthVarType == AuthVarTypePk || AuthVarType == AuthVarTypePriv) {
    21162440    Pkcs7FreeSigners (RootCert);
    21172441    Pkcs7FreeSigners (SignerCerts);
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h

    r48674 r58459  
    33  internal structure and functions used by AuthService module.
    44
    5 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
     5  Caution: This module requires additional review when modified.
     6  This driver will have external input - variable data. It may be input in SMM mode.
     7  This external input must be validated carefully to avoid security issue like
     8  buffer overflow, integer overflow.
     9  Variable attribute should also be checked to avoid authentication bypass.
     10     The whole SMM authentication variable design relies on the integrity of flash part and SMM.
     11  which is assumed to be protected by platform.  All variable code and metadata in flash/SMM Memory
     12  may not be modified without authorization. If platform fails to protect these resources,
     13  the authentication service provided in this driver will be broken, and the behavior is undefined.
     14
     15Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    616This program and the accompanying materials
    717are licensed and made available under the terms and conditions of the BSD License
     
    3747///
    3848#define AUTHVAR_KEYDB_NAME      L"AuthVarKeyDatabase"
    39 #define AUTHVAR_KEYDB_NAME_SIZE 38
    40 
    41 ///
    42 /// Max size of public key database, restricted by max individal EFI varible size, exclude variable header and name size.
    43 ///
    44 #define MAX_KEYDB_SIZE  (FixedPcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - AUTHVAR_KEYDB_NAME_SIZE)
    45 #define MAX_KEY_NUM     (MAX_KEYDB_SIZE / EFI_CERT_TYPE_RSA2048_SIZE)
     49
     50///
     51/// "certdb" variable stores the signer's certificates for non PK/KEK/DB/DBX
     52/// variables with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.
     53/// 
     54///
     55#define EFI_CERT_DB_NAME        L"certdb"
    4656
    4757///
     
    6070  AuthVarTypePk,
    6171  AuthVarTypeKek,
    62   AuthVarTypePriv
     72  AuthVarTypePriv,
     73  AuthVarTypePayload
    6374} AUTHVAR_TYPE;
    6475
     
    7788  Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.
    7889
     90  Caution: This function may receive untrusted input.
     91  This function may be invoked in SMM mode, and datasize and data are external input.
     92  This function will do basic validation, before parse the data.
     93  This function will parse the authentication carefully to avoid security issues, like
     94  buffer overflow, integer overflow.
     95  This function will check attribute carefully to avoid authentication bypass.
     96
    7997  @param[in]  VariableName                Name of Variable to be found.
    8098  @param[in]  VendorGuid                  Variable vendor GUID.
     
    162180/**
    163181  Process variable with platform key for verification.
     182
     183  Caution: This function may receive untrusted input.
     184  This function may be invoked in SMM mode, and datasize and data are external input.
     185  This function will do basic validation, before parse the data.
     186  This function will parse the authentication carefully to avoid security issues, like
     187  buffer overflow, integer overflow.
     188  This function will check attribute carefully to avoid authentication bypass.
    164189
    165190  @param[in]  VariableName                Name of Variable to be found.
     
    192217  Process variable with key exchange key for verification.
    193218
     219  Caution: This function may receive untrusted input.
     220  This function may be invoked in SMM mode, and datasize and data are external input.
     221  This function will do basic validation, before parse the data.
     222  This function will parse the authentication carefully to avoid security issues, like
     223  buffer overflow, integer overflow.
     224  This function will check attribute carefully to avoid authentication bypass.
     225
    194226  @param[in]  VariableName                Name of Variable to be found.
    195227  @param[in]  VendorGuid                  Variable vendor GUID.
     
    221253  will be ignored.
    222254
    223   @param[in, out]  Data            Pointer to original EFI_SIGNATURE_LIST.
    224   @param[in]       DataSize        Size of Data buffer.
    225   @param[in]       NewData         Pointer to new EFI_SIGNATURE_LIST to be appended.
    226   @param[in]       NewDataSize     Size of NewData buffer.
    227 
    228   @return Size of the merged buffer.
    229 
    230 **/
    231 UINTN
     255  @param[in, out]  Data             Pointer to original EFI_SIGNATURE_LIST.
     256  @param[in]       DataSize         Size of Data buffer.
     257  @param[in]       FreeBufSize      Size of free data buffer
     258  @param[in]       NewData          Pointer to new EFI_SIGNATURE_LIST to be appended.
     259  @param[in]       NewDataSize      Size of NewData buffer.
     260  @param[out]      MergedBufSize    Size of the merged buffer
     261
     262  @return EFI_BUFFER_TOO_SMALL if input Data buffer overflowed
     263
     264**/
     265EFI_STATUS
    232266AppendSignatureList (
    233267  IN  OUT VOID            *Data,
    234268  IN  UINTN               DataSize,
     269  IN  UINTN               FreeBufSize,
    235270  IN  VOID                *NewData,
    236   IN  UINTN               NewDataSize
     271  IN  UINTN               NewDataSize,
     272  OUT UINTN               *MergedBufSize
    237273  );
    238274
     
    257293/**
    258294  Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
     295
     296  Caution: This function may receive untrusted input.
     297  This function may be invoked in SMM mode, and datasize and data are external input.
     298  This function will do basic validation, before parse the data.
     299  This function will parse the authentication carefully to avoid security issues, like
     300  buffer overflow, integer overflow.
    259301
    260302  @param[in]  VariableName                Name of Variable to be found.
     
    288330  );
    289331
    290 extern UINT8  mPubKeyStore[MAX_KEYDB_SIZE];
     332extern UINT8  *mPubKeyStore;
     333extern UINT8  *mCertDbStore;
    291334extern UINT32 mPubKeyNumber;
    292335extern VOID   *mHashCtx;
    293 extern VOID   *mStorageArea;
    294336extern UINT8  *mSerializationRuntimeBuffer;
    295337
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/Reclaim.c

    r48674 r58459  
    33  (Fault Tolerant Write) protocol.
    44
    5 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
     5Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    66This program and the accompanying materials
    77are licensed and made available under the terms and conditions of the BSD License
     
    4949  *Lba    = (EFI_LBA) (-1);
    5050  *Offset = 0;
    51  
     51  Fvb = NULL;
     52
    5253  //
    5354  // Get the proper FVB protocol.
     
    99100
    100101  @param  VariableBase   Base address of variable to write
    101   @param  Buffer         Point to the data buffer.
    102   @param  BufferSize     The number of bytes of the data Buffer.
     102  @param  VariableBuffer Point to the variable data buffer.
    103103
    104104  @retval EFI_SUCCESS    The function completed successfully.
     
    110110FtwVariableSpace (
    111111  IN EFI_PHYSICAL_ADDRESS   VariableBase,
    112   IN UINT8                  *Buffer,
    113   IN UINTN                  BufferSize
     112  IN VARIABLE_STORE_HEADER  *VariableBuffer
    114113  )
    115114{
     
    118117  EFI_LBA                            VarLba;
    119118  UINTN                              VarOffset;
    120   UINT8                              *FtwBuffer;
    121119  UINTN                              FtwBufferSize;
    122120  EFI_FAULT_TOLERANT_WRITE_PROTOCOL  *FtwProtocol;
     
    143141    return EFI_ABORTED;
    144142  }
    145   //
    146   // Prepare for the variable data.
    147   //
     143
    148144  FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
    149   FtwBuffer     = AllocatePool (FtwBufferSize);
    150   if (FtwBuffer == NULL) {
    151     return EFI_OUT_OF_RESOURCES;
    152   }
    153 
    154   SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff);
    155   CopyMem (FtwBuffer, Buffer, BufferSize);
     145  ASSERT (FtwBufferSize == VariableBuffer->Size);
    156146
    157147  //
     
    165155                          NULL,           // PrivateData NULL
    166156                          FvbHandle,      // Fvb Handle
    167                           FtwBuffer      // write buffer
     157                          (VOID *) VariableBuffer // write buffer
    168158                          );
    169159
    170   FreePool (FtwBuffer);
    171160  return Status;
    172161}
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c

    r48674 r58459  
    11/** @file
    2   The common variable operation routines shared by DXE_RINTIME variable
     2  The common variable operation routines shared by DXE_RUNTIME variable
    33  module and DXE_SMM variable module.
    44
    5 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
     5  Caution: This module requires additional review when modified.
     6  This driver will have external input - variable data. They may be input in SMM mode.
     7  This external input must be validated carefully to avoid security issue like
     8  buffer overflow, integer overflow.
     9
     10  VariableServiceGetNextVariableName () and VariableServiceQueryVariableInfo() are external API.
     11  They need check input parameter.
     12
     13  VariableServiceGetVariable() and VariableServiceSetVariable() are external API
     14  to receive datasize and data buffer. The size should be checked carefully.
     15
     16  VariableServiceSetVariable() should also check authenticate data to avoid buffer overflow,
     17  integer overflow. It should also check attribute to avoid authentication bypass.
     18
     19Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    620This program and the accompanying materials
    721are licensed and made available under the terms and conditions of the BSD License
     
    2236/// Define a memory cache that improves the search performance for a variable.
    2337///
    24 VARIABLE_STORE_HEADER  *mNvVariableCache = NULL;
     38VARIABLE_STORE_HEADER  *mNvVariableCache      = NULL;
    2539
    2640///
    2741/// The memory entry used for variable statistics data.
    2842///
    29 VARIABLE_INFO_ENTRY    *gVariableInfo    = NULL;
    30 
     43VARIABLE_INFO_ENTRY    *gVariableInfo         = NULL;
     44
     45///
     46/// The list to store the variables which cannot be set after the EFI_END_OF_DXE_EVENT_GROUP_GUID
     47/// or EVT_GROUP_READY_TO_BOOT event.
     48///
     49LIST_ENTRY             mLockedVariableList    = INITIALIZE_LIST_HEAD_VARIABLE (mLockedVariableList);
     50
     51///
     52/// The flag to indicate whether the platform has left the DXE phase of execution.
     53///
     54BOOLEAN                mEndOfDxe              = FALSE;
     55
     56///
     57/// The flag to indicate whether the variable storage locking is enabled.
     58///
     59BOOLEAN                mEnableLocking         = TRUE;
     60
     61//
     62// To prevent name collisions with possible future globally defined variables,
     63// other internal firmware data variables that are not defined here must be
     64// saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or
     65// any other GUID defined by the UEFI Specification. Implementations must
     66// only permit the creation of variables with a UEFI Specification-defined
     67// VendorGuid when these variables are documented in the UEFI Specification.
     68//
     69GLOBAL_VARIABLE_ENTRY mGlobalVariableList[] = {
     70  {EFI_LANG_CODES_VARIABLE_NAME,             VARIABLE_ATTRIBUTE_BS_RT},
     71  {EFI_LANG_VARIABLE_NAME,                   VARIABLE_ATTRIBUTE_NV_BS_RT},
     72  {EFI_TIME_OUT_VARIABLE_NAME,               VARIABLE_ATTRIBUTE_NV_BS_RT},
     73  {EFI_PLATFORM_LANG_CODES_VARIABLE_NAME,    VARIABLE_ATTRIBUTE_BS_RT},
     74  {EFI_PLATFORM_LANG_VARIABLE_NAME,          VARIABLE_ATTRIBUTE_NV_BS_RT},
     75  {EFI_CON_IN_VARIABLE_NAME,                 VARIABLE_ATTRIBUTE_NV_BS_RT},
     76  {EFI_CON_OUT_VARIABLE_NAME,                VARIABLE_ATTRIBUTE_NV_BS_RT},
     77  {EFI_ERR_OUT_VARIABLE_NAME,                VARIABLE_ATTRIBUTE_NV_BS_RT},
     78  {EFI_CON_IN_DEV_VARIABLE_NAME,             VARIABLE_ATTRIBUTE_BS_RT},
     79  {EFI_CON_OUT_DEV_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     80  {EFI_ERR_OUT_DEV_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     81  {EFI_BOOT_ORDER_VARIABLE_NAME,             VARIABLE_ATTRIBUTE_NV_BS_RT},
     82  {EFI_BOOT_NEXT_VARIABLE_NAME,              VARIABLE_ATTRIBUTE_NV_BS_RT},
     83  {EFI_BOOT_CURRENT_VARIABLE_NAME,           VARIABLE_ATTRIBUTE_BS_RT},
     84  {EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME,    VARIABLE_ATTRIBUTE_BS_RT},
     85  {EFI_DRIVER_ORDER_VARIABLE_NAME,           VARIABLE_ATTRIBUTE_NV_BS_RT},
     86  {EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME,     VARIABLE_ATTRIBUTE_NV_BS_RT},
     87  {EFI_SETUP_MODE_NAME,                      VARIABLE_ATTRIBUTE_BS_RT},
     88  {EFI_KEY_EXCHANGE_KEY_NAME,                VARIABLE_ATTRIBUTE_NV_BS_RT_AT},
     89  {EFI_PLATFORM_KEY_NAME,                    VARIABLE_ATTRIBUTE_NV_BS_RT_AT},
     90  {EFI_SIGNATURE_SUPPORT_NAME,               VARIABLE_ATTRIBUTE_BS_RT},
     91  {EFI_SECURE_BOOT_MODE_NAME,                VARIABLE_ATTRIBUTE_BS_RT},
     92  {EFI_KEK_DEFAULT_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     93  {EFI_PK_DEFAULT_VARIABLE_NAME,             VARIABLE_ATTRIBUTE_BS_RT},
     94  {EFI_DB_DEFAULT_VARIABLE_NAME,             VARIABLE_ATTRIBUTE_BS_RT},
     95  {EFI_DBX_DEFAULT_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     96  {EFI_DBT_DEFAULT_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     97  {EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
     98  {EFI_OS_INDICATIONS_VARIABLE_NAME,         VARIABLE_ATTRIBUTE_NV_BS_RT},
     99  {EFI_VENDOR_KEYS_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     100};
     101GLOBAL_VARIABLE_ENTRY mGlobalVariableList2[] = {
     102  {L"Boot####",                              VARIABLE_ATTRIBUTE_NV_BS_RT},
     103  {L"Driver####",                            VARIABLE_ATTRIBUTE_NV_BS_RT},
     104  {L"Key####",                               VARIABLE_ATTRIBUTE_NV_BS_RT},
     105};
     106
     107/**
     108
     109  SecureBoot Hook for auth variable update.
     110
     111  @param[in] VariableName                 Name of Variable to be found.
     112  @param[in] VendorGuid                   Variable vendor GUID.
     113**/
     114VOID
     115EFIAPI
     116SecureBootHook (
     117  IN CHAR16                                 *VariableName,
     118  IN EFI_GUID                               *VendorGuid
     119  );
    31120
    32121/**
     
    130219  This code checks if variable header is valid or not.
    131220
    132   @param Variable        Pointer to the Variable Header.
    133 
    134   @retval TRUE           Variable header is valid.
    135   @retval FALSE          Variable header is not valid.
     221  @param Variable           Pointer to the Variable Header.
     222  @param VariableStoreEnd   Pointer to the Variable Store End.
     223
     224  @retval TRUE              Variable header is valid.
     225  @retval FALSE             Variable header is not valid.
    136226
    137227**/
    138228BOOLEAN
    139229IsValidVariableHeader (
    140   IN  VARIABLE_HEADER   *Variable
     230  IN  VARIABLE_HEADER       *Variable,
     231  IN  VARIABLE_HEADER       *VariableStoreEnd
    141232  )
    142233{
    143   if (Variable == NULL || Variable->StartId != VARIABLE_DATA) {
     234  if ((Variable == NULL) || (Variable >= VariableStoreEnd) || (Variable->StartId != VARIABLE_DATA)) {
     235    //
     236    // Variable is NULL or has reached the end of variable store,
     237    // or the StartId is not correct.
     238    //
    144239    return FALSE;
    145240  }
     
    441536  UINTN Value;
    442537
    443   if (!IsValidVariableHeader (Variable)) {
    444     return NULL;
    445   }
    446 
    447538  Value =  (UINTN) GetVariableDataPtr (Variable);
    448539  Value += DataSizeOfVariable (Variable);
     
    498589}
    499590
    500 
    501591/**
    502592
     593  Check the PubKeyIndex is a valid key or not.
     594
     595  This function will iterate the NV storage to see if this PubKeyIndex is still referenced
     596  by any valid count-based auth variabe.
     597 
     598  @param[in]  PubKeyIndex     Index of the public key in public key store.
     599
     600  @retval     TRUE            The PubKeyIndex is still in use.
     601  @retval     FALSE           The PubKeyIndex is not referenced by any count-based auth variabe.
     602 
     603**/
     604BOOLEAN
     605IsValidPubKeyIndex (
     606  IN   UINT32      PubKeyIndex
     607  )
     608{
     609  VARIABLE_HEADER          *Variable;
     610  VARIABLE_HEADER          *VariableStoreEnd;
     611
     612  if (PubKeyIndex > mPubKeyNumber) {
     613    return FALSE;
     614  }
     615
     616  Variable = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
     617  VariableStoreEnd = GetEndPointer ((VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
     618
     619  while (IsValidVariableHeader (Variable, VariableStoreEnd)) {
     620    if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) &&
     621        Variable->PubKeyIndex == PubKeyIndex) {
     622      return TRUE;
     623    }
     624    Variable = GetNextVariablePtr (Variable);
     625  }
     626 
     627  return FALSE;
     628}
     629
     630/**
     631
     632  Get the number of valid public key in PubKeyStore.
     633 
     634  @param[in]  PubKeyNumber     Number of the public key in public key store.
     635
     636  @return     Number of valid public key in PubKeyStore.
     637
     638**/
     639UINT32
     640GetValidPubKeyNumber (
     641  IN   UINT32       PubKeyNumber
     642  )
     643{
     644  UINT32       PubKeyIndex;
     645  UINT32       Counter;
     646
     647  Counter = 0;
     648 
     649  for (PubKeyIndex = 1; PubKeyIndex <= PubKeyNumber; PubKeyIndex++) {
     650    if (IsValidPubKeyIndex (PubKeyIndex)) {
     651      Counter++;
     652    }
     653  }
     654 
     655  return Counter;
     656}
     657
     658/**
     659
     660  Filter the useless key in public key store.
     661
     662  This function will find out all valid public keys in public key database, save them in new allocated
     663  buffer NewPubKeyStore, and give the new PubKeyIndex. The caller is responsible for freeing buffer
     664  NewPubKeyIndex and NewPubKeyStore with FreePool().
     665
     666  @param[in]   PubKeyStore          Point to the public key database.
     667  @param[in]   PubKeyNumber         Number of the public key in PubKeyStore.
     668  @param[out]  NewPubKeyIndex       Point to an array of new PubKeyIndex corresponds to NewPubKeyStore.
     669  @param[out]  NewPubKeyStore       Saved all valid public keys in PubKeyStore.
     670  @param[out]  NewPubKeySize        Buffer size of the NewPubKeyStore.
     671 
     672  @retval  EFI_SUCCESS              Trim operation is complete successfully.
     673  @retval  EFI_OUT_OF_RESOURCES     No enough memory resources, or no useless key in PubKeyStore.
     674 
     675**/
     676EFI_STATUS
     677PubKeyStoreFilter (
     678  IN   UINT8         *PubKeyStore,
     679  IN   UINT32        PubKeyNumber,
     680  OUT  UINT32        **NewPubKeyIndex,
     681  OUT  UINT8         **NewPubKeyStore,
     682  OUT  UINT32        *NewPubKeySize
     683  )
     684{
     685  UINT32        PubKeyIndex;
     686  UINT32        CopiedKey;
     687  UINT32        NewPubKeyNumber;
     688 
     689  NewPubKeyNumber = GetValidPubKeyNumber (PubKeyNumber);
     690  if (NewPubKeyNumber == PubKeyNumber) {
     691    return EFI_OUT_OF_RESOURCES;
     692  }
     693
     694  if (NewPubKeyNumber != 0) {
     695    *NewPubKeySize = NewPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE;
     696  } else {
     697    *NewPubKeySize = sizeof (UINT8);
     698  }
     699
     700  *NewPubKeyStore = AllocatePool (*NewPubKeySize);
     701  if (*NewPubKeyStore == NULL) {
     702    return EFI_OUT_OF_RESOURCES;
     703  }
     704
     705  *NewPubKeyIndex = AllocateZeroPool ((PubKeyNumber + 1) * sizeof (UINT32));
     706  if (*NewPubKeyIndex == NULL) {
     707    FreePool (*NewPubKeyStore);
     708    *NewPubKeyStore = NULL;
     709    return EFI_OUT_OF_RESOURCES;
     710  }
     711
     712  CopiedKey = 0;
     713  for (PubKeyIndex = 1; PubKeyIndex <= PubKeyNumber; PubKeyIndex++) {
     714    if (IsValidPubKeyIndex (PubKeyIndex)) {
     715      CopyMem (
     716        *NewPubKeyStore + CopiedKey * EFI_CERT_TYPE_RSA2048_SIZE,
     717        PubKeyStore + (PubKeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE,
     718        EFI_CERT_TYPE_RSA2048_SIZE
     719        );
     720      (*NewPubKeyIndex)[PubKeyIndex] = ++CopiedKey;
     721    }
     722  }
     723  return EFI_SUCCESS;
     724}
     725
     726/**
     727
    503728  Variable store garbage collection and reclaim operation.
    504729
    505   @param VariableBase            Base address of variable store.
    506   @param LastVariableOffset      Offset of last variable.
    507   @param IsVolatile              The variable store is volatile or not;
    508                                  if it is non-volatile, need FTW.
    509   @param UpdatingVariable        Pointer to updating variable.
    510 
    511   @return EFI_OUT_OF_RESOURCES
    512   @return EFI_SUCCESS
    513   @return Others
     730  If ReclaimPubKeyStore is FALSE, reclaim variable space by deleting the obsoleted varaibles.
     731  If ReclaimPubKeyStore is TRUE, reclaim invalid key in public key database and update the PubKeyIndex
     732  for all the count-based authenticate variable in NV storage.
     733
     734  @param[in]      VariableBase            Base address of variable store.
     735  @param[out]     LastVariableOffset      Offset of last variable.
     736  @param[in]      IsVolatile              The variable store is volatile or not;
     737                                          if it is non-volatile, need FTW.
     738  @param[in, out] UpdatingPtrTrack        Pointer to updating variable pointer track structure.
     739  @param[in]      NewVariable             Pointer to new variable.
     740  @param[in]      NewVariableSize         New variable size.
     741  @param[in]      ReclaimPubKeyStore      Reclaim for public key database or not.
     742 
     743  @return EFI_SUCCESS                  Reclaim operation has finished successfully.
     744  @return EFI_OUT_OF_RESOURCES         No enough memory resources or variable space.
     745  @return EFI_DEVICE_ERROR             The public key database doesn't exist.
     746  @return Others                       Unexpect error happened during reclaim operation.
    514747
    515748**/
    516749EFI_STATUS
    517750Reclaim (
    518   IN  EFI_PHYSICAL_ADDRESS  VariableBase,
    519   OUT UINTN                 *LastVariableOffset,
    520   IN  BOOLEAN               IsVolatile,
    521   IN  VARIABLE_HEADER       *UpdatingVariable
     751  IN     EFI_PHYSICAL_ADDRESS         VariableBase,
     752  OUT    UINTN                        *LastVariableOffset,
     753  IN     BOOLEAN                      IsVolatile,
     754  IN OUT VARIABLE_POINTER_TRACK       *UpdatingPtrTrack,
     755  IN     VARIABLE_HEADER              *NewVariable,
     756  IN     UINTN                        NewVariableSize,
     757  IN     BOOLEAN                      ReclaimPubKeyStore
    522758  )
    523759{
     
    530766  UINTN                 MaximumBufferSize;
    531767  UINTN                 VariableSize;
    532   UINTN                 VariableNameSize;
    533   UINTN                 UpdatingVariableNameSize;
    534768  UINTN                 NameSize;
    535769  UINT8                 *CurrPtr;
     
    538772  BOOLEAN               FoundAdded;
    539773  EFI_STATUS            Status;
    540   CHAR16                *VariableNamePtr;
    541   CHAR16                *UpdatingVariableNamePtr;
     774  UINTN                 CommonVariableTotalSize;
     775  UINTN                 HwErrVariableTotalSize;
     776  UINT32                *NewPubKeyIndex;
     777  UINT8                 *NewPubKeyStore;
     778  UINT32                NewPubKeySize;
     779  VARIABLE_HEADER       *PubKeyHeader;
     780  VARIABLE_HEADER       *UpdatingVariable;
     781  VARIABLE_HEADER       *UpdatingInDeletedTransition;
     782
     783  UpdatingVariable = NULL;
     784  UpdatingInDeletedTransition = NULL;
     785  if (UpdatingPtrTrack != NULL) {
     786    UpdatingVariable = UpdatingPtrTrack->CurrPtr;
     787    UpdatingInDeletedTransition = UpdatingPtrTrack->InDeletedTransitionPtr;
     788  }
    542789
    543790  VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
    544   //
    545   // Recalculate the total size of Common/HwErr type variables in non-volatile area.
    546   //
    547   if (!IsVolatile) {
    548     mVariableModuleGlobal->CommonVariableTotalSize = 0;
    549     mVariableModuleGlobal->HwErrVariableTotalSize  = 0;
    550   }
    551 
    552   //
    553   // Start Pointers for the variable.
    554   //
    555   Variable          = GetStartPointer (VariableStoreHeader);
    556   MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);
    557 
    558   while (IsValidVariableHeader (Variable)) {
    559     NextVariable = GetNextVariablePtr (Variable);
    560     if (Variable->State == VAR_ADDED ||
    561         Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
    562        ) {
    563       VariableSize = (UINTN) NextVariable - (UINTN) Variable;
    564       MaximumBufferSize += VariableSize;
    565     }
    566 
    567     Variable = NextVariable;
    568   }
    569 
    570   //
    571   // Reserve the 1 Bytes with Oxff to identify the
    572   // end of the variable buffer.
    573   //
    574   MaximumBufferSize += 1;
    575   ValidBuffer = AllocatePool (MaximumBufferSize);
    576   if (ValidBuffer == NULL) {
    577     return EFI_OUT_OF_RESOURCES;
     791
     792  CommonVariableTotalSize = 0;
     793  HwErrVariableTotalSize  = 0;
     794  NewPubKeyIndex = NULL;
     795  NewPubKeyStore = NULL;
     796  NewPubKeySize  = 0;
     797  PubKeyHeader   = NULL;
     798
     799  if (IsVolatile) {
     800    //
     801    // Start Pointers for the variable.
     802    //
     803    Variable          = GetStartPointer (VariableStoreHeader);
     804    MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);
     805
     806    while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
     807      NextVariable = GetNextVariablePtr (Variable);
     808      if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) &&
     809          Variable != UpdatingVariable &&
     810          Variable != UpdatingInDeletedTransition
     811         ) {
     812        VariableSize = (UINTN) NextVariable - (UINTN) Variable;
     813        MaximumBufferSize += VariableSize;
     814      }
     815
     816      Variable = NextVariable;
     817    }
     818
     819    if (NewVariable != NULL) {
     820      //
     821      // Add the new variable size.
     822      //
     823      MaximumBufferSize += NewVariableSize;
     824    }
     825
     826    //
     827    // Reserve the 1 Bytes with Oxff to identify the
     828    // end of the variable buffer.
     829    //
     830    MaximumBufferSize += 1;
     831    ValidBuffer = AllocatePool (MaximumBufferSize);
     832    if (ValidBuffer == NULL) {
     833      return EFI_OUT_OF_RESOURCES;
     834    }
     835  } else {
     836    //
     837    // For NV variable reclaim, don't allocate pool here and just use mNvVariableCache
     838    // as the buffer to reduce SMRAM consumption for SMM variable driver.
     839    //
     840    MaximumBufferSize = mNvVariableCache->Size;
     841    ValidBuffer = (UINT8 *) mNvVariableCache;
    578842  }
    579843
     
    586850  CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);
    587851
    588   //
    589   // Reinstall all ADDED variables as long as they are not identical to Updating Variable.
    590   //
    591   Variable = GetStartPointer (VariableStoreHeader);
    592   while (IsValidVariableHeader (Variable)) {
    593     NextVariable = GetNextVariablePtr (Variable);
    594     if (Variable->State == VAR_ADDED) {
    595       if (UpdatingVariable != NULL) {
    596         if (UpdatingVariable == Variable) {
     852  if (ReclaimPubKeyStore) {
     853    ASSERT (IsVolatile == FALSE);
     854    //
     855    // Trim the PubKeyStore and get new PubKeyIndex.
     856    //
     857    Status = PubKeyStoreFilter (
     858               mPubKeyStore,
     859               mPubKeyNumber,
     860               &NewPubKeyIndex,
     861               &NewPubKeyStore,
     862               &NewPubKeySize
     863               );
     864    if (EFI_ERROR (Status)) {
     865      goto Done;
     866    }
     867    ASSERT ((NewPubKeyIndex != NULL) && (NewPubKeyStore != NULL));
     868
     869    //
     870    // Refresh the PubKeyIndex for all valid variables (ADDED and IN_DELETED_TRANSITION).
     871    //
     872    Variable = GetStartPointer (VariableStoreHeader);
     873    while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
     874      NextVariable = GetNextVariablePtr (Variable);
     875      if (Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     876        if ((StrCmp (GetVariableNamePtr (Variable), AUTHVAR_KEYDB_NAME) == 0) &&
     877            (CompareGuid (&Variable->VendorGuid, &gEfiAuthenticatedVariableGuid))) {
     878          //
     879          // Skip the public key database, it will be reinstalled later.
     880          //
     881          PubKeyHeader = Variable;
    597882          Variable = NextVariable;
    598883          continue;
    599884        }
    600 
    601         VariableNameSize         = NameSizeOfVariable(Variable);
    602         UpdatingVariableNameSize = NameSizeOfVariable(UpdatingVariable);
    603 
    604         VariableNamePtr         = GetVariableNamePtr (Variable);
    605         UpdatingVariableNamePtr = GetVariableNamePtr (UpdatingVariable);
    606         if (CompareGuid (&Variable->VendorGuid, &UpdatingVariable->VendorGuid)    &&
    607             VariableNameSize == UpdatingVariableNameSize &&
    608             CompareMem (VariableNamePtr, UpdatingVariableNamePtr, VariableNameSize) == 0 ) {
    609           Variable = NextVariable;
    610           continue;
     885       
     886        VariableSize = (UINTN) NextVariable - (UINTN) Variable;
     887        CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
     888        ((VARIABLE_HEADER*) CurrPtr)->PubKeyIndex = NewPubKeyIndex[Variable->PubKeyIndex];
     889        CurrPtr += VariableSize;
     890        if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     891          HwErrVariableTotalSize += VariableSize;
     892        } else if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     893          CommonVariableTotalSize += VariableSize;
    611894        }
    612895      }
    613       VariableSize = (UINTN) NextVariable - (UINTN) Variable;
    614       CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
    615       CurrPtr += VariableSize;
    616       if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    617         mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
    618       } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    619         mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
    620       }
    621     }
    622     Variable = NextVariable;
    623   }
    624 
    625   //
    626   // Reinstall the variable being updated if it is not NULL.
    627   //
    628   if (UpdatingVariable != NULL) {
    629     VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;
    630     CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize);
    631     CurrPtr += VariableSize;
    632     if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    633         mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
    634     } else if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    635         mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
    636     }
    637   }
    638 
    639   //
    640   // Reinstall all in delete transition variables.
    641   //
    642   Variable      = GetStartPointer (VariableStoreHeader);
    643   while (IsValidVariableHeader (Variable)) {
    644     NextVariable = GetNextVariablePtr (Variable);
    645     if (Variable != UpdatingVariable && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
    646 
    647       //
    648       // Buffer has cached all ADDED variable.
    649       // Per IN_DELETED variable, we have to guarantee that
    650       // no ADDED one in previous buffer.
    651       //
    652 
    653       FoundAdded = FALSE;
    654       AddedVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);
    655       while (IsValidVariableHeader (AddedVariable)) {
    656         NextAddedVariable = GetNextVariablePtr (AddedVariable);
    657         NameSize = NameSizeOfVariable (AddedVariable);
    658         if (CompareGuid (&AddedVariable->VendorGuid, &Variable->VendorGuid) &&
    659             NameSize == NameSizeOfVariable (Variable)
    660            ) {
    661           Point0 = (VOID *) GetVariableNamePtr (AddedVariable);
    662           Point1 = (VOID *) GetVariableNamePtr (Variable);
    663           if (CompareMem (Point0, Point1, NameSizeOfVariable (AddedVariable)) == 0) {
    664             FoundAdded = TRUE;
    665             break;
     896      Variable = NextVariable;
     897    }
     898
     899    //
     900    // Reinstall the new public key database.
     901    //
     902    ASSERT (PubKeyHeader != NULL);
     903    if (PubKeyHeader == NULL) {
     904      Status = EFI_DEVICE_ERROR;
     905      goto Done;
     906    }
     907    CopyMem (CurrPtr, (UINT8*) PubKeyHeader, sizeof (VARIABLE_HEADER));
     908    Variable = (VARIABLE_HEADER*) CurrPtr;
     909    Variable->DataSize = NewPubKeySize;
     910    StrCpy (GetVariableNamePtr (Variable), GetVariableNamePtr (PubKeyHeader));
     911    CopyMem (GetVariableDataPtr (Variable), NewPubKeyStore, NewPubKeySize);
     912    CurrPtr = (UINT8*) GetNextVariablePtr (Variable);
     913    CommonVariableTotalSize += (UINTN) CurrPtr - (UINTN) Variable;
     914  } else {
     915    //
     916    // Reinstall all ADDED variables as long as they are not identical to Updating Variable.
     917    //
     918    Variable = GetStartPointer (VariableStoreHeader);
     919    while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
     920      NextVariable = GetNextVariablePtr (Variable);
     921      if (Variable != UpdatingVariable && Variable->State == VAR_ADDED) {
     922        VariableSize = (UINTN) NextVariable - (UINTN) Variable;
     923        CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
     924        CurrPtr += VariableSize;
     925        if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
     926          HwErrVariableTotalSize += VariableSize;
     927        } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
     928          CommonVariableTotalSize += VariableSize;
     929        }
     930      }
     931      Variable = NextVariable;
     932    }
     933
     934    //
     935    // Reinstall all in delete transition variables.
     936    //
     937    Variable = GetStartPointer (VariableStoreHeader);
     938    while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
     939      NextVariable = GetNextVariablePtr (Variable);
     940      if (Variable != UpdatingVariable && Variable != UpdatingInDeletedTransition && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     941
     942        //
     943        // Buffer has cached all ADDED variable.
     944        // Per IN_DELETED variable, we have to guarantee that
     945        // no ADDED one in previous buffer.
     946        //
     947
     948        FoundAdded = FALSE;
     949        AddedVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);
     950        while (IsValidVariableHeader (AddedVariable, GetEndPointer ((VARIABLE_STORE_HEADER *) ValidBuffer))) {
     951          NextAddedVariable = GetNextVariablePtr (AddedVariable);
     952          NameSize = NameSizeOfVariable (AddedVariable);
     953          if (CompareGuid (&AddedVariable->VendorGuid, &Variable->VendorGuid) &&
     954              NameSize == NameSizeOfVariable (Variable)
     955             ) {
     956            Point0 = (VOID *) GetVariableNamePtr (AddedVariable);
     957            Point1 = (VOID *) GetVariableNamePtr (Variable);
     958            if (CompareMem (Point0, Point1, NameSize) == 0) {
     959              FoundAdded = TRUE;
     960              break;
     961            }
     962          }
     963          AddedVariable = NextAddedVariable;
     964        }
     965        if (!FoundAdded) {
     966          //
     967          // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED.
     968          //
     969          VariableSize = (UINTN) NextVariable - (UINTN) Variable;
     970          CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
     971          ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;
     972          CurrPtr += VariableSize;
     973          if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
     974            HwErrVariableTotalSize += VariableSize;
     975          } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
     976            CommonVariableTotalSize += VariableSize;
    666977          }
    667978        }
    668         AddedVariable = NextAddedVariable;
    669       }
    670       if (!FoundAdded) {
    671         //
    672         // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED.
    673         //
    674         VariableSize = (UINTN) NextVariable - (UINTN) Variable;
    675         CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
    676         ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;
    677         CurrPtr += VariableSize;
    678         if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    679           mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
    680         } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    681           mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
     979      }
     980
     981      Variable = NextVariable;
     982    }
     983
     984    //
     985    // Install the new variable if it is not NULL.
     986    //
     987    if (NewVariable != NULL) {
     988      if ((UINTN) (CurrPtr - ValidBuffer) + NewVariableSize > VariableStoreHeader->Size) {
     989        //
     990        // No enough space to store the new variable.
     991        //
     992        Status = EFI_OUT_OF_RESOURCES;
     993        goto Done;
     994      }
     995      if (!IsVolatile) {
     996        if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     997          HwErrVariableTotalSize += NewVariableSize;
     998        } else if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     999          CommonVariableTotalSize += NewVariableSize;
    6821000        }
    683       }
    684     }
    685 
    686     Variable = NextVariable;
     1001        if ((HwErrVariableTotalSize > PcdGet32 (PcdHwErrStorageSize)) ||
     1002            (CommonVariableTotalSize > VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize))) {
     1003          //
     1004          // No enough space to store the new variable by NV or NV+HR attribute.
     1005          //
     1006          Status = EFI_OUT_OF_RESOURCES;
     1007          goto Done;
     1008        }
     1009      }
     1010
     1011      CopyMem (CurrPtr, (UINT8 *) NewVariable, NewVariableSize);
     1012      ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;
     1013      if (UpdatingVariable != NULL) {
     1014        UpdatingPtrTrack->CurrPtr = (VARIABLE_HEADER *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer)));
     1015        UpdatingPtrTrack->InDeletedTransitionPtr = NULL;
     1016      }
     1017      CurrPtr += NewVariableSize;
     1018    }
    6871019  }
    6881020
     
    6921024    //
    6931025    SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);
    694     CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - (UINT8 *) ValidBuffer));
     1026    CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - ValidBuffer));
     1027    *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);
    6951028    Status  = EFI_SUCCESS;
    6961029  } else {
     
    7001033    Status = FtwVariableSpace (
    7011034              VariableBase,
    702               ValidBuffer,
    703               (UINTN) (CurrPtr - (UINT8 *) ValidBuffer)
     1035              (VARIABLE_STORE_HEADER *) ValidBuffer
    7041036              );
    705     CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableBase, VariableStoreHeader->Size);
    706   }
    707   if (!EFI_ERROR (Status)) {
    708     *LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer);
     1037    if (!EFI_ERROR (Status)) {
     1038      *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);
     1039      mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;
     1040      mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;
     1041    } else {
     1042      NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);
     1043      while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase))) {
     1044        VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
     1045        if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     1046          mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
     1047        } else if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     1048          mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
     1049        }
     1050
     1051        NextVariable = GetNextVariablePtr (NextVariable);
     1052      }
     1053      *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;
     1054    }
     1055  }
     1056
     1057Done:
     1058  if (IsVolatile) {
     1059    FreePool (ValidBuffer);
    7091060  } else {
    710     *LastVariableOffset = 0;
    711   }
    712 
    713   FreePool (ValidBuffer);
     1061    //
     1062    // For NV variable reclaim, we use mNvVariableCache as the buffer, so copy the data back.
     1063    //
     1064    CopyMem (mNvVariableCache, (UINT8 *)(UINTN)VariableBase, VariableStoreHeader->Size);
     1065
     1066    if (NewPubKeyStore != NULL) {
     1067      FreePool (NewPubKeyStore);
     1068    }
     1069
     1070    if (NewPubKeyIndex != NULL) {
     1071      FreePool (NewPubKeyIndex);
     1072    }
     1073  }
    7141074
    7151075  return Status;
     
    7391099  VOID                           *Point;
    7401100
     1101  PtrTrack->InDeletedTransitionPtr = NULL;
     1102
    7411103  //
    7421104  // Find the variable by walk through HOB, volatile and non-volatile variable store.
     
    7451107
    7461108  for ( PtrTrack->CurrPtr = PtrTrack->StartPtr
    747       ; (PtrTrack->CurrPtr < PtrTrack->EndPtr) && IsValidVariableHeader (PtrTrack->CurrPtr)
     1109      ; IsValidVariableHeader (PtrTrack->CurrPtr, PtrTrack->EndPtr)
    7481110      ; PtrTrack->CurrPtr = GetNextVariablePtr (PtrTrack->CurrPtr)
    7491111      ) {
     
    7561118            InDeletedVariable   = PtrTrack->CurrPtr;
    7571119          } else {
     1120            PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
    7581121            return EFI_SUCCESS;
    7591122          }
     
    7671130                InDeletedVariable     = PtrTrack->CurrPtr;
    7681131              } else {
     1132                PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
    7691133                return EFI_SUCCESS;
    7701134              }
     
    11511515
    11521516/**
     1517  This function is to check if the remaining variable space is enough to set
     1518  all Variables from argument list successfully. The purpose of the check
     1519  is to keep the consistency of the Variables to be in variable storage.
     1520
     1521  Note: Variables are assumed to be in same storage.
     1522  The set sequence of Variables will be same with the sequence of VariableEntry from argument list,
     1523  so follow the argument sequence to check the Variables.
     1524
     1525  @param[in] Attributes         Variable attributes for Variable entries.
     1526  @param ...                    The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *.
     1527                                A NULL terminates the list. The VariableSize of
     1528                                VARIABLE_ENTRY_CONSISTENCY is the variable data size as input.
     1529                                It will be changed to variable total size as output.
     1530
     1531  @retval TRUE                  Have enough variable space to set the Variables successfully.
     1532  @retval FALSE                 No enough variable space to set the Variables successfully.
     1533
     1534**/
     1535BOOLEAN
     1536EFIAPI
     1537CheckRemainingSpaceForConsistency (
     1538  IN UINT32                     Attributes,
     1539  ...
     1540  )
     1541{
     1542  EFI_STATUS                    Status;
     1543  VA_LIST                       Args;
     1544  VARIABLE_ENTRY_CONSISTENCY    *VariableEntry;
     1545  UINT64                        MaximumVariableStorageSize;
     1546  UINT64                        RemainingVariableStorageSize;
     1547  UINT64                        MaximumVariableSize;
     1548  UINTN                         TotalNeededSize;
     1549  UINTN                         OriginalVarSize;
     1550  VARIABLE_STORE_HEADER         *VariableStoreHeader;
     1551  VARIABLE_POINTER_TRACK        VariablePtrTrack;
     1552  VARIABLE_HEADER               *NextVariable;
     1553  UINTN                         VarNameSize;
     1554  UINTN                         VarDataSize;
     1555
     1556  //
     1557  // Non-Volatile related.
     1558  //
     1559  VariableStoreHeader = mNvVariableCache;
     1560
     1561  Status = VariableServiceQueryVariableInfoInternal (
     1562             Attributes,
     1563             &MaximumVariableStorageSize,
     1564             &RemainingVariableStorageSize,
     1565             &MaximumVariableSize
     1566             );
     1567  ASSERT_EFI_ERROR (Status);
     1568
     1569  TotalNeededSize = 0;
     1570  VA_START (Args, Attributes);
     1571  VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
     1572  while (VariableEntry != NULL) {
     1573    //
     1574    // Calculate variable total size.
     1575    //
     1576    VarNameSize  = StrSize (VariableEntry->Name);
     1577    VarNameSize += GET_PAD_SIZE (VarNameSize);
     1578    VarDataSize  = VariableEntry->VariableSize;
     1579    VarDataSize += GET_PAD_SIZE (VarDataSize);
     1580    VariableEntry->VariableSize = HEADER_ALIGN (sizeof (VARIABLE_HEADER) + VarNameSize + VarDataSize);
     1581
     1582    TotalNeededSize += VariableEntry->VariableSize;
     1583    VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
     1584  }
     1585  VA_END (Args);
     1586
     1587  if (RemainingVariableStorageSize >= TotalNeededSize) {
     1588    //
     1589    // Already have enough space.
     1590    //
     1591    return TRUE;
     1592  } else if (AtRuntime ()) {
     1593    //
     1594    // At runtime, no reclaim.
     1595    // The original variable space of Variables can't be reused.
     1596    //
     1597    return FALSE;
     1598  }
     1599
     1600  VA_START (Args, Attributes);
     1601  VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
     1602  while (VariableEntry != NULL) {
     1603    //
     1604    // Check if Variable[Index] has been present and get its size.
     1605    //
     1606    OriginalVarSize = 0;
     1607    VariablePtrTrack.StartPtr = GetStartPointer (VariableStoreHeader);
     1608    VariablePtrTrack.EndPtr   = GetEndPointer   (VariableStoreHeader);
     1609    Status = FindVariableEx (
     1610               VariableEntry->Name,
     1611               VariableEntry->Guid,
     1612               FALSE,
     1613               &VariablePtrTrack
     1614               );
     1615    if (!EFI_ERROR (Status)) {
     1616      //
     1617      // Get size of Variable[Index].
     1618      //
     1619      NextVariable = GetNextVariablePtr (VariablePtrTrack.CurrPtr);
     1620      OriginalVarSize = (UINTN) NextVariable - (UINTN) VariablePtrTrack.CurrPtr;
     1621      //
     1622      // Add the original size of Variable[Index] to remaining variable storage size.
     1623      //
     1624      RemainingVariableStorageSize += OriginalVarSize;
     1625    }
     1626    if (VariableEntry->VariableSize > RemainingVariableStorageSize) {
     1627      //
     1628      // No enough space for Variable[Index].
     1629      //
     1630      VA_END (Args);
     1631      return FALSE;
     1632    }
     1633    //
     1634    // Sub the (new) size of Variable[Index] from remaining variable storage size.
     1635    //
     1636    RemainingVariableStorageSize -= VariableEntry->VariableSize;
     1637    VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
     1638  }
     1639  VA_END (Args);
     1640
     1641  return TRUE;
     1642}
     1643
     1644/**
    11531645  Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.
    11541646
     
    11641656  @param[in] DataSize           Size of data. 0 means delete.
    11651657
    1166 **/
    1167 VOID
     1658  @retval EFI_SUCCESS           The update operation is successful or ignored.
     1659  @retval EFI_WRITE_PROTECTED   Update PlatformLangCodes/LangCodes at runtime.
     1660  @retval EFI_OUT_OF_RESOURCES  No enough variable space to do the update operation.
     1661  @retval Others                Other errors happened during the update operation.
     1662
     1663**/
     1664EFI_STATUS
    11681665AutoUpdateLangVariable (
    11691666  IN  CHAR16             *VariableName,
     
    11791676  VARIABLE_POINTER_TRACK Variable;
    11801677  BOOLEAN                SetLanguageCodes;
     1678  VARIABLE_ENTRY_CONSISTENCY VariableEntry[2];
    11811679
    11821680  //
     
    11841682  //
    11851683  if (DataSize == 0) {
    1186     return;
     1684    return EFI_SUCCESS;
    11871685  }
    11881686
    11891687  SetLanguageCodes = FALSE;
    11901688
    1191   if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {
     1689  if (StrCmp (VariableName, EFI_PLATFORM_LANG_CODES_VARIABLE_NAME) == 0) {
    11921690    //
    11931691    // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.
    11941692    //
    11951693    if (AtRuntime ()) {
    1196       return;
     1694      return EFI_WRITE_PROTECTED;
    11971695    }
    11981696
     
    12191717    ASSERT (mVariableModuleGlobal->PlatformLang != NULL);
    12201718
    1221   } else if (StrCmp (VariableName, L"LangCodes") == 0) {
     1719  } else if (StrCmp (VariableName, EFI_LANG_CODES_VARIABLE_NAME) == 0) {
    12221720    //
    12231721    // LangCodes is a volatile variable, so it can not be updated at runtime.
    12241722    //
    12251723    if (AtRuntime ()) {
    1226       return;
     1724      return EFI_WRITE_PROTECTED;
    12271725    }
    12281726
     
    12471745    // Update PlatformLang if Lang is already set
    12481746    //
    1249     Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     1747    Status = FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
    12501748    if (!EFI_ERROR (Status)) {
    12511749      //
    12521750      // Update Lang
    12531751      //
    1254       VariableName = L"PlatformLang";
     1752      VariableName = EFI_PLATFORM_LANG_VARIABLE_NAME;
    12551753      Data         = GetVariableDataPtr (Variable.CurrPtr);
    12561754      DataSize     = Variable.CurrPtr->DataSize;
    12571755    } else {
    1258       Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     1756      Status = FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
    12591757      if (!EFI_ERROR (Status)) {
    12601758        //
    12611759        // Update PlatformLang
    12621760        //
    1263         VariableName = L"Lang";
     1761        VariableName = EFI_LANG_VARIABLE_NAME;
    12641762        Data         = GetVariableDataPtr (Variable.CurrPtr);
    12651763        DataSize     = Variable.CurrPtr->DataSize;
     
    12681766        // Neither PlatformLang nor Lang is set, directly return
    12691767        //
    1270         return;
    1271       }
    1272     }
    1273   }
     1768        return EFI_SUCCESS;
     1769      }
     1770    }
     1771  }
     1772
     1773  Status = EFI_SUCCESS;
    12741774
    12751775  //
     
    12781778  Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
    12791779
    1280   if (StrCmp (VariableName, L"PlatformLang") == 0) {
     1780  if (StrCmp (VariableName, EFI_PLATFORM_LANG_VARIABLE_NAME) == 0) {
    12811781    //
    12821782    // Update Lang when PlatformLangCodes/LangCodes were set.
     
    12991799
    13001800        //
    1301         // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
    1302         //
    1303         FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
    1304 
    1305         Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang,
    1306                                  ISO_639_2_ENTRY_SIZE + 1, Attributes, 0, 0, &Variable, NULL);
    1307 
    1308         DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));
    1309 
    1310         ASSERT_EFI_ERROR(Status);
    1311       }
    1312     }
    1313 
    1314   } else if (StrCmp (VariableName, L"Lang") == 0) {
     1801        // Check the variable space for both Lang and PlatformLang variable.
     1802        //
     1803        VariableEntry[0].VariableSize = ISO_639_2_ENTRY_SIZE + 1;
     1804        VariableEntry[0].Guid = &gEfiGlobalVariableGuid;
     1805        VariableEntry[0].Name = EFI_LANG_VARIABLE_NAME;
     1806       
     1807        VariableEntry[1].VariableSize = AsciiStrSize (BestPlatformLang);
     1808        VariableEntry[1].Guid = &gEfiGlobalVariableGuid;
     1809        VariableEntry[1].Name = EFI_PLATFORM_LANG_VARIABLE_NAME;
     1810        if (!CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {
     1811          //
     1812          // No enough variable space to set both Lang and PlatformLang successfully.
     1813          //
     1814          Status = EFI_OUT_OF_RESOURCES;
     1815        } else {
     1816          //
     1817          // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
     1818          //
     1819          FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     1820
     1821          Status = UpdateVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestLang,
     1822                                   ISO_639_2_ENTRY_SIZE + 1, Attributes, 0, 0, &Variable, NULL);
     1823        }
     1824
     1825        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a Status: %r\n", BestPlatformLang, BestLang, Status));
     1826      }
     1827    }
     1828
     1829  } else if (StrCmp (VariableName, EFI_LANG_VARIABLE_NAME) == 0) {
    13151830    //
    13161831    // Update PlatformLang when PlatformLangCodes/LangCodes were set.
     
    13331848
    13341849        //
    1335         // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
    1336         //
    1337         FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
    1338 
    1339         Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang,
    1340                                  AsciiStrSize (BestPlatformLang), Attributes, 0, 0, &Variable, NULL);
    1341 
    1342         DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));
    1343         ASSERT_EFI_ERROR (Status);
    1344       }
    1345     }
     1850        // Check the variable space for both PlatformLang and Lang variable.
     1851        //
     1852        VariableEntry[0].VariableSize = AsciiStrSize (BestPlatformLang);
     1853        VariableEntry[0].Guid = &gEfiGlobalVariableGuid;
     1854        VariableEntry[0].Name = EFI_PLATFORM_LANG_VARIABLE_NAME;
     1855
     1856        VariableEntry[1].VariableSize = ISO_639_2_ENTRY_SIZE + 1;
     1857        VariableEntry[1].Guid = &gEfiGlobalVariableGuid;
     1858        VariableEntry[1].Name = EFI_LANG_VARIABLE_NAME;
     1859        if (!CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {
     1860          //
     1861          // No enough variable space to set both PlatformLang and Lang successfully.
     1862          //
     1863          Status = EFI_OUT_OF_RESOURCES;
     1864        } else {
     1865          //
     1866          // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
     1867          //
     1868          FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     1869
     1870          Status = UpdateVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestPlatformLang,
     1871                                   AsciiStrSize (BestPlatformLang), Attributes, 0, 0, &Variable, NULL);
     1872        }
     1873
     1874        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a Status: %r\n", BestLang, BestPlatformLang, Status));
     1875      }
     1876    }
     1877  }
     1878
     1879  if (SetLanguageCodes) {
     1880    //
     1881    // Continue to set PlatformLangCodes or LangCodes.
     1882    //
     1883    return EFI_SUCCESS;
     1884  } else {
     1885    return Status;
    13461886  }
    13471887}
     
    13581898  @param[in] KeyIndex           Index of associated public key.
    13591899  @param[in] MonotonicCount     Value of associated monotonic count.
    1360   @param[in] CacheVariable      The variable information which is used to keep track of variable usage.
     1900  @param[in, out] CacheVariable The variable information which is used to keep track of variable usage.
    13611901  @param[in] TimeStamp          Value of associated TimeStamp.
    13621902
     
    13741914  IN      UINT32                      KeyIndex        OPTIONAL,
    13751915  IN      UINT64                      MonotonicCount  OPTIONAL,
    1376   IN      VARIABLE_POINTER_TRACK      *CacheVariable,
     1916  IN OUT  VARIABLE_POINTER_TRACK      *CacheVariable,
    13771917  IN      EFI_TIME                    *TimeStamp      OPTIONAL
    13781918  )
     
    13811921  VARIABLE_HEADER                     *NextVariable;
    13821922  UINTN                               ScratchSize;
    1383   UINTN                               ScratchDataSize;
     1923  UINTN                               MaxDataSize;
    13841924  UINTN                               NonVolatileVarableStoreSize;
    13851925  UINTN                               VarNameOffset;
     
    13901930  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;
    13911931  UINT8                               State;
    1392   BOOLEAN                             Reclaimed;
    13931932  VARIABLE_POINTER_TRACK              *Variable;
    13941933  VARIABLE_POINTER_TRACK              NvVariable;
    13951934  VARIABLE_STORE_HEADER               *VariableStoreHeader;
    13961935  UINTN                               CacheOffset;
    1397   UINTN                               BufSize;
     1936  UINT8                               *BufferForMerge;
     1937  UINTN                               MergedBufSize;
     1938  BOOLEAN                             DataReady;
    13981939  UINTN                               DataOffset;
    1399   UINTN                               RevBufSize;
    14001940
    14011941  if (mVariableModuleGlobal->FvbInstance == NULL) {
     
    14301970    Variable->EndPtr   = GetEndPointer (VariableStoreHeader);
    14311971    Variable->CurrPtr  = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));
     1972    if (CacheVariable->InDeletedTransitionPtr != NULL) {
     1973      Variable->InDeletedTransitionPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - (UINTN)CacheVariable->StartPtr));
     1974    } else {
     1975      Variable->InDeletedTransitionPtr = NULL;
     1976    }
    14321977    Variable->Volatile = FALSE;
    14331978  }
    14341979
    14351980  Fvb       = mVariableModuleGlobal->FvbInstance;
    1436   Reclaimed = FALSE;
    14371981
    14381982  //
     
    14421986  NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));
    14431987  ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
    1444   ScratchDataSize = ScratchSize - sizeof (VARIABLE_HEADER) - StrSize (VariableName) - GET_PAD_SIZE (StrSize (VariableName));
     1988  SetMem (NextVariable, ScratchSize, 0xff);
     1989  DataReady = FALSE;
    14451990
    14461991  if (Variable->CurrPtr != NULL) {
     
    14822027    //
    14832028    if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0))|| ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0)) {
     2029      if (Variable->InDeletedTransitionPtr != NULL) {
     2030        //
     2031        // Both ADDED and IN_DELETED_TRANSITION variable are present,
     2032        // set IN_DELETED_TRANSITION one to DELETED state first.
     2033        //
     2034        State = Variable->InDeletedTransitionPtr->State;
     2035        State &= VAR_DELETED;
     2036        Status = UpdateVariableStore (
     2037                   &mVariableModuleGlobal->VariableGlobal,
     2038                   Variable->Volatile,
     2039                   FALSE,
     2040                   Fvb,
     2041                   (UINTN) &Variable->InDeletedTransitionPtr->State,
     2042                   sizeof (UINT8),
     2043                   &State
     2044                   );
     2045        if (!EFI_ERROR (Status)) {
     2046          if (!Variable->Volatile) {
     2047            ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);
     2048            CacheVariable->InDeletedTransitionPtr->State = State;
     2049          }
     2050        } else {
     2051          goto Done;
     2052        }
     2053      }
     2054
    14842055      State = Variable->CurrPtr->State;
    14852056      State &= VAR_DELETED;
     
    14982069        if (!Variable->Volatile) {
    14992070          CacheVariable->CurrPtr->State = State;
     2071          FlushHobVariableToFlash (VariableName, VendorGuid);
    15002072        }
    15012073      }
     
    15072079    //
    15082080    if (DataSizeOfVariable (Variable->CurrPtr) == DataSize &&
    1509         (CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0)  &&
     2081        (CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0) &&
    15102082        ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) &&
    15112083        (TimeStamp == NULL)) {
     
    15242096      if ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0) {
    15252097        //
    1526         // Cache the previous variable data into StorageArea.
     2098        // NOTE: From 0 to DataOffset of NextVariable is reserved for Variable Header and Name.
     2099        // From DataOffset of NextVariable is to save the existing variable data.
    15272100        //
    15282101        DataOffset = sizeof (VARIABLE_HEADER) + Variable->CurrPtr->NameSize + GET_PAD_SIZE (Variable->CurrPtr->NameSize);
    1529         CopyMem (mStorageArea, (UINT8*)((UINTN) Variable->CurrPtr + DataOffset), Variable->CurrPtr->DataSize);
    1530 
    1531         if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) ||
    1532                 (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {
     2102        BufferForMerge = (UINT8 *) ((UINTN) NextVariable + DataOffset);
     2103        CopyMem (BufferForMerge, (UINT8 *) ((UINTN) Variable->CurrPtr + DataOffset), Variable->CurrPtr->DataSize);
     2104
     2105        //
     2106        // Set Max Common Variable Data Size as default MaxDataSize
     2107        //
     2108        MaxDataSize = PcdGet32 (PcdMaxVariableSize) - DataOffset;
     2109
     2110        if ((CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
     2111            ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))) ||
     2112            (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {
    15332113          //
    1534           // For variables with the GUID EFI_IMAGE_SECURITY_DATABASE_GUID (i.e. where the data
    1535           // buffer is formatted as EFI_SIGNATURE_LIST), the driver shall not perform an append of
     2114          // For variables with formatted as EFI_SIGNATURE_LIST, the driver shall not perform an append of
    15362115          // EFI_SIGNATURE_DATA values that are already part of the existing variable value.
    15372116          //
    1538           BufSize = AppendSignatureList (mStorageArea, Variable->CurrPtr->DataSize, Data, DataSize);
    1539           if (BufSize == Variable->CurrPtr->DataSize) {
     2117          Status = AppendSignatureList (
     2118                     BufferForMerge,
     2119                     Variable->CurrPtr->DataSize,
     2120                     MaxDataSize - Variable->CurrPtr->DataSize,
     2121                     Data,
     2122                     DataSize,
     2123                     &MergedBufSize
     2124                     );
     2125          if (Status == EFI_BUFFER_TOO_SMALL) {
     2126            //
     2127            // Signature List is too long, Failed to Append.
     2128            //
     2129            Status = EFI_INVALID_PARAMETER;
     2130            goto Done;
     2131          }
     2132
     2133          if (MergedBufSize == Variable->CurrPtr->DataSize) {
    15402134            if ((TimeStamp == NULL) || CompareTimeStamp (TimeStamp, &Variable->CurrPtr->TimeStamp)) {
    15412135              //
     
    15502144        } else {
    15512145          //
    1552           // For other Variables, append the new data to the end of previous data.
     2146          // For other Variables, append the new data to the end of existing data.
     2147          // Max Harware error record variable data size is different from common variable
    15532148          //
    1554           CopyMem ((UINT8*)((UINTN) mStorageArea + Variable->CurrPtr->DataSize), Data, DataSize);
    1555           BufSize = Variable->CurrPtr->DataSize + DataSize;
     2149          if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     2150            MaxDataSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - DataOffset;
     2151          }
     2152
     2153          if (Variable->CurrPtr->DataSize + DataSize > MaxDataSize) {
     2154            //
     2155            // Existing data size + new data size exceed maximum variable size limitation.
     2156            //
     2157            Status = EFI_INVALID_PARAMETER;
     2158            goto Done;
     2159          }
     2160          CopyMem ((UINT8*) ((UINTN) BufferForMerge + Variable->CurrPtr->DataSize), Data, DataSize);
     2161          MergedBufSize = Variable->CurrPtr->DataSize + DataSize;
    15562162        }
    15572163
    1558         RevBufSize = MIN (PcdGet32 (PcdMaxVariableSize), ScratchDataSize);
    1559         if (BufSize > RevBufSize) {
    1560           //
    1561           // If variable size (previous + current) is bigger than reserved buffer in runtime,
    1562           // return EFI_OUT_OF_RESOURCES.
    1563           //
    1564           return EFI_OUT_OF_RESOURCES;
    1565         }
    1566 
    1567         //
    1568         // Override Data and DataSize which are used for combined data area including previous and new data.
    1569         //
    1570         Data     = mStorageArea;
    1571         DataSize = BufSize;
     2164        //
     2165        // BufferForMerge(from DataOffset of NextVariable) has included the merged existing and new data.
     2166        //
     2167        Data      = BufferForMerge;
     2168        DataSize  = MergedBufSize;
     2169        DataReady = TRUE;
    15722170      }
    15732171
     
    16262224  // Function part - create a new variable and copy the data.
    16272225  // Both update a variable and create a variable will come here.
    1628 
    1629   SetMem (NextVariable, ScratchSize, 0xff);
    1630 
     2226  //
    16312227  NextVariable->StartId     = VARIABLE_DATA;
    16322228  //
     
    16702266    );
    16712267  VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);
    1672   CopyMem (
    1673     (UINT8 *) ((UINTN) NextVariable + VarDataOffset),
    1674     Data,
    1675     DataSize
    1676     );
     2268
     2269  //
     2270  // If DataReady is TRUE, it means the variable data has been saved into
     2271  // NextVariable during EFI_VARIABLE_APPEND_WRITE operation preparation.
     2272  //
     2273  if (!DataReady) {
     2274    CopyMem (
     2275      (UINT8 *) ((UINTN) NextVariable + VarDataOffset),
     2276      Data,
     2277      DataSize
     2278      );
     2279  }
     2280
    16772281  CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));
    16782282  //
     
    17042308      }
    17052309      //
    1706       // Perform garbage collection & reclaim operation.
    1707       //
    1708       Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
    1709                         &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr);
    1710       if (EFI_ERROR (Status)) {
    1711         goto Done;
    1712       }
    1713       //
    1714       // If still no enough space, return out of resources.
    1715       //
    1716       if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)
    1717         && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))
    1718         || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0)
    1719         && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) {
    1720         Status = EFI_OUT_OF_RESOURCES;
    1721         goto Done;
    1722       }
    1723       Reclaimed = TRUE;
     2310      // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.
     2311      //
     2312      Status = Reclaim (
     2313                 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
     2314                 &mVariableModuleGlobal->NonVolatileLastVariableOffset,
     2315                 FALSE,
     2316                 Variable,
     2317                 NextVariable,
     2318                 HEADER_ALIGN (VarSize),
     2319                 FALSE
     2320                 );
     2321      if (!EFI_ERROR (Status)) {
     2322        //
     2323        // The new variable has been integrated successfully during reclaiming.
     2324        //
     2325        if (Variable->CurrPtr != NULL) {
     2326          CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));
     2327          CacheVariable->InDeletedTransitionPtr = NULL;
     2328        }
     2329        UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE);
     2330        FlushHobVariableToFlash (VariableName, VendorGuid);
     2331      }
     2332      goto Done;
    17242333    }
    17252334    //
     
    18192428        ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size) {
    18202429      //
    1821       // Perform garbage collection & reclaim operation.
    1822       //
    1823       Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
    1824                           &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr);
    1825       if (EFI_ERROR (Status)) {
    1826         goto Done;
    1827       }
    1828       //
    1829       // If still no enough space, return out of resources.
    1830       //
    1831       if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >
    1832             ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size
    1833             ) {
    1834         Status = EFI_OUT_OF_RESOURCES;
    1835         goto Done;
    1836       }
    1837       Reclaimed = TRUE;
     2430      // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.
     2431      //
     2432      Status = Reclaim (
     2433                 mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
     2434                 &mVariableModuleGlobal->VolatileLastVariableOffset,
     2435                 TRUE,
     2436                 Variable,
     2437                 NextVariable,
     2438                 HEADER_ALIGN (VarSize),
     2439                 FALSE
     2440                 );
     2441      if (!EFI_ERROR (Status)) {
     2442        //
     2443        // The new variable has been integrated successfully during reclaiming.
     2444        //
     2445        if (Variable->CurrPtr != NULL) {
     2446          CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));
     2447          CacheVariable->InDeletedTransitionPtr = NULL;
     2448        }
     2449        UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, FALSE, FALSE);
     2450      }
     2451      goto Done;
    18382452    }
    18392453
     
    18592473  // Mark the old variable as deleted.
    18602474  //
    1861   if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) {
     2475  if (!EFI_ERROR (Status) && Variable->CurrPtr != NULL) {
     2476    if (Variable->InDeletedTransitionPtr != NULL) {
     2477      //
     2478      // Both ADDED and IN_DELETED_TRANSITION old variable are present,
     2479      // set IN_DELETED_TRANSITION one to DELETED state first.
     2480      //
     2481      State = Variable->InDeletedTransitionPtr->State;
     2482      State &= VAR_DELETED;
     2483      Status = UpdateVariableStore (
     2484                 &mVariableModuleGlobal->VariableGlobal,
     2485                 Variable->Volatile,
     2486                 FALSE,
     2487                 Fvb,
     2488                 (UINTN) &Variable->InDeletedTransitionPtr->State,
     2489                 sizeof (UINT8),
     2490                 &State
     2491                 );
     2492      if (!EFI_ERROR (Status)) {
     2493        if (!Variable->Volatile) {
     2494          ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);
     2495          CacheVariable->InDeletedTransitionPtr->State = State;
     2496        }
     2497      } else {
     2498        goto Done;
     2499      }
     2500    }
     2501
    18622502    State = Variable->CurrPtr->State;
    18632503    State &= VAR_DELETED;
     
    18792519  if (!EFI_ERROR (Status)) {
    18802520    UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);
     2521    if (!Volatile) {
     2522      FlushHobVariableToFlash (VariableName, VendorGuid);
     2523    }
    18812524  }
    18822525
     
    18862529
    18872530/**
     2531  Check if a Unicode character is a hexadecimal character.
     2532
     2533  This function checks if a Unicode character is a
     2534  hexadecimal character.  The valid hexadecimal character is
     2535  L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
     2536
     2537
     2538  @param Char           The character to check against.
     2539
     2540  @retval TRUE          If the Char is a hexadecmial character.
     2541  @retval FALSE         If the Char is not a hexadecmial character.
     2542
     2543**/
     2544BOOLEAN
     2545EFIAPI
     2546IsHexaDecimalDigitCharacter (
     2547  IN CHAR16             Char
     2548  )
     2549{
     2550  return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));
     2551}
     2552
     2553/**
     2554
     2555  This code checks if variable is hardware error record variable or not.
     2556
     2557  According to UEFI spec, hardware error record variable should use the EFI_HARDWARE_ERROR_VARIABLE VendorGuid
     2558  and have the L"HwErrRec####" name convention, #### is a printed hex value and no 0x or h is included in the hex value.
     2559
     2560  @param VariableName   Pointer to variable name.
     2561  @param VendorGuid     Variable Vendor Guid.
     2562
     2563  @retval TRUE          Variable is hardware error record variable.
     2564  @retval FALSE         Variable is not hardware error record variable.
     2565
     2566**/
     2567BOOLEAN
     2568EFIAPI
     2569IsHwErrRecVariable (
     2570  IN CHAR16             *VariableName,
     2571  IN EFI_GUID           *VendorGuid
     2572  )
     2573{
     2574  if (!CompareGuid (VendorGuid, &gEfiHardwareErrorVariableGuid) ||
     2575      (StrLen (VariableName) != StrLen (L"HwErrRec####")) ||
     2576      (StrnCmp(VariableName, L"HwErrRec", StrLen (L"HwErrRec")) != 0) ||
     2577      !IsHexaDecimalDigitCharacter (VariableName[0x8]) ||
     2578      !IsHexaDecimalDigitCharacter (VariableName[0x9]) ||
     2579      !IsHexaDecimalDigitCharacter (VariableName[0xA]) ||
     2580      !IsHexaDecimalDigitCharacter (VariableName[0xB])) {
     2581    return FALSE;
     2582  }
     2583
     2584  return TRUE;
     2585}
     2586
     2587/**
     2588  This code checks if variable guid is global variable guid first.
     2589  If yes, further check if variable name is in mGlobalVariableList or mGlobalVariableList2 and attributes matched.
     2590
     2591  @param[in] VariableName       Pointer to variable name.
     2592  @param[in] VendorGuid         Variable Vendor Guid.
     2593  @param[in] Attributes         Attributes of the variable.
     2594
     2595  @retval EFI_SUCCESS           Variable is not global variable, or Variable is global variable, variable name is in the lists and attributes matched.
     2596  @retval EFI_INVALID_PARAMETER Variable is global variable, but variable name is not in the lists or attributes unmatched.
     2597
     2598**/
     2599EFI_STATUS
     2600EFIAPI
     2601CheckEfiGlobalVariable (
     2602  IN CHAR16             *VariableName,
     2603  IN EFI_GUID           *VendorGuid,
     2604  IN UINT32             Attributes
     2605  )
     2606{
     2607  UINTN     Index;
     2608  UINTN     NameLength;
     2609
     2610  if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)){
     2611    //
     2612    // Try list 1, exactly match.
     2613    //
     2614    for (Index = 0; Index < sizeof (mGlobalVariableList)/sizeof (mGlobalVariableList[0]); Index++) {
     2615      if ((StrCmp (mGlobalVariableList[Index].Name, VariableName) == 0) &&
     2616          (Attributes == 0 || (Attributes & (~EFI_VARIABLE_APPEND_WRITE)) == mGlobalVariableList[Index].Attributes)) {
     2617        return EFI_SUCCESS;
     2618      }
     2619    }
     2620
     2621    //
     2622    // Try list 2.
     2623    //
     2624    NameLength = StrLen (VariableName) - 4;
     2625    for (Index = 0; Index < sizeof (mGlobalVariableList2)/sizeof (mGlobalVariableList2[0]); Index++) {
     2626      if ((StrLen (VariableName) == StrLen (mGlobalVariableList2[Index].Name)) &&
     2627          (StrnCmp (mGlobalVariableList2[Index].Name, VariableName, NameLength) == 0) &&
     2628          IsHexaDecimalDigitCharacter (VariableName[NameLength]) &&
     2629          IsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) &&
     2630          IsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) &&
     2631          IsHexaDecimalDigitCharacter (VariableName[NameLength + 3]) &&
     2632          (Attributes == 0 || (Attributes & (~EFI_VARIABLE_APPEND_WRITE)) == mGlobalVariableList2[Index].Attributes)) {
     2633        return EFI_SUCCESS;
     2634      }
     2635    }
     2636
     2637    DEBUG ((EFI_D_INFO, "[Variable]: set global variable with invalid variable name or attributes - %g:%s:%x\n", VendorGuid, VariableName, Attributes));
     2638    return EFI_INVALID_PARAMETER;
     2639  }
     2640
     2641  return EFI_SUCCESS;
     2642}
     2643
     2644/**
     2645  Mark a variable that will become read-only after leaving the DXE phase of execution.
     2646
     2647  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
     2648  @param[in] VariableName  A pointer to the variable name that will be made read-only subsequently.
     2649  @param[in] VendorGuid    A pointer to the vendor GUID that will be made read-only subsequently.
     2650
     2651  @retval EFI_SUCCESS           The variable specified by the VariableName and the VendorGuid was marked
     2652                                as pending to be read-only.
     2653  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
     2654                                Or VariableName is an empty string.
     2655  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
     2656                                already been signaled.
     2657  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock request.
     2658**/
     2659EFI_STATUS
     2660EFIAPI
     2661VariableLockRequestToLock (
     2662  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
     2663  IN       CHAR16                       *VariableName,
     2664  IN       EFI_GUID                     *VendorGuid
     2665  )
     2666{
     2667  VARIABLE_ENTRY                  *Entry;
     2668
     2669  if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
     2670    return EFI_INVALID_PARAMETER;
     2671  }
     2672
     2673  if (mEndOfDxe) {
     2674    return EFI_ACCESS_DENIED;
     2675  }
     2676
     2677  Entry = AllocateRuntimePool (sizeof (*Entry) + StrSize (VariableName));
     2678  if (Entry == NULL) {
     2679    return EFI_OUT_OF_RESOURCES;
     2680  }
     2681
     2682  DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s\n", VendorGuid, VariableName));
     2683
     2684  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
     2685
     2686  Entry->Name = (CHAR16 *) (Entry + 1);
     2687  StrCpy   (Entry->Name, VariableName);
     2688  CopyGuid (&Entry->Guid, VendorGuid);
     2689  InsertTailList (&mLockedVariableList, &Entry->Link);
     2690
     2691  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
     2692
     2693  return EFI_SUCCESS;
     2694}
     2695
     2696/**
     2697  This code checks if variable should be treated as read-only variable.
     2698
     2699  @param[in]      VariableName            Name of the Variable.
     2700  @param[in]      VendorGuid              GUID of the Variable.
     2701
     2702  @retval TRUE      This variable is read-only variable.
     2703  @retval FALSE     This variable is NOT read-only variable.
     2704 
     2705**/
     2706BOOLEAN
     2707IsReadOnlyVariable (
     2708  IN     CHAR16         *VariableName,
     2709  IN     EFI_GUID       *VendorGuid
     2710  )
     2711{
     2712  if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)) {
     2713    if ((StrCmp (VariableName, EFI_SETUP_MODE_NAME) == 0) ||
     2714        (StrCmp (VariableName, EFI_SIGNATURE_SUPPORT_NAME) == 0) ||
     2715        (StrCmp (VariableName, EFI_SECURE_BOOT_MODE_NAME) == 0) ||
     2716        (StrCmp (VariableName, EFI_VENDOR_KEYS_VARIABLE_NAME) == 0) ||
     2717        (StrCmp (VariableName, EFI_KEK_DEFAULT_VARIABLE_NAME) == 0) ||
     2718        (StrCmp (VariableName, EFI_PK_DEFAULT_VARIABLE_NAME) == 0) ||
     2719        (StrCmp (VariableName, EFI_DB_DEFAULT_VARIABLE_NAME) == 0) ||
     2720        (StrCmp (VariableName, EFI_DBX_DEFAULT_VARIABLE_NAME) == 0) ||
     2721        (StrCmp (VariableName, EFI_DBT_DEFAULT_VARIABLE_NAME) == 0)) {
     2722      return TRUE;
     2723    }
     2724  }
     2725 
     2726  return FALSE;
     2727}
     2728
     2729/**
    18882730
    18892731  This code finds variable in storage blocks (Volatile or Non-Volatile).
     2732
     2733  Caution: This function may receive untrusted input.
     2734  This function may be invoked in SMM mode, and datasize is external input.
     2735  This function will do basic validation, before parse the data.
    18902736
    18912737  @param VariableName               Name of Variable to be found.
     
    19662812  This code Finds the Next available variable.
    19672813
     2814  Caution: This function may receive untrusted input.
     2815  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
     2816
    19682817  @param VariableNameSize           Size of the variable name.
    19692818  @param VariableName               Pointer to variable name.
     
    19872836  VARIABLE_POINTER_TRACK  Variable;
    19882837  VARIABLE_POINTER_TRACK  VariableInHob;
     2838  VARIABLE_POINTER_TRACK  VariablePtrTrack;
    19892839  UINTN                   VarNameSize;
    19902840  EFI_STATUS              Status;
     
    20222872    // Switch from Volatile to HOB, to Non-Volatile.
    20232873    //
    2024     while ((Variable.CurrPtr >= Variable.EndPtr) ||
    2025            (Variable.CurrPtr == NULL)            ||
    2026            !IsValidVariableHeader (Variable.CurrPtr)
    2027           ) {
     2874    while (!IsValidVariableHeader (Variable.CurrPtr, Variable.EndPtr)) {
    20282875      //
    20292876      // Find current storage index
     
    20602907    // Variable is found
    20612908    //
    2062     if (Variable.CurrPtr->State == VAR_ADDED) {
    2063       if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {
     2909    if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     2910      if (!AtRuntime () || ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
     2911        if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     2912          //
     2913          // If it is a IN_DELETED_TRANSITION variable,
     2914          // and there is also a same ADDED one at the same time,
     2915          // don't return it.
     2916          //
     2917          VariablePtrTrack.StartPtr = Variable.StartPtr;
     2918          VariablePtrTrack.EndPtr = Variable.EndPtr;
     2919          Status = FindVariableEx (
     2920                     GetVariableNamePtr (Variable.CurrPtr),
     2921                     &Variable.CurrPtr->VendorGuid,
     2922                     FALSE,
     2923                     &VariablePtrTrack
     2924                     );
     2925          if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {
     2926            Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
     2927            continue;
     2928          }
     2929        }
    20642930
    20652931        //
     
    21112977  This code sets variable in storage blocks (Volatile or Non-Volatile).
    21122978
     2979  Caution: This function may receive untrusted input.
     2980  This function may be invoked in SMM mode, and datasize and data are external input.
     2981  This function will do basic validation, before parse the data.
     2982  This function will parse the authentication carefully to avoid security issues, like
     2983  buffer overflow, integer overflow.
     2984  This function will check attribute carefully to avoid authentication bypass.
     2985
    21132986  @param VariableName                     Name of Variable to be found.
    21142987  @param VendorGuid                       Variable vendor GUID.
     
    21403013  EFI_PHYSICAL_ADDRESS                Point;
    21413014  UINTN                               PayloadSize;
     3015  LIST_ENTRY                          *Link;
     3016  VARIABLE_ENTRY                      *Entry;
    21423017
    21433018  //
     
    21483023  }
    21493024
     3025  if (IsReadOnlyVariable (VariableName, VendorGuid)) {
     3026    return EFI_WRITE_PROTECTED;
     3027  }
     3028
    21503029  if (DataSize != 0 && Data == NULL) {
     3030    return EFI_INVALID_PARAMETER;
     3031  }
     3032
     3033  //
     3034  // Check for reserverd bit in variable attribute.
     3035  //
     3036  if ((Attributes & (~EFI_VARIABLE_ATTRIBUTES_MASK)) != 0) {
    21513037    return EFI_INVALID_PARAMETER;
    21523038  }
     
    21903076  }
    21913077
     3078  if ((UINTN)(~0) - PayloadSize < StrSize(VariableName)){
     3079    //
     3080    // Prevent whole variable size overflow
     3081    //
     3082    return EFI_INVALID_PARAMETER;
     3083  }
     3084
    21923085  //
    21933086  //  The size of the VariableName, including the Unicode Null in bytes plus
     
    21963089  //
    21973090  if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
    2198     if ((PayloadSize > PcdGet32 (PcdMaxHardwareErrorVariableSize)) ||
    2199         (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + PayloadSize > PcdGet32 (PcdMaxHardwareErrorVariableSize))) {
     3091    if (StrSize (VariableName) + PayloadSize > PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER)) {
    22003092      return EFI_INVALID_PARAMETER;
    22013093    }
    2202     //
    2203     // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX".
    2204     //
    2205     if (StrnCmp(VariableName, L"HwErrRec", StrLen(L"HwErrRec")) != 0) {
     3094    if (!IsHwErrRecVariable(VariableName, VendorGuid)) {
    22063095      return EFI_INVALID_PARAMETER;
    22073096    }
     
    22113100    //  the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.
    22123101    //
    2213     if ((PayloadSize > PcdGet32 (PcdMaxVariableSize)) ||
    2214         (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + PayloadSize > PcdGet32 (PcdMaxVariableSize))) {
     3102    if (StrSize (VariableName) + PayloadSize > PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER)) {
    22153103      return EFI_INVALID_PARAMETER;
    22163104    }
     3105  }
     3106
     3107  Status = CheckEfiGlobalVariable (VariableName, VendorGuid, Attributes);
     3108  if (EFI_ERROR (Status)) {
     3109    return Status;
    22173110  }
    22183111
     
    22283121    //
    22293122    NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point);
    2230     while ((NextVariable < GetEndPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point))
    2231         && IsValidVariableHeader (NextVariable)) {
     3123    while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point))) {
    22323124      NextVariable = GetNextVariablePtr (NextVariable);
    22333125    }
    22343126    mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) Point;
     3127  }
     3128
     3129  if (mEndOfDxe && mEnableLocking) {
     3130    //
     3131    // Treat the variables listed in the forbidden variable list as read-only after leaving DXE phase.
     3132    //
     3133    for ( Link = GetFirstNode (&mLockedVariableList)
     3134        ; !IsNull (&mLockedVariableList, Link)
     3135        ; Link = GetNextNode (&mLockedVariableList, Link)
     3136        ) {
     3137      Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
     3138      if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Entry->Name, VariableName) == 0)) {
     3139        Status = EFI_WRITE_PROTECTED;
     3140        DEBUG ((EFI_D_INFO, "[Variable]: Changing readonly variable after leaving DXE phase - %g:%s\n", VendorGuid, VariableName));
     3141        goto Done;
     3142      }
     3143    }
    22353144  }
    22363145
     
    22413150  if (!EFI_ERROR (Status)) {
    22423151    if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) {
    2243       return EFI_WRITE_PROTECTED;
    2244     }
    2245   }
    2246  
    2247   //
    2248   // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.
    2249   //
    2250   AutoUpdateLangVariable (VariableName, Data, DataSize);
     3152      Status = EFI_WRITE_PROTECTED;
     3153      goto Done;
     3154    }
     3155    if (Attributes != 0 && (Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Variable.CurrPtr->Attributes) {
     3156      //
     3157      // If a preexisting variable is rewritten with different attributes, SetVariable() shall not
     3158      // modify the variable and shall return EFI_INVALID_PARAMETER. Two exceptions to this rule:
     3159      // 1. No access attributes specified
     3160      // 2. The only attribute differing is EFI_VARIABLE_APPEND_WRITE
     3161      //
     3162      Status = EFI_INVALID_PARAMETER;
     3163      goto Done;
     3164    }
     3165  }
     3166
     3167  if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {
     3168    //
     3169    // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.
     3170    //
     3171    Status = AutoUpdateLangVariable (VariableName, Data, DataSize);
     3172    if (EFI_ERROR (Status)) {
     3173      //
     3174      // The auto update operation failed, directly return to avoid inconsistency between PlatformLang and Lang.
     3175      //
     3176      goto Done;
     3177    }
     3178  }
     3179
    22513180  //
    22523181  // Process PK, KEK, Sigdb seperately.
     
    22583187  } else if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
    22593188          ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))) {
    2260     Status = ProcessVarWithKek (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes);
     3189    Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes, FALSE);
     3190    if (EFI_ERROR (Status)) {
     3191      Status = ProcessVarWithKek (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes);
     3192    }
    22613193  } else {
    22623194    Status = ProcessVariable (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes);
    22633195  }
    22643196
     3197Done:
    22653198  InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);
    22663199  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
    22673200
     3201  if (!AtRuntime ()) {
     3202    if (!EFI_ERROR (Status)) {
     3203      SecureBootHook (
     3204        VariableName,
     3205        VendorGuid
     3206        );
     3207    }
     3208  }
     3209
    22683210  return Status;
    22693211}
     
    22723214
    22733215  This code returns information about the EFI variables.
     3216
     3217  Caution: This function may receive untrusted input.
     3218  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
    22743219
    22753220  @param Attributes                     Attributes bitmask to specify the type of variables
     
    22823227                                        associated with the attributes specified.
    22833228
    2284   @return EFI_INVALID_PARAMETER         An invalid combination of attribute bits was supplied.
    22853229  @return EFI_SUCCESS                   Query successfully.
    2286   @return EFI_UNSUPPORTED               The attribute is not supported on this platform.
    22873230
    22883231**/
    22893232EFI_STATUS
    22903233EFIAPI
    2291 VariableServiceQueryVariableInfo (
     3234VariableServiceQueryVariableInfoInternal (
    22923235  IN  UINT32                 Attributes,
    22933236  OUT UINT64                 *MaximumVariableStorageSize,
     
    23023245  UINT64                 CommonVariableTotalSize;
    23033246  UINT64                 HwErrVariableTotalSize;
     3247  EFI_STATUS             Status;
     3248  VARIABLE_POINTER_TRACK VariablePtrTrack;
    23043249
    23053250  CommonVariableTotalSize = 0;
    23063251  HwErrVariableTotalSize = 0;
    2307 
    2308   if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
    2309     return EFI_INVALID_PARAMETER;
    2310   }
    2311 
    2312   if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {
    2313     //
    2314     // Make sure the Attributes combination is supported by the platform.
    2315     //
    2316     return EFI_UNSUPPORTED;
    2317   } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
    2318     //
    2319     // Make sure if runtime bit is set, boot service bit is set also.
    2320     //
    2321     return EFI_INVALID_PARAMETER;
    2322   } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
    2323     //
    2324     // Make sure RT Attribute is set if we are in Runtime phase.
    2325     //
    2326     return EFI_INVALID_PARAMETER;
    2327   } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
    2328     //
    2329     // Make sure Hw Attribute is set with NV.
    2330     //
    2331     return EFI_INVALID_PARAMETER;
    2332   }
    2333 
    2334   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
    23353252
    23363253  if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
     
    23783295  // Now walk through the related variable store.
    23793296  //
    2380   while ((Variable < GetEndPointer (VariableStoreHeader)) && IsValidVariableHeader (Variable)) {
     3297  while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
    23813298    NextVariable = GetNextVariablePtr (Variable);
    23823299    VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;
     
    24053322          CommonVariableTotalSize += VariableSize;
    24063323        }
     3324      } else if (Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     3325        //
     3326        // If it is a IN_DELETED_TRANSITION variable,
     3327        // and there is not also a same ADDED one at the same time,
     3328        // this IN_DELETED_TRANSITION variable is valid.
     3329        //
     3330        VariablePtrTrack.StartPtr = GetStartPointer (VariableStoreHeader);
     3331        VariablePtrTrack.EndPtr   = GetEndPointer   (VariableStoreHeader);
     3332        Status = FindVariableEx (
     3333                   GetVariableNamePtr (Variable),
     3334                   &Variable->VendorGuid,
     3335                   FALSE,
     3336                   &VariablePtrTrack
     3337                   );
     3338        if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State != VAR_ADDED) {
     3339          if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     3340            HwErrVariableTotalSize += VariableSize;
     3341          } else {
     3342            CommonVariableTotalSize += VariableSize;
     3343          }
     3344        }
    24073345      }
    24083346    }
     
    24263364  }
    24273365
    2428   ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
    24293366  return EFI_SUCCESS;
    24303367}
    24313368
     3369/**
     3370
     3371  This code returns information about the EFI variables.
     3372
     3373  Caution: This function may receive untrusted input.
     3374  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
     3375
     3376  @param Attributes                     Attributes bitmask to specify the type of variables
     3377                                        on which to return information.
     3378  @param MaximumVariableStorageSize     Pointer to the maximum size of the storage space available
     3379                                        for the EFI variables associated with the attributes specified.
     3380  @param RemainingVariableStorageSize   Pointer to the remaining size of the storage space available
     3381                                        for EFI variables associated with the attributes specified.
     3382  @param MaximumVariableSize            Pointer to the maximum size of an individual EFI variables
     3383                                        associated with the attributes specified.
     3384
     3385  @return EFI_INVALID_PARAMETER         An invalid combination of attribute bits was supplied.
     3386  @return EFI_SUCCESS                   Query successfully.
     3387  @return EFI_UNSUPPORTED               The attribute is not supported on this platform.
     3388
     3389**/
     3390EFI_STATUS
     3391EFIAPI
     3392VariableServiceQueryVariableInfo (
     3393  IN  UINT32                 Attributes,
     3394  OUT UINT64                 *MaximumVariableStorageSize,
     3395  OUT UINT64                 *RemainingVariableStorageSize,
     3396  OUT UINT64                 *MaximumVariableSize
     3397  )
     3398{
     3399  EFI_STATUS             Status;
     3400
     3401  if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
     3402    return EFI_INVALID_PARAMETER;
     3403  }
     3404
     3405  if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {
     3406    //
     3407    // Make sure the Attributes combination is supported by the platform.
     3408    //
     3409    return EFI_UNSUPPORTED;
     3410  } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
     3411    //
     3412    // Make sure if runtime bit is set, boot service bit is set also.
     3413    //
     3414    return EFI_INVALID_PARAMETER;
     3415  } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
     3416    //
     3417    // Make sure RT Attribute is set if we are in Runtime phase.
     3418    //
     3419    return EFI_INVALID_PARAMETER;
     3420  } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     3421    //
     3422    // Make sure Hw Attribute is set with NV.
     3423    //
     3424    return EFI_INVALID_PARAMETER;
     3425  }
     3426
     3427  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
     3428
     3429  Status = VariableServiceQueryVariableInfoInternal (
     3430             Attributes,
     3431             MaximumVariableStorageSize,
     3432             RemainingVariableStorageSize,
     3433             MaximumVariableSize
     3434             );
     3435
     3436  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
     3437  return Status;
     3438}
    24323439
    24333440/**
    24343441  This function reclaims variable storage if free size is below the threshold.
     3442
     3443  Caution: This function may be invoked at SMM mode.
     3444  Care must be taken to make sure not security issue.
    24353445
    24363446**/
     
    24443454  UINTN                          RemainingCommonVariableSpace;
    24453455  UINTN                          RemainingHwErrVariableSpace;
     3456  STATIC BOOLEAN                 Reclaimed;
     3457
     3458  //
     3459  // This function will be called only once at EndOfDxe or ReadyToBoot event.
     3460  //
     3461  if (Reclaimed) {
     3462    return;
     3463  }
     3464  Reclaimed = TRUE;
    24463465
    24473466  Status  = EFI_SUCCESS;
     
    24623481            &mVariableModuleGlobal->NonVolatileLastVariableOffset,
    24633482            FALSE,
    2464             NULL
     3483            NULL,
     3484            NULL,
     3485            0,
     3486            FALSE
    24653487            );
    24663488    ASSERT_EFI_ERROR (Status);
     
    24683490}
    24693491
    2470 
    24713492/**
    2472   Initializes variable write service after FVB was ready.
     3493  Init non-volatile variable store.
     3494
     3495  @retval EFI_SUCCESS           Function successfully executed.
     3496  @retval EFI_OUT_OF_RESOURCES  Fail to allocate enough memory resource.
     3497  @retval EFI_VOLUME_CORRUPTED  Variable Store or Firmware Volume for Variable Store is corrupted.
     3498
     3499**/
     3500EFI_STATUS
     3501InitNonVolatileVariableStore (
     3502  VOID
     3503  )
     3504{
     3505  EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;
     3506  VARIABLE_HEADER                       *NextVariable;
     3507  EFI_PHYSICAL_ADDRESS                  VariableStoreBase;
     3508  UINT64                                VariableStoreLength;
     3509  UINTN                                 VariableSize;
     3510  EFI_HOB_GUID_TYPE                     *GuidHob;
     3511  EFI_PHYSICAL_ADDRESS                  NvStorageBase;
     3512  UINT8                                 *NvStorageData;
     3513  UINT32                                NvStorageSize;
     3514  FAULT_TOLERANT_WRITE_LAST_WRITE_DATA  *FtwLastWriteData;
     3515  UINT32                                BackUpOffset;
     3516  UINT32                                BackUpSize;
     3517
     3518  mVariableModuleGlobal->FvbInstance = NULL;
     3519
     3520  //
     3521  // Note that in EdkII variable driver implementation, Hardware Error Record type variable
     3522  // is stored with common variable in the same NV region. So the platform integrator should
     3523  // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
     3524  // PcdFlashNvStorageVariableSize.
     3525  //
     3526  ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));
     3527
     3528  //
     3529  // Allocate runtime memory used for a memory copy of the FLASH region.
     3530  // Keep the memory and the FLASH in sync as updates occur.
     3531  //
     3532  NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
     3533  NvStorageData = AllocateRuntimeZeroPool (NvStorageSize);
     3534  if (NvStorageData == NULL) {
     3535    return EFI_OUT_OF_RESOURCES;
     3536  }
     3537
     3538  NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
     3539  if (NvStorageBase == 0) {
     3540    NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
     3541  }
     3542  //
     3543  // Copy NV storage data to the memory buffer.
     3544  //
     3545  CopyMem (NvStorageData, (UINT8 *) (UINTN) NvStorageBase, NvStorageSize);
     3546
     3547  //
     3548  // Check the FTW last write data hob.
     3549  //
     3550  GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
     3551  if (GuidHob != NULL) {
     3552    FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);
     3553    if (FtwLastWriteData->TargetAddress == NvStorageBase) {
     3554      DEBUG ((EFI_D_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));
     3555      //
     3556      // Copy the backed up NV storage data to the memory buffer from spare block.
     3557      //
     3558      CopyMem (NvStorageData, (UINT8 *) (UINTN) (FtwLastWriteData->SpareAddress), NvStorageSize);
     3559    } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&
     3560               (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {
     3561      //
     3562      // Flash NV storage from the Offset is backed up in spare block.
     3563      //
     3564      BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);
     3565      BackUpSize = NvStorageSize - BackUpOffset;
     3566      DEBUG ((EFI_D_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));
     3567      //
     3568      // Copy the partial backed up NV storage data to the memory buffer from spare block.
     3569      //
     3570      CopyMem (NvStorageData + BackUpOffset, (UINT8 *) (UINTN) FtwLastWriteData->SpareAddress, BackUpSize);
     3571    }
     3572  }
     3573
     3574  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) NvStorageData;
     3575
     3576  //
     3577  // Check if the Firmware Volume is not corrupted
     3578  //
     3579  if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {
     3580    FreePool (NvStorageData);
     3581    DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
     3582    return EFI_VOLUME_CORRUPTED;
     3583  }
     3584
     3585  VariableStoreBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) FvHeader + FvHeader->HeaderLength);
     3586  VariableStoreLength = (UINT64) (NvStorageSize - FvHeader->HeaderLength);
     3587
     3588  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
     3589  mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase;
     3590  if (GetVariableStoreStatus (mNvVariableCache) != EfiValid) {
     3591    FreePool (NvStorageData);
     3592    DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n"));
     3593    return EFI_VOLUME_CORRUPTED;
     3594  }
     3595  ASSERT(mNvVariableCache->Size == VariableStoreLength);
     3596
     3597  //
     3598  // The max variable or hardware error variable size should be < variable store size.
     3599  //
     3600  ASSERT(MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) < VariableStoreLength);
     3601
     3602  //
     3603  // Parse non-volatile variable data and get last variable offset.
     3604  //
     3605  NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
     3606  while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase))) {
     3607    VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
     3608    if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
     3609      mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
     3610    } else {
     3611      mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
     3612    }
     3613
     3614    NextVariable = GetNextVariablePtr (NextVariable);
     3615  }
     3616  mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;
     3617
     3618  return EFI_SUCCESS;
     3619}
     3620
     3621/**
     3622  Flush the HOB variable to flash.
     3623
     3624  @param[in] VariableName       Name of variable has been updated or deleted.
     3625  @param[in] VendorGuid         Guid of variable has been updated or deleted.
     3626
     3627**/
     3628VOID
     3629FlushHobVariableToFlash (
     3630  IN CHAR16                     *VariableName,
     3631  IN EFI_GUID                   *VendorGuid
     3632  )
     3633{
     3634  EFI_STATUS                    Status;
     3635  VARIABLE_STORE_HEADER         *VariableStoreHeader;
     3636  VARIABLE_HEADER               *Variable;
     3637  VOID                          *VariableData;
     3638  BOOLEAN                       ErrorFlag;
     3639
     3640  ErrorFlag = FALSE;
     3641
     3642  //
     3643  // Flush the HOB variable to flash.
     3644  //
     3645  if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
     3646    VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
     3647    //
     3648    // Set HobVariableBase to 0, it can avoid SetVariable to call back.
     3649    //
     3650    mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
     3651    for ( Variable = GetStartPointer (VariableStoreHeader)
     3652        ; IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))
     3653        ; Variable = GetNextVariablePtr (Variable)
     3654        ) {
     3655      if (Variable->State != VAR_ADDED) {
     3656        //
     3657        // The HOB variable has been set to DELETED state in local.
     3658        //
     3659        continue;
     3660      }
     3661      ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
     3662      if (VendorGuid == NULL || VariableName == NULL ||
     3663          !CompareGuid (VendorGuid, &Variable->VendorGuid) ||
     3664          StrCmp (VariableName, GetVariableNamePtr (Variable)) != 0) {
     3665        VariableData = GetVariableDataPtr (Variable);
     3666        Status = VariableServiceSetVariable (
     3667                   GetVariableNamePtr (Variable),
     3668                   &Variable->VendorGuid,
     3669                   Variable->Attributes,
     3670                   Variable->DataSize,
     3671                   VariableData
     3672                   );
     3673        DEBUG ((EFI_D_INFO, "Variable driver flush the HOB variable to flash: %g %s %r\n", &Variable->VendorGuid, GetVariableNamePtr (Variable), Status));
     3674      } else {
     3675        //
     3676        // The updated or deleted variable is matched with the HOB variable.
     3677        // Don't break here because we will try to set other HOB variables
     3678        // since this variable could be set successfully.
     3679        //
     3680        Status = EFI_SUCCESS;
     3681      }
     3682      if (!EFI_ERROR (Status)) {
     3683        //
     3684        // If set variable successful, or the updated or deleted variable is matched with the HOB variable,
     3685        // set the HOB variable to DELETED state in local.
     3686        //
     3687        DEBUG ((EFI_D_INFO, "Variable driver set the HOB variable to DELETED state in local: %g %s\n", &Variable->VendorGuid, GetVariableNamePtr (Variable)));
     3688        Variable->State &= VAR_DELETED;
     3689      } else {
     3690        ErrorFlag = TRUE;
     3691      }
     3692    }
     3693    if (ErrorFlag) {
     3694      //
     3695      // We still have HOB variable(s) not flushed in flash.
     3696      //
     3697      mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;
     3698    } else {
     3699      //
     3700      // All HOB variables have been flushed in flash.
     3701      //
     3702      DEBUG ((EFI_D_INFO, "Variable driver: all HOB variables have been flushed in flash.\n"));
     3703      if (!AtRuntime ()) {
     3704        FreePool ((VOID *) VariableStoreHeader);
     3705      }
     3706    }
     3707  }
     3708
     3709}
     3710
     3711/**
     3712  Initializes variable write service after FTW was ready.
    24733713
    24743714  @retval EFI_SUCCESS          Function successfully executed.
     
    24863726  UINT8                           Data;
    24873727  EFI_PHYSICAL_ADDRESS            VariableStoreBase;
    2488   VARIABLE_HEADER                 *Variable;
    2489   VOID                            *VariableData;
    2490 
    2491   VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
     3728  EFI_PHYSICAL_ADDRESS            NvStorageBase;
     3729
     3730  NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
     3731  if (NvStorageBase == 0) {
     3732    NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
     3733  }
     3734  VariableStoreBase = NvStorageBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageBase))->HeaderLength);
     3735
     3736  //
     3737  // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.
     3738  //
     3739  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
    24923740  VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
    24933741
     
    25053753                 &mVariableModuleGlobal->NonVolatileLastVariableOffset,
    25063754                 FALSE,
    2507                  NULL
     3755                 NULL,
     3756                 NULL,
     3757                 0,
     3758                 FALSE
    25083759                 );
    25093760      if (EFI_ERROR (Status)) {
     
    25143765  }
    25153766
    2516 
    2517   //
    2518   // Flush the HOB variable to flash and invalidate HOB variable.
    2519   //
    2520   if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
    2521     //
    2522     // Clear the HobVariableBase to avoid SetVariable() updating the variable in HOB
    2523     //
    2524     VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
    2525     mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
    2526 
    2527     for ( Variable = GetStartPointer (VariableStoreHeader)
    2528         ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))
    2529         ; Variable = GetNextVariablePtr (Variable)
    2530         ) {
    2531       ASSERT (Variable->State == VAR_ADDED);
    2532       ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
    2533       VariableData = GetVariableDataPtr (Variable);
    2534       Status = VariableServiceSetVariable (
    2535                  GetVariableNamePtr (Variable),
    2536                  &Variable->VendorGuid,
    2537                  Variable->Attributes,
    2538                  Variable->DataSize,
    2539                  VariableData
    2540                  );
    2541       ASSERT_EFI_ERROR (Status);
    2542     }
    2543   }
     3767  FlushHobVariableToFlash (NULL, NULL);
    25443768
    25453769  //
     
    25673791  VARIABLE_STORE_HEADER           *VolatileVariableStore;
    25683792  VARIABLE_STORE_HEADER           *VariableStoreHeader;
    2569   VARIABLE_HEADER                 *NextVariable;
    2570   EFI_PHYSICAL_ADDRESS            TempVariableStoreHeader;
    2571   EFI_PHYSICAL_ADDRESS            VariableStoreBase;
    25723793  UINT64                          VariableStoreLength;
    25733794  UINTN                           ScratchSize;
    2574   UINTN                           VariableSize;
    25753795  EFI_HOB_GUID_TYPE               *GuidHob;
    25763796
     
    25863806
    25873807  //
    2588   // Note that in EdkII variable driver implementation, Hardware Error Record type variable
    2589   // is stored with common variable in the same NV region. So the platform integrator should
    2590   // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
    2591   // PcdFlashNvStorageVariableSize.
    2592   //
    2593   ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));
    2594 
    2595   //
    25963808  // Get HOB variable store.
    25973809  //
     
    25993811  if (GuidHob != NULL) {
    26003812    VariableStoreHeader = GET_GUID_HOB_DATA (GuidHob);
     3813    VariableStoreLength = (UINT64) (GuidHob->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE));
    26013814    if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {
    2602       mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;
     3815      mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);
     3816      if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {
     3817        FreePool (mVariableModuleGlobal);
     3818        return EFI_OUT_OF_RESOURCES;
     3819      }
    26033820    } else {
    26043821      DEBUG ((EFI_D_ERROR, "HOB Variable Store header is corrupted!\n"));
     
    26123829  VolatileVariableStore = AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize) + ScratchSize);
    26133830  if (VolatileVariableStore == NULL) {
     3831    if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
     3832      FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);
     3833    }
    26143834    FreePool (mVariableModuleGlobal);
    26153835    return EFI_OUT_OF_RESOURCES;
     
    26233843  mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;
    26243844  mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;
    2625   mVariableModuleGlobal->FvbInstance = NULL;
    26263845
    26273846  CopyGuid (&VolatileVariableStore->Signature, &gEfiAuthenticatedVariableGuid);
     
    26333852
    26343853  //
    2635   // Get non-volatile variable store.
    2636   //
    2637 
    2638   TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
    2639   if (TempVariableStoreHeader == 0) {
    2640     TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
    2641   }
    2642  
    2643   //
    2644   // Check if the Firmware Volume is not corrupted
    2645   //
    2646   if ((((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->Signature != EFI_FVH_SIGNATURE) ||
    2647       (!CompareGuid (&gEfiSystemNvDataFvGuid, &((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->FileSystemGuid))) {
    2648     Status = EFI_VOLUME_CORRUPTED;
    2649     DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
    2650     goto Done;
    2651   }
    2652 
    2653   VariableStoreBase       = TempVariableStoreHeader + \
    2654                               (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
    2655   VariableStoreLength     = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \
    2656                               (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
    2657 
    2658   mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
    2659   VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
    2660   if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
    2661     Status = EFI_VOLUME_CORRUPTED;
    2662     DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n"));
    2663     goto Done;
    2664   }
    2665   ASSERT(VariableStoreHeader->Size == VariableStoreLength);
    2666 
    2667   //
    2668   // Parse non-volatile variable data and get last variable offset.
    2669   //
    2670   NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
    2671   while (IsValidVariableHeader (NextVariable)) {
    2672     VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
    2673     if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    2674       mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
    2675     } else {
    2676       mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
    2677     }
    2678 
    2679     NextVariable = GetNextVariablePtr (NextVariable);
    2680   }
    2681 
    2682   mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;
    2683 
    2684   //
    2685   // Allocate runtime memory used for a memory copy of the FLASH region.
    2686   // Keep the memory and the FLASH in sync as updates occur
    2687   //
    2688   mNvVariableCache = AllocateRuntimeZeroPool ((UINTN)VariableStoreLength);
    2689   if (mNvVariableCache == NULL) {
    2690     Status = EFI_OUT_OF_RESOURCES;
    2691     goto Done;
    2692   }
    2693   CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableStoreBase, (UINTN)VariableStoreLength);
    2694   Status = EFI_SUCCESS;
    2695 
    2696 Done:
     3854  // Init non-volatile variable store.
     3855  //
     3856  Status = InitNonVolatileVariableStore ();
    26973857  if (EFI_ERROR (Status)) {
     3858    if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
     3859      FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);
     3860    }
    26983861    FreePool (mVariableModuleGlobal);
    26993862    FreePool (VolatileVariableStore);
     
    27283891  EFI_FVB_ATTRIBUTES_2                    Attributes;
    27293892
     3893  HandleBuffer = NULL;
    27303894  //
    27313895  // Get all FVB handles.
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h

    r48674 r58459  
    33  internal structure and functions used by Variable modules.
    44
    5 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
     5Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    66This program and the accompanying materials
    77are licensed and made available under the terms and conditions of the BSD License
     
    2222#include <Protocol/FirmwareVolumeBlock.h>
    2323#include <Protocol/Variable.h>
     24#include <Protocol/VariableLock.h>
    2425#include <Library/PcdLib.h>
    2526#include <Library/HobLib.h>
     
    4142#include <Guid/ImageAuthentication.h>
    4243#include <Guid/SystemNvDataGuid.h>
    43 
    44 #define VARIABLE_RECLAIM_THRESHOLD (1024)
     44#include <Guid/FaultTolerantWrite.h>
     45#include <Guid/HardwareErrorVariable.h>
     46
     47#define EFI_VARIABLE_ATTRIBUTES_MASK (EFI_VARIABLE_NON_VOLATILE | \
     48                                      EFI_VARIABLE_BOOTSERVICE_ACCESS | \
     49                                      EFI_VARIABLE_RUNTIME_ACCESS | \
     50                                      EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
     51                                      EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
     52                                      EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
     53                                      EFI_VARIABLE_APPEND_WRITE)
     54
     55#define VARIABLE_ATTRIBUTE_BS_RT        (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)
     56#define VARIABLE_ATTRIBUTE_NV_BS_RT     (VARIABLE_ATTRIBUTE_BS_RT | EFI_VARIABLE_NON_VOLATILE)
     57#define VARIABLE_ATTRIBUTE_NV_BS_RT_AT  (VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
     58
     59typedef struct {
     60  CHAR16      *Name;
     61  UINT32      Attributes;
     62} GLOBAL_VARIABLE_ENTRY;
    4563
    4664///
     
    5876typedef struct {
    5977  VARIABLE_HEADER *CurrPtr;
     78  //
     79  // If both ADDED and IN_DELETED_TRANSITION variable are present,
     80  // InDeletedTransitionPtr will point to the IN_DELETED_TRANSITION one.
     81  // Otherwise, CurrPtr will point to the ADDED or IN_DELETED_TRANSITION one,
     82  // and InDeletedTransitionPtr will be NULL at the same time.
     83  //
     84  VARIABLE_HEADER *InDeletedTransitionPtr;
    6085  VARIABLE_HEADER *EndPtr;
    6186  VARIABLE_HEADER *StartPtr;
     
    87112  EFI_GUID    *Guid;
    88113  CHAR16      *Name;
    89   UINT32      Attributes;
    90   UINTN       DataSize;
    91   VOID        *Data;
    92 } VARIABLE_CACHE_ENTRY;
     114  UINTN       VariableSize;
     115} VARIABLE_ENTRY_CONSISTENCY;
     116
     117typedef struct {
     118  EFI_GUID    Guid;
     119  CHAR16      *Name;
     120  LIST_ENTRY  Link;
     121} VARIABLE_ENTRY;
     122
     123/**
     124  Flush the HOB variable to flash.
     125
     126  @param[in] VariableName       Name of variable has been updated or deleted.
     127  @param[in] VendorGuid         Guid of variable has been updated or deleted.
     128
     129**/
     130VOID
     131FlushHobVariableToFlash (
     132  IN CHAR16                     *VariableName,
     133  IN EFI_GUID                   *VendorGuid
     134  );
    93135
    94136/**
     
    100142
    101143  @param  VariableBase   Base address of the variable to write.
    102   @param  Buffer         Point to the data buffer.
    103   @param  BufferSize     The number of bytes of the data Buffer.
     144  @param  VariableBuffer Point to the variable data buffer.
    104145
    105146  @retval EFI_SUCCESS    The function completed successfully.
     
    111152FtwVariableSpace (
    112153  IN EFI_PHYSICAL_ADDRESS   VariableBase,
    113   IN UINT8                  *Buffer,
    114   IN UINTN                  BufferSize
     154  IN VARIABLE_STORE_HEADER  *VariableBuffer
    115155  );
    116156
     
    179219
    180220/**
     221  This function is to check if the remaining variable space is enough to set
     222  all Variables from argument list successfully. The purpose of the check
     223  is to keep the consistency of the Variables to be in variable storage.
     224
     225  Note: Variables are assumed to be in same storage.
     226  The set sequence of Variables will be same with the sequence of VariableEntry from argument list,
     227  so follow the argument sequence to check the Variables.
     228
     229  @param[in] Attributes         Variable attributes for Variable entries.
     230  @param ...                    The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *.
     231                                A NULL terminates the list. The VariableSize of
     232                                VARIABLE_ENTRY_CONSISTENCY is the variable data size as input.
     233                                It will be changed to variable total size as output.
     234
     235  @retval TRUE                  Have enough variable space to set the Variables successfully.
     236  @retval FALSE                 No enough variable space to set the Variables successfully.
     237
     238**/
     239BOOLEAN
     240EFIAPI
     241CheckRemainingSpaceForConsistency (
     242  IN UINT32                     Attributes,
     243  ...
     244  );
     245 
     246/**
    181247  Update the variable region with Variable information. If EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is set,
    182248  index of associated public key is needed.
     
    189255  @param[in] KeyIndex           Index of associated public key.
    190256  @param[in] MonotonicCount     Value of associated monotonic count.
    191   @param[in] Variable           The variable information that is used to keep track of variable usage.
     257  @param[in, out] Variable      The variable information that is used to keep track of variable usage.
    192258
    193259  @param[in] TimeStamp          Value of associated TimeStamp.
     
    206272  IN      UINT32          KeyIndex  OPTIONAL,
    207273  IN      UINT64          MonotonicCount  OPTIONAL,
    208   IN      VARIABLE_POINTER_TRACK *Variable,
     274  IN OUT  VARIABLE_POINTER_TRACK *Variable,
    209275  IN      EFI_TIME        *TimeStamp  OPTIONAL 
    210276  );
     
    347413
    348414/**
     415
     416  Variable store garbage collection and reclaim operation.
     417
     418  If ReclaimPubKeyStore is FALSE, reclaim variable space by deleting the obsoleted varaibles.
     419  If ReclaimPubKeyStore is TRUE, reclaim invalid key in public key database and update the PubKeyIndex
     420  for all the count-based authenticate variable in NV storage.
     421
     422  @param[in]      VariableBase            Base address of variable store.
     423  @param[out]     LastVariableOffset      Offset of last variable.
     424  @param[in]      IsVolatile              The variable store is volatile or not;
     425                                          if it is non-volatile, need FTW.
     426  @param[in, out] UpdatingPtrTrack        Pointer to updating variable pointer track structure.
     427  @param[in]      NewVariable             Pointer to new variable.
     428  @param[in]      NewVariableSize         New variable size.
     429  @param[in]      ReclaimPubKeyStore      Reclaim for public key database or not.
     430 
     431  @return EFI_SUCCESS                  Reclaim operation has finished successfully.
     432  @return EFI_OUT_OF_RESOURCES         No enough memory resources or variable space.
     433  @return EFI_DEVICE_ERROR             The public key database doesn't exist.
     434  @return Others                       Unexpect error happened during reclaim operation.
     435
     436**/
     437EFI_STATUS
     438Reclaim (
     439  IN     EFI_PHYSICAL_ADDRESS         VariableBase,
     440  OUT    UINTN                        *LastVariableOffset,
     441  IN     BOOLEAN                      IsVolatile,
     442  IN OUT VARIABLE_POINTER_TRACK       *UpdatingPtrTrack,
     443  IN     VARIABLE_HEADER              *NewVariable,
     444  IN     UINTN                        NewVariableSize,
     445  IN     BOOLEAN                      ReclaimPubKeyStore
     446  );
     447
     448/**
    349449  This function reclaims variable storage if free size is below the threshold.
    350450 
     
    401501
    402502  This code finds variable in storage blocks (Volatile or Non-Volatile).
     503
     504  Caution: This function may receive untrusted input.
     505  This function may be invoked in SMM mode, and datasize and data are external input.
     506  This function will do basic validation, before parse the data.
    403507
    404508  @param VariableName               Name of Variable to be found.
     
    429533  This code Finds the Next available variable.
    430534
     535  Caution: This function may receive untrusted input.
     536  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
     537
    431538  @param VariableNameSize           Size of the variable name.
    432539  @param VariableName               Pointer to variable name.
     
    450557
    451558  This code sets variable in storage blocks (Volatile or Non-Volatile).
     559
     560  Caution: This function may receive untrusted input.
     561  This function may be invoked in SMM mode, and datasize and data are external input.
     562  This function will do basic validation, before parse the data.
     563  This function will parse the authentication carefully to avoid security issues, like
     564  buffer overflow, integer overflow.
     565  This function will check attribute carefully to avoid authentication bypass.
    452566
    453567  @param VariableName                     Name of Variable to be found.
     
    478592
    479593  This code returns information about the EFI variables.
     594
     595  Caution: This function may receive untrusted input.
     596  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
    480597
    481598  @param Attributes                     Attributes bitmask to specify the type of variables
     
    488605                                        associated with the attributes specified.
    489606
     607  @return EFI_SUCCESS                   Query successfully.
     608
     609**/
     610EFI_STATUS
     611EFIAPI
     612VariableServiceQueryVariableInfoInternal (
     613  IN  UINT32                 Attributes,
     614  OUT UINT64                 *MaximumVariableStorageSize,
     615  OUT UINT64                 *RemainingVariableStorageSize,
     616  OUT UINT64                 *MaximumVariableSize
     617  );
     618
     619/**
     620
     621  This code returns information about the EFI variables.
     622
     623  Caution: This function may receive untrusted input.
     624  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
     625
     626  @param Attributes                     Attributes bitmask to specify the type of variables
     627                                        on which to return information.
     628  @param MaximumVariableStorageSize     Pointer to the maximum size of the storage space available
     629                                        for the EFI variables associated with the attributes specified.
     630  @param RemainingVariableStorageSize   Pointer to the remaining size of the storage space available
     631                                        for EFI variables associated with the attributes specified.
     632  @param MaximumVariableSize            Pointer to the maximum size of an individual EFI variables
     633                                        associated with the attributes specified.
     634
    490635  @return EFI_INVALID_PARAMETER         An invalid combination of attribute bits was supplied.
    491636  @return EFI_SUCCESS                   Query successfully.
     
    501646  OUT UINT64                 *MaximumVariableSize
    502647  ); 
    503  
     648
     649/**
     650  Mark a variable that will become read-only after leaving the DXE phase of execution.
     651
     652  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
     653  @param[in] VariableName  A pointer to the variable name that will be made read-only subsequently.
     654  @param[in] VendorGuid    A pointer to the vendor GUID that will be made read-only subsequently.
     655
     656  @retval EFI_SUCCESS           The variable specified by the VariableName and the VendorGuid was marked
     657                                as pending to be read-only.
     658  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
     659                                Or VariableName is an empty string.
     660  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
     661                                already been signaled.
     662  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock request.
     663**/
     664EFI_STATUS
     665EFIAPI
     666VariableLockRequestToLock (
     667  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
     668  IN       CHAR16                       *VariableName,
     669  IN       EFI_GUID                     *VendorGuid
     670  );
     671
    504672extern VARIABLE_MODULE_GLOBAL  *mVariableModuleGlobal;
    505673
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c

    r48674 r58459  
    33  and volatile storage space and install variable architecture protocol.
    44
    5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
     5Copyright (C) 2013, Red Hat, Inc.
     6Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    67This program and the accompanying materials
    78are licensed and made available under the terms and conditions of the BSD License
     
    1718#include "AuthService.h"
    1819
    19 extern VARIABLE_STORE_HEADER        *mNvVariableCache;
    20 extern VARIABLE_INFO_ENTRY          *gVariableInfo;
    21 EFI_HANDLE                          mHandle                    = NULL;
    22 EFI_EVENT                           mVirtualAddressChangeEvent = NULL;
    23 EFI_EVENT                           mFtwRegistration           = NULL;
     20extern VARIABLE_STORE_HEADER   *mNvVariableCache;
     21extern VARIABLE_INFO_ENTRY     *gVariableInfo;
     22EFI_HANDLE                     mHandle                    = NULL;
     23EFI_EVENT                      mVirtualAddressChangeEvent = NULL;
     24EFI_EVENT                      mFtwRegistration           = NULL;
     25extern LIST_ENTRY              mLockedVariableList;
     26extern BOOLEAN                 mEndOfDxe;
     27EDKII_VARIABLE_LOCK_PROTOCOL   mVariableLock              = { VariableLockRequestToLock };
    2428
    2529/**
     
    219223  )
    220224{
     225  LIST_ENTRY     *Link;
     226  VARIABLE_ENTRY *Entry;
     227  EFI_STATUS     Status;
     228
    221229  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);
    222230  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);
     
    234242  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
    235243  EfiConvertPointer (0x0, (VOID **) &mHashCtx);
    236   EfiConvertPointer (0x0, (VOID **) &mStorageArea);
    237244  EfiConvertPointer (0x0, (VOID **) &mSerializationRuntimeBuffer);
    238245  EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
     246  EfiConvertPointer (0x0, (VOID **) &mPubKeyStore);
     247  EfiConvertPointer (0x0, (VOID **) &mCertDbStore);
     248
     249  //
     250  // in the list of locked variables, convert the name pointers first
     251  //
     252  for ( Link = GetFirstNode (&mLockedVariableList)
     253      ; !IsNull (&mLockedVariableList, Link)
     254      ; Link = GetNextNode (&mLockedVariableList, Link)
     255      ) {
     256    Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
     257    Status = EfiConvertPointer (0x0, (VOID **) &Entry->Name);
     258    ASSERT_EFI_ERROR (Status);
     259  }
     260  //
     261  // second, convert the list itself using UefiRuntimeLib
     262  //
     263  Status = EfiConvertList (0x0, &mLockedVariableList);
     264  ASSERT_EFI_ERROR (Status);
    239265}
    240266
     
    258284  )
    259285{
     286  //
     287  // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.
     288  //
     289  mEndOfDxe = TRUE;
    260290  ReclaimForOS ();
    261291  if (FeaturePcdGet (PcdVariableCollectStatistics)) {
     
    264294}
    265295
     296/**
     297  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
     298
     299  This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
     300
     301  @param  Event        Event whose notification function is being invoked.
     302  @param  Context      Pointer to the notification function's context.
     303
     304**/
     305VOID
     306EFIAPI
     307OnEndOfDxe (
     308  EFI_EVENT                               Event,
     309  VOID                                    *Context
     310  )
     311{
     312  mEndOfDxe = TRUE;
     313  if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) {
     314    ReclaimForOS ();
     315  }
     316}
    266317
    267318/**
     
    291342  EFI_PHYSICAL_ADDRESS                    VariableStoreBase;
    292343  UINT64                                  VariableStoreLength;
     344  UINTN                                   FtwMaxBlockSize;
    293345
    294346  //
     
    300352  }
    301353
     354  Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);
     355  if (!EFI_ERROR (Status)) {
     356    ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);
     357  }
     358
    302359  //
    303360  // Find the proper FVB protocol for variable.
     
    316373  // Mark the variable storage region of the FLASH as RUNTIME.
    317374  //
    318   VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
     375  VariableStoreBase   = NvStorageVariableBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageVariableBase))->HeaderLength);
    319376  VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size;
    320377  BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK);
     
    324381  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
    325382  if (EFI_ERROR (Status)) {
    326     DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
     383    DEBUG ((DEBUG_WARN, "Variable driver failed to get flash memory attribute.\n"));
    327384  } else {
    328385    Status = gDS->SetMemorySpaceAttributes (
     
    337394
    338395  Status = VariableWriteServiceInitialize ();
    339   ASSERT_EFI_ERROR (Status);
     396  if (EFI_ERROR (Status)) {
     397    DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));
     398  }
    340399
    341400  //
     
    379438  EFI_STATUS                            Status;
    380439  EFI_EVENT                             ReadyToBootEvent;
     440  EFI_EVENT                             EndOfDxeEvent;
    381441
    382442  Status = VariableCommonInitialize ();
     443  ASSERT_EFI_ERROR (Status);
     444
     445  Status = gBS->InstallMultipleProtocolInterfaces (
     446                  &mHandle,
     447                  &gEdkiiVariableLockProtocolGuid,
     448                  &mVariableLock,
     449                  NULL
     450                  );
    383451  ASSERT_EFI_ERROR (Status);
    384452
     
    429497             &ReadyToBootEvent
    430498             );
     499  ASSERT_EFI_ERROR (Status);
     500
     501  //
     502  // Register the event handling function to set the End Of DXE flag.
     503  //
     504  Status = gBS->CreateEventEx (
     505                  EVT_NOTIFY_SIGNAL,
     506                  TPL_NOTIFY,
     507                  OnEndOfDxe,
     508                  NULL,
     509                  &gEfiEndOfDxeEventGroupGuid,
     510                  &EndOfDxeEvent
     511                  );
     512  ASSERT_EFI_ERROR (Status);
    431513
    432514  return EFI_SUCCESS;
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf

    r48674 r58459  
    11## @file
    2 Component description file for Authenticated Variable module.
     2Provides authenticated variable service
    33#
    4 # Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
     4#  This module installs variable arch protocol and variable write arch protocol to provide
     5#  variable services: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo.
     6#
     7#  Caution: This module requires additional review when modified.
     8#  This driver will have external input - variable data.
     9#  This external input must be validated carefully to avoid security issues such as
     10#  buffer overflow or integer overflow.
     11#
     12# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
    513# This program and the accompanying materials
    614# are licensed and made available under the terms and conditions of the BSD License
     
    1422[Defines]
    1523  INF_VERSION                    = 0x00010005
    16   BASE_NAME                      = VariableRuntimeDxe
     24  BASE_NAME                      = VariableAuthRuntimeDxe
     25  MODULE_UNI_FILE                = VariableAuthRuntimeDxe.uni
    1726  FILE_GUID                      = 2226F30F-3D5B-402d-9936-A97184EB4516
    1827  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
     
    3544  AuthService.c
    3645  AuthService.h
     46  Measurement.c
    3747
    3848[Packages]
     
    5767  PlatformSecureLib
    5868  HobLib
     69  TpmMeasurementLib
    5970
    6071[Protocols]
    61   gEfiFirmwareVolumeBlockProtocolGuid           ## SOMETIMES_CONSUMES
    62   gEfiVariableWriteArchProtocolGuid             ## ALWAYS_PRODUCES
    63   gEfiVariableArchProtocolGuid                  ## ALWAYS_PRODUCES
    64   gEfiFaultTolerantWriteProtocolGuid            ## SOMETIMES_CONSUMES
     72  gEfiFirmwareVolumeBlockProtocolGuid           ## CONSUMES
     73  ## CONSUMES
     74  ## NOTIFY
     75  gEfiFaultTolerantWriteProtocolGuid
     76  gEfiVariableWriteArchProtocolGuid             ## PRODUCES
     77  gEfiVariableArchProtocolGuid                  ## PRODUCES
     78  gEdkiiVariableLockProtocolGuid                ## PRODUCES
     79
    6580
    6681[Guids]
    67   gEfiAuthenticatedVariableGuid                 ## PRODUCES ## Configuration Table Guid
    68   gEfiGlobalVariableGuid                        ## PRODUCES ## Variable Guid
    69   gEfiEventVirtualAddressChangeGuid             ## PRODUCES ## Event
    70   gEfiCertTypeRsa2048Sha256Guid
     82  ## PRODUCES             ## GUID # Variable store header
     83  ## CONSUMES             ## GUID # Variable store header
     84  ## SOMETIMES_CONSUMES   ## HOB
     85  ## SOMETIMES_PRODUCES   ## SystemTable
     86  gEfiAuthenticatedVariableGuid
     87 
     88  ## SOMETIMES_CONSUMES   ## Variable:L"PlatformLang"
     89  ## SOMETIMES_PRODUCES   ## Variable:L"PlatformLang"
     90  ## SOMETIMES_CONSUMES   ## Variable:L"Lang"
     91  ## SOMETIMES_PRODUCES   ## Variable:L"Lang"
     92  ## SOMETIMES_CONSUMES   ## Variable:L"HwErrRecSupport"
     93  ## CONSUMES             ## Variable:L"SetupMode"
     94  ## PRODUCES             ## Variable:L"SetupMode"
     95  ## SOMETIMES_CONSUMES   ## Variable:L"PK"
     96  ## SOMETIMES_CONSUMES   ## Variable:L"KEK"
     97  ## CONSUMES             ## Variable:L"SecureBoot"
     98  ## PRODUCES             ## Variable:L"SecureBoot"
     99  ## CONSUMES             ## Variable:L"SignatureSupport"
     100  ## PRODUCES             ## Variable:L"SignatureSupport" 
     101  ## PRODUCES             ## Variable:L"VendorKeys"
     102  gEfiGlobalVariableGuid
     103 
     104  ## SOMETIMES_CONSUMES   ## Variable:L"DB"
     105  ## SOMETIMES_CONSUMES   ## Variable:L"DBX"
    71106  gEfiImageSecurityDatabaseGuid
    72   gEfiCertX509Guid
    73   gEfiCertPkcs7Guid
    74   gEfiCertRsa2048Guid
     107 
     108  ## CONSUMES             ## Variable:L"SecureBootEnable"
     109  ## PRODUCES             ## Variable:L"SecureBootEnable"
    75110  gEfiSecureBootEnableDisableGuid
     111 
     112  ## CONSUMES             ## Variable:L"CustomMode"
     113  ## PRODUCES             ## Variable:L"CustomMode"
    76114  gEfiCustomModeEnableGuid
    77   gEfiSystemNvDataFvGuid                        ## CONSUMES
     115 
     116  ## CONSUMES             ## Variable:L"certdb"
     117  ## PRODUCES             ## Variable:L"certdb"
    78118  gEfiCertDbGuid
     119 
     120  ## CONSUMES             ## Variable:L"VendorKeysNv"
     121  ## PRODUCES             ## Variable:L"VendorKeysNv"
     122  gEfiVendorKeysNvGuid
     123
     124  gEfiEndOfDxeEventGroupGuid               ## CONSUMES               ## Event
     125  gEfiEventVirtualAddressChangeGuid        ## CONSUMES               ## Event
     126  gEfiCertTypeRsa2048Sha256Guid            ## SOMETIMES_CONSUMES     ## GUID     # Unique ID for the type of the certificate.
     127  gEfiCertPkcs7Guid                        ## SOMETIMES_CONSUMES     ## GUID     # Unique ID for the type of the certificate.
     128  gEfiCertX509Guid                         ## SOMETIMES_CONSUMES     ## GUID     # Unique ID for the type of the signature.
     129  gEfiSystemNvDataFvGuid                   ## CONSUMES               ## GUID
     130  gEfiHardwareErrorVariableGuid            ## SOMETIMES_CONSUMES     ## Variable:L"HwErrRec####"
     131  gEdkiiFaultTolerantWriteGuid             ## SOMETIMES_CONSUMES     ## HOB
    79132
    80133[Pcd]
    81   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
    82   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
    83   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
    84   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
    85   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
    86   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
    87   gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
     134  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize       ## CONSUMES
     135  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase       ## SOMETIMES_CONSUMES
     136  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64     ## CONSUMES
     137  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                  ## CONSUMES
     138  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize     ## CONSUMES
     139  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize                ## CONSUMES
     140  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                 ## CONSUMES
     141  gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe   ## CONSUMES
    88142
    89143[FeaturePcd]
    90   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics  ## SOMETIME_CONSUMES (statistic the information of variable.)
     144  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics        ## CONSUMES  # statistic the information of variable.
     145  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate       ## CONSUMES  # Auto update PlatformLang/Lang
    91146
    92147[Depex]
    93   gEfiFirmwareVolumeBlockProtocolGuid AND gEfiFaultTolerantWriteProtocolGuid
     148  TRUE
    94149
    95 # [Event]
    96 #   ##
    97 #   # Event will be signaled for VIRTUAL_ADDRESS_CHANGE event.
    98 #   #
    99 #   EVENT_TYPE_NOTIFY_SIGNAL                    ## PRODUCES
    100 #
    101 #
    102 
     150[UserExtensions.TianoCore."ExtraFiles"]
     151  VariableRuntimeDxeExtra.uni
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c

    r48674 r58459  
    44  to provide variable services.
    55
    6 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
     6  Caution: This module requires additional review when modified.
     7  This driver will have external input - variable data and communicate buffer in SMM mode.
     8  This external input must be validated carefully to avoid security issue like
     9  buffer overflow, integer overflow.
     10
     11  SmmVariableHandler() will receive untrusted input and do basic validation.
     12
     13  Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),
     14  VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),
     15  SmmVariableGetStatistics() should also do validation based on its own knowledge.
     16
     17Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
    718This program and the accompanying materials
    819are licensed and made available under the terms and conditions of the BSD License
     
    1829#include <Protocol/SmmFirmwareVolumeBlock.h>
    1930#include <Protocol/SmmFaultTolerantWrite.h>
     31#include <Protocol/SmmEndOfDxe.h>
     32
    2033#include <Library/SmmServicesTableLib.h>
     34#include <Library/SmmMemLib.h>
    2135
    2236#include <Guid/AuthenticatedVariableFormat.h>
     
    2943BOOLEAN                                              mAtRuntime              = FALSE;
    3044EFI_GUID                                             mZeroGuid               = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
    31  
     45UINT8                                                *mVariableBufferPayload = NULL;
     46UINTN                                                mVariableBufferPayloadSize;
     47extern BOOLEAN                                       mEndOfDxe;
     48extern BOOLEAN                                       mEnableLocking;
     49
     50/**
     51  SecureBoot Hook for SetVariable.
     52
     53  @param[in] VariableName                 Name of Variable to be found.
     54  @param[in] VendorGuid                   Variable vendor GUID.
     55
     56**/
     57VOID
     58EFIAPI
     59SecureBootHook (
     60  IN CHAR16                                 *VariableName,
     61  IN EFI_GUID                               *VendorGuid
     62  )
     63{
     64  return ;
     65}
     66
     67/**
     68
     69  This code sets variable in storage blocks (Volatile or Non-Volatile).
     70
     71  @param VariableName                     Name of Variable to be found.
     72  @param VendorGuid                       Variable vendor GUID.
     73  @param Attributes                       Attribute value of the variable found
     74  @param DataSize                         Size of Data found. If size is less than the
     75                                          data, this value contains the required size.
     76  @param Data                             Data pointer.
     77
     78  @return EFI_INVALID_PARAMETER           Invalid parameter.
     79  @return EFI_SUCCESS                     Set successfully.
     80  @return EFI_OUT_OF_RESOURCES            Resource not enough to set variable.
     81  @return EFI_NOT_FOUND                   Not found.
     82  @return EFI_WRITE_PROTECTED             Variable is read-only.
     83
     84**/
     85EFI_STATUS
     86EFIAPI
     87SmmVariableSetVariable (
     88  IN CHAR16                  *VariableName,
     89  IN EFI_GUID                *VendorGuid,
     90  IN UINT32                  Attributes,
     91  IN UINTN                   DataSize,
     92  IN VOID                    *Data
     93  )
     94{
     95  EFI_STATUS                 Status;
     96
     97  //
     98  // Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL.
     99  //
     100  mEnableLocking = FALSE;
     101  Status         = VariableServiceSetVariable (
     102                     VariableName,
     103                     VendorGuid,
     104                     Attributes,
     105                     DataSize,
     106                     Data
     107                     );
     108  mEnableLocking = TRUE;
     109  return Status;
     110}
     111
    32112EFI_SMM_VARIABLE_PROTOCOL      gSmmVariable = {
    33113  VariableServiceGetVariable,
    34114  VariableServiceGetNextVariableName,
    35   VariableServiceSetVariable,
     115  SmmVariableSetVariable,
    36116  VariableServiceQueryVariableInfo
    37117};
    38 
    39118
    40119/**
     
    233312  if (EFI_ERROR(Status)) {
    234313    *NumberHandles = 0;
     314    FreePool (*Buffer);
     315    *Buffer = NULL;
    235316  }
    236317
     
    241322/**
    242323  Get the variable statistics information from the information buffer pointed by gVariableInfo.
     324
     325  Caution: This function may be invoked at SMM runtime.
     326  InfoEntry and InfoSize are external input. Care must be taken to make sure not security issue at runtime.
    243327
    244328  @param[in, out]  InfoEntry    A pointer to the buffer of variable information entry.
     
    266350  UINTN                                                StatisticsInfoSize;
    267351  CHAR16                                               *InfoName;
     352  EFI_GUID                                             VendorGuid;
    268353 
    269354  if (InfoEntry == NULL) {
     
    277362
    278363  StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);
    279   if (*InfoSize < sizeof (VARIABLE_INFO_ENTRY)) {
     364  if (*InfoSize < StatisticsInfoSize) {
    280365    *InfoSize = StatisticsInfoSize;
    281366    return EFI_BUFFER_TOO_SMALL;
     
    283368  InfoName = (CHAR16 *)(InfoEntry + 1);
    284369
    285   if (CompareGuid (&InfoEntry->VendorGuid, &mZeroGuid)) {
     370  CopyGuid (&VendorGuid, &InfoEntry->VendorGuid);
     371
     372  if (CompareGuid (&VendorGuid, &mZeroGuid)) {
    286373    //
    287374    // Return the first variable info
     
    297384  //
    298385  while (VariableInfo != NULL) {
    299     if (CompareGuid (&VariableInfo->VendorGuid, &InfoEntry->VendorGuid)) {
     386    if (CompareGuid (&VariableInfo->VendorGuid, &VendorGuid)) {
    300387      NameLength = StrSize (VariableInfo->Name);
    301388      if (NameLength == StrSize (InfoName)) {
     
    339426  This SMI handler provides services for the variable wrapper driver.
    340427
     428  Caution: This function may receive untrusted input.
     429  This variable data and communicate buffer are external input, so this function will do basic validation.
     430  Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),
     431  VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),
     432  SmmVariableGetStatistics() should also do validation based on its own knowledge.
     433
    341434  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
    342435  @param[in]     RegisterContext Points to an optional handler context which was specified when the
     
    353446                                              be called.
    354447  @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.
    355   @retval EFI_INVALID_PARAMETER               Input parameter is invalid.
    356448
    357449**/
     
    371463  SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO     *QueryVariableInfo;
    372464  VARIABLE_INFO_ENTRY                              *VariableInfo;
     465  SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE           *VariableToLock;
    373466  UINTN                                            InfoSize;
    374 
    375   if (CommBuffer == NULL) {
    376     return EFI_INVALID_PARAMETER;
    377   }
    378 
     467  UINTN                                            NameBufferSize;
     468  UINTN                                            CommBufferPayloadSize;
     469  UINTN                                            TempCommBufferSize;
     470
     471  //
     472  // If input is invalid, stop processing this SMI
     473  //
     474  if (CommBuffer == NULL || CommBufferSize == NULL) {
     475    return EFI_SUCCESS;
     476  }
     477
     478  TempCommBufferSize = *CommBufferSize;
     479
     480  if (TempCommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
     481    DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n"));
     482    return EFI_SUCCESS;
     483  }
     484  CommBufferPayloadSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
     485  if (CommBufferPayloadSize > mVariableBufferPayloadSize) {
     486    DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));
     487    return EFI_SUCCESS;
     488  }
     489
     490  if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
     491    DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));
     492    return EFI_SUCCESS;
     493  }
     494 
    379495  SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer;
     496   
    380497  switch (SmmVariableFunctionHeader->Function) {
    381498    case SMM_VARIABLE_FUNCTION_GET_VARIABLE:
    382       SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data;     
     499      if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
     500        DEBUG ((EFI_D_ERROR, "GetVariable: SMM communication buffer size invalid!\n"));
     501        return EFI_SUCCESS;
     502      }
     503      //
     504      // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.
     505      //
     506      CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);
     507      SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;
     508      if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||
     509         ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {
     510        //
     511        // Prevent InfoSize overflow happen
     512        //
     513        Status = EFI_ACCESS_DENIED;
     514        goto EXIT;
     515      }
     516      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)
     517                 + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;
     518
     519      //
     520      // SMRAM range check already covered before
     521      //
     522      if (InfoSize > CommBufferPayloadSize) {
     523        DEBUG ((EFI_D_ERROR, "GetVariable: Data size exceed communication buffer size limit!\n"));
     524        Status = EFI_ACCESS_DENIED;
     525        goto EXIT;
     526      }
     527
     528      if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {
     529        //
     530        // Make sure VariableName is A Null-terminated string.
     531        //
     532        Status = EFI_ACCESS_DENIED;
     533        goto EXIT;
     534      }
     535
    383536      Status = VariableServiceGetVariable (
    384537                 SmmVariableHeader->Name,
     
    388541                 (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize
    389542                 );
     543      CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);
    390544      break;
    391545     
    392546    case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:
    393       GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) SmmVariableFunctionHeader->Data;
     547      if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
     548        DEBUG ((EFI_D_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));
     549        return EFI_SUCCESS;
     550      }
     551      //
     552      // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.
     553      //
     554      CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);
     555      GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) mVariableBufferPayload;
     556      if ((UINTN)(~0) - GetNextVariableName->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
     557        //
     558        // Prevent InfoSize overflow happen
     559        //
     560        Status = EFI_ACCESS_DENIED;
     561        goto EXIT;
     562      }
     563      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + GetNextVariableName->NameSize;
     564
     565      //
     566      // SMRAM range check already covered before
     567      //
     568      if (InfoSize > CommBufferPayloadSize) {
     569        DEBUG ((EFI_D_ERROR, "GetNextVariableName: Data size exceed communication buffer size limit!\n"));
     570        Status = EFI_ACCESS_DENIED;
     571        goto EXIT;
     572      }
     573
     574      NameBufferSize = CommBufferPayloadSize - OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);
     575      if (NameBufferSize < sizeof (CHAR16) || GetNextVariableName->Name[NameBufferSize/sizeof (CHAR16) - 1] != L'\0') {
     576        //
     577        // Make sure input VariableName is A Null-terminated string.
     578        //
     579        Status = EFI_ACCESS_DENIED;
     580        goto EXIT;
     581      }
     582
    394583      Status = VariableServiceGetNextVariableName (
    395584                 &GetNextVariableName->NameSize,
     
    397586                 &GetNextVariableName->Guid
    398587                 );
     588      CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);
    399589      break;
    400590     
    401591    case SMM_VARIABLE_FUNCTION_SET_VARIABLE:
    402       SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data;
     592      if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
     593        DEBUG ((EFI_D_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));
     594        return EFI_SUCCESS;
     595      }
     596      //
     597      // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.
     598      //
     599      CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);
     600      SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;
     601      if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||
     602         ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {
     603        //
     604        // Prevent InfoSize overflow happen
     605        //
     606        Status = EFI_ACCESS_DENIED;
     607        goto EXIT;
     608      }
     609      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)
     610                 + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;
     611
     612      //
     613      // SMRAM range check already covered before
     614      // Data buffer should not contain SMM range
     615      //
     616      if (InfoSize > CommBufferPayloadSize) {
     617        DEBUG ((EFI_D_ERROR, "SetVariable: Data size exceed communication buffer size limit!\n"));
     618        Status = EFI_ACCESS_DENIED;
     619        goto EXIT;
     620      }
     621
     622      if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {
     623        //
     624        // Make sure VariableName is A Null-terminated string.
     625        //
     626        Status = EFI_ACCESS_DENIED;
     627        goto EXIT;
     628      }
     629
    403630      Status = VariableServiceSetVariable (
    404631                 SmmVariableHeader->Name,
     
    411638     
    412639    case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:
     640      if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {
     641        DEBUG ((EFI_D_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));
     642        return EFI_SUCCESS;
     643      }
    413644      QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data;
     645 
    414646      Status = VariableServiceQueryVariableInfo (
    415647                 QueryVariableInfo->Attributes,
     
    421653
    422654    case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:
     655      mEndOfDxe = TRUE;
     656      if (AtRuntime()) {
     657        Status = EFI_UNSUPPORTED;
     658        break;
     659      }
    423660      ReclaimForOS ();
    424661      Status = EFI_SUCCESS;
     
    432669    case SMM_VARIABLE_FUNCTION_GET_STATISTICS:
    433670      VariableInfo = (VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data;
    434       InfoSize = *CommBufferSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data);
     671      InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
     672
     673      //
     674      // Do not need to check SmmVariableFunctionHeader->Data in SMRAM here.
     675      // It is covered by previous CommBuffer check
     676      //
     677     
     678      if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) {
     679        DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n"));
     680        Status = EFI_ACCESS_DENIED;
     681        goto EXIT;
     682      } 
     683
    435684      Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);
    436       *CommBufferSize = InfoSize + OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data);
     685      *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
    437686      break;
    438687
     688    case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:
     689      if (mEndOfDxe) {
     690        Status = EFI_ACCESS_DENIED;
     691      } else {
     692        VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data;
     693        Status = VariableLockRequestToLock (
     694                   NULL,
     695                   VariableToLock->Name,
     696                   &VariableToLock->Guid
     697                   );
     698      }
     699      break;
     700
    439701    default:
    440       ASSERT (FALSE);
    441702      Status = EFI_UNSUPPORTED;
    442703  }
    443704
     705EXIT:
     706
    444707  SmmVariableFunctionHeader->ReturnStatus = Status;
    445 
    446708  return EFI_SUCCESS;
    447709}
    448710
     711/**
     712  SMM END_OF_DXE protocol notification event handler.
     713
     714  @param  Protocol   Points to the protocol's unique identifier
     715  @param  Interface  Points to the interface instance
     716  @param  Handle     The handle on which the interface was installed
     717
     718  @retval EFI_SUCCESS   SmmEndOfDxeCallback runs successfully
     719
     720**/
     721EFI_STATUS
     722EFIAPI
     723SmmEndOfDxeCallback (
     724  IN CONST EFI_GUID                       *Protocol,
     725  IN VOID                                 *Interface,
     726  IN EFI_HANDLE                           Handle
     727  )
     728{
     729  DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n"));
     730  mEndOfDxe = TRUE;
     731  if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) {
     732    ReclaimForOS ();
     733  }
     734  return EFI_SUCCESS;
     735}
    449736
    450737/**
     
    474761  EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL   *FtwProtocol;
    475762  EFI_PHYSICAL_ADDRESS                    NvStorageVariableBase;
     763  UINTN                                   FtwMaxBlockSize;
    476764 
    477765  if (mVariableModuleGlobal->FvbInstance != NULL) {
     
    487775  }
    488776
     777  Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);
     778  if (!EFI_ERROR (Status)) {
     779    ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);
     780  }
     781
    489782  //
    490783  // Find the proper FVB protocol for variable.
     
    502795 
    503796  Status = VariableWriteServiceInitialize ();
    504   ASSERT_EFI_ERROR (Status);
     797  if (EFI_ERROR (Status)) {
     798    DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));
     799  }
    505800 
    506801  //
     
    541836  EFI_HANDLE                              VariableHandle;
    542837  VOID                                    *SmmFtwRegistration;
    543  
     838  VOID                                    *SmmEndOfDxeRegistration;
     839
    544840  //
    545841  // Variable initialize.
     
    560856  ASSERT_EFI_ERROR (Status);
    561857
     858  mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +
     859                               OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - sizeof (VARIABLE_HEADER);
     860
     861  Status = gSmst->SmmAllocatePool (
     862                    EfiRuntimeServicesData,
     863                    mVariableBufferPayloadSize,
     864                    (VOID **)&mVariableBufferPayload
     865                    );
     866  ASSERT_EFI_ERROR (Status);
     867
    562868  ///
    563869  /// Register SMM variable SMI handler
     
    579885 
    580886  //
     887  // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.
     888  //
     889  Status = gSmst->SmmRegisterProtocolNotify (
     890                    &gEfiSmmEndOfDxeProtocolGuid,
     891                    SmmEndOfDxeCallback,
     892                    &SmmEndOfDxeRegistration
     893                    );
     894  ASSERT_EFI_ERROR (Status);
     895
     896  //
    581897  // Register FtwNotificationEvent () notify function.
    582898  //
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf

    r48674 r58459  
    11## @file
    2 Component description file for SMM Authenticated Variable module.
     2Provides SMM authenticated variable service
    33#
    44#  This module installs SMM variable protocol into SMM protocol database,
     
    77#  Dxe driver that the SMM variable service is ready.
    88#  This module should be used with SMM Runtime DXE module together. The
    9 #  SMM Runtime DXE module would install variable arch protocol and variable
     9#  SMM Runtime DXE module installs variable arch protocol and variable
    1010#  write arch protocol based on SMM variable module.
    1111#
    12 # Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
     12#  Caution: This module requires additional review when modified.
     13#  This driver will have external input - variable data and communicate buffer in SMM mode.
     14#  This external input must be validated carefully to avoid security issues such as
     15#  buffer overflow or integer overflow.
     16#    The whole SMM authentication variable design relies on the integrity of flash part and SMM.
     17#  which is assumed to be protected by platform.  All variable code and metadata in flash/SMM Memory
     18#  may not be modified without authorization. If platform fails to protect these resources,
     19#  the authentication service provided in this driver will be broken, and the behavior is undefined.
     20#
     21# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
    1322# This program and the accompanying materials
    1423# are licensed and made available under the terms and conditions of the BSD License
     
    2231[Defines]
    2332  INF_VERSION                    = 0x00010005
    24   BASE_NAME                      = VariableSmm
     33  BASE_NAME                      = VariableAuthSmm
     34  MODULE_UNI_FILE                = VariableAuthSmm.uni
    2535  FILE_GUID                      = D34BDC5E-968A-40f5-A48C-E594F45AE211
    2636  MODULE_TYPE                    = DXE_SMM_DRIVER
     
    6373  PlatformSecureLib
    6474  HobLib
     75  SmmMemLib
    6576
    6677[Protocols]
    67   gEfiSmmFirmwareVolumeBlockProtocolGuid        ## SOMETIMES_CONSUMES
    68   gEfiSmmVariableProtocolGuid                   ## ALWAYS_PRODUCES
    69   gEfiSmmFaultTolerantWriteProtocolGuid         ## SOMETIMES_CONSUMES
     78  gEfiSmmFirmwareVolumeBlockProtocolGuid        ## CONSUMES
     79 
     80  ## PRODUCES
     81  ## UNDEFINED     # SmiHandlerRegister
     82  gEfiSmmVariableProtocolGuid
     83 
     84  ## CONSUMES
     85  ## NOTIFY 
     86  gEfiSmmFaultTolerantWriteProtocolGuid
     87  gEfiSmmEndOfDxeProtocolGuid              ## NOTIFY
    7088
    7189[Guids]
    72   gEfiAuthenticatedVariableGuid                 ## PRODUCES ## Configuration Table Guid
    73   gEfiGlobalVariableGuid                        ## PRODUCES ## Variable Guid
    74   gSmmVariableWriteGuid                         ## PRODUCES ## SMM Variable Write Guid
    75   gEfiCertTypeRsa2048Sha256Guid
     90  ## PRODUCES             ## GUID # Variable store header
     91  ## CONSUMES             ## GUID # Variable store header
     92  ## SOMETIMES_CONSUMES   ## HOB
     93  gEfiAuthenticatedVariableGuid
     94 
     95  ## SOMETIMES_CONSUMES   ## Variable:L"PlatformLang"
     96  ## SOMETIMES_PRODUCES   ## Variable:L"PlatformLang"
     97  ## SOMETIMES_CONSUMES   ## Variable:L"Lang"
     98  ## SOMETIMES_PRODUCES   ## Variable:L"Lang"
     99  ## SOMETIMES_CONSUMES   ## Variable:L"HwErrRecSupport"
     100  ## CONSUMES             ## Variable:L"SetupMode"
     101  ## PRODUCES             ## Variable:L"SetupMode"
     102  ## SOMETIMES_CONSUMES   ## Variable:L"PK"
     103  ## SOMETIMES_CONSUMES   ## Variable:L"KEK"
     104  ## CONSUMES             ## Variable:L"SecureBoot"
     105  ## PRODUCES             ## Variable:L"SecureBoot"
     106  ## CONSUMES             ## Variable:L"SignatureSupport"
     107  ## PRODUCES             ## Variable:L"SignatureSupport"
     108  ## PRODUCES             ## Variable:L"VendorKeys"
     109  gEfiGlobalVariableGuid
     110 
     111  ## SOMETIMES_CONSUMES   ## Variable:L"DB"
     112  ## SOMETIMES_CONSUMES   ## Variable:L"DBX"
    76113  gEfiImageSecurityDatabaseGuid
    77   gEfiCertX509Guid
    78   gEfiCertPkcs7Guid
    79   gEfiCertRsa2048Guid
     114 
     115  ## CONSUMES             ## Variable:L"SecureBootEnable"
     116  ## PRODUCES             ## Variable:L"SecureBootEnable"
    80117  gEfiSecureBootEnableDisableGuid
     118 
     119  ## CONSUMES             ## Variable:L"CustomMode"
     120  ## PRODUCES             ## Variable:L"CustomMode"
    81121  gEfiCustomModeEnableGuid
    82   gEfiSystemNvDataFvGuid                        ## CONSUMES
     122 
     123  ## CONSUMES             ## Variable:L"certdb"
     124  ## PRODUCES             ## Variable:L"certdb"
    83125  gEfiCertDbGuid
    84126
     127  ## CONSUMES             ## Variable:L"VendorKeysNv"
     128  ## PRODUCES             ## Variable:L"VendorKeysNv"
     129  gEfiVendorKeysNvGuid
     130   
     131  gSmmVariableWriteGuid                    ## PRODUCES               ## GUID        # Install protocol
     132  gEfiCertTypeRsa2048Sha256Guid            ## SOMETIMES_CONSUMES     ## GUID        # Unique ID for the format of the CertData.
     133  gEfiCertPkcs7Guid                        ## SOMETIMES_CONSUMES     ## GUID        # Unique ID for the format of the CertData.
     134  gEfiCertX509Guid                         ## SOMETIMES_CONSUMES     ## GUID        # Unique ID for the type of the signature.
     135  gEfiSystemNvDataFvGuid                   ## CONSUMES               ## GUID
     136  gEfiHardwareErrorVariableGuid            ## SOMETIMES_CONSUMES     ## Variable:L"HwErrRec####"
     137  gEdkiiFaultTolerantWriteGuid             ## SOMETIMES_CONSUMES     ## HOB
     138 
    85139[Pcd]
    86   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
    87   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
    88   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
    89   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
    90   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
    91   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
    92   gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
     140  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize       ## CONSUMES
     141  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase       ## SOMETIMES_CONSUMES
     142  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64     ## CONSUMES
     143  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                  ## CONSUMES
     144  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize     ## CONSUMES
     145  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize                ## CONSUMES
     146  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                 ## CONSUMES
     147  gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe   ## CONSUMES
    93148
    94149[FeaturePcd]
    95   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics  ## SOMETIME_CONSUMES (statistic the information of variable.)
     150  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics        ## CONSUMES  # statistic the information of variable.
     151  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate       ## CONSUMES  # Auto update PlatformLang/Lang
    96152
    97153[Depex]
    98154  TRUE
    99 
    100 
     155 
     156[UserExtensions.TianoCore."ExtraFiles"]
     157  VariableSmmExtra.uni
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c

    r48674 r58459  
    44  based on SMM variable module.
    55
    6 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
     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
     16Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
    717This program and the accompanying materials
    818are licensed and made available under the terms and conditions of the BSD License
     
    2030#include <Protocol/SmmCommunication.h>
    2131#include <Protocol/SmmVariable.h>
     32#include <Protocol/VariableLock.h>
    2233
    2334#include <Library/UefiBootServicesTableLib.h>
     
    4354UINT8                           *mVariableBufferPhysical    = NULL;
    4455UINTN                            mVariableBufferSize;
    45 
     56UINTN                            mVariableBufferPayloadSize;
     57EFI_LOCK                         mVariableServicesLock;
     58EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;
     59
     60/**
     61  SecureBoot Hook for SetVariable.
     62
     63  @param[in] VariableName                 Name of Variable to be found.
     64  @param[in] VendorGuid                   Variable vendor GUID.
     65
     66**/
     67VOID
     68EFIAPI
     69SecureBootHook (
     70  IN CHAR16                                 *VariableName,
     71  IN EFI_GUID                               *VendorGuid
     72  );
     73
     74/**
     75  Acquires lock only at boot time. Simply returns at runtime.
     76
     77  This is a temperary function that will be removed when
     78  EfiAcquireLock() in UefiLib can handle the call in UEFI
     79  Runtimer driver in RT phase.
     80  It calls EfiAcquireLock() at boot time, and simply returns
     81  at runtime.
     82
     83  @param  Lock         A pointer to the lock to acquire.
     84
     85**/
     86VOID
     87AcquireLockOnlyAtBootTime (
     88  IN EFI_LOCK                             *Lock
     89  )
     90{
     91  if (!EfiAtRuntime ()) {
     92    EfiAcquireLock (Lock);
     93  }
     94}
     95
     96/**
     97  Releases lock only at boot time. Simply returns at runtime.
     98
     99  This is a temperary function which will be removed when
     100  EfiReleaseLock() in UefiLib can handle the call in UEFI
     101  Runtimer driver in RT phase.
     102  It calls EfiReleaseLock() at boot time and simply returns
     103  at runtime.
     104
     105  @param  Lock         A pointer to the lock to release.
     106
     107**/
     108VOID
     109ReleaseLockOnlyAtBootTime (
     110  IN EFI_LOCK                             *Lock
     111  )
     112{
     113  if (!EfiAtRuntime ()) {
     114    EfiReleaseLock (Lock);
     115  }
     116}
    46117
    47118/**
     
    50121  The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
    51122  DataSize.
     123
     124  Caution: This function may receive untrusted input.
     125  The data size external input, so this function will validate it carefully to avoid buffer overflow.
    52126
    53127  @param[out]      DataPtr          Points to the data in the communicate buffer.
     
    116190}
    117191
     192/**
     193  Mark a variable that will become read-only after leaving the DXE phase of execution.
     194
     195  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
     196  @param[in] VariableName  A pointer to the variable name that will be made read-only subsequently.
     197  @param[in] VendorGuid    A pointer to the vendor GUID that will be made read-only subsequently.
     198
     199  @retval EFI_SUCCESS           The variable specified by the VariableName and the VendorGuid was marked
     200                                as pending to be read-only.
     201  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
     202                                Or VariableName is an empty string.
     203  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
     204                                already been signaled.
     205  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock request.
     206**/
     207EFI_STATUS
     208EFIAPI
     209VariableLockRequestToLock (
     210  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
     211  IN       CHAR16                       *VariableName,
     212  IN       EFI_GUID                     *VendorGuid
     213  )
     214{
     215  EFI_STATUS                                Status;
     216  UINTN                                     VariableNameSize;
     217  UINTN                                     PayloadSize;
     218  SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE    *VariableToLock;
     219
     220  if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
     221    return EFI_INVALID_PARAMETER;
     222  }
     223
     224  VariableNameSize = StrSize (VariableName);
     225  VariableToLock   = NULL;
     226
     227  //
     228  // If VariableName exceeds SMM payload limit. Return failure
     229  //
     230  if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {
     231    return EFI_INVALID_PARAMETER;
     232  }
     233
     234  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
     235
     236  //
     237  // Init the communicate buffer. The buffer data size is:
     238  // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
     239  //
     240  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize;
     241  Status = InitCommunicateBuffer ((VOID **) &VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE);
     242  if (EFI_ERROR (Status)) {
     243    goto Done;
     244  }
     245  ASSERT (VariableToLock != NULL);
     246
     247  CopyGuid (&VariableToLock->Guid, VendorGuid);
     248  VariableToLock->NameSize = VariableNameSize;
     249  CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize);
     250
     251  //
     252  // Send data to SMM.
     253  //
     254  Status = SendCommunicateBuffer (PayloadSize);
     255
     256Done:
     257  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
     258  return Status;
     259}
    118260
    119261/**
    120262  This code finds variable in storage blocks (Volatile or Non-Volatile).
     263
     264  Caution: This function may receive untrusted input.
     265  The data size is external input, so this function will validate it carefully to avoid buffer overflow.
    121266
    122267  @param[in]      VariableName       Name of Variable to be found.
     
    146291  UINTN                                     PayloadSize;
    147292  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE  *SmmVariableHeader;
     293  UINTN                                     TempDataSize;
     294  UINTN                                     VariableNameSize;
    148295
    149296  if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
     
    154301    return EFI_INVALID_PARAMETER;
    155302  }
    156  
     303
     304  TempDataSize          = *DataSize;
     305  VariableNameSize      = StrSize (VariableName);
     306  SmmVariableHeader     = NULL;
     307
     308  //
     309  // If VariableName exceeds SMM payload limit. Return failure
     310  //
     311  if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
     312    return EFI_INVALID_PARAMETER;
     313  }
     314
     315  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
     316
    157317  //
    158318  // Init the communicate buffer. The buffer data size is:
    159319  // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
    160320  //
    161   PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName);
     321  if (TempDataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize) {
     322    //
     323    // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size
     324    //
     325    TempDataSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize;
     326  }
     327  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + TempDataSize;
     328
    162329  Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
    163330  if (EFI_ERROR (Status)) {
    164     return Status;
     331    goto Done;
    165332  }
    166333  ASSERT (SmmVariableHeader != NULL);
    167334
    168335  CopyGuid (&SmmVariableHeader->Guid, VendorGuid);
    169   SmmVariableHeader->DataSize   = *DataSize;
    170   SmmVariableHeader->NameSize   = StrSize (VariableName);
     336  SmmVariableHeader->DataSize   = TempDataSize;
     337  SmmVariableHeader->NameSize   = VariableNameSize;
    171338  if (Attributes == NULL) {
    172339    SmmVariableHeader->Attributes = 0;
     
    184351  // Get data from SMM.
    185352  //
    186   *DataSize = SmmVariableHeader->DataSize;
     353  if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {
     354    //
     355    // SMM CommBuffer DataSize can be a trimed value
     356    // Only update DataSize when needed
     357    //
     358    *DataSize = SmmVariableHeader->DataSize;
     359  }
    187360  if (Attributes != NULL) {
    188361    *Attributes = SmmVariableHeader->Attributes;
     
    190363
    191364  if (EFI_ERROR (Status)) {
    192     return Status;
     365    goto Done;
    193366  }
    194367
    195368  CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);
    196369
     370Done:
     371  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
    197372  return Status;
    198373}
     
    223398  UINTN                                           PayloadSize;
    224399  SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;
     400  UINTN                                           OutVariableNameSize;
     401  UINTN                                           InVariableNameSize;
    225402
    226403  if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
    227404    return EFI_INVALID_PARAMETER;
    228405  }
    229  
     406
     407  OutVariableNameSize   = *VariableNameSize;
     408  InVariableNameSize    = StrSize (VariableName);
     409  SmmGetNextVariableName = NULL;
     410
     411  //
     412  // If input string exceeds SMM payload limit. Return failure
     413  //
     414  if (InVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
     415    return EFI_INVALID_PARAMETER;
     416  }
     417
     418  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
     419
    230420  //
    231421  // Init the communicate buffer. The buffer data size is:
    232422  // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
    233423  //
    234   PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + *VariableNameSize;
     424  if (OutVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
     425    //
     426    // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size
     427    //
     428    OutVariableNameSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);
     429  }
     430  //
     431  // Payload should be Guid + NameSize + MAX of Input & Output buffer
     432  //
     433  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize);
     434
    235435  Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
    236436  if (EFI_ERROR (Status)) {
    237     return Status;
     437    goto Done;
    238438  }
    239439  ASSERT (SmmGetNextVariableName != NULL);
    240440
    241   SmmGetNextVariableName->NameSize = *VariableNameSize;
     441  //
     442  // SMM comm buffer->NameSize is buffer size for return string
     443  //
     444  SmmGetNextVariableName->NameSize = OutVariableNameSize;
     445
    242446  CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);
    243   CopyMem (SmmGetNextVariableName->Name, VariableName, *VariableNameSize);
     447  //
     448  // Copy whole string
     449  //
     450  CopyMem (SmmGetNextVariableName->Name, VariableName, InVariableNameSize);
     451  if (OutVariableNameSize > InVariableNameSize) {
     452    ZeroMem ((UINT8 *) SmmGetNextVariableName->Name + InVariableNameSize, OutVariableNameSize - InVariableNameSize);
     453  }
    244454
    245455  //
     
    251461  // Get data from SMM.
    252462  //
    253   *VariableNameSize = SmmGetNextVariableName->NameSize;   
     463  if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {
     464    //
     465    // SMM CommBuffer NameSize can be a trimed value
     466    // Only update VariableNameSize when needed
     467    //
     468    *VariableNameSize = SmmGetNextVariableName->NameSize;
     469  }
    254470  if (EFI_ERROR (Status)) {
    255     return Status;
     471    goto Done;
    256472  }
    257473 
     
    259475  CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize); 
    260476
     477Done:
     478  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
    261479  return Status;
    262480}
     
    264482/**
    265483  This code sets variable in storage blocks (Volatile or Non-Volatile).
     484
     485  Caution: This function may receive untrusted input.
     486  The data size and data are external input, so this function will validate it carefully to avoid buffer overflow.
    266487
    267488  @param[in] VariableName                 Name of Variable to be found.
     
    292513  UINTN                                     PayloadSize;
    293514  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE  *SmmVariableHeader;
     515  UINTN                                     VariableNameSize;
    294516   
    295517  //
     
    303525    return EFI_INVALID_PARAMETER;
    304526  }
    305  
     527
     528  VariableNameSize      = StrSize (VariableName);
     529  SmmVariableHeader     = NULL;
     530
     531  //
     532  // If VariableName or DataSize exceeds SMM payload limit. Return failure
     533  //
     534  if ((VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||
     535      (DataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize)){
     536    return EFI_INVALID_PARAMETER;
     537  }
     538
     539  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
     540
    306541  //
    307542  // Init the communicate buffer. The buffer data size is:
    308543  // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
    309544  //
    310   PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + DataSize;
     545  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + DataSize;
    311546  Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);
    312547  if (EFI_ERROR (Status)) {
    313     return Status;
     548    goto Done;
    314549  }
    315550  ASSERT (SmmVariableHeader != NULL);
     
    317552  CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid);
    318553  SmmVariableHeader->DataSize   = DataSize;
    319   SmmVariableHeader->NameSize   = StrSize (VariableName);
     554  SmmVariableHeader->NameSize   = VariableNameSize;
    320555  SmmVariableHeader->Attributes = Attributes;
    321556  CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
     
    326561  //
    327562  Status = SendCommunicateBuffer (PayloadSize);
    328  
     563
     564Done:
     565  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
     566
     567  if (!EfiAtRuntime ()) {
     568    if (!EFI_ERROR (Status)) {
     569      SecureBootHook (
     570        VariableName,
     571        VendorGuid
     572        );
     573    }
     574  }
    329575  return Status;
    330576}
     
    361607  SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo;
    362608
     609  SmmQueryVariableInfo = NULL;
     610
    363611  if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
    364612    return EFI_INVALID_PARAMETER;
    365613  }
    366  
     614
     615  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
     616
    367617  //
    368618  // Init the communicate buffer. The buffer data size is:
     
    372622  Status = InitCommunicateBuffer ((VOID **)&SmmQueryVariableInfo, PayloadSize, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO);
    373623  if (EFI_ERROR (Status)) {
    374     return Status;
     624    goto Done;
    375625  }
    376626  ASSERT (SmmQueryVariableInfo != NULL);
     
    383633  Status = SendCommunicateBuffer (PayloadSize);
    384634  if (EFI_ERROR (Status)) {
    385     return Status;
     635    goto Done;
    386636  }
    387637
     
    392642  *MaximumVariableStorageSize   = SmmQueryVariableInfo->MaximumVariableStorageSize;
    393643  *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;
    394  
    395   return EFI_SUCCESS;
     644
     645Done:
     646  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
     647  return Status;
    396648}
    397649
     
    502754 
    503755  //
    504   // Allocate memory for variable store.
    505   //
    506   mVariableBufferSize  = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
    507   mVariableBufferSize += MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
     756  // Allocate memory for variable communicate buffer.
     757  //
     758  mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +
     759                               OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - sizeof (VARIABLE_HEADER);
     760  mVariableBufferSize  = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + mVariableBufferPayloadSize;
    508761  mVariableBuffer      = AllocateRuntimePool (mVariableBufferSize);
    509762  ASSERT (mVariableBuffer != NULL);
     
    586839  )
    587840{
     841  EFI_STATUS                                Status;
    588842  VOID                                      *SmmVariableRegistration;
    589843  VOID                                      *SmmVariableWriteRegistration;
    590844  EFI_EVENT                                 OnReadyToBootEvent;
    591845  EFI_EVENT                                 ExitBootServiceEvent;
    592  
     846
     847  EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);
     848
     849  mVariableLock.RequestToLock = VariableLockRequestToLock;
     850  Status = gBS->InstallMultipleProtocolInterfaces (
     851                  &mHandle,
     852                  &gEdkiiVariableLockProtocolGuid,
     853                  &mVariableLock,
     854                  NULL
     855                  );
     856  ASSERT_EFI_ERROR (Status);
     857
    593858  //
    594859  // Smm variable service is ready
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf

    r48674 r58459  
    11## @file
    2 Component description file for Authenticated Variable SmmRuntimeDxe module.
     2Runtime DXE part corresponding to SMM authenticated variable module
    33#
    4 #  This module is the Runtime DXE part correspond to SMM variable module. It
    5 #  installs variable arch protocol and variable write arch protocol and works
    6 #  with SMM variable module together.
     4#  This module installs variable arch protocol and variable write arch protocol to provide
     5#  variable service. This module need work together with SMM authenticated variable module.
    76#
    8 # Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
     7#  Caution: This module requires additional review when modified.
     8#  This driver will have external input - variable data.
     9#  This external input must be validated carefully to avoid security issues such as
     10#  buffer overflow or integer overflow.
     11#    The whole SMM authentication variable design relies on the integrity of flash part and SMM.
     12#  which is assumed to be protected by platform.  All variable code and metadata in flash/SMM Memory
     13#  may not be modified without authorization. If platform fails to protect these resources,
     14#  the authentication service provided in this driver will be broken, and the behavior is undefined.
     15#
     16# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
    917# This program and the accompanying materials
    1018# are licensed and made available under the terms and conditions of the BSD License
     
    1826[Defines]
    1927  INF_VERSION                    = 0x00010005
    20   BASE_NAME                      = VariableSmmRuntimeDxe
     28  BASE_NAME                      = VariableAuthSmmRuntimeDxe
     29  MODULE_UNI_FILE                = VariableAuthSmmRuntimeDxe.uni
    2130  FILE_GUID                      = 067E2381-7234-4798-B49C-D5FECBFF6D07
    2231  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
     
    3443[Sources]
    3544  VariableSmmRuntimeDxe.c
     45  Measurement.c
    3646
    3747[Packages]
     
    4959  UefiDriverEntryPoint
    5060  PcdLib 
     61  TpmMeasurementLib
    5162
    5263[Protocols]
    53   gEfiVariableWriteArchProtocolGuid             ## ALWAYS_PRODUCES
    54   gEfiVariableArchProtocolGuid                  ## ALWAYS_PRODUCES 
    55   gEfiSmmCommunicationProtocolGuid
     64  gEfiVariableWriteArchProtocolGuid                                 ## PRODUCES
     65  gEfiVariableArchProtocolGuid                                      ## PRODUCES
     66  gEfiSmmCommunicationProtocolGuid                                  ## CONSUMES
     67  gEdkiiVariableLockProtocolGuid                                    ## PRODUCES
     68
     69  ## CONSUMES
     70  ## NOTIFY
     71  ## UNDEFINED   # Used to do smm communication
    5672  gEfiSmmVariableProtocolGuid
    5773
    5874[Guids]
    59   gEfiEventVirtualAddressChangeGuid             ## PRODUCES ## Event
     75  gEfiEventVirtualAddressChangeGuid                                 ## CONSUMES       ## Event
     76  gEfiEventExitBootServicesGuid                                     ## CONSUMES       ## Event
     77   
     78  ## CONSUMES ## UNDEFINED # Locate protocol
     79  ## CONSUMES ## UNDEFINED # Protocol notify
    6080  gSmmVariableWriteGuid
     81 
     82
     83  ## SOMETIMES_CONSUMES   ## Variable:L"PK"
     84  ## SOMETIMES_CONSUMES   ## Variable:L"KEK"
     85  ## SOMETIMES_CONSUMES   ## Variable:L"SecureBoot"
     86  gEfiGlobalVariableGuid
     87 
     88  ## SOMETIMES_CONSUMES   ## Variable:L"DB"
     89  ## SOMETIMES_CONSUMES   ## Variable:L"DBX"
     90  gEfiImageSecurityDatabaseGuid
    6191
    6292[Pcd]
    63   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
    64   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
    65   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
    66  
     93  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                 ## CONSUMES
     94  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize    ## CONSUMES
     95  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase      ## CONSUMES
     96
    6797[Depex]
    6898  gEfiSmmCommunicationProtocolGuid
     99
     100[UserExtensions.TianoCore."ExtraFiles"]
     101  VariableSmmRuntimeDxeExtra.uni
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr

    r48674 r58459  
    22  VFR file used by the SecureBoot configuration component.
    33
    4 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
    55This program and the accompanying materials
    66are licensed and made available under the terms and conditions of the BSD License
     
    3333
    3434    subtitle text = STRING_TOKEN(STR_NULL);
    35    
     35
     36    text
     37      help   = STRING_TOKEN(STR_SECURE_BOOT_STATE_HELP),
     38      text   = STRING_TOKEN(STR_SECURE_BOOT_STATE_PROMPT),
     39        text   = STRING_TOKEN(STR_SECURE_BOOT_STATE_CONTENT);
     40       
    3641    //
    3742    // Define of Check Box: Attempt Secure Boot
     
    3944    suppressif TRUE;
    4045      checkbox varid   = SECUREBOOT_CONFIGURATION.HideSecureBoot,
     46              questionid = KEY_HIDE_SECURE_BOOT,
    4147              prompt   = STRING_TOKEN(STR_NULL),
    4248              help     = STRING_TOKEN(STR_NULL),
     49              flags    = INTERACTIVE,
    4350      endcheckbox;
    4451    endif; 
     
    4855    //
    4956    grayoutif ideqval SECUREBOOT_CONFIGURATION.HideSecureBoot == 1;
    50     checkbox varid = SECUREBOOT_CONFIGURATION.SecureBootState,
     57    checkbox varid = SECUREBOOT_CONFIGURATION.AttemptSecureBoot,
    5158          questionid = KEY_SECURE_BOOT_ENABLE,
    5259          prompt = STRING_TOKEN(STR_SECURE_BOOT_PROMPT),
    5360          help   = STRING_TOKEN(STR_SECURE_BOOT_HELP),
    54           flags  = INTERACTIVE,
     61          flags  = INTERACTIVE | RESET_REQUIRED,
    5562    endcheckbox;
    5663    endif;
     
    5966    // Display of Oneof: 'Secure Boot Mode'
    6067    //
    61     oneof varid  = SECUREBOOT_CONFIGURATION.SecureBootMode,
    62           questionid = KEY_SECURE_BOOT_MODE,     
    63           prompt = STRING_TOKEN(STR_SECURE_BOOT_MODE_PROMPT),
    64           help   = STRING_TOKEN(STR_SECURE_BOOT_MODE_HELP),
    65           flags  = INTERACTIVE,
    66           option text = STRING_TOKEN(STR_STANDARD_MODE),    value = SECURE_BOOT_MODE_STANDARD, flags = DEFAULT;
    67           option text = STRING_TOKEN(STR_CUSTOM_MODE),      value = SECURE_BOOT_MODE_CUSTOM,   flags = 0;
    68     endoneof;
     68    disableif TRUE;
     69      oneof varid  = SECUREBOOT_CONFIGURATION.SecureBootMode,
     70            prompt = STRING_TOKEN(STR_SECURE_BOOT_MODE_PROMPT),
     71            help   = STRING_TOKEN(STR_SECURE_BOOT_MODE_HELP),
     72            flags  = INTERACTIVE,
     73            option text = STRING_TOKEN(STR_STANDARD_MODE),    value = SECURE_BOOT_MODE_STANDARD, flags = 0;
     74            option text = STRING_TOKEN(STR_CUSTOM_MODE),      value = SECURE_BOOT_MODE_CUSTOM,   flags = 0;
     75      endoneof;
     76    endif;
     77      oneof name = SecureBootMode,
     78            questionid = KEY_SECURE_BOOT_MODE,     
     79            prompt = STRING_TOKEN(STR_SECURE_BOOT_MODE_PROMPT),
     80            help   = STRING_TOKEN(STR_SECURE_BOOT_MODE_HELP),
     81            flags  = INTERACTIVE | NUMERIC_SIZE_1,
     82            option text = STRING_TOKEN(STR_STANDARD_MODE),    value = SECURE_BOOT_MODE_STANDARD, flags = DEFAULT;
     83            option text = STRING_TOKEN(STR_CUSTOM_MODE),      value = SECURE_BOOT_MODE_CUSTOM,   flags = 0;
     84      endoneof;
    6985   
    7086    //
     
    7288    // Display of 'Current Secure Boot Mode'
    7389    //
    74     suppressif ideqval SECUREBOOT_CONFIGURATION.SecureBootMode == SECURE_BOOT_MODE_STANDARD;
     90    suppressif questionref(SecureBootMode) == SECURE_BOOT_MODE_STANDARD;
    7591      grayoutif NOT ideqval SECUREBOOT_CONFIGURATION.PhysicalPresent == 1;
    7692      goto FORMID_SECURE_BOOT_OPTION_FORM,
     
    159175          prompt = STRING_TOKEN(STR_DELETE_PK),         
    160176          help   = STRING_TOKEN(STR_DELETE_PK_HELP),
    161           flags  = INTERACTIVE,
     177          flags  = INTERACTIVE | RESET_REQUIRED,
    162178    endcheckbox;
    163179    endif;
     
    480496       help   = STRING_TOKEN(STR_SAVE_AND_EXIT),
    481497       text   = STRING_TOKEN(STR_SAVE_AND_EXIT),
    482        text   = STRING_TOKEN(STR_NULL),
    483498       flags  = INTERACTIVE,
    484499       key    = KEY_VALUE_SAVE_AND_EXIT_PK;
     
    487502       help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
    488503       text   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
    489        text   = STRING_TOKEN(STR_NULL),
    490504       flags  = INTERACTIVE,
    491505       key    = KEY_VALUE_NO_SAVE_AND_EXIT_PK;
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDevicePath.c

    r48674 r58459  
    22  Internal function defines the default device path string for SecureBoot configuration module.
    33
    4 Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
    55This program and the accompanying materials
    66are licensed and made available under the terms and conditions of the BSD License
     
    1414
    1515#include "SecureBootConfigImpl.h"
    16 
    17 /**
    18   Concatenates a formatted unicode string to allocated pool.
    19   The caller must free the resulting buffer.
    20 
    21   @param[in, out]  Str      Tracks the allocated pool, size in use, and amount of pool allocated.
    22   @param[in]       Fmt      The format string
    23   @param[in]       ...      The data will be printed.
    24 
    25   @return Allocated buffer with the formatted string printed in it.
    26           The caller must free the allocated buffer.
    27           The buffer allocation is not packed.
    28 
    29 **/
    30 CHAR16 *
    31 EFIAPI
    32 CatPrint (
    33   IN OUT POOL_PRINT   *Str,
    34   IN CHAR16           *Fmt,
    35   ...
    36   )
    37 {
    38   UINT16  *AppendStr;
    39   VA_LIST Args;
    40   UINTN   StringSize;
    41 
    42   AppendStr = AllocateZeroPool (0x1000);
    43   if (AppendStr == NULL) {
    44     return Str->Str;
    45   }
    46 
    47   VA_START (Args, Fmt);
    48   UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args);
    49   VA_END (Args);
    50   if (NULL == Str->Str) {
    51     StringSize   = StrSize (AppendStr);
    52     Str->Str  = AllocateZeroPool (StringSize);
    53     ASSERT (Str->Str != NULL);
    54   } else {
    55     StringSize = StrSize (AppendStr);
    56     StringSize += (StrSize (Str->Str) - sizeof (UINT16));
    57 
    58     Str->Str = ReallocatePool (
    59                 StrSize (Str->Str),
    60                 StringSize,
    61                 Str->Str
    62                 );
    63     ASSERT (Str->Str != NULL);
    64   }
    65 
    66   Str->Maxlen = MAX_CHAR * sizeof (UINT16);
    67   if (StringSize < Str->Maxlen) {
    68     StrCat (Str->Str, AppendStr);
    69     Str->Len = StringSize - sizeof (UINT16);
    70   }
    71 
    72   FreePool (AppendStr);
    73   return Str->Str;
    74 }
    75 
    76 /**
    77   Convert Device Path to a Unicode string for printing.
    78 
    79   @param[in, out] Str           The buffer holding the output string.
    80                                 This buffer contains the length of the string and
    81                                 the maixmum length reserved for the string buffer.
    82   @param[in]      DevPath       The device path.
    83 
    84 **/
    85 VOID
    86 DevPathPci (
    87   IN OUT POOL_PRINT       *Str,
    88   IN VOID                 *DevPath
    89   )
    90 {
    91   PCI_DEVICE_PATH *Pci;
    92 
    93   Pci = DevPath;
    94   CatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function);
    95 }
    96 
    97 /**
    98   Convert Device Path to a Unicode string for printing.
    99 
    100   @param[in, out] Str           The buffer holding the output string.
    101                                 This buffer contains the length of the string and
    102                                 the maixmum length reserved for the string buffer.
    103   @param[in]      DevPath       The device path.
    104 
    105 **/
    106 VOID
    107 DevPathPccard (
    108   IN OUT POOL_PRINT       *Str,
    109   IN VOID                 *DevPath
    110   )
    111 {
    112   PCCARD_DEVICE_PATH  *Pccard;
    113 
    114   Pccard = DevPath;
    115   CatPrint (Str, L"Pcmcia(Function%x)", (UINTN) Pccard->FunctionNumber);
    116 }
    117 
    118 /**
    119   Convert Device Path to a Unicode string for printing.
    120 
    121   @param[in, out] Str           The buffer holding the output string.
    122                                 This buffer contains the length of the string and
    123                                 the maixmum length reserved for the string buffer.
    124   @param[in]      DevPath       The device path.
    125 
    126 **/
    127 VOID
    128 DevPathMemMap (
    129   IN OUT POOL_PRINT       *Str,
    130   IN VOID                 *DevPath
    131   )
    132 {
    133   MEMMAP_DEVICE_PATH  *MemMap;
    134 
    135   MemMap = DevPath;
    136   CatPrint (
    137     Str,
    138     L"MemMap(%d:%lx-%lx)",
    139     (UINTN) MemMap->MemoryType,
    140     MemMap->StartingAddress,
    141     MemMap->EndingAddress
    142     );
    143 }
    144 
    145 /**
    146   Convert Device Path to a Unicode string for printing.
    147 
    148   @param[in, out] Str           The buffer holding the output string.
    149                                 This buffer contains the length of the string and
    150                                 the maixmum length reserved for the string buffer.
    151   @param[in]      DevPath       The device path.
    152 
    153 **/
    154 VOID
    155 DevPathController (
    156   IN OUT POOL_PRINT       *Str,
    157   IN VOID                 *DevPath
    158   )
    159 {
    160   CONTROLLER_DEVICE_PATH  *Controller;
    161 
    162   Controller = DevPath;
    163   CatPrint (Str, L"Ctrl(%d)", (UINTN) Controller->ControllerNumber);
    164 }
    165 
    166 
    167 /**
    168   Convert Vendor device path to device name.
    169 
    170   @param[in, out]  Str      The buffer store device name
    171   @param[in]       DevPath  Pointer to vendor device path
    172 
    173 **/
    174 VOID
    175 DevPathVendor (
    176   IN OUT POOL_PRINT       *Str,
    177   IN VOID                 *DevPath
    178   )
    179 {
    180   VENDOR_DEVICE_PATH  *Vendor;
    181   CHAR16              *Type;
    182   UINTN               DataLength;
    183   UINTN               Index;
    184   UINT32              FlowControlMap;
    185 
    186   UINT16              Info;
    187 
    188   Vendor  = DevPath;
    189 
    190   switch (DevicePathType (&Vendor->Header)) {
    191   case HARDWARE_DEVICE_PATH:
    192     Type = L"Hw";
    193     break;
    194 
    195   case MESSAGING_DEVICE_PATH:
    196     Type = L"Msg";
    197     if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {
    198       CatPrint (Str, L"VenPcAnsi()");
    199       return ;
    200     } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {
    201       CatPrint (Str, L"VenVt100()");
    202       return ;
    203     } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {
    204       CatPrint (Str, L"VenVt100Plus()");
    205       return ;
    206     } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {
    207       CatPrint (Str, L"VenUft8()");
    208       return ;
    209     } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid     )) {
    210       FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);
    211       switch (FlowControlMap & 0x00000003) {
    212       case 0:
    213         CatPrint (Str, L"UartFlowCtrl(%s)", L"None");
    214         break;
    215 
    216       case 1:
    217         CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");
    218         break;
    219 
    220       case 2:
    221         CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");
    222         break;
    223 
    224       default:
    225         break;
    226       }
    227 
    228       return ;
    229 
    230     } else if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) {
    231       CatPrint (
    232         Str,
    233         L"SAS(%lx,%lx,%x,",
    234         ((SAS_DEVICE_PATH *) Vendor)->SasAddress,
    235         ((SAS_DEVICE_PATH *) Vendor)->Lun,
    236         (UINTN) ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort
    237         );
    238       Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);
    239       if ((Info & 0x0f) == 0) {
    240         CatPrint (Str, L"NoTopology,0,0,0,");
    241       } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {
    242         CatPrint (
    243           Str,
    244           L"%s,%s,%s,",
    245           ((Info & (0x1 << 4)) != 0) ? L"SATA" : L"SAS",
    246           ((Info & (0x1 << 5)) != 0) ? L"External" : L"Internal",
    247           ((Info & (0x1 << 6)) != 0) ? L"Expanded" : L"Direct"
    248           );
    249         if ((Info & 0x0f) == 1) {
    250           CatPrint (Str, L"0,");
    251         } else {
    252           CatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff));
    253         }
    254       } else {
    255         CatPrint (Str, L"0,0,0,0,");
    256       }
    257 
    258       CatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved);
    259       return ;
    260 
    261     } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {
    262       CatPrint (Str, L"DebugPort()");
    263       return ;
    264     }
    265     break;
    266 
    267   case MEDIA_DEVICE_PATH:
    268     Type = L"Media";
    269     break;
    270 
    271   default:
    272     Type = L"?";
    273     break;
    274   }
    275 
    276   CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid);
    277   DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);
    278   if (DataLength > 0) {
    279     CatPrint (Str, L",");
    280     for (Index = 0; Index < DataLength; Index++) {
    281       CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);
    282     }
    283   }
    284   CatPrint (Str, L")");
    285 }
    286 
    287 /**
    288   Convert Device Path to a Unicode string for printing.
    289 
    290   @param[in, out] Str           The buffer holding the output string.
    291                                 This buffer contains the length of the string and
    292                                 the maixmum length reserved for the string buffer.
    293   @param[in]      DevPath       The device path.
    294 
    295 **/
    296 VOID
    297 DevPathAcpi (
    298   IN OUT POOL_PRINT       *Str,
    299   IN VOID                 *DevPath
    300   )
    301 {
    302   ACPI_HID_DEVICE_PATH  *Acpi;
    303 
    304   Acpi = DevPath;
    305   if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
    306     CatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN)  EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID);
    307   } else {
    308     CatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID);
    309   }
    310 }
    311 
    312 /**
    313   Convert Device Path to a Unicode string for printing.
    314 
    315   @param[in, out] Str           The buffer holding the output string.
    316                                 This buffer contains the length of the string and
    317                                 the maixmum length reserved for the string buffer.
    318   @param[in]      DevPath       The device path.
    319 
    320 **/
    321 VOID
    322 DevPathExtendedAcpi (
    323   IN OUT POOL_PRINT       *Str,
    324   IN VOID                 *DevPath
    325   )
    326 {
    327   ACPI_EXTENDED_HID_DEVICE_PATH   *ExtendedAcpi;
    328  
    329   //
    330   // Index for HID, UID and CID strings, 0 for non-exist
    331   //
    332   UINT16                          HIDSTRIdx;
    333   UINT16                          UIDSTRIdx;
    334   UINT16                          CIDSTRIdx;
    335   UINT16                          Index;
    336   UINT16                          Length;
    337   UINT16                          Anchor;
    338   CHAR8                           *AsChar8Array;
    339 
    340   HIDSTRIdx    = 0;
    341   UIDSTRIdx    = 0;
    342   CIDSTRIdx    = 0;
    343   ExtendedAcpi = DevPath;
    344   Length       = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) ExtendedAcpi);
    345 
    346   AsChar8Array = (CHAR8 *) ExtendedAcpi;
    347 
    348   //
    349   // find HIDSTR
    350   //
    351   Anchor = 16;
    352   for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {
    353     ;
    354   }
    355   if (Index > Anchor) {
    356     HIDSTRIdx = Anchor;
    357   }
    358   //
    359   // find UIDSTR
    360   //
    361   Anchor = (UINT16) (Index + 1);
    362   for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {
    363     ;
    364   }
    365   if (Index > Anchor) {
    366     UIDSTRIdx = Anchor;
    367   }
    368   //
    369   // find CIDSTR
    370   //
    371   Anchor = (UINT16) (Index + 1);
    372   for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {
    373     ;
    374   }
    375   if (Index > Anchor) {
    376     CIDSTRIdx = Anchor;
    377   }
    378 
    379   if (HIDSTRIdx == 0 && CIDSTRIdx == 0 && ExtendedAcpi->UID == 0) {
    380     CatPrint (Str, L"AcpiExp(");
    381     if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
    382       CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));
    383     } else {
    384       CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);
    385     }
    386     if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
    387       CatPrint (Str, L"PNP%04x,", (UINTN)  EISA_ID_TO_NUM (ExtendedAcpi->CID));
    388     } else {
    389       CatPrint (Str, L"%08x,", (UINTN)  ExtendedAcpi->CID);
    390     }
    391     if (UIDSTRIdx != 0) {
    392       CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);
    393     } else {
    394       CatPrint (Str, L"\"\")");
    395     }
    396   } else {
    397     CatPrint (Str, L"AcpiEx(");
    398     if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
    399       CatPrint (Str, L"PNP%04x,", (UINTN)  EISA_ID_TO_NUM (ExtendedAcpi->HID));
    400     } else {
    401       CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);
    402     }
    403     if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
    404       CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));
    405     } else {
    406       CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);
    407     }
    408     CatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID);
    409 
    410     if (HIDSTRIdx != 0) {
    411       CatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx);
    412     } else {
    413       CatPrint (Str, L"\"\",");
    414     }
    415     if (CIDSTRIdx != 0) {
    416       CatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx);
    417     } else {
    418       CatPrint (Str, L"\"\",");
    419     }
    420     if (UIDSTRIdx != 0) {
    421       CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);
    422     } else {
    423       CatPrint (Str, L"\"\")");
    424     }
    425   }
    426 
    427 }
    428 
    429 /**
    430   Convert Device Path to a Unicode string for printing.
    431 
    432   @param[in, out] Str           The buffer holding the output string.
    433                                 This buffer contains the length of the string and
    434                                 the maixmum length reserved for the string buffer.
    435   @param[in]      DevPath       The device path.
    436 
    437 **/
    438 VOID
    439 DevPathAdrAcpi (
    440   IN OUT POOL_PRINT       *Str,
    441   IN VOID                 *DevPath
    442   )
    443 {
    444   ACPI_ADR_DEVICE_PATH    *AcpiAdr;
    445   UINT16                  Index;
    446   UINT16                  Length;
    447   UINT16                  AdditionalAdrCount;
    448 
    449   AcpiAdr            = DevPath;
    450   Length             = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);
    451   AdditionalAdrCount = (UINT16) ((Length - 8) / 4);
    452 
    453   CatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR);
    454   for (Index = 0; Index < AdditionalAdrCount; Index++) {
    455     CatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4));
    456   }
    457   CatPrint (Str, L")");
    458 }
    459 
    460 /**
    461   Convert Device Path to a Unicode string for printing.
    462 
    463   @param[in, out] Str           The buffer holding the output string.
    464                                 This buffer contains the length of the string and
    465                                 the maixmum length reserved for the string buffer.
    466   @param[in]      DevPath       The device path.
    467 
    468 **/
    469 VOID
    470 DevPathAtapi (
    471   IN OUT POOL_PRINT       *Str,
    472   IN VOID                 *DevPath
    473   )
    474 {
    475   ATAPI_DEVICE_PATH *Atapi;
    476 
    477   Atapi = DevPath;
    478   CatPrint (
    479     Str,
    480     L"Ata(%s,%s)",
    481     (Atapi->PrimarySecondary != 0)? L"Secondary" : L"Primary",
    482     (Atapi->SlaveMaster != 0)? L"Slave" : L"Master"
    483     );
    484 }
    485 
    486 /**
    487   Convert Device Path to a Unicode string for printing.
    488 
    489   @param[in, out] Str           The buffer holding the output string.
    490                                 This buffer contains the length of the string and
    491                                 the maixmum length reserved for the string buffer.
    492   @param[in]      DevPath       The device path.
    493 
    494 **/
    495 VOID
    496 DevPathScsi (
    497   IN OUT POOL_PRINT       *Str,
    498   IN VOID                 *DevPath
    499   )
    500 {
    501   SCSI_DEVICE_PATH  *Scsi;
    502 
    503   Scsi = DevPath;
    504   CatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun);
    505 }
    506 
    507 /**
    508   Convert Device Path to a Unicode string for printing.
    509 
    510   @param[in, out] Str           The buffer holding the output string.
    511                                 This buffer contains the length of the string and
    512                                 the maixmum length reserved for the string buffer.
    513   @param[in]      DevPath       The device path.
    514  
    515 **/
    516 VOID
    517 DevPathFibre (
    518   IN OUT POOL_PRINT       *Str,
    519   IN VOID                 *DevPath
    520   )
    521 {
    522   FIBRECHANNEL_DEVICE_PATH  *Fibre;
    523 
    524   Fibre = DevPath;
    525   CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun);
    526 }
    527 
    528 /**
    529   Convert Device Path to a Unicode string for printing.
    530 
    531   @param[in, out] Str           The buffer holding the output string.
    532                                 This buffer contains the length of the string and
    533                                 the maixmum length reserved for the string buffer.
    534   @param[in]      DevPath       The device path.
    535 
    536 **/
    537 VOID
    538 DevPath1394 (
    539   IN OUT POOL_PRINT       *Str,
    540   IN VOID                 *DevPath
    541   )
    542 {
    543   F1394_DEVICE_PATH *F1394Path;
    544 
    545   F1394Path = DevPath;
    546   CatPrint (Str, L"1394(%lx)", &F1394Path->Guid);
    547 }
    548 
    549 /**
    550   Convert Device Path to a Unicode string for printing.
    551 
    552   @param[in, out] Str           The buffer holding the output string.
    553                                 This buffer contains the length of the string and
    554                                 the maixmum length reserved for the string buffer.
    555   @param[in]      DevPath       The device path.
    556  
    557 **/
    558 VOID
    559 DevPathUsb (
    560   IN OUT POOL_PRINT       *Str,
    561   IN VOID                 *DevPath
    562   )
    563 {
    564   USB_DEVICE_PATH *Usb;
    565 
    566   Usb = DevPath;
    567   CatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber);
    568 }
    569 
    570 /**
    571   Convert Device Path to a Unicode string for printing.
    572 
    573   @param[in, out] Str           The buffer holding the output string.
    574                                 This buffer contains the length of the string and
    575                                 the maixmum length reserved for the string buffer.
    576   @param[in]      DevPath       The device path.
    577 
    578 **/
    579 VOID
    580 DevPathUsbWWID (
    581   IN OUT POOL_PRINT       *Str,
    582   IN VOID                 *DevPath
    583   )
    584 {
    585   USB_WWID_DEVICE_PATH  *UsbWWId;
    586 
    587   UsbWWId = DevPath;
    588   CatPrint (
    589     Str,
    590     L"UsbWwid(%x,%x,%x,\"WWID\")",
    591     (UINTN) UsbWWId->VendorId,
    592     (UINTN) UsbWWId->ProductId,
    593     (UINTN) UsbWWId->InterfaceNumber
    594     );
    595 }
    596 
    597 /**
    598   Convert Device Path to a Unicode string for printing.
    599 
    600   @param[in, out] Str           The buffer holding the output string.
    601                                 This buffer contains the length of the string and
    602                                 the maixmum length reserved for the string buffer.
    603   @param[in]      DevPath       The device path.
    604 
    605 **/
    606 VOID
    607 DevPathLogicalUnit (
    608   IN OUT POOL_PRINT       *Str,
    609   IN VOID                 *DevPath
    610   )
    611 {
    612   DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
    613 
    614   LogicalUnit = DevPath;
    615   CatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun);
    616 }
    617 
    618 /**
    619   Convert Device Path to a Unicode string for printing.
    620 
    621   @param[in, out] Str           The buffer holding the output string.
    622                                 This buffer contains the length of the string and
    623                                 the maixmum length reserved for the string buffer.
    624   @param[in]      DevPath       The device path.
    625 
    626 **/
    627 VOID
    628 DevPathUsbClass (
    629   IN OUT POOL_PRINT       *Str,
    630   IN VOID                 *DevPath
    631   )
    632 {
    633   USB_CLASS_DEVICE_PATH *UsbClass;
    634 
    635   UsbClass = DevPath;
    636   CatPrint (
    637     Str,
    638     L"Usb Class(%x,%x,%x,%x,%x)",
    639     (UINTN) UsbClass->VendorId,
    640     (UINTN) UsbClass->ProductId,
    641     (UINTN) UsbClass->DeviceClass,
    642     (UINTN) UsbClass->DeviceSubClass,
    643     (UINTN) UsbClass->DeviceProtocol
    644     );
    645 }
    646 
    647 /**
    648   Convert Device Path to a Unicode string for printing.
    649 
    650   @param[in, out] Str           The buffer holding the output string.
    651                                 This buffer contains the length of the string and
    652                                 the maixmum length reserved for the string buffer.
    653   @param[in]      DevPath       The device path.
    654 
    655 **/
    656 VOID
    657 DevPathSata (
    658   IN OUT POOL_PRINT       *Str,
    659   IN VOID                 *DevPath
    660   )
    661 {
    662   SATA_DEVICE_PATH *Sata;
    663 
    664   Sata = DevPath;
    665   if ((Sata->PortMultiplierPortNumber & SATA_HBA_DIRECT_CONNECT_FLAG) != 0) {
    666     CatPrint (
    667       Str,
    668       L"Sata(%x,%x)",
    669       (UINTN) Sata->HBAPortNumber,
    670       (UINTN) Sata->Lun
    671       );
    672   } else {
    673     CatPrint (
    674       Str,
    675       L"Sata(%x,%x,%x)",
    676       (UINTN) Sata->HBAPortNumber,
    677       (UINTN) Sata->PortMultiplierPortNumber,
    678       (UINTN) Sata->Lun
    679       );
    680   }
    681 }
    682 
    683 /**
    684   Convert Device Path to a Unicode string for printing.
    685 
    686   @param[in, out] Str           The buffer holding the output string.
    687                                 This buffer contains the length of the string and
    688                                 the maixmum length reserved for the string buffer.
    689   @param[in]      DevPath       The device path.
    690 
    691 **/
    692 VOID
    693 DevPathI2O (
    694   IN OUT POOL_PRINT       *Str,
    695   IN VOID                 *DevPath
    696   )
    697 {
    698   I2O_DEVICE_PATH *I2OPath;
    699 
    700   I2OPath = DevPath;
    701   CatPrint (Str, L"I2O(%x)", (UINTN) I2OPath->Tid);
    702 }
    703 
    704 /**
    705   Convert Device Path to a Unicode string for printing.
    706 
    707   @param[in, out] Str           The buffer holding the output string.
    708                                 This buffer contains the length of the string and
    709                                 the maixmum length reserved for the string buffer.
    710   @param[in]      DevPath       The device path.
    711 
    712 **/
    713 VOID
    714 DevPathMacAddr (
    715   IN OUT POOL_PRINT       *Str,
    716   IN VOID                 *DevPath
    717   )
    718 {
    719   MAC_ADDR_DEVICE_PATH  *MACDevPath;
    720   UINTN                 HwAddressSize;
    721   UINTN                 Index;
    722 
    723   MACDevPath           = DevPath;
    724 
    725   HwAddressSize = sizeof (EFI_MAC_ADDRESS);
    726   if (MACDevPath->IfType == 0x01 || MACDevPath->IfType == 0x00) {
    727     HwAddressSize = 6;
    728   }
    729 
    730   CatPrint (Str, L"Mac(");
    731 
    732   for (Index = 0; Index < HwAddressSize; Index++) {
    733     CatPrint (Str, L"%02x", (UINTN) MACDevPath->MacAddress.Addr[Index]);
    734   }
    735 
    736   CatPrint (Str, L")");
    737 }
    738 
    739 /**
    740   Convert Device Path to a Unicode string for printing.
    741 
    742   @param[in, out] Str           The buffer holding the output string.
    743                                 This buffer contains the length of the string and
    744                                 the maixmum length reserved for the string buffer.
    745   @param[in]      DevPath       The device path.
    746 
    747 **/
    748 VOID
    749 DevPathIPv4 (
    750   IN OUT POOL_PRINT       *Str,
    751   IN VOID                 *DevPath
    752   )
    753 {
    754   IPv4_DEVICE_PATH  *IPDevPath;
    755 
    756   IPDevPath = DevPath;
    757   CatPrint (
    758     Str,
    759     L"IPv4(%d.%d.%d.%d:%d)",
    760     (UINTN) IPDevPath->RemoteIpAddress.Addr[0],
    761     (UINTN) IPDevPath->RemoteIpAddress.Addr[1],
    762     (UINTN) IPDevPath->RemoteIpAddress.Addr[2],
    763     (UINTN) IPDevPath->RemoteIpAddress.Addr[3],
    764     (UINTN) IPDevPath->RemotePort
    765     );
    766 }
    767 
    768 /**
    769   Convert Device Path to a Unicode string for printing.
    770 
    771   @param[in, out] Str           The buffer holding the output string.
    772                                 This buffer contains the length of the string and
    773                                 the maixmum length reserved for the string buffer.
    774   @param[in]      DevPath       The device path.
    775 
    776 **/
    777 VOID
    778 DevPathIPv6 (
    779   IN OUT POOL_PRINT       *Str,
    780   IN VOID                 *DevPath
    781   )
    782 {
    783   IPv6_DEVICE_PATH  *IPv6DevPath;
    784 
    785   IPv6DevPath = DevPath;
    786   CatPrint (
    787     Str,
    788     L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",
    789     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[0],
    790     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[1],
    791     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[2],
    792     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[3],
    793     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[4],
    794     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[5],
    795     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[6],
    796     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[7],
    797     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[8],
    798     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[9],
    799     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[10],
    800     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[11],
    801     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[12],
    802     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[13],
    803     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[14],
    804     (UINTN) IPv6DevPath->RemoteIpAddress.Addr[15]
    805     );
    806 }
    807 
    808 /**
    809   Convert Device Path to a Unicode string for printing.
    810 
    811   @param[in, out] Str           The buffer holding the output string.
    812                                 This buffer contains the length of the string and
    813                                 the maixmum length reserved for the string buffer.
    814   @param[in]      DevPath       The device path.
    815 
    816 **/
    817 VOID
    818 DevPathInfiniBand (
    819   IN OUT POOL_PRINT       *Str,
    820   IN VOID                 *DevPath
    821   )
    822 {
    823   INFINIBAND_DEVICE_PATH  *InfiniBand;
    824 
    825   InfiniBand = DevPath;
    826   CatPrint (
    827     Str,
    828     L"Infiniband(%x,%g,%lx,%lx,%lx)",
    829     (UINTN) InfiniBand->ResourceFlags,
    830     InfiniBand->PortGid,
    831     InfiniBand->ServiceId,
    832     InfiniBand->TargetPortId,
    833     InfiniBand->DeviceId
    834     );
    835 }
    836 
    837 /**
    838   Convert Device Path to a Unicode string for printing.
    839 
    840   @param[in, out] Str           The buffer holding the output string.
    841                                 This buffer contains the length of the string and
    842                                 the maixmum length reserved for the string buffer.
    843   @param[in]      DevPath       The device path.
    844 
    845 **/
    846 VOID
    847 DevPathUart (
    848   IN OUT POOL_PRINT       *Str,
    849   IN VOID                 *DevPath
    850   )
    851 {
    852   UART_DEVICE_PATH  *Uart;
    853   CHAR8             Parity;
    854 
    855   Uart = DevPath;
    856   switch (Uart->Parity) {
    857   case 0:
    858     Parity = 'D';
    859     break;
    860 
    861   case 1:
    862     Parity = 'N';
    863     break;
    864 
    865   case 2:
    866     Parity = 'E';
    867     break;
    868 
    869   case 3:
    870     Parity = 'O';
    871     break;
    872 
    873   case 4:
    874     Parity = 'M';
    875     break;
    876 
    877   case 5:
    878     Parity = 'S';
    879     break;
    880 
    881   default:
    882     Parity = 'x';
    883     break;
    884   }
    885 
    886   if (Uart->BaudRate == 0) {
    887     CatPrint (Str, L"Uart(DEFAULT,%c,", Parity);
    888   } else {
    889     CatPrint (Str, L"Uart(%ld,%c,", Uart->BaudRate, Parity);
    890   }
    891 
    892   if (Uart->DataBits == 0) {
    893     CatPrint (Str, L"D,");
    894   } else {
    895     CatPrint (Str, L"%d,", (UINTN) Uart->DataBits);
    896   }
    897 
    898   switch (Uart->StopBits) {
    899   case 0:
    900     CatPrint (Str, L"D)");
    901     break;
    902 
    903   case 1:
    904     CatPrint (Str, L"1)");
    905     break;
    906 
    907   case 2:
    908     CatPrint (Str, L"1.5)");
    909     break;
    910 
    911   case 3:
    912     CatPrint (Str, L"2)");
    913     break;
    914 
    915   default:
    916     CatPrint (Str, L"x)");
    917     break;
    918   }
    919 }
    920 
    921 /**
    922   Convert Device Path to a Unicode string for printing.
    923 
    924   @param[in, out] Str           The buffer holding the output string.
    925                                 This buffer contains the length of the string and
    926                                 the maixmum length reserved for the string buffer.
    927   @param[in]      DevPath       The device path.
    928 
    929 **/
    930 VOID
    931 DevPathiSCSI (
    932   IN OUT POOL_PRINT       *Str,
    933   IN VOID                 *DevPath
    934   )
    935 {
    936   ISCSI_DEVICE_PATH_WITH_NAME *IScsi;
    937   UINT16                      Options;
    938 
    939   IScsi = DevPath;
    940   CatPrint (
    941     Str,
    942     L"iSCSI(%a,%x,%lx,",
    943     IScsi->TargetName,
    944     (UINTN) IScsi->TargetPortalGroupTag,
    945     IScsi->Lun
    946     );
    947 
    948   Options = IScsi->LoginOption;
    949   CatPrint (Str, L"%s,", (((Options >> 1) & 0x0001) != 0) ? L"CRC32C" : L"None");
    950   CatPrint (Str, L"%s,", (((Options >> 3) & 0x0001) != 0) ? L"CRC32C" : L"None");
    951   if (((Options >> 11) & 0x0001) != 0) {
    952     CatPrint (Str, L"%s,", L"None");
    953   } else if (((Options >> 12) & 0x0001) != 0) {
    954     CatPrint (Str, L"%s,", L"CHAP_UNI");
    955   } else {
    956     CatPrint (Str, L"%s,", L"CHAP_BI");
    957 
    958   }
    959 
    960   CatPrint (Str, L"%s)", (IScsi->NetworkProtocol == 0) ? L"TCP" : L"reserved");
    961 }
    962 
    963 /**
    964   Convert Device Path to a Unicode string for printing.
    965 
    966   @param[in, out] Str           The buffer holding the output string.
    967                                 This buffer contains the length of the string and
    968                                 the maixmum length reserved for the string buffer.
    969   @param[in]      DevPath       The device path.
    970 
    971 **/
    972 VOID
    973 DevPathVlan (
    974   IN OUT POOL_PRINT       *Str,
    975   IN VOID                 *DevPath
    976   )
    977 {
    978   VLAN_DEVICE_PATH  *Vlan;
    979 
    980   Vlan = DevPath;
    981   CatPrint (Str, L"Vlan(%d)", (UINTN) Vlan->VlanId);
    982 }
    983 
    984 /**
    985   Convert Device Path to a Unicode string for printing.
    986 
    987   @param[in, out] Str           The buffer holding the output string.
    988                                 This buffer contains the length of the string and
    989                                 the maixmum length reserved for the string buffer.
    990   @param[in]      DevPath       The device path.
    991 
    992 **/
    993 VOID
    994 DevPathHardDrive (
    995   IN OUT POOL_PRINT       *Str,
    996   IN VOID                 *DevPath
    997   )
    998 {
    999   HARDDRIVE_DEVICE_PATH *Hd;
    1000 
    1001   Hd = DevPath;
    1002   switch (Hd->SignatureType) {
    1003   case SIGNATURE_TYPE_MBR:
    1004     CatPrint (
    1005       Str,
    1006       L"HD(Part%d,Sig%08x)",
    1007       (UINTN) Hd->PartitionNumber,
    1008       (UINTN) *((UINT32 *) (&(Hd->Signature[0])))
    1009       );
    1010     break;
    1011 
    1012   case SIGNATURE_TYPE_GUID:
    1013     CatPrint (
    1014       Str,
    1015       L"HD(Part%d,Sig%g)",
    1016       (UINTN) Hd->PartitionNumber,
    1017       (EFI_GUID *) &(Hd->Signature[0])
    1018       );
    1019     break;
    1020 
    1021   default:
    1022     CatPrint (
    1023       Str,
    1024       L"HD(Part%d,MBRType=%02x,SigType=%02x)",
    1025       (UINTN) Hd->PartitionNumber,
    1026       (UINTN) Hd->MBRType,
    1027       (UINTN) Hd->SignatureType
    1028       );
    1029     break;
    1030   }
    1031 }
    1032 
    1033 /**
    1034   Convert Device Path to a Unicode string for printing.
    1035 
    1036   @param[in, out] Str           The buffer holding the output string.
    1037                                 This buffer contains the length of the string and
    1038                                 the maixmum length reserved for the string buffer.
    1039   @param[in]      DevPath       The device path.
    1040 
    1041 **/
    1042 VOID
    1043 DevPathCDROM (
    1044   IN OUT POOL_PRINT       *Str,
    1045   IN VOID                 *DevPath
    1046   )
    1047 {
    1048   CDROM_DEVICE_PATH *Cd;
    1049 
    1050   Cd = DevPath;
    1051   CatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry);
    1052 }
    1053 
    1054 /**
    1055   Convert Device Path to a Unicode string for printing.
    1056 
    1057   @param[in, out] Str           The buffer holding the output string.
    1058                                 This buffer contains the length of the string and
    1059                                 the maixmum length reserved for the string buffer.
    1060   @param[in]      DevPath       The device path.
    1061 
    1062 **/
    1063 VOID
    1064 DevPathFilePath (
    1065   IN OUT POOL_PRINT       *Str,
    1066   IN VOID                 *DevPath
    1067   )
    1068 {
    1069   FILEPATH_DEVICE_PATH  *Fp;
    1070 
    1071   Fp = DevPath;
    1072   CatPrint (Str, L"%s", Fp->PathName);
    1073 }
    1074 
    1075 /**
    1076   Convert Device Path to a Unicode string for printing.
    1077 
    1078   @param[in, out] Str           The buffer holding the output string.
    1079                                 This buffer contains the length of the string and
    1080                                 the maixmum length reserved for the string buffer.
    1081   @param[in]      DevPath       The device path.
    1082 
    1083 **/
    1084 VOID
    1085 DevPathMediaProtocol (
    1086   IN OUT POOL_PRINT       *Str,
    1087   IN VOID                 *DevPath
    1088   )
    1089 {
    1090   MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
    1091 
    1092   MediaProt = DevPath;
    1093   CatPrint (Str, L"Media(%g)", &MediaProt->Protocol);
    1094 }
    1095 
    1096 /**
    1097   Convert Device Path to a Unicode string for printing.
    1098 
    1099   @param[in, out] Str           The buffer holding the output string.
    1100                                 This buffer contains the length of the string and
    1101                                 the maixmum length reserved for the string buffer.
    1102   @param[in]      DevPath       The device path.
    1103 
    1104 **/
    1105 VOID
    1106 DevPathFvFilePath (
    1107   IN OUT POOL_PRINT       *Str,
    1108   IN VOID                 *DevPath
    1109   )
    1110 {
    1111   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
    1112 
    1113   FvFilePath = DevPath;
    1114   CatPrint (Str, L"%g", &FvFilePath->FvFileName);
    1115 }
    1116 
    1117 /**
    1118   Convert Device Path to a Unicode string for printing.
    1119 
    1120   @param[in, out] Str           The buffer holding the output string.
    1121                                 This buffer contains the length of the string and
    1122                                 the maixmum length reserved for the string buffer.
    1123   @param[in]      DevPath       The device path.
    1124 
    1125 **/
    1126 VOID
    1127 DevPathRelativeOffsetRange (
    1128   IN OUT POOL_PRINT       *Str,
    1129   IN VOID                 *DevPath
    1130   )
    1131 {
    1132   MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;
    1133 
    1134   Offset = DevPath;
    1135   CatPrint (
    1136     Str,
    1137     L"Offset(%lx,%lx)",
    1138     Offset->StartingOffset,
    1139     Offset->EndingOffset
    1140     );
    1141 }
    1142 
    1143 /**
    1144   Convert Device Path to a Unicode string for printing.
    1145 
    1146   @param[in, out] Str           The buffer holding the output string.
    1147                                 This buffer contains the length of the string and
    1148                                 the maixmum length reserved for the string buffer.
    1149   @param[in]      DevPath       The device path.
    1150 
    1151 **/
    1152 VOID
    1153 DevPathBssBss (
    1154   IN OUT POOL_PRINT       *Str,
    1155   IN VOID                 *DevPath
    1156   )
    1157 {
    1158   BBS_BBS_DEVICE_PATH *Bbs;
    1159   CHAR16              *Type;
    1160 
    1161   Bbs = DevPath;
    1162   switch (Bbs->DeviceType) {
    1163   case BBS_TYPE_FLOPPY:
    1164     Type = L"Floppy";
    1165     break;
    1166 
    1167   case BBS_TYPE_HARDDRIVE:
    1168     Type = L"Harddrive";
    1169     break;
    1170 
    1171   case BBS_TYPE_CDROM:
    1172     Type = L"CDROM";
    1173     break;
    1174 
    1175   case BBS_TYPE_PCMCIA:
    1176     Type = L"PCMCIA";
    1177     break;
    1178 
    1179   case BBS_TYPE_USB:
    1180     Type = L"Usb";
    1181     break;
    1182 
    1183   case BBS_TYPE_EMBEDDED_NETWORK:
    1184     Type = L"Net";
    1185     break;
    1186 
    1187   case BBS_TYPE_BEV:
    1188     Type = L"BEV";
    1189     break;
    1190 
    1191   default:
    1192     Type = L"?";
    1193     break;
    1194   }
    1195   CatPrint (Str, L"Legacy-%s", Type);
    1196 }
    1197 
    1198 /**
    1199   Convert Device Path to a Unicode string for printing.
    1200 
    1201   @param[in, out] Str           The buffer holding the output string.
    1202                                 This buffer contains the length of the string and
    1203                                 the maixmum length reserved for the string buffer.
    1204   @param[in]      DevPath       The device path.
    1205 
    1206 **/
    1207 VOID
    1208 DevPathEndInstance (
    1209   IN OUT POOL_PRINT       *Str,
    1210   IN VOID                 *DevPath
    1211   )
    1212 {
    1213   CatPrint (Str, L",");
    1214 }
    1215 
    1216 /**
    1217   Convert Device Path to a Unicode string for printing.
    1218 
    1219   @param[in, out] Str           The buffer holding the output string.
    1220                                 This buffer contains the length of the string and
    1221                                 the maixmum length reserved for the string buffer.
    1222   @param[in]      DevPath       The device path.
    1223 
    1224 **/
    1225 VOID
    1226 DevPathNodeUnknown (
    1227   IN OUT POOL_PRINT       *Str,
    1228   IN VOID                 *DevPath
    1229   )
    1230 {
    1231   CatPrint (Str, L"?");
    1232 }
    1233 /**
    1234   Convert Device Path to a Unicode string for printing.
    1235 
    1236   @param[in, out] Str           The buffer holding the output string.
    1237                                 This buffer contains the length of the string and
    1238                                 the maixmum length reserved for the string buffer.
    1239   @param[in]      DevPath       The device path.
    1240 
    1241 **/
    1242 VOID
    1243 DevPathFvPath (
    1244   IN OUT POOL_PRINT       *Str,
    1245   IN VOID                 *DevPath
    1246   )
    1247 {
    1248   MEDIA_FW_VOL_DEVICE_PATH *FvPath;
    1249 
    1250   FvPath = DevPath;
    1251   CatPrint (Str, L"Fv(%g)", &FvPath->FvName);
    1252 }
    1253 
    1254 DEVICE_PATH_STRING_TABLE  DevPathTable[] = {
    1255   {
    1256     HARDWARE_DEVICE_PATH,
    1257     HW_PCI_DP,
    1258     DevPathPci
    1259   },
    1260   {
    1261     HARDWARE_DEVICE_PATH,
    1262     HW_PCCARD_DP,
    1263     DevPathPccard
    1264   },
    1265   {
    1266     HARDWARE_DEVICE_PATH,
    1267     HW_MEMMAP_DP,
    1268     DevPathMemMap
    1269   },
    1270   {
    1271     HARDWARE_DEVICE_PATH,
    1272     HW_VENDOR_DP,
    1273     DevPathVendor
    1274   },
    1275   {
    1276     HARDWARE_DEVICE_PATH,
    1277     HW_CONTROLLER_DP,
    1278     DevPathController
    1279   },
    1280   {
    1281     ACPI_DEVICE_PATH,
    1282     ACPI_DP,
    1283     DevPathAcpi
    1284   },
    1285   {
    1286     ACPI_DEVICE_PATH,
    1287     ACPI_EXTENDED_DP,
    1288     DevPathExtendedAcpi
    1289   },
    1290   {
    1291     ACPI_DEVICE_PATH,
    1292     ACPI_ADR_DP,
    1293     DevPathAdrAcpi
    1294   },
    1295   {
    1296     MESSAGING_DEVICE_PATH,
    1297     MSG_ATAPI_DP,
    1298     DevPathAtapi
    1299   },
    1300   {
    1301     MESSAGING_DEVICE_PATH,
    1302     MSG_SCSI_DP,
    1303     DevPathScsi
    1304   },
    1305   {
    1306     MESSAGING_DEVICE_PATH,
    1307     MSG_FIBRECHANNEL_DP,
    1308     DevPathFibre
    1309   },
    1310   {
    1311     MESSAGING_DEVICE_PATH,
    1312     MSG_1394_DP,
    1313     DevPath1394
    1314   },
    1315   {
    1316     MESSAGING_DEVICE_PATH,
    1317     MSG_USB_DP,
    1318     DevPathUsb
    1319   },
    1320   {
    1321     MESSAGING_DEVICE_PATH,
    1322     MSG_USB_WWID_DP,
    1323     DevPathUsbWWID
    1324   },
    1325   {
    1326     MESSAGING_DEVICE_PATH,
    1327     MSG_DEVICE_LOGICAL_UNIT_DP,
    1328     DevPathLogicalUnit
    1329   },
    1330   {
    1331     MESSAGING_DEVICE_PATH,
    1332     MSG_USB_CLASS_DP,
    1333     DevPathUsbClass
    1334   },
    1335   {
    1336     MESSAGING_DEVICE_PATH,
    1337     MSG_SATA_DP,
    1338     DevPathSata
    1339   },
    1340   {
    1341     MESSAGING_DEVICE_PATH,
    1342     MSG_I2O_DP,
    1343     DevPathI2O
    1344   },
    1345   {
    1346     MESSAGING_DEVICE_PATH,
    1347     MSG_MAC_ADDR_DP,
    1348     DevPathMacAddr
    1349   },
    1350   {
    1351     MESSAGING_DEVICE_PATH,
    1352     MSG_IPv4_DP,
    1353     DevPathIPv4
    1354   },
    1355   {
    1356     MESSAGING_DEVICE_PATH,
    1357     MSG_IPv6_DP,
    1358     DevPathIPv6
    1359   },
    1360   {
    1361     MESSAGING_DEVICE_PATH,
    1362     MSG_INFINIBAND_DP,
    1363     DevPathInfiniBand
    1364   },
    1365   {
    1366     MESSAGING_DEVICE_PATH,
    1367     MSG_UART_DP,
    1368     DevPathUart
    1369   },
    1370   {
    1371     MESSAGING_DEVICE_PATH,
    1372     MSG_VENDOR_DP,
    1373     DevPathVendor
    1374   },
    1375   {
    1376     MESSAGING_DEVICE_PATH,
    1377     MSG_ISCSI_DP,
    1378     DevPathiSCSI
    1379   },
    1380   {
    1381     MESSAGING_DEVICE_PATH,
    1382     MSG_VLAN_DP,
    1383     DevPathVlan
    1384   },
    1385   {
    1386     MEDIA_DEVICE_PATH,
    1387     MEDIA_HARDDRIVE_DP,
    1388     DevPathHardDrive
    1389   },
    1390   {
    1391     MEDIA_DEVICE_PATH,
    1392     MEDIA_CDROM_DP,
    1393     DevPathCDROM
    1394   },
    1395   {
    1396     MEDIA_DEVICE_PATH,
    1397     MEDIA_VENDOR_DP,
    1398     DevPathVendor
    1399   },
    1400   {
    1401     MEDIA_DEVICE_PATH,
    1402     MEDIA_FILEPATH_DP,
    1403     DevPathFilePath
    1404   },
    1405   {
    1406     MEDIA_DEVICE_PATH,
    1407     MEDIA_PROTOCOL_DP,
    1408     DevPathMediaProtocol
    1409   },
    1410   {
    1411     MEDIA_DEVICE_PATH,
    1412     MEDIA_PIWG_FW_VOL_DP,
    1413     DevPathFvPath,
    1414   },
    1415   {
    1416     MEDIA_DEVICE_PATH,
    1417     MEDIA_PIWG_FW_FILE_DP,
    1418     DevPathFvFilePath
    1419   },
    1420   {
    1421     MEDIA_DEVICE_PATH,
    1422     MEDIA_RELATIVE_OFFSET_RANGE_DP,
    1423     DevPathRelativeOffsetRange,
    1424   },
    1425   {
    1426     BBS_DEVICE_PATH,
    1427     BBS_BBS_DP,
    1428     DevPathBssBss
    1429   },
    1430   {
    1431     END_DEVICE_PATH_TYPE,
    1432     END_INSTANCE_DEVICE_PATH_SUBTYPE,
    1433     DevPathEndInstance
    1434   },
    1435   {
    1436     0,
    1437     0,
    1438     NULL
    1439   }
    1440 };
    144116
    144217
     
    145530  )
    145631{
    1457   POOL_PRINT                Str;
    1458   EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;
    1459   VOID (*DumpNode) (POOL_PRINT *, VOID *);
    1460 
    1461   UINTN Index;
    1462   UINTN NewSize;
    1463 
    1464   EFI_STATUS                       Status;
    1465   CHAR16                           *ToText;
    1466   EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
    1467 
    1468   ZeroMem (&Str, sizeof (Str));
    1469 
    1470   if (DevPath == NULL) {
    1471     goto Done;
    1472   }
    1473 
    1474   Status = gBS->LocateProtocol (
    1475                   &gEfiDevicePathToTextProtocolGuid,
    1476                   NULL,
    1477                   (VOID **) &DevPathToText
    1478                   );
    1479   if (!EFI_ERROR (Status)) {
    1480     ToText = DevPathToText->ConvertDevicePathToText (
    1481                               DevPath,
    1482                               FALSE,
    1483                               TRUE
    1484                               );
    1485     ASSERT (ToText != NULL);
    1486     return ToText;
    1487   }
    1488 
    1489   //
    1490   // Process each device path node
    1491   //
    1492   DevPathNode = DevPath;
    1493   while (!IsDevicePathEnd (DevPathNode)) {
    1494     //
    1495     // Find the handler to dump this device path node
    1496     //
    1497     DumpNode = NULL;
    1498     for (Index = 0; DevPathTable[Index].Function != NULL; Index += 1) {
    1499 
    1500       if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&
    1501           DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType
    1502           ) {
    1503         DumpNode = DevPathTable[Index].Function;
    1504         break;
    1505       }
    1506     }
    1507     //
    1508     // If not found, use a generic function
    1509     //
    1510     if (!DumpNode) {
    1511       DumpNode = DevPathNodeUnknown;
    1512     }
    1513     //
    1514     //  Put a path seperator in if needed
    1515     //
    1516     if ((Str.Len != 0) && (DumpNode != DevPathEndInstance)) {
    1517       CatPrint (&Str, L"/");
    1518     }
    1519     //
    1520     // Print this node of the device path
    1521     //
    1522     DumpNode (&Str, DevPathNode);
    1523 
    1524     //
    1525     // Next device path node
    1526     //
    1527     DevPathNode = NextDevicePathNode (DevPathNode);
    1528   }
    1529 
    1530 Done:
    1531   NewSize = (Str.Len + 1) * sizeof (CHAR16);
    1532   Str.Str = ReallocatePool (NewSize, NewSize, Str.Str);
    1533   ASSERT (Str.Str != NULL);
    1534   Str.Str[Str.Len] = 0;
    1535   return Str.Str;
     32  return ConvertDevicePathToText (
     33           DevPath,
     34           FALSE,
     35           TRUE
     36           );
    153637}
    153738
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf

    r48674 r58459  
    11## @file
    2 #  Component name for SecureBoot configuration module.
     2#  Provides the capbility to configure secure boot in a setup browser
     3#  By this module, user may change the content of DB, DBX, PK and KEK.
    34#
    4 # Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
     5# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
    56# This program and the accompanying materials
    67# are licensed and made available under the terms and conditions of the BSD License
     
    1516  INF_VERSION                    = 0x00010005
    1617  BASE_NAME                      = SecureBootConfigDxe
     18  MODULE_UNI_FILE                = SecureBootConfigDxe.uni
    1719  FILE_GUID                      = F0E6A44F-7195-41c3-AC64-54F202CD0A21
    1820  MODULE_TYPE                    = DXE_DRIVER
     
    5456  DebugLib
    5557  HiiLib
    56   PlatformSecureLib 
     58  PlatformSecureLib
     59  DevicePathLib
    5760
    5861[Guids]
    59   gEfiIfrTianoGuid
     62  ## SOMETIMES_CONSUMES      ## Variable:L"CustomMode"
     63  ## SOMETIMES_PRODUCES      ## Variable:L"CustomMode"
    6064  gEfiCustomModeEnableGuid
     65   
     66  ## SOMETIMES_CONSUMES      ## Variable:L"SecureBootEnable"
     67  ## SOMETIMES_PRODUCES      ## Variable:L"SecureBootEnable"
    6168  gEfiSecureBootEnableDisableGuid
     69 
     70  ## SOMETIMES_CONSUMES      ## GUID            # Unique ID for the type of the signature.
     71  ## SOMETIMES_PRODUCES      ## GUID            # Unique ID for the type of the signature.
     72  gEfiCertRsa2048Guid
     73 
     74  ## SOMETIMES_CONSUMES      ## GUID            # Unique ID for the type of the signature.
     75  ## SOMETIMES_PRODUCES      ## GUID            # Unique ID for the type of the signature.                               
     76  gEfiCertX509Guid
     77 
     78  ## SOMETIMES_CONSUMES      ## GUID            # Unique ID for the type of the signature.
     79  ## SOMETIMES_PRODUCES      ## GUID            # Unique ID for the type of the signature.   
     80  gEfiCertSha1Guid
     81 
     82  ## SOMETIMES_CONSUMES      ## GUID            # Unique ID for the type of the signature.
     83  ## SOMETIMES_PRODUCES      ## GUID            # Unique ID for the type of the signature.   
     84  gEfiCertSha256Guid
     85 
     86  ## SOMETIMES_CONSUMES      ## Variable:L"db"
     87  ## SOMETIMES_PRODUCES      ## Variable:L"db"
     88  ## SOMETIMES_CONSUMES      ## Variable:L"dbx"
     89  ## SOMETIMES_PRODUCES      ## Variable:L"dbx"
     90  gEfiImageSecurityDatabaseGuid
     91   
     92  ## SOMETIMES_CONSUMES      ## Variable:L"SetupMode"
     93  ## SOMETIMES_PRODUCES      ## Variable:L"PK"
     94  ## SOMETIMES_CONSUMES      ## Variable:L"KEK"
     95  ## SOMETIMES_PRODUCES      ## Variable:L"KEK"
     96  ## SOMETIMES_CONSUMES      ## Variable:L"SecureBoot"
     97  gEfiGlobalVariableGuid
     98 
     99  gEfiIfrTianoGuid                              ## PRODUCES            ## GUID       # HII opcode
     100  ## PRODUCES                ## HII
     101  ## CONSUMES                ## HII
    62102  gSecureBootConfigFormSetGuid
    63   gEfiCertPkcs7Guid
    64   gEfiCertRsa2048Guid                           ## CONSUMES
    65   gEfiCertX509Guid                              ## CONSUMES
    66   gEfiCertSha1Guid                              ## CONSUMES
    67   gEfiCertSha256Guid                            ## CONSUMES
    68   gEfiCertTypeRsa2048Sha256Guid                 ## CONSUMES
    69   gEfiImageSecurityDatabaseGuid                 ## CONSUMES
    70   gEfiFileSystemVolumeLabelInfoIdGuid           ## CONSUMES
    71   gEfiGlobalVariableGuid                        ## PRODUCES ## Variable Guid
    72   gEfiVT100PlusGuid                             ## CONSUMES ## GUID (The type of terminal)
    73   gEfiVT100Guid                                 ## CONSUMES ## GUID (The type of terminal)
    74                                                 ## CONSUMES ## GUID HOB (The hob holding memory type information)
    75   gEfiVTUTF8Guid                                ## CONSUMES ## GUID (The type of terminal)
    76                                                 ## SOMETIMES_CONSUMES ## Variable:L"BootXX" (Boot option variable)
    77                                                 ## CONSUMES           ## Variable:L"Timeout" (The time out value in second of showing progress bar)
    78                                                 ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array)
    79                                                 ## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" (The driver order list)
    80                                                 ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device)
    81                                                 ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device)
    82                                                 ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device)
    83   gEfiFileInfoGuid                              ## CONSUMES ## GUID
    84   gEfiPcAnsiGuid                                ## CONSUMES ## GUID (The type of terminal)
    85   gEfiUartDevicePathGuid                        ## CONSUMES ## GUID (Identify the device path for UARD device)
    86   gEfiSasDevicePathGuid                         ## CONSUMES ## GUID (Identify the device path for SAS device)
     103  gEfiCertPkcs7Guid                             ## SOMETIMES_PRODUCES  ## GUID  # Unique ID for the type of the certificate.
     104  gEfiCertTypeRsa2048Sha256Guid                 ## SOMETIMES_CONSUMES  ## GUID  # Unique ID for the type of the certificate.
     105  gEfiFileSystemVolumeLabelInfoIdGuid           ## SOMETIMES_CONSUMES  ## GUID  # Indicate the information type
     106  gEfiFileInfoGuid                              ## SOMETIMES_CONSUMES  ## GUID  # Indicate the information type
    87107
    88108[Protocols]
    89109  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
    90   gEfiHiiConfigRoutingProtocolGuid              ## CONSUMES
    91   gEfiSimpleFileSystemProtocolGuid              ## PROTOCOL CONSUMES
    92   gEfiLoadFileProtocolGuid                      ## PROTOCOL CONSUMES
    93   gEfiBlockIoProtocolGuid                       ## PROTOCOL CONSUMES
    94   gEfiDevicePathProtocolGuid                    ## PROTOCOL CONSUMES
    95   gEfiDevicePathToTextProtocolGuid
    96   gEfiDebugPortProtocolGuid
     110  gEfiDevicePathProtocolGuid                    ## PRODUCES
     111  gEfiSimpleFileSystemProtocolGuid              ## SOMETIMES_CONSUMES
     112  gEfiBlockIoProtocolGuid                       ## SOMETIMES_CONSUMES
    97113
    98114[Depex]
     
    101117  gEfiVariableArchProtocolGuid      AND
    102118  gEfiVariableWriteArchProtocolGuid
     119
     120[UserExtensions.TianoCore."ExtraFiles"]
     121  SecureBootConfigDxeExtra.uni
     122 
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigFileExplorer.c

    r48674 r58459  
    22  Internal file explorer functions for SecureBoot configuration module.
    33
    4 Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>
    55This program and the accompanying materials
    66are licensed and made available under the terms and conditions of the BSD License
     
    324324  FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext;
    325325
    326   if (!FileContext->IsRoot) {
     326  if (!FileContext->IsRoot && FileContext->DevicePath != NULL) {
    327327    FreePool (FileContext->DevicePath);
    328328  } else {
     
    341341  FreePool (FileContext);
    342342
    343   FreePool (MenuEntry->DisplayString);
     343  if (MenuEntry->DisplayString != NULL) {
     344    FreePool (MenuEntry->DisplayString);
     345  }
    344346  if (MenuEntry->HelpString != NULL) {
    345347    FreePool (MenuEntry->HelpString);
     
    10681070        STRING_TOKEN (STR_NULL),
    10691071        EFI_IFR_FLAG_CALLBACK,
    1070         (UINT16) (FILE_OPTION_OFFSET + Index)
     1072        (UINT16) (FILE_OPTION_GOTO_OFFSET + Index)
    10711073        );
    10721074    }
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c

    r48674 r58459  
    22  HII Config Access protocol implementation of SecureBoot configuration module.
    33
    4 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
    55This program and the accompanying materials
    66are licensed and made available under the terms and conditions of the BSD License
     
    4949
    5050
     51BOOLEAN mIsEnterSecureBootForm = FALSE;
     52
    5153//
    5254// OID ASN.1 Value for Hash Algorithms
     
    6971};
    7072
    71 
    72 // Variable Definitions                                           
     73//
     74// Variable Definitions
     75//                                         
    7376UINT32            mPeCoffHeaderOffset = 0;
    7477WIN_CERTIFICATE   *mCertificate = NULL;
     
    8285EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  mNtHeader;
    8386
     87//
     88// Possible DER-encoded certificate file suffixes, end with NULL pointer.
     89//
     90CHAR16* mDerEncodedSuffix[] = {
     91  L".cer",
     92  L".der",
     93  L".crt",
     94  NULL
     95};
     96CHAR16* mSupportX509Suffix = L"*.cer/der/crt";
     97
     98/**
     99  This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
     100
     101  @param[in] FileSuffix            The suffix of the input certificate file
     102
     103  @retval    TRUE           It's a DER-encoded certificate.
     104  @retval    FALSE          It's NOT a DER-encoded certificate.
     105
     106**/
     107BOOLEAN
     108IsDerEncodeCertificate (
     109  IN CONST CHAR16         *FileSuffix
     110)
     111{
     112  UINTN     Index;
     113  for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) {
     114    if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) {
     115      return TRUE;
     116    }
     117  }
     118  return FALSE;
     119}
    84120
    85121/**
     
    216252  UINT32                  Attr;
    217253
    218   Variable = GetVariable (VariableName, VendorGuid);
     254  GetVariable2 (VariableName, VendorGuid, &Variable, NULL);
    219255  if (Variable == NULL) {
    220256    return EFI_SUCCESS;
    221257  }
     258  FreePool (Variable);
    222259
    223260  Data     = NULL;
     
    243280  }
    244281  return Status;
     282}
     283
     284/**
     285
     286  Set the platform secure boot mode into "Custom" or "Standard" mode.
     287
     288  @param[in]   SecureBootMode        New secure boot mode: STANDARD_SECURE_BOOT_MODE or
     289                                     CUSTOM_SECURE_BOOT_MODE.
     290 
     291  @return EFI_SUCCESS                The platform has switched to the special mode successfully.
     292  @return other                      Fail to operate the secure boot mode.
     293 
     294**/
     295EFI_STATUS
     296SetSecureBootMode (
     297  IN     UINT8         SecureBootMode
     298  )
     299{
     300  return gRT->SetVariable (                         
     301                EFI_CUSTOM_MODE_NAME,
     302                &gEfiCustomModeEnableGuid,
     303                EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
     304                sizeof (UINT8),
     305                &SecureBootMode
     306                );
    245307}
    246308
     
    340402  EFI_SIGNATURE_LIST              *PkCert;
    341403  UINT16*                         FilePostFix;
     404  UINTN                           NameLength;
    342405 
    343406  if (Private->FileContext->FileName == NULL) {
     
    347410  PkCert = NULL;
    348411
    349   //
    350   // Parse the file's postfix. Only support *.cer(X509) files.
    351   //
    352   FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;
    353   if (CompareMem (FilePostFix, L".cer",4)) {
    354     DEBUG ((EFI_D_ERROR, "Don't support the file, only *.cer is supported."));
     412  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
     413  if (EFI_ERROR (Status)) {
     414    return Status;
     415  }
     416
     417  //
     418  // Parse the file's postfix. Only support DER encoded X.509 certificate files.
     419  //
     420  NameLength = StrLen (Private->FileContext->FileName);
     421  if (NameLength <= 4) {
     422    return EFI_INVALID_PARAMETER;
     423  }
     424  FilePostFix = Private->FileContext->FileName + NameLength - 4;
     425  if (!IsDerEncodeCertificate(FilePostFix)) {
     426    DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix));
    355427    return EFI_INVALID_PARAMETER;
    356428  }
     
    423495{
    424496  EFI_STATUS Status;
     497
     498  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
     499  if (EFI_ERROR (Status)) {
     500    return Status;
     501  }
    425502
    426503  Status = DeleteVariable (
     
    733810{
    734811  UINT16*     FilePostFix;
     812  EFI_STATUS  Status;
     813  UINTN       NameLength;
    735814 
    736815  if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {
     
    738817  }
    739818
    740   //
    741   // Parse the file's postfix. Supports .cer and .der file as X509 certificate,
     819  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
     820  if (EFI_ERROR (Status)) {
     821    return Status;
     822  }
     823
     824  //
     825  // Parse the file's postfix. Supports DER-encoded X509 certificate,
    742826  // and .pbk as RSA public key file.
    743827  //
    744   FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;
    745   if ((CompareMem (FilePostFix, L".cer",4) == 0) || (CompareMem (FilePostFix, L".der",4) == 0)) {
     828  NameLength = StrLen (Private->FileContext->FileName);
     829  if (NameLength <= 4) {
     830    return EFI_INVALID_PARAMETER;
     831  }
     832  FilePostFix = Private->FileContext->FileName + NameLength - 4;
     833  if (IsDerEncodeCertificate(FilePostFix)) {
    746834    return EnrollX509ToKek (Private);
    747835  } else if (CompareMem (FilePostFix, L".pbk",4) == 0) {
     
    10171105  // But CheckSum field and SECURITY data directory (certificate) are excluded
    10181106  //
    1019   Magic = mNtHeader.Pe32->OptionalHeader.Magic;
     1107  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
     1108    //
     1109    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
     1110    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
     1111    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
     1112    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
     1113    //
     1114    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
     1115  } else {
     1116    //
     1117    // Get the magic value from the PE/COFF Optional Header
     1118    //
     1119    Magic = mNtHeader.Pe32->OptionalHeader.Magic;
     1120  }
     1121 
    10201122  //
    10211123  // 3.  Calculate the distance from the base of the image header to the image checksum address.
     
    14611563{
    14621564  UINT16*      FilePostFix;
     1565  EFI_STATUS   Status;
     1566  UINTN        NameLength;
    14631567
    14641568  if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {
     
    14661570  }
    14671571
     1572  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
     1573  if (EFI_ERROR (Status)) {
     1574    return Status;
     1575  }
     1576 
    14681577  //
    14691578  // Parse the file's postfix.
    14701579  //
    1471   FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;
    1472   if ((CompareMem (FilePostFix, L".cer",4) == 0) || (CompareMem (FilePostFix, L".der",4) == 0)) {
    1473     //
    1474     // Supports .cer and .der file as X509 certificate.
     1580  NameLength = StrLen (Private->FileContext->FileName);
     1581  if (NameLength <= 4) {
     1582    return EFI_INVALID_PARAMETER;
     1583  }
     1584  FilePostFix = Private->FileContext->FileName + NameLength - 4;
     1585  if (IsDerEncodeCertificate(FilePostFix)) {
     1586    //
     1587    // Supports DER-encoded X509 certificate.
    14751588    //
    14761589    return EnrollX509toSigDB (Private, VariableName);
     
    16121725      // The signature type is not supported in current implementation.
    16131726      //
     1727      ItemDataSize -= CertList->SignatureListSize;
     1728      CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
    16141729      continue;
    16151730    }
     
    17091824  Attr            = 0;   
    17101825  DeleteKekIndex  = QuestionId - OPTION_DEL_KEK_QUESTION_ID;
     1826
     1827  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
     1828  if (EFI_ERROR (Status)) {
     1829    return Status;
     1830  }
    17111831 
    17121832  //
     
    18011921  while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
    18021922    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
    1803     DEBUG ((DEBUG_ERROR, "       CertCount = %x\n", CertCount));
     1923    DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));
    18041924    if (CertCount != 0) {
    18051925      CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);
     
    18962016  Cert            = NULL;
    18972017  Attr            = 0;
     2018
     2019  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
     2020  if (EFI_ERROR (Status)) {
     2021    return Status;
     2022  }
    18982023
    18992024  //
     
    19942119  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
    19952120    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
    1996     DEBUG ((DEBUG_ERROR, "       CertCount = %x\n", CertCount));
     2121    DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));
    19972122    if (CertCount != 0) {
    19982123      CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
     
    20632188 
    20642189  //
    2065   // Get the SecureBootEnable Variable
    2066   //
    2067   SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);
    2068 
    2069   //
    20702190  // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
    20712191  // Checkbox.
    20722192  //
     2193  ConfigData->AttemptSecureBoot = FALSE;
     2194  GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
    20732195  if (SecureBootEnable == NULL) {
    20742196    ConfigData->HideSecureBoot = TRUE;
    20752197  } else {
    20762198    ConfigData->HideSecureBoot = FALSE;
    2077     ConfigData->SecureBootState = *SecureBootEnable;
    2078   }
     2199    if ((*SecureBootEnable) == SECURE_BOOT_ENABLE) {
     2200      ConfigData->AttemptSecureBoot = TRUE;
     2201    }
     2202  }
     2203 
    20792204  //
    20802205  // If it is Physical Presence User, set the PhysicalPresent to true.
     
    20892214  // If there is no PK then the Delete Pk button will be gray.
    20902215  //
    2091   SetupMode = GetVariable (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid);
    2092   if (SetupMode == NULL || (*SetupMode) == 1) {
     2216  GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);
     2217  if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {
    20932218    ConfigData->HasPk = FALSE;
    20942219  } else  {
     
    20992224  // Get the SecureBootMode from CustomMode variable.
    21002225  //
    2101   SecureBootMode = GetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid);
     2226  GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);
    21022227  if (SecureBootMode == NULL) {
    21032228    ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;
     
    21052230    ConfigData->SecureBootMode = *(SecureBootMode);
    21062231  }
    2107  
     2232
     2233  if (SecureBootEnable != NULL) {
     2234    FreePool (SecureBootEnable);
     2235  }
     2236  if (SetupMode != NULL) {
     2237    FreePool (SetupMode);
     2238  }
     2239  if (SecureBootMode != NULL) {
     2240    FreePool (SecureBootMode);
     2241  }
    21082242}
    21092243
     
    21512285  SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData;
    21522286  BOOLEAN                           AllocatedRequest;
     2287  UINT8                             *SecureBoot;
    21532288
    21542289  if (Progress == NULL || Results == NULL) {
     
    21602295  ConfigRequest    = NULL;
    21612296  Size             = 0;
     2297  SecureBoot       = NULL;
    21622298 
    21632299  ZeroMem (&Configuration, sizeof (Configuration));
     
    21732309  //
    21742310  SecureBootExtractConfigFromVariable (&Configuration);
     2311
     2312  //
     2313  // Update current secure boot state.
     2314  //
     2315  GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);
     2316  if (SecureBoot != NULL && *SecureBoot == SECURE_BOOT_MODE_ENABLE) {
     2317    HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);
     2318  } else {
     2319    HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);
     2320  }
     2321  if (SecureBoot != NULL) {
     2322    FreePool (SecureBoot);
     2323  }
    21752324 
    21762325  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
     
    22472396  )
    22482397{
     2398  UINT8                      *SecureBootEnable;
     2399  SECUREBOOT_CONFIGURATION   IfrNvData;
     2400  UINTN                      BufferSize;
     2401  EFI_STATUS                 Status;
     2402 
    22492403  if (Configuration == NULL || Progress == NULL) {
    22502404    return EFI_INVALID_PARAMETER;
     
    22542408  if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {
    22552409    return EFI_NOT_FOUND;
     2410  }
     2411
     2412  //
     2413  // Get Configuration from Variable.
     2414  //
     2415  SecureBootExtractConfigFromVariable (&IfrNvData);
     2416
     2417  //
     2418  // Map the Configuration to the configuration block.
     2419  //
     2420  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
     2421  Status = gHiiConfigRouting->ConfigToBlock (
     2422                                gHiiConfigRouting,
     2423                                Configuration,
     2424                                (UINT8 *)&IfrNvData,
     2425                                &BufferSize,
     2426                                Progress
     2427                                );
     2428  if (EFI_ERROR (Status)) {
     2429    return Status;
     2430  }
     2431
     2432  //
     2433  // Store Buffer Storage back to EFI variable if needed
     2434  //
     2435  SecureBootEnable = NULL;
     2436  GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
     2437  if (NULL != SecureBootEnable) {
     2438    FreePool (SecureBootEnable);
     2439    Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot);
     2440    if (EFI_ERROR (Status)) {
     2441      return Status;
     2442    }
    22562443  }
    22572444
     
    22992486  SECUREBOOT_CONFIGURATION        *IfrNvData;
    23002487  UINT16                          LabelId;
     2488  UINT8                           *SecureBootEnable;
     2489  UINT8                           *SecureBootMode;
     2490  UINT8                           *SetupMode;
     2491  CHAR16                          PromptString[100];
     2492
     2493  SecureBootEnable = NULL;
     2494  SecureBootMode   = NULL;
     2495  SetupMode        = NULL;
    23012496
    23022497  if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
     
    23042499  }
    23052500
    2306   if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING)) {
     2501  if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
     2502    if (QuestionId == KEY_SECURE_BOOT_MODE) {
     2503      mIsEnterSecureBootForm = TRUE;
     2504    }
     2505
     2506    return EFI_SUCCESS;
     2507  }
     2508 
     2509  if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
     2510    Status = EFI_UNSUPPORTED;
     2511    if (QuestionId == KEY_SECURE_BOOT_MODE) {
     2512      if (mIsEnterSecureBootForm) {
     2513        Value->u8 = SECURE_BOOT_MODE_STANDARD;
     2514        Status = EFI_SUCCESS;
     2515      }
     2516    }
     2517    return Status;
     2518  }
     2519 
     2520  if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
     2521      (Action != EFI_BROWSER_ACTION_CHANGING) &&
     2522      (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&
     2523      (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) {
    23072524    return EFI_UNSUPPORTED;
    23082525  }
     
    23212538  Status = EFI_SUCCESS;
    23222539
    2323   HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
     2540  HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData);
    23242541 
    23252542  if (Action == EFI_BROWSER_ACTION_CHANGING) {
     
    23272544    switch (QuestionId) {
    23282545    case KEY_SECURE_BOOT_ENABLE:
    2329       if (NULL != GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid)) {
     2546      GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
     2547      if (NULL != SecureBootEnable) {
     2548        FreePool (SecureBootEnable);
    23302549        if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {
    23312550          CreatePopUp (
     
    23362555            );
    23372556          Status = EFI_UNSUPPORTED;
     2557        } else {
     2558          CreatePopUp (
     2559            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
     2560            &Key,
     2561            L"Configuration changed, please reset the platform to take effect!",
     2562            NULL
     2563            );
    23382564        }
    2339         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
    23402565      }
    23412566      break;
     
    23942619
    23952620    case KEY_SECURE_BOOT_DELETE_PK:
    2396         if (Value->u8) {
     2621      if (Value->u8) {
     2622        CreatePopUp (
     2623          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
     2624          &Key,
     2625          L"Are you sure you want to delete PK? Secure boot will be disabled!",
     2626          L"Press 'Y' to delete PK and exit, 'N' to discard change and return",
     2627          NULL
     2628          );
     2629        if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {
    23972630          Status = DeletePlatformKey ();
    2398           *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
     2631          if (EFI_ERROR (Status)) {
     2632            CreatePopUp (
     2633              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
     2634              &Key,
     2635              L"Only Physical Presence User could delete PK in custom mode!",
     2636              NULL
     2637              );
     2638          }
    23992639        }
     2640      }
    24002641      break;
    24012642
     
    24362677    case KEY_VALUE_SAVE_AND_EXIT_KEK:
    24372678      Status = EnrollKeyExchangeKey (Private);
     2679      if (EFI_ERROR (Status)) {
     2680        CreatePopUp (
     2681          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
     2682          &Key,
     2683          L"ERROR: Unsupported file type!",
     2684          L"Only supports DER-encoded X509 certificate",
     2685          NULL
     2686          );
     2687      }
    24382688      break;
    24392689
    24402690    case KEY_VALUE_SAVE_AND_EXIT_DB:
    24412691      Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);
     2692      if (EFI_ERROR (Status)) {
     2693        CreatePopUp (
     2694          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
     2695          &Key,
     2696          L"ERROR: Unsupported file type!",
     2697          L"Only supports DER-encoded X509 certificate and executable EFI image",
     2698          NULL
     2699          );
     2700      }
    24422701      break;
    24432702
    24442703    case KEY_VALUE_SAVE_AND_EXIT_DBX:
    24452704      Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);
     2705      if (EFI_ERROR (Status)) {
     2706        CreatePopUp (
     2707          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
     2708          &Key,
     2709          L"ERROR: Unsupported file type!",
     2710          L"Only supports DER-encoded X509 certificate and executable EFI image",
     2711          NULL
     2712          );
     2713      }
    24462714      break;
    24472715
    24482716    default:
    2449       if (QuestionId >= FILE_OPTION_OFFSET) {
     2717      if (QuestionId >= FILE_OPTION_GOTO_OFFSET) {
    24502718        UpdateFileExplorer (Private, QuestionId);
    24512719      } else if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&
     
    24802748    switch (QuestionId) {
    24812749    case KEY_SECURE_BOOT_ENABLE:
    2482       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;     
     2750      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
    24832751      break; 
    24842752    case KEY_VALUE_SAVE_AND_EXIT_PK:
    24852753      Status = EnrollPlatformKey (Private);
    24862754      if (EFI_ERROR (Status)) {
     2755        UnicodeSPrint (
     2756          PromptString,
     2757          sizeof (PromptString),
     2758          L"Only DER encoded certificate file (%s) is supported.",
     2759          mSupportX509Suffix
     2760          );
    24872761        CreatePopUp (
    24882762          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
    24892763          &Key,
    2490           L"ERROR: Unsupported file type, only *.cer is supported!",
     2764          L"ERROR: Unsupported file type!",
     2765          PromptString,
    24912766          NULL
    24922767          );
    24932768      } else {
    2494         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
     2769        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;
    24952770      }       
    24962771      break;
     
    25142789     
    25152790    case KEY_SECURE_BOOT_MODE:
    2516       if (NULL != GetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid)) {
    2517         Status = gRT->SetVariable (                         
    2518                         EFI_CUSTOM_MODE_NAME,
    2519                         &gEfiCustomModeEnableGuid,
    2520                         EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    2521                         sizeof (UINT8),
    2522                         &Value->u8
    2523                         );
    2524         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
    2525         IfrNvData->SecureBootMode = Value->u8;
    2526       }       
     2791      mIsEnterSecureBootForm = FALSE;
    25272792      break;
    25282793
     
    25442809
    25452810    case KEY_SECURE_BOOT_DELETE_PK:
    2546       if (Value->u8) {
     2811      GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);
     2812      if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {
     2813        IfrNvData->DeletePk = TRUE;
     2814        IfrNvData->HasPk    = FALSE;
    25472815        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
     2816      } else  {
     2817        IfrNvData->DeletePk = FALSE;
     2818        IfrNvData->HasPk    = TRUE;
     2819        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
    25482820      }
    2549       break; 
     2821      if (SetupMode != NULL) {
     2822        FreePool (SetupMode);
     2823      }
     2824      break;
     2825    default:
     2826      if (QuestionId >= FILE_OPTION_OFFSET && QuestionId < FILE_OPTION_GOTO_OFFSET) {
     2827        if (UpdateFileExplorer (Private, QuestionId)) {
     2828          *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
     2829        }
     2830      }
     2831      break;
     2832    }
     2833  } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) {
     2834    if (QuestionId == KEY_HIDE_SECURE_BOOT) {
     2835      GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
     2836      if (SecureBootEnable == NULL) {
     2837        IfrNvData->HideSecureBoot = TRUE;
     2838      } else {
     2839        FreePool (SecureBootEnable);
     2840        IfrNvData->HideSecureBoot = FALSE;
     2841      }
     2842      Value->b = IfrNvData->HideSecureBoot;
     2843    }
     2844  } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
     2845    //
     2846    // Force the platform back to Standard Mode once user leave the setup screen.
     2847    //
     2848    GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);
     2849    if (NULL != SecureBootMode && *SecureBootMode == CUSTOM_SECURE_BOOT_MODE) {
     2850      IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;
     2851      SetSecureBootMode(STANDARD_SECURE_BOOT_MODE);
     2852    }
     2853    if (SecureBootMode != NULL) {
     2854      FreePool (SecureBootMode);
    25502855    }
    25512856  }
     
    25532858  if (!EFI_ERROR (Status)) {
    25542859    BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
    2555     HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8*) IfrNvData, NULL);
     2860    HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL);
    25562861  }
    25572862  FreePool (IfrNvData);
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h

    r48674 r58459  
    2424#include <Protocol/BlockIo.h>
    2525#include <Protocol/DevicePath.h>
    26 #include <Protocol/DevicePathToText.h>
    2726#include <Protocol/DebugPort.h>
    2827#include <Protocol/LoadFile.h>
  • trunk/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h

    r48674 r58459  
    22  Header file for NV data structure definition.
    33
    4 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
     4Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
    55This program and the accompanying materials
    66are licensed and made available under the terms and conditions of the BSD License
     
    5656#define KEY_VALUE_SAVE_AND_EXIT_DBX           0x100a
    5757#define KEY_VALUE_NO_SAVE_AND_EXIT_DBX        0x100b
     58#define KEY_HIDE_SECURE_BOOT                  0x100c
    5859
    5960#define KEY_SECURE_BOOT_OPTION                0x1100
     
    9596#define OPTION_DEL_DBX_QUESTION_ID            0x4000
    9697
    97 
     98#define FILE_OPTION_GOTO_OFFSET               0xC000
    9899#define FILE_OPTION_OFFSET                    0x8000
    99 #define FILE_OPTION_MASK                      0x7FFF
     100#define FILE_OPTION_MASK                      0x3FFF
    100101
    101102#define SECURE_BOOT_GUID_SIZE                 36
     
    107108//
    108109typedef struct {
    109   BOOLEAN SecureBootState; //Secure Boot Disable/Enable;
     110  BOOLEAN AttemptSecureBoot;  //Attempt to enable/disable Secure Boot.
    110111  BOOLEAN HideSecureBoot;  //Hiden Attempt Secure Boot
    111112  CHAR16  SignatureGuid[SECURE_BOOT_GUID_STORAGE_SIZE];
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette