fsvariable.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,279 行 · 第 1/3 页

C
1,279
字号
/*++

Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution.  The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

Module Name:

  FSVariable.c

Abstract:

  Provide support functions for variable services.

--*/

#include "FSVariable.h"
#include "EfiRuntimeLib.h"
#include EFI_ARCH_PROTOCOL_DEFINITION (Variable)
#include EFI_ARCH_PROTOCOL_DEFINITION (VariableWrite)
#include "PatchVariable.h"

VARIABLE_STORE_HEADER mValidStoreHeaderTemplate = {
  VARIABLE_STORE_SIGNATURE,
  VARIABLE_STORE_SIZE,
  VARIABLE_STORE_FORMATTED,
  VARIABLE_STORE_HEALTHY,
  0,
  0
};

//
// Don't use module globals after the SetVirtualAddress map is signaled
//
VARIABLE_GLOBAL  *mGlobal;
VOID             *mSFSRegistration;

STATIC
VOID
EFIAPI
OnVirtualAddressChange (
  IN EFI_EVENT        Event,
  IN VOID             *Context
  );

STATIC
VOID
EFIAPI
OnSimpleFileSystemInstall (
  IN EFI_EVENT        Event,
  IN VOID             *Context
  );

STATIC
BOOLEAN
IsValidVariableHeader (
  IN  VARIABLE_HEADER   *Variable
  )
/*++

Routine Description:

  This code checks if variable header is valid or not.

Arguments:
  Variable        Pointer to the Variable Header.

Returns:
  TRUE            Variable header is valid.
  FALSE           Variable header is not valid.

--*/
{
  if (Variable == NULL ||
      Variable->StartId != VARIABLE_DATA ||
      (sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize) > MAX_VARIABLE_SIZE
      ) {
    return FALSE;
  }

  return TRUE;
}

STATIC
VARIABLE_STORE_STATUS
GetVariableStoreStatus (
  IN VARIABLE_STORE_HEADER *VarStoreHeader
  )
/*++

Routine Description:

  This code gets the current status of Variable Store.

Arguments:

  VarStoreHeader  Pointer to the Variable Store Header.

Returns:

  EfiRaw        Variable store status is raw
  EfiValid      Variable store status is valid
  EfiInvalid    Variable store status is invalid

--*/
{
  if (EfiCompareMem (VarStoreHeader, &mValidStoreHeaderTemplate, sizeof (*VarStoreHeader)) == 0) {
    return EfiValid;
  } else if (VarStoreHeader->Signature == VAR_DEFAULT_VALUE_32 &&
           VarStoreHeader->Size == VAR_DEFAULT_VALUE_32 &&
           VarStoreHeader->Format == VAR_DEFAULT_VALUE &&
           VarStoreHeader->State == VAR_DEFAULT_VALUE
          ) {

    return EfiRaw;
  } else {
    return EfiInvalid;
  }
}

STATIC
UINT8 *
GetVariableDataPtr (
  IN  VARIABLE_HEADER   *Variable
  )
/*++

Routine Description:

  This code gets the pointer to the variable data.

Arguments:

  Variable            Pointer to the Variable Header.

Returns:

  UINT8*              Pointer to Variable Data

--*/
{
  //
  // Be careful about pad size for alignment
  //
  return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));
}

STATIC
VARIABLE_HEADER *
GetNextVariablePtr (
  IN  VARIABLE_HEADER   *Variable
  )
/*++

Routine Description:

  This code gets the pointer to the next variable header.

Arguments:

  Variable              Pointer to the Variable Header.

Returns:

  VARIABLE_HEADER*      Pointer to next variable header.

--*/
{
  if (!IsValidVariableHeader (Variable)) {
    return NULL;
  }
  //
  // Be careful about pad size for alignment
  //
  return (VARIABLE_HEADER *) ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));
}

STATIC
VARIABLE_HEADER *
GetEndPointer (
  IN VARIABLE_STORE_HEADER       *VarStoreHeader
  )
/*++

Routine Description:

  This code gets the pointer to the last variable memory pointer byte

Arguments:

  VarStoreHeader        Pointer to the Variable Store Header.

Returns:

  VARIABLE_HEADER*      Pointer to last unavailable Variable Header

--*/
{
  //
  // The end of variable store
  //
  return (VARIABLE_HEADER *) ((UINTN) VarStoreHeader + VarStoreHeader->Size);
}

STATIC
EFI_STATUS
Reclaim (
  IN  VARIABLE_STORAGE_TYPE StorageType,
  IN  VARIABLE_HEADER       *CurrentVariable OPTIONAL
  )
/*++

Routine Description:

  Variable store garbage collection and reclaim operation

Arguments:

  IsVolatile                  The variable store is volatile or not,
                              if it is non-volatile, need FTW
  CurrentVairable             If it is not NULL, it means not to process
                              current variable for Reclaim.

Returns:

  EFI STATUS

--*/
{
  VARIABLE_HEADER       *Variable;
  VARIABLE_HEADER       *NextVariable;
  VARIABLE_STORE_HEADER *VariableStoreHeader;
  UINT8                 *ValidBuffer;
  UINTN                 ValidBufferSize;
  UINTN                 VariableSize;
  UINT8                 *CurrPtr;
  EFI_STATUS            Status;

  VariableStoreHeader = (VARIABLE_STORE_HEADER *) mGlobal->VariableBase[StorageType];

  //
  // Start Pointers for the variable.
  //
  Variable        = (VARIABLE_HEADER *) (VariableStoreHeader + 1);

  ValidBufferSize = sizeof (VARIABLE_STORE_HEADER);

  while (IsValidVariableHeader (Variable)) {
    NextVariable = GetNextVariablePtr (Variable);
    if ((Variable->State == VAR_ADDED) ||
        ((Variable != CurrentVariable) &&
         (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)))) {
      VariableSize = (UINTN) NextVariable - (UINTN) Variable;
      ValidBufferSize += VariableSize;
    }

    Variable = NextVariable;
  }

  Status = gBS->AllocatePool (
                  EfiBootServicesData,
                  ValidBufferSize,
                  &ValidBuffer
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  CurrPtr = ValidBuffer;

  //
  // Copy variable store header
  //
  EfiCopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));
  CurrPtr += sizeof (VARIABLE_STORE_HEADER);

  //
  // Start Pointers for the variable.
  //
  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);

  while (IsValidVariableHeader (Variable)) {
    NextVariable = GetNextVariablePtr (Variable);
    if ((Variable->State == VAR_ADDED) ||
        ((Variable != CurrentVariable) &&
         (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)))) {
      VariableSize = (UINTN) NextVariable - (UINTN) Variable;
      EfiCopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
      //
      // Mark all variable as VAR_ADDED
      //
      ((VARIABLE_HEADER *)CurrPtr)->State = VAR_ADDED;
      CurrPtr += VariableSize;
    }

    Variable = NextVariable;
  }

  //
  // TODO: cannot restore to original state, basic FTW needed
  //
  Status = mGlobal->VariableStore[StorageType]->Erase (
                                                  mGlobal->VariableStore[StorageType]
                                                  );
  Status = mGlobal->VariableStore[StorageType]->Write (
                                                    mGlobal->VariableStore[StorageType],
                                                    0,
                                                    ValidBufferSize,
                                                    ValidBuffer
                                                    );

  // ASSERT_EFI_ERROR (Status);

  mGlobal->LastVariableOffset[StorageType] = ValidBufferSize;
  gBS->FreePool (ValidBuffer);

  return Status;
}

STATIC
EFI_STATUS
FindVariable (
  IN  CHAR16                  *VariableName,
  IN  EFI_GUID                *VendorGuid,
  OUT VARIABLE_POINTER_TRACK  *PtrTrack
  )
/*++

Routine Description:

  This code finds variable in storage blocks (Volatile or Non-Volatile)

Arguments:

  VariableName                Name of the variable to be found
  VendorGuid                  Vendor GUID to be found.
  PtrTrack                    Variable Track Pointer structure that contains
                              Variable Information.
                              Contains the pointer of Variable header.

Returns:

  EFI STATUS

--*/
{
  VARIABLE_HEADER         *Variable;
  VARIABLE_STORE_HEADER   *VariableStoreHeader;
  UINTN                   Index;
  VARIABLE_HEADER         *InDeleteVariable;
  UINTN                   InDeleteIndex;

  if (VariableName[0] != 0 && VendorGuid == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  InDeleteVariable = NULL;
  InDeleteIndex    = (UINTN)-1;

  for (Index = 0; Index < MaxType; Index ++) {
    //
    // 0: Non-Volatile, 1: Volatile
    //
    VariableStoreHeader = (VARIABLE_STORE_HEADER *) mGlobal->VariableBase[Index];

    //
    // Start Pointers for the variable.
    // Actual Data Pointer where data can be written.
    //
    Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);

    //
    // Find the variable by walk through non-volatile and volatile variable store
    //
    PtrTrack->StartPtr  = Variable;
    PtrTrack->EndPtr    = GetEndPointer (VariableStoreHeader);

    while (IsValidVariableHeader (Variable) && (Variable < PtrTrack->EndPtr)) {
      if (Variable->State == VAR_ADDED) {
        if (!EfiAtRuntime () || (Variable->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
          if (VariableName[0] == 0) {
            PtrTrack->CurrPtr = Variable;
            PtrTrack->Type    = (VARIABLE_STORAGE_TYPE) Index;
            return EFI_SUCCESS;
          } else {
            if (EfiCompareGuid (VendorGuid, &Variable->VendorGuid)) {
              if (!EfiCompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), EfiStrSize (VariableName))) {
                PtrTrack->CurrPtr = Variable;
                PtrTrack->Type    = (VARIABLE_STORAGE_TYPE) Index;
                return EFI_SUCCESS;
              }
            }
          }
        }
      } else if (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)) {
        //
        // VAR_IN_DELETED_TRANSITION should also be checked.
        //
        if (!EfiAtRuntime () || (Variable->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
          if (VariableName[0] == 0) {
            InDeleteVariable = Variable;
            InDeleteIndex    = Index;
          } else {
            if (EfiCompareGuid (VendorGuid, &Variable->VendorGuid)) {
              if (!EfiCompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), EfiStrSize (VariableName))) {
                InDeleteVariable = Variable;
                InDeleteIndex    = Index;
              }
            }
          }
        }
      }

      Variable = GetNextVariablePtr (Variable);
    }
    //
    // While (...)
    //
  }
  //
  // for (...)
  //

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?