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 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_VOLUME_CORRUPTED Corrupted volume.
@retval EFI_SUCCESS Function successfully returned.
**/
@ -199,7 +198,7 @@ EFI_STATUS
CoreProcessFvImageFile (
IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
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 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_VOLUME_CORRUPTED Corrupted volume.
@retval EFI_SUCCESS Function successfully returned.
**/
@ -1019,7 +1017,7 @@ EFI_STATUS
CoreProcessFvImageFile (
IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
IN EFI_HANDLE FvHandle,
IN EFI_GUID *DriverName
IN EFI_GUID *FileName
)
{
EFI_STATUS Status;
@ -1033,141 +1031,158 @@ CoreProcessFvImageFile (
EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath;
UINT32 FvUsedSize;
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;
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) {
//
// Security check failed. The firmware volume should not be used for any purpose.
//
if (Buffer != NULL) {
FreePool (Buffer);
Index = 0;
do {
FvHeader = NULL;
FvAlignment = 0;
Buffer = NULL;
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;
}
}
//
// 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 {
if (Status != EFI_SUCCESS) {
//
// 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)) {
//
// 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);
if (Buffer != NULL) {
FreePool (Buffer);
}
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) AlignedBuffer;
CoreFreePool (Buffer);
Buffer = NULL;
break;
}
}
//
// 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 (
(EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
(UINT64)BufferSize,
FvHandle,
AuthenticationStatus,
NULL
);
return EFI_SUCCESS;
} else {
return Status;
}
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;
}