variable.c

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

C
1,542
字号
                );

      if (EFI_ERROR (Status)) {
        return Status;
      }
      //
      // Step 2:
      //
      Status = UpdateVariableStore (
                Global,
                FALSE,
                TRUE,
                Instance,
                *NonVolatileOffset + sizeof (VARIABLE_HEADER),
                (UINT32) VarSize - sizeof (VARIABLE_HEADER),
                (UINT8 *) NextVariable + sizeof (VARIABLE_HEADER)
                );

      if (EFI_ERROR (Status)) {
        return Status;
      }
      //
      // Step 3:
      //
      NextVariable->State = VAR_ADDED;
      Status = UpdateVariableStore (
                Global,
                FALSE,
                TRUE,
                Instance,
                *NonVolatileOffset,
                sizeof (VARIABLE_HEADER),
                (UINT8 *) NextVariable
                );

      if (EFI_ERROR (Status)) {
        return Status;
      }

      *NonVolatileOffset = *NonVolatileOffset + VarSize;

    } else {
      if (EfiAtRuntime ()) {
        return EFI_INVALID_PARAMETER;
      }

      if ((UINT32) (VarSize +*VolatileOffset) >
            ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size
            ) {
        //
        // Perform garbage collection & reclaim operation
        //
        Status = Reclaim (Global->VolatileVariableBase, VolatileOffset, TRUE, Variable.CurrPtr);
        if (EFI_ERROR (Status)) {
          return Status;
        }
        //
        // If still no enough space, return out of resources
        //
        if ((UINT32) (VarSize +*VolatileOffset) >
              ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size
              ) {
          return EFI_OUT_OF_RESOURCES;
        }
        
        Reclaimed = TRUE;
      }

      NextVariable->State = VAR_ADDED;
      Status = UpdateVariableStore (
                Global,
                TRUE,
                TRUE,
                Instance,
                *VolatileOffset,
                (UINT32) VarSize,
                (UINT8 *) NextVariable
                );

      if (EFI_ERROR (Status)) {
        return Status;
      }

      *VolatileOffset = *VolatileOffset + VarSize;
    }
    //
    // Mark the old variable as deleted
    //
    if (!Reclaimed && !EFI_ERROR (Status) && Variable.CurrPtr != NULL) {
      State = Variable.CurrPtr->State;
      State &= VAR_DELETED;

      Status = UpdateVariableStore (
                Global,
                Variable.Volatile,
                FALSE,
                Instance,
                (UINTN) &Variable.CurrPtr->State,
                sizeof (UINT8),
                &State
                );

      if (EFI_ERROR (Status)) {
        return Status;
      }
    }
  }

  return EFI_SUCCESS;
}

#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
EFI_STATUS
EFIAPI
QueryVariableInfo (
  IN  UINT32                 Attributes,
  OUT UINT64                 *MaximumVariableStorageSize,
  OUT UINT64                 *RemainingVariableStorageSize,
  OUT UINT64                 *MaximumVariableSize,
  IN  VARIABLE_GLOBAL        *Global,
  IN  UINT32                 Instance
  )
/*++

Routine Description:

  This code returns information about the EFI variables.

Arguments:

  Attributes                      Attributes bitmask to specify the type of variables 
                                  on which to return information.
  MaximumVariableStorageSize      Pointer to the maximum size of the storage space available
                                  for the EFI variables associated with the attributes specified.
  RemainingVariableStorageSize    Pointer to the remaining size of the storage space available 
                                  for the EFI variables associated with the attributes specified.
  MaximumVariableSize             Pointer to the maximum size of the individual EFI variables
                                  associated with the attributes specified.
  Global                          Pointer to VARIABLE_GLOBAL structure.
  Instance                        Instance of the Firmware Volume.

Returns:

  EFI STATUS
  EFI_INVALID_PARAMETER           - An invalid combination of attribute bits was supplied.
  EFI_SUCCESS                     - Query successfully.
  EFI_UNSUPPORTED                 - The attribute is not supported on this platform.

--*/
{
  VARIABLE_HEADER        *Variable;
  VARIABLE_HEADER        *NextVariable;
  UINT64                 VariableSize;
  VARIABLE_STORE_HEADER  *VariableStoreHeader;
  
  if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) == 0) {
    //
    // Make sure the Attributes combination is supported by the platform.
    //
    return EFI_UNSUPPORTED;
  } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
    //
    // Make sure if runtime bit is set, boot service bit is set also.
    //
    return EFI_INVALID_PARAMETER;
  } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
    //
    // Make sure RT Attribute is set if we are in Runtime phase.
    //
    return EFI_INVALID_PARAMETER;
  }  else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {
    //
    // Cannot Query volatile variable in Runtime
    //
    return EFI_INVALID_PARAMETER;
  }

  if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
    //
    // Query is Volatile related.
    //
    VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);    
  } else {
    //
    // Query is Non-Volatile related.
    //
    VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);
  }

  //
  // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize 
  // with the storage size (excluding the storage header size).
  //
  *MaximumVariableStorageSize   = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
  *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);

  //
  // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
  //
  *MaximumVariableSize = MAX_VARIABLE_SIZE;

  //
  // Point to the starting address of the variables.
  //
  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);

  //
  // Now walk through the related variable store.
  //
  while (IsValidVariableHeader (Variable) && (Variable < GetEndPointer (VariableStoreHeader))) {
    NextVariable = GetNextVariablePtr (Variable);
    VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;

    if (EfiAtRuntime ()) {
      //
      // we don't take the state of the variables in mind 
      // when calculating RemainingVariableStorageSize,
      // since the space occupied by variables not marked with 
      // VAR_ADDED is not allowed to be reclaimed in Runtime.
      //
      *RemainingVariableStorageSize -= VariableSize;
    } else {
      //
      // Only care about Variables with State VAR_ADDED,because 
      // the space not marked as VAR_ADDED is reclaimable now.
      //
      if ((Variable->State == VAR_ADDED) ||
          (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {
        *RemainingVariableStorageSize -= VariableSize;
      }
    }
    
    //
    // Go to the next one
    //
    Variable = NextVariable;
  }
 
  return EFI_SUCCESS;
}
#endif

EFI_STATUS
EFIAPI
VariableCommonInitialize (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
/*++

Routine Description:
  This function does common initialization for variable services

Arguments:

  ImageHandle   - The firmware allocated handle for the EFI image.
  SystemTable   - A pointer to the EFI System Table.

Returns:
  
  Status code.
  
  EFI_NOT_FOUND     - Variable store area not found.
  EFI_UNSUPPORTED   - Currently only one non-volatile variable store is supported.
  EFI_SUCCESS       - Variable services successfully initialized.

--*/
{
  EFI_STATUS                      Status;
  VOID                            *HobList;
  EFI_FIRMWARE_VOLUME_HEADER      *FwVolHeader;
  CHAR8                           *CurrPtr;
  VARIABLE_STORE_HEADER           *VolatileVariableStore;
  VARIABLE_STORE_HEADER           *VariableStoreHeader;
  VARIABLE_HEADER                 *NextVariable;
  UINT32                          Instance;
  EFI_PHYSICAL_ADDRESS            FvVolHdr;

  VOID                            *Buffer;
  EFI_FLASH_MAP_ENTRY_DATA        *FlashMapEntryData;
  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
  EFI_FLASH_SUBAREA_ENTRY         VariableStoreEntry;
  UINT64                          BaseAddress;
  UINT64                          Length;
  UINTN                           Index;
  UINT8                           Data;

  EfiInitializeRuntimeDriverLib (
    ImageHandle,
    SystemTable,
    VariableClassAddressChangeEvent
    );

  Status = gBS->AllocatePool (
                  EfiRuntimeServicesData,
                  sizeof (ESAL_VARIABLE_GLOBAL),
                  &mVariableModuleGlobal
                  );

  if (EFI_ERROR (Status)) {
    goto Shutdown;
  }
  //
  // Allocate memory for volatile variable store
  //
  Status = gBS->AllocatePool (
                  EfiRuntimeServicesData,
                  VARIABLE_STORE_SIZE + SCRATCH_SIZE,
                  &VolatileVariableStore
                  );

  if (EFI_ERROR (Status)) {
    goto Shutdown_Free_mVariableModuleGlobal;
  }

  EfiSetMem (VolatileVariableStore, VARIABLE_STORE_SIZE + SCRATCH_SIZE, 0xff);

  //
  //  Variable Specific Data
  //
  mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;
  mVariableModuleGlobal->VolatileLastVariableOffset = sizeof (VARIABLE_STORE_HEADER);

  VolatileVariableStore->Signature                  = VARIABLE_STORE_SIGNATURE;
  VolatileVariableStore->Size                       = VARIABLE_STORE_SIZE;
  VolatileVariableStore->Format                     = VARIABLE_STORE_FORMATTED;
  VolatileVariableStore->State                      = VARIABLE_STORE_HEALTHY;
  VolatileVariableStore->Reserved                   = 0;
  VolatileVariableStore->Reserved1                  = 0;

  //
  // Get non volatile varaible store
  //
  Status = EfiFvbInitialize ();
  if (EFI_ERROR (Status)) {
    goto Shutdown_Free_VolatileVariableStore;
  }

  Status = EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);

  if (EFI_ERROR (Status)) {
    goto Shutdown_Fvb;
  }

  FlashMapEntryData = NULL;

  for (;;) {
    Status = GetNextGuidHob (&HobList, &gEfiFlashMapHobGuid, &Buffer, NULL);
    if (EFI_ERROR (Status)) {
      break;
    }

    FlashMapEntryData = (EFI_FLASH_MAP_ENTRY_DATA *) Buffer;

    //
    // Get the variable store area
    //
    if (FlashMapEntryData->AreaType == EFI_FLASH_AREA_EFI_VARIABLES) {
      break;
    }
  }

  if (EFI_ERROR (Status) || FlashMapEntryData == NULL) {
    Status = EFI_NOT_FOUND;
    goto Shutdown_Fvb;
  }

  FlashMapEntryData = (EFI_FLASH_MAP_ENTRY_DATA *) Buffer;

  //
  // Currently only one non-volatile variable store is supported
  //
  if (FlashMapEntryData->NumEntries != 1) {
    Status = EFI_UNSUPPORTED;
    goto Shutdown_Fvb;
  }

  VariableStoreEntry = FlashMapEntryData->Entries[0];

  //
  // Mark the variable storage region of the FLASH as RUNTIME
  //
  BaseAddress = VariableStoreEntry.Base & (~EFI_PAGE_MASK);
  Length      = VariableStoreEntry.Length + (VariableStoreEntry.Base - BaseAddress);
  Length      = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);

  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
  if (EFI_ERROR (Status)) {
    Status = EFI_UNSUPPORTED;
    goto Shutdown_Fvb;
  }

  Status = gDS->SetMemorySpaceAttributes (
                  BaseAddress,
                  Length,
                  GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME
                  );
  if (EFI_ERROR (Status)) {
    Status = EFI_UNSUPPORTED;
    goto Shutdown_Fvb;
  }
  //
  // Get address of non volatile variable store base
  //
  mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase = VariableStoreEntry.Base;

  //
  // Check Integrity
  //
  //
  // Find the Correct Instance of the FV Block Service.
  //
  Instance  = 0;
  CurrPtr   = (CHAR8 *) ((UINTN) mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase);
  while (EfiFvbGetPhysicalAddress (Instance, &FvVolHdr) == EFI_SUCCESS) {
    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);
    if (CurrPtr >= (CHAR8 *) FwVolHeader && CurrPtr < (((CHAR8 *) FwVolHeader) + FwVolHeader->FvLength)) {
      mVariableModuleGlobal->FvbInstance = Instance;
      break;
    }

    Instance++;
  }

  VariableStoreHeader = (VARIABLE_STORE_HEADER *) CurrPtr;
  if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {
    if (~VariableStoreHeader->Size == 0) {
      Status = UpdateVariableStore (
                &mVariableModuleGlobal->VariableBase[Physical],
                FALSE,
                FALSE,
                mVariableModuleGlobal->FvbInstance,
                (UINTN) &VariableStoreHeader->Size,
                sizeof (UINT32),
                (CHAR8 *) &VariableStoreEntry.Length
                );

      if (EFI_ERROR (Status)) {
        goto Shutdown_Fvb;
      }
    }

    mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) CurrPtr);
    //
    // Parse non-volatile variable data and get last variable offset
    //
    NextVariable  = (VARIABLE_HEADER *) (CurrPtr + sizeof (VARIABLE_STORE_HEADER));
    Status        = EFI_SUCCESS;

    while (IsValidVariableHeader (NextVariable)) {
      NextVariable = GetNextVariablePtr (NextVariable);
    }

    mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) CurrPtr;

    //
    // Check if the free area is blow a threshold
    //
    if ((((VARIABLE_STORE_HEADER *)((UINTN) CurrPtr))->Size - mVariableModuleGlobal->NonVolatileLastVariableOffset) < VARIABLE_RECLAIM_THRESHOLD) {
      Status = Reclaim (
                mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase,
                &mVariableModuleGlobal->NonVolatileLastVariableOffset,
                FALSE,
                NULL
                );
    }

    if (EFI_ERROR (Status)) {
      gBS->FreePool (mVariableModuleGlobal);
      gBS->FreePool (VolatileVariableStore);
      return Status;
    }

    //
    // Check if the free area is really free.
    //
    for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreHeader->Size; Index++) {
      Data = ((UINT8 *) (UINTN) mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase)[Index];
      if (Data != 0xff) {
        //
        // There must be something wrong in variable store, do reclaim operation.
        //
        Status = Reclaim (
                  mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase,
                  &mVariableModuleGlobal->NonVolatileLastVariableOffset,
                  FALSE,
                  NULL
                  );
        break;
      }
    }
  }

  if (EFI_ERROR (Status)) {
    goto Shutdown_Fvb;
  }
  return Status;
Shutdown_Fvb:
  EfiFvbShutdown ();

Shutdown_Free_VolatileVariableStore:
    gBS->FreePool (VolatileVariableStore);
Shutdown_Free_mVariableModuleGlobal:
  gBS->FreePool (mVariableModuleGlobal);

Shutdown:
  EfiShutdownRuntimeDriverLib ();
  return Status;
}

⌨️ 快捷键说明

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