MdeModulePkg DxeCore: Handle multiple FV images in one FV file

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1131

PI spec and BaseTools support to generate multiple FV images
in one FV file.
This patch is to update DxeCore to handle the case.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
Star Zeng 2018-08-29 11:08:25 +08:00
parent 0e042d0ad7
commit e3b9ab433a
1 changed files with 142 additions and 127 deletions

View File

@ -184,14 +184,13 @@ CoreAddToDriverList (
); );
/** /**
Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle. Get Fv image(s) from the FV through file name, and produce FVB protocol for every Fv image(s).
@param Fv The FIRMWARE_VOLUME protocol installed on the FV. @param Fv The FIRMWARE_VOLUME protocol installed on the FV.
@param FvHandle The handle which FVB protocol installed on. @param FvHandle The handle which FVB protocol installed on.
@param DriverName The driver guid specified. @param FileName The file name guid specified.
@retval EFI_OUT_OF_RESOURCES No enough memory or other resource. @retval EFI_OUT_OF_RESOURCES No enough memory or other resource.
@retval EFI_VOLUME_CORRUPTED Corrupted volume.
@retval EFI_SUCCESS Function successfully returned. @retval EFI_SUCCESS Function successfully returned.
**/ **/
@ -199,7 +198,7 @@ EFI_STATUS
CoreProcessFvImageFile ( CoreProcessFvImageFile (
IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv, IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
IN EFI_HANDLE FvHandle, IN EFI_HANDLE FvHandle,
IN EFI_GUID *DriverName IN EFI_GUID *FileName
); );
@ -1004,14 +1003,13 @@ GetFvUsedSize (
} }
/** /**
Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle. Get Fv image(s) from the FV through file name, and produce FVB protocol for every Fv image(s).
@param Fv The FIRMWARE_VOLUME protocol installed on the FV. @param Fv The FIRMWARE_VOLUME protocol installed on the FV.
@param FvHandle The handle which FVB protocol installed on. @param FvHandle The handle which FVB protocol installed on.
@param DriverName The driver guid specified. @param FileName The file name guid specified.
@retval EFI_OUT_OF_RESOURCES No enough memory or other resource. @retval EFI_OUT_OF_RESOURCES No enough memory or other resource.
@retval EFI_VOLUME_CORRUPTED Corrupted volume.
@retval EFI_SUCCESS Function successfully returned. @retval EFI_SUCCESS Function successfully returned.
**/ **/
@ -1019,7 +1017,7 @@ EFI_STATUS
CoreProcessFvImageFile ( CoreProcessFvImageFile (
IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv, IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
IN EFI_HANDLE FvHandle, IN EFI_HANDLE FvHandle,
IN EFI_GUID *DriverName IN EFI_GUID *FileName
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
@ -1033,141 +1031,158 @@ CoreProcessFvImageFile (
EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath; EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath;
UINT32 FvUsedSize; UINT32 FvUsedSize;
UINT8 EraseByte; UINT8 EraseByte;
UINTN Index;
// //
// Read the first (and only the first) firmware volume section // Read firmware volume section(s)
// //
SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
FvHeader = NULL;
FvAlignment = 0;
Buffer = NULL;
BufferSize = 0;
AlignedBuffer = NULL;
Status = Fv->ReadSection (
Fv,
DriverName,
SectionType,
0,
&Buffer,
&BufferSize,
&AuthenticationStatus
);
if (!EFI_ERROR (Status)) {
//
// Evaluate the authentication status of the Firmware Volume through
// Security Architectural Protocol
//
if (gSecurity != NULL) {
FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, DriverName);
Status = gSecurity->FileAuthenticationState (
gSecurity,
AuthenticationStatus,
FvFileDevicePath
);
if (FvFileDevicePath != NULL) {
FreePool (FvFileDevicePath);
}
if (Status != EFI_SUCCESS) { Index = 0;
// do {
// Security check failed. The firmware volume should not be used for any purpose. FvHeader = NULL;
// FvAlignment = 0;
if (Buffer != NULL) { Buffer = NULL;
FreePool (Buffer); BufferSize = 0;
AlignedBuffer = NULL;
Status = Fv->ReadSection (
Fv,
FileName,
SectionType,
Index,
&Buffer,
&BufferSize,
&AuthenticationStatus
);
if (!EFI_ERROR (Status)) {
//
// Evaluate the authentication status of the Firmware Volume through
// Security Architectural Protocol
//
if (gSecurity != NULL) {
FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, FileName);
Status = gSecurity->FileAuthenticationState (
gSecurity,
AuthenticationStatus,
FvFileDevicePath
);
if (FvFileDevicePath != NULL) {
FreePool (FvFileDevicePath);
} }
return Status;
}
}
// if (Status != EFI_SUCCESS) {
// FvImage should be at its required alignment.
//
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;
//
// If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume
// can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from
// its initial linked location and maintain its alignment.
//
if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {
//
// Get FvHeader alignment
//
FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);
//
// FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
//
if (FvAlignment < 8) {
FvAlignment = 8;
}
DEBUG ((
DEBUG_INFO,
"%a() FV at 0x%x, FvAlignment required is 0x%x\n",
__FUNCTION__,
FvHeader,
FvAlignment
));
//
// Check FvImage alignment.
//
if ((UINTN) FvHeader % FvAlignment != 0) {
//
// Allocate the aligned buffer for the FvImage.
//
AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);
if (AlignedBuffer == NULL) {
FreePool (Buffer);
return EFI_OUT_OF_RESOURCES;
} else {
// //
// Move FvImage into the aligned buffer and release the original buffer. // Security check failed. The firmware volume should not be used for any purpose.
// //
if (GetFvUsedSize (FvHeader, &FvUsedSize, &EraseByte)) { if (Buffer != NULL) {
// FreePool (Buffer);
// Copy the used bytes and fill the rest with the erase value.
//
CopyMem (AlignedBuffer, FvHeader, (UINTN) FvUsedSize);
SetMem (
(UINT8 *) AlignedBuffer + FvUsedSize,
(UINTN) (BufferSize - FvUsedSize),
EraseByte
);
} else {
CopyMem (AlignedBuffer, Buffer, BufferSize);
} }
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) AlignedBuffer; break;
CoreFreePool (Buffer);
Buffer = NULL;
} }
} }
//
// FvImage should be at its required alignment.
//
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;
//
// If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume
// can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from
// its initial linked location and maintain its alignment.
//
if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {
//
// Get FvHeader alignment
//
FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);
//
// FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
//
if (FvAlignment < 8) {
FvAlignment = 8;
}
DEBUG ((
DEBUG_INFO,
"%a() FV at 0x%x, FvAlignment required is 0x%x\n",
__FUNCTION__,
FvHeader,
FvAlignment
));
//
// Check FvImage alignment.
//
if ((UINTN) FvHeader % FvAlignment != 0) {
//
// Allocate the aligned buffer for the FvImage.
//
AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);
if (AlignedBuffer == NULL) {
FreePool (Buffer);
Status = EFI_OUT_OF_RESOURCES;
break;
} else {
//
// Move FvImage into the aligned buffer and release the original buffer.
//
if (GetFvUsedSize (FvHeader, &FvUsedSize, &EraseByte)) {
//
// Copy the used bytes and fill the rest with the erase value.
//
CopyMem (AlignedBuffer, FvHeader, (UINTN) FvUsedSize);
SetMem (
(UINT8 *) AlignedBuffer + FvUsedSize,
(UINTN) (BufferSize - FvUsedSize),
EraseByte
);
} else {
CopyMem (AlignedBuffer, Buffer, BufferSize);
}
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) AlignedBuffer;
FreePool (Buffer);
Buffer = NULL;
}
}
}
//
// Produce a FVB protocol for the file
//
Status = ProduceFVBProtocolOnBuffer (
(EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
(UINT64)BufferSize,
FvHandle,
AuthenticationStatus,
NULL
);
} }
if (EFI_ERROR (Status)) {
//
// ReadSection or Produce FVB failed, Free data buffer
//
if (Buffer != NULL) {
FreePool (Buffer);
}
if (AlignedBuffer != NULL) {
FreeAlignedPages (AlignedBuffer, EFI_SIZE_TO_PAGES (BufferSize));
}
break;
} else {
Index++;
}
} while (TRUE);
if (Index > 0) {
// //
// Produce a FVB protocol for the file // At least one FvImage has been processed successfully.
// //
Status = ProduceFVBProtocolOnBuffer ( return EFI_SUCCESS;
(EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, } else {
(UINT64)BufferSize, return Status;
FvHandle,
AuthenticationStatus,
NULL
);
} }
if (EFI_ERROR (Status)) {
//
// ReadSection or Produce FVB failed, Free data buffer
//
if (Buffer != NULL) {
FreePool (Buffer);
}
if (AlignedBuffer != NULL) {
FreeAlignedPages (AlignedBuffer, EFI_SIZE_TO_PAGES (BufferSize));
}
}
return Status;
} }