From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- Board/ReportFV2.c | 1060 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1060 insertions(+) create mode 100644 Board/ReportFV2.c (limited to 'Board/ReportFV2.c') diff --git a/Board/ReportFV2.c b/Board/ReportFV2.c new file mode 100644 index 0000000..b4ed589 --- /dev/null +++ b/Board/ReportFV2.c @@ -0,0 +1,1060 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Board/ReportFV2.c 2 10/25/12 9:20a Wesleychen $ +// +// $Revision: 2 $ +// +// $Date: 10/25/12 9:20a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Board/ReportFV2.c $ +// +// 2 10/25/12 9:20a Wesleychen +// Update Board to 4.6.5.4_Board_31. +// +// 1 2/24/12 7:59a Victortu +// [TAG] EIPEIP71398 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] BIOS Crisis Recovery halt on F1/3b very long time if +// LZMA_SUPPORT = 1 +// [Solution] Make sure all recovery-related FFS are outside of nested +// FV and do not publish it. +// +// 11 8/16/12 12:30p Artems +// [TAG] EIP N/A +// [Category] Improvement +// [Description] Added OEM hook to PublishNestedFv function +// [Files] Board.sdl Board.mak ReportFv2.c +// +// 10 8/03/12 5:26p Artems +// [TAG] EIP N/A +// [Category] Bug Fix +// [Severity] Critical +// [Symptom] System hangs randomly +// [RootCause] Rom layout section beginning is marked with unique GUID. +// However same GUID defined in code also, which leads to presence +// of two instances of the GUID in ROM file. Depending on which +// will be picked system hangs as underlying data can be incorrect +// [Solution] Added additional verification of validity of ROM layout +// section +// [Files] ReportFV2.c +// +// 9 11/11/11 3:19p Artems +// Publish ROM layout hob on recovery boot path +// Add verification of parent of nested FV +// +// 8 11/01/11 4:34p Artems +// Enaabled CheckBeforePublishing for Core 4.6.5.2 compatibility. +// +// 7 10/05/11 5:25p Artems +// Disabled CheckBeforePublishing for Core 4.6.5.1 compatibility. +// +// 6 10/05/11 4:49p Artems +// EIP 65805 - fixed problem with too many FVs published on recovery boot +// path +// +// 5 3/23/11 12:27p Artems +// Enhancement - do not terminate publishing of FVs when corrupted volume +// encountered +// +// 4 3/04/11 4:15p Artems +// Moved publishing of nested FV to DxeIpl stage for performance reasons +// +// 3 2/15/11 12:38p Artems +// Added RomLayoutHob publishing +// +// 2 2/07/11 5:22p Artems +// EIP 53374: Coding standard changes - replaced tabs with spaces, added +// functions headers +// +// 1 2/04/11 7:56p Artems +// +// 6 1/13/10 2:13p Felixp +// +//********************************************************************** +// +// +// Name: ReportFv.c +// +// Description: Implementation of flexible ROM layout infrastructure support +// +// +//********************************************************************** + +#include +#include +#include +#include +#include + +#define ROM_LAYOUT_FFS_GUID \ + { 0x0DCA793A, 0xEA96, 0x42d8, 0xBD, 0x7B, 0xDC, 0x7F, 0x68, 0x4E, 0x38, 0xC1 } + +#define ROM_LAYOUT_SECTION_GUID \ + { 0x88A15A4F, 0x977D, 0x4682, 0xB1, 0x7C, 0xDA, 0x1F, 0x31, 0x6C, 0x1F, 0x32 } + +#define NULL_GUID \ + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } + +typedef struct _ROM_LAYOUT_SECTION { + EFI_GUID FfsGuid; + UINT8 Reserved[12]; + EFI_GUID SectionGuid; + ROM_AREA Layout[1]; +} ROM_LAYOUT_SECTION; + +static EFI_GUID NullGuid = NULL_GUID; +static EFI_GUID RomLayoutFfsGuid = ROM_LAYOUT_FFS_GUID; +static EFI_GUID RomLayoutSectionGuid = ROM_LAYOUT_SECTION_GUID; +static EFI_GUID gEfiFirmwareVolumeInfoPpiGuid = EFI_PEI_FIRMWARE_VOLUME_INFO_PPI_GUID; + +typedef BOOLEAN (PROCESS_FV_BEFORE_PUBLISHING)( + IN EFI_PEI_SERVICES **PeiServices, IN OUT ROM_AREA *Area, IN UINT32 FvType +); +typedef BOOLEAN (PROCESS_DXEFV_IN_DXEIPL)( + IN EFI_PEI_SERVICES **PeiServices, IN OUT ROM_AREA *Area +); + +extern PROCESS_FV_BEFORE_PUBLISHING ProcessFvBeforePublishing EndOfFvHookList1; +extern PROCESS_DXEFV_IN_DXEIPL ProcessDxeFvInDxeIpl EndOfFvHookList2; + +PROCESS_FV_BEFORE_PUBLISHING* ProcessFvBeforePublishingList[]= + { ProcessFvBeforePublishing NULL }; +PROCESS_DXEFV_IN_DXEIPL* ProcessDxeFvInDxeIplList[]= + { ProcessDxeFvInDxeIpl NULL }; + +typedef EFI_STATUS (PROCESS_NESTED_FV_BEFORE_PUBLISHING)( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT ROM_AREA *Area, + OUT EFI_FIRMWARE_VOLUME_HEADER **Fv, + OUT EFI_FIRMWARE_VOLUME_HEADER **NewFv, + OUT EFI_FFS_FILE_HEADER **Nfv +); + +extern PROCESS_NESTED_FV_BEFORE_PUBLISHING ProcessNestedFvBeforePublishing EndOfFvHookList3; +PROCESS_NESTED_FV_BEFORE_PUBLISHING* ProcessNestedFvBeforePublishingList[]= + { ProcessNestedFvBeforePublishing NULL }; +// +//---------------------------------------------------------------------------- +// Procedure: ProcessFvBeforePublishingHook +// +// Description: Porting hook to support OEM-specific FV validation control flow +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN OUT ROM_AREA *Area - pointer to ROM Area, which contains FV +// to be processed +// IN UINT32 FvType - FV type +// +// Output: TRUE if validation is passed, FALSE otherwise +// +//---------------------------------------------------------------------------- +// +EFI_STATUS ProcessNestedFvBeforePublishingHook( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT ROM_AREA *Area, + OUT EFI_FIRMWARE_VOLUME_HEADER **Fv, + OUT EFI_FIRMWARE_VOLUME_HEADER **NewFv, + OUT EFI_FFS_FILE_HEADER **Nfv) +{ + UINTN i; + EFI_STATUS Status = EFI_NOT_FOUND; + + for(i = 0; ProcessNestedFvBeforePublishingList[i] && EFI_ERROR(Status); i++) + Status = ProcessNestedFvBeforePublishingList[i](PeiServices, Area, Fv, NewFv, Nfv); + + return Status; +} +// +//---------------------------------------------------------------------------- +// Procedure: ProcessFvBeforePublishingHook +// +// Description: Porting hook to support OEM-specific FV validation control flow +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN OUT ROM_AREA *Area - pointer to ROM Area, which contains FV +// to be processed +// IN UINT32 FvType - FV type +// +// Output: TRUE if validation is passed, FALSE otherwise +// +//---------------------------------------------------------------------------- +// +BOOLEAN ProcessFvBeforePublishingHook( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT ROM_AREA *Area, + IN UINT32 FvType) +{ + UINTN i; + BOOLEAN Result = TRUE; + for(i=0; ProcessFvBeforePublishingList[i] && Result; i++) + Result = ProcessFvBeforePublishingList[i](PeiServices, Area, FvType); + return Result; +} + +// +//---------------------------------------------------------------------------- +// Procedure: ProcessDxeFvInDxeIplHook +// +// Description: Porting hook to support OEM-specific FV validation control flow +// before passing control to DXE +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN OUT ROM_AREA *Area - pointer to ROM Area, which contains FV +// to be processed +// +// Output: TRUE if validation is passed, FALSE otherwise +// +//---------------------------------------------------------------------------- +// +BOOLEAN ProcessDxeFvInDxeIplHook( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT ROM_AREA *Area) +{ + UINTN i; + BOOLEAN Result = TRUE; + for(i=0; ProcessDxeFvInDxeIplList[i] && Result; i++) + Result = ProcessDxeFvInDxeIplList[i](PeiServices, Area); + return Result; +} + +// +//---------------------------------------------------------------------------- +// Procedure: EfiReadSection +// +// Description: Function to read section of specific type from given FFS file +// +// Input: IN EFI_PEI_SERVICES **ppPS - pointer to PEI services +// IN EFI_SECTION_TYPE SectionType - type of section to read +// IN EFI_FFS_FILE_HEADER *pFile - pointer to FFS file to read from +// OUT VOID **ppData - pointer for output buffer +// +// Output: EFI_SUCCESS if reading completed successfully +// +//---------------------------------------------------------------------------- +// +EFI_STATUS EfiReadSection( + IN EFI_PEI_SERVICES **ppPS, + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *pFile, + OUT VOID **ppData) +{ + EFI_STATUS Status; + UINT32 SrcSize, DstSize, TmpSize; + VOID *pSrc; + EFI_PHYSICAL_ADDRESS DstAddress; + EFI_HOB_HANDOFF_INFO_TABLE *pHob; + EFI_COMPRESSION_SECTION_HEADER *pCs; + + if (!ppData) + return EFI_INVALID_PARAMETER; + + //TODO: Support for GUIDed sections + Status = (*ppPS)->FfsFindSectionData(ppPS, SectionType, pFile, &pSrc); + if (!EFI_ERROR(Status)) { + *ppData = pSrc; + return Status; + } + + Status = (*ppPS)->FfsFindSectionData(ppPS, EFI_SECTION_COMPRESSION, pFile, &pCs); + if (EFI_ERROR(Status)) + return Status; + + SrcSize = FVSECTION_SIZE(pCs) - sizeof(EFI_COMPRESSION_SECTION_HEADER); + pSrc = pCs + 1; + if (pCs->CompressionType != EFI_NOT_COMPRESSED) { + GET_INFO GetInfoPtr; + DECOMPRESS DecompressPtr; + BOOLEAN KnownCompressionType; + + KnownCompressionType = GetDecompressInterface(pCs->CompressionType, &GetInfoPtr, &DecompressPtr); + if (!KnownCompressionType) + return EFI_UNSUPPORTED; + + Status = GetInfoPtr(pSrc, SrcSize, &DstSize, &TmpSize); + if (EFI_ERROR(Status)) + return Status; + + //No FreePool, so the memory is never freed + Status = (*ppPS)->AllocatePages(ppPS, EfiBootServicesCode,( DstSize >> 12) + 1, &DstAddress); + if (EFI_ERROR(Status)) + return Status; + + (*ppPS)->GetHobList(ppPS,&pHob); + if (pHob->EfiFreeMemoryTop - pHob->EfiFreeMemoryBottom < TmpSize) + return EFI_OUT_OF_RESOURCES; + + Status = DecompressPtr(pSrc, SrcSize, (VOID*)DstAddress, DstSize, (VOID*)pHob->EfiFreeMemoryBottom, TmpSize); + if (EFI_ERROR(Status)) + return Status; + + pSrc = (VOID*)(UINTN)DstAddress; + } + + do { + if (((EFI_COMMON_SECTION_HEADER*)pSrc)->Type == SectionType) { + *ppData = (EFI_COMMON_SECTION_HEADER*)pSrc+1; + return EFI_SUCCESS; + } + + TmpSize = FVSECTION_SIZE(pSrc); + TmpSize += (4 - (TmpSize & 3)) & 3; + if (TmpSize>=DstSize) + return EFI_NOT_FOUND; + + DstSize -= TmpSize; + pSrc = (UINT8*)pSrc + TmpSize; + }while(TRUE); +} + +// +//---------------------------------------------------------------------------- +// Procedure: GetRomLayout +// +// Description: Function to read ROM_LAYOUT data from FFS file +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// OUT ROM_AREA **Layout - pointer to output buffer +// +// Output: EFI_SUCCESS if ROM layout is retrieved +// +//---------------------------------------------------------------------------- +// +EFI_STATUS GetRomLayout( + IN EFI_PEI_SERVICES **PeiServices, + OUT ROM_AREA **Layout +) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *BootFv; + EFI_FFS_FILE_HEADER *File = NULL; + ROM_LAYOUT_SECTION *Section; + + Status = (*PeiServices)->FfsFindNextVolume(PeiServices, 0, &BootFv); + if (EFI_ERROR(Status)) + return Status; + + do { + Status = (*PeiServices)->FfsFindNextFile(PeiServices, EFI_FV_FILETYPE_FREEFORM, BootFv, &File); + if (!EFI_ERROR(Status) && !guidcmp(&(File->Name), &RomLayoutFfsGuid)) { + break; + } + } while(Status == EFI_SUCCESS); + + if (EFI_ERROR(Status)) + return Status; + + Section = (ROM_LAYOUT_SECTION *)File; + + *Layout = Section->Layout; + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: GetRomLayout +// +// Description: Function to read ROM_LAYOUT data from given data buffer +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// OUT ROM_AREA **Layout - pointer to output buffer +// IN VOID *RecoveryCapsule - pointer to data buffer to read from +// +// Output: EFI_SUCCESS if ROM layout is retrieved +// +//---------------------------------------------------------------------------- +// +EFI_STATUS GetRecoveryRomLayout( + IN EFI_PEI_SERVICES **PeiServices, + OUT ROM_AREA **Layout, + IN VOID *RecoveryCapsule +) +{ + UINT32 Signature; + UINT32 *SearchPointer; + ROM_LAYOUT_SECTION *Section; + + SearchPointer = (UINT32 *)((UINT8 *)RecoveryCapsule - sizeof(EFI_GUID) + FLASH_SIZE); + Signature = RomLayoutFfsGuid.Data1; + + do { + if(*SearchPointer == Signature) { + Section = (ROM_LAYOUT_SECTION *)SearchPointer; + if(!guidcmp(&RomLayoutFfsGuid, &(Section->FfsGuid)) && + !guidcmp(&RomLayoutSectionGuid, &(Section->SectionGuid))) { + *Layout = Section->Layout; + return EFI_SUCCESS; + } + } + } while(SearchPointer-- != RecoveryCapsule); + + return EFI_NOT_FOUND; +} + +// +//---------------------------------------------------------------------------- +// Procedure: VerifyFwVolume +// +// Description: Function to verify that FV is not corrupted +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN EFI_FIRMWARE_VOLUME_HEADER *Fv - pointer to FV to verify +// +// Output: EFI_SUCCESS if verification passed +// +//---------------------------------------------------------------------------- +// +EFI_STATUS VerifyFwVolume( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FIRMWARE_VOLUME_HEADER *Fv +) +{ + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: CreateFvHob +// +// Description: Function to create FV hob for given ROM layout unit +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN ROM_AREA *Area - pointer to ROM layout unit to process +// +// Output: EFI_SUCCESS if Hob created successfully +// +//---------------------------------------------------------------------------- +// +EFI_STATUS CreateFvHob( + IN EFI_PEI_SERVICES **PeiServices, + IN ROM_AREA *Area +) +{ + EFI_STATUS Status; + EFI_HOB_FIRMWARE_VOLUME *FVHob; + + Status = (*PeiServices)->CreateHob( + PeiServices, + EFI_HOB_TYPE_FV, + sizeof(EFI_HOB_FIRMWARE_VOLUME), + &FVHob); + if (EFI_ERROR(Status)) + return Status; + + FVHob->BaseAddress = Area->Address; + FVHob->Length = (UINT64)Area->Size; + + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: CreateFvHob2 +// +// Description: Function to create FV hob type 2 for given ROM layout unit +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN ROM_AREA *Area - pointer to ROM layout unit to process +// IN EFI_GUID *FvName - pointer to FV name +// IN EFI_GUID *FfsName - pointer to parent FFS file +// +// Output: EFI_SUCCESS if Hob created successfully +// +//---------------------------------------------------------------------------- +// +EFI_STATUS CreateFvHob2( + IN EFI_PEI_SERVICES **PeiServices, + IN ROM_AREA *Area, + IN EFI_GUID *FvName, + IN EFI_GUID *FfsName +) +{ + EFI_STATUS Status; + EFI_HOB_FIRMWARE_VOLUME2 *FVHob; + + Status = (*PeiServices)->CreateHob( + PeiServices, + EFI_HOB_TYPE_FV2, + sizeof(EFI_HOB_FIRMWARE_VOLUME2), + &FVHob); + if (EFI_ERROR(Status)) + return Status; + + FVHob->BaseAddress = Area->Address; + FVHob->Length = (UINT64)Area->Size; + FVHob->FvName = *FvName; + FVHob->FileName = *FfsName; + + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: CheckBeforePublishing +// +// Description: Function to verify if FvPPI should be installed. +// On recovery only PPI for FV with DXE_CORE FFS should be installed +// from recovery capsule +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN EFI_FIRMWARE_VOLUME_HEADER *Fv - pointer to FV to check +// +// Output: EFI_SUCCESS if FV should be published, EFI_ERROR otherwise +// +//---------------------------------------------------------------------------- +// +EFI_STATUS CheckBeforePublishing( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FIRMWARE_VOLUME_HEADER *Fv +) +{ + EFI_STATUS Status; + RECOVERY_IMAGE_HOB *RecoveryHob; + EFI_FFS_FILE_HEADER *File = NULL; + static EFI_GUID RecoveryHobGuid = AMI_RECOVERY_IMAGE_HOB_GUID; + +//check if we are on recovery boot path, with recovery capsule already loaded + + Status = (*PeiServices)->GetHobList(PeiServices, &RecoveryHob); + if(EFI_ERROR(Status)) + return EFI_SUCCESS; //we are not on recovery boot path + + Status = FindNextHobByGuid(&RecoveryHobGuid, &RecoveryHob); + if(EFI_ERROR(Status)) + return EFI_SUCCESS; //we are not on recovery boot path + + if(RecoveryHob->Status == EFI_SUCCESS && RecoveryHob->Address != NULL) { //we're on recovery boot path + Status = (*PeiServices)->FfsFindNextFile(PeiServices, EFI_FV_FILETYPE_DXE_CORE, Fv, &File); + return Status; + } + + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: CreateFvInfoPpi +// +// Description: Function to install FwVolume info PPI for given ROM layout unit +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN ROM_AREA *Area - pointer to ROM layout unit to process +// IN EFI_GUID *FvName - pointer to parent FV name +// IN EFI_GUID *FfsName - pointer to parent FFS file +// +// Output: EFI_SUCCESS if PPI installed +// +//---------------------------------------------------------------------------- +// +EFI_STATUS CreateFvInfoPpi( + IN EFI_PEI_SERVICES **PeiServices, + IN ROM_AREA *Area, + IN EFI_GUID *FvName OPTIONAL, + IN EFI_GUID *FfsName OPTIONAL +) +{ + EFI_STATUS Status; + + EFI_PEI_PPI_DESCRIPTOR *FirmwareVolume; + EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FirmwareVolumeInfo; + + Status = CheckBeforePublishing(PeiServices, (EFI_FIRMWARE_VOLUME_HEADER*)Area->Address); + if(EFI_ERROR(Status)) + return EFI_VOLUME_FULL; + + Status = (*PeiServices)->AllocatePool( + PeiServices, + sizeof(EFI_PEI_PPI_DESCRIPTOR) + sizeof(EFI_PEI_FIRMWARE_VOLUME_INFO_PPI), + &FirmwareVolume); + if(EFI_ERROR(Status)) + return EFI_VOLUME_FULL; + + FirmwareVolumeInfo = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI*)(FirmwareVolume + 1); + + FirmwareVolumeInfo->FvFormat = ((EFI_FIRMWARE_VOLUME_HEADER*)Area->Address)->FileSystemGuid; + FirmwareVolumeInfo->FvInfo = (VOID *)(UINTN)Area->Address; + FirmwareVolumeInfo->FvInfoSize = Area->Size; + FirmwareVolumeInfo->ParentFvName = FvName; + FirmwareVolumeInfo->ParentFileName = FfsName; + + + FirmwareVolume->Ppi = FirmwareVolumeInfo; + FirmwareVolume->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + FirmwareVolume->Guid = &gEfiFirmwareVolumeInfoPpiGuid; + + return (*PeiServices)->InstallPpi(PeiServices, FirmwareVolume); +} + +// +//---------------------------------------------------------------------------- +// Procedure: FindFvHob +// +// Description: Function to find FV Hob for corresponding ROM layout unit +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN ROM_AREA *Area - pointer to ROM layout unit to find matching Hob +// OUT EFI_HOB_FIRMWARE_VOLUME **FvHob - pointer to output buffer +// +// Output: EFI_SUCCESS if corresponding Hob found +// +//---------------------------------------------------------------------------- +// +EFI_STATUS FindFvHob( + IN EFI_PEI_SERVICES **PeiServices, + IN ROM_AREA *Area, + OUT EFI_HOB_FIRMWARE_VOLUME **FvHob +) +{ + EFI_HOB_FIRMWARE_VOLUME *FvHob2; + + (*PeiServices)->GetHobList(PeiServices, FvHob); + + FvHob2 = *FvHob; + while(!EFI_ERROR(FindNextHobByType(EFI_HOB_TYPE_FV, FvHob))){ + if ((*FvHob)->BaseAddress == Area->Address) + return EFI_SUCCESS; + } + + while(!EFI_ERROR(FindNextHobByType(EFI_HOB_TYPE_FV2, &FvHob2))){ + if (FvHob2->BaseAddress == Area->Address) { + *FvHob = FvHob2; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + +// +//---------------------------------------------------------------------------- +// Procedure: RemoveFvHob +// +// Description: Function to remove FV Hob for corresponding ROM layout unit +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN ROM_AREA *Area - pointer to ROM layout unit to remove matching Hob +// or NULL to remove all FV Hobs +// +// Output: None +// +//---------------------------------------------------------------------------- +// +VOID RemoveFvHob( + IN EFI_PEI_SERVICES **PeiServices, + IN ROM_AREA *Area OPTIONAL +) +{ + EFI_STATUS Status; + EFI_HOB_FIRMWARE_VOLUME *FvHob; + EFI_HOB_FIRMWARE_VOLUME2 *FvHob2; + + if(Area == NULL) { //delete all Fv hobs + (*PeiServices)->GetHobList(PeiServices, &FvHob); + FvHob2 = (EFI_HOB_FIRMWARE_VOLUME2 *)FvHob; + while(!EFI_ERROR(FindNextHobByType(EFI_HOB_TYPE_FV, &FvHob))) { + FvHob->Header.HobType = EFI_HOB_TYPE_UNUSED; + } + + while(!EFI_ERROR(FindNextHobByType(EFI_HOB_TYPE_FV2, &FvHob2))) { + FvHob2->Header.HobType = EFI_HOB_TYPE_UNUSED; + } + } else { + Status = FindFvHob(PeiServices, Area, &FvHob); + if(!EFI_ERROR(Status)) + FvHob->Header.HobType = EFI_HOB_TYPE_UNUSED; + } + return; +} + +// +//---------------------------------------------------------------------------- +// Procedure: PublishFv +// +// Description: Function to publish Firmware Volume for corresponding ROM layout unit +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN ROM_AREA *Area - pointer to ROM layout unit describing FV +// IN BOOLEAN Nested - TRUE if published FV is nested, FALSE otherwise +// +// Output: EFI_SUCCESS if FV published successfully +// +//---------------------------------------------------------------------------- +// +EFI_STATUS PublishFv( + IN EFI_PEI_SERVICES **PeiServices, + IN ROM_AREA *Area, + IN BOOLEAN Nested +) +{ + EFI_FIRMWARE_VOLUME_HEADER *Fv; + EFI_STATUS Status = EFI_SUCCESS; + + if(!ProcessFvBeforePublishingHook(PeiServices, Area, Area->Attributes)) + return EFI_VOLUME_CORRUPTED; + + Fv = (EFI_FIRMWARE_VOLUME_HEADER*)Area->Address; + if(Fv->Signature != FV_SIGNATURE) + return EFI_VOLUME_CORRUPTED; + + if(Area->Attributes & ROM_AREA_FV_VERIFY) + Status = VerifyFwVolume(PeiServices, Fv); + + if(EFI_ERROR(Status) || Nested) //for nested FV PublishNestedFv will call CreateFvInfoPpi and CreateHob + return Status; + + Status = CreateFvHob(PeiServices, Area); + if(EFI_ERROR(Status)) + return Status; + +#if PI_SPECIFICATION_VERSION >= 0x00010000 + Status = CreateFvInfoPpi(PeiServices, Area, NULL, NULL); +#endif + + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: InitRecovery +// +// Description: Function to initialize recovery process +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// +// Output: None +// +//---------------------------------------------------------------------------- +// +VOID InitRecovery( + IN EFI_PEI_SERVICES **PeiServices +) +{ + static EFI_GUID RecoveryBootModeGuid = EFI_PEI_BOOT_IN_RECOVERY_MODE_PEIM_PPI; + static EFI_PEI_PPI_DESCRIPTOR RecoveryModePpi = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &RecoveryBootModeGuid, NULL + }; + + EFI_BOOT_MODE BootMode; + EFI_STATUS Status; + + Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode); + + if(EFI_ERROR(Status) || (BootMode != BOOT_IN_RECOVERY_MODE)) { + (*PeiServices)->SetBootMode(PeiServices, BOOT_IN_RECOVERY_MODE); + (*PeiServices)->InstallPpi(PeiServices, &RecoveryModePpi); + PEI_PROGRESS_CODE(PeiServices, PEI_RECOVERY_AUTO); + } +} + +// +//---------------------------------------------------------------------------- +// Procedure: ReportFV2Pei +// +// Description: Function to publish PEI Firmware Volumes early in PEI phase +// +// Input: IN EFI_FFS_FILE_HEADER *FfsHeader - pointer to image FFS file +// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// +// Output: EFI_SUCCESS if all FVs published successfully +// +//---------------------------------------------------------------------------- +// +EFI_STATUS ReportFV2Pei( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + ROM_AREA *Area; + EFI_STATUS Status; + ROM_AREA Current; + + Status = GetRomLayout(PeiServices, &Area); + + while(Area->Size != 0) { + Current = *Area; + if(Area->Attributes & ROM_AREA_FV_PEI) { + Status = PublishFv(PeiServices, &Current, FALSE); + if(EFI_ERROR(Status) && !(Area->Attributes & ROM_AREA_FV_NON_CRITICAL)) { + InitRecovery(PeiServices); + } + } + Area++; + } + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: RelocateFv +// +// Description: Function to relocate Firmware Volume into memory for corresponding +// ROM layout unit +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN ROM_AREA *Area - pointer to ROM layout unit describing FV +// +// Output: EFI_SUCCESS if FV relocated successfully +// +//---------------------------------------------------------------------------- +// +EFI_STATUS RelocateFv( + IN EFI_PEI_SERVICES **PeiServices, + IN ROM_AREA *Area +) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Dest; + UINTN Pages; + + Pages = EFI_SIZE_TO_PAGES(Area->Size); + Status = (*PeiServices)->AllocatePages(PeiServices, EfiBootServicesData, Pages, &Dest); + if(EFI_ERROR(Status)) + return Status; + + MemCpy((VOID *)(UINTN)Dest, (VOID *)(UINTN)Area->Address, Area->Size); + Area->Address = Dest; + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: PublishNestedFv +// +// Description: Function to publish Nested Firmware Volume for corresponding ROM layout unit +// +// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// IN ROM_AREA *Area - pointer to ROM layout unit describing FV +// +// Output: EFI_SUCCESS if FV published successfully +// +//---------------------------------------------------------------------------- +// +EFI_STATUS PublishNestedFv( + IN EFI_PEI_SERVICES **PeiServices, + IN ROM_AREA *Area +) +{ + EFI_FIRMWARE_VOLUME_HEADER *Fv; + EFI_FIRMWARE_VOLUME_HEADER *NewFv; + EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtFv; + EFI_FFS_FILE_HEADER *Nfv = NULL; + ROM_AREA NewArea; + EFI_STATUS Status; + + Fv = (EFI_FIRMWARE_VOLUME_HEADER*)Area->Address; + if(Fv->Signature != FV_SIGNATURE) + return EFI_VOLUME_CORRUPTED; + + Status = ProcessNestedFvBeforePublishingHook(PeiServices, Area, &Fv, &NewFv, &Nfv); + if(EFI_ERROR(Status)) { + Status = (*PeiServices)->FfsFindNextFile (PeiServices, EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, Fv, &Nfv); + if(EFI_ERROR(Status)) + return Status; + + Status = EfiReadSection(PeiServices, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, Nfv, &NewFv); + if(EFI_ERROR(Status)) + return Status; + } + + NewArea.Address = (EFI_PHYSICAL_ADDRESS)(UINTN)NewFv; + NewArea.Size = (UINT32)NewFv->FvLength; + NewArea.Type = RomAreaTypeFv; + NewArea.Attributes = Area->Attributes; + + Status = PublishFv(PeiServices, &NewArea, TRUE); + if(EFI_ERROR(Status)) + return Status; + + if(NewFv->ExtHeaderOffset == 0) { //no FvName Guid + Status = CreateFvHob2(PeiServices, &NewArea, &NullGuid, &(Nfv->Name)); + } else { + ExtFv = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)NewFv + NewFv->ExtHeaderOffset); + Status = CreateFvHob2(PeiServices, &NewArea, &(ExtFv->FvName), &(Nfv->Name)); + } + if(EFI_ERROR(Status)) + return Status; + +#if PI_SPECIFICATION_VERSION >= 0x00010000 + if(Fv->ExtHeaderOffset == 0) { //no FvName Guid + Status = CreateFvInfoPpi(PeiServices, &NewArea, NULL, &(Nfv->Name)); + } else { + ExtFv = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)Fv + Fv->ExtHeaderOffset); + Status = CreateFvInfoPpi(PeiServices, &NewArea, &(ExtFv->FvName), &(Nfv->Name)); + } +#endif + + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: ReportFV2PeiAfterMem +// +// Description: Function to publish PEI Firmware Volumes in PEI phase after +// memory is available +// +// Input: IN EFI_FFS_FILE_HEADER *FfsHeader - pointer to image FFS file +// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// +// Output: EFI_SUCCESS if all FVs published successfully +// +//---------------------------------------------------------------------------- +// +EFI_STATUS ReportFV2PeiAfterMem( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + ROM_AREA *Area; + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + BOOLEAN CorruptedVolume; + ROM_AREA Current; + + Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode); + Status = GetRomLayout(PeiServices, &Area); + + while(Area->Size != 0) { + Current = *Area; + CorruptedVolume = FALSE; + if(Area->Attributes & ROM_AREA_FV_PEI_MEM) { + Status = PublishFv(PeiServices, &Current, FALSE); + if(EFI_ERROR(Status) && !(Area->Attributes & ROM_AREA_FV_NON_CRITICAL)) { + InitRecovery(PeiServices); + CorruptedVolume = TRUE; + } + } else if(Area->Attributes & ROM_AREA_FV_PEI_SHADOW && BootMode != BOOT_ON_S3_RESUME) { + Status = RelocateFv(PeiServices, &Current); + if(!EFI_ERROR(Status)) + Status = PublishFv(PeiServices, &Current, FALSE); + + if(EFI_ERROR(Status) && !(Area->Attributes & ROM_AREA_FV_NON_CRITICAL)) { + InitRecovery(PeiServices); + CorruptedVolume = TRUE; + } + } +/* (EIP71398)> + if(!CorruptedVolume && + Area->Attributes & ROM_AREA_FV_NFV_PRESENT && + Area->Attributes & ROM_AREA_FV_PEI_ACCESS && + BootMode == BOOT_IN_RECOVERY_MODE) { + Status = PublishNestedFv(PeiServices, &Current); + if(EFI_ERROR(Status) && !(Area->Attributes & ROM_AREA_FV_NON_CRITICAL)) { + InitRecovery(PeiServices); + } + } +<(EIP71398) */ + Area++; + } + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: ReportFV2Dxe +// +// Description: Function to publish PEI Firmware Volumes in PEI phase right before +// passing control to DXE core +// +// Input: IN VOID* RecoveryCapsule - pointer to recovery capsule if in Recovery mode +// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services +// +// Output: EFI_SUCCESS if all FVs published successfully +// +//---------------------------------------------------------------------------- +// +EFI_STATUS ReportFV2Dxe( + IN VOID* RecoveryCapsule OPTIONAL, + IN EFI_PEI_SERVICES **PeiServices +) +{ + ROM_AREA *Area; + EFI_STATUS Status; + ROM_AREA Current; + + static EFI_GUID AmiRomLayoutHobGuid = AMI_ROM_LAYOUT_HOB_GUID; + ROM_LAYOUT_HOB *RomLayoutHob; + UINTN RomLayoutSize; + UINT8 *RomLayoutStart; + + if(RecoveryCapsule == NULL) { + Status = GetRomLayout(PeiServices, &Area); + } else { + Status = GetRecoveryRomLayout(PeiServices, &Area, RecoveryCapsule); + if(EFI_ERROR(Status)) + return Status; //recovery will fail and we will boot from existing ROM + RemoveFvHob(PeiServices, NULL); + } + + RomLayoutStart = (UINT8*)Area; + + while(Area->Size != 0) { + Current = *Area; + if(RecoveryCapsule != NULL) + Current.Address = Area->Offset + (UINTN)RecoveryCapsule; + + if(Area->Attributes & ROM_AREA_FV_DXE) { + if((Area->Attributes & ROM_AREA_FV_PEI_ACCESS) && RecoveryCapsule == NULL) { + if(Area->Attributes & ROM_AREA_FV_NFV_PRESENT) { + Status = PublishNestedFv(PeiServices, &Current); + } + Area++; + continue; //all PEI-related HOBs were processed earlier + } + + Status = PublishFv(PeiServices, &Current, FALSE); + + if(Area->Attributes & ROM_AREA_FV_NFV_PRESENT) { + Status = PublishNestedFv(PeiServices, &Current); + } + + } else { + if((Area->Attributes & ROM_AREA_FV_PEI_ACCESS) && RecoveryCapsule == NULL) { + RemoveFvHob(PeiServices, Area); + } + } + Area++; + } + + // Create a HOB for the entire ROM layout defined in the RomLayout Variable + RomLayoutSize = (UINT8*)(Area + 1) - RomLayoutStart; + Status = (*PeiServices)->CreateHob(PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof(ROM_LAYOUT_HOB) + RomLayoutSize, + &RomLayoutHob); + if (!EFI_ERROR(Status)) { + RomLayoutHob->Header.Name = AmiRomLayoutHobGuid; + MemCpy(RomLayoutHob + 1, RomLayoutStart, RomLayoutSize); + } + + return EFI_SUCCESS; +} + + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** \ No newline at end of file -- cgit v1.2.3