OsLoader - Container Type Cleanup (#1816)
* Add Name field to IMAGE_DATA structure Add a name field to the structure to be used by container parsing functions. It will be useful to determine the name of the container component when dealing with special files like ACPI blobs. Signed-off-by: Atharva Lele <atharva.lele@intel.com> * OsLoader: save the name of the component when creating array of components Saving the name will help us deal with special files like ACPI blobs more easily Signed-off-by: Atharva Lele <atharva.lele@intel.com> * OsLoader: streamline container types Update container functionality to streamline container types: - Normal: PE32, FV, ELF images. Supports ACPI table update. - Classic (Linux): Used for a traditional Linux boot setup. (cmdline, bzImage, initrd). Additionally supports ACPI table update. - Multiboot: Used for Multiboot/Multiboot-2 compliant ELF images. Supports ACPI table update. Signed-off-by: Atharva Lele <atharva.lele@intel.com> * Rename CLASSIC container to CLASSIC_LINUX This type of container is to be used for a traditional Linux boot setup consisting of a cmdline, bzImage, initrd(optional), and other binary blobs or ACPI blobs. Rename it to CLASSIC_LINUX to make the purpose of the container clearer. Signed-off-by: Atharva Lele <atharva.lele@intel.com> * OsLoader: copy Linux ExtraBlobs to reserved mem and add to cmdline Until now, SBL loaded the Extra blobs with the Linux kernel into memory. However, there was no way for the OS to know where these blobs resided in memory. The blobs were also loaded in memory that was not marked as reserved. This patch copies the blobs to reserved memory and adds the blob addresses into an expected placeholder in the Linux cmdline. If the placeholder is not present, nothing related to that blob will be added to the cmdline. Signed-off-by: Atharva Lele <atharva.lele@intel.com> --------- Signed-off-by: Atharva Lele <atharva.lele@intel.com>
This commit is contained in:
parent
401228a7db
commit
82769186dc
|
@ -42,7 +42,7 @@ typedef UINT8 AUTH_TYPE;
|
|||
|
||||
// Container Image types
|
||||
#define CONTAINER_TYPE_NORMAL 0x0 // Used for boot images in FV, regular ELF, PE32, etc. formats
|
||||
#define CONTAINER_TYPE_CLASSIC 0x3 // Used for booting Linux with bzImage, cmdline, initrd, etc.
|
||||
#define CONTAINER_TYPE_CLASSIC_LINUX 0x3 // Used for booting Linux with bzImage, cmdline, initrd, etc.
|
||||
#define CONTAINER_TYPE_MULTIBOOT 0x4 // Multiboot compliant ELF images
|
||||
|
||||
// Max images per container
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
This file defines IAS File structures.
|
||||
|
||||
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
|
@ -66,6 +66,7 @@ typedef struct { /* a file (sub-image) inside a boot image */
|
|||
VOID *Addr;
|
||||
UINT32 Size;
|
||||
IMAGE_ALLOCATE_TYPE AllocType;
|
||||
UINT32 Name; // Name specified for the component when building the container
|
||||
} IMAGE_DATA;
|
||||
|
||||
//
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2017 - 2022, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
@ -64,22 +64,22 @@ UpdateLoadedImage (
|
|||
COMMON_IMAGE *CommonImage;
|
||||
PLATFORM_SERVICE *PlatformService;
|
||||
CHAR8 *TypeStr;
|
||||
CHAR8 BlobName[5]; // 4 character component name + null termination
|
||||
CHAR8 BlobAddr[17]; // 64-bit address in ASCII hex + null termination
|
||||
CHAR8 *BlobPos; // Pointer to a character in the kernel cmdline string
|
||||
CHAR8 BlobSearchStr[28]; // ASCII string in the expected format: SBL.XXXX=0x0000000000000000
|
||||
VOID *BlobReservedBuf; // Pointer to allocated reserved memory
|
||||
|
||||
PlatformService = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
if (ImageType == CONTAINER_TYPE_NORMAL) {
|
||||
// Image can be of type: Multiboot, PE, FV, bzImage, or ELF
|
||||
// Image can be of type: PE, FV, bzImage, or ELF
|
||||
// Container can contain additional ACPI binary blobs
|
||||
// Assuming that the first image in the container is used for booting
|
||||
CommonImage = &LoadedImage->Image.Common;
|
||||
CopyMem (&CommonImage->BootFile, &File[0], sizeof (IMAGE_DATA));
|
||||
if (IsMultiboot (File[0].Addr)) {
|
||||
LoadedImage->Flags |= LOADED_IMAGE_MULTIBOOT;
|
||||
TypeStr = "Multiboot";
|
||||
} else if (IsMultiboot2 (File[0].Addr)) {
|
||||
LoadedImage->Flags |= LOADED_IMAGE_MULTIBOOT2;
|
||||
TypeStr = "Multiboot-2";
|
||||
} else if (IsTePe32Image (File[0].Addr, NULL) && \
|
||||
if (IsTePe32Image (File[0].Addr, NULL) && \
|
||||
(* (UINT32 *)File[0].Addr == EFI_IMAGE_DOS_SIGNATURE)) {
|
||||
// Add extra check to ensure it is a PE32 image generated from payload build.
|
||||
// Please note vmlinuxz is also following PE32 format, but it should
|
||||
|
@ -101,10 +101,31 @@ UpdateLoadedImage (
|
|||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "One %a file in boot image file .... \n", TypeStr));
|
||||
|
||||
// If there are more files, check for ACPI blobs and update ACPI tables accordingly
|
||||
if (NumFiles > 1) {
|
||||
Index = 1;
|
||||
while (Index < NumFiles) {
|
||||
// Update ACPI tables if we encounter an ACPI blob
|
||||
if (File[Index].Name == SIGNATURE_32('A', 'C', 'P', 'I')) {
|
||||
DEBUG ((DEBUG_INFO, "Loading boot image ACPI tables...\n"));
|
||||
PlatformService = (PLATFORM_SERVICE *) GetServiceBySignature (PLATFORM_SERVICE_SIGNATURE);
|
||||
if ((PlatformService != NULL) && (PlatformService->AcpiTableUpdate != NULL)) {
|
||||
Status = PlatformService->AcpiTableUpdate (File[Index].Addr, File[Index].Size);
|
||||
DEBUG ((DEBUG_INFO, "Updating ACPI table with boot image %d - %r\n", Index, Status));
|
||||
}
|
||||
FreeImageData (&File[Index]);
|
||||
continue;
|
||||
}
|
||||
Index++;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
} else if (ImageType == CONTAINER_TYPE_CLASSIC) {
|
||||
// Files: cmdline, bzImage, initrd, acpi, firmware1, firmware2, ...
|
||||
// The file order mentioned above is fixed and needs to be followed
|
||||
} else if (ImageType == CONTAINER_TYPE_CLASSIC_LINUX) {
|
||||
// Files: cmdline, bzImage, initrd, other optional files (acpi, firmware1, firmware2, ...)
|
||||
// The file order for the first three files mentioned above is fixed. The rest are optional and can be in any order.
|
||||
// Container can contain additional ACPI binary blobs
|
||||
|
||||
// Make sure that the boot file (File[1]) is present
|
||||
if (NumFiles < 2) {
|
||||
|
@ -136,14 +157,91 @@ UpdateLoadedImage (
|
|||
|
||||
// Save other binary blobs
|
||||
Index = 3;
|
||||
while ((Index < MAX_MULTIBOOT_MODULE_NUMBER) && (Index < NumFiles)) {
|
||||
while ((Index < MAX_EXTRA_FILE_NUMBER) && (Index < NumFiles)) {
|
||||
// Update ACPI tables if we encounter an ACPI blob
|
||||
if (File[Index].Name == SIGNATURE_32('A', 'C', 'P', 'I')) {
|
||||
DEBUG ((DEBUG_INFO, "Loading boot image ACPI tables...\n"));
|
||||
PlatformService = (PLATFORM_SERVICE *) GetServiceBySignature (PLATFORM_SERVICE_SIGNATURE);
|
||||
if ((PlatformService != NULL) && (PlatformService->AcpiTableUpdate != NULL)) {
|
||||
Status = PlatformService->AcpiTableUpdate (File[Index].Addr, File[Index].Size);
|
||||
DEBUG ((DEBUG_INFO, "Updating ACPI table with boot image %d - %r\n", Index, Status));
|
||||
}
|
||||
FreeImageData (&File[Index]);
|
||||
Index++;
|
||||
continue;
|
||||
}
|
||||
CopyMem (&LinuxImage->ExtraBlob[Index - 3], &File[Index], sizeof (IMAGE_DATA));
|
||||
|
||||
//
|
||||
// Update the blob's address in the kernel command line so that the OS knows where it resides
|
||||
// We also copy the blob into a reserved memory address so that the OS does not overwrite it
|
||||
//
|
||||
|
||||
// Get the blob name
|
||||
CopyMem(BlobName, &File[Index].Name, 4);
|
||||
BlobName[4] = '\0';
|
||||
|
||||
// Copy the extra blob into reserved memory
|
||||
BlobReservedBuf = AllocateReservedPages(EFI_SIZE_TO_PAGES(File[Index].Size));
|
||||
if (BlobReservedBuf == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
CopyMem(BlobReservedBuf, File[Index].Addr, File[Index].Size);
|
||||
DEBUG ((DEBUG_INFO, "Copied %a to reserved memory @ 0x%016X\n", BlobName, BlobReservedBuf));
|
||||
|
||||
// Generate the search string: SBL.XXXX=0x0000000000000000
|
||||
AsciiSPrint(BlobSearchStr, 28, "SBL.%a=0x0000000000000000", BlobName);
|
||||
DEBUG ((DEBUG_INFO, "Searching for \"%a\" blob placeholder string in cmdline: %a... ", BlobName, BlobSearchStr));
|
||||
|
||||
// Find the location of the placeholder string
|
||||
BlobPos = AsciiStrStr(LinuxImage->CmdFile.Addr, BlobSearchStr);
|
||||
|
||||
if (BlobPos != NULL) {
|
||||
// Move the pointer to where we get to the actual adress (part after 0x)
|
||||
// e.g. SBL.ABCD=0x0000000000000000
|
||||
// AsciiStrStr will get us a pointer to 'S'. Adding 11 will get us to the address
|
||||
BlobPos += 11;
|
||||
|
||||
// Get the blob's address into a string
|
||||
// AsciiSPrint(BlobAddr, 17, "%016X", File[Index].Addr);
|
||||
AsciiSPrint(BlobAddr, 17, "%016X", BlobReservedBuf);
|
||||
|
||||
// Copy the actual address at the placeholder location
|
||||
AsciiStrCpyS(BlobPos, 17, BlobAddr);
|
||||
|
||||
// Replace the copied string's last character with a space for all files except the last one
|
||||
// We don't do this for the last one since the kernel expects a null-terminated cmdline
|
||||
if (Index != NumFiles) {
|
||||
BlobPos += 16;
|
||||
*BlobPos = ' ';
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "Found and patched address!\n"));
|
||||
} else {
|
||||
DEBUG ((DEBUG_INFO, "Could not find cmdline placeholder\n"));
|
||||
}
|
||||
|
||||
// Move to the next file
|
||||
Index++;
|
||||
}
|
||||
LinuxImage->ExtraBlobNumber = Index;
|
||||
} else if (ImageType == CONTAINER_TYPE_MULTIBOOT) {
|
||||
// Files: cmdline1, elf1, cmdline2, elf2, ...
|
||||
// Container can contain additional ACPI binary blobs
|
||||
// Assume the first elf file is the one to boot
|
||||
if (IsMultiboot (File[1].Addr)) {
|
||||
LoadedImage->Flags |= LOADED_IMAGE_MULTIBOOT;
|
||||
TypeStr = "Multiboot";
|
||||
} else if (IsMultiboot2 (File[1].Addr)) {
|
||||
LoadedImage->Flags |= LOADED_IMAGE_MULTIBOOT2;
|
||||
TypeStr = "Multiboot-2";
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "\"Multiboot\" container type used for a non-multiboot image!"));
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a file in boot image file .... \n", TypeStr));
|
||||
|
||||
MultiBoot = &LoadedImage->Image.MultiBoot;
|
||||
LoadedImage->Flags |= LOADED_IMAGE_MULTIBOOT;
|
||||
CopyMem (&MultiBoot->CmdFile, &File[0], sizeof (IMAGE_DATA));
|
||||
|
@ -153,6 +251,10 @@ UpdateLoadedImage (
|
|||
ModuleIndex = 0;
|
||||
for (Index = 2; Index < NumFiles; Index += 2) {
|
||||
if (Index < MAX_MULTIBOOT_MODULE_NUMBER) {
|
||||
// Multiboot modules are in a cmdline-ELF pair according to the spec.
|
||||
// So to accomodate for that, ACPI binary blobs should be preceded by
|
||||
// a corresponding dummy cmdline file that contains the MULTIBOOT_SPECIAL_MODULE_MAGIC
|
||||
// string to indicate that the paired file is the ACPI binary blob
|
||||
if (* (UINT32 *) File[Index].Addr == MULTIBOOT_SPECIAL_MODULE_MAGIC) {
|
||||
DEBUG ((DEBUG_INFO, "Loading boot image ACPI tables...\n"));
|
||||
PlatformService = (PLATFORM_SERVICE *) GetServiceBySignature (PLATFORM_SERVICE_SIGNATURE);
|
||||
|
@ -261,6 +363,9 @@ ParseContainerImage (
|
|||
}
|
||||
}
|
||||
|
||||
// Save the name of the component
|
||||
File[Index].Name = (UINT32) ComponentName;
|
||||
|
||||
Index++;
|
||||
} while ((Status == EFI_SUCCESS) && (Index < ARRAY_SIZE (File)));
|
||||
|
||||
|
|
Loading…
Reference in New Issue