+/**\r
+ Process a firmware volume and create a volume handle.\r
+\r
+ Create a volume handle from the information in the buffer. For\r
+ memory-mapped firmware volumes, Buffer and BufferSize refer to\r
+ the start of the firmware volume and the firmware volume size.\r
+ For non memory-mapped firmware volumes, this points to a\r
+ buffer which contains the necessary information for creating\r
+ the firmware volume handle. Normally, these values are derived\r
+ from the EFI_FIRMWARE_VOLUME_INFO_PPI.\r
+ \r
+ \r
+ @param This Points to this instance of the\r
+ EFI_PEI_FIRMWARE_VOLUME_PPI.\r
+ @param Buffer Points to the start of the buffer.\r
+ @param BufferSize Size of the buffer.\r
+ @param FvHandle Points to the returned firmware volume\r
+ handle. The firmware volume handle must\r
+ be unique within the system. \r
+\r
+ @retval EFI_SUCCESS Firmware volume handle created.\r
+ @retval EFI_VOLUME_CORRUPTED Volume was corrupt.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiFfs2FvPpiProcessVolume (\r
+ IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
+ IN VOID *Buffer,\r
+ IN UINTN BufferSize,\r
+ OUT EFI_PEI_FV_HANDLE *FvHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PEI_CORE_INSTANCE *PrivateData;\r
+ EFI_PEI_FILE_HANDLE FileHandle;\r
+ VOID *DepexData;\r
+ EFI_PEI_SERVICES **PeiServices;\r
+ UINTN FvIndex;\r
+ \r
+ PeiServices = (EFI_PEI_SERVICES**) GetPeiServicesTablePointer ();\r
+ PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
+ \r
+ //\r
+ // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2 support memory-mapped\r
+ // FV image and the handle is pointed to Fv image's buffer.\r
+ //\r
+ *FvHandle = (EFI_PEI_FV_HANDLE) Buffer;\r
+ \r
+ //\r
+ // Do verify for given FV buffer.\r
+ //\r
+ Status = VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER*) Buffer);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Fail to verify FV which address is 0x%11p", Buffer));\r
+ return EFI_VOLUME_CORRUPTED;\r
+ }\r
+\r
+ //\r
+ // Check whether the FV has already been processed.\r
+ //\r
+ for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {\r
+ if (PrivateData->Fv[FvIndex].FvHandle == *FvHandle) {\r
+ DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!", Buffer));\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Update internal PEI_CORE_FV array.\r
+ //\r
+ PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) Buffer;\r
+ PrivateData->Fv[PrivateData->FvCount].FvPpi = (EFI_PEI_FIRMWARE_VOLUME_PPI*) This;\r
+ PrivateData->Fv[PrivateData->FvCount].FvHandle = *FvHandle;\r
+ \r
+ DEBUG ((EFI_D_INFO, \r
+ "The %dth FV start address is 0x%11p and size is 0x%08x\n", \r
+ (UINT32) PrivateData->FvCount, \r
+ (VOID *) Buffer, \r
+ BufferSize\r
+ ));\r
+ PrivateData->FvCount ++;\r
+ \r
+ do {\r
+ Status = This->FindFileByType (\r
+ This,\r
+ EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
+ *FvHandle,\r
+ &FileHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = This->FindSectionByType (\r
+ This,\r
+ EFI_SECTION_PEI_DEPEX,\r
+ FileHandle,\r
+ (VOID**)&DepexData\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (!PeimDispatchReadiness (PeiServices, DepexData)) {\r
+ //\r
+ // Dependency is not satisfied.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+ \r
+ DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p", FileHandle, PrivateData->FvCount - 1, *FvHandle));\r
+ ProcessFvFile (&PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);\r
+ }\r
+ } while (FileHandle != NULL);\r
+\r
+ return EFI_SUCCESS;\r
+} \r
+\r
+/**\r
+ Finds the next file of the specified type.\r
+\r
+ This service enables PEI modules to discover additional firmware files. \r
+ The FileHandle must be unique within the system.\r
+\r
+ @param This Points to this instance of the\r
+ EFI_PEI_FIRMWARE_VOLUME_PPI.\r
+ @param SearchType A filter to find only files of this type. Type\r
+ EFI_FV_FILETYPE_ALL causes no filtering to be\r
+ done.\r
+ @param FvHandle Handle of firmware volume in which to\r
+ search.\r
+ @param FileHandle Points to the current handle from which to\r
+ begin searching or NULL to start at the\r
+ beginning of the firmware volume. Updated\r
+ upon return to reflect the file found.\r
+\r
+ @retval EFI_SUCCESS The file was found.\r
+ @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiFfs2FvPpiFindFileByType (\r
+ IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
+ IN EFI_FV_FILETYPE SearchType,\r
+ IN EFI_PEI_FV_HANDLE FvHandle,\r
+ IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
+ )\r
+{ \r
+ return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);\r
+}\r
+\r
+/**\r
+ Find a file within a volume by its name. \r
+ \r
+ This service searches for files with a specific name, within\r
+ either the specified firmware volume or all firmware volumes.\r
+\r
+ @param This Points to this instance of the\r
+ EFI_PEI_FIRMWARE_VOLUME_PPI.\r
+ @param FileName A pointer to the name of the file to find\r
+ within the firmware volume.\r
+ @param FvHandle Upon entry, the pointer to the firmware\r
+ volume to search or NULL if all firmware\r
+ volumes should be searched. Upon exit, the\r
+ actual firmware volume in which the file was\r
+ found.\r
+ @param FileHandle Upon exit, points to the found file's\r
+ handle or NULL if it could not be found.\r
+\r
+ @retval EFI_SUCCESS File was found.\r
+ @retval EFI_NOT_FOUND File was not found.\r
+ @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or\r
+ FileName was NULL.\r
+\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiFfs2FvPpiFindFileByName (\r
+ IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
+ IN CONST EFI_GUID *FileName,\r
+ IN EFI_PEI_FV_HANDLE *FvHandle,\r
+ OUT EFI_PEI_FILE_HANDLE *FileHandle \r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PEI_CORE_INSTANCE *PrivateData;\r
+ UINTN Index;\r
+ \r
+ if ((FvHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if (*FvHandle != NULL) {\r
+ Status = FindFileEx (*FvHandle, FileName, 0, FileHandle, NULL);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ *FileHandle = NULL;\r
+ }\r
+ } else { \r
+ //\r
+ // If *FvHandle = NULL, so search all FV for given filename\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+ \r
+ PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());\r
+ for (Index = 0; Index < PrivateData->FvCount; Index ++) {\r
+ //\r
+ // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance.\r
+ //\r
+ if (PrivateData->Fv[Index].FvPpi != NULL) {\r
+ Status = FindFileEx (PrivateData->Fv[Index].FvHandle, FileName, 0, FileHandle, NULL);\r
+ if (!EFI_ERROR (Status)) {\r
+ *FvHandle = PrivateData->Fv[Index].FvHandle;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ return Status; \r
+} \r
+\r
+/**\r
+ Returns information about a specific file.\r
+\r
+ This function returns information about a specific\r
+ file, including its file name, type, attributes, starting\r
+ address and size. \r
+ \r
+ @param This Points to this instance of the\r
+ EFI_PEI_FIRMWARE_VOLUME_PPI.\r
+ @param FileHandle Handle of the file.\r
+ @param FileInfo Upon exit, points to the file's\r
+ information.\r
+\r
+ @retval EFI_SUCCESS File information returned.\r
+ @retval EFI_INVALID_PARAMETER If FileHandle does not\r
+ represent a valid file.\r
+ @retval EFI_INVALID_PARAMETER If FileInfo is NULL.\r
+ \r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+PeiFfs2FvPpiGetFileInfo (\r
+ IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, \r
+ IN EFI_PEI_FILE_HANDLE FileHandle, \r
+ OUT EFI_FV_FILE_INFO *FileInfo\r
+ )\r
+{\r
+ UINT8 FileState;\r
+ UINT8 ErasePolarity;\r
+ EFI_FFS_FILE_HEADER *FileHeader;\r
+ PEI_CORE_FV_HANDLE *CoreFvHandle;\r
+ \r
+ if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Retrieve the FirmwareVolume which the file resides in.\r
+ //\r
+ CoreFvHandle = FileHandleToVolume (FileHandle);\r
+ if (CoreFvHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (CoreFvHandle->FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+ ErasePolarity = 1;\r
+ } else {\r
+ ErasePolarity = 0;\r
+ }\r
+\r
+ //\r
+ // Get FileState which is the highest bit of the State \r
+ //\r
+ FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);\r
+\r
+ switch (FileState) {\r
+ case EFI_FILE_DATA_VALID:\r
+ case EFI_FILE_MARKED_FOR_UPDATE:\r
+ break; \r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;\r
+ CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));\r
+ FileInfo->FileType = FileHeader->Type;\r
+ FileInfo->FileAttributes = FileHeader->Attributes;\r
+ FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER);\r
+ FileInfo->Buffer = (FileHeader + 1);\r
+ return EFI_SUCCESS; \r
+} \r
+ \r
+/**\r
+ This function returns information about the firmware volume.\r
+ \r
+ @param This Points to this instance of the\r
+ EFI_PEI_FIRMWARE_VOLUME_PPI.\r
+ @param FvHandle Handle to the firmware handle.\r
+ @param VolumeInfo Points to the returned firmware volume\r
+ information.\r
+\r
+ @retval EFI_SUCCESS Information returned successfully.\r
+ @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid\r
+ firmware volume or VolumeInfo is NULL.\r
+\r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+PeiFfs2FvPpiGetVolumeInfo (\r
+ IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, \r
+ IN EFI_PEI_FV_HANDLE FvHandle, \r
+ OUT EFI_FV_INFO *VolumeInfo\r
+ )\r
+{\r
+ EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;\r
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;\r
+\r
+ if (VolumeInfo == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ //\r
+ // VolumeHandle may not align at 8 byte, \r
+ // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. \r
+ // So, Copy FvHeader into the local FvHeader structure.\r
+ //\r
+ CopyMem (&FwVolHeader, FvHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+\r
+ //\r
+ // Check Fv Image Signature\r
+ //\r
+ if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (VolumeInfo, sizeof (EFI_FV_INFO));\r
+ VolumeInfo->FvAttributes = FwVolHeader.Attributes;\r
+ VolumeInfo->FvStart = (VOID *) FvHandle;\r
+ VolumeInfo->FvSize = FwVolHeader.FvLength;\r
+ CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));\r
+\r
+ if (FwVolHeader.ExtHeaderOffset != 0) {\r
+ FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FvHandle) + FwVolHeader.ExtHeaderOffset);\r
+ CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));\r
+ }\r
+ \r
+ return EFI_SUCCESS; \r
+} \r
+\r
+/**\r
+ Find the next matching section in the firmware file.\r
+ \r
+ This service enables PEI modules to discover sections\r
+ of a given type within a valid file.\r
+ \r
+ @param This Points to this instance of the\r
+ EFI_PEI_FIRMWARE_VOLUME_PPI.\r
+ @param SearchType A filter to find only sections of this\r
+ type.\r
+ @param FileHandle Handle of firmware file in which to\r
+ search.\r
+ @param SectionData Updated upon return to point to the\r
+ section found.\r
+ \r
+ @retval EFI_SUCCESS Section was found.\r
+ @retval EFI_NOT_FOUND Section of the specified type was not\r
+ found. SectionData contains NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiFfs2FvPpiFindSectionByType (\r
+ IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
+ IN EFI_SECTION_TYPE SearchType,\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ OUT VOID **SectionData\r
+ )\r
+{\r
+ EFI_FFS_FILE_HEADER *FfsFileHeader;\r
+ UINT32 FileSize;\r
+ EFI_COMMON_SECTION_HEADER *Section;\r
+ \r
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);\r
+\r
+ //\r
+ // Size is 24 bits wide so mask upper 8 bits. \r
+ // Does not include FfsFileHeader header size\r
+ // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
+ //\r
+ Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);\r
+ FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
+ FileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
+\r
+ return ProcessSection (\r
+ GetPeiServicesTablePointer (),\r
+ SearchType, \r
+ Section, \r
+ FileSize, \r
+ SectionData\r
+ ); \r
+} \r
+\r
+/**\r
+ Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.\r
+ \r
+ @param FvHandle The handle of a FV.\r
+ \r
+ @retval NULL if can not find.\r
+ @return Pointer of corresponding PEI_CORE_FV_HANDLE. \r
+**/\r
+PEI_CORE_FV_HANDLE *\r
+FvHandleToCoreHandle (\r
+ IN EFI_PEI_FV_HANDLE FvHandle\r
+ )\r
+{\r
+ UINTN Index;\r
+ PEI_CORE_INSTANCE *PrivateData;\r
+ \r
+ PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer()); \r
+ for (Index = 0; Index < PrivateData->FvCount; Index ++) {\r
+ if (FvHandle == PrivateData->Fv[Index].FvHandle) {\r
+ return &PrivateData->Fv[Index];\r
+ }\r
+ }\r
+ \r
+ return NULL;\r
+} \r
+\r
+/**\r
+ Get instance of PEI_CORE_FV_HANDLE for next volume according to given index.\r
+ \r
+ This routine also will install FvInfo ppi for FV hob in PI ways.\r
+ \r
+ @param Private Pointer of PEI_CORE_INSTANCE\r
+ @param Instance The index of FV want to be searched.\r
+ \r
+ @return Instance of PEI_CORE_FV_HANDLE.\r
+**/\r
+PEI_CORE_FV_HANDLE *\r
+FindNextCoreFvHandle (\r
+ IN PEI_CORE_INSTANCE *Private,\r
+ IN UINTN Instance\r
+ )\r
+{\r
+ UINTN Index;\r
+ BOOLEAN Match;\r
+ EFI_HOB_FIRMWARE_VOLUME *FvHob;\r
+ \r
+ //\r
+ // Handle Framework FvHob and Install FvInfo Ppi for it.\r
+ //\r
+ if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
+ //\r
+ // Loop to search the wanted FirmwareVolume which supports FFS\r
+ //\r
+ FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetFirstHob (EFI_HOB_TYPE_FV);\r
+ while (FvHob != NULL) {\r
+ for (Index = 0, Match = FALSE; Index < Private->FvCount; Index++) {\r
+ if ((EFI_PEI_FV_HANDLE)(UINTN)FvHob->BaseAddress == Private->Fv[Index].FvHeader) {\r
+ Match = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // If Not Found, Install FvInfo Ppi for it.\r
+ //\r
+ if (!Match) {\r
+ PeiServicesInstallFvInfoPpi (\r
+ &(((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHob->BaseAddress)->FileSystemGuid),\r
+ (VOID *)(UINTN)FvHob->BaseAddress,\r
+ (UINT32)FvHob->Length,\r
+ NULL,\r
+ NULL\r
+ );\r
+ }\r
+ FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetNextHob (EFI_HOB_TYPE_FV, (VOID *)((UINTN)FvHob + FvHob->Header.HobLength)); \r
+ }\r
+ }\r
+\r
+ if (Instance >= Private->FvCount) {\r
+ return NULL;\r
+ }\r