Allow boot from container component

This patch added support to boot from a component inside a container
from OsLoader. Now a boot option for SPI/memory device can be used
to boot from container component by specifying the boot image name
as '!AAAA/BBBB' format. AAAA is the container name and BBBB is
the component name. This component can be FV/TE/PE image format.

Signed-off-by: Maurice Ma <maurice.ma@intel.com>
This commit is contained in:
Maurice Ma 2020-08-13 14:59:01 -07:00
parent 4bee65a8f6
commit 90ca0f11dd
3 changed files with 170 additions and 113 deletions

View File

@ -53,132 +53,154 @@ GetBootImageFromRawPartition (
UINT8 SwPart; UINT8 SwPart;
UINT64 Address; UINT64 Address;
CONTAINER_HDR *ContainerHdr; CONTAINER_HDR *ContainerHdr;
CHAR8 *FileName;
SwPart = BootOption->Image[LoadedImage->LoadImageType].LbaImage.SwPart; SwPart = BootOption->Image[LoadedImage->LoadImageType].LbaImage.SwPart;
LbaAddr = BootOption->Image[LoadedImage->LoadImageType].LbaImage.LbaAddr; LbaAddr = BootOption->Image[LoadedImage->LoadImageType].LbaImage.LbaAddr;
FileName = (CHAR8 *)BootOption->Image[LoadedImage->LoadImageType].FileName;
// if ((FileName[0] == '!') && (LbaAddr == 0)) {
// The image_B partition number, is image_A partition number + 1 // Load file from internal container path instead
// They share same LBA offset address. Status = EFI_NOT_FOUND;
// if ((AsciiStrLen(FileName) > 9) && (FileName[0] == '!') && (FileName[5] == '/')) {
if ((BootOption->BootFlags & LOAD_IMAGE_FROM_BACKUP) != 0) { Buffer = NULL;
if ((LoadedImage->LoadImageType == LoadImageTypeTrusty) ImageSize = 0;
|| (LoadedImage->LoadImageType == LoadImageTypeNormal)) { Status = LoadComponent (
SwPart++; *(UINT32 *)(FileName + 1),
*(UINT32 *)(FileName + 6),
(VOID **)&Buffer,
(UINT32 *)&ImageSize
);
} }
} if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Load component '%a' error - %r\n", FileName, Status));
DEBUG ((DEBUG_INFO, "Load image from SwPart (0x%x), LbaAddr(0x%llx)\n", SwPart, LbaAddr)); return Status;
Status = GetLogicalPartitionInfo (SwPart, LoadedImage->HwPartHandle, &LogicBlkDev); }
if (EFI_ERROR (Status)) { LoadedImage->Flags |= LOADED_IMAGE_COMPONENT;
DEBUG ((DEBUG_INFO, "Get logical partition error, Status = %r\n", Status));
return Status;
}
Status = MediaGetMediaInfo (BootOption->HwPart, &BlockInfo);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "GetMediaInfo Error %r\n", Status));
return Status;
}
//
// Read the IAS Header first to get total size of the IAS image.
// Make sure to round the Header size to be block aligned in bytes.
//
BlockSize = BlockInfo.BlockSize;
AlignedHeaderSize = ((sizeof (IAS_HEADER) % BlockSize) == 0) ? \
sizeof (IAS_HEADER) : \
((sizeof (IAS_HEADER) / BlockSize) + 1) * BlockSize;
BlockData = AllocatePages (EFI_SIZE_TO_PAGES (AlignedHeaderSize));
if (BlockData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if ( BootOption->DevType == OsBootDeviceMemory ) {
Address = LogicBlkDev.StartBlock + LbaAddr;
} else { } else {
Address = LbaAddr; //
} // The image_B partition number, is image_A partition number + 1
// They share same LBA offset address.
//
if ((BootOption->BootFlags & LOAD_IMAGE_FROM_BACKUP) != 0) {
if ((LoadedImage->LoadImageType == LoadImageTypeTrusty)
|| (LoadedImage->LoadImageType == LoadImageTypeNormal)) {
SwPart++;
}
}
Status = MediaReadBlocks ( DEBUG ((DEBUG_INFO, "Load image from SwPart (0x%x), LbaAddr(0x%llx)\n", SwPart, LbaAddr));
BootOption->HwPart, Status = GetLogicalPartitionInfo (SwPart, LoadedImage->HwPartHandle, &LogicBlkDev);
Address, if (EFI_ERROR (Status)) {
AlignedHeaderSize, DEBUG ((DEBUG_INFO, "Get logical partition error - %r\n", Status));
BlockData return Status;
); }
if (EFI_ERROR (Status)) { Status = MediaGetMediaInfo (BootOption->HwPart, &BlockInfo);
DEBUG ((DEBUG_INFO, "Read image error, Status = %r\n", Status)); if (EFI_ERROR (Status)) {
return Status; DEBUG ((DEBUG_INFO, "Get media info error - %r\n", Status));
} return Status;
}
// //
// Make sure to round the image size to be block aligned in bytes. // Read the IAS Header first to get total size of the IAS image.
// // Make sure to round the Header size to be block aligned in bytes.
ContainerHdr = (CONTAINER_HDR *)BlockData; //
if (ContainerHdr->Signature == CONTAINER_BOOT_SIGNATURE) { BlockSize = BlockInfo.BlockSize;
ImageSize = ContainerHdr->DataOffset + ContainerHdr->DataSize; AlignedHeaderSize = ((sizeof (IAS_HEADER) % BlockSize) == 0) ? \
} else if (ContainerHdr->Signature == IAS_MAGIC_PATTERN) { sizeof (IAS_HEADER) : \
ImageSize = IAS_IMAGE_SIZE ((IAS_HEADER *) BlockData); ((sizeof (IAS_HEADER) / BlockSize) + 1) * BlockSize;
} else {
DEBUG ((DEBUG_INFO, "No valid image header found !\n"));
return EFI_LOAD_ERROR;
}
// BlockData = AllocatePages (EFI_SIZE_TO_PAGES (AlignedHeaderSize));
// Check image size from the image header if (BlockData == NULL) {
// return EFI_OUT_OF_RESOURCES;
if (ImageSize == 0) { }
return EFI_LOAD_ERROR;
} if ( BootOption->DevType == OsBootDeviceMemory ) {
Address = LogicBlkDev.StartBlock + LbaAddr;
} else {
Address = LbaAddr;
}
Status = MediaReadBlocks (
BootOption->HwPart,
Address,
AlignedHeaderSize,
BlockData
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Read image error - %r\n", Status));
return Status;
}
//
// Make sure to round the image size to be block aligned in bytes.
//
ContainerHdr = (CONTAINER_HDR *)BlockData;
if (ContainerHdr->Signature == CONTAINER_BOOT_SIGNATURE) {
ImageSize = ContainerHdr->DataOffset + ContainerHdr->DataSize;
} else if (ContainerHdr->Signature == IAS_MAGIC_PATTERN) {
ImageSize = IAS_IMAGE_SIZE ((IAS_HEADER *) BlockData);
} else {
DEBUG ((DEBUG_INFO, "No valid image header found !\n"));
return EFI_LOAD_ERROR;
}
//
// Check image size from the image header
//
if (ImageSize == 0) {
return EFI_LOAD_ERROR;
}
AlignedImageSize = ((ImageSize % BlockSize) == 0) ? \
ImageSize : \
((ImageSize / BlockSize) + 1) * BlockSize;
if (AlignedImageSize > MAX_IAS_IMAGE_SIZE) {
DEBUG ((DEBUG_INFO, "Image is bigger than limitation (0x%x). ImageSize=0x%x\n",
MAX_IAS_IMAGE_SIZE, AlignedImageSize));
//
// Free temporary pages used for image header
//
FreePages (BlockData, EFI_SIZE_TO_PAGES (AlignedHeaderSize));
return EFI_LOAD_ERROR;
}
Buffer = (UINT8 *) AllocatePages (EFI_SIZE_TO_PAGES (AlignedImageSize));
if (Buffer == NULL) {
DEBUG ((DEBUG_INFO, "Allocate memory (size:0x%x) fail.\n", AlignedImageSize));
return EFI_OUT_OF_RESOURCES;
}
CopyMem (Buffer, BlockData, AlignedHeaderSize);
AlignedImageSize = ((ImageSize % BlockSize) == 0) ? \
ImageSize : \
((ImageSize / BlockSize) + 1) * BlockSize;
if (AlignedImageSize > MAX_IAS_IMAGE_SIZE) {
DEBUG ((DEBUG_INFO, "Image is bigger than limitation (0x%x). ImageSize=0x%x\n",
MAX_IAS_IMAGE_SIZE, AlignedImageSize));
// //
// Free temporary pages used for image header // Free temporary pages used for image header
// //
FreePages (BlockData, EFI_SIZE_TO_PAGES (AlignedHeaderSize)); FreePages (BlockData, EFI_SIZE_TO_PAGES (AlignedHeaderSize));
return EFI_LOAD_ERROR;
}
Buffer = (UINT8 *) AllocatePages (EFI_SIZE_TO_PAGES (AlignedImageSize)); //
if (Buffer == NULL) { // Read the rest of the IAS image into the buffer
DEBUG ((DEBUG_INFO, "Allocate memory (size:0x%x) fail.\n", AlignedImageSize)); //
return EFI_OUT_OF_RESOURCES;
}
CopyMem (Buffer, BlockData, AlignedHeaderSize);
// if ( BootOption->DevType == OsBootDeviceMemory ) {
// Free temporary pages used for image header Address = LogicBlkDev.StartBlock + LbaAddr + AlignedHeaderSize;
// } else {
FreePages (BlockData, EFI_SIZE_TO_PAGES (AlignedHeaderSize)); Address = LbaAddr + AlignedHeaderSize;
}
// Status = MediaReadBlocks (
// Read the rest of the IAS image into the buffer BootOption->HwPart,
// Address,
(AlignedImageSize - AlignedHeaderSize),
(VOID *)((UINTN)Buffer + AlignedHeaderSize)
);
if ( BootOption->DevType == OsBootDeviceMemory ) { if (EFI_ERROR (Status)) {
Address = LogicBlkDev.StartBlock + LbaAddr + AlignedHeaderSize; DEBUG ((DEBUG_INFO, "Read rest of image error - %r\n", Status));
} else { FreePages (Buffer, EFI_SIZE_TO_PAGES (AlignedImageSize));
Address = LbaAddr + AlignedHeaderSize; return Status;
} }
Status = MediaReadBlocks (
BootOption->HwPart,
Address,
(AlignedImageSize - AlignedHeaderSize),
(VOID *)((UINTN)Buffer + AlignedHeaderSize)
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Read rest of image error, Status = %r\n", Status));
FreePages (Buffer, EFI_SIZE_TO_PAGES (AlignedImageSize));
return Status;
} }
LoadedImage->ImageData.Addr = Buffer; LoadedImage->ImageData.Addr = Buffer;

View File

@ -178,7 +178,7 @@ UpdateLoadedImage (
@param[in] BootOption Current boot option @param[in] BootOption Current boot option
@param[in, out] LoadedImage Loaded Image information. @param[in, out] LoadedImage Loaded Image information.
@retval RETURN_SUCCESS Parse IAS image successfully @retval RETURN_SUCCESS Parse container image successfully
@retval Others There is error when parsing IAS image. @retval Others There is error when parsing IAS image.
**/ **/
EFI_STATUS EFI_STATUS
@ -260,6 +260,37 @@ ParseContainerImage (
return Status; return Status;
} }
/**
Parse a single component image
This function will parse a single image.
This image could be TE/PE/FV or multi-boot format.
@param[in] BootOption Current boot option
@param[in, out] LoadedImage Loaded Image information.
@retval RETURN_SUCCESS Parse component image successfully
@retval Others There is error when parsing IAS image.
**/
EFI_STATUS
ParseComponentImage (
IN OS_BOOT_OPTION *BootOption,
IN OUT LOADED_IMAGE *LoadedImage
)
{
IMAGE_DATA File;
EFI_STATUS Status;
File.Addr = LoadedImage->ImageData.Addr;
File.Size = LoadedImage->ImageData.Size;
File.AllocType = ImageAllocateTypePointer;
Status = UpdateLoadedImage (1, &File, LoadedImage, 0);
if (EFI_ERROR (Status)) {
UnloadLoadedImage (LoadedImage);
}
return Status;
}
/** /**
Parse IAS image Parse IAS image
@ -783,16 +814,17 @@ InitBootFileSystem (
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINT32 SwPart; UINT32 SwPart;
UINT32 FsType; UINT32 DevType;
INT32 BootSlot; INT32 BootSlot;
OS_FILE_SYSTEM_TYPE FsType;
ASSERT (OsBootOption != NULL); ASSERT (OsBootOption != NULL);
SwPart = OsBootOption->SwPart; SwPart = OsBootOption->SwPart;
FsType = OsBootOption->FsType; FsType = OsBootOption->FsType;
DevType = OsBootOption->DevType;
DEBUG ((DEBUG_INFO, "Init File system\n")); DEBUG ((DEBUG_INFO, "Init File system\n"));
if ((OS_FILE_SYSTEM_TYPE)FsType < EnumFileSystemMax) { if ((DevType != OsBootDeviceSpi) && (DevType != OsBootDeviceMemory) && (FsType < EnumFileSystemMax)) {
Status = InitFileSystem (SwPart, FsType, HwPartHandle, FsHandle); Status = InitFileSystem (SwPart, FsType, HwPartHandle, FsHandle);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "No partitions found, Status = %r\n", Status)); DEBUG ((DEBUG_INFO, "No partitions found, Status = %r\n", Status));
@ -859,6 +891,8 @@ ParseBootImages (
} }
} else if ((LoadedImage->Flags & LOADED_IMAGE_IAS) != 0) { } else if ((LoadedImage->Flags & LOADED_IMAGE_IAS) != 0) {
Status = ParseIasImage (OsBootOption, LoadedImage); Status = ParseIasImage (OsBootOption, LoadedImage);
} else if ((LoadedImage->Flags & LOADED_IMAGE_COMPONENT) != 0) {
Status = ParseComponentImage (OsBootOption, LoadedImage);
} }
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {

View File

@ -78,6 +78,7 @@
#define LOADED_IMAGE_PE32 BIT3 #define LOADED_IMAGE_PE32 BIT3
#define LOADED_IMAGE_FV BIT4 #define LOADED_IMAGE_FV BIT4
#define LOADED_IMAGE_CONTAINER BIT5 #define LOADED_IMAGE_CONTAINER BIT5
#define LOADED_IMAGE_COMPONENT BIT6
#define MAX_EXTRA_FILE_NUMBER 16 #define MAX_EXTRA_FILE_NUMBER 16