summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Core/Pei/FwVol/FwVol.c235
-rw-r--r--MdeModulePkg/Core/Pei/FwVol/FwVol.h68
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain.h11
3 files changed, 293 insertions, 21 deletions
diff --git a/MdeModulePkg/Core/Pei/FwVol/FwVol.c b/MdeModulePkg/Core/Pei/FwVol/FwVol.c
index 453b72f..140f1b0 100644
--- a/MdeModulePkg/Core/Pei/FwVol/FwVol.c
+++ b/MdeModulePkg/Core/Pei/FwVol/FwVol.c
@@ -455,26 +455,7 @@ FirmwareVolmeInfoPpiNotifyCallback (
} else {
DEBUG ((EFI_D_ERROR, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfoPpi->FvInfo));
- //
- // If can not find EFI_FIRMWARE_VOLUME_PPI to process firmware to get FvHandle,
- // use the address of FV buffer as its handle.
- //
- FvHandle = FvInfoPpi->FvInfo;
-
- //
- // Check whether the FV has already been processed.
- //
- for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {
- if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
- DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvHandle));
- return EFI_SUCCESS;
- }
- }
-
- PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfoPpi->FvInfo;
- PrivateData->Fv[PrivateData->FvCount].FvPpi = NULL;
- PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
- PrivateData->FvCount ++;
+ AddUnknownFormatFvInfo (PrivateData, &FvInfoPpi->FvFormat, FvInfoPpi->FvInfo, FvInfoPpi->FvInfoSize);
}
return EFI_SUCCESS;
@@ -1440,3 +1421,217 @@ PeiReinitializeFv (
}
}
+/**
+ Report the information for a new discoveried FV in unknown third-party format.
+
+ If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for third-party FV format, but
+ the FV in this format has been discoveried, then this FV's information will be cached into
+ PEI_CORE_INSTANCE's UnknownFvInfo array.
+ Also a notification would be installed for unknown third-party FV format guid, if EFI_PEI_FIRMWARE_VOLUME_PPI
+ is installed later by platform's PEIM, the original unknown third-party FV will be processed by
+ using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
+
+ @param PrivateData Point to instance of PEI_CORE_INSTANCE
+ @param Format Point to the unknown third-party format guid.
+ @param FvInfo Point to FvInfo buffer.
+ @param FvInfoSize The size of FvInfo buffer.
+
+ @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces.
+ @retval EFI_SUCCESS Success to add the information for unknown FV.
+**/
+EFI_STATUS
+AddUnknownFormatFvInfo (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN EFI_GUID *Format,
+ IN VOID *FvInfo,
+ IN UINT32 FvInfoSize
+ )
+{
+ PEI_CORE_UNKNOW_FORMAT_FV_INFO *NewUnknownFv;
+
+ if (PrivateData->UnknownFvInfoCount + 1 >= FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewUnknownFv = &PrivateData->UnknownFvInfo[PrivateData->UnknownFvInfoCount];
+ PrivateData->UnknownFvInfoCount ++;
+
+ CopyGuid (&NewUnknownFv->FvFormat, Format);
+ NewUnknownFv->FvInfo = FvInfo;
+ NewUnknownFv->FvInfoSize = FvInfoSize;
+ NewUnknownFv->NotifyDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ NewUnknownFv->NotifyDescriptor.Guid = &NewUnknownFv->FvFormat;
+ NewUnknownFv->NotifyDescriptor.Notify = ThirdPartyFvPpiNotifyCallback;
+
+ PeiServicesNotifyPpi (&NewUnknownFv->NotifyDescriptor);
+ return EFI_SUCCESS;
+}
+
+/**
+ Find the FV information according to third-party FV format guid.
+
+ This routine also will remove the FV information found by given FV format guid from
+ PrivateData->UnknownFvInfo[].
+
+ @param PrivateData Point to instance of PEI_CORE_INSTANCE
+ @param Format Point to given FV format guid
+ @param FvInfo On return, the pointer of FV information buffer
+ @param FvInfoSize On return, the size of FV information buffer.
+
+ @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI
+ @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
+**/
+EFI_STATUS
+FindUnknownFormatFvInfo (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN EFI_GUID *Format,
+ OUT VOID **FvInfo,
+ OUT UINT32 *FvInfoSize
+ )
+{
+ UINTN Index;
+ UINTN Index2;
+
+ Index = 0;
+ for (; Index < PrivateData->UnknownFvInfoCount; Index ++) {
+ if (CompareGuid (Format, &PrivateData->UnknownFvInfo[Index].FvFormat)) {
+ break;
+ }
+ }
+
+ if (Index == PrivateData->UnknownFvInfoCount) {
+ return EFI_NOT_FOUND;
+ }
+
+ *FvInfo = PrivateData->UnknownFvInfo[Index].FvInfo;
+ *FvInfoSize = PrivateData->UnknownFvInfo[Index].FvInfoSize;
+
+ //
+ // Remove an entry from UnknownFvInfo array.
+ //
+ Index2 = Index + 1;
+ for (;Index2 < PrivateData->UnknownFvInfoCount; Index2 ++, Index ++) {
+ CopyMem (&PrivateData->UnknownFvInfo[Index], &PrivateData->UnknownFvInfo[Index2], sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO));
+ }
+ PrivateData->UnknownFvInfoCount --;
+ return EFI_SUCCESS;
+}
+
+/**
+ Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.
+
+ When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this
+ routine is called to process all discoveried FVs in this format.
+
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param NotifyDescriptor Address of the notification descriptor data structure.
+ @param Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS The notification callback is processed correctly.
+**/
+EFI_STATUS
+EFIAPI
+ThirdPartyFvPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ PEI_CORE_INSTANCE *PrivateData;
+ EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
+ VOID *FvInfo;
+ UINT32 FvInfoSize;
+ EFI_STATUS Status;
+ EFI_PEI_FV_HANDLE FvHandle;
+ BOOLEAN IsProcessed;
+ UINTN FvIndex;
+ EFI_PEI_FILE_HANDLE FileHandle;
+ VOID *DepexData;
+
+ PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
+ FvPpi = (EFI_PEI_FIRMWARE_VOLUME_PPI*) Ppi;
+
+ do {
+ Status = FindUnknownFormatFvInfo (PrivateData, NotifyDescriptor->Guid, &FvInfo, &FvInfoSize);
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Process new found FV and get FV handle.
+ //
+ Status = FvPpi->ProcessVolume (FvPpi, FvInfo, FvInfoSize, &FvHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Fail to process the FV 0x%p, FV may be corrupted!\n", FvInfo));
+ continue;
+ }
+
+ //
+ // Check whether the FV has already been processed.
+ //
+ IsProcessed = FALSE;
+ for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {
+ if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
+ DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfo));
+ IsProcessed = TRUE;
+ break;
+ }
+ }
+
+ if (IsProcessed) {
+ continue;
+ }
+
+ //
+ // Update internal PEI_CORE_FV array.
+ //
+ PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfo;
+ PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;
+ PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
+ DEBUG ((
+ EFI_D_INFO,
+ "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
+ (UINT32) PrivateData->FvCount,
+ (VOID *) FvInfo,
+ FvInfoSize,
+ FvHandle
+ ));
+ PrivateData->FvCount ++;
+
+ //
+ // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
+ //
+ FileHandle = NULL;
+ do {
+ Status = FvPpi->FindFileByType (
+ FvPpi,
+ EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
+ FvHandle,
+ &FileHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = FvPpi->FindSectionByType (
+ FvPpi,
+ EFI_SECTION_PEI_DEPEX,
+ FileHandle,
+ (VOID**)&DepexData
+ );
+ if (!EFI_ERROR (Status)) {
+ if (!PeimDispatchReadiness (PeiServices, DepexData)) {
+ //
+ // Dependency is not satisfied.
+ //
+ continue;
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, PrivateData->FvCount - 1, FvHandle));
+ ProcessFvFile (&PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);
+ }
+ } while (FileHandle != NULL);
+ } while (TRUE);
+
+ return EFI_SUCCESS;
+}
+
+ \ No newline at end of file
diff --git a/MdeModulePkg/Core/Pei/FwVol/FwVol.h b/MdeModulePkg/Core/Pei/FwVol/FwVol.h
index 65c17e3..9409910 100644
--- a/MdeModulePkg/Core/Pei/FwVol/FwVol.h
+++ b/MdeModulePkg/Core/Pei/FwVol/FwVol.h
@@ -235,4 +235,72 @@ FindFileEx (
IN OUT EFI_PEI_FV_HANDLE *AprioriFile OPTIONAL
);
+/**
+ Report the information for a new discoveried FV in unknown format.
+
+ If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been install for specifical FV format, but
+ the FV in this FV format has been discoveried, then the information of this FV
+ will be cached into PEI_CORE_INSTANCE's UnknownFvInfo array.
+ Also a notification would be installed for unknown FV format guid, if EFI_PEI_FIRMWARE_VOLUME_PPI
+ is installed later by platform's PEIM, the original unknown FV will be processed by
+ using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
+
+ @param PrivateData Point to instance of PEI_CORE_INSTANCE
+ @param Format Point to the unknown FV format guid.
+ @param FvInfo Point to FvInfo buffer.
+ @param FvInfoSize The size of FvInfo buffer.
+
+ @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces.
+ @retval EFI_SUCCESS Success to add the information for unknown FV.
+**/
+EFI_STATUS
+AddUnknownFormatFvInfo (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN EFI_GUID *Format,
+ IN VOID *FvInfo,
+ IN UINT32 FvInfoSize
+ );
+
+/**
+ Find the FV information according to FV format guid.
+
+ This routine also will remove the FV information found by given FV format guid from
+ PrivateData->UnknownFvInfo[].
+
+ @param PrivateData Point to instance of PEI_CORE_INSTANCE
+ @param Format Point to given FV format guid
+ @param FvInfo On return, the pointer of FV information buffer in given FV format guid
+ @param FvInfoSize On return, the size of FV information buffer.
+
+ @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI
+ @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
+**/
+EFI_STATUS
+FindUnknownFormatFvInfo (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN EFI_GUID *Format,
+ OUT VOID **FvInfo,
+ OUT UINT32 *FvInfoSize
+ );
+
+/**
+ Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.
+
+ When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this
+ routine is called to process all discoveried FVs in this format.
+
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param NotifyDescriptor Address of the notification descriptor data structure.
+ @param Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS The notification callback is processed correctly.
+**/
+EFI_STATUS
+EFIAPI
+ThirdPartyFvPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
#endif
diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h
index c6b41b6..dc5ea22 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.h
+++ b/MdeModulePkg/Core/Pei/PeiMain.h
@@ -112,6 +112,13 @@ typedef struct {
BOOLEAN ScanFv;
} PEI_CORE_FV_HANDLE;
+typedef struct {
+ EFI_GUID FvFormat;
+ VOID *FvInfo;
+ UINT32 FvInfoSize;
+ EFI_PEI_NOTIFY_DESCRIPTOR NotifyDescriptor;
+} PEI_CORE_UNKNOW_FORMAT_FV_INFO;
+
#define CACHE_SETION_MAX_NUMBER 0x10
typedef struct {
EFI_COMMON_SECTION_HEADER* Section[CACHE_SETION_MAX_NUMBER];
@@ -145,7 +152,9 @@ typedef struct{
/// The instance arrary for FVs which contains FFS and could be dispatched by PeiCore.
///
PEI_CORE_FV_HANDLE Fv[FixedPcdGet32 (PcdPeiCoreMaxFvSupported)];
-
+ PEI_CORE_UNKNOW_FORMAT_FV_INFO UnknownFvInfo[FixedPcdGet32 (PcdPeiCoreMaxFvSupported)];
+ UINTN UnknownFvInfoCount;
+
EFI_PEI_FILE_HANDLE CurrentFvFileHandles[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];
UINTN AprioriCount;
UINTN CurrentPeimFvCount;