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:
parent
4bee65a8f6
commit
90ca0f11dd
|
@ -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;
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue