Beispiel #1
0
/**
  Install FvInfo PPI and create fv hobs for remained fvs

**/
VOID
CbPeiReportRemainedFvs (
  VOID
  )
{
  UINT8*  TempPtr;
  UINT8*  EndPtr;

  TempPtr = (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase);
  EndPtr = (UINT8* )(UINTN) (PcdGet32 (PcdPayloadFdMemBase) + PcdGet32 (PcdPayloadFdMemSize));

  for (;TempPtr < EndPtr;) {
    if (IsFvHeaderValid ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)) {
      if (TempPtr != (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase))  {
        // Skip the PEI FV
        DEBUG((EFI_D_ERROR, "Found one valid fv : 0x%lx.\n", TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength));

        PeiServicesInstallFvInfoPpi (
          NULL,
          (VOID *) (UINTN) TempPtr,
          (UINT32) (UINTN) ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength,
          NULL,
          NULL
          );
        BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN) TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength);
      }
    }
    TempPtr += ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength;
  }
}
Beispiel #2
0
/**
  The driver entry point for Firmware Volume Block Driver.

  The function does the necessary initialization work
  Firmware Volume Block Driver.

  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
  @param[in]  SystemTable       A pointer to the EFI system table.

  @retval     EFI_SUCCESS       This funtion always return EFI_SUCCESS.
                                It will ASSERT on errors.

**/
EFI_STATUS
FvbInitialize (
  )
{
  EFI_FW_VOL_INSTANCE                   *FwhInstance;
  EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader;
  EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;
  EFI_FV_BLOCK_MAP_ENTRY                *PtrBlockMapEntry;
  EFI_PHYSICAL_ADDRESS                  BaseAddress;
  EFI_STATUS                            Status;
  UINTN                                 BufferSize;
  UINTN                                 TmpHeaderLength;
  UINTN                                 Idx;
  UINT32                                MaxLbaSize;
  BOOLEAN                               FvHeaderValid;
  UINTN                                 FvFlashLinearAddress;
  EFI_BOOT_MODE                         BootMode;
  UINT32                                Index;
  UINT32                                PlatformFvBaseAddress[5];
  UINT32                                PlatformFvBaseAddressCount;
  UINT32                                PlatformFvLockList[4];
  UINT32                                PlatformFvLockListCount;
  
  //
  // This platform driver knows there are 3 FVs on
  // FD, which are FvRecovery, FvMain and FvNvStorage.
  //
  BootMode = GetBootModeHob ();
  if (BootMode == BOOT_IN_RECOVERY_MODE) {
    //
    // On recovery boot, don't report any firmware FV images except payload, because their data can't be trusted.
    //
    PlatformFvBaseAddressCount = 2;
    PlatformFvBaseAddress[0]   = PcdGet32 (PcdFlashNvStorageVariableBase);
    PlatformFvBaseAddress[1]   = PcdGet32 (PcdFlashPayloadBase);
  } else {
    PlatformFvBaseAddressCount = 5;
    PlatformFvBaseAddress[0]   = PcdGet32 (PcdFlashFvMainBase);
    PlatformFvBaseAddress[1]   = PcdGet32 (PcdFlashNvStorageVariableBase);
    PlatformFvBaseAddress[2]   = PcdGet32 (PcdFlashFvRecoveryBase);
    PlatformFvBaseAddress[3]   = PcdGet32 (PcdFlashFvRecovery2Base);
    PlatformFvBaseAddress[4]   = PcdGet32 (PcdFlashPayloadBase);
  }

  //
  // List of FVs that should be write protected on normal boots.
  //
  PlatformFvLockListCount = 4;
  PlatformFvLockList[0]   = PcdGet32 (PcdFlashFvMainBase);
  PlatformFvLockList[1]   = PcdGet32 (PcdFlashFvRecoveryBase);
  PlatformFvLockList[2]   = PcdGet32 (PcdFlashFvRecovery2Base);
  PlatformFvLockList[3]   = PcdGet32 (PcdFlashPayloadBase);

  //
  // Calculate the total size for all firmware volume block instances and
  // allocate a buffer to store them in.
  //
  BufferSize = 0;
  for (Idx = 0; Idx < PlatformFvBaseAddressCount; Idx++) {
    FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PlatformFvBaseAddress[Idx];
    if (FvHeader == NULL) {
      continue;
    }
    BufferSize +=  (FvHeader->HeaderLength +
                    sizeof (EFI_FW_VOL_INSTANCE) -
                    sizeof (EFI_FIRMWARE_VOLUME_HEADER)
                   );
  }
  mFvbModuleGlobal.FvInstance =  (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize);
  ASSERT (NULL != mFvbModuleGlobal.FvInstance);

  //
  // Perform other variable initialization.
  //
  MaxLbaSize = 0;
  FwhInstance = mFvbModuleGlobal.FvInstance;
  mFvbModuleGlobal.NumFv   = 0;

  for (Idx = 0; Idx < PlatformFvBaseAddressCount; Idx++) {
  
    if ((BootMode == BOOT_ASSUMING_NO_CONFIGURATION_CHANGES) && PlatformFvBaseAddress[Idx]!= PcdGet32 (PcdFlashNvStorageVariableBase) && PlatformFvBaseAddress[Idx]!= PcdGet32 (PcdFlashPayloadBase)) {
      continue;
    }
    //
    // Get base address information.
    //
    BaseAddress = PlatformFvBaseAddress[Idx];
    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;
    if (FwVolHeader == NULL) {
      continue;
    }
    //
    // Find the flash linear address of the current FV.
    //
    FvFlashLinearAddress = (UINTN) FLASH_LINEAR_ADDRESS(BaseAddress);

    if (!IsFvHeaderValid (BaseAddress, FwVolHeader)) {
      FvHeaderValid = FALSE;

      //
      // If not valid, get FvbInfo from the information carried in
      // FVB driver.
      //
      DEBUG ((EFI_D_ERROR, "Fvb: FV header @ 0x%lx invalid\n", BaseAddress));
      Status = GetFvbInfo (BaseAddress, &FwVolHeader);
      ASSERT_EFI_ERROR(Status);

      //
      //  Write back a healthy FV header.
      //
      DEBUG ((EFI_D_INFO, "FwBlockService.c: Writing back healthy FV header\n"));
      mSpiDeviceProtocol->SpiLock (FvFlashLinearAddress, FwVolHeader->BlockMap->Length, FALSE);

      Status = mSpiDeviceProtocol->SpiErase (FvFlashLinearAddress, FwVolHeader->BlockMap->Length);

      TmpHeaderLength = (UINTN) FwVolHeader->HeaderLength;
      Status = mSpiDeviceProtocol->SpiWrite (
                                     FvFlashLinearAddress,
                                     &TmpHeaderLength,
                                     (UINT8 *) FwVolHeader
                                     );

      mSpiDeviceProtocol->SpiLock (FvFlashLinearAddress, FwVolHeader->BlockMap->Length, TRUE);

      WriteBackInvalidateDataCacheRange (
        (VOID *) (UINTN) BaseAddress,
        FwVolHeader->BlockMap->Length
        );

    }

    //
    // Copy FV header into local storage and assign base address.
    //
    CopyMem (&(FwhInstance->VolumeHeader), FwVolHeader, FwVolHeader->HeaderLength);
    FwVolHeader = &(FwhInstance->VolumeHeader);
    FwhInstance->FvBase = (UINTN)BaseAddress;
    FwhInstance->FvFlashLinearAddress = FvFlashLinearAddress;

    //
    // In some cases the Recovery and Main FVs should be considered locked from
    // write access by this protocol.  Only in the case of flash updates and
    // configuration mode should they be left unlocked.
    //
    if (BootMode != BOOT_IN_RECOVERY_MODE &&
        BootMode != BOOT_ON_FLASH_UPDATE) {
      for (Index = 0; Index < PlatformFvLockListCount; Index++) {
        if (FwhInstance->FvBase == PlatformFvLockList[Index]) {
          //
          // For all FVs in the lock list we need to clear the write status bit
          // and lock write status updates.  This will make sure this protocol
          // will not attempt to write to the FV.
          //
          FwhInstance->VolumeHeader.Attributes &= (UINT64) ~EFI_FVB2_WRITE_STATUS;
          FwhInstance->VolumeHeader.Attributes |= (EFI_FVB2_LOCK_STATUS | EFI_FVB2_WRITE_LOCK_STATUS);
        }
      }
    }

    //
    // Process the block map for each FV
    //
    FwhInstance->NumOfBlocks   = 0;
    for (PtrBlockMapEntry = FwVolHeader->BlockMap;
         PtrBlockMapEntry->NumBlocks != 0;
         PtrBlockMapEntry++) {
      //
      // Get the maximum size of a block.
      //
      if (MaxLbaSize < PtrBlockMapEntry->Length) {
        MaxLbaSize  = PtrBlockMapEntry->Length;
      }
      FwhInstance->NumOfBlocks += PtrBlockMapEntry->NumBlocks;
    }

    //
    // Add a FVB Protocol Instance
    //
    mFvbModuleGlobal.NumFv++;
    InstallFvbProtocol (FwhInstance, mFvbModuleGlobal.NumFv - 1);

    //
    // Move on to the next FwhInstance
    //
    FwhInstance = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhInstance) +
                                          FwVolHeader->HeaderLength +
                                          (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));
  }

  if ((PcdGet32 (PcdFlashNvStorageFtwWorkingBase) == 0) || (PcdGet32 (PcdFlashNvStorageFtwSpareBase) == 0)) {
    return EFI_SUCCESS;
  }
  
  //
  // Install FVB protocols for FTW spare space and FTW working space.
  // These is no FV header for these 2 spaces.
  //
  mFvbModuleGlobal.FvInstance = (EFI_FW_VOL_INSTANCE *) ReallocateRuntimePool (
                                  BufferSize, 
                                  BufferSize + (sizeof (EFI_FW_VOL_INSTANCE) + sizeof (EFI_FV_BLOCK_MAP_ENTRY)) * 2, 
                                  mFvbModuleGlobal.FvInstance
                                  );
  ASSERT (NULL != mFvbModuleGlobal.FvInstance);
  PlatformFvBaseAddress[0] = PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
  PlatformFvBaseAddress[1] = PcdGet32 (PcdFlashNvStorageFtwSpareBase);
  
  for (Idx = 0; Idx < 2; Idx++) {
    BaseAddress = PlatformFvBaseAddress[Idx];
    Status = GetFtwFvbInfo (BaseAddress, &FwVolHeader);
    ASSERT_EFI_ERROR(Status);
  
    //
    // Copy FV header into local storage and assign base address.
    //
    mFvbModuleGlobal.NumFv++;
    FwhInstance = GetFvbInstance (mFvbModuleGlobal.NumFv - 1);
    CopyMem (&(FwhInstance->VolumeHeader), FwVolHeader, FwVolHeader->HeaderLength);
    FwVolHeader = &(FwhInstance->VolumeHeader);

    //
    // Process the block map for each FV
    //
    FwhInstance->NumOfBlocks   = 0;
    for (PtrBlockMapEntry = FwVolHeader->BlockMap;
         PtrBlockMapEntry->NumBlocks != 0;
         PtrBlockMapEntry++) {
      FwhInstance->NumOfBlocks += PtrBlockMapEntry->NumBlocks;
    }

    FwhInstance->FvBase = (UINTN)BaseAddress;
    FwhInstance->FvFlashLinearAddress = (UINTN) FLASH_LINEAR_ADDRESS(BaseAddress);

    InstallFvbProtocol (FwhInstance, mFvbModuleGlobal.NumFv - 1);
  }    
  
  return EFI_SUCCESS;
}