/** 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; } }
/** 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; }