diff --git a/PayloadPkg/OsLoader/LoadImage.c b/PayloadPkg/OsLoader/LoadImage.c index 0cc7395d..c64604a4 100644 --- a/PayloadPkg/OsLoader/LoadImage.c +++ b/PayloadPkg/OsLoader/LoadImage.c @@ -53,132 +53,154 @@ GetBootImageFromRawPartition ( UINT8 SwPart; UINT64 Address; CONTAINER_HDR *ContainerHdr; + CHAR8 *FileName; - SwPart = BootOption->Image[LoadedImage->LoadImageType].LbaImage.SwPart; - LbaAddr = BootOption->Image[LoadedImage->LoadImageType].LbaImage.LbaAddr; + SwPart = BootOption->Image[LoadedImage->LoadImageType].LbaImage.SwPart; + LbaAddr = BootOption->Image[LoadedImage->LoadImageType].LbaImage.LbaAddr; + FileName = (CHAR8 *)BootOption->Image[LoadedImage->LoadImageType].FileName; - // - // 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++; + if ((FileName[0] == '!') && (LbaAddr == 0)) { + // Load file from internal container path instead + Status = EFI_NOT_FOUND; + if ((AsciiStrLen(FileName) > 9) && (FileName[0] == '!') && (FileName[5] == '/')) { + Buffer = NULL; + ImageSize = 0; + Status = LoadComponent ( + *(UINT32 *)(FileName + 1), + *(UINT32 *)(FileName + 6), + (VOID **)&Buffer, + (UINT32 *)&ImageSize + ); } - } - - DEBUG ((DEBUG_INFO, "Load image from SwPart (0x%x), LbaAddr(0x%llx)\n", SwPart, LbaAddr)); - Status = GetLogicalPartitionInfo (SwPart, LoadedImage->HwPartHandle, &LogicBlkDev); - if (EFI_ERROR (Status)) { - 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; + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Load component '%a' error - %r\n", FileName, Status)); + return Status; + } + LoadedImage->Flags |= LOADED_IMAGE_COMPONENT; } 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 ( - BootOption->HwPart, - Address, - AlignedHeaderSize, - BlockData - ); + DEBUG ((DEBUG_INFO, "Load image from SwPart (0x%x), LbaAddr(0x%llx)\n", SwPart, LbaAddr)); + Status = GetLogicalPartitionInfo (SwPart, LoadedImage->HwPartHandle, &LogicBlkDev); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Get logical partition error - %r\n", Status)); + return Status; + } - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "Read image error, Status = %r\n", Status)); - return Status; - } + Status = MediaGetMediaInfo (BootOption->HwPart, &BlockInfo); + if (EFI_ERROR (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. - // - 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; - } + // + // 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; - // - // Check image size from the image header - // - if (ImageSize == 0) { - return EFI_LOAD_ERROR; - } + BlockData = AllocatePages (EFI_SIZE_TO_PAGES (AlignedHeaderSize)); + if (BlockData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + 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 // 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); + // + // Read the rest of the IAS image into the buffer + // - // - // Free temporary pages used for image header - // - FreePages (BlockData, EFI_SIZE_TO_PAGES (AlignedHeaderSize)); + if ( BootOption->DevType == OsBootDeviceMemory ) { + Address = LogicBlkDev.StartBlock + LbaAddr + AlignedHeaderSize; + } else { + Address = LbaAddr + AlignedHeaderSize; + } - // - // Read the rest of the IAS image into the buffer - // + Status = MediaReadBlocks ( + BootOption->HwPart, + Address, + (AlignedImageSize - AlignedHeaderSize), + (VOID *)((UINTN)Buffer + AlignedHeaderSize) + ); - if ( BootOption->DevType == OsBootDeviceMemory ) { - Address = LogicBlkDev.StartBlock + LbaAddr + AlignedHeaderSize; - } else { - Address = LbaAddr + AlignedHeaderSize; - } - - 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; + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Read rest of image error - %r\n", Status)); + FreePages (Buffer, EFI_SIZE_TO_PAGES (AlignedImageSize)); + return Status; + } } LoadedImage->ImageData.Addr = Buffer; diff --git a/PayloadPkg/OsLoader/OsLoader.c b/PayloadPkg/OsLoader/OsLoader.c index 3b4331ed..d5f799bb 100644 --- a/PayloadPkg/OsLoader/OsLoader.c +++ b/PayloadPkg/OsLoader/OsLoader.c @@ -178,7 +178,7 @@ UpdateLoadedImage ( @param[in] BootOption Current boot option @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. **/ EFI_STATUS @@ -260,6 +260,37 @@ ParseContainerImage ( 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 @@ -783,16 +814,17 @@ InitBootFileSystem ( { EFI_STATUS Status; UINT32 SwPart; - UINT32 FsType; + UINT32 DevType; INT32 BootSlot; + OS_FILE_SYSTEM_TYPE FsType; ASSERT (OsBootOption != NULL); SwPart = OsBootOption->SwPart; FsType = OsBootOption->FsType; - + DevType = OsBootOption->DevType; 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); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "No partitions found, Status = %r\n", Status)); @@ -859,6 +891,8 @@ ParseBootImages ( } } else if ((LoadedImage->Flags & LOADED_IMAGE_IAS) != 0) { Status = ParseIasImage (OsBootOption, LoadedImage); + } else if ((LoadedImage->Flags & LOADED_IMAGE_COMPONENT) != 0) { + Status = ParseComponentImage (OsBootOption, LoadedImage); } if (EFI_ERROR (Status)) { diff --git a/PayloadPkg/OsLoader/OsLoader.h b/PayloadPkg/OsLoader/OsLoader.h index a50df362..c947f20a 100644 --- a/PayloadPkg/OsLoader/OsLoader.h +++ b/PayloadPkg/OsLoader/OsLoader.h @@ -78,6 +78,7 @@ #define LOADED_IMAGE_PE32 BIT3 #define LOADED_IMAGE_FV BIT4 #define LOADED_IMAGE_CONTAINER BIT5 +#define LOADED_IMAGE_COMPONENT BIT6 #define MAX_EXTRA_FILE_NUMBER 16